aboutsummaryrefslogtreecommitdiff
path: root/tests/ide-test.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2013-03-13 13:30:24 +0100
committerKevin Wolf <kwolf@redhat.com>2013-05-08 15:28:49 +0200
commit948eaed171e0dac541a59b42867f80881399bbd0 (patch)
tree8b361db778c8b3ec6df3f6dcd5682120926cd6c1 /tests/ide-test.c
parentb95739dcf5ae1dfa8cd5b2a5be27d427835e693b (diff)
qtest/ide-test: Test short and long PRDTs
This tests the behaviour of the DMA engine when the given PRDT contains physical region descriptors for either more or less bytes than the IDE request is for. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'tests/ide-test.c')
-rw-r--r--tests/ide-test.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/ide-test.c b/tests/ide-test.c
index 5fc496fd0a..bdc1da7dfe 100644
--- a/tests/ide-test.c
+++ b/tests/ide-test.c
@@ -77,6 +77,8 @@ enum {
CMD_READ_DMA = 0xc8,
CMD_WRITE_DMA = 0xca,
CMD_IDENTIFY = 0xec,
+
+ CMDF_ABORT = 0x100,
};
enum {
@@ -170,9 +172,13 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
size_t len;
bool from_dev;
uint8_t status;
+ int flags;
dev = get_pci_device(&bmdma_base);
+ flags = cmd & ~0xff;
+ cmd &= 0xff;
+
switch (cmd) {
case CMD_READ_DMA:
from_dev = true;
@@ -209,6 +215,10 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
/* Start DMA transfer */
outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
+ if (flags & CMDF_ABORT) {
+ outb(bmdma_base + bmreg_cmd, 0);
+ }
+
/* Wait for the DMA transfer to complete */
do {
status = inb(bmdma_base + bmreg_status);
@@ -289,6 +299,48 @@ static void test_bmdma_simple_rw(void)
g_free(cmpbuf);
}
+static void test_bmdma_short_prdt(void)
+{
+ uint8_t status;
+
+ PrdtEntry prdt[] = {
+ { .addr = 0, .size = 0x10 | PRDT_EOT },
+ };
+
+ /* Normal request */
+ status = send_dma_request(CMD_READ_DMA, 0, 1,
+ prdt, ARRAY_SIZE(prdt));
+ g_assert_cmphex(status, ==, 0);
+ assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+
+ /* Abort the request before it completes */
+ status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1,
+ prdt, ARRAY_SIZE(prdt));
+ g_assert_cmphex(status, ==, 0);
+ assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+}
+
+static void test_bmdma_long_prdt(void)
+{
+ uint8_t status;
+
+ PrdtEntry prdt[] = {
+ { .addr = 0, .size = 0x1000 | PRDT_EOT },
+ };
+
+ /* Normal request */
+ status = send_dma_request(CMD_READ_DMA, 0, 1,
+ prdt, ARRAY_SIZE(prdt));
+ g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR);
+ assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+
+ /* Abort the request before it completes */
+ status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1,
+ prdt, ARRAY_SIZE(prdt));
+ g_assert_cmphex(status, ==, BM_STS_INTR);
+ assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
+}
+
static void test_bmdma_setup(void)
{
ide_test_start(
@@ -375,6 +427,8 @@ int main(int argc, char **argv)
qtest_add_func("/ide/bmdma/setup", test_bmdma_setup);
qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw);
+ qtest_add_func("/ide/bmdma/short_prdt", test_bmdma_short_prdt);
+ qtest_add_func("/ide/bmdma/long_prdt", test_bmdma_long_prdt);
qtest_add_func("/ide/bmdma/teardown", test_bmdma_teardown);
ret = g_test_run();