pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x09;
- register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb);
- register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb);
+ pm_smbus_init(&s->dev.qdev, &s->smb);
+ memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
memory_region_init(&s->io, "piix4-pm", 64);
memory_region_set_enabled(&s->io, false);
s->powerdown_notifier.notify = piix4_pm_powerdown_req;
qemu_register_powerdown_notifier(&s->powerdown_notifier);
- pm_smbus_init(&s->dev.qdev, &s->smb);
s->machine_ready.notify = piix4_pm_machine_ready;
qemu_add_machine_init_done_notifier(&s->machine_ready);
qemu_register_reset(piix4_reset, s);
s->smb_stat |= 0x04;
}
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
{
PMSMBus *s = opaque;
- addr &= 0x3f;
+
SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val);
switch(addr) {
case SMBHSTSTS:
}
}
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr)
+static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
{
PMSMBus *s = opaque;
uint32_t val;
- addr &= 0x3f;
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
return val;
}
+static const MemoryRegionOps pm_smbus_ops = {
+ .read = smb_ioport_readb,
+ .write = smb_ioport_writeb,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 1,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
{
smb->smbus = i2c_init_bus(parent, "i2c");
+ memory_region_init_io(&smb->io, &pm_smbus_ops, smb, "pm-smbus", 64);
}
typedef struct PMSMBus {
i2c_bus *smbus;
+ MemoryRegion io;
uint8_t smb_stat;
uint8_t smb_ctl;
} PMSMBus;
void pm_smbus_init(DeviceState *parent, PMSMBus *smb);
-void smb_ioport_writeb(void *opaque, uint32_t addr, uint32_t val);
-uint32_t smb_ioport_readb(void *opaque, uint32_t addr);
#endif /* !PM_SMBUS_H */
PCIDevice dev;
PMSMBus smb;
- MemoryRegion mem_bar;
} ICH9SMBState;
static const VMStateDescription vmstate_ich9_smbus = {
}
};
-static void ich9_smb_ioport_writeb(void *opaque, hwaddr addr,
- uint64_t val, unsigned size)
+static void ich9_smbus_write_config(PCIDevice *d, uint32_t address,
+ uint32_t val, int len)
{
- ICH9SMBState *s = opaque;
- uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+ ICH9SMBState *s = ICH9_SMB_DEVICE(d);
- if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
- uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
- smb_ioport_writeb(&s->smb, offset, val);
+ pci_default_write_config(d, address, val, len);
+ if (range_covers_byte(address, len, ICH9_SMB_HOSTC)) {
+ uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
+ if ((hostc & ICH9_SMB_HOSTC_HST_EN) &&
+ !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
+ memory_region_set_enabled(&s->smb.io, true);
+ } else {
+ memory_region_set_enabled(&s->smb.io, false);
+ }
}
}
-static uint64_t ich9_smb_ioport_readb(void *opaque, hwaddr addr,
- unsigned size)
-{
- ICH9SMBState *s = opaque;
- uint8_t hostc = s->dev.config[ICH9_SMB_HOSTC];
-
- if ((hostc & ICH9_SMB_HOSTC_HST_EN) && !(hostc & ICH9_SMB_HOSTC_I2C_EN)) {
- uint64_t offset = addr - s->dev.io_regions[ICH9_SMB_SMB_BASE_BAR].addr;
- return smb_ioport_readb(&s->smb, offset);
- }
-
- return 0xff;
-}
-
-static const MemoryRegionOps lpc_smb_mmio_ops = {
- .read = ich9_smb_ioport_readb,
- .write = ich9_smb_ioport_writeb,
- .endianness = DEVICE_LITTLE_ENDIAN,
- .impl = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
-};
-
static int ich9_smbus_initfn(PCIDevice *d)
{
ICH9SMBState *s = ICH9_SMB_DEVICE(d);
* Is there any OS that depends on them?
*/
- /* TODO smb_io_base */
pci_set_byte(d->config + ICH9_SMB_HOSTC, 0);
/* TODO bar0, bar1: 64bit BAR support*/
- memory_region_init_io(&s->mem_bar, &lpc_smb_mmio_ops, s, "ich9-smbus-bar",
- ICH9_SMB_SMB_BASE_SIZE);
- pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
- &s->mem_bar);
pm_smbus_init(&d->qdev, &s->smb);
+ pci_register_bar(d, ICH9_SMB_SMB_BASE_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+ &s->smb.io);
return 0;
}
dc->vmsd = &vmstate_ich9_smbus;
dc->desc = "ICH9 SMBUS Bridge";
k->init = ich9_smbus_initfn;
+ k->config_write = ich9_smbus_write_config;
}
i2c_bus *ich9_smb_init(PCIBus *bus, int devfn, uint32_t smb_io_base)
pci_conf[0x90] = s->smb_io_base | 1;
pci_conf[0x91] = s->smb_io_base >> 8;
pci_conf[0xd2] = 0x90;
- register_ioport_write(s->smb_io_base, 0xf, 1, smb_ioport_writeb, &s->smb);
- register_ioport_read(s->smb_io_base, 0xf, 1, smb_ioport_readb, &s->smb);
+ pm_smbus_init(&s->dev.qdev, &s->smb);
+ memory_region_add_subregion(get_system_io(), s->smb_io_base, &s->smb.io);
apm_init(&s->apm, NULL, s);
acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io);
acpi_pm1_cnt_init(&s->ar, &s->io);
- pm_smbus_init(&s->dev.qdev, &s->smb);
-
return 0;
}