diff options
-rw-r--r-- | hw/ide/cmd646.c | 102 | ||||
-rw-r--r-- | hw/ide/pci.c | 65 | ||||
-rw-r--r-- | hw/ide/sii3112.c | 52 | ||||
-rw-r--r-- | hw/ide/via.c | 87 | ||||
-rw-r--r-- | hw/mips/mips_fulong2e.c | 2 | ||||
-rw-r--r-- | include/hw/ide.h | 2 | ||||
-rw-r--r-- | include/hw/ide/pci.h | 14 |
7 files changed, 148 insertions, 176 deletions
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 6bb92d717f..5a5679134a 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -50,86 +50,6 @@ static void cmd646_update_irq(PCIDevice *pd); -static uint64_t cmd646_cmd_read(void *opaque, hwaddr addr, - unsigned size) -{ - CMD646BAR *cmd646bar = opaque; - - if (addr != 2 || size != 1) { - return ((uint64_t)1 << (size * 8)) - 1; - } - return ide_status_read(cmd646bar->bus, addr + 2); -} - -static void cmd646_cmd_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - CMD646BAR *cmd646bar = opaque; - - if (addr != 2 || size != 1) { - return; - } - ide_cmd_write(cmd646bar->bus, addr + 2, data); -} - -static const MemoryRegionOps cmd646_cmd_ops = { - .read = cmd646_cmd_read, - .write = cmd646_cmd_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static uint64_t cmd646_data_read(void *opaque, hwaddr addr, - unsigned size) -{ - CMD646BAR *cmd646bar = opaque; - - if (size == 1) { - return ide_ioport_read(cmd646bar->bus, addr); - } else if (addr == 0) { - if (size == 2) { - return ide_data_readw(cmd646bar->bus, addr); - } else { - return ide_data_readl(cmd646bar->bus, addr); - } - } - return ((uint64_t)1 << (size * 8)) - 1; -} - -static void cmd646_data_write(void *opaque, hwaddr addr, - uint64_t data, unsigned size) -{ - CMD646BAR *cmd646bar = opaque; - - if (size == 1) { - ide_ioport_write(cmd646bar->bus, addr, data); - } else if (addr == 0) { - if (size == 2) { - ide_data_writew(cmd646bar->bus, addr, data); - } else { - ide_data_writel(cmd646bar->bus, addr, data); - } - } -} - -static const MemoryRegionOps cmd646_data_ops = { - .read = cmd646_data_read, - .write = cmd646_data_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -static void setup_cmd646_bar(PCIIDEState *d, int bus_num) -{ - IDEBus *bus = &d->bus[bus_num]; - CMD646BAR *bar = &d->cmd646_bar[bus_num]; - - bar->bus = bus; - bar->pci_dev = d; - memory_region_init_io(&bar->cmd, OBJECT(d), &cmd646_cmd_ops, bar, - "cmd646-cmd", 4); - memory_region_init_io(&bar->data, OBJECT(d), &cmd646_data_ops, bar, - "cmd646-data", 8); -} - static void cmd646_update_dma_interrupts(PCIDevice *pd) { /* Sync DMA interrupt status from UDMA interrupt status */ @@ -346,12 +266,22 @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) dev->wmask[MRDMODE] = 0x0; dev->w1cmask[MRDMODE] = MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1; - setup_cmd646_bar(d, 0); - setup_cmd646_bar(d, 1); - pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[0].data); - pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[0].cmd); - pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[1].data); - pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd646_bar[1].cmd); + memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops, + &d->bus[0], "cmd646-data0", 8); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]); + + memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops, + &d->bus[0], "cmd646-cmd0", 4); + pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]); + + memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops, + &d->bus[1], "cmd646-data1", 8); + pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]); + + memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops, + &d->bus[1], "cmd646-cmd1", 4); + pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]); + bmdma_setup_bar(d); pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); diff --git a/hw/ide/pci.c b/hw/ide/pci.c index b75154f99f..942613a9a9 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -36,6 +36,71 @@ (IDE_RETRY_DMA | IDE_RETRY_PIO | \ IDE_RETRY_READ | IDE_RETRY_FLUSH) +static uint64_t pci_ide_cmd_read(void *opaque, hwaddr addr, unsigned size) +{ + IDEBus *bus = opaque; + + if (addr != 2 || size != 1) { + return ((uint64_t)1 << (size * 8)) - 1; + } + return ide_status_read(bus, addr + 2); +} + +static void pci_ide_cmd_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + IDEBus *bus = opaque; + + if (addr != 2 || size != 1) { + return; + } + ide_cmd_write(bus, addr + 2, data); +} + +const MemoryRegionOps pci_ide_cmd_le_ops = { + .read = pci_ide_cmd_read, + .write = pci_ide_cmd_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static uint64_t pci_ide_data_read(void *opaque, hwaddr addr, unsigned size) +{ + IDEBus *bus = opaque; + + if (size == 1) { + return ide_ioport_read(bus, addr); + } else if (addr == 0) { + if (size == 2) { + return ide_data_readw(bus, addr); + } else { + return ide_data_readl(bus, addr); + } + } + return ((uint64_t)1 << (size * 8)) - 1; +} + +static void pci_ide_data_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + IDEBus *bus = opaque; + + if (size == 1) { + ide_ioport_write(bus, addr, data); + } else if (addr == 0) { + if (size == 2) { + ide_data_writew(bus, addr, data); + } else { + ide_data_writel(bus, addr, data); + } + } +} + +const MemoryRegionOps pci_ide_data_le_ops = { + .read = pci_ide_data_read, + .write = pci_ide_data_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + static void bmdma_start_dma(IDEDMA *dma, IDEState *s, BlockCompletionFunc *dma_cb) { diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c index 743a50ed51..59db09cfe4 100644 --- a/hw/ide/sii3112.c +++ b/hw/ide/sii3112.c @@ -88,35 +88,19 @@ static uint64_t sii3112_reg_read(void *opaque, hwaddr addr, val |= (uint32_t)d->i.bmdma[1].status << 16; break; case 0x80 ... 0x87: - if (size == 1) { - val = ide_ioport_read(&d->i.bus[0], addr - 0x80); - } else if (addr == 0x80) { - val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) : - ide_data_readl(&d->i.bus[0], 0); - } else { - val = (1ULL << (size * 8)) - 1; - } + val = pci_ide_data_le_ops.read(&d->i.bus[0], addr - 0x80, size); break; case 0x8a: - val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) : - (1ULL << (size * 8)) - 1; + val = pci_ide_cmd_le_ops.read(&d->i.bus[0], 2, size); break; case 0xa0: val = d->regs[0].confstat; break; case 0xc0 ... 0xc7: - if (size == 1) { - val = ide_ioport_read(&d->i.bus[1], addr - 0xc0); - } else if (addr == 0xc0) { - val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) : - ide_data_readl(&d->i.bus[1], 0); - } else { - val = (1ULL << (size * 8)) - 1; - } + val = pci_ide_data_le_ops.read(&d->i.bus[1], addr - 0xc0, size); break; case 0xca: - val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) : - (1ULL << (size * 8)) - 1; + val = pci_ide_cmd_le_ops.read(&d->i.bus[1], 2, size); break; case 0xe0: val = d->regs[1].confstat; @@ -186,36 +170,16 @@ static void sii3112_reg_write(void *opaque, hwaddr addr, bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size); break; case 0x80 ... 0x87: - if (size == 1) { - ide_ioport_write(&d->i.bus[0], addr - 0x80, val); - } else if (addr == 0x80) { - if (size == 2) { - ide_data_writew(&d->i.bus[0], 0, val); - } else { - ide_data_writel(&d->i.bus[0], 0, val); - } - } + pci_ide_data_le_ops.write(&d->i.bus[0], addr - 0x80, val, size); break; case 0x8a: - if (size == 1) { - ide_cmd_write(&d->i.bus[0], 4, val); - } + pci_ide_cmd_le_ops.write(&d->i.bus[0], 2, val, size); break; case 0xc0 ... 0xc7: - if (size == 1) { - ide_ioport_write(&d->i.bus[1], addr - 0xc0, val); - } else if (addr == 0xc0) { - if (size == 2) { - ide_data_writew(&d->i.bus[1], 0, val); - } else { - ide_data_writel(&d->i.bus[1], 0, val); - } - } + pci_ide_data_le_ops.write(&d->i.bus[1], addr - 0xc0, val, size); break; case 0xca: - if (size == 1) { - ide_cmd_write(&d->i.bus[1], 4, val); - } + pci_ide_cmd_le_ops.write(&d->i.bus[1], 2, val, size); break; case 0x100: d->regs[0].scontrol = val & 0xfff; diff --git a/hw/ide/via.c b/hw/ide/via.c index 987d99c5ec..ac9385228c 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -101,7 +101,24 @@ static void bmdma_setup_bar(PCIIDEState *d) } } -static void via_reset(void *opaque) +static void via_ide_set_irq(void *opaque, int n, int level) +{ + PCIDevice *d = PCI_DEVICE(opaque); + + if (level) { + d->config[0x70 + n * 8] |= 0x80; + } else { + d->config[0x70 + n * 8] &= ~0x80; + } + + level = (d->config[0x70] & 0x80) || (d->config[0x78] & 0x80); + n = pci_get_byte(d->config + PCI_INTERRUPT_LINE); + if (n) { + qemu_set_irq(isa_get_irq(NULL, n), level); + } +} + +static void via_ide_reset(void *opaque) { PCIIDEState *d = opaque; PCIDevice *pd = PCI_DEVICE(d); @@ -112,7 +129,7 @@ static void via_reset(void *opaque) ide_bus_reset(&d->bus[i]); } - pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_WAIT); + pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT); pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); @@ -143,48 +160,50 @@ static void via_reset(void *opaque) pci_set_long(pci_conf + 0xc0, 0x00020001); } -static void vt82c686b_init_ports(PCIIDEState *d) { - static const struct { - int iobase; - int iobase2; - int isairq; - } port_info[] = { - {0x1f0, 0x3f6, 14}, - {0x170, 0x376, 15}, - }; - int i; - - for (i = 0; i < 2; i++) { - ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2); - 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], d); - d->bmdma[i].bus = &d->bus[i]; - ide_register_restart_cb(&d->bus[i]); - } -} - -/* via ide func */ -static void vt82c686b_ide_realize(PCIDevice *dev, Error **errp) +static void via_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); uint8_t *pci_conf = dev->config; + int i; - pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy ATA mode */ + pci_config_set_prog_interface(pci_conf, 0x8f); /* native PCI ATA mode */ pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); + dev->wmask[PCI_INTERRUPT_LINE] = 0xf; + + qemu_register_reset(via_ide_reset, d); + + memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops, + &d->bus[0], "via-ide0-data", 8); + pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]); + + memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops, + &d->bus[0], "via-ide0-cmd", 4); + pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]); + + memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops, + &d->bus[1], "via-ide1-data", 8); + pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]); + + memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops, + &d->bus[1], "via-ide1-cmd", 4); + pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]); - qemu_register_reset(via_reset, d); bmdma_setup_bar(d); pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d); - vt82c686b_init_ports(d); + for (i = 0; i < 2; i++) { + ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2); + ide_init2(&d->bus[i], qemu_allocate_irq(via_ide_set_irq, d, i)); + + bmdma_init(&d->bus[i], &d->bmdma[i], d); + d->bmdma[i].bus = &d->bus[i]; + ide_register_restart_cb(&d->bus[i]); + } } -static void vt82c686b_ide_exitfn(PCIDevice *dev) +static void via_ide_exitfn(PCIDevice *dev) { PCIIDEState *d = PCI_IDE(dev); unsigned i; @@ -195,7 +214,7 @@ static void vt82c686b_ide_exitfn(PCIDevice *dev) } } -void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) +void via_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) { PCIDevice *dev; @@ -208,8 +227,8 @@ static void via_ide_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - k->realize = vt82c686b_ide_realize; - k->exit = vt82c686b_ide_exitfn; + k->realize = via_ide_realize; + k->exit = via_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_VIA; k->device_id = PCI_DEVICE_ID_VIA_IDE; k->revision = 0x06; diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 2fbba32c48..42d09f6892 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -249,7 +249,7 @@ static void vt82c686b_southbridge_init(PCIBus *pci_bus, int slot, qemu_irq intc, isa_create_simple(isa_bus, TYPE_VT82C686B_SUPERIO); ide_drive_get(hd, ARRAY_SIZE(hd)); - vt82c686b_ide_init(pci_bus, hd, PCI_DEVFN(slot, 1)); + via_ide_init(pci_bus, hd, PCI_DEVFN(slot, 1)); pci_create_simple(pci_bus, PCI_DEVFN(slot, 2), "vt82c686b-usb-uhci"); pci_create_simple(pci_bus, PCI_DEVFN(slot, 3), "vt82c686b-usb-uhci"); diff --git a/include/hw/ide.h b/include/hw/ide.h index 3ae087c572..28d8a06439 100644 --- a/include/hw/ide.h +++ b/include/hw/ide.h @@ -18,7 +18,7 @@ PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); int pci_piix3_xen_ide_unplug(DeviceState *dev, bool aux); -void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); +void via_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn); /* ide-mmio.c */ void mmio_ide_init_drives(DeviceState *dev, DriveInfo *hd0, DriveInfo *hd1); diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h index dbc6a0383d..a9f2c33e68 100644 --- a/include/hw/ide/pci.h +++ b/include/hw/ide/pci.h @@ -37,13 +37,6 @@ typedef struct BMDMAState { struct PCIIDEState *pci_dev; } BMDMAState; -typedef struct CMD646BAR { - MemoryRegion cmd; - MemoryRegion data; - IDEBus *bus; - struct PCIIDEState *pci_dev; -} CMD646BAR; - #define TYPE_PCI_IDE "pci-ide" #define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) @@ -56,21 +49,22 @@ typedef struct PCIIDEState { BMDMAState bmdma[2]; uint32_t secondary; /* used only for cmd646 */ MemoryRegion bmdma_bar; - CMD646BAR cmd646_bar[2]; /* used only for cmd646 */ + MemoryRegion cmd_bar[2]; + MemoryRegion data_bar[2]; } PCIIDEState; - static inline IDEState *bmdma_active_if(BMDMAState *bmdma) { assert(bmdma->bus->retry_unit != (uint8_t)-1); return bmdma->bus->ifs + bmdma->bus->retry_unit; } - void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d); void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); extern MemoryRegionOps bmdma_addr_ioport_ops; void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); extern const VMStateDescription vmstate_ide_pci; +extern const MemoryRegionOps pci_ide_cmd_le_ops; +extern const MemoryRegionOps pci_ide_data_le_ops; #endif |