r2068 - trunk/src/host/qemu-neo1973/hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Wed May 23 14:44:35 CEST 2007


Author: andrew
Date: 2007-05-23 14:44:30 +0200 (Wed, 23 May 2007)
New Revision: 2068

Modified:
   trunk/src/host/qemu-neo1973/hw/ads7846.c
   trunk/src/host/qemu-neo1973/hw/ide.c
   trunk/src/host/qemu-neo1973/hw/max111x.c
   trunk/src/host/qemu-neo1973/hw/max7310.c
   trunk/src/host/qemu-neo1973/hw/pxa.h
   trunk/src/host/qemu-neo1973/hw/pxa2xx.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c
   trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c
   trunk/src/host/qemu-neo1973/hw/spitz.c
Log:
Save/restore support for PXA2xx on-chip peripherals, the microdrive, the MAX7310, MAX1110/1, ADS7846, Scoop devices, Sharp flash.


Modified: trunk/src/host/qemu-neo1973/hw/ads7846.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/ads7846.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -104,10 +104,41 @@
     if (s->pressure == !buttons_state) {
         s->pressure = !!buttons_state;
 
-         ads7846_int_update(s);
+        ads7846_int_update(s);
     }
 }
 
+static void ads7846_save(QEMUFile *f, void *opaque)
+{
+    struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 8; i ++)
+        qemu_put_be32(f, s->input[i]);
+    qemu_put_be32(f, s->noise);
+    qemu_put_be32(f, s->cycle);
+    qemu_put_be32(f, s->output);
+}
+
+static int ads7846_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct ads7846_state_s *s = (struct ads7846_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 8; i ++)
+        s->input[i] = qemu_get_be32(f);
+    s->noise = qemu_get_be32(f);
+    s->cycle = qemu_get_be32(f);
+    s->output = qemu_get_be32(f);
+
+    s->pressure = 0;
+    ads7846_int_update(s);
+
+    return 0;
+}
+
+static int ads7846_iid = 0;
+
 struct ads7846_state_s *ads7846_init(qemu_irq penirq)
 {
     struct ads7846_state_s *s;
@@ -127,5 +158,9 @@
                     "QEMU ADS7846-driven Touchscreen");
 
     ads7846_int_update(s);
+
+    register_savevm("ads7846", ads7846_iid ++, 0,
+                    ads7846_save, ads7846_load, s);
+
     return s;
 }

Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/ide.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -2416,6 +2416,62 @@
     register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state);
 }
 
+/* save per IDE drive data */
+static void ide_save(QEMUFile* f, IDEState *s)
+{
+    qemu_put_be32s(f, &s->mult_sectors);
+    qemu_put_be32s(f, &s->identify_set);
+    if (s->identify_set) {
+        qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
+    }
+    qemu_put_8s(f, &s->feature);
+    qemu_put_8s(f, &s->error);
+    qemu_put_be32s(f, &s->nsector);
+    qemu_put_8s(f, &s->sector);
+    qemu_put_8s(f, &s->lcyl);
+    qemu_put_8s(f, &s->hcyl);
+    qemu_put_8s(f, &s->hob_feature);
+    qemu_put_8s(f, &s->hob_nsector);
+    qemu_put_8s(f, &s->hob_sector);
+    qemu_put_8s(f, &s->hob_lcyl);
+    qemu_put_8s(f, &s->hob_hcyl);
+    qemu_put_8s(f, &s->select);
+    qemu_put_8s(f, &s->status);
+    qemu_put_8s(f, &s->lba48);
+
+    qemu_put_8s(f, &s->sense_key);
+    qemu_put_8s(f, &s->asc);
+    /* XXX: if a transfer is pending, we do not save it yet */
+}
+
+/* load per IDE drive data */
+static void ide_load(QEMUFile* f, IDEState *s)
+{
+    qemu_get_be32s(f, &s->mult_sectors);
+    qemu_get_be32s(f, &s->identify_set);
+    if (s->identify_set) {
+        qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
+    }
+    qemu_get_8s(f, &s->feature);
+    qemu_get_8s(f, &s->error);
+    qemu_get_be32s(f, &s->nsector);
+    qemu_get_8s(f, &s->sector);
+    qemu_get_8s(f, &s->lcyl);
+    qemu_get_8s(f, &s->hcyl);
+    qemu_get_8s(f, &s->hob_feature);
+    qemu_get_8s(f, &s->hob_nsector);
+    qemu_get_8s(f, &s->hob_sector);
+    qemu_get_8s(f, &s->hob_lcyl);
+    qemu_get_8s(f, &s->hob_hcyl);
+    qemu_get_8s(f, &s->select);
+    qemu_get_8s(f, &s->status);
+    qemu_get_8s(f, &s->lba48);
+
+    qemu_get_8s(f, &s->sense_key);
+    qemu_get_8s(f, &s->asc);
+    /* XXX: if a transfer is pending, we do not save it yet */
+}
+
 /***********************************************************/
 /* ISA IDE definitions */
 
@@ -2731,30 +2787,7 @@
 
     /* per IDE drive data */
     for(i = 0; i < 4; i++) {
-        IDEState *s = &d->ide_if[i];
-        qemu_put_be32s(f, &s->mult_sectors);
-        qemu_put_be32s(f, &s->identify_set);
-        if (s->identify_set) {
-            qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
-        }
-        qemu_put_8s(f, &s->feature);
-        qemu_put_8s(f, &s->error);
-        qemu_put_be32s(f, &s->nsector);
-        qemu_put_8s(f, &s->sector);
-        qemu_put_8s(f, &s->lcyl);
-        qemu_put_8s(f, &s->hcyl);
-        qemu_put_8s(f, &s->hob_feature);
-        qemu_put_8s(f, &s->hob_nsector);
-        qemu_put_8s(f, &s->hob_sector);
-        qemu_put_8s(f, &s->hob_lcyl);
-        qemu_put_8s(f, &s->hob_hcyl);
-        qemu_put_8s(f, &s->select);
-        qemu_put_8s(f, &s->status);
-        qemu_put_8s(f, &s->lba48);
-
-        qemu_put_8s(f, &s->sense_key);
-        qemu_put_8s(f, &s->asc);
-        /* XXX: if a transfer is pending, we do not save it yet */
+        ide_save(f, &d->ide_if[i]);
     }
 }
 
@@ -2788,30 +2821,7 @@
 
     /* per IDE drive data */
     for(i = 0; i < 4; i++) {
-        IDEState *s = &d->ide_if[i];
-        qemu_get_be32s(f, &s->mult_sectors);
-        qemu_get_be32s(f, &s->identify_set);
-        if (s->identify_set) {
-            qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
-        }
-        qemu_get_8s(f, &s->feature);
-        qemu_get_8s(f, &s->error);
-        qemu_get_be32s(f, &s->nsector);
-        qemu_get_8s(f, &s->sector);
-        qemu_get_8s(f, &s->lcyl);
-        qemu_get_8s(f, &s->hcyl);
-        qemu_get_8s(f, &s->hob_feature);
-        qemu_get_8s(f, &s->hob_nsector);
-        qemu_get_8s(f, &s->hob_sector);
-        qemu_get_8s(f, &s->hob_lcyl);
-        qemu_get_8s(f, &s->hob_hcyl);
-        qemu_get_8s(f, &s->select);
-        qemu_get_8s(f, &s->status);
-        qemu_get_8s(f, &s->lba48);
-
-        qemu_get_8s(f, &s->sense_key);
-        qemu_get_8s(f, &s->asc);
-        /* XXX: if a transfer is pending, we do not save it yet */
+        ide_load(f, &d->ide_if[i]);
     }
     return 0;
 }
@@ -3255,6 +3265,54 @@
     }
 }
 
+static void md_save(QEMUFile *f, void *opaque)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    int i;
+    uint8_t drive1_selected;
+
+    qemu_put_8s(f, &s->opt);
+    qemu_put_8s(f, &s->stat);
+    qemu_put_8s(f, &s->pins);
+
+    qemu_put_8s(f, &s->ctrl);
+    qemu_put_be16s(f, &s->io);
+    qemu_put_byte(f, s->cycle);
+
+    drive1_selected = (s->ide->cur_drive != s->ide);
+    qemu_put_8s(f, &s->ide->cmd);
+    qemu_put_8s(f, &drive1_selected);
+
+    for (i = 0; i < 2; i ++)
+        ide_save(f, &s->ide[i]);
+}
+
+static int md_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct md_s *s = (struct md_s *) opaque;
+    int i;
+    uint8_t drive1_selected;
+
+    qemu_get_8s(f, &s->opt);
+    qemu_get_8s(f, &s->stat);
+    qemu_get_8s(f, &s->pins);
+
+    qemu_get_8s(f, &s->ctrl);
+    qemu_get_be16s(f, &s->io);
+    s->cycle = qemu_get_byte(f);
+
+    qemu_get_8s(f, &s->ide->cmd);
+    qemu_get_8s(f, &drive1_selected);
+    s->ide->cur_drive = &s->ide[(drive1_selected != 0)];
+
+    for (i = 0; i < 2; i ++)
+        ide_load(f, &s->ide[i]);
+
+    return 0;
+}
+
+static int md_iid = 0;
+
 static const uint8_t dscm1xxxx_cis[0x14a] = {
     [0x000] = CISTPL_DEVICE,	/* 5V Device Information */
     [0x002] = 0x03,		/* Tuple length = 4 bytes */
@@ -3480,5 +3538,8 @@
     md->ide->is_cf = 1;
     md->ide->mdata_size = METADATA_SIZE;
     md->ide->mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
+
+    register_savevm("microdrive", md_iid ++, 0, md_save, md_load, md);
+
     return &md->card;
 }

Modified: trunk/src/host/qemu-neo1973/hw/max111x.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/max111x.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -89,6 +89,39 @@
         qemu_irq_raise(s->interrupt);
 }
 
+static void max111x_save(QEMUFile *f, void *opaque)
+{
+    struct max111x_s *s = (struct max111x_s *) opaque;
+    int i;
+
+    qemu_put_8s(f, &s->tb1);
+    qemu_put_8s(f, &s->rb2);
+    qemu_put_8s(f, &s->rb3);
+    qemu_put_be32(f, s->inputs);
+    qemu_put_be32(f, s->com);
+    for (i = 0; i < s->inputs; i ++)
+        qemu_put_byte(f, s->input[i]);
+}
+
+static int max111x_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct max111x_s *s = (struct max111x_s *) opaque;
+    int i;
+
+    qemu_get_8s(f, &s->tb1);
+    qemu_get_8s(f, &s->rb2);
+    qemu_get_8s(f, &s->rb3);
+    if (s->inputs != qemu_get_be32(f))
+        return -EINVAL;
+    s->com = qemu_get_be32(f);
+    for (i = 0; i < s->inputs; i ++)
+        s->input[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
+static int max111x_iid = 0;
+
 static struct max111x_s *max111x_init(qemu_irq cb)
 {
     struct max111x_s *s;
@@ -108,6 +141,10 @@
     s->input[6] = 0x90;
     s->input[7] = 0x80;
     s->com = 0;
+
+    register_savevm("max111x", max111x_iid ++, 0,
+                    max111x_save, max111x_load, s);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/max7310.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/max7310.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -146,6 +146,41 @@
     }
 }
 
+static void max7310_save(QEMUFile *f, void *opaque)
+{
+    struct max7310_s *s = (struct max7310_s *) opaque;
+
+    qemu_put_be32(f, s->i2c_command_byte);
+    qemu_put_be32(f, s->len);
+
+    qemu_put_8s(f, &s->level);
+    qemu_put_8s(f, &s->direction);
+    qemu_put_8s(f, &s->polarity);
+    qemu_put_8s(f, &s->status);
+    qemu_put_8s(f, &s->command);
+
+    i2c_slave_save(f, &s->i2c);
+}
+
+static int max7310_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct max7310_s *s = (struct max7310_s *) opaque;
+
+    s->i2c_command_byte = qemu_get_be32(f);
+    s->len = qemu_get_be32(f);
+
+    qemu_get_8s(f, &s->level);
+    qemu_get_8s(f, &s->direction);
+    qemu_get_8s(f, &s->polarity);
+    qemu_get_8s(f, &s->status);
+    qemu_get_8s(f, &s->command);
+
+    i2c_slave_load(f, &s->i2c);
+    return 0;
+}
+
+static int max7310_iid = 0;
+
 /* MAX7310 is SMBus-compatible (can be used with only SMBus protocols),
  * but also accepts sequences that are not SMBus so return an I2C device.  */
 struct i2c_slave *max7310_init(i2c_bus *bus)
@@ -157,6 +192,10 @@
     s->i2c.send = max7310_tx;
 
     max7310_reset(&s->i2c);
+
+    register_savevm("max7310", max7310_iid ++, 0,
+                    max7310_save, max7310_load, s);
+
     return &s->i2c;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa.h	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa.h	2007-05-23 12:44:30 UTC (rev 2068)
@@ -65,10 +65,8 @@
 qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
 
 /* pxa2xx_timer.c */
-void pxa25x_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, CPUState *cpustate);
-void pxa27x_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate);
+void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs);
+void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4);
 
 /* pxa2xx_gpio.c */
 struct pxa2xx_gpio_info_s;

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -141,6 +141,26 @@
     pxa2xx_pm_write,
 };
 
+static void pxa2xx_pm_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 0x40; i ++)
+        qemu_put_be32s(f, &s->pm_regs[i]);
+}
+
+static int pxa2xx_pm_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 0x40; i ++)
+        qemu_get_be32s(f, &s->pm_regs[i]);
+
+    return 0;
+}
+
 #define CCCR	0x00	/* Core Clock Configuration register */
 #define CKEN	0x04	/* Clock Enable register */
 #define OSCC	0x08	/* Oscillator Configuration register */
@@ -204,6 +224,30 @@
     pxa2xx_cm_write,
 };
 
+static void pxa2xx_cm_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 4; i ++)
+        qemu_put_be32s(f, &s->cm_regs[i]);
+    qemu_put_be32s(f, &s->clkcfg);
+    qemu_put_be32s(f, &s->pmnc);
+}
+
+static int pxa2xx_cm_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 4; i ++)
+        qemu_get_be32s(f, &s->cm_regs[i]);
+    qemu_get_be32s(f, &s->clkcfg);
+    qemu_get_be32s(f, &s->pmnc);
+
+    return 0;
+}
+
 static uint32_t pxa2xx_clkpwr_read(void *opaque, int op2, int reg, int crm)
 {
     struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
@@ -482,6 +526,26 @@
     pxa2xx_mm_write,
 };
 
+static void pxa2xx_mm_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 0x1a; i ++)
+        qemu_put_be32s(f, &s->mm_regs[i]);
+}
+
+static int pxa2xx_mm_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 0x1a; i ++)
+        qemu_get_be32s(f, &s->mm_regs[i]);
+
+    return 0;
+}
+
 /* Synchronous Serial Ports */
 struct pxa2xx_ssp_s {
     target_phys_addr_t base;
@@ -761,6 +825,53 @@
     pxa2xx_ssp_write,
 };
 
+static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_be32s(f, &s->sscr[0]);
+    qemu_put_be32s(f, &s->sscr[1]);
+    qemu_put_be32s(f, &s->sspsp);
+    qemu_put_be32s(f, &s->ssto);
+    qemu_put_be32s(f, &s->ssitr);
+    qemu_put_be32s(f, &s->sssr);
+    qemu_put_8s(f, &s->sstsa);
+    qemu_put_8s(f, &s->ssrsa);
+    qemu_put_8s(f, &s->ssacd);
+
+    qemu_put_byte(f, s->rx_level);
+    for (i = 0; i < s->rx_level; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
+}
+
+static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_ssp_s *s = (struct pxa2xx_ssp_s *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_be32s(f, &s->sscr[0]);
+    qemu_get_be32s(f, &s->sscr[1]);
+    qemu_get_be32s(f, &s->sspsp);
+    qemu_get_be32s(f, &s->ssto);
+    qemu_get_be32s(f, &s->ssitr);
+    qemu_get_be32s(f, &s->sssr);
+    qemu_get_8s(f, &s->sstsa);
+    qemu_get_8s(f, &s->ssrsa);
+    qemu_get_8s(f, &s->ssacd);
+
+    s->rx_level = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_level; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
 /* Real-Time Clock */
 #define RCNR		0x00	/* RTC Counter register */
 #define RTAR		0x04	/* RTC Alarm register */
@@ -1052,7 +1163,19 @@
     }
 }
 
-static void pxa2xx_rtc_reset(struct pxa2xx_state_s *s)
+static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = {
+    pxa2xx_rtc_read,
+    pxa2xx_rtc_read,
+    pxa2xx_rtc_read,
+};
+
+static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {
+    pxa2xx_rtc_write,
+    pxa2xx_rtc_write,
+    pxa2xx_rtc_write,
+};
+
+static void pxa2xx_rtc_init(struct pxa2xx_state_s *s)
 {
     struct tm *tm;
     time_t ti;
@@ -1086,18 +1209,62 @@
     s->rtc_pi    = qemu_new_timer(rt_clock, pxa2xx_rtc_pi_tick,    s);
 }
 
-static CPUReadMemoryFunc *pxa2xx_rtc_readfn[] = {
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-    pxa2xx_rtc_read,
-};
+static void pxa2xx_rtc_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
 
-static CPUWriteMemoryFunc *pxa2xx_rtc_writefn[] = {
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
-    pxa2xx_rtc_write,
-};
+    pxa2xx_rtc_hzupdate(s);
+    pxa2xx_rtc_piupdate(s);
+    pxa2xx_rtc_swupdate(s);
 
+    qemu_put_be32s(f, &s->rttr);
+    qemu_put_be32s(f, &s->rtsr);
+    qemu_put_be32s(f, &s->rtar);
+    qemu_put_be32s(f, &s->rdar1);
+    qemu_put_be32s(f, &s->rdar2);
+    qemu_put_be32s(f, &s->ryar1);
+    qemu_put_be32s(f, &s->ryar2);
+    qemu_put_be32s(f, &s->swar1);
+    qemu_put_be32s(f, &s->swar2);
+    qemu_put_be32s(f, &s->piar);
+    qemu_put_be32s(f, &s->last_rcnr);
+    qemu_put_be32s(f, &s->last_rdcr);
+    qemu_put_be32s(f, &s->last_rycr);
+    qemu_put_be32s(f, &s->last_swcr);
+    qemu_put_be32s(f, &s->last_rtcpicr);
+    qemu_put_be64s(f, &s->last_hz);
+    qemu_put_be64s(f, &s->last_sw);
+    qemu_put_be64s(f, &s->last_pi);
+}
+
+static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_state_s *s = (struct pxa2xx_state_s *) opaque;
+
+    qemu_get_be32s(f, &s->rttr);
+    qemu_get_be32s(f, &s->rtsr);
+    qemu_get_be32s(f, &s->rtar);
+    qemu_get_be32s(f, &s->rdar1);
+    qemu_get_be32s(f, &s->rdar2);
+    qemu_get_be32s(f, &s->ryar1);
+    qemu_get_be32s(f, &s->ryar2);
+    qemu_get_be32s(f, &s->swar1);
+    qemu_get_be32s(f, &s->swar2);
+    qemu_get_be32s(f, &s->piar);
+    qemu_get_be32s(f, &s->last_rcnr);
+    qemu_get_be32s(f, &s->last_rdcr);
+    qemu_get_be32s(f, &s->last_rycr);
+    qemu_get_be32s(f, &s->last_swcr);
+    qemu_get_be32s(f, &s->last_rtcpicr);
+    qemu_get_be64s(f, &s->last_hz);
+    qemu_get_be64s(f, &s->last_sw);
+    qemu_get_be64s(f, &s->last_pi);
+
+    pxa2xx_rtc_alarm_update(s, s->rtsr);
+
+    return 0;
+}
+
 /* I2C Interface */
 #define IBMR	0x80	/* I2C Bus Monitor register */
 #define IDBR	0x88	/* I2C Data Buffer register */
@@ -1277,6 +1444,33 @@
     pxa2xx_i2c_write,
 };
 
+static void pxa2xx_i2c_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
+
+    qemu_put_be16s(f, &s->control);
+    qemu_put_be16s(f, &s->status);
+    qemu_put_8s(f, &s->ibmr);
+    qemu_put_8s(f, &s->data);
+
+    i2c_bus_save(f, s->bus);
+    i2c_slave_save(f, &s->slave);
+}
+
+static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
+
+    qemu_get_be16s(f, &s->control);
+    qemu_get_be16s(f, &s->status);
+    qemu_get_8s(f, &s->ibmr);
+    qemu_get_8s(f, &s->data);
+
+    i2c_bus_load(f, s->bus);
+    i2c_slave_load(f, &s->slave);
+    return 0;
+}
+
 static struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base,
                 qemu_irq irq, int ioregister)
 {
@@ -1297,6 +1491,9 @@
         cpu_register_physical_memory(s->base & 0xfffff000, 0xfff, iomemtype);
     }
 
+    register_savevm("pxa2xx_i2c", base, 0,
+                    pxa2xx_i2c_save, pxa2xx_i2c_load, s);
+
     return s;
 }
 
@@ -1453,6 +1650,40 @@
     pxa2xx_i2s_write,
 };
 
+static void pxa2xx_i2s_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
+
+    qemu_put_be32s(f, &s->control[0]);
+    qemu_put_be32s(f, &s->control[1]);
+    qemu_put_be32s(f, &s->status);
+    qemu_put_be32s(f, &s->mask);
+    qemu_put_be32s(f, &s->clk);
+
+    qemu_put_be32(f, s->enable);
+    qemu_put_be32(f, s->rx_len);
+    qemu_put_be32(f, s->tx_len);
+    qemu_put_be32(f, s->fifo_len);
+}
+
+static int pxa2xx_i2s_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
+
+    qemu_get_be32s(f, &s->control[0]);
+    qemu_get_be32s(f, &s->control[1]);
+    qemu_get_be32s(f, &s->status);
+    qemu_get_be32s(f, &s->mask);
+    qemu_get_be32s(f, &s->clk);
+
+    s->enable = qemu_get_be32(f);
+    s->rx_len = qemu_get_be32(f);
+    s->tx_len = qemu_get_be32(f);
+    s->fifo_len = qemu_get_be32(f);
+
+    return 0;
+}
+
 static void pxa2xx_i2s_data_req(void *opaque, int tx, int rx)
 {
     struct pxa2xx_i2s_s *s = (struct pxa2xx_i2s_s *) opaque;
@@ -1493,6 +1724,9 @@
                     pxa2xx_i2s_writefn, s);
     cpu_register_physical_memory(s->base & 0xfff00000, 0xfffff, iomemtype);
 
+    register_savevm("pxa2xx_i2s", base, 0,
+                    pxa2xx_i2s_save, pxa2xx_i2s_load, s);
+
     return s;
 }
 
@@ -1695,6 +1929,45 @@
 {
 }
 
+static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->enable);
+
+    qemu_put_8s(f, &s->control[0]);
+    qemu_put_8s(f, &s->control[1]);
+    qemu_put_8s(f, &s->control[2]);
+    qemu_put_8s(f, &s->status[0]);
+    qemu_put_8s(f, &s->status[1]);
+
+    qemu_put_byte(f, s->rx_len);
+    for (i = 0; i < s->rx_len; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
+}
+
+static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_fir_s *s = (struct pxa2xx_fir_s *) opaque;
+    int i;
+
+    s->enable = qemu_get_be32(f);
+
+    qemu_get_8s(f, &s->control[0]);
+    qemu_get_8s(f, &s->control[1]);
+    qemu_get_8s(f, &s->control[2]);
+    qemu_get_8s(f, &s->status[0]);
+    qemu_get_8s(f, &s->status[1]);
+
+    s->rx_len = qemu_get_byte(f);
+    s->rx_start = 0;
+    for (i = 0; i < s->rx_len; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    return 0;
+}
+
 static struct pxa2xx_fir_s *pxa2xx_fir_init(target_phys_addr_t base,
                 qemu_irq irq, struct pxa2xx_dma_state_s *dma,
                 CharDriverState *chr)
@@ -1718,6 +1991,8 @@
         qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
                         pxa2xx_fir_rx, pxa2xx_fir_event, s);
 
+    register_savevm("pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s);
+
     return s;
 }
 
@@ -1746,6 +2021,7 @@
 
     s->env = cpu_init();
     cpu_arm_set_model(s->env, revision ?: "pxa270");
+    register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env);
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE,
@@ -1783,6 +2059,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -1793,6 +2070,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     for (i = 0; pxa27x_ssp[i].io_base; i ++);
     s->ssp = (struct pxa2xx_ssp_s **)
@@ -1807,6 +2085,8 @@
         iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn,
                         pxa2xx_ssp_writefn, &ssp[i]);
         cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
+        register_savevm("pxa2xx_ssp", i, 0,
+                        pxa2xx_ssp_save, pxa2xx_ssp_load, s);
     }
 
     if (usb_enabled) {
@@ -1820,7 +2100,8 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype);
-    pxa2xx_rtc_reset(s);
+    pxa2xx_rtc_init(s);
+    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
 
     /* Note that PM registers are in the same page with PWRI2C registers.
      * As a workaround we don't map PWRI2C into memory and we expect
@@ -1832,6 +2113,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
 
@@ -1852,6 +2134,7 @@
 
     s->env = cpu_init();
     cpu_arm_set_model(s->env, "pxa255");
+    register_savevm("cpu", 0, 0, cpu_save, cpu_load, s->env);
 
     /* SDRAM & Internal Memory Storage */
     cpu_register_physical_memory(PXA2XX_SDRAM_BASE, sdram_size,
@@ -1888,6 +2171,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_cm_readfn,
                     pxa2xx_cm_writefn, s);
     cpu_register_physical_memory(s->cm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_cm", 0, 0, pxa2xx_cm_save, pxa2xx_cm_load, s);
 
     cpu_arm_set_cp_io(s->env, 14, pxa2xx_cp14_read, pxa2xx_cp14_write, s);
 
@@ -1898,6 +2182,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_mm_readfn,
                     pxa2xx_mm_writefn, s);
     cpu_register_physical_memory(s->mm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_mm", 0, 0, pxa2xx_mm_save, pxa2xx_mm_load, s);
 
     for (i = 0; pxa255_ssp[i].io_base; i ++);
     s->ssp = (struct pxa2xx_ssp_s **)
@@ -1912,6 +2197,8 @@
         iomemtype = cpu_register_io_memory(0, pxa2xx_ssp_readfn,
                         pxa2xx_ssp_writefn, &ssp[i]);
         cpu_register_physical_memory(ssp[i].base, 0xfff, iomemtype);
+        register_savevm("pxa2xx_ssp", i, 0,
+                        pxa2xx_ssp_save, pxa2xx_ssp_load, s);
     }
 
     if (usb_enabled) {
@@ -1925,8 +2212,12 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_rtc_readfn,
                     pxa2xx_rtc_writefn, s);
     cpu_register_physical_memory(s->rtc_base, 0xfff, iomemtype);
-    pxa2xx_rtc_reset(s);
+    pxa2xx_rtc_init(s);
+    register_savevm("pxa2xx_rtc", 0, 0, pxa2xx_rtc_save, pxa2xx_rtc_load, s);
 
+    /* Note that PM registers are in the same page with PWRI2C registers.
+     * As a workaround we don't map PWRI2C into memory and we expect
+     * PM handlers to call PWRI2C handlers when appropriate.  */
     s->i2c[0] = pxa2xx_i2c_init(0x40301600, s->pic[PXA2XX_PIC_I2C], 1);
     s->i2c[1] = pxa2xx_i2c_init(0x40f00100, s->pic[PXA2XX_PIC_PWRI2C], 0);
 
@@ -1934,6 +2225,7 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_pm_readfn,
                     pxa2xx_pm_writefn, s);
     cpu_register_physical_memory(s->pm_base, 0xfff, iomemtype);
+    register_savevm("pxa2xx_pm", 0, 0, pxa2xx_pm_save, pxa2xx_pm_load, s);
 
     s->i2s = pxa2xx_i2s_init(0x40400000, s->pic[PXA2XX_PIC_I2S], s->dma);
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_dma.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -430,6 +430,61 @@
     pxa2xx_dma_write
 };
 
+static void pxa2xx_dma_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_dma_state_s *s = (struct pxa2xx_dma_state_s *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->channels);
+
+    qemu_put_be32s(f, &s->stopintr);
+    qemu_put_be32s(f, &s->eorintr);
+    qemu_put_be32s(f, &s->rasintr);
+    qemu_put_be32s(f, &s->startintr);
+    qemu_put_be32s(f, &s->endintr);
+    qemu_put_be32s(f, &s->align);
+    qemu_put_be32s(f, &s->pio);
+
+    qemu_put_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS);
+    for (i = 0; i < s->channels; i ++) {
+        qemu_put_betl(f, s->chan[i].descr);
+        qemu_put_betl(f, s->chan[i].src);
+        qemu_put_betl(f, s->chan[i].dest);
+        qemu_put_be32s(f, &s->chan[i].cmd);
+        qemu_put_be32s(f, &s->chan[i].state);
+        qemu_put_be32(f, s->chan[i].request);
+    };
+}
+
+static int pxa2xx_dma_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_dma_state_s *s = (struct pxa2xx_dma_state_s *) opaque;
+    int i;
+
+    if (qemu_get_be32(f) != s->channels)
+        return -EINVAL;
+
+    qemu_get_be32s(f, &s->stopintr);
+    qemu_get_be32s(f, &s->eorintr);
+    qemu_get_be32s(f, &s->rasintr);
+    qemu_get_be32s(f, &s->startintr);
+    qemu_get_be32s(f, &s->endintr);
+    qemu_get_be32s(f, &s->align);
+    qemu_get_be32s(f, &s->pio);
+
+    qemu_get_buffer(f, s->req, PXA2XX_DMA_NUM_REQUESTS);
+    for (i = 0; i < s->channels; i ++) {
+        s->chan[i].descr = qemu_get_betl(f);
+        s->chan[i].src = qemu_get_betl(f);
+        s->chan[i].dest = qemu_get_betl(f);
+        qemu_get_be32s(f, &s->chan[i].cmd);
+        qemu_get_be32s(f, &s->chan[i].state);
+        s->chan[i].request = qemu_get_be32(f);
+    };
+
+    return 0;
+}
+
 static struct pxa2xx_dma_state_s *pxa2xx_dma_init(target_phys_addr_t base,
                 qemu_irq irq, int channels)
 {
@@ -443,18 +498,20 @@
     s->base = base;
     s->irq = irq;
     s->handler = (pxa2xx_dma_handler_t) pxa2xx_dma_request;
-    s->req = qemu_mallocz(sizeof(int) * PXA2XX_DMA_NUM_REQUESTS);
+    s->req = qemu_mallocz(sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
     memset(s->chan, 0, sizeof(struct pxa2xx_dma_channel_s) * s->channels);
     for (i = 0; i < s->channels; i ++)
         s->chan[i].state = DCSR_STOPINTR;
 
-    memset(s->req, 0, sizeof(int) * PXA2XX_DMA_NUM_REQUESTS);
+    memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
 
     iomemtype = cpu_register_io_memory(0, pxa2xx_dma_readfn,
-                   pxa2xx_dma_writefn, s);
+                    pxa2xx_dma_writefn, s);
     cpu_register_physical_memory(base, 0x0000ffff, iomemtype);
 
+    register_savevm("pxa2xx_dma", 0, 0, pxa2xx_dma_save, pxa2xx_dma_load, s);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_gpio.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -247,6 +247,51 @@
     pxa2xx_gpio_write
 };
 
+static void pxa2xx_gpio_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->lines);
+
+    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+        qemu_put_be32s(f, &s->ilevel[i]);
+        qemu_put_be32s(f, &s->olevel[i]);
+        qemu_put_be32s(f, &s->dir[i]);
+        qemu_put_be32s(f, &s->rising[i]);
+        qemu_put_be32s(f, &s->falling[i]);
+        qemu_put_be32s(f, &s->status[i]);
+        qemu_put_be32s(f, &s->gafr[i * 2 + 0]);
+        qemu_put_be32s(f, &s->gafr[i * 2 + 1]);
+
+        qemu_put_be32s(f, &s->prev_level[i]);
+    }
+}
+
+static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_gpio_info_s *s = (struct pxa2xx_gpio_info_s *) opaque;
+    int i;
+
+    if (qemu_get_be32(f) != s->lines)
+        return -EINVAL;
+
+    for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
+        qemu_get_be32s(f, &s->ilevel[i]);
+        qemu_get_be32s(f, &s->olevel[i]);
+        qemu_get_be32s(f, &s->dir[i]);
+        qemu_get_be32s(f, &s->rising[i]);
+        qemu_get_be32s(f, &s->falling[i]);
+        qemu_get_be32s(f, &s->status[i]);
+        qemu_get_be32s(f, &s->gafr[i * 2 + 0]);
+        qemu_get_be32s(f, &s->gafr[i * 2 + 1]);
+
+        qemu_get_be32s(f, &s->prev_level[i]);
+    }
+
+    return 0;
+}
+
 struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base,
                 CPUState *env, qemu_irq *pic, int lines)
 {
@@ -265,6 +310,9 @@
                     pxa2xx_gpio_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
 
+    register_savevm("pxa2xx_gpio", 0, 0,
+                    pxa2xx_gpio_save, pxa2xx_gpio_load, s);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_lcd.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -924,6 +924,81 @@
     pxa2xx_lcdc_resize(s);
 }
 
+static void pxa2xx_lcdc_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+    int i;
+
+    qemu_put_be32(f, s->irqlevel);
+    qemu_put_be32(f, s->transp);
+
+    for (i = 0; i < 6; i ++)
+        qemu_put_be32s(f, &s->control[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->status[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->ovl1c[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->ovl2c[i]);
+    qemu_put_be32s(f, &s->ccr);
+    qemu_put_be32s(f, &s->cmdcr);
+    qemu_put_be32s(f, &s->trgbr);
+    qemu_put_be32s(f, &s->tcr);
+    qemu_put_be32s(f, &s->liidr);
+    qemu_put_8s(f, &s->bscntr);
+
+    for (i = 0; i < 7; i ++) {
+        qemu_put_betl(f, s->dma_ch[i].branch);
+        qemu_put_byte(f, s->dma_ch[i].up);
+        qemu_put_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
+
+        qemu_put_betl(f, s->dma_ch[i].descriptor);
+        qemu_put_betl(f, s->dma_ch[i].source);
+        qemu_put_be32s(f, &s->dma_ch[i].id);
+        qemu_put_be32s(f, &s->dma_ch[i].command);
+    }
+}
+
+static int pxa2xx_lcdc_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque;
+    int i;
+
+    s->irqlevel = qemu_get_be32(f);
+    s->transp = qemu_get_be32(f);
+
+    for (i = 0; i < 6; i ++)
+        qemu_get_be32s(f, &s->control[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->status[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->ovl1c[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->ovl2c[i]);
+    qemu_get_be32s(f, &s->ccr);
+    qemu_get_be32s(f, &s->cmdcr);
+    qemu_get_be32s(f, &s->trgbr);
+    qemu_get_be32s(f, &s->tcr);
+    qemu_get_be32s(f, &s->liidr);
+    qemu_get_8s(f, &s->bscntr);
+
+    for (i = 0; i < 7; i ++) {
+        s->dma_ch[i].branch = qemu_get_betl(f);
+        s->dma_ch[i].up = qemu_get_byte(f);
+        qemu_get_buffer(f, s->dma_ch[i].pbuffer, sizeof(s->dma_ch[i].pbuffer));
+
+        s->dma_ch[i].descriptor = qemu_get_betl(f);
+        s->dma_ch[i].source = qemu_get_betl(f);
+        qemu_get_be32s(f, &s->dma_ch[i].id);
+        qemu_get_be32s(f, &s->dma_ch[i].command);
+    }
+
+    s->bpp = LCCR3_BPP(s->control[3]);
+    s->xres = s->yres = s->pal_for = -1;
+
+    return 0;
+}
+
 #define BITS 8
 #include "pxa2xx_template.h"
 #define BITS 15
@@ -989,6 +1064,10 @@
         fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
         exit(1);
     }
+
+    register_savevm("pxa2xx_lcdc", 0, 0,
+                    pxa2xx_lcdc_save, pxa2xx_lcdc_load, s);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_mmci.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -443,6 +443,84 @@
     pxa2xx_mmci_writew
 };
 
+static void pxa2xx_mmci_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
+    int i;
+
+    qemu_put_be32s(f, &s->status);
+    qemu_put_be32s(f, &s->clkrt);
+    qemu_put_be32s(f, &s->spi);
+    qemu_put_be32s(f, &s->cmdat);
+    qemu_put_be32s(f, &s->resp_tout);
+    qemu_put_be32s(f, &s->read_tout);
+    qemu_put_be32(f, s->blklen);
+    qemu_put_be32(f, s->numblk);
+    qemu_put_be32s(f, &s->intmask);
+    qemu_put_be32s(f, &s->intreq);
+    qemu_put_be32(f, s->cmd);
+    qemu_put_be32s(f, &s->arg);
+    qemu_put_be32(f, s->cmdreq);
+    qemu_put_be32(f, s->active);
+    qemu_put_be32(f, s->bytesleft);
+
+    qemu_put_byte(f, s->tx_len);
+    for (i = 0; i < s->tx_len; i ++)
+        qemu_put_byte(f, s->tx_fifo[(s->tx_start + i) & 63]);
+
+    qemu_put_byte(f, s->rx_len);
+    for (i = 0; i < s->rx_len; i ++)
+        qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 31]);
+
+    qemu_put_byte(f, s->resp_len);
+    for (i = s->resp_len; i < 9; i ++)
+        qemu_put_be16s(f, &s->resp_fifo[i]);
+}
+
+static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_mmci_s *s = (struct pxa2xx_mmci_s *) opaque;
+    int i;
+
+    qemu_get_be32s(f, &s->status);
+    qemu_get_be32s(f, &s->clkrt);
+    qemu_get_be32s(f, &s->spi);
+    qemu_get_be32s(f, &s->cmdat);
+    qemu_get_be32s(f, &s->resp_tout);
+    qemu_get_be32s(f, &s->read_tout);
+    s->blklen = qemu_get_be32(f);
+    s->numblk = qemu_get_be32(f);
+    qemu_get_be32s(f, &s->intmask);
+    qemu_get_be32s(f, &s->intreq);
+    s->cmd = qemu_get_be32(f);
+    qemu_get_be32s(f, &s->arg);
+    s->cmdreq = qemu_get_be32(f);
+    s->active = qemu_get_be32(f);
+    s->bytesleft = qemu_get_be32(f);
+
+    s->tx_len = qemu_get_byte(f);
+    s->tx_start = 0;
+    if (s->tx_len >= sizeof(s->tx_fifo) || s->tx_len < 0)
+        return -EINVAL;
+    for (i = 0; i < s->tx_len; i ++)
+        s->tx_fifo[i] = qemu_get_byte(f);
+
+    s->rx_len = qemu_get_byte(f);
+    s->rx_start = 0;
+    if (s->rx_len >= sizeof(s->rx_fifo) || s->rx_len < 0)
+        return -EINVAL;
+    for (i = 0; i < s->rx_len; i ++)
+        s->rx_fifo[i] = qemu_get_byte(f);
+
+    s->resp_len = qemu_get_byte(f);
+    if (s->resp_len > 9 || s->resp_len < 0)
+        return -EINVAL;
+    for (i = s->resp_len; i < 9; i ++)
+         qemu_get_be16s(f, &s->resp_fifo[i]);
+
+    return 0;
+}
+
 struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base,
                 qemu_irq irq, void *dma)
 {
@@ -461,6 +539,9 @@
     /* Instantiate the actual storage */
     s->card = sd_init(sd_bdrv);
 
+    register_savevm("pxa2xx_mmci", 0, 0,
+                    pxa2xx_mmci_save, pxa2xx_mmci_load, s);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_pcmcia.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -171,6 +171,7 @@
         s->slot.slot_string = "PXA PC Card Socket 0";
     s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
     pcmcia_socket_register(&s->slot);
+
     return s;
 }
 

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_pic.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -245,6 +245,41 @@
     pxa2xx_pic_mem_write,
 };
 
+static void pxa2xx_pic_save(QEMUFile *f, void *opaque)
+{
+    struct pxa2xx_pic_state_s *s = (struct pxa2xx_pic_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->int_enabled[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->int_pending[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_put_be32s(f, &s->is_fiq[i]);
+    qemu_put_be32s(f, &s->int_idle);
+    for (i = 0; i < PXA2XX_PIC_SRCS; i ++)
+        qemu_put_be32s(f, &s->priority[i]);
+}
+
+static int pxa2xx_pic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct pxa2xx_pic_state_s *s = (struct pxa2xx_pic_state_s *) opaque;
+    int i;
+
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->int_enabled[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->int_pending[i]);
+    for (i = 0; i < 2; i ++)
+        qemu_get_be32s(f, &s->is_fiq[i]);
+    qemu_get_be32s(f, &s->int_idle);
+    for (i = 0; i < PXA2XX_PIC_SRCS; i ++)
+        qemu_get_be32s(f, &s->priority[i]);
+
+    pxa2xx_pic_update(opaque);
+    return 0;
+}
+
 qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env)
 {
     struct pxa2xx_pic_state_s *s;
@@ -276,5 +311,7 @@
     /* Enable IC coprocessor access.  */
     cpu_arm_set_cp_io(env, 6, pxa2xx_pic_cp_read, pxa2xx_pic_cp_write, s);
 
+    register_savevm("pxa2xx_pic", 0, 0, pxa2xx_pic_save, pxa2xx_pic_load, s);
+
     return qi;
 }

Modified: trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/pxa2xx_timer.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -75,7 +75,7 @@
 };
 
 typedef struct {
-    uint32_t base;
+    target_phys_addr_t base;
     int32_t clock;
     int32_t oldclock;
     uint64_t lastload;
@@ -85,8 +85,6 @@
     uint32_t events;
     uint32_t irq_enabled;
     uint32_t reset3;
-    CPUState *cpustate;
-    int64_t qemu_ticks;
     uint32_t snapshot;
 } pxa2xx_timer_info;
 
@@ -121,7 +119,7 @@
         counter = counters[n];
 
     if (!s->tm4[counter].freq) {
-        qemu_del_timer(s->timer[n].qtimer);
+        qemu_del_timer(s->tm4[n].tm.qtimer);
         return;
     }
 
@@ -131,7 +129,7 @@
 
     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
                     ticks_per_sec, s->tm4[counter].freq);
-    qemu_mod_timer(s->timer[n].qtimer, new_qemu);
+    qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 }
 
 static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
@@ -350,7 +348,7 @@
     if (t->num == 3)
         if (i->reset3 & 1) {
             i->reset3 = 0;
-            cpu_reset(i->cpustate);
+            qemu_system_reset_request();
         }
 }
 
@@ -366,8 +364,75 @@
         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
 }
 
+static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
+{
+    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    int i;
+
+    qemu_put_be32s(f, &s->clock);
+    qemu_put_be32s(f, &s->oldclock);
+    qemu_put_be64s(f, &s->lastload);
+
+    for (i = 0; i < 4; i ++) {
+        qemu_put_be32s(f, &s->timer[i].value);
+        qemu_put_be32(f, s->timer[i].level);
+    }
+    if (s->tm4)
+        for (i = 0; i < 8; i ++) {
+            qemu_put_be32s(f, &s->tm4[i].tm.value);
+            qemu_put_be32(f, s->tm4[i].tm.level);
+            qemu_put_be32s(f, &s->tm4[i].oldclock);
+            qemu_put_be32s(f, &s->tm4[i].clock);
+            qemu_put_be64s(f, &s->tm4[i].lastload);
+            qemu_put_be32s(f, &s->tm4[i].freq);
+            qemu_put_be32s(f, &s->tm4[i].control);
+        }
+
+    qemu_put_be32s(f, &s->events);
+    qemu_put_be32s(f, &s->irq_enabled);
+    qemu_put_be32s(f, &s->reset3);
+    qemu_put_be32s(f, &s->snapshot);
+}
+
+static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
+{
+    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
+    int64_t now;
+    int i;
+
+    qemu_get_be32s(f, &s->clock);
+    qemu_get_be32s(f, &s->oldclock);
+    qemu_get_be64s(f, &s->lastload);
+
+    now = qemu_get_clock(vm_clock);
+    for (i = 0; i < 4; i ++) {
+        qemu_get_be32s(f, &s->timer[i].value);
+        s->timer[i].level = qemu_get_be32(f);
+    }
+    pxa2xx_timer_update(s, now);
+
+    if (s->tm4)
+        for (i = 0; i < 8; i ++) {
+            qemu_get_be32s(f, &s->tm4[i].tm.value);
+            s->tm4[i].tm.level = qemu_get_be32(f);
+            qemu_get_be32s(f, &s->tm4[i].oldclock);
+            qemu_get_be32s(f, &s->tm4[i].clock);
+            qemu_get_be64s(f, &s->tm4[i].lastload);
+            qemu_get_be32s(f, &s->tm4[i].freq);
+            qemu_get_be32s(f, &s->tm4[i].control);
+            pxa2xx_timer_update4(s, now, i);
+        }
+
+    qemu_get_be32s(f, &s->events);
+    qemu_get_be32s(f, &s->irq_enabled);
+    qemu_get_be32s(f, &s->reset3);
+    qemu_get_be32s(f, &s->snapshot);
+
+    return 0;
+}
+
 static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, CPUState *cpustate)
+                qemu_irq *irqs)
 {
     int i;
     int iomemtype;
@@ -380,7 +445,6 @@
     s->clock = 0;
     s->lastload = qemu_get_clock(vm_clock);
     s->reset3 = 0;
-    s->cpustate = cpustate;
 
     for (i = 0; i < 4; i ++) {
         s->timer[i].value = 0;
@@ -395,21 +459,24 @@
     iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
                     pxa2xx_timer_writefn, s);
     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
+
+    register_savevm("pxa2xx_timer", 0, 0,
+                    pxa2xx_timer_save, pxa2xx_timer_load, s);
+
     return s;
 }
 
-void pxa25x_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, CPUState *cpustate)
+void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
     s->freq = PXA25X_FREQ;
     s->tm4 = 0;
 }
 
 void pxa27x_timer_init(target_phys_addr_t base,
-                qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate)
+                qemu_irq *irqs, qemu_irq irq4)
 {
-    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
+    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
     int i;
     s->freq = PXA27X_FREQ;
     s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *

Modified: trunk/src/host/qemu-neo1973/hw/spitz.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/spitz.c	2007-05-23 11:38:46 UTC (rev 2067)
+++ trunk/src/host/qemu-neo1973/hw/spitz.c	2007-05-23 12:44:30 UTC (rev 2068)
@@ -109,6 +109,24 @@
     }
 }
 
+static void sl_save(QEMUFile *f, void *opaque)
+{
+    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
+
+    qemu_put_8s(f, &s->ctl);
+    ecc_put(f, &s->ecc);
+}
+
+static int sl_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct sl_nand_s *s = (struct sl_nand_s *) opaque;
+
+    qemu_get_8s(f, &s->ctl);
+    ecc_get(f, &s->ecc);
+
+    return 0;
+}
+
 enum {
     FLASH_128M,
     FLASH_1024M,
@@ -140,6 +158,8 @@
     iomemtype = cpu_register_io_memory(0, sl_readfn,
                     sl_writefn, s);
     cpu_register_physical_memory(s->target_base, 0x40, iomemtype);
+
+    register_savevm("sl_flash", 0, 0, sl_save, sl_load, s);
 }
 
 /* Spitz Keyboard */
@@ -406,6 +426,38 @@
 #undef CTRL
 #undef FN
 
+static void spitz_keyboard_save(QEMUFile *f, void *opaque)
+{
+    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
+    int i;
+
+    qemu_put_be16s(f, &s->sense_state);
+    qemu_put_be16s(f, &s->strobe_state);
+    for (i = 0; i < 5; i ++)
+        qemu_put_byte(f, spitz_gpio_invert[i]);
+}
+
+static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct spitz_keyboard_s *s = (struct spitz_keyboard_s *) opaque;
+    int i;
+
+    qemu_get_be16s(f, &s->sense_state);
+    qemu_get_be16s(f, &s->strobe_state);
+    for (i = 0; i < 5; i ++)
+        spitz_gpio_invert[i] = qemu_get_byte(f);
+
+    /* Release all pressed keys */
+    memset(s->keyrow, 0, sizeof(s->keyrow));
+    spitz_keyboard_sense_update(s);
+    s->modifiers = 0;
+    s->imodifiers = 0;
+    s->fifopos = 0;
+    s->fifolen = 0;
+
+    return 0;
+}
+
 static void spitz_keyboard_register(struct pxa2xx_state_s *cpu)
 {
     int i, j;
@@ -429,6 +481,9 @@
 
     spitz_keyboard_pre_map(s);
     qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
+
+    register_savevm("spitz_keyboard", 0, 0,
+                    spitz_keyboard_save, spitz_keyboard_load, s);
 }
 
 /* SCOOP devices */
@@ -597,6 +652,42 @@
     s->handler[line].opaque = opaque;
 }
 
+static void scoop_save(QEMUFile *f, void *opaque)
+{
+    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
+    qemu_put_be16s(f, &s->status);
+    qemu_put_be16s(f, &s->power);
+    qemu_put_be32s(f, &s->gpio_level);
+    qemu_put_be32s(f, &s->gpio_dir);
+    qemu_put_be32s(f, &s->prev_level);
+    qemu_put_be16s(f, &s->mcr);
+    qemu_put_be16s(f, &s->cdr);
+    qemu_put_be16s(f, &s->ccr);
+    qemu_put_be16s(f, &s->irr);
+    qemu_put_be16s(f, &s->imr);
+    qemu_put_be16s(f, &s->isr);
+    qemu_put_be16s(f, &s->gprr);
+}
+
+static int scoop_load(QEMUFile *f, void *opaque, int version_id)
+{
+    struct scoop_info_s *s = (struct scoop_info_s *) opaque;
+    qemu_get_be16s(f, &s->status);
+    qemu_get_be16s(f, &s->power);
+    qemu_get_be32s(f, &s->gpio_level);
+    qemu_get_be32s(f, &s->gpio_dir);
+    qemu_get_be32s(f, &s->prev_level);
+    qemu_get_be16s(f, &s->mcr);
+    qemu_get_be16s(f, &s->cdr);
+    qemu_get_be16s(f, &s->ccr);
+    qemu_get_be16s(f, &s->irr);
+    qemu_get_be16s(f, &s->imr);
+    qemu_get_be16s(f, &s->isr);
+    qemu_get_be16s(f, &s->gprr);
+
+    return 0;
+}
+
 static struct scoop_info_s *spitz_scoop_init(struct pxa2xx_state_s *cpu,
                 int count) {
     int iomemtype;
@@ -615,6 +706,7 @@
     iomemtype = cpu_register_io_memory(0, scoop_readfn,
                     scoop_writefn, &s[0]);
     cpu_register_physical_memory(s[0].target_base, 0xfff, iomemtype);
+    register_savevm("scoop", 0, 0, scoop_save, scoop_load, &s[0]);
 
     if (count < 2)
         return s;
@@ -622,6 +714,7 @@
     iomemtype = cpu_register_io_memory(0, scoop_readfn,
                     scoop_writefn, &s[1]);
     cpu_register_physical_memory(s[1].target_base, 0xfff, iomemtype);
+    register_savevm("scoop", 1, 0, scoop_save, scoop_load, &s[1]);
 
     return s;
 }
@@ -763,6 +856,26 @@
     pxa2xx_gpio_set(cpu->gpio, SPITZ_GPIO_TP_INT, level);
 }
 
+static void spitz_ssp_save(QEMUFile *f, void *opaque)
+{
+    qemu_put_be32(f, lcd_en);
+    qemu_put_be32(f, ads_en);
+    qemu_put_be32(f, max_en);
+    qemu_put_be32(f, bl_intensity);
+    qemu_put_be32(f, bl_power);
+}
+
+static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id)
+{
+    lcd_en = qemu_get_be32(f);
+    ads_en = qemu_get_be32(f);
+    max_en = qemu_get_be32(f);
+    bl_intensity = qemu_get_be32(f);
+    bl_power = qemu_get_be32(f);
+
+    return 0;
+}
+
 static void spitz_ssp_attach(struct pxa2xx_state_s *cpu)
 {
     lcd_en = ads_en = max_en = 0;
@@ -786,6 +899,8 @@
 
     bl_intensity = 0x20;
     bl_power = 0;
+
+    register_savevm("spitz_ssp", 0, 0, spitz_ssp_save, spitz_ssp_load, cpu);
 }
 
 /* CF Microdrive */





More information about the commitlog mailing list