mirror of https://github.com/xemu-project/xemu.git
Fix i2c save/restore.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4820 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
75f482aeed
commit
c701b35b42
49
hw/i2c.c
49
hw/i2c.c
|
@ -14,14 +14,38 @@ struct i2c_bus
|
||||||
{
|
{
|
||||||
i2c_slave *current_dev;
|
i2c_slave *current_dev;
|
||||||
i2c_slave *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. */
|
/* Create a new I2C bus. */
|
||||||
i2c_bus *i2c_init_bus(void)
|
i2c_bus *i2c_init_bus(void)
|
||||||
{
|
{
|
||||||
i2c_bus *bus;
|
i2c_bus *bus;
|
||||||
|
|
||||||
bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
|
bus = (i2c_bus *)qemu_mallocz(sizeof(i2c_bus));
|
||||||
|
register_savevm("i2c_bus", -1, 1, i2c_bus_save, i2c_bus_load, bus);
|
||||||
return bus;
|
return bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +61,7 @@ i2c_slave *i2c_slave_init(i2c_bus *bus, int address, int size)
|
||||||
dev->address = address;
|
dev->address = address;
|
||||||
dev->next = bus->dev;
|
dev->next = bus->dev;
|
||||||
bus->dev = dev;
|
bus->dev = dev;
|
||||||
|
dev->bus = bus;
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
@ -115,28 +140,6 @@ void i2c_nack(i2c_bus *bus)
|
||||||
dev->event(dev, I2C_NACK);
|
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)
|
void i2c_slave_save(QEMUFile *f, i2c_slave *dev)
|
||||||
{
|
{
|
||||||
qemu_put_byte(f, dev->address);
|
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)
|
void i2c_slave_load(QEMUFile *f, i2c_slave *dev)
|
||||||
{
|
{
|
||||||
dev->address = qemu_get_byte(f);
|
dev->address = qemu_get_byte(f);
|
||||||
|
if (dev->bus->saved_address == dev->address)
|
||||||
|
dev->bus->current_dev = dev;
|
||||||
}
|
}
|
||||||
|
|
3
hw/i2c.h
3
hw/i2c.h
|
@ -30,6 +30,7 @@ struct i2c_slave
|
||||||
/* Remaining fields for internal use by the I2C code. */
|
/* Remaining fields for internal use by the I2C code. */
|
||||||
int address;
|
int address;
|
||||||
void *next;
|
void *next;
|
||||||
|
i2c_bus *bus;
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c_bus *i2c_init_bus(void);
|
i2c_bus *i2c_init_bus(void);
|
||||||
|
@ -41,8 +42,6 @@ void i2c_end_transfer(i2c_bus *bus);
|
||||||
void i2c_nack(i2c_bus *bus);
|
void i2c_nack(i2c_bus *bus);
|
||||||
int i2c_send(i2c_bus *bus, uint8_t data);
|
int i2c_send(i2c_bus *bus, uint8_t data);
|
||||||
int i2c_recv(i2c_bus *bus);
|
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_save(QEMUFile *f, i2c_slave *dev);
|
||||||
void i2c_slave_load(QEMUFile *f, i2c_slave *dev);
|
void i2c_slave_load(QEMUFile *f, i2c_slave *dev);
|
||||||
|
|
||||||
|
|
|
@ -1466,7 +1466,6 @@ static void pxa2xx_i2c_save(QEMUFile *f, void *opaque)
|
||||||
qemu_put_8s(f, &s->ibmr);
|
qemu_put_8s(f, &s->ibmr);
|
||||||
qemu_put_8s(f, &s->data);
|
qemu_put_8s(f, &s->data);
|
||||||
|
|
||||||
i2c_bus_save(f, s->bus);
|
|
||||||
i2c_slave_save(f, &s->slave);
|
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;
|
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->control);
|
||||||
qemu_get_be16s(f, &s->status);
|
qemu_get_be16s(f, &s->status);
|
||||||
qemu_get_8s(f, &s->ibmr);
|
qemu_get_8s(f, &s->ibmr);
|
||||||
qemu_get_8s(f, &s->data);
|
qemu_get_8s(f, &s->data);
|
||||||
|
|
||||||
i2c_bus_load(f, s->bus);
|
|
||||||
i2c_slave_load(f, &s->slave);
|
i2c_slave_load(f, &s->slave);
|
||||||
return 0;
|
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)
|
qemu_irq irq, uint32_t page_size)
|
||||||
{
|
{
|
||||||
int iomemtype;
|
int iomemtype;
|
||||||
|
/* FIXME: Should the slave device really be on a separate bus? */
|
||||||
struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *)
|
struct pxa2xx_i2c_s *s = (struct pxa2xx_i2c_s *)
|
||||||
i2c_slave_init(i2c_init_bus(), 0, sizeof(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);
|
pxa2xx_i2c_writefn, s);
|
||||||
cpu_register_physical_memory(s->base & ~page_size, page_size, iomemtype);
|
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);
|
pxa2xx_i2c_save, pxa2xx_i2c_load, s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
Loading…
Reference in New Issue