Commit c701b35b42d50537122486e47006d1c6ce952240
1 parent
75f482ae
Fix i2c save/restore.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4820 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
33 additions
and
27 deletions
hw/i2c.c
@@ -14,14 +14,38 @@ struct i2c_bus | @@ -14,14 +14,38 @@ struct i2c_bus | ||
14 | { | 14 | { |
15 | i2c_slave *current_dev; | 15 | i2c_slave *current_dev; |
16 | i2c_slave *dev; | 16 | i2c_slave *dev; |
17 | + int saved_address; | ||
17 | }; | 18 | }; |
18 | 19 | ||
20 | +static void i2c_bus_save(QEMUFile *f, void *opaque) | ||
21 | +{ | ||
22 | + i2c_bus *bus = (i2c_bus *)opaque; | ||
23 | + | ||
24 | + qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : -1); | ||
25 | +} | ||
26 | + | ||
27 | +static int i2c_bus_load(QEMUFile *f, void *opaque, int version_id) | ||
28 | +{ | ||
29 | + i2c_bus *bus = (i2c_bus *)opaque; | ||
30 | + | ||
31 | + if (version_id != 1) | ||
32 | + return -EINVAL; | ||
33 | + | ||
34 | + /* The bus is loaded before attached devices, so load and save the | ||
35 | + current device id. Devices will check themselves as loaded. */ | ||
36 | + bus->saved_address = qemu_get_be32(f); | ||
37 | + bus->current_dev = NULL; | ||
38 | + | ||
39 | + return 0; | ||
40 | +} | ||
41 | + | ||
19 | /* Create a new I2C bus. */ | 42 | /* Create a new I2C bus. */ |
20 | i2c_bus *i2c_init_bus(void) | 43 | i2c_bus *i2c_init_bus(void) |
21 | { | 44 | { |
22 | i2c_bus *bus; | 45 | i2c_bus *bus; |
23 | 46 | ||
24 | bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus)); | 47 | bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus)); |
48 | + register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus); | ||
25 | return bus; | 49 | return bus; |
26 | } | 50 | } |
27 | 51 | ||
@@ -37,6 +61,7 @@ i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size) | @@ -37,6 +61,7 @@ i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size) | ||
37 | dev->address = address; | 61 | dev->address = address; |
38 | dev->next = bus->dev; | 62 | dev->next = bus->dev; |
39 | bus->dev = dev; | 63 | bus->dev = dev; |
64 | + dev->bus = bus; | ||
40 | 65 | ||
41 | return dev; | 66 | return dev; |
42 | } | 67 | } |
@@ -115,28 +140,6 @@ void i2c_nack(i2c_bus *bus) | @@ -115,28 +140,6 @@ void i2c_nack(i2c_bus *bus) | ||
115 | dev->event(dev, I2C_NACK); | 140 | dev->event(dev, I2C_NACK); |
116 | } | 141 | } |
117 | 142 | ||
118 | -void i2c_bus_save(QEMUFile *f, i2c_bus *bus) | ||
119 | -{ | ||
120 | - qemu_put_byte(f, bus->current_dev ? bus->current_dev->address : 0x00); | ||
121 | -} | ||
122 | - | ||
123 | -void i2c_bus_load(QEMUFile *f, i2c_bus *bus) | ||
124 | -{ | ||
125 | - i2c_slave *dev; | ||
126 | - uint8_t address = qemu_get_byte(f); | ||
127 | - | ||
128 | - if (address) { | ||
129 | - for (dev = bus->dev; dev; dev = dev->next) | ||
130 | - if (dev->address == address) { | ||
131 | - bus->current_dev = dev; | ||
132 | - return; | ||
133 | - } | ||
134 | - | ||
135 | - fprintf(stderr, "%s: I2C slave with address %02x disappeared\n", | ||
136 | - __FUNCTION__, address); | ||
137 | - } | ||
138 | -} | ||
139 | - | ||
140 | void i2c_slave_save(QEMUFile *f, i2c_slave *dev) | 143 | void i2c_slave_save(QEMUFile *f, i2c_slave *dev) |
141 | { | 144 | { |
142 | qemu_put_byte(f, dev->address); | 145 | qemu_put_byte(f, dev->address); |
@@ -145,4 +148,6 @@ void i2c_slave_save(QEMUFile *f, i2c_slave *dev) | @@ -145,4 +148,6 @@ void i2c_slave_save(QEMUFile *f, i2c_slave *dev) | ||
145 | void i2c_slave_load(QEMUFile *f, i2c_slave *dev) | 148 | void i2c_slave_load(QEMUFile *f, i2c_slave *dev) |
146 | { | 149 | { |
147 | dev->address = qemu_get_byte(f); | 150 | dev->address = qemu_get_byte(f); |
151 | + if (dev->bus->saved_address == dev->address) | ||
152 | + dev->bus->current_dev = dev; | ||
148 | } | 153 | } |
hw/i2c.h
@@ -30,6 +30,7 @@ struct i2c_slave | @@ -30,6 +30,7 @@ struct i2c_slave | ||
30 | /* Remaining fields for internal use by the I2C code. */ | 30 | /* Remaining fields for internal use by the I2C code. */ |
31 | int address; | 31 | int address; |
32 | void *next; | 32 | void *next; |
33 | + i2c_bus *bus; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | i2c_bus *i2c_init_bus(void); | 36 | i2c_bus *i2c_init_bus(void); |
@@ -41,8 +42,6 @@ void i2c_end_transfer(i2c_bus *bus); | @@ -41,8 +42,6 @@ void i2c_end_transfer(i2c_bus *bus); | ||
41 | void i2c_nack(i2c_bus *bus); | 42 | void i2c_nack(i2c_bus *bus); |
42 | int i2c_send(i2c_bus *bus, uint8_t data); | 43 | int i2c_send(i2c_bus *bus, uint8_t data); |
43 | int i2c_recv(i2c_bus *bus); | 44 | int i2c_recv(i2c_bus *bus); |
44 | -void i2c_bus_save(QEMUFile *f, i2c_bus *bus); | ||
45 | -void i2c_bus_load(QEMUFile *f, i2c_bus *bus); | ||
46 | void i2c_slave_save(QEMUFile *f, i2c_slave *dev); | 45 | void i2c_slave_save(QEMUFile *f, i2c_slave *dev); |
47 | void i2c_slave_load(QEMUFile *f, i2c_slave *dev); | 46 | void i2c_slave_load(QEMUFile *f, i2c_slave *dev); |
48 | 47 |
hw/pxa2xx.c
@@ -1466,7 +1466,6 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque) | @@ -1466,7 +1466,6 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque) | ||
1466 | qemu_put_8s(f, &s->ibmr); | 1466 | qemu_put_8s(f, &s->ibmr); |
1467 | qemu_put_8s(f, &s->data); | 1467 | qemu_put_8s(f, &s->data); |
1468 | 1468 | ||
1469 | - i2c_bus_save(f, s->bus); | ||
1470 | i2c_slave_save(f, &s->slave); | 1469 | i2c_slave_save(f, &s->slave); |
1471 | } | 1470 | } |
1472 | 1471 | ||
@@ -1474,12 +1473,14 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id) | @@ -1474,12 +1473,14 @@ static int pxa2xx_i2c_load(QEMUFile *f, void *opaque, int version_id) | ||
1474 | { | 1473 | { |
1475 | struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; | 1474 | struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; |
1476 | 1475 | ||
1476 | + if (version_id != 1) | ||
1477 | + return -EINVAL; | ||
1478 | + | ||
1477 | qemu_get_be16s(f, &s->control); | 1479 | qemu_get_be16s(f, &s->control); |
1478 | qemu_get_be16s(f, &s->status); | 1480 | qemu_get_be16s(f, &s->status); |
1479 | qemu_get_8s(f, &s->ibmr); | 1481 | qemu_get_8s(f, &s->ibmr); |
1480 | qemu_get_8s(f, &s->data); | 1482 | qemu_get_8s(f, &s->data); |
1481 | 1483 | ||
1482 | - i2c_bus_load(f, s->bus); | ||
1483 | i2c_slave_load(f, &s->slave); | 1484 | i2c_slave_load(f, &s->slave); |
1484 | return 0; | 1485 | return 0; |
1485 | } | 1486 | } |
@@ -1488,6 +1489,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, | @@ -1488,6 +1489,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, | ||
1488 | qemu_irq irq, uint32_t page_size) | 1489 | qemu_irq irq, uint32_t page_size) |
1489 | { | 1490 | { |
1490 | int iomemtype; | 1491 | int iomemtype; |
1492 | + /* FIXME: Should the slave device really be on a separate bus? */ | ||
1491 | struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) | 1493 | struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) |
1492 | i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s)); | 1494 | i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s)); |
1493 | 1495 | ||
@@ -1502,7 +1504,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, | @@ -1502,7 +1504,7 @@ struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, | ||
1502 | pxa2xx_i2c_writefn, s); | 1504 | pxa2xx_i2c_writefn, s); |
1503 | cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype); | 1505 | cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype); |
1504 | 1506 | ||
1505 | - register_savevm("pxa2xx_i2c", base, 0, | 1507 | + register_savevm("pxa2xx_i2c", base, 1, |
1506 | pxa2xx_i2c_save, pxa2xx_i2c_load, s); | 1508 | pxa2xx_i2c_save, pxa2xx_i2c_load, s); |
1507 | 1509 | ||
1508 | return s; | 1510 | return s; |