tests/qtest/ahci: cover raw (2352-byte) ATAPI CD reads
Add /ahci/cdrom/{pio,dma}/raw: read several sectors with READ CD in raw mode (atapi_raw), so the ATAPI 2352-byte unpack path is exercised through the AHCI delivery, which IDE coverage does not reach. Each sector's 2048-byte payload is verified at its in-sector offset. The PIO case uses a byte-count limit of one raw sector per DRQ burst: libqos asserts a one-sector PIO transfer, and the multi-sector unpack loop is already covered by the IDE raw test. Signed-off-by: Denis V. Lunev <den@openvz.org>
Denis V. Lunev committed
Jun 19, 2026 at 02:29 UTC
31f13e71afd1cfb55b02c6977c829f0813ab439c
1 file changed
+68
tests/qtest/ahci-test.c
+68
@@ -1565,6 +1565,31 @@ static int ahci_cb_cmp_buff(AHCIQState *ahci, AHCICommand *cmd,
1565
return 0;
1566
}
1567
1568
+static int ahci_cb_cmp_raw(AHCIQState *ahci, AHCICommand *cmd,
1569
+ const AHCIOpts *opts)
1570
+{
1571
+ unsigned char *tx = opts->opaque;
1572
+ unsigned char *rx;
1573
+ unsigned i, nsectors;
1574
+
1575
+ if (!opts->size) {
1576
+ return 0;
1577
+ }
1578
+
1579
+ nsectors = opts->size / ATAPI_RAW_SECTOR_SIZE;
1580
+ rx = g_malloc0(opts->size);
1581
+ qtest_bufread(ahci->parent->qts, opts->buffer, rx, opts->size);
1582
+ /* Each raw sector carries its 2048-byte payload past a 16-byte header. */
1583
+ for (i = 0; i < nsectors; i++) {
1584
+ g_assert_cmphex(memcmp(rx + i * ATAPI_RAW_SECTOR_SIZE + 16,
1585
+ tx + i * ATAPI_SECTOR_SIZE,
1586
+ ATAPI_SECTOR_SIZE), ==, 0);
1587
+ }
1588
+ g_free(rx);
1589
+
1590
+ return 0;
1591
+}
1592
+
1593
static void ahci_test_cdrom(int nsectors, bool dma, uint8_t cmd,
1594
bool override_bcl, uint16_t bcl)
1595
{
@@ -1625,6 +1650,47 @@ static void test_cdrom_pio_multi(void)
1650
ahci_test_cdrom_read10(3, false);
1651
}
1652
1653
+static void ahci_test_cdrom_raw(int nsectors, bool dma)
1654
+{
1655
+ AHCIQState *ahci;
1656
+ unsigned char *tx;
1657
+ char *iso;
1658
+ int fd;
1659
+ AHCIOpts opts = {
1660
+ .size = (uint64_t)ATAPI_RAW_SECTOR_SIZE * nsectors,
1661
+ .atapi = true,
1662
+ .atapi_dma = dma,
1663
+ .atapi_raw = true,
1664
+ .set_bcl = true,
1665
+ .bcl = ATAPI_RAW_SECTOR_SIZE, /* one raw sector per DRQ burst */
1666
+ .post_cb = ahci_cb_cmp_raw,
1667
+ };
1668
+ uint64_t iso_size = (uint64_t)ATAPI_SECTOR_SIZE * (nsectors + 1);
1669
+
1670
+ fd = prepare_iso(iso_size, &tx, &iso);
1671
+ opts.opaque = tx;
1672
+
1673
+ ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,format=raw "
1674
+ "-M q35 "
1675
+ "-device ide-cd,drive=drive0 ", iso);
1676
+
1677
+ ahci_exec(ahci, ahci_port_select(ahci), CMD_ATAPI_READ_CD, &opts);
1678
+
1679
+ g_free(tx);
1680
+ ahci_shutdown(ahci);
1681
+ remove_iso(fd, iso);
1682
+}
1683
+
1684
+static void test_cdrom_dma_raw(void)
1685
+{
1686
+ ahci_test_cdrom_raw(3, true);
1687
+}
1688
+
1689
+static void test_cdrom_pio_raw(void)
1690
+{
1691
+ ahci_test_cdrom_raw(3, false);
1692
+}
1693
+
1694
/*
1695
* Regression test: a buffered ATAPI read completing after a command
1696
* engine restart must not dereference the cleared cur_cmd. Cover both
@@ -2100,8 +2166,10 @@ int main(int argc, char **argv)
2166
2167
qtest_add_func("/ahci/cdrom/dma/single", test_cdrom_dma);
2168
qtest_add_func("/ahci/cdrom/dma/multi", test_cdrom_dma_multi);
2169
+ qtest_add_func("/ahci/cdrom/dma/raw", test_cdrom_dma_raw);
2170
qtest_add_func("/ahci/cdrom/pio/single", test_cdrom_pio);
2171
qtest_add_func("/ahci/cdrom/pio/multi", test_cdrom_pio_multi);
2172
+ qtest_add_func("/ahci/cdrom/pio/raw", test_cdrom_pio_raw);
2173
2174
qtest_add_func("/ahci/cdrom/pio/bcl", test_atapi_bcl);
2175
qtest_add_func("/ahci/cdrom/eject", test_atapi_tray);