libqos: Change PCI accessors to take opaque BAR handle
The usual use model for the libqos PCI functions is to map a specific PCI BAR using qpci_iomap() then pass the returned token into IO accessor functions. This, and the fact that iomap() returns a (void *) which actually contains a PCI space address, kind of suggests that the return value from iomap is supposed to be an opaque token. ..except that the callers expect to be able to add offsets to it. Which also assumes the compiler will support pointer arithmetic on a (void *), and treat it as working with byte offsets. To clarify this situation change iomap() and the IO accessors to take a definitely opaque BAR handle (enforced with a wrapper struct) along with an offset within the BAR. This changes both the functions and all the callers. There were a number of places that checked if iomap() returned non-NULL, and or initialized it to NULL before hand. Since iomap() already assert()s if it fails to map the BAR, these tests were mostly pointless and are removed. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Greg Kurz <groug@kaod.org>
This commit is contained in:
parent
e7c8526b2a
commit
b4ba67d9a7
@ -87,7 +87,7 @@
|
||||
|
||||
typedef struct e1000e_device {
|
||||
QPCIDevice *pci_dev;
|
||||
void *mac_regs;
|
||||
QPCIBar mac_regs;
|
||||
|
||||
uint64_t tx_ring;
|
||||
uint64_t rx_ring;
|
||||
@ -119,12 +119,12 @@ static QPCIDevice *e1000e_device_find(QPCIBus *bus)
|
||||
|
||||
static void e1000e_macreg_write(e1000e_device *d, uint32_t reg, uint32_t val)
|
||||
{
|
||||
qpci_io_writel(d->pci_dev, d->mac_regs + reg, val);
|
||||
qpci_io_writel(d->pci_dev, d->mac_regs, reg, val);
|
||||
}
|
||||
|
||||
static uint32_t e1000e_macreg_read(e1000e_device *d, uint32_t reg)
|
||||
{
|
||||
return qpci_io_readl(d->pci_dev, d->mac_regs + reg);
|
||||
return qpci_io_readl(d->pci_dev, d->mac_regs, reg);
|
||||
}
|
||||
|
||||
static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
|
||||
@ -138,7 +138,6 @@ static void e1000e_device_init(QPCIBus *bus, e1000e_device *d)
|
||||
|
||||
/* Map BAR0 (mac registers) */
|
||||
d->mac_regs = qpci_iomap(d->pci_dev, 0, NULL);
|
||||
g_assert_nonnull(d->mac_regs);
|
||||
|
||||
/* Reset the device */
|
||||
val = e1000e_macreg_read(d, E1000E_CTRL);
|
||||
|
176
tests/ide-test.c
176
tests/ide-test.c
@ -137,7 +137,7 @@ static void ide_test_quit(void)
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
static QPCIDevice *get_pci_device(void **bmdma_base, void **ide_base)
|
||||
static QPCIDevice *get_pci_device(QPCIBar *bmdma_bar, QPCIBar *ide_bar)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
uint16_t vendor_id, device_id;
|
||||
@ -156,9 +156,9 @@ static QPCIDevice *get_pci_device(void **bmdma_base, void **ide_base)
|
||||
g_assert(device_id == PCI_DEVICE_ID_INTEL_82371SB_1);
|
||||
|
||||
/* Map bmdma BAR */
|
||||
*bmdma_base = qpci_iomap(dev, 4, NULL);
|
||||
*bmdma_bar = qpci_iomap(dev, 4, NULL);
|
||||
|
||||
*ide_base = qpci_legacy_iomap(dev, IDE_BASE);
|
||||
*ide_bar = qpci_legacy_iomap(dev, IDE_BASE);
|
||||
|
||||
qpci_device_enable(dev);
|
||||
|
||||
@ -181,19 +181,18 @@ typedef struct PrdtEntry {
|
||||
|
||||
static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
|
||||
PrdtEntry *prdt, int prdt_entries,
|
||||
void(*post_exec)(QPCIDevice *dev, void *ide_base,
|
||||
void(*post_exec)(QPCIDevice *dev, QPCIBar ide_bar,
|
||||
uint64_t sector, int nb_sectors))
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base;
|
||||
void *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uintptr_t guest_prdt;
|
||||
size_t len;
|
||||
bool from_dev;
|
||||
uint8_t status;
|
||||
int flags;
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
flags = cmd & ~0xff;
|
||||
cmd &= 0xff;
|
||||
@ -218,60 +217,60 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
|
||||
}
|
||||
|
||||
/* Select device 0 */
|
||||
qpci_io_writeb(dev, ide_base + reg_device, 0 | LBA);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0 | LBA);
|
||||
|
||||
/* Stop any running transfer, clear any pending interrupt */
|
||||
qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);
|
||||
qpci_io_writeb(dev, bmdma_base + bmreg_status, BM_STS_INTR);
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_status, BM_STS_INTR);
|
||||
|
||||
/* Setup PRDT */
|
||||
len = sizeof(*prdt) * prdt_entries;
|
||||
guest_prdt = guest_alloc(guest_malloc, len);
|
||||
memwrite(guest_prdt, prdt, len);
|
||||
qpci_io_writel(dev, bmdma_base + bmreg_prdt, guest_prdt);
|
||||
qpci_io_writel(dev, bmdma_bar, bmreg_prdt, guest_prdt);
|
||||
|
||||
/* ATA DMA command */
|
||||
if (cmd == CMD_PACKET) {
|
||||
/* Enables ATAPI DMA; otherwise PIO is attempted */
|
||||
qpci_io_writeb(dev, ide_base + reg_feature, 0x01);
|
||||
qpci_io_writeb(dev, ide_bar, reg_feature, 0x01);
|
||||
} else {
|
||||
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);
|
||||
qpci_io_writeb(dev, ide_bar, reg_nsectors, nb_sectors);
|
||||
qpci_io_writeb(dev, ide_bar, reg_lba_low, sector & 0xff);
|
||||
qpci_io_writeb(dev, ide_bar, reg_lba_middle, (sector >> 8) & 0xff);
|
||||
qpci_io_writeb(dev, ide_bar, reg_lba_high, (sector >> 16) & 0xff);
|
||||
}
|
||||
|
||||
qpci_io_writeb(dev, ide_base + reg_command, cmd);
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, cmd);
|
||||
|
||||
if (post_exec) {
|
||||
post_exec(dev, ide_base, sector, nb_sectors);
|
||||
post_exec(dev, ide_bar, sector, nb_sectors);
|
||||
}
|
||||
|
||||
/* Start DMA transfer */
|
||||
qpci_io_writeb(dev, bmdma_base + bmreg_cmd,
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd,
|
||||
BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
|
||||
|
||||
if (flags & CMDF_ABORT) {
|
||||
qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
}
|
||||
|
||||
/* Wait for the DMA transfer to complete */
|
||||
do {
|
||||
status = qpci_io_readb(dev, bmdma_base + bmreg_status);
|
||||
status = qpci_io_readb(dev, bmdma_bar, 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(qpci_io_readb(dev, ide_base + reg_status), DRDY);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), BSY | DRQ);
|
||||
assert_bit_set(qpci_io_readb(dev, ide_bar, reg_status), DRDY);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, 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) {
|
||||
qpci_io_writeb(dev, bmdma_base + bmreg_cmd, 0);
|
||||
qpci_io_writeb(dev, bmdma_bar, bmreg_cmd, 0);
|
||||
}
|
||||
|
||||
free_pci_device(dev);
|
||||
@ -282,7 +281,7 @@ 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;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
uint8_t *buf;
|
||||
uint8_t *cmpbuf;
|
||||
@ -296,7 +295,7 @@ static void test_bmdma_simple_rw(void)
|
||||
},
|
||||
};
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
buf = g_malloc(len);
|
||||
cmpbuf = g_malloc(len);
|
||||
@ -308,7 +307,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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
|
||||
/* Write 0xaa pattern to sector 1 */
|
||||
memset(buf, 0xaa, len);
|
||||
@ -317,14 +316,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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
|
||||
memread(guest_buf, buf, len);
|
||||
g_assert(memcmp(buf, cmpbuf, len) == 0);
|
||||
@ -334,7 +333,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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
|
||||
memread(guest_buf, buf, len);
|
||||
g_assert(memcmp(buf, cmpbuf, len) == 0);
|
||||
@ -347,7 +346,7 @@ static void test_bmdma_simple_rw(void)
|
||||
static void test_bmdma_short_prdt(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
|
||||
PrdtEntry prdt[] = {
|
||||
@ -357,25 +356,25 @@ static void test_bmdma_short_prdt(void)
|
||||
},
|
||||
};
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* Normal request */
|
||||
status = send_dma_request(CMD_READ_DMA, 0, 1,
|
||||
prdt, ARRAY_SIZE(prdt), NULL);
|
||||
g_assert_cmphex(status, ==, 0);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
}
|
||||
|
||||
static void test_bmdma_one_sector_short_prdt(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
|
||||
/* Read 2 sectors but only give 1 sector in PRDT */
|
||||
@ -386,25 +385,25 @@ static void test_bmdma_one_sector_short_prdt(void)
|
||||
},
|
||||
};
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* Normal request */
|
||||
status = send_dma_request(CMD_READ_DMA, 0, 2,
|
||||
prdt, ARRAY_SIZE(prdt), NULL);
|
||||
g_assert_cmphex(status, ==, 0);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
}
|
||||
|
||||
static void test_bmdma_long_prdt(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
|
||||
PrdtEntry prdt[] = {
|
||||
@ -414,28 +413,28 @@ static void test_bmdma_long_prdt(void)
|
||||
},
|
||||
};
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
}
|
||||
|
||||
static void test_bmdma_no_busmaster(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* 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
|
||||
@ -449,7 +448,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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
}
|
||||
|
||||
static void test_bmdma_setup(void)
|
||||
@ -480,7 +479,7 @@ static void string_cpu_to_be16(uint16_t *s, size_t bytes)
|
||||
static void test_identify(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t data;
|
||||
uint16_t buf[256];
|
||||
int i;
|
||||
@ -491,25 +490,25 @@ static void test_identify(void)
|
||||
"-global ide-hd.ver=%s",
|
||||
tmp_path, "testdisk", "version");
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* IDENTIFY command on device 0*/
|
||||
qpci_io_writeb(dev, ide_base + reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_base + reg_command, CMD_IDENTIFY);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, CMD_IDENTIFY);
|
||||
|
||||
/* Read in the IDENTIFY buffer and check registers */
|
||||
data = qpci_io_readb(dev, ide_base + reg_device);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_device);
|
||||
g_assert_cmpint(data & DEV, ==, 0);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
assert_bit_set(data, DRDY | DRQ);
|
||||
assert_bit_clear(data, BSY | DF | ERR);
|
||||
|
||||
buf[i] = qpci_io_readw(dev, ide_base + reg_data);
|
||||
buf[i] = qpci_io_readw(dev, ide_bar, reg_data);
|
||||
}
|
||||
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
assert_bit_set(data, DRDY);
|
||||
assert_bit_clear(data, BSY | DF | ERR | DRQ);
|
||||
|
||||
@ -535,13 +534,13 @@ static void test_identify(void)
|
||||
static void make_dirty(uint8_t device)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t status;
|
||||
size_t len = 512;
|
||||
uintptr_t guest_buf;
|
||||
void* buf;
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
guest_buf = guest_alloc(guest_malloc, len);
|
||||
buf = g_malloc(len);
|
||||
@ -560,7 +559,7 @@ 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(qpci_io_readb(dev, ide_base + reg_status), DF | ERR);
|
||||
assert_bit_clear(qpci_io_readb(dev, ide_bar, reg_status), DF | ERR);
|
||||
|
||||
g_free(buf);
|
||||
}
|
||||
@ -568,14 +567,14 @@ static void make_dirty(uint8_t device)
|
||||
static void test_flush(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
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);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "ioapic");
|
||||
|
||||
@ -586,11 +585,11 @@ static void test_flush(void)
|
||||
g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\""));
|
||||
|
||||
/* FLUSH CACHE command on device 0*/
|
||||
qpci_io_writeb(dev, ide_base + reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, CMD_FLUSH_CACHE);
|
||||
|
||||
/* Check status while request is in flight*/
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
assert_bit_set(data, BSY | DRDY);
|
||||
assert_bit_clear(data, DF | ERR | DRQ);
|
||||
|
||||
@ -598,11 +597,11 @@ static void test_flush(void)
|
||||
g_free(hmp("qemu-io ide0-hd0 \"resume A\""));
|
||||
|
||||
/* Check registers */
|
||||
data = qpci_io_readb(dev, ide_base + reg_device);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_device);
|
||||
g_assert_cmpint(data & DEV, ==, 0);
|
||||
|
||||
do {
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
} while (data & BSY);
|
||||
|
||||
assert_bit_set(data, DRDY);
|
||||
@ -614,7 +613,7 @@ static void test_flush(void)
|
||||
static void test_retry_flush(const char *machine)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t data;
|
||||
const char *s;
|
||||
|
||||
@ -626,7 +625,7 @@ static void test_retry_flush(const char *machine)
|
||||
"rerror=stop,werror=stop",
|
||||
debug_path, tmp_path);
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
qtest_irq_intercept_in(global_qtest, "ioapic");
|
||||
|
||||
@ -634,11 +633,11 @@ static void test_retry_flush(const char *machine)
|
||||
make_dirty(0);
|
||||
|
||||
/* FLUSH CACHE command on device 0*/
|
||||
qpci_io_writeb(dev, ide_base + reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, CMD_FLUSH_CACHE);
|
||||
|
||||
/* Check status while request is in flight*/
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
assert_bit_set(data, BSY | DRDY);
|
||||
assert_bit_clear(data, DF | ERR | DRQ);
|
||||
|
||||
@ -649,11 +648,11 @@ static void test_retry_flush(const char *machine)
|
||||
qmp_discard_response(s);
|
||||
|
||||
/* Check registers */
|
||||
data = qpci_io_readb(dev, ide_base + reg_device);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_device);
|
||||
g_assert_cmpint(data & DEV, ==, 0);
|
||||
|
||||
do {
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
} while (data & BSY);
|
||||
|
||||
assert_bit_set(data, DRDY);
|
||||
@ -665,15 +664,15 @@ static void test_retry_flush(const char *machine)
|
||||
static void test_flush_nodev(void)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
|
||||
ide_test_start("");
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* FLUSH CACHE command on device 0*/
|
||||
qpci_io_writeb(dev, ide_base + reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_base + reg_command, CMD_FLUSH_CACHE);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, CMD_FLUSH_CACHE);
|
||||
|
||||
/* Just testing that qemu doesn't crash... */
|
||||
|
||||
@ -700,7 +699,7 @@ typedef struct Read10CDB {
|
||||
uint16_t padding;
|
||||
} __attribute__((__packed__)) Read10CDB;
|
||||
|
||||
static void send_scsi_cdb_read10(QPCIDevice *dev, void *ide_base,
|
||||
static void send_scsi_cdb_read10(QPCIDevice *dev, QPCIBar ide_bar,
|
||||
uint64_t lba, int nblocks)
|
||||
{
|
||||
Read10CDB pkt = { .padding = 0 };
|
||||
@ -717,7 +716,7 @@ static void send_scsi_cdb_read10(QPCIDevice *dev, void *ide_base,
|
||||
|
||||
/* Send Packet */
|
||||
for (i = 0; i < sizeof(Read10CDB)/2; i++) {
|
||||
qpci_io_writew(dev, ide_base + reg_data,
|
||||
qpci_io_writew(dev, ide_bar, reg_data,
|
||||
le16_to_cpu(((uint16_t *)&pkt)[i]));
|
||||
}
|
||||
}
|
||||
@ -732,16 +731,16 @@ static void nsleep(int64_t nsecs)
|
||||
static uint8_t ide_wait_clear(uint8_t flag)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
uint8_t data;
|
||||
time_t st;
|
||||
|
||||
dev = get_pci_device(&bmdma_base, &ide_base);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
|
||||
/* Wait with a 5 second timeout */
|
||||
time(&st);
|
||||
while (true) {
|
||||
data = qpci_io_readb(dev, ide_base + reg_status);
|
||||
data = qpci_io_readb(dev, ide_bar, reg_status);
|
||||
if (!(data & flag)) {
|
||||
return data;
|
||||
}
|
||||
@ -776,7 +775,7 @@ static void ide_wait_intr(int irq)
|
||||
static void cdrom_pio_impl(int nblocks)
|
||||
{
|
||||
QPCIDevice *dev;
|
||||
void *bmdma_base, *ide_base;
|
||||
QPCIBar bmdma_bar, ide_bar;
|
||||
FILE *fh;
|
||||
int patt_blocks = MAX(16, nblocks);
|
||||
size_t patt_len = ATAPI_BLOCK_SIZE * patt_blocks;
|
||||
@ -795,15 +794,14 @@ 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);
|
||||
dev = get_pci_device(&bmdma_bar, &ide_bar);
|
||||
qtest_irq_intercept_in(global_qtest, "ioapic");
|
||||
|
||||
/* PACKET command on device 0 */
|
||||
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);
|
||||
qpci_io_writeb(dev, ide_bar, reg_device, 0);
|
||||
qpci_io_writeb(dev, ide_bar, reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF);
|
||||
qpci_io_writeb(dev, ide_bar, reg_lba_high, (BYTE_COUNT_LIMIT >> 8 & 0xFF));
|
||||
qpci_io_writeb(dev, ide_bar, reg_command, CMD_PACKET);
|
||||
/* HP0: Check_Status_A State */
|
||||
nsleep(400);
|
||||
data = ide_wait_clear(BSY);
|
||||
@ -812,7 +810,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(dev, ide_base, 0, nblocks);
|
||||
send_scsi_cdb_read10(dev, ide_bar, 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.
|
||||
@ -836,8 +834,8 @@ static void cdrom_pio_impl(int nblocks)
|
||||
|
||||
/* HP4: Transfer_Data */
|
||||
for (j = 0; j < MIN((limit / 2), rem); j++) {
|
||||
rx[offset + j] = cpu_to_le16(qpci_io_readw(dev,
|
||||
ide_base + reg_data));
|
||||
rx[offset + j] = cpu_to_le16(qpci_io_readw(dev, ide_bar,
|
||||
reg_data));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ static QPCIDevice *get_device(QPCIBus *pcibus)
|
||||
|
||||
typedef struct _IVState {
|
||||
QTestState *qtest;
|
||||
void *reg_base, *mem_base;
|
||||
QPCIBar reg_bar, mem_bar;
|
||||
QPCIBus *pcibus;
|
||||
QPCIDevice *dev;
|
||||
} IVState;
|
||||
@ -75,7 +75,7 @@ static inline unsigned in_reg(IVState *s, enum Reg reg)
|
||||
unsigned res;
|
||||
|
||||
global_qtest = s->qtest;
|
||||
res = qpci_io_readl(s->dev, s->reg_base + reg);
|
||||
res = qpci_io_readl(s->dev, s->reg_bar, reg);
|
||||
g_test_message("*%s -> %x\n", name, res);
|
||||
global_qtest = qtest;
|
||||
|
||||
@ -89,7 +89,7 @@ static inline void out_reg(IVState *s, enum Reg reg, unsigned v)
|
||||
|
||||
global_qtest = s->qtest;
|
||||
g_test_message("%x -> *%s\n", v, name);
|
||||
qpci_io_writel(s->dev, s->reg_base + reg, v);
|
||||
qpci_io_writel(s->dev, s->reg_bar, reg, v);
|
||||
global_qtest = qtest;
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ static inline void read_mem(IVState *s, uint64_t off, void *buf, size_t len)
|
||||
QTestState *qtest = global_qtest;
|
||||
|
||||
global_qtest = s->qtest;
|
||||
qpci_memread(s->dev, s->mem_base + off, buf, len);
|
||||
qpci_memread(s->dev, s->mem_bar, off, buf, len);
|
||||
global_qtest = qtest;
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ static inline void write_mem(IVState *s, uint64_t off,
|
||||
QTestState *qtest = global_qtest;
|
||||
|
||||
global_qtest = s->qtest;
|
||||
qpci_memwrite(s->dev, s->mem_base + off, buf, len);
|
||||
qpci_memwrite(s->dev, s->mem_bar, off, buf, len);
|
||||
global_qtest = qtest;
|
||||
}
|
||||
|
||||
@ -127,16 +127,14 @@ static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
|
||||
s->pcibus = qpci_init_pc(NULL);
|
||||
s->dev = get_device(s->pcibus);
|
||||
|
||||
s->reg_base = qpci_iomap(s->dev, 0, &barsize);
|
||||
g_assert_nonnull(s->reg_base);
|
||||
s->reg_bar = qpci_iomap(s->dev, 0, &barsize);
|
||||
g_assert_cmpuint(barsize, ==, 256);
|
||||
|
||||
if (msix) {
|
||||
qpci_msix_enable(s->dev);
|
||||
}
|
||||
|
||||
s->mem_base = qpci_iomap(s->dev, 2, &barsize);
|
||||
g_assert_nonnull(s->mem_base);
|
||||
s->mem_bar = qpci_iomap(s->dev, 2, &barsize);
|
||||
g_assert_cmpuint(barsize, ==, TMPSHMSIZE);
|
||||
|
||||
qpci_device_enable(s->dev);
|
||||
|
@ -210,8 +210,7 @@ void ahci_pci_enable(AHCIQState *ahci)
|
||||
void start_ahci_device(AHCIQState *ahci)
|
||||
{
|
||||
/* Map AHCI's ABAR (BAR5) */
|
||||
ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize);
|
||||
g_assert(ahci->hba_base);
|
||||
ahci->hba_bar = qpci_iomap(ahci->dev, 5, &ahci->barsize);
|
||||
|
||||
/* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
|
||||
qpci_device_enable(ahci->dev);
|
||||
|
@ -321,7 +321,7 @@ typedef struct AHCIPortQState {
|
||||
typedef struct AHCIQState {
|
||||
QOSState *parent;
|
||||
QPCIDevice *dev;
|
||||
void *hba_base;
|
||||
QPCIBar hba_bar;
|
||||
uint64_t barsize;
|
||||
uint32_t fingerprint;
|
||||
uint32_t cap;
|
||||
@ -489,12 +489,12 @@ typedef struct AHCIOpts {
|
||||
|
||||
static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset)
|
||||
{
|
||||
return qpci_io_readl(ahci->dev, ahci->hba_base + offset);
|
||||
return qpci_io_readl(ahci->dev, ahci->hba_bar, offset);
|
||||
}
|
||||
|
||||
static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value)
|
||||
{
|
||||
qpci_io_writel(ahci->dev, ahci->hba_base + offset, value);
|
||||
qpci_io_writel(ahci->dev, ahci->hba_bar, offset, value);
|
||||
}
|
||||
|
||||
static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num)
|
||||
|
@ -104,7 +104,6 @@ void qpci_msix_enable(QPCIDevice *dev)
|
||||
uint32_t table;
|
||||
uint8_t bir_table;
|
||||
uint8_t bir_pba;
|
||||
void *offset;
|
||||
|
||||
addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
g_assert_cmphex(addr, !=, 0);
|
||||
@ -114,18 +113,16 @@ void qpci_msix_enable(QPCIDevice *dev)
|
||||
|
||||
table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
|
||||
bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
|
||||
offset = qpci_iomap(dev, bir_table, NULL);
|
||||
dev->msix_table = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
|
||||
dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
|
||||
dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
|
||||
table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
|
||||
bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
|
||||
if (bir_pba != bir_table) {
|
||||
offset = qpci_iomap(dev, bir_pba, NULL);
|
||||
dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
|
||||
}
|
||||
dev->msix_pba = offset + (table & ~PCI_MSIX_FLAGS_BIRMASK);
|
||||
dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
|
||||
|
||||
g_assert(dev->msix_table != NULL);
|
||||
g_assert(dev->msix_pba != NULL);
|
||||
dev->msix_enabled = true;
|
||||
}
|
||||
|
||||
@ -141,22 +138,23 @@ void qpci_msix_disable(QPCIDevice *dev)
|
||||
qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
|
||||
val & ~PCI_MSIX_FLAGS_ENABLE);
|
||||
|
||||
qpci_iounmap(dev, dev->msix_table);
|
||||
qpci_iounmap(dev, dev->msix_pba);
|
||||
qpci_iounmap(dev, dev->msix_table_bar);
|
||||
qpci_iounmap(dev, dev->msix_pba_bar);
|
||||
dev->msix_enabled = 0;
|
||||
dev->msix_table = NULL;
|
||||
dev->msix_pba = NULL;
|
||||
dev->msix_table_off = 0;
|
||||
dev->msix_pba_off = 0;
|
||||
}
|
||||
|
||||
bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
|
||||
{
|
||||
uint32_t pba_entry;
|
||||
uint8_t bit_n = entry % 32;
|
||||
void *addr = dev->msix_pba + (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
|
||||
uint64_t off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
|
||||
|
||||
g_assert(dev->msix_enabled);
|
||||
pba_entry = qpci_io_readl(dev, addr);
|
||||
qpci_io_writel(dev, addr, pba_entry & ~(1 << bit_n));
|
||||
pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
|
||||
qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
|
||||
pba_entry & ~(1 << bit_n));
|
||||
return (pba_entry & (1 << bit_n)) != 0;
|
||||
}
|
||||
|
||||
@ -164,7 +162,7 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
|
||||
{
|
||||
uint8_t addr;
|
||||
uint16_t val;
|
||||
void *vector_addr = dev->msix_table + (entry * PCI_MSIX_ENTRY_SIZE);
|
||||
uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
|
||||
|
||||
g_assert(dev->msix_enabled);
|
||||
addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX);
|
||||
@ -174,8 +172,9 @@ bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
|
||||
if (val & PCI_MSIX_FLAGS_MASKALL) {
|
||||
return true;
|
||||
} else {
|
||||
return (qpci_io_readl(dev, vector_addr + PCI_MSIX_ENTRY_VECTOR_CTRL)
|
||||
& PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
|
||||
return (qpci_io_readl(dev, dev->msix_table_bar,
|
||||
vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
|
||||
& PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,129 +221,115 @@ void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
|
||||
dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
|
||||
}
|
||||
|
||||
|
||||
uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
|
||||
uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readb(dev->bus, addr);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readb(dev->bus, token.addr + off);
|
||||
} else {
|
||||
uint8_t val;
|
||||
dev->bus->memread(dev->bus, addr, &val, sizeof(val));
|
||||
dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
|
||||
uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readw(dev->bus, addr);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readw(dev->bus, token.addr + off);
|
||||
} else {
|
||||
uint16_t val;
|
||||
dev->bus->memread(dev->bus, addr, &val, sizeof(val));
|
||||
dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
|
||||
return le16_to_cpu(val);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
|
||||
uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readl(dev->bus, addr);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readl(dev->bus, token.addr + off);
|
||||
} else {
|
||||
uint32_t val;
|
||||
dev->bus->memread(dev->bus, addr, &val, sizeof(val));
|
||||
dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
|
||||
return le32_to_cpu(val);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t qpci_io_readq(QPCIDevice *dev, void *data)
|
||||
uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readq(dev->bus, addr);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
return dev->bus->pio_readq(dev->bus, token.addr + off);
|
||||
} else {
|
||||
uint64_t val;
|
||||
dev->bus->memread(dev->bus, addr, &val, sizeof(val));
|
||||
dev->bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
|
||||
return le64_to_cpu(val);
|
||||
}
|
||||
}
|
||||
|
||||
void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
|
||||
void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint8_t value)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writeb(dev->bus, addr, value);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writeb(dev->bus, token.addr + off, value);
|
||||
} else {
|
||||
dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
|
||||
dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
|
||||
void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint16_t value)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writew(dev->bus, addr, value);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writew(dev->bus, token.addr + off, value);
|
||||
} else {
|
||||
value = cpu_to_le16(value);
|
||||
dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
|
||||
dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
|
||||
void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint32_t value)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writel(dev->bus, addr, value);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writel(dev->bus, token.addr + off, value);
|
||||
} else {
|
||||
value = cpu_to_le32(value);
|
||||
dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
|
||||
dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void qpci_io_writeq(QPCIDevice *dev, void *data, uint64_t value)
|
||||
void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint64_t value)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
if (addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writeq(dev->bus, addr, value);
|
||||
if (token.addr < QPCI_PIO_LIMIT) {
|
||||
dev->bus->pio_writeq(dev->bus, token.addr + off, value);
|
||||
} else {
|
||||
value = cpu_to_le64(value);
|
||||
dev->bus->memwrite(dev->bus, addr, &value, sizeof(value));
|
||||
dev->bus->memwrite(dev->bus, token.addr + off, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void qpci_memread(QPCIDevice *dev, void *data, void *buf, size_t len)
|
||||
void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
g_assert(addr >= QPCI_PIO_LIMIT);
|
||||
dev->bus->memread(dev->bus, addr, buf, len);
|
||||
g_assert(token.addr >= QPCI_PIO_LIMIT);
|
||||
dev->bus->memread(dev->bus, token.addr + off, buf, len);
|
||||
}
|
||||
|
||||
void qpci_memwrite(QPCIDevice *dev, void *data, const void *buf, size_t len)
|
||||
void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
uintptr_t addr = (uintptr_t)data;
|
||||
|
||||
g_assert(addr >= QPCI_PIO_LIMIT);
|
||||
dev->bus->memwrite(dev->bus, addr, buf, len);
|
||||
g_assert(token.addr >= QPCI_PIO_LIMIT);
|
||||
dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
|
||||
}
|
||||
|
||||
void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
|
||||
QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
|
||||
{
|
||||
QPCIBus *bus = dev->bus;
|
||||
static const int bar_reg_map[] = {
|
||||
PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
|
||||
PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
|
||||
};
|
||||
QPCIBar bar;
|
||||
int bar_reg;
|
||||
uint32_t addr, size;
|
||||
uint32_t io_type;
|
||||
@ -391,17 +376,19 @@ void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
|
||||
qpci_config_writel(dev, bar_reg, loc);
|
||||
}
|
||||
|
||||
return (void *)(uintptr_t)loc;
|
||||
bar.addr = loc;
|
||||
return bar;
|
||||
}
|
||||
|
||||
void qpci_iounmap(QPCIDevice *dev, void *data)
|
||||
void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
void *qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
|
||||
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
|
||||
{
|
||||
return (void *)(uintptr_t)addr;
|
||||
QPCIBar bar = { .addr = addr };
|
||||
return bar;
|
||||
}
|
||||
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
typedef struct QPCIDevice QPCIDevice;
|
||||
typedef struct QPCIBus QPCIBus;
|
||||
typedef struct QPCIBar QPCIBar;
|
||||
|
||||
struct QPCIBus {
|
||||
uint8_t (*pio_readb)(QPCIBus *bus, uint32_t addr);
|
||||
@ -51,13 +52,17 @@ struct QPCIBus {
|
||||
uint64_t mmio_alloc_ptr, mmio_limit;
|
||||
};
|
||||
|
||||
struct QPCIBar {
|
||||
uint64_t addr;
|
||||
};
|
||||
|
||||
struct QPCIDevice
|
||||
{
|
||||
QPCIBus *bus;
|
||||
int devfn;
|
||||
bool msix_enabled;
|
||||
void *msix_table;
|
||||
void *msix_pba;
|
||||
QPCIBar msix_table_bar, msix_pba_bar;
|
||||
uint64_t msix_table_off, msix_pba_off;
|
||||
};
|
||||
|
||||
void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
|
||||
@ -81,22 +86,27 @@ void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
|
||||
void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
|
||||
void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
|
||||
|
||||
uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
|
||||
uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
|
||||
uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
|
||||
uint64_t qpci_io_readq(QPCIDevice *dev, void *data);
|
||||
uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off);
|
||||
uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off);
|
||||
uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off);
|
||||
uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off);
|
||||
|
||||
void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
|
||||
void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
|
||||
void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
|
||||
void qpci_io_writeq(QPCIDevice *dev, void *data, uint64_t value);
|
||||
void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint8_t value);
|
||||
void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint16_t value);
|
||||
void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint32_t value);
|
||||
void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
|
||||
uint64_t value);
|
||||
|
||||
void qpci_memread(QPCIDevice *bus, void *data, void *buf, size_t len);
|
||||
void qpci_memwrite(QPCIDevice *bus, void *data, const void *buf, size_t len);
|
||||
|
||||
void *qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
|
||||
void qpci_iounmap(QPCIDevice *dev, void *data);
|
||||
void *qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr);
|
||||
void qpci_memread(QPCIDevice *bus, QPCIBar token, uint64_t off,
|
||||
void *buf, size_t len);
|
||||
void qpci_memwrite(QPCIDevice *bus, QPCIBar token, uint64_t off,
|
||||
const void *buf, size_t len);
|
||||
QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr);
|
||||
void qpci_iounmap(QPCIDevice *dev, QPCIBar addr);
|
||||
QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr);
|
||||
|
||||
void qpci_plug_device_test(const char *driver, const char *id,
|
||||
uint8_t slot, const char *opts);
|
||||
|
@ -21,14 +21,12 @@ void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc, uint32_t devfn, int bar)
|
||||
hc->dev = qpci_device_find(pcibus, devfn);
|
||||
g_assert(hc->dev != NULL);
|
||||
qpci_device_enable(hc->dev);
|
||||
hc->base = qpci_iomap(hc->dev, bar, NULL);
|
||||
g_assert(hc->base != NULL);
|
||||
hc->bar = qpci_iomap(hc->dev, bar, NULL);
|
||||
}
|
||||
|
||||
void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
|
||||
{
|
||||
void *addr = hc->base + 0x10 + 2 * port;
|
||||
uint16_t value = qpci_io_readw(hc->dev, addr);
|
||||
uint16_t value = qpci_io_readw(hc->dev, hc->bar, 0x10 + 2 * port);
|
||||
uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
|
||||
|
||||
g_assert((value & mask) == (expect & mask));
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
struct qhc {
|
||||
QPCIDevice *dev;
|
||||
void *base;
|
||||
QPCIBar bar;
|
||||
};
|
||||
|
||||
void qusb_pci_init_one(QPCIBus *pcibus, struct qhc *hc,
|
||||
|
@ -62,13 +62,12 @@ static void qvirtio_pci_assign_device(QVirtioDevice *d, void *data)
|
||||
*vpcidev = (QVirtioPCIDevice *)d;
|
||||
}
|
||||
|
||||
#define CONFIG_BASE(dev) \
|
||||
((dev)->addr + VIRTIO_PCI_CONFIG_OFF((dev)->pdev->msix_enabled))
|
||||
#define CONFIG_BASE(dev) (VIRTIO_PCI_CONFIG_OFF((dev)->pdev->msix_enabled))
|
||||
|
||||
static uint8_t qvirtio_pci_config_readb(QVirtioDevice *d, uint64_t off)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
return qpci_io_readb(dev->pdev, CONFIG_BASE(dev) + off);
|
||||
return qpci_io_readb(dev->pdev, dev->bar, CONFIG_BASE(dev) + off);
|
||||
}
|
||||
|
||||
/* PCI is always read in little-endian order
|
||||
@ -84,7 +83,7 @@ static uint16_t qvirtio_pci_config_readw(QVirtioDevice *d, uint64_t off)
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
uint16_t value;
|
||||
|
||||
value = qpci_io_readw(dev->pdev, CONFIG_BASE(dev) + off);
|
||||
value = qpci_io_readw(dev->pdev, dev->bar, CONFIG_BASE(dev) + off);
|
||||
if (qvirtio_is_big_endian(d)) {
|
||||
value = bswap16(value);
|
||||
}
|
||||
@ -96,7 +95,7 @@ static uint32_t qvirtio_pci_config_readl(QVirtioDevice *d, uint64_t off)
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
uint32_t value;
|
||||
|
||||
value = qpci_io_readl(dev->pdev, CONFIG_BASE(dev) + off);
|
||||
value = qpci_io_readl(dev->pdev, dev->bar, CONFIG_BASE(dev) + off);
|
||||
if (qvirtio_is_big_endian(d)) {
|
||||
value = bswap32(value);
|
||||
}
|
||||
@ -108,7 +107,7 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
uint64_t val;
|
||||
|
||||
val = qpci_io_readq(dev->pdev, CONFIG_BASE(dev) + off);
|
||||
val = qpci_io_readq(dev->pdev, dev->bar, CONFIG_BASE(dev) + off);
|
||||
if (qvirtio_is_big_endian(d)) {
|
||||
val = bswap64(val);
|
||||
}
|
||||
@ -119,31 +118,31 @@ static uint64_t qvirtio_pci_config_readq(QVirtioDevice *d, uint64_t off)
|
||||
static uint32_t qvirtio_pci_get_features(QVirtioDevice *d)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_HOST_FEATURES);
|
||||
return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_HOST_FEATURES);
|
||||
}
|
||||
|
||||
static void qvirtio_pci_set_features(QVirtioDevice *d, uint32_t features)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES, features);
|
||||
qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES, features);
|
||||
}
|
||||
|
||||
static uint32_t qvirtio_pci_get_guest_features(QVirtioDevice *d)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
return qpci_io_readl(dev->pdev, dev->addr + VIRTIO_PCI_GUEST_FEATURES);
|
||||
return qpci_io_readl(dev->pdev, dev->bar, VIRTIO_PCI_GUEST_FEATURES);
|
||||
}
|
||||
|
||||
static uint8_t qvirtio_pci_get_status(QVirtioDevice *d)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS);
|
||||
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS);
|
||||
}
|
||||
|
||||
static void qvirtio_pci_set_status(QVirtioDevice *d, uint8_t status)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_STATUS, status);
|
||||
qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_STATUS, status);
|
||||
}
|
||||
|
||||
static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
|
||||
@ -167,7 +166,7 @@ static bool qvirtio_pci_get_queue_isr_status(QVirtioDevice *d, QVirtQueue *vq)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 1;
|
||||
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,26 +190,26 @@ static bool qvirtio_pci_get_config_isr_status(QVirtioDevice *d)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return qpci_io_readb(dev->pdev, dev->addr + VIRTIO_PCI_ISR) & 2;
|
||||
return qpci_io_readb(dev->pdev, dev->bar, VIRTIO_PCI_ISR) & 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void qvirtio_pci_queue_select(QVirtioDevice *d, uint16_t index)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
qpci_io_writeb(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_SEL, index);
|
||||
qpci_io_writeb(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_SEL, index);
|
||||
}
|
||||
|
||||
static uint16_t qvirtio_pci_get_queue_size(QVirtioDevice *d)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
return qpci_io_readw(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NUM);
|
||||
return qpci_io_readw(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NUM);
|
||||
}
|
||||
|
||||
static void qvirtio_pci_set_queue_address(QVirtioDevice *d, uint32_t pfn)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
qpci_io_writel(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_PFN, pfn);
|
||||
qpci_io_writel(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_PFN, pfn);
|
||||
}
|
||||
|
||||
static QVirtQueue *qvirtio_pci_virtqueue_setup(QVirtioDevice *d,
|
||||
@ -262,7 +261,7 @@ static void qvirtio_pci_virtqueue_cleanup(QVirtQueue *vq,
|
||||
static void qvirtio_pci_virtqueue_kick(QVirtioDevice *d, QVirtQueue *vq)
|
||||
{
|
||||
QVirtioPCIDevice *dev = (QVirtioPCIDevice *)d;
|
||||
qpci_io_writew(dev->pdev, dev->addr + VIRTIO_PCI_QUEUE_NOTIFY, vq->index);
|
||||
qpci_io_writew(dev->pdev, dev->bar, VIRTIO_PCI_QUEUE_NOTIFY, vq->index);
|
||||
}
|
||||
|
||||
const QVirtioBus qvirtio_pci = {
|
||||
@ -309,14 +308,12 @@ QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, uint16_t device_type)
|
||||
void qvirtio_pci_device_enable(QVirtioPCIDevice *d)
|
||||
{
|
||||
qpci_device_enable(d->pdev);
|
||||
d->addr = qpci_iomap(d->pdev, 0, NULL);
|
||||
g_assert(d->addr != NULL);
|
||||
d->bar = qpci_iomap(d->pdev, 0, NULL);
|
||||
}
|
||||
|
||||
void qvirtio_pci_device_disable(QVirtioPCIDevice *d)
|
||||
{
|
||||
qpci_iounmap(d->pdev, d->addr);
|
||||
d->addr = NULL;
|
||||
qpci_iounmap(d->pdev, d->bar);
|
||||
}
|
||||
|
||||
void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
|
||||
@ -324,29 +321,33 @@ void qvirtqueue_pci_msix_setup(QVirtioPCIDevice *d, QVirtQueuePCI *vqpci,
|
||||
{
|
||||
uint16_t vector;
|
||||
uint32_t control;
|
||||
void *addr;
|
||||
uint64_t off;
|
||||
|
||||
g_assert(d->pdev->msix_enabled);
|
||||
addr = d->pdev->msix_table + (entry * 16);
|
||||
off = d->pdev->msix_table_off + (entry * 16);
|
||||
|
||||
g_assert_cmpint(entry, >=, 0);
|
||||
g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
|
||||
vqpci->msix_entry = entry;
|
||||
|
||||
vqpci->msix_addr = guest_alloc(alloc, 4);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
|
||||
vqpci->msix_addr & ~0UL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
|
||||
(vqpci->msix_addr >> 32) & ~0UL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_LOWER_ADDR, vqpci->msix_addr & ~0UL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_UPPER_ADDR,
|
||||
(vqpci->msix_addr >> 32) & ~0UL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_DATA, vqpci->msix_data);
|
||||
|
||||
control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
|
||||
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
|
||||
control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_VECTOR_CTRL,
|
||||
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
|
||||
|
||||
qvirtio_pci_queue_select(&d->vdev, vqpci->vq.index);
|
||||
qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR, entry);
|
||||
vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_QUEUE_VECTOR);
|
||||
qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR, entry);
|
||||
vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_QUEUE_VECTOR);
|
||||
g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
|
||||
}
|
||||
|
||||
@ -355,10 +356,10 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
|
||||
{
|
||||
uint16_t vector;
|
||||
uint32_t control;
|
||||
void *addr;
|
||||
uint64_t off;
|
||||
|
||||
g_assert(d->pdev->msix_enabled);
|
||||
addr = d->pdev->msix_table + (entry * 16);
|
||||
off = d->pdev->msix_table_off + (entry * 16);
|
||||
|
||||
g_assert_cmpint(entry, >=, 0);
|
||||
g_assert_cmpint(entry, <, qpci_msix_table_size(d->pdev));
|
||||
@ -367,17 +368,21 @@ void qvirtio_pci_set_msix_configuration_vector(QVirtioPCIDevice *d,
|
||||
d->config_msix_data = 0x12345678;
|
||||
d->config_msix_addr = guest_alloc(alloc, 4);
|
||||
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_LOWER_ADDR,
|
||||
d->config_msix_addr & ~0UL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_UPPER_ADDR,
|
||||
(d->config_msix_addr >> 32) & ~0UL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_LOWER_ADDR, d->config_msix_addr & ~0UL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_UPPER_ADDR,
|
||||
(d->config_msix_addr >> 32) & ~0UL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_DATA, d->config_msix_data);
|
||||
|
||||
control = qpci_io_readl(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
||||
qpci_io_writel(d->pdev, addr + PCI_MSIX_ENTRY_VECTOR_CTRL,
|
||||
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
|
||||
control = qpci_io_readl(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
||||
qpci_io_writel(d->pdev, d->pdev->msix_table_bar,
|
||||
off + PCI_MSIX_ENTRY_VECTOR_CTRL,
|
||||
control & ~PCI_MSIX_ENTRY_CTRL_MASKBIT);
|
||||
|
||||
qpci_io_writew(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR, entry);
|
||||
vector = qpci_io_readw(d->pdev, d->addr + VIRTIO_MSI_CONFIG_VECTOR);
|
||||
qpci_io_writew(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR, entry);
|
||||
vector = qpci_io_readw(d->pdev, d->bar, VIRTIO_MSI_CONFIG_VECTOR);
|
||||
g_assert_cmphex(vector, !=, VIRTIO_MSI_NO_VECTOR);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
typedef struct QVirtioPCIDevice {
|
||||
QVirtioDevice vdev;
|
||||
QPCIDevice *pdev;
|
||||
void *addr;
|
||||
QPCIBar bar;
|
||||
uint16_t config_msix_entry;
|
||||
uint64_t config_msix_addr;
|
||||
uint32_t config_msix_data;
|
||||
|
@ -22,7 +22,7 @@ static void nop(void)
|
||||
|
||||
static QPCIBus *pcibus;
|
||||
static QPCIDevice *dev;
|
||||
static void *dev_base;
|
||||
static QPCIBar dev_bar;
|
||||
|
||||
static void save_fn(QPCIDevice *dev, int devfn, void *data)
|
||||
{
|
||||
@ -45,14 +45,14 @@ static QPCIDevice *get_device(void)
|
||||
#define PORT(name, len, val) \
|
||||
static unsigned __attribute__((unused)) in_##name(void) \
|
||||
{ \
|
||||
unsigned res = qpci_io_read##len(dev, dev_base+(val)); \
|
||||
unsigned res = qpci_io_read##len(dev, dev_bar, (val)); \
|
||||
g_test_message("*%s -> %x\n", #name, res); \
|
||||
return res; \
|
||||
} \
|
||||
static void out_##name(unsigned v) \
|
||||
{ \
|
||||
g_test_message("%x -> *%s\n", v, #name); \
|
||||
qpci_io_write##len(dev, dev_base+(val), v); \
|
||||
qpci_io_write##len(dev, dev_bar, (val), v); \
|
||||
}
|
||||
|
||||
PORT(Timer, l, 0x48)
|
||||
@ -186,9 +186,7 @@ static void test_init(void)
|
||||
|
||||
dev = get_device();
|
||||
|
||||
dev_base = qpci_iomap(dev, 0, &barsize);
|
||||
|
||||
g_assert(dev_base != NULL);
|
||||
dev_bar = qpci_iomap(dev, 0, &barsize);
|
||||
|
||||
qpci_device_enable(dev);
|
||||
|
||||
|
@ -41,7 +41,7 @@ typedef struct {
|
||||
const char *args;
|
||||
bool noreboot;
|
||||
QPCIDevice *dev;
|
||||
void *tco_io_base;
|
||||
QPCIBar tco_io_bar;
|
||||
} TestData;
|
||||
|
||||
static void test_init(TestData *d)
|
||||
@ -70,42 +70,42 @@ static void test_init(TestData *d)
|
||||
/* set Root Complex BAR */
|
||||
qpci_config_writel(d->dev, ICH9_LPC_RCBA, RCBA_BASE_ADDR | 0x1);
|
||||
|
||||
d->tco_io_base = qpci_legacy_iomap(d->dev, PM_IO_BASE_ADDR + 0x60);
|
||||
d->tco_io_bar = qpci_legacy_iomap(d->dev, PM_IO_BASE_ADDR + 0x60);
|
||||
}
|
||||
|
||||
static void stop_tco(const TestData *d)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = qpci_io_readw(d->dev, d->tco_io_base + TCO1_CNT);
|
||||
val = qpci_io_readw(d->dev, d->tco_io_bar, TCO1_CNT);
|
||||
val |= TCO_TMR_HLT;
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO1_CNT, val);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO1_CNT, val);
|
||||
}
|
||||
|
||||
static void start_tco(const TestData *d)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = qpci_io_readw(d->dev, d->tco_io_base + TCO1_CNT);
|
||||
val = qpci_io_readw(d->dev, d->tco_io_bar, TCO1_CNT);
|
||||
val &= ~TCO_TMR_HLT;
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO1_CNT, val);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO1_CNT, val);
|
||||
}
|
||||
|
||||
static void load_tco(const TestData *d)
|
||||
{
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO_RLD, 4);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO_RLD, 4);
|
||||
}
|
||||
|
||||
static void set_tco_timeout(const TestData *d, uint16_t ticks)
|
||||
{
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO_TMR, ticks);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO_TMR, ticks);
|
||||
}
|
||||
|
||||
static void clear_tco_status(const TestData *d)
|
||||
{
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO1_STS, 0x0008);
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO2_STS, 0x0002);
|
||||
qpci_io_writew(d->dev, d->tco_io_base + TCO2_STS, 0x0004);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO1_STS, 0x0008);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO2_STS, 0x0002);
|
||||
qpci_io_writew(d->dev, d->tco_io_bar, TCO2_STS, 0x0004);
|
||||
}
|
||||
|
||||
static void reset_on_second_timeout(bool enable)
|
||||
@ -128,25 +128,25 @@ static void test_tco_defaults(void)
|
||||
d.args = NULL;
|
||||
d.noreboot = true;
|
||||
test_init(&d);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD), ==,
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD), ==,
|
||||
TCO_RLD_DEFAULT);
|
||||
/* TCO_DAT_IN & TCO_DAT_OUT */
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_DAT_IN), ==,
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_DAT_IN), ==,
|
||||
(TCO_DAT_OUT_DEFAULT << 8) | TCO_DAT_IN_DEFAULT);
|
||||
/* TCO1_STS & TCO2_STS */
|
||||
g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_base + TCO1_STS), ==,
|
||||
g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_bar, TCO1_STS), ==,
|
||||
(TCO2_STS_DEFAULT << 16) | TCO1_STS_DEFAULT);
|
||||
/* TCO1_CNT & TCO2_CNT */
|
||||
g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_base + TCO1_CNT), ==,
|
||||
g_assert_cmpint(qpci_io_readl(d.dev, d.tco_io_bar, TCO1_CNT), ==,
|
||||
(TCO2_CNT_DEFAULT << 16) | TCO1_CNT_DEFAULT);
|
||||
/* TCO_MESSAGE1 & TCO_MESSAGE2 */
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_MESSAGE1), ==,
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_MESSAGE1), ==,
|
||||
(TCO_MESSAGE2_DEFAULT << 8) | TCO_MESSAGE1_DEFAULT);
|
||||
g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_base + TCO_WDCNT), ==,
|
||||
g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_bar, TCO_WDCNT), ==,
|
||||
TCO_WDCNT_DEFAULT);
|
||||
g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_base + SW_IRQ_GEN), ==,
|
||||
g_assert_cmpint(qpci_io_readb(d.dev, d.tco_io_bar, SW_IRQ_GEN), ==,
|
||||
SW_IRQ_GEN_DEFAULT);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO_TMR), ==,
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO_TMR), ==,
|
||||
TCO_TMR_DEFAULT);
|
||||
qtest_end();
|
||||
}
|
||||
@ -171,23 +171,23 @@ static void test_tco_timeout(void)
|
||||
clock_step(ticks * TCO_TICK_NSEC);
|
||||
|
||||
/* test first timeout */
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & TCO_TIMEOUT ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
|
||||
/* test clearing timeout bit */
|
||||
val |= TCO_TIMEOUT;
|
||||
qpci_io_writew(d.dev, d.tco_io_base + TCO1_STS, val);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
qpci_io_writew(d.dev, d.tco_io_bar, TCO1_STS, val);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & TCO_TIMEOUT ? 1 : 0;
|
||||
g_assert(ret == 0);
|
||||
|
||||
/* test second timeout */
|
||||
clock_step(ticks * TCO_TICK_NSEC);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & TCO_TIMEOUT ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS);
|
||||
ret = val & TCO_SECOND_TO_STS ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
|
||||
@ -214,13 +214,13 @@ static void test_tco_max_timeout(void)
|
||||
start_tco(&d);
|
||||
clock_step(((ticks & TCO_TMR_MASK) - 1) * TCO_TICK_NSEC);
|
||||
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD);
|
||||
g_assert_cmpint(val & TCO_RLD_MASK, ==, 1);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & TCO_TIMEOUT ? 1 : 0;
|
||||
g_assert(ret == 0);
|
||||
clock_step(TCO_TICK_NSEC);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & TCO_TIMEOUT ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
|
||||
@ -358,11 +358,11 @@ static void test_tco_ticks_counter(void)
|
||||
start_tco(&d);
|
||||
|
||||
do {
|
||||
rld = qpci_io_readw(d.dev, d.tco_io_base + TCO_RLD) & TCO_RLD_MASK;
|
||||
rld = qpci_io_readw(d.dev, d.tco_io_bar, TCO_RLD) & TCO_RLD_MASK;
|
||||
g_assert_cmpint(rld, ==, ticks);
|
||||
clock_step(TCO_TICK_NSEC);
|
||||
ticks--;
|
||||
} while (!(qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS) & TCO_TIMEOUT));
|
||||
} while (!(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS) & TCO_TIMEOUT));
|
||||
|
||||
stop_tco(&d);
|
||||
qtest_end();
|
||||
@ -378,10 +378,10 @@ static void test_tco1_control_bits(void)
|
||||
test_init(&d);
|
||||
|
||||
val = TCO_LOCK;
|
||||
qpci_io_writew(d.dev, d.tco_io_base + TCO1_CNT, val);
|
||||
qpci_io_writew(d.dev, d.tco_io_bar, TCO1_CNT, val);
|
||||
val &= ~TCO_LOCK;
|
||||
qpci_io_writew(d.dev, d.tco_io_base + TCO1_CNT, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO1_CNT), ==,
|
||||
qpci_io_writew(d.dev, d.tco_io_bar, TCO1_CNT, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_CNT), ==,
|
||||
TCO_LOCK);
|
||||
qtest_end();
|
||||
}
|
||||
@ -405,13 +405,13 @@ static void test_tco1_status_bits(void)
|
||||
start_tco(&d);
|
||||
clock_step(ticks * TCO_TICK_NSEC);
|
||||
|
||||
qpci_io_writeb(d.dev, d.tco_io_base + TCO_DAT_IN, 0);
|
||||
qpci_io_writeb(d.dev, d.tco_io_base + TCO_DAT_OUT, 0);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS);
|
||||
qpci_io_writeb(d.dev, d.tco_io_bar, TCO_DAT_IN, 0);
|
||||
qpci_io_writeb(d.dev, d.tco_io_bar, TCO_DAT_OUT, 0);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS);
|
||||
ret = val & (TCO_TIMEOUT | SW_TCO_SMI | TCO_INT_STS) ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
qpci_io_writew(d.dev, d.tco_io_base + TCO1_STS, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO1_STS), ==, 0);
|
||||
qpci_io_writew(d.dev, d.tco_io_bar, TCO1_STS, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO1_STS), ==, 0);
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
@ -434,11 +434,11 @@ static void test_tco2_status_bits(void)
|
||||
start_tco(&d);
|
||||
clock_step(ticks * TCO_TICK_NSEC * 2);
|
||||
|
||||
val = qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS);
|
||||
val = qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS);
|
||||
ret = val & (TCO_SECOND_TO_STS | TCO_BOOT_STS) ? 1 : 0;
|
||||
g_assert(ret == 1);
|
||||
qpci_io_writew(d.dev, d.tco_io_base + TCO2_STS, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_base + TCO2_STS), ==, 0);
|
||||
qpci_io_writew(d.dev, d.tco_io_bar, TCO2_STS, val);
|
||||
g_assert_cmpint(qpci_io_readw(d.dev, d.tco_io_bar, TCO2_STS), ==, 0);
|
||||
qtest_end();
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,7 @@ static void uhci_port_update(struct qhc *hc, int port,
|
||||
|
||||
static void ehci_port_test(struct qhc *hc, int port, uint32_t expect)
|
||||
{
|
||||
void *addr = hc->base + 0x64 + 4 * port;
|
||||
uint32_t value = qpci_io_readl(hc->dev, addr);
|
||||
uint32_t value = qpci_io_readl(hc->dev, hc->bar, 0x64 + 4 * port);
|
||||
uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC);
|
||||
|
||||
#if 0
|
||||
@ -91,7 +90,7 @@ static void pci_ehci_port_1(void)
|
||||
static void pci_ehci_config(void)
|
||||
{
|
||||
/* hands over all ports from companion uhci to ehci */
|
||||
qpci_io_writew(ehci1.dev, ehci1.base + 0x60, 1);
|
||||
qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1);
|
||||
}
|
||||
|
||||
static void pci_uhci_port_2(void)
|
||||
|
Loading…
Reference in New Issue
Block a user