* THE SOFTWARE.
*/
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
+#include "qemu/osdep.h"
-#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
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,
DSKCHG = 0x80,
};
-char test_image[] = "/tmp/qtest.XXXXXX";
+static char test_image[] = "/tmp/qtest.XXXXXX";
#define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
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;
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);
}
st0 = floppy_recv();
- if (st0 != 0x60) {
+ if (st0 != 0x40) {
ret = 1;
}
inb(FLOPPY_BASE + reg_fifo);
}
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_set(msr, BUSY | RQM | DIO);
+ g_assert(get_irq(FLOPPY_IRQ));
+
st0 = floppy_recv();
if (st0 != expected_st0) {
ret = 1;
floppy_recv();
floppy_recv();
floppy_recv();
+ g_assert(get_irq(FLOPPY_IRQ));
floppy_recv();
+ /* Check that we're back in command phase */
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_clear(msr, BUSY | DIO);
+ assert_bit_set(msr, RQM);
+ g_assert(!get_irq(FLOPPY_IRQ));
+
return ret;
}
uint8_t cmos;
cmos = cmos_read(CMOS_FLOPPY);
- g_assert(cmos == 0x40);
+ g_assert(cmos == 0x40 || cmos == 0x50);
}
static void test_no_media_on_start(void)
{
uint8_t ret;
- ret = send_read_command();
+ ret = send_read_command(CMD_READ);
g_assert(ret == 0);
}
/* Insert media in drive. DSKCHK should not be reset until a step pulse
* is sent. */
- qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', "
- "'target': '%s' }}", test_image);
- qmp(""); /* ignore event (FIXME open -> open transition?!) */
- qmp(""); /* ignore event */
+ qmp_discard_response("{'execute':'change', 'arguments':{"
+ " 'device':'floppy0', 'target': %s, 'arg': 'raw' }}",
+ test_image);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
- qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}");
- qmp(""); /* ignore event */
+ qmp_discard_response("{'execute':'eject', 'arguments':{"
+ " 'device':'floppy0' }}");
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
g_assert(pcn == 0);
}
+static void test_read_id(void)
+{
+ uint8_t drive = 0;
+ uint8_t head = 0;
+ uint8_t cyl;
+ uint8_t st0;
+ uint8_t msr;
+
+ /* 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);
+
+ msr = inb(FLOPPY_BASE + reg_msr);
+ if (!get_irq(FLOPPY_IRQ)) {
+ assert_bit_set(msr, BUSY);
+ assert_bit_clear(msr, RQM);
+ }
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_set(msr, BUSY | RQM | DIO);
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ g_assert(get_irq(FLOPPY_IRQ));
+ floppy_recv();
+ g_assert(!get_irq(FLOPPY_IRQ));
+
+ 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);
+
+ msr = inb(FLOPPY_BASE + reg_msr);
+ if (!get_irq(FLOPPY_IRQ)) {
+ assert_bit_set(msr, BUSY);
+ assert_bit_clear(msr, RQM);
+ }
+
+ while (!get_irq(FLOPPY_IRQ)) {
+ /* qemu involves a timer with READ ID... */
+ clock_step(1000000000LL / 50);
+ }
+
+ msr = inb(FLOPPY_BASE + reg_msr);
+ assert_bit_set(msr, BUSY | RQM | DIO);
+
+ st0 = floppy_recv();
+ floppy_recv();
+ floppy_recv();
+ cyl = floppy_recv();
+ head = floppy_recv();
+ floppy_recv();
+ g_assert(get_irq(FLOPPY_IRQ));
+ floppy_recv();
+ g_assert(!get_irq(FLOPPY_IRQ));
+
+ 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, 0x24); /* FIXME: should be 0x04 */
+ ret = send_read_no_dma_command(1, 0x04);
g_assert(ret == 0);
}
outb(FLOPPY_BASE + reg_dor, inb(FLOPPY_BASE + reg_dor) & ~0x08);
send_seek(0);
- ret = send_read_no_dma_command(18, 0x24); /* FIXME: should be 0x04 */
+ ret = send_read_no_dma_command(18, 0x04);
g_assert(ret == 0);
}
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)
{
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
- char *cmdline;
int fd;
int ret;
/* Run the tests */
g_test_init(&argc, &argv, NULL);
- cmdline = g_strdup_printf("-vnc none ");
-
- qtest_start(cmdline);
+ qtest_start(NULL);
qtest_irq_intercept_in(global_qtest, "ioapic");
qtest_add_func("/fdc/cmos", test_cmos);
qtest_add_func("/fdc/no_media_on_start", test_no_media_on_start);
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);
ret = g_test_run();
/* Cleanup */
- qtest_quit(global_qtest);
+ qtest_end();
unlink(test_image);
return ret;