@samitouri / QOSamiQemu / commits / ebec7c7322

tests/qtest/ide-test: parametrize the ATAPI CD-ROM read test

cdrom_pio_impl() and test_cdrom_dma() duplicate the same image setup and data-integrity check around two different transfer mechanisms. Fold them into a single cdrom_read_impl(nblocks, flags) helper, with a CDROM_PIO/CDROM_DMA flag selecting the transfer, so further read coverage can be added once for both paths. No functional change: /ide/cdrom/pio, pio_large and dma run exactly as before. Signed-off-by: Denis V. Lunev <den@openvz.org>

Denis V. Lunev committed Jun 19, 2026 at 02:25 UTC ebec7c73229831c6574c70fec3cc28c778566277
1 file changed +67 -78
tests/qtest/ide-test.c
+67 -78
@@ -1034,8 +1034,12 @@ static void ide_wait_intr(QTestState *qts, int irq)
1034 g_assert_not_reached();
1035 }
1036
1037 -static void cdrom_pio_impl(int nblocks)
1037 +#define CDROM_PIO 0
1038 +#define CDROM_DMA (1 << 0)
1039 +
1040 +static void cdrom_read_impl(int nblocks, unsigned flags)
1041 {
1042 + bool dma = flags & CDROM_DMA;
1043 QTestState *qts;
1044 QPCIDevice *dev;
1045 QPCIBar bmdma_bar, ide_bar;
@@ -1063,57 +1067,75 @@ static void cdrom_pio_impl(int nblocks)
1067 dev = get_pci_device(qts, &bmdma_bar, &ide_bar);
1068 qtest_irq_intercept_in(qts, "ioapic");
1069
1066 - /* PACKET command on device 0 */
1067 - qpci_io_writeb(dev, ide_bar, reg_device, 0);
1068 - qpci_io_writeb(dev, ide_bar, reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF);
1069 - qpci_io_writeb(dev, ide_bar, reg_lba_high, (BYTE_COUNT_LIMIT >> 8 & 0xFF));
1070 - qpci_io_writeb(dev, ide_bar, reg_command, CMD_PACKET);
1071 - /* HP0: Check_Status_A State */
1072 - nsleep(qts, 400);
1073 - data = ide_wait_clear(qts, BSY);
1074 - /* HP1: Send_Packet State */
1075 - assert_bit_set(data, DRQ | DRDY);
1076 - assert_bit_clear(data, ERR | DF | BSY);
1077 -
1078 - /* SCSI CDB (READ10) -- read n*2048 bytes from block 0 */
1079 - send_scsi_cdb_read10(dev, ide_bar, 0, nblocks);
1080 -
1081 - /* Read data back: occurs in bursts of 'BYTE_COUNT_LIMIT' bytes.
1082 - * If BYTE_COUNT_LIMIT is odd, we transfer BYTE_COUNT_LIMIT - 1 bytes.
1083 - * We allow an odd limit only when the remaining transfer size is
1084 - * less than BYTE_COUNT_LIMIT. However, SCSI's read10 command can only
1085 - * request n blocks, so our request size is always even.
1086 - * For this reason, we assume there is never a hanging byte to fetch. */
1087 - g_assert(!(rxsize & 1));
1088 - limit = BYTE_COUNT_LIMIT & ~1;
1089 - for (i = 0; i < DIV_ROUND_UP(rxsize, limit); i++) {
1090 - size_t offset = i * (limit / 2);
1091 - size_t rem = (rxsize / 2) - offset;
1092 -
1093 - /* HP3: INTRQ_Wait */
1094 - ide_wait_intr(qts, IDE_PRIMARY_IRQ);
1070 + if (dma) {
1071 + uintptr_t guest_buf = guest_alloc(&guest_malloc, rxsize);
1072 + PrdtEntry prdt[1];
1073 +
1074 + prdt[0].addr = cpu_to_le32(guest_buf);
1075 + prdt[0].size = cpu_to_le32(rxsize | PRDT_EOT);
1076 +
1077 + send_dma_request_dev(qts, dev, bmdma_bar, ide_bar, CMD_PACKET, 0,
1078 + nblocks, prdt, ARRAY_SIZE(prdt),
1079 + send_scsi_cdb_read10);
1080
1096 - /* HP2: Check_Status_B (and clear IRQ) */
1081 + qtest_memread(qts, guest_buf, rx, rxsize);
1082 + } else {
1083 + /* PACKET command on device 0 */
1084 + qpci_io_writeb(dev, ide_bar, reg_device, 0);
1085 + qpci_io_writeb(dev, ide_bar, reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF);
1086 + qpci_io_writeb(dev, ide_bar, reg_lba_high,
1087 + (BYTE_COUNT_LIMIT >> 8 & 0xFF));
1088 + qpci_io_writeb(dev, ide_bar, reg_command, CMD_PACKET);
1089 + /* HP0: Check_Status_A State */
1090 + nsleep(qts, 400);
1091 data = ide_wait_clear(qts, BSY);
1092 + /* HP1: Send_Packet State */
1093 assert_bit_set(data, DRQ | DRDY);
1094 assert_bit_clear(data, ERR | DF | BSY);
1095
1101 - /* HP4: Transfer_Data */
1102 - for (j = 0; j < MIN((limit / 2), rem); j++) {
1103 - rx[offset + j] = cpu_to_le16(qpci_io_readw(dev, ide_bar,
1104 - reg_data));
1096 + /* SCSI CDB (READ10) -- read n*2048 bytes from block 0 */
1097 + send_scsi_cdb_read10(dev, ide_bar, 0, nblocks);
1098 +
1099 + /*
1100 + * Read data back: occurs in bursts of 'BYTE_COUNT_LIMIT' bytes.
1101 + * If BYTE_COUNT_LIMIT is odd, we transfer BYTE_COUNT_LIMIT - 1 bytes.
1102 + * We allow an odd limit only when the remaining transfer size is
1103 + * less than BYTE_COUNT_LIMIT. However, SCSI's read10 command can only
1104 + * request n blocks, so our request size is always even.
1105 + * For this reason, we assume there is never a hanging byte to fetch.
1106 + */
1107 + g_assert(!(rxsize & 1));
1108 + limit = BYTE_COUNT_LIMIT & ~1;
1109 + for (i = 0; i < DIV_ROUND_UP(rxsize, limit); i++) {
1110 + size_t offset = i * (limit / 2);
1111 + size_t rem = (rxsize / 2) - offset;
1112 +
1113 + /* HP3: INTRQ_Wait */
1114 + ide_wait_intr(qts, IDE_PRIMARY_IRQ);
1115 +
1116 + /* HP2: Check_Status_B (and clear IRQ) */
1117 + data = ide_wait_clear(qts, BSY);
1118 + assert_bit_set(data, DRQ | DRDY);
1119 + assert_bit_clear(data, ERR | DF | BSY);
1120 +
1121 + /* HP4: Transfer_Data */
1122 + for (j = 0; j < MIN((limit / 2), rem); j++) {
1123 + rx[offset + j] = cpu_to_le16(qpci_io_readw(dev, ide_bar,
1124 + reg_data));
1125 + }
1126 }
1106 - }
1127
1108 - /* Check for final completion IRQ */
1109 - ide_wait_intr(qts, IDE_PRIMARY_IRQ);
1128 + /* Check for final completion IRQ */
1129 + ide_wait_intr(qts, IDE_PRIMARY_IRQ);
1130
1111 - /* Sanity check final state */
1112 - data = ide_wait_clear(qts, DRQ);
1113 - assert_bit_set(data, DRDY);
1114 - assert_bit_clear(data, DRQ | ERR | DF | BSY);
1131 + /* Sanity check final state */
1132 + data = ide_wait_clear(qts, DRQ);
1133 + assert_bit_set(data, DRDY);
1134 + assert_bit_clear(data, DRQ | ERR | DF | BSY);
1135 + }
1136
1137 g_assert_cmpint(memcmp(pattern, rx, rxsize), ==, 0);
1138 +
1139 g_free(pattern);
1140 g_free(rx);
1141 test_bmdma_teardown(qts);
@@ -1122,51 +1144,18 @@ static void cdrom_pio_impl(int nblocks)
1144
1145 static void test_cdrom_pio(void)
1146 {
1125 - cdrom_pio_impl(1);
1147 + cdrom_read_impl(1, CDROM_PIO);
1148 }
1149
1150 static void test_cdrom_pio_large(void)
1151 {
1152 /* Test a few loops of the PIO DRQ mechanism. */
1131 - cdrom_pio_impl(BYTE_COUNT_LIMIT * 4 / ATAPI_BLOCK_SIZE);
1153 + cdrom_read_impl(BYTE_COUNT_LIMIT * 4 / ATAPI_BLOCK_SIZE, CDROM_PIO);
1154 }
1155
1134 -
1156 static void test_cdrom_dma(void)
1157 {
1137 - QTestState *qts;
1138 - static const size_t len = ATAPI_BLOCK_SIZE;
1139 - size_t ret;
1140 - char *pattern = g_malloc(ATAPI_BLOCK_SIZE * 16);
1141 - char *rx = g_malloc0(len);
1142 - uintptr_t guest_buf;
1143 - PrdtEntry prdt[1];
1144 - FILE *fh;
1145 -
1146 - qts = ide_test_start(
1147 - "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
1148 - "-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]);
1149 - qtest_irq_intercept_in(qts, "ioapic");
1150 -
1151 - guest_buf = guest_alloc(&guest_malloc, len);
1152 - prdt[0].addr = cpu_to_le32(guest_buf);
1153 - prdt[0].size = cpu_to_le32(len | PRDT_EOT);
1154 -
1155 - generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE);
1156 - fh = fopen(tmp_path[0], "wb+");
1157 - ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh);
1158 - g_assert_cmpint(ret, ==, 16);
1159 - fclose(fh);
1160 -
1161 - send_dma_request(qts, CMD_PACKET, 0, 1, prdt, 1, send_scsi_cdb_read10);
1162 -
1163 - /* Read back data from guest memory into local qtest memory */
1164 - qtest_memread(qts, guest_buf, rx, len);
1165 - g_assert_cmpint(memcmp(pattern, rx, len), ==, 0);
1166 -
1167 - g_free(pattern);
1168 - g_free(rx);
1169 - test_bmdma_teardown(qts);
1158 + cdrom_read_impl(1, CDROM_DMA);
1159 }
1160
1161 int main(int argc, char **argv)