diff options
Diffstat (limited to 'hw/ide/piix.c')
-rw-r--r-- | hw/ide/piix.c | 107 |
1 files changed, 92 insertions, 15 deletions
diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 84f72b0a66..8525336075 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -33,11 +33,15 @@ #include <hw/ide/pci.h> -static uint32_t bmdma_readb(void *opaque, uint32_t addr) +static uint64_t bmdma_read(void *opaque, target_phys_addr_t addr, unsigned size) { BMDMAState *bm = opaque; uint32_t val; + if (size != 1) { + return ((uint64_t)1 << (size * 8)) - 1; + } + switch(addr & 3) { case 0: val = bm->cmd; @@ -55,36 +59,46 @@ static uint32_t bmdma_readb(void *opaque, uint32_t addr) return val; } -static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) +static void bmdma_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) { BMDMAState *bm = opaque; + + if (size != 1) { + return; + } + #ifdef DEBUG_IDE printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val); #endif switch(addr & 3) { + case 0: + return bmdma_cmd_writeb(bm, val); case 2: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); break; } } -static void bmdma_map(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type) +static MemoryRegionOps piix_bmdma_ops = { + .read = bmdma_read, + .write = bmdma_write, +}; + +static void bmdma_setup_bar(PCIIDEState *d) { - PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev); int i; + memory_region_init(&d->bmdma_bar, "piix-bmdma-container", 16); for(i = 0;i < 2; i++) { BMDMAState *bm = &d->bmdma[i]; - register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); - - register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); - register_ioport_read(addr, 4, 1, bmdma_readb, bm); - - iorange_init(&bm->addr_ioport, &bmdma_addr_ioport_ops, addr + 4, 4); - ioport_register(&bm->addr_ioport); - addr += 8; + memory_region_init_io(&bm->extra_io, &piix_bmdma_ops, bm, + "piix-bmdma", 4); + memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); + memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm, + "bmdma", 4); + memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); } } @@ -124,7 +138,7 @@ static void pci_piix_init_ports(PCIIDEState *d) { ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq)); - bmdma_init(&d->bus[i], &d->bmdma[i]); + bmdma_init(&d->bus[i], &d->bmdma[i], d); d->bmdma[i].bus = &d->bus[i]; qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb, &d->bmdma[i].dma); @@ -140,7 +154,8 @@ static int pci_piix_ide_initfn(PCIDevice *dev) qemu_register_reset(piix3_reset, d); - pci_register_bar(&d->dev, 4, 0x10, PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); + bmdma_setup_bar(d); + pci_register_bar(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d); @@ -149,6 +164,58 @@ static int pci_piix_ide_initfn(PCIDevice *dev) return 0; } +static int pci_piix3_xen_ide_unplug(DeviceState *dev) +{ + PCIDevice *pci_dev; + PCIIDEState *pci_ide; + DriveInfo *di; + int i = 0; + + pci_dev = DO_UPCAST(PCIDevice, qdev, dev); + pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev); + + for (; i < 3; i++) { + di = drive_get_by_index(IF_IDE, i); + if (di != NULL && di->bdrv != NULL && !di->bdrv->removable) { + DeviceState *ds = bdrv_get_attached(di->bdrv); + if (ds) { + bdrv_detach(di->bdrv, ds); + } + bdrv_close(di->bdrv); + pci_ide->bus[di->bus].ifs[di->unit].bs = NULL; + drive_put_ref(di); + } + } + qdev_reset_all(&(pci_ide->dev.qdev)); + return 0; +} + +PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) +{ + PCIDevice *dev; + + dev = pci_create_simple(bus, devfn, "piix3-ide-xen"); + dev->qdev.info->unplug = pci_piix3_xen_ide_unplug; + pci_ide_create_devs(dev, hd_table); + return dev; +} + +static int pci_piix_ide_exitfn(PCIDevice *dev) +{ + PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); + unsigned i; + + for (i = 0; i < 2; ++i) { + memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io); + memory_region_destroy(&d->bmdma[i].extra_io); + memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport); + memory_region_destroy(&d->bmdma[i].addr_ioport); + } + memory_region_destroy(&d->bmdma_bar); + + return 0; +} + /* hd_table must contain 4 block drivers */ /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) @@ -178,6 +245,15 @@ static PCIDeviceInfo piix_ide_info[] = { .qdev.no_user = 1, .no_hotplug = 1, .init = pci_piix_ide_initfn, + .exit = pci_piix_ide_exitfn, + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = PCI_DEVICE_ID_INTEL_82371SB_1, + .class_id = PCI_CLASS_STORAGE_IDE, + },{ + .qdev.name = "piix3-ide-xen", + .qdev.size = sizeof(PCIIDEState), + .qdev.no_user = 1, + .init = pci_piix_ide_initfn, .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82371SB_1, .class_id = PCI_CLASS_STORAGE_IDE, @@ -187,6 +263,7 @@ static PCIDeviceInfo piix_ide_info[] = { .qdev.no_user = 1, .no_hotplug = 1, .init = pci_piix_ide_initfn, + .exit = pci_piix_ide_exitfn, .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82371AB, .class_id = PCI_CLASS_STORAGE_IDE, |