aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-05-08 13:14:18 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-05-08 13:14:18 +0000
commited5fd2cce48520e4c0d4eec016743017df93e43a (patch)
tree2d0958bd390ed9205d90e434b3b82d6658f18e2f
parentbee32909369039337b030395a63ba5d2e05fca77 (diff)
timer for READ_ID (win98 floppy fix) - simpler irq handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@787 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--hw/fdc.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/hw/fdc.c b/hw/fdc.c
index dceee8fc7..ada3ad265 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -125,17 +125,17 @@ static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
if (track > drv->max_track ||
(head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
- FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
- head, track, sect, 1,
- (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
- drv->max_track, drv->last_sect);
+ FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
+ head, track, sect, 1,
+ (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
+ drv->max_track, drv->last_sect);
return 2;
}
if (sect > drv->last_sect) {
- FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
- head, track, sect, 1,
- (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
- drv->max_track, drv->last_sect);
+ FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
+ head, track, sect, 1,
+ (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
+ drv->max_track, drv->last_sect);
return 3;
}
sector = _fd_sector(head, track, sect, drv->last_sect);
@@ -240,8 +240,8 @@ static void fd_revalidate (fdrive_t *drv)
ro = bdrv_is_read_only(drv->bs);
bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
- printf("User defined disk (%d %d %d)",
- nb_heads - 1, max_track, last_sect);
+ FLOPPY_DPRINTF("User defined disk (%d %d %d)",
+ nb_heads - 1, max_track, last_sect);
} else {
bdrv_get_geometry(drv->bs, &nb_sectors);
match = -1;
@@ -273,8 +273,8 @@ static void fd_revalidate (fdrive_t *drv)
max_track = parse->max_track;
last_sect = parse->last_sect;
drv->drive = parse->drive;
- printf("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
- nb_heads, max_track, last_sect, ro ? "ro" : "rw");
+ FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
+ nb_heads, max_track, last_sect, ro ? "ro" : "rw");
}
if (nb_heads == 1) {
drv->flags &= ~FDISK_DBL_SIDES;
@@ -285,7 +285,7 @@ static void fd_revalidate (fdrive_t *drv)
drv->last_sect = last_sect;
drv->ro = ro;
} else {
- printf("No disk in drive\n");
+ FLOPPY_DPRINTF("No disk in drive\n");
drv->last_sect = 0;
drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES;
@@ -318,6 +318,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size);
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
+static void fdctrl_result_timer(void *opaque);
static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
@@ -331,10 +332,10 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
enum {
- FD_CTRL_ACTIVE = 0x01,
+ FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
FD_CTRL_RESET = 0x02,
- FD_CTRL_SLEEP = 0x04,
- FD_CTRL_BUSY = 0x08,
+ FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
+ FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
FD_CTRL_INTR = 0x10,
};
@@ -372,6 +373,7 @@ struct fdctrl_t {
int dma_chann;
uint32_t io_base;
/* Controler state */
+ QEMUTimer *result_timer;
uint8_t state;
uint8_t dma_en;
uint8_t cur_drv;
@@ -425,6 +427,7 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
retval = (uint32_t)(-1);
break;
}
+ FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
return retval;
}
@@ -433,6 +436,8 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
{
fdctrl_t *fdctrl = opaque;
+ FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
+
switch (reg & 0x07) {
case 0x02:
fdctrl_write_dor(fdctrl, value);
@@ -476,6 +481,9 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
fdctrl = qemu_mallocz(sizeof(fdctrl_t));
if (!fdctrl)
return NULL;
+ fdctrl->result_timer = qemu_new_timer(vm_clock,
+ fdctrl_result_timer, fdctrl);
+
fdctrl->version = 0x90; /* Intel 82078 controler */
fdctrl->irq_lvl = irq_lvl;
fdctrl->dma_chann = dma_chann;
@@ -524,10 +532,9 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
/* Change IRQ state */
static void fdctrl_reset_irq (fdctrl_t *fdctrl)
{
- if (fdctrl->state & FD_CTRL_INTR) {
- pic_set_irq(fdctrl->irq_lvl, 0);
- fdctrl->state &= ~(FD_CTRL_INTR | FD_CTRL_SLEEP | FD_CTRL_BUSY);
- }
+ FLOPPY_DPRINTF("Reset interrupt\n");
+ pic_set_irq(fdctrl->irq_lvl, 0);
+ fdctrl->state &= ~FD_CTRL_INTR;
}
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
@@ -558,7 +565,7 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
fd_reset(&fdctrl->drives[i]);
fdctrl_reset_fifo(fdctrl);
if (do_irq)
- fdctrl_raise_irq(fdctrl, 0x20);
+ fdctrl_raise_irq(fdctrl, 0xc0);
}
static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
@@ -579,9 +586,7 @@ static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
/* Status B register : 0x01 (read-only) */
static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
{
- fdctrl_reset_irq(fdctrl);
FLOPPY_DPRINTF("status register: 0x00\n");
-
return 0;
}
@@ -608,7 +613,6 @@ static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
{
- fdctrl_reset_irq(fdctrl);
/* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) {
if (!(value & 0x04)) {
@@ -653,7 +657,6 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
{
uint32_t retval = 0;
- fdctrl_reset_irq(fdctrl);
/* Disk boot selection indicator */
retval |= fdctrl->bootsel << 2;
/* Tape indicators: never allowed */
@@ -664,7 +667,6 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
{
- fdctrl_reset_irq(fdctrl);
/* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) {
FLOPPY_DPRINTF("Floppy controler in RESET state !\n");
@@ -681,7 +683,6 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
{
uint32_t retval = 0;
- fdctrl_reset_irq(fdctrl);
fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
if (!(fdctrl->state & FD_CTRL_BUSY)) {
/* Data transfer allowed */
@@ -703,7 +704,6 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
/* Data select rate register : 0x04 (write) */
static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
{
- fdctrl_reset_irq(fdctrl);
/* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) {
FLOPPY_DPRINTF("Floppy controler in RESET state !\n");
@@ -728,7 +728,6 @@ static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
{
uint32_t retval = 0;
- fdctrl_reset_irq(fdctrl);
if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
retval |= 0x80;
@@ -795,8 +794,10 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
fdctrl->fifo[5] = cur_drv->sect;
fdctrl->fifo[6] = FD_SECTOR_SC;
fdctrl->data_dir = FD_DIR_READ;
- if (fdctrl->state & FD_CTRL_BUSY)
+ if (fdctrl->state & FD_CTRL_BUSY) {
DMA_release_DREQ(fdctrl->dma_chann);
+ fdctrl->state &= ~FD_CTRL_BUSY;
+ }
fdctrl_set_fifo(fdctrl, 7, 1);
}
@@ -916,7 +917,6 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
fdctrl = opaque;
- fdctrl_reset_irq(fdctrl);
if (!(fdctrl->state & FD_CTRL_BUSY)) {
FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
return 0;
@@ -1049,7 +1049,6 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
uint32_t retval = 0;
int pos, len;
- fdctrl_reset_irq(fdctrl);
cur_drv = get_cur_drv(fdctrl);
fdctrl->state &= ~FD_CTRL_SLEEP;
if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {
@@ -1073,10 +1072,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
/* Switch from transfert mode to status mode
* then from status mode to command mode
*/
- if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
- else
+ } else {
fdctrl_reset_fifo(fdctrl);
+ fdctrl_reset_irq(fdctrl);
+ }
}
FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
@@ -1152,7 +1153,6 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
{
fdrive_t *cur_drv;
- fdctrl_reset_irq(fdctrl);
cur_drv = get_cur_drv(fdctrl);
/* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) {
@@ -1583,7 +1583,9 @@ enqueue:
case 0x4A:
/* READ_ID */
FLOPPY_DPRINTF("treat READ_ID command\n");
- fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+ /* XXX: should set main status register to busy */
+ qemu_mod_timer(fdctrl->result_timer,
+ qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
break;
case 0x4C:
/* RESTORE */
@@ -1688,3 +1690,9 @@ enqueue:
}
}
}
+
+static void fdctrl_result_timer(void *opaque)
+{
+ fdctrl_t *fdctrl = opaque;
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+}