Revision c701b35b
b/hw/i2c.c | ||
---|---|---|
14 | 14 |
{ |
15 | 15 |
i2c_slave *current_dev; |
16 | 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 | 42 |
/* Create a new I2C bus. */ |
20 | 43 |
i2c_bus *i2c_init_bus(void) |
21 | 44 |
{ |
22 | 45 |
i2c_bus *bus; |
23 | 46 |
|
24 | 47 |
bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus)); |
48 |
register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus); |
|
25 | 49 |
return bus; |
26 | 50 |
} |
27 | 51 |
|
... | ... | |
37 | 61 |
dev->address = address; |
38 | 62 |
dev->next = bus->dev; |
39 | 63 |
bus->dev = dev; |
64 |
dev->bus = bus; |
|
40 | 65 |
|
41 | 66 |
return dev; |
42 | 67 |
} |
... | ... | |
115 | 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 | 143 |
void i2c_slave_save(QEMUFile *f, i2c_slave *dev) |
141 | 144 |
{ |
142 | 145 |
qemu_put_byte(f, dev->address); |
... | ... | |
145 | 148 |
void i2c_slave_load(QEMUFile *f, i2c_slave *dev) |
146 | 149 |
{ |
147 | 150 |
dev->address = qemu_get_byte(f); |
151 |
if (dev->bus->saved_address == dev->address) |
|
152 |
dev->bus->current_dev = dev; |
|
148 | 153 |
} |
b/hw/i2c.h | ||
---|---|---|
30 | 30 |
/* Remaining fields for internal use by the I2C code. */ |
31 | 31 |
int address; |
32 | 32 |
void *next; |
33 |
i2c_bus *bus; |
|
33 | 34 |
}; |
34 | 35 |
|
35 | 36 |
i2c_bus *i2c_init_bus(void); |
... | ... | |
41 | 42 |
void i2c_nack(i2c_bus *bus); |
42 | 43 |
int i2c_send(i2c_bus *bus, uint8_t data); |
43 | 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 | 45 |
void i2c_slave_save(QEMUFile *f, i2c_slave *dev); |
47 | 46 |
void i2c_slave_load(QEMUFile *f, i2c_slave *dev); |
48 | 47 |
|
b/hw/pxa2xx.c | ||
---|---|---|
1466 | 1466 |
qemu_put_8s(f, &s->ibmr); |
1467 | 1467 |
qemu_put_8s(f, &s->data); |
1468 | 1468 |
|
1469 |
i2c_bus_save(f, s->bus); |
|
1470 | 1469 |
i2c_slave_save(f, &s->slave); |
1471 | 1470 |
} |
1472 | 1471 |
|
... | ... | |
1474 | 1473 |
{ |
1475 | 1474 |
struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) opaque; |
1476 | 1475 |
|
1476 |
if (version_id != 1) |
|
1477 |
return -EINVAL; |
|
1478 |
|
|
1477 | 1479 |
qemu_get_be16s(f, &s->control); |
1478 | 1480 |
qemu_get_be16s(f, &s->status); |
1479 | 1481 |
qemu_get_8s(f, &s->ibmr); |
1480 | 1482 |
qemu_get_8s(f, &s->data); |
1481 | 1483 |
|
1482 |
i2c_bus_load(f, s->bus); |
|
1483 | 1484 |
i2c_slave_load(f, &s->slave); |
1484 | 1485 |
return 0; |
1485 | 1486 |
} |
... | ... | |
1488 | 1489 |
qemu_irq irq, uint32_t page_size) |
1489 | 1490 |
{ |
1490 | 1491 |
int iomemtype; |
1492 |
/* FIXME: Should the slave device really be on a separate bus? */ |
|
1491 | 1493 |
struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *) |
1492 | 1494 |
i2c_slave_init(i2c_init_bus(), 0, sizeof(struct pxa2xx_i2c_s)); |
1493 | 1495 |
|
... | ... | |
1502 | 1504 |
pxa2xx_i2c_writefn, s); |
1503 | 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 | 1508 |
pxa2xx_i2c_save, pxa2xx_i2c_load, s); |
1507 | 1509 |
|
1508 | 1510 |
return s; |
Also available in: Unified diff