aboutsummaryrefslogtreecommitdiff
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
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>
-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();