ide-test uses many explicit inb() / outb() operations for its IO, which means it's not portable to non-x86 platforms. This cleans it up to use the libqos PCI accessors instead.
Signed-off-by: David Gibson <da...@gibson.dropbear.id.au> Reviewed-by: Greg Kurz <gr...@kaod.org> --- tests/ide-test.c | 179 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 118 insertions(+), 61 deletions(-) diff --git a/tests/ide-test.c b/tests/ide-test.c index a8a4081..86c4373 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -137,7 +137,7 @@ static void ide_test_quit(void) qtest_end(); } -static QPCIDevice *get_pci_device(uint16_t *bmdma_base) +static QPCIDevice *get_pci_device(void **bmdma_base, void **ide_base) { QPCIDevice *dev; uint16_t vendor_id, device_id; @@ -156,7 +156,9 @@ static QPCIDevice *get_pci_device(uint16_t *bmdma_base) g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1); /* Map bmdma BAR */ - *bmdma_base = (uint16_t)(uintptr_t) qpci_iomap(dev, 4, NULL); + *bmdma_base = qpci_iomap(dev, 4, NULL); + + *ide_base = qpci_legacy_iomap(dev, IDE_BASE); qpci_device_enable(dev); @@ -179,17 +181,19 @@ typedef struct PrdtEntry { static int send_dma_request(int cmd, uint64_t sector, int nb_sectors, PrdtEntry *prdt, int prdt_entries, - void(*post_exec)(uint64_t sector, int nb_sectors)) + void(*post_exec)(QPCIDevice *dev, void *ide_base, + uint64_t sector, int nb_sectors)) { QPCIDevice *dev; - uint16_t bmdma_base; + void *bmdma_base; + void *ide_base; uintptr_t guest_prdt; size_t len; bool from_dev; uint8_t status; int flags; - dev = get_pci_device(&bmdma_base); + dev = get_pci_device(&bmdma_base, &ide_base); flags = cmd & ~0xff; cmd &= 0xff; @@ -214,59 +218,60 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors, } /* Select device 0 */ - outb(IDE_BASE + reg_device, 0 | LBA); + qpci_io_writeb(dev, ide_base + reg_device, 0 | LBA); /* Stop any running transfer, clear any pending interrupt */ - outb(bmdma_base + bmreg_cmd, 0); - outb(bmdma_base + bmreg_status, BM_STS_INTR); + qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0); + qpci_io_writeb(dev, bmdma_base + bmreg_status, BM_STS_INTR); /* Setup PRDT */ len = sizeof(*prdt) * prdt_entries; guest_prdt = guest_alloc(guest_malloc, len); memwrite(guest_prdt, prdt, len); - outl(bmdma_base + bmreg_prdt, guest_prdt); + qpci_io_writel(dev, bmdma_base + bmreg_prdt, guest_prdt); /* ATA DMA command */ if (cmd == CMD_PACKET) { /* Enables ATAPI DMA; otherwise PIO is attempted */ - outb(IDE_BASE + reg_feature, 0x01); + qpci_io_writeb(dev, ide_base + reg_feature, 0x01); } else { - outb(IDE_BASE + reg_nsectors, nb_sectors); - outb(IDE_BASE + reg_lba_low, sector & 0xff); - outb(IDE_BASE + reg_lba_middle, (sector >> 8) & 0xff); - outb(IDE_BASE + reg_lba_high, (sector >> 16) & 0xff); + qpci_io_writeb(dev, ide_base + reg_nsectors, nb_sectors); + qpci_io_writeb(dev, ide_base + reg_lba_low, sector & 0xff); + qpci_io_writeb(dev, ide_base + reg_lba_middle, (sector >> 8) & 0xff); + qpci_io_writeb(dev, ide_base + reg_lba_high, (sector >> 16) & 0xff); } - outb(IDE_BASE + reg_command, cmd); + qpci_io_writeb(dev, ide_base + reg_command, cmd); if (post_exec) { - post_exec(sector, nb_sectors); + post_exec(dev, ide_base, sector, nb_sectors); } /* Start DMA transfer */ - outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0)); + qpci_io_writeb(dev, bmdma_base + bmreg_cmd, + BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0)); if (flags & CMDF_ABORT) { - outb(bmdma_base + bmreg_cmd, 0); + qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0); } /* Wait for the DMA transfer to complete */ do { - status = inb(bmdma_base + bmreg_status); + status = qpci_io_readb(dev, bmdma_base + bmreg_status); } while ((status & (BM_STS_ACTIVE | BM_STS_INTR)) == BM_STS_ACTIVE); g_assert_cmpint(get_irq(IDE_PRIMARY_IRQ), ==, !!(status & BM_STS_INTR)); /* Check IDE status code */ - assert_bit_set(inb(IDE_BASE + reg_status), DRDY); - assert_bit_clear(inb(IDE_BASE + reg_status), BSY | DRQ); + assert_bit_set(qpci_io_readb(dev, ide_base + reg_status), DRDY); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), BSY | DRQ); /* Reading the status register clears the IRQ */ g_assert(!get_irq(IDE_PRIMARY_IRQ)); /* Stop DMA transfer if still active */ if (status & BM_STS_ACTIVE) { - outb(bmdma_base + bmreg_cmd, 0); + qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0); } free_pci_device(dev); @@ -276,6 +281,8 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors, static void test_bmdma_simple_rw(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; uint8_t *buf; uint8_t *cmpbuf; @@ -289,6 +296,8 @@ static void test_bmdma_simple_rw(void) }, }; + dev = get_pci_device(&bmdma_base, &ide_base); + buf = g_malloc(len); cmpbuf = g_malloc(len); @@ -299,7 +308,7 @@ static void test_bmdma_simple_rw(void) status = send_dma_request(CMD_WRITE_DMA, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); /* Write 0xaa pattern to sector 1 */ memset(buf, 0xaa, len); @@ -308,14 +317,14 @@ static void test_bmdma_simple_rw(void) status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); /* Read and verify 0x55 pattern in sector 0 */ memset(cmpbuf, 0x55, len); status = send_dma_request(CMD_READ_DMA, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); memread(guest_buf, buf, len); g_assert(memcmp(buf, cmpbuf, len) == 0); @@ -325,7 +334,7 @@ static void test_bmdma_simple_rw(void) status = send_dma_request(CMD_READ_DMA, 1, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); memread(guest_buf, buf, len); g_assert(memcmp(buf, cmpbuf, len) == 0); @@ -337,6 +346,8 @@ static void test_bmdma_simple_rw(void) static void test_bmdma_short_prdt(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; PrdtEntry prdt[] = { @@ -346,21 +357,25 @@ static void test_bmdma_short_prdt(void) }, }; + dev = get_pci_device(&bmdma_base, &ide_base); + /* Normal request */ status = send_dma_request(CMD_READ_DMA, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, 0); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); /* Abort the request before it completes */ status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, 0); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); } static void test_bmdma_one_sector_short_prdt(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; /* Read 2 sectors but only give 1 sector in PRDT */ @@ -371,21 +386,25 @@ static void test_bmdma_one_sector_short_prdt(void) }, }; + dev = get_pci_device(&bmdma_base, &ide_base); + /* Normal request */ status = send_dma_request(CMD_READ_DMA, 0, 2, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, 0); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); /* Abort the request before it completes */ status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 2, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, 0); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); } static void test_bmdma_long_prdt(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; PrdtEntry prdt[] = { @@ -395,23 +414,29 @@ static void test_bmdma_long_prdt(void) }, }; + dev = get_pci_device(&bmdma_base, &ide_base); + /* Normal request */ status = send_dma_request(CMD_READ_DMA, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); /* Abort the request before it completes */ status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); } static void test_bmdma_no_busmaster(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; + dev = get_pci_device(&bmdma_base, &ide_base); + /* No PRDT_EOT, each entry addr 0/size 64k, and in theory qemu shouldn't be * able to access it anyway because the Bus Master bit in the PCI command * register isn't set. This is complete nonsense, but it used to be pretty @@ -424,7 +449,7 @@ static void test_bmdma_no_busmaster(void) /* Not entirely clear what the expected result is, but this is what we get * in practice. At least we want to be aware of any changes. */ g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); } static void test_bmdma_setup(void) @@ -454,6 +479,8 @@ static void string_cpu_to_be16(uint16_t *s, size_t bytes) static void test_identify(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t data; uint16_t buf[256]; int i; @@ -464,23 +491,25 @@ static void test_identify(void) "-global ide-hd.ver=%s", tmp_path, "testdisk", "version"); + dev = get_pci_device(&bmdma_base, &ide_base); + /* IDENTIFY command on device 0*/ - outb(IDE_BASE + reg_device, 0); - outb(IDE_BASE + reg_command, CMD_IDENTIFY); + qpci_io_writeb(dev, ide_base + reg_device, 0); + qpci_io_writeb(dev, ide_base + reg_command, CMD_IDENTIFY); /* Read in the IDENTIFY buffer and check registers */ - data = inb(IDE_BASE + reg_device); + data = qpci_io_readb(dev, ide_base + reg_device); g_assert_cmpint(data & DEV, ==, 0); for (i = 0; i < 256; i++) { - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); assert_bit_set(data, DRDY | DRQ); assert_bit_clear(data, BSY | DF | ERR); - ((uint16_t*) buf)[i] = inw(IDE_BASE + reg_data); + buf[i] = qpci_io_readw(dev, ide_base + reg_data); } - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); assert_bit_set(data, DRDY); assert_bit_clear(data, BSY | DF | ERR | DRQ); @@ -505,11 +534,15 @@ static void test_identify(void) */ static void make_dirty(uint8_t device) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t status; size_t len = 512; uintptr_t guest_buf; void* buf; + dev = get_pci_device(&bmdma_base, &ide_base); + guest_buf = guest_alloc(guest_malloc, len); buf = g_malloc(len); g_assert(guest_buf); @@ -527,19 +560,23 @@ static void make_dirty(uint8_t device) status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt, ARRAY_SIZE(prdt), NULL); g_assert_cmphex(status, ==, BM_STS_INTR); - assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR); + assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR); g_free(buf); } static void test_flush(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t data; ide_test_start( "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", tmp_path); + dev = get_pci_device(&bmdma_base, &ide_base); + qtest_irq_intercept_in(global_qtest, "ioapic"); /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ @@ -549,11 +586,11 @@ static void test_flush(void) g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\"")); /* FLUSH CACHE command on device 0*/ - outb(IDE_BASE + reg_device, 0); - outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); + qpci_io_writeb(dev, ide_base + reg_device, 0); + qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE); /* Check status while request is in flight*/ - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); assert_bit_set(data, BSY | DRDY); assert_bit_clear(data, DF | ERR | DRQ); @@ -561,11 +598,11 @@ static void test_flush(void) g_free(hmp("qemu-io ide0-hd0 \"resume A\"")); /* Check registers */ - data = inb(IDE_BASE + reg_device); + data = qpci_io_readb(dev, ide_base + reg_device); g_assert_cmpint(data & DEV, ==, 0); do { - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); } while (data & BSY); assert_bit_set(data, DRDY); @@ -576,6 +613,8 @@ static void test_flush(void) static void test_retry_flush(const char *machine) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t data; const char *s; @@ -587,17 +626,19 @@ static void test_retry_flush(const char *machine) "rerror=stop,werror=stop", debug_path, tmp_path); + dev = get_pci_device(&bmdma_base, &ide_base); + qtest_irq_intercept_in(global_qtest, "ioapic"); /* Dirty media so that CMD_FLUSH_CACHE will actually go to disk */ make_dirty(0); /* FLUSH CACHE command on device 0*/ - outb(IDE_BASE + reg_device, 0); - outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); + qpci_io_writeb(dev, ide_base + reg_device, 0); + qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE); /* Check status while request is in flight*/ - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); assert_bit_set(data, BSY | DRDY); assert_bit_clear(data, DF | ERR | DRQ); @@ -608,11 +649,11 @@ static void test_retry_flush(const char *machine) qmp_discard_response(s); /* Check registers */ - data = inb(IDE_BASE + reg_device); + data = qpci_io_readb(dev, ide_base + reg_device); g_assert_cmpint(data & DEV, ==, 0); do { - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); } while (data & BSY); assert_bit_set(data, DRDY); @@ -623,11 +664,16 @@ static void test_retry_flush(const char *machine) static void test_flush_nodev(void) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; + ide_test_start(""); + dev = get_pci_device(&bmdma_base, &ide_base); + /* FLUSH CACHE command on device 0*/ - outb(IDE_BASE + reg_device, 0); - outb(IDE_BASE + reg_command, CMD_FLUSH_CACHE); + qpci_io_writeb(dev, ide_base + reg_device, 0); + qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE); /* Just testing that qemu doesn't crash... */ @@ -654,7 +700,8 @@ typedef struct Read10CDB { uint16_t padding; } __attribute__((__packed__)) Read10CDB; -static void send_scsi_cdb_read10(uint64_t lba, int nblocks) +static void send_scsi_cdb_read10(QPCIDevice *dev, void *ide_base, + uint64_t lba, int nblocks) { Read10CDB pkt = { .padding = 0 }; int i; @@ -670,7 +717,8 @@ static void send_scsi_cdb_read10(uint64_t lba, int nblocks) /* Send Packet */ for (i = 0; i < sizeof(Read10CDB)/2; i++) { - outw(IDE_BASE + reg_data, cpu_to_le16(((uint16_t *)&pkt)[i])); + qpci_io_writew(dev, ide_base + reg_data, + le16_to_cpu(((uint16_t *)&pkt)[i])); } } @@ -683,13 +731,17 @@ static void nsleep(int64_t nsecs) static uint8_t ide_wait_clear(uint8_t flag) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; uint8_t data; time_t st; + dev = get_pci_device(&bmdma_base, &ide_base); + /* Wait with a 5 second timeout */ time(&st); while (true) { - data = inb(IDE_BASE + reg_status); + data = qpci_io_readb(dev, ide_base + reg_status); if (!(data & flag)) { return data; } @@ -723,6 +775,8 @@ static void ide_wait_intr(int irq) static void cdrom_pio_impl(int nblocks) { + QPCIDevice *dev; + void *bmdma_base, *ide_base; FILE *fh; int patt_blocks = MAX(16, nblocks); size_t patt_len = ATAPI_BLOCK_SIZE * patt_blocks; @@ -741,13 +795,15 @@ static void cdrom_pio_impl(int nblocks) ide_test_start("-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " "-device ide-cd,drive=sr0,bus=ide.0", tmp_path); + dev = get_pci_device(&bmdma_base, &ide_base); qtest_irq_intercept_in(global_qtest, "ioapic"); /* PACKET command on device 0 */ - outb(IDE_BASE + reg_device, 0); - outb(IDE_BASE + reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF); - outb(IDE_BASE + reg_lba_high, (BYTE_COUNT_LIMIT >> 8 & 0xFF)); - outb(IDE_BASE + reg_command, CMD_PACKET); + qpci_io_writeb(dev, ide_base + reg_device, 0); + qpci_io_writeb(dev, ide_base + reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF); + qpci_io_writeb(dev, ide_base + reg_lba_high, + (BYTE_COUNT_LIMIT >> 8 & 0xFF)); + qpci_io_writeb(dev, ide_base + reg_command, CMD_PACKET); /* HP0: Check_Status_A State */ nsleep(400); data = ide_wait_clear(BSY); @@ -756,7 +812,7 @@ static void cdrom_pio_impl(int nblocks) assert_bit_clear(data, ERR | DF | BSY); /* SCSI CDB (READ10) -- read n*2048 bytes from block 0 */ - send_scsi_cdb_read10(0, nblocks); + send_scsi_cdb_read10(dev, ide_base, 0, nblocks); /* Read data back: occurs in bursts of 'BYTE_COUNT_LIMIT' bytes. * If BYTE_COUNT_LIMIT is odd, we transfer BYTE_COUNT_LIMIT - 1 bytes. @@ -780,7 +836,8 @@ static void cdrom_pio_impl(int nblocks) /* HP4: Transfer_Data */ for (j = 0; j < MIN((limit / 2), rem); j++) { - rx[offset + j] = le16_to_cpu(inw(IDE_BASE + reg_data)); + rx[offset + j] = cpu_to_le16(qpci_io_readw(dev, + ide_base + reg_data)); } } -- 2.7.4