]> xenbits.xensource.com Git - qemu-xen-4.6-testing.git/commitdiff
Fix i2c save/restore.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 1 Jul 2008 23:16:53 +0000 (23:16 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 1 Jul 2008 23:16:53 +0000 (23:16 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4820 c046a42c-6fe2-441c-8c8c-71466251a162

hw/i2c.c
hw/i2c.h
hw/pxa2xx.c

index e590801af30957268b28dd4b2d1dd3fd9fb6b7e1..5d283fb4cb723999bc2d573fcffaa1fbfe9fcc1f 100644 (file)
--- a/hw/i2c.c
+++ b/hw/i2c.c
@@ -14,14 +14,38 @@ struct i2c_bus
 {
     i2c_slave *current_dev;
     i2c_slave *dev;
+    int saved_address;
 };
 
+static void i2c_bus_save(QEMUFile *f, void *opaque)
+{
+    i2c_bus *bus = (i2c_bus *)opaque;
+
+    qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : -1);
+}
+
+static int i2c_bus_load(QEMUFile *f, void *opaque, int version_id)
+{
+    i2c_bus *bus = (i2c_bus *)opaque;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    /* The bus is loaded before attached devices, so load and save the
+       current device id.  Devices will check themselves as loaded.  */
+    bus->saved_address = qemu_get_be32(f);
+    bus->current_dev = NULL;
+
+    return 0;
+}
+
 /* Create a new I2C bus.  */
 i2c_bus *i2c_init_bus(void)
 {
     i2c_bus *bus;
 
     bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
+    register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus);
     return bus;
 }
 
@@ -37,6 +61,7 @@ i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
     dev->address = address;
     dev->next = bus->dev;
     bus->dev = dev;
+    dev->bus = bus;
 
     return dev;
 }
@@ -115,28 +140,6 @@ void i2c_nack(i2c_bus *bus)
     dev->event(dev, I2C_NACK);
 }
 
-void i2c_bus_save(QEMUFile *f, i2c_bus *bus)
-{
-    qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : 0x00);
-}
-
-void i2c_bus_load(QEMUFile *f, i2c_bus *bus)
-{
-    i2c_slave *dev;
-    uint8_t address = qemu_get_byte(f);
-
-    if (address) {
-        for (dev = bus->dev; dev; dev = dev->next)
-            if (dev->address == address) {
-                bus->current_dev = dev;
-                return;
-            }
-
-        fprintf(stderr, "%s: I2C slave with address %02x disappeared\n",
-                __FUNCTION__, address);
-    }
-}
-
 void i2c_slave_save(QEMUFile *f, i2c_slave *dev)
 {
     qemu_put_byte(f, dev->address);
@@ -145,4 +148,6 @@ void i2c_slave_save(QEMUFile *f, i2c_slave *dev)
 void i2c_slave_load(QEMUFile *f, i2c_slave *dev)
 {
     dev->address = qemu_get_byte(f);
+    if (dev->bus->saved_address == dev->address)
+        dev->bus->current_dev = dev;
 }
index f297237b728b99f195e10de629095bf1c882d99b..d3e4352b1ffc040f6602cbf13c2607def4085e1b 100644 (file)
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -30,6 +30,7 @@ struct i2c_slave
     /* Remaining fields for internal use by the I2C code.  */
     int address;
     void *next;
+    i2c_bus *bus;
 };
 
 i2c_bus *i2c_init_bus(void);
@@ -41,8 +42,6 @@ void i2c_end_transfer(i2c_bus *bus);
 void i2c_nack(i2c_bus *bus);
 int i2c_send(i2c_bus *bus, uint8_t data);
 int i2c_recv(i2c_bus *bus);
-void i2c_bus_save(QEMUFile *f, i2c_bus *bus);
-void i2c_bus_load(QEMUFile *f, i2c_bus *bus);
 void i2c_slave_save(QEMUFile *f, i2c_slave *dev);
 void i2c_slave_load(QEMUFile *f, i2c_slave *dev);
 
index cb6670c3546b0685673b74f424ad079075c32b7a..fd663d9da1788208e2db988dd2a41d6cb00834dc 100644 (file)
@@ -1466,7 +1466,6 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque)
     qemu_put_8s(f, &s->ibmr);
     qemu_put_8s(f, &s->data);
 
-    i2c_bus_save(f, s->bus);
     i2c_slave_save(f, &s->slave);
 }
 
@@ -1474,12 +1473,14 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id)
 {
     struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque;
 
+    if (version_id != 1)
+        return -EINVAL;
+
     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;
 }
@@ -1488,6 +1489,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base,
                 qemu_irq irq, uint32_t page_size)
 {
     int iomemtype;
+    /* FIXME: Should the slave device really be on a separate bus?  */
     struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *)
             i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s));
 
@@ -1502,7 +1504,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base,
                     pxa2xx_i2c_writefn, s);
     cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype);
 
-    register_savevm("pxa2xx_i2c", base, 0,
+    register_savevm("pxa2xx_i2c", base, 1,
                     pxa2xx_i2c_save, pxa2xx_i2c_load, s);
 
     return s;