diff --git a/MAINTAINERS b/MAINTAINERS index 04beb34e7e..36055f14c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1772,6 +1772,7 @@ F: include/hw/scsi/* F: hw/scsi/* F: tests/qtest/virtio-scsi-test.c F: tests/qtest/fuzz-virtio-scsi-test.c +F: tests/qtest/am53c974-test.c T: git https://github.com/bonzini/qemu.git scsi-next SSI diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index c3d3dab05e..9db10b1a48 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -332,6 +332,7 @@ static const VMStateDescription vmstate_esp_pci_scsi = { .name = "pciespscsi", .version_id = 2, .minimum_version_id = 1, + .pre_save = esp_pre_save, .fields = (VMStateField[]) { VMSTATE_PCI_DEVICE(parent_obj, PCIESPState), VMSTATE_BUFFER_UNSAFE(dma_regs, PCIESPState, 0, 8 * sizeof(uint32_t)), diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 507ab363bc..b668acef82 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -95,45 +95,44 @@ void esp_request_cancelled(SCSIRequest *req) scsi_req_unref(s->current_req); s->current_req = NULL; s->current_dev = NULL; + s->async_len = 0; } } -static void esp_fifo_push(ESPState *s, uint8_t val) +static void esp_fifo_push(Fifo8 *fifo, uint8_t val) { - if (fifo8_num_used(&s->fifo) == ESP_FIFO_SZ) { + if (fifo8_num_used(fifo) == fifo->capacity) { trace_esp_error_fifo_overrun(); return; } - fifo8_push(&s->fifo, val); + fifo8_push(fifo, val); } -static uint8_t esp_fifo_pop(ESPState *s) +static uint8_t esp_fifo_pop(Fifo8 *fifo) { - if (fifo8_is_empty(&s->fifo)) { + if (fifo8_is_empty(fifo)) { return 0; } - return fifo8_pop(&s->fifo); + return fifo8_pop(fifo); } -static void esp_cmdfifo_push(ESPState *s, uint8_t val) +static uint32_t esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen) { - if (fifo8_num_used(&s->cmdfifo) == ESP_CMDFIFO_SZ) { - trace_esp_error_fifo_overrun(); - return; - } + const uint8_t *buf; + uint32_t n; - fifo8_push(&s->cmdfifo, val); -} - -static uint8_t esp_cmdfifo_pop(ESPState *s) -{ - if (fifo8_is_empty(&s->cmdfifo)) { + if (maxlen == 0) { return 0; } - return fifo8_pop(&s->cmdfifo); + buf = fifo8_pop_buf(fifo, maxlen, &n); + if (dest) { + memcpy(dest, buf, n); + } + + return n; } static uint32_t esp_get_tc(ESPState *s) @@ -170,9 +169,9 @@ static uint8_t esp_pdma_read(ESPState *s) uint8_t val; if (s->do_cmd) { - val = esp_cmdfifo_pop(s); + val = esp_fifo_pop(&s->cmdfifo); } else { - val = esp_fifo_pop(s); + val = esp_fifo_pop(&s->fifo); } return val; @@ -187,9 +186,9 @@ static void esp_pdma_write(ESPState *s, uint8_t val) } if (s->do_cmd) { - esp_cmdfifo_push(s, val); + esp_fifo_push(&s->cmdfifo, val); } else { - esp_fifo_push(s, val); + esp_fifo_push(&s->fifo, val); } dmalen--; @@ -208,7 +207,6 @@ static int esp_select(ESPState *s) if (s->current_req) { /* Started a new command before the old one finished. Cancel it. */ scsi_req_cancel(s->current_req); - s->async_len = 0; } s->current_dev = scsi_device_find(&s->bus, 0, target, 0); @@ -245,6 +243,7 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen) } if (s->dma_memory_read) { s->dma_memory_read(s->dma_opaque, buf, dmalen); + dmalen = MIN(fifo8_num_free(&s->cmdfifo), dmalen); fifo8_push_all(&s->cmdfifo, buf, dmalen); } else { if (esp_select(s) < 0) { @@ -260,11 +259,12 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen) if (dmalen == 0) { return 0; } - memcpy(buf, fifo8_pop_buf(&s->fifo, dmalen, &n), dmalen); - if (dmalen >= 3) { + n = esp_fifo_pop_buf(&s->fifo, buf, dmalen); + if (n >= 3) { buf[0] = buf[2] >> 5; } - fifo8_push_all(&s->cmdfifo, buf, dmalen); + n = MIN(fifo8_num_free(&s->cmdfifo), n); + fifo8_push_all(&s->cmdfifo, buf, n); } trace_esp_get_cmd(dmalen, target); @@ -277,16 +277,19 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen) static void do_busid_cmd(ESPState *s, uint8_t busid) { - uint32_t n, cmdlen; + uint32_t cmdlen; int32_t datalen; int lun; SCSIDevice *current_lun; - uint8_t *buf; + uint8_t buf[ESP_CMDFIFO_SZ]; trace_esp_do_busid_cmd(busid); lun = busid & 7; cmdlen = fifo8_num_used(&s->cmdfifo); - buf = (uint8_t *)fifo8_pop_buf(&s->cmdfifo, cmdlen, &n); + if (!cmdlen || !s->current_dev) { + return; + } + esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen); current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun); s->current_req = scsi_req_new(current_lun, 0, lun, buf, s); @@ -318,14 +321,15 @@ static void do_busid_cmd(ESPState *s, uint8_t busid) static void do_cmd(ESPState *s) { - uint8_t busid = fifo8_pop(&s->cmdfifo); - uint32_t n; + uint8_t busid = esp_fifo_pop(&s->cmdfifo); + int len; s->cmdfifo_cdb_offset--; /* Ignore extended messages for now */ if (s->cmdfifo_cdb_offset) { - fifo8_pop_buf(&s->cmdfifo, s->cmdfifo_cdb_offset, &n); + len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo)); + esp_fifo_pop_buf(&s->cmdfifo, NULL, len); s->cmdfifo_cdb_offset = 0; } @@ -353,6 +357,7 @@ static void handle_satn(ESPState *s) cmdlen = get_cmd(s, ESP_CMDFIFO_SZ); if (cmdlen > 0) { s->cmdfifo_cdb_offset = 1; + s->do_cmd = 0; do_cmd(s); } else if (cmdlen == 0) { s->do_cmd = 1; @@ -386,6 +391,7 @@ static void handle_s_without_atn(ESPState *s) cmdlen = get_cmd(s, ESP_CMDFIFO_SZ); if (cmdlen > 0) { s->cmdfifo_cdb_offset = 0; + s->do_cmd = 0; do_busid_cmd(s, 0); } else if (cmdlen == 0) { s->do_cmd = 1; @@ -445,18 +451,16 @@ static void write_response_pdma_cb(ESPState *s) static void write_response(ESPState *s) { - uint32_t n; + uint8_t buf[2]; trace_esp_write_response(s->status); - fifo8_reset(&s->fifo); - esp_fifo_push(s, s->status); - esp_fifo_push(s, 0); + buf[0] = s->status; + buf[1] = 0; if (s->dma) { if (s->dma_memory_write) { - s->dma_memory_write(s->dma_opaque, - (uint8_t *)fifo8_pop_buf(&s->fifo, 2, &n), 2); + s->dma_memory_write(s->dma_opaque, buf, 2); s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; s->rregs[ESP_RINTR] |= INTR_BS | INTR_FC; s->rregs[ESP_RSEQ] = SEQ_CD; @@ -466,7 +470,8 @@ static void write_response(ESPState *s) return; } } else { - s->ti_size = 2; + fifo8_reset(&s->fifo); + fifo8_push_all(&s->fifo, buf, 2); s->rregs[ESP_RFLAGS] = 2; } esp_raise_irq(s); @@ -496,11 +501,15 @@ static void do_dma_pdma_cb(ESPState *s) return; } + if (!s->current_req) { + return; + } + if (to_device) { /* Copy FIFO data to device */ len = MIN(s->async_len, ESP_FIFO_SZ); len = MIN(len, fifo8_num_used(&s->fifo)); - memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len); + n = esp_fifo_pop_buf(&s->fifo, s->async_buf, len); s->async_buf += n; s->async_len -= n; s->ti_size += n; @@ -508,7 +517,7 @@ static void do_dma_pdma_cb(ESPState *s) if (n < len) { /* Unaligned accesses can cause FIFO wraparound */ len = len - n; - memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len); + n = esp_fifo_pop_buf(&s->fifo, s->async_buf, len); s->async_buf += n; s->async_len -= n; s->ti_size += n; @@ -527,11 +536,9 @@ static void do_dma_pdma_cb(ESPState *s) return; } else { if (s->async_len == 0) { - if (s->current_req) { - /* Defer until the scsi layer has completed */ - scsi_req_continue(s->current_req); - s->data_in_ready = false; - } + /* Defer until the scsi layer has completed */ + scsi_req_continue(s->current_req); + s->data_in_ready = false; return; } @@ -573,6 +580,7 @@ static void esp_do_dma(ESPState *s) cmdlen = fifo8_num_used(&s->cmdfifo); trace_esp_do_dma(cmdlen, len); if (s->dma_memory_read) { + len = MIN(len, fifo8_num_free(&s->cmdfifo)); s->dma_memory_read(s->dma_opaque, buf, len); fifo8_push_all(&s->cmdfifo, buf, len); } else { @@ -604,6 +612,9 @@ static void esp_do_dma(ESPState *s) } return; } + if (!s->current_req) { + return; + } if (s->async_len == 0) { /* Defer until data is available. */ return; @@ -641,7 +652,7 @@ static void esp_do_dma(ESPState *s) */ if (len < esp_get_tc(s) && esp_get_tc(s) <= ESP_FIFO_SZ) { while (fifo8_num_used(&s->fifo) < ESP_FIFO_SZ) { - esp_fifo_push(s, 0); + esp_fifo_push(&s->fifo, 0); len++; } } @@ -683,7 +694,7 @@ static void esp_do_dma(ESPState *s) static void esp_do_nodma(ESPState *s) { int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO); - uint32_t cmdlen, n; + uint32_t cmdlen; int len; if (s->do_cmd) { @@ -713,6 +724,10 @@ static void esp_do_nodma(ESPState *s) return; } + if (!s->current_req) { + return; + } + if (s->async_len == 0) { /* Defer until data is available. */ return; @@ -720,7 +735,7 @@ static void esp_do_nodma(ESPState *s) if (to_device) { len = MIN(fifo8_num_used(&s->fifo), ESP_FIFO_SZ); - memcpy(s->async_buf, fifo8_pop_buf(&s->fifo, len, &n), len); + esp_fifo_pop_buf(&s->fifo, s->async_buf, len); s->async_buf += len; s->async_len -= len; s->ti_size += len; @@ -890,7 +905,7 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr) qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n"); s->rregs[ESP_FIFO] = 0; } else { - s->rregs[ESP_FIFO] = esp_fifo_pop(s); + s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo); } val = s->rregs[ESP_FIFO]; break; @@ -939,9 +954,9 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) break; case ESP_FIFO: if (s->do_cmd) { - esp_cmdfifo_push(s, val); + esp_fifo_push(&s->cmdfifo, val); } else { - esp_fifo_push(s, val); + esp_fifo_push(&s->fifo, val); } /* Non-DMA transfers raise an interrupt after every byte */ @@ -1076,9 +1091,10 @@ static bool esp_is_version_5(void *opaque, int version_id) return version_id == 5; } -static int esp_pre_save(void *opaque) +int esp_pre_save(void *opaque) { - ESPState *s = ESP(opaque); + ESPState *s = ESP(object_resolve_path_component( + OBJECT(opaque), "esp")); s->mig_version_id = vmstate_esp.version_id; return 0; @@ -1114,7 +1130,6 @@ const VMStateDescription vmstate_esp = { .name = "esp", .version_id = 5, .minimum_version_id = 3, - .pre_save = esp_pre_save, .post_load = esp_post_load, .fields = (VMStateField[]) { VMSTATE_BUFFER(rregs, ESPState), @@ -1304,6 +1319,7 @@ static const VMStateDescription vmstate_sysbus_esp_scsi = { .name = "sysbusespscsi", .version_id = 2, .minimum_version_id = 1, + .pre_save = esp_pre_save, .fields = (VMStateField[]) { VMSTATE_UINT8_V(esp.mig_version_id, SysBusESPState, 2), VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState), diff --git a/include/hw/scsi/esp.h b/include/hw/scsi/esp.h index 95088490aa..aada3680b7 100644 --- a/include/hw/scsi/esp.h +++ b/include/hw/scsi/esp.h @@ -157,5 +157,6 @@ void esp_hard_reset(ESPState *s); uint64_t esp_reg_read(ESPState *s, uint32_t saddr); void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val); extern const VMStateDescription vmstate_esp; +int esp_pre_save(void *opaque); #endif diff --git a/tests/qtest/am53c974-test.c b/tests/qtest/am53c974-test.c new file mode 100644 index 0000000000..d996866cd4 --- /dev/null +++ b/tests/qtest/am53c974-test.c @@ -0,0 +1,218 @@ +/* + * QTest testcase for am53c974 + * + * Copyright (c) 2021 Mark Cave-Ayland + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * later. See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "libqos/libqtest.h" + + +static void test_cmdfifo_underflow_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outl(s, 0xcf8, 0x8000100e); + qtest_outl(s, 0xcfc, 0x8a000000); + qtest_outl(s, 0x8a09, 0x42000000); + qtest_outl(s, 0x8a0d, 0x00); + qtest_outl(s, 0x8a0b, 0x1000); + qtest_quit(s); +} + +/* Reported as crash_1548bd10e7 */ +static void test_cmdfifo_underflow2_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi -device scsi-hd,drive=disk0 " + "-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outw(s, 0xc00c, 0x41); + qtest_outw(s, 0xc00a, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00c, 0x43); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00c, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00a, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00c, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00a, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00c, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00a, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00c, 0x00); + qtest_outl(s, 0xc00a, 0x00); + qtest_outl(s, 0xc006, 0x00); + qtest_outl(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x0800); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x00); + qtest_outl(s, 0xc006, 0x00); + qtest_outl(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x0800); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x4100); + qtest_outw(s, 0xc00a, 0x00); + qtest_outl(s, 0xc00a, 0x100000); + qtest_outl(s, 0xc00a, 0x00); + qtest_outw(s, 0xc00c, 0x43); + qtest_outl(s, 0xc00a, 0x100000); + qtest_outl(s, 0xc00a, 0x100000); + qtest_quit(s); +} + +static void test_cmdfifo_overflow_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outl(s, 0xcf8, 0x8000100e); + qtest_outl(s, 0xcfc, 0x0e000000); + qtest_outl(s, 0xe40, 0x03); + qtest_outl(s, 0xe0b, 0x4100); + qtest_outl(s, 0xe0b, 0x9000); + qtest_quit(s); +} + +/* Reported as crash_530ff2e211 */ +static void test_cmdfifo_overflow2_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi -device scsi-hd,drive=disk0 " + "-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outl(s, 0xc00b, 0x4100); + qtest_outw(s, 0xc00b, 0xc200); + qtest_outl(s, 0xc03f, 0x0300); + qtest_quit(s); +} + +/* Reported as crash_0900379669 */ +static void test_fifo_pop_buf(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi -device scsi-hd,drive=disk0 " + "-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outb(s, 0xc000, 0x4); + qtest_outb(s, 0xc008, 0xa0); + qtest_outl(s, 0xc03f, 0x0300); + qtest_outl(s, 0xc00b, 0xc300); + qtest_outw(s, 0xc00b, 0x9000); + qtest_outl(s, 0xc00b, 0xc300); + qtest_outl(s, 0xc00b, 0xc300); + qtest_outl(s, 0xc00b, 0xc300); + qtest_outw(s, 0xc00b, 0x9000); + qtest_outw(s, 0xc00b, 0x1000); + qtest_quit(s); +} + +static void test_target_selected_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001001); + qtest_outl(s, 0xcfc, 0x01000000); + qtest_outl(s, 0xcf8, 0x8000100e); + qtest_outl(s, 0xcfc, 0xef800000); + qtest_outl(s, 0xef8b, 0x4100); + qtest_outw(s, 0xef80, 0x01); + qtest_outl(s, 0xefc0, 0x03); + qtest_outl(s, 0xef8b, 0xc100); + qtest_outl(s, 0xef8b, 0x9000); + qtest_quit(s); +} + +static void test_fifo_underflow_on_write_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outl(s, 0xc008, 0x0a); + qtest_outl(s, 0xc009, 0x41000000); + qtest_outl(s, 0xc009, 0x41000000); + qtest_outl(s, 0xc00b, 0x1000); + qtest_quit(s); +} + +static void test_cancelled_request_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x05); + qtest_outb(s, 0xc046, 0x02); + qtest_outl(s, 0xc00b, 0xc100); + qtest_outl(s, 0xc040, 0x03); + qtest_outl(s, 0xc040, 0x03); + qtest_bufwrite(s, 0x0, "\x41", 0x1); + qtest_outl(s, 0xc00b, 0xc100); + qtest_outw(s, 0xc040, 0x02); + qtest_outw(s, 0xc040, 0x81); + qtest_outl(s, 0xc00b, 0x9000); + qtest_quit(s); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0) { + qtest_add_func("am53c974/test_cmdfifo_underflow_ok", + test_cmdfifo_underflow_ok); + qtest_add_func("am53c974/test_cmdfifo_underflow2_ok", + test_cmdfifo_underflow2_ok); + qtest_add_func("am53c974/test_cmdfifo_overflow_ok", + test_cmdfifo_overflow_ok); + qtest_add_func("am53c974/test_cmdfifo_overflow2_ok", + test_cmdfifo_overflow2_ok); + qtest_add_func("am53c974/test_fifo_pop_buf", + test_fifo_pop_buf); + qtest_add_func("am53c974/test_target_selected_ok", + test_target_selected_ok); + qtest_add_func("am53c974/test_fifo_underflow_on_write_ok", + test_fifo_underflow_on_write_ok); + qtest_add_func("am53c974/test_cancelled_request_ok", + test_cancelled_request_ok); + } + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 420cd9986e..0c76738921 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -65,6 +65,7 @@ qtests_i386 = \ (config_all_devices.has_key('CONFIG_TPM_TIS_ISA') ? ['tpm-tis-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['rtl8139-test'] : []) + \ (config_all_devices.has_key('CONFIG_E1000E_PCI_EXPRESS') ? ['fuzz-e1000e-test'] : []) + \ + (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \ qtests_pci + \ ['fdc-test', 'ide-test',