--- qemu/hw/ide/piix.c 2018/04/24 18:40:23 1.1.1.4 +++ qemu/hw/ide/piix.c 2018/04/24 19:51:01 1.1.1.8 @@ -27,17 +27,20 @@ #include #include #include "block.h" -#include "block_int.h" #include "sysemu.h" #include "dma.h" #include -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; @@ -50,41 +53,51 @@ static uint32_t bmdma_readb(void *opaque break; } #ifdef DEBUG_IDE - printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val); + printf("bmdma: readb 0x%02x : 0x%02x\n", (uint8_t)addr, val); #endif 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); + printf("bmdma: writeb 0x%02x : 0x%02x\n", (uint8_t)addr, (uint8_t)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 const 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); } } @@ -109,8 +122,7 @@ static void piix3_reset(void *opaque) } static void pci_piix_init_ports(PCIIDEState *d) { - int i; - struct { + static const struct { int iobase; int iobase2; int isairq; @@ -118,29 +130,32 @@ static void pci_piix_init_ports(PCIIDESt {0x1f0, 0x3f6, 14}, {0x170, 0x376, 15}, }; + int i; for (i = 0; i < 2; i++) { ide_bus_new(&d->bus[i], &d->dev.qdev, i); - ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); - ide_init2(&d->bus[i], isa_reserve_irq(port_info[i].isairq)); + ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase, + port_info[i].iobase2); + ide_init2(&d->bus[i], isa_get_irq(NULL, 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); } } -static int pci_piix_ide_initfn(PCIIDEState *d) +static int pci_piix_ide_initfn(PCIDevice *dev) { + PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); uint8_t *pci_conf = d->dev.config; pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode - pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); 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,22 +164,55 @@ static int pci_piix_ide_initfn(PCIIDESta return 0; } -static int pci_piix3_ide_initfn(PCIDevice *dev) +static int pci_piix3_xen_ide_unplug(DeviceState *dev) { - PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, 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->media_cd) { + DeviceState *ds = bdrv_get_attached_dev(di->bdrv); + if (ds) { + bdrv_detach_dev(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; +} - pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL); - pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371SB_1); - return pci_piix_ide_initfn(d); +PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) +{ + PCIDevice *dev; + + dev = pci_create_simple(bus, devfn, "piix3-ide-xen"); + pci_ide_create_devs(dev, hd_table); + return dev; } -static int pci_piix4_ide_initfn(PCIDevice *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); - pci_config_set_vendor_id(d->dev.config, PCI_VENDOR_ID_INTEL); - pci_config_set_device_id(d->dev.config, PCI_DEVICE_ID_INTEL_82371AB); - return pci_piix_ide_initfn(d); + return 0; } /* hd_table must contain 4 block drivers */ @@ -189,26 +237,73 @@ PCIDevice *pci_piix4_ide_init(PCIBus *bu return dev; } -static PCIDeviceInfo piix_ide_info[] = { - { - .qdev.name = "piix3-ide", - .qdev.size = sizeof(PCIIDEState), - .qdev.no_user = 1, - .no_hotplug = 1, - .init = pci_piix3_ide_initfn, - },{ - .qdev.name = "piix4-ide", - .qdev.size = sizeof(PCIIDEState), - .qdev.no_user = 1, - .no_hotplug = 1, - .init = pci_piix4_ide_initfn, - },{ - /* end of list */ - } +static void piix3_ide_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->no_hotplug = 1; + k->init = pci_piix_ide_initfn; + k->exit = pci_piix_ide_exitfn; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + dc->no_user = 1; +} + +static TypeInfo piix3_ide_info = { + .name = "piix3-ide", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIIDEState), + .class_init = piix3_ide_class_init, }; -static void piix_ide_register(void) +static void piix3_ide_xen_class_init(ObjectClass *klass, void *data) { - pci_qdev_register_many(piix_ide_info); + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = pci_piix_ide_initfn; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1; + k->class_id = PCI_CLASS_STORAGE_IDE; + dc->no_user = 1; + dc->unplug = pci_piix3_xen_ide_unplug; +} + +static TypeInfo piix3_ide_xen_info = { + .name = "piix3-ide-xen", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIIDEState), + .class_init = piix3_ide_xen_class_init, +}; + +static void piix4_ide_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->no_hotplug = 1; + k->init = pci_piix_ide_initfn; + k->exit = pci_piix_ide_exitfn; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = PCI_DEVICE_ID_INTEL_82371AB; + k->class_id = PCI_CLASS_STORAGE_IDE; + dc->no_user = 1; +} + +static TypeInfo piix4_ide_info = { + .name = "piix4-ide", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIIDEState), + .class_init = piix4_ide_class_init, +}; + +static void piix_ide_register_types(void) +{ + type_register_static(&piix3_ide_info); + type_register_static(&piix3_ide_xen_info); + type_register_static(&piix4_ide_info); } -device_init(piix_ide_register); + +type_init(piix_ide_register_types)