summaryrefslogtreecommitdiff
path: root/tests/fdc-test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fdc-test.c')
-rw-r--r--tests/fdc-test.c192
1 files changed, 187 insertions, 5 deletions
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index fa7441110d..4b0301da46 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -48,13 +48,17 @@ enum {
enum {
CMD_SENSE_INT = 0x08,
+ CMD_READ_ID = 0x0a,
CMD_SEEK = 0x0f,
+ CMD_VERIFY = 0x16,
CMD_READ = 0xe6,
CMD_RELATIVE_SEEK_OUT = 0x8f,
CMD_RELATIVE_SEEK_IN = 0xcf,
};
enum {
+ BUSY = 0x10,
+ NONDMA = 0x20,
RQM = 0x80,
DIO = 0x40,
@@ -110,7 +114,7 @@ static void ack_irq(uint8_t *pcn)
g_assert(!get_irq(FLOPPY_IRQ));
}
-static uint8_t send_read_command(void)
+static uint8_t send_read_command(uint8_t cmd)
{
uint8_t drive = 0;
uint8_t head = 0;
@@ -126,7 +130,7 @@ static uint8_t send_read_command(void)
uint8_t ret = 0;
- floppy_send(CMD_READ);
+ floppy_send(cmd);
floppy_send(head << 2 | drive);
g_assert(!get_irq(FLOPPY_IRQ));
floppy_send(cyl);
@@ -152,7 +156,70 @@ static uint8_t send_read_command(void)
}
st0 = floppy_recv();
- if (st0 != 0x60) {
+ if (st0 != 0x40) {
+ ret = 1;
+ }
+
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ return ret;
+}
+
+static uint8_t send_read_no_dma_command(int nb_sect, uint8_t expected_st0)
+{
+ uint8_t drive = 0;
+ uint8_t head = 0;
+ uint8_t cyl = 0;
+ uint8_t sect_addr = 1;
+ uint8_t sect_size = 2;
+ uint8_t eot = nb_sect;
+ uint8_t gap = 0x1b;
+ uint8_t gpl = 0xff;
+
+ uint8_t msr = 0;
+ uint8_t st0;
+
+ uint8_t ret = 0;
+
+ floppy_send(CMD_READ);
+ floppy_send(head << 2 | drive);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(cyl);
+ floppy_send(head);
+ floppy_send(sect_addr);
+ floppy_send(sect_size);
+ floppy_send(eot);
+ floppy_send(gap);
+ floppy_send(gpl);
+
+ uint16_t i = 0;
+ uint8_t n = 2;
+ for (; i < n; i++) {
+ msr = inb(FLOPPY_BASE + reg_msr);
+ if (msr == (BUSY | NONDMA | DIO | RQM)) {
+ break;
+ }
+ sleep(1);
+ }
+
+ if (i >= n) {
+ return 1;
+ }
+
+ /* Non-DMA mode */
+ for (i = 0; i < 512 * 2 * nb_sect; i++) {
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_set(msr, BUSY | RQM | DIO);
+ inb(FLOPPY_BASE + reg_fifo);
+ }
+
+ st0 = floppy_recv();
+ if (st0 != expected_st0) {
ret = 1;
}
@@ -213,11 +280,11 @@ static void test_read_without_media(void)
{
uint8_t ret;
- ret = send_read_command();
+ ret = send_read_command(CMD_READ);
g_assert(ret == 0);
}
-static void test_media_change(void)
+static void test_media_insert(void)
{
uint8_t dir;
@@ -245,6 +312,13 @@ static void test_media_change(void)
assert_bit_clear(dir, DSKCHG);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_clear(dir, DSKCHG);
+}
+
+static void test_media_change(void)
+{
+ uint8_t dir;
+
+ test_media_insert();
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
@@ -320,6 +394,108 @@ static void test_relative_seek(void)
g_assert(pcn == 0);
}
+static void test_read_id(void)
+{
+ uint8_t drive = 0;
+ uint8_t head = 0;
+ uint8_t cyl;
+ uint8_t st0;
+
+ /* Seek to track 0 and check with READ ID */
+ send_seek(0);
+
+ floppy_send(CMD_READ_ID);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(head << 2 | drive);
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ g_assert_cmpint(cyl, ==, 0);
+ g_assert_cmpint(head, ==, 0);
+ g_assert_cmpint(st0, ==, head << 2);
+
+ /* Seek to track 8 on head 1 and check with READ ID */
+ head = 1;
+ cyl = 8;
+
+ floppy_send(CMD_SEEK);
+ floppy_send(head << 2 | drive);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(cyl);
+ g_assert(get_irq(FLOPPY_IRQ));
+ ack_irq(NULL);
+
+ floppy_send(CMD_READ_ID);
+ g_assert(!get_irq(FLOPPY_IRQ));
+ floppy_send(head << 2 | drive);
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+
+ g_assert_cmpint(cyl, ==, 8);
+ g_assert_cmpint(head, ==, 1);
+ g_assert_cmpint(st0, ==, head << 2);
+}
+
+static void test_read_no_dma_1(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(1, 0x04);
+ g_assert(ret == 0);
+}
+
+static void test_read_no_dma_18(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(18, 0x04);
+ g_assert(ret == 0);
+}
+
+static void test_read_no_dma_19(void)
+{
+ uint8_t ret;
+
+ outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
+ send_seek(0);
+ ret = send_read_no_dma_command(19, 0x20);
+ g_assert(ret == 0);
+}
+
+static void test_verify(void)
+{
+ uint8_t ret;
+
+ ret = send_read_command(CMD_VERIFY);
+ g_assert(ret == 0);
+}
+
/* success if no crash or abort */
static void fuzz_registers(void)
{
@@ -369,6 +545,12 @@ int main(int argc, char **argv)
qtest_add_func("/fdc/media_change", test_media_change);
qtest_add_func("/fdc/sense_interrupt", test_sense_interrupt);
qtest_add_func("/fdc/relative_seek", test_relative_seek);
+ qtest_add_func("/fdc/read_id", test_read_id);
+ qtest_add_func("/fdc/verify", test_verify);
+ qtest_add_func("/fdc/media_insert", test_media_insert);
+ qtest_add_func("/fdc/read_no_dma_1", test_read_no_dma_1);
+ qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18);
+ qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19);
qtest_add_func("/fdc/fuzz-registers", fuzz_registers);
ret = g_test_run();