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
This commit is contained in:
bellard 2004-05-08 13:14:18 +00:00
parent bee3290936
commit ed5fd2cce4

View File

@ -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 || if (track > drv->max_track ||
(head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) { (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n", FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
head, track, sect, 1, head, track, sect, 1,
(drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
drv->max_track, drv->last_sect); drv->max_track, drv->last_sect);
return 2; return 2;
} }
if (sect > drv->last_sect) { if (sect > drv->last_sect) {
FLOPPY_ERROR("try to read %d %02x %02x (max=%d %d %02x %02x)\n", FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
head, track, sect, 1, head, track, sect, 1,
(drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
drv->max_track, drv->last_sect); drv->max_track, drv->last_sect);
return 3; return 3;
} }
sector = _fd_sector(head, track, sect, drv->last_sect); 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); ro = bdrv_is_read_only(drv->bs);
bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect); bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
if (nb_heads != 0 && max_track != 0 && last_sect != 0) { if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
printf("User defined disk (%d %d %d)", FLOPPY_DPRINTF("User defined disk (%d %d %d)",
nb_heads - 1, max_track, last_sect); nb_heads - 1, max_track, last_sect);
} else { } else {
bdrv_get_geometry(drv->bs, &nb_sectors); bdrv_get_geometry(drv->bs, &nb_sectors);
match = -1; match = -1;
@ -273,8 +273,8 @@ static void fd_revalidate (fdrive_t *drv)
max_track = parse->max_track; max_track = parse->max_track;
last_sect = parse->last_sect; last_sect = parse->last_sect;
drv->drive = parse->drive; drv->drive = parse->drive;
printf("%s floppy disk (%d h %d t %d s) %s\n", parse->str, FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
nb_heads, max_track, last_sect, ro ? "ro" : "rw"); nb_heads, max_track, last_sect, ro ? "ro" : "rw");
} }
if (nb_heads == 1) { if (nb_heads == 1) {
drv->flags &= ~FDISK_DBL_SIDES; drv->flags &= ~FDISK_DBL_SIDES;
@ -285,7 +285,7 @@ static void fd_revalidate (fdrive_t *drv)
drv->last_sect = last_sect; drv->last_sect = last_sect;
drv->ro = ro; drv->ro = ro;
} else { } else {
printf("No disk in drive\n"); FLOPPY_DPRINTF("No disk in drive\n");
drv->last_sect = 0; drv->last_sect = 0;
drv->max_track = 0; drv->max_track = 0;
drv->flags &= ~FDISK_DBL_SIDES; 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 void fdctrl_reset_fifo (fdctrl_t *fdctrl);
static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size); 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_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_statusB (fdctrl_t *fdctrl);
static uint32_t fdctrl_read_dor (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); static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
enum { enum {
FD_CTRL_ACTIVE = 0x01, FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
FD_CTRL_RESET = 0x02, FD_CTRL_RESET = 0x02,
FD_CTRL_SLEEP = 0x04, FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
FD_CTRL_BUSY = 0x08, FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
FD_CTRL_INTR = 0x10, FD_CTRL_INTR = 0x10,
}; };
@ -372,6 +373,7 @@ struct fdctrl_t {
int dma_chann; int dma_chann;
uint32_t io_base; uint32_t io_base;
/* Controler state */ /* Controler state */
QEMUTimer *result_timer;
uint8_t state; uint8_t state;
uint8_t dma_en; uint8_t dma_en;
uint8_t cur_drv; uint8_t cur_drv;
@ -425,6 +427,7 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
retval = (uint32_t)(-1); retval = (uint32_t)(-1);
break; break;
} }
FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
return retval; return retval;
} }
@ -433,6 +436,8 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
{ {
fdctrl_t *fdctrl = opaque; fdctrl_t *fdctrl = opaque;
FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
switch (reg & 0x07) { switch (reg & 0x07) {
case 0x02: case 0x02:
fdctrl_write_dor(fdctrl, value); 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)); fdctrl = qemu_mallocz(sizeof(fdctrl_t));
if (!fdctrl) if (!fdctrl)
return NULL; return NULL;
fdctrl->result_timer = qemu_new_timer(vm_clock,
fdctrl_result_timer, fdctrl);
fdctrl->version = 0x90; /* Intel 82078 controler */ fdctrl->version = 0x90; /* Intel 82078 controler */
fdctrl->irq_lvl = irq_lvl; fdctrl->irq_lvl = irq_lvl;
fdctrl->dma_chann = dma_chann; fdctrl->dma_chann = dma_chann;
@ -524,10 +532,9 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
/* Change IRQ state */ /* Change IRQ state */
static void fdctrl_reset_irq (fdctrl_t *fdctrl) static void fdctrl_reset_irq (fdctrl_t *fdctrl)
{ {
if (fdctrl->state & FD_CTRL_INTR) { FLOPPY_DPRINTF("Reset interrupt\n");
pic_set_irq(fdctrl->irq_lvl, 0); pic_set_irq(fdctrl->irq_lvl, 0);
fdctrl->state &= ~(FD_CTRL_INTR | FD_CTRL_SLEEP | FD_CTRL_BUSY); fdctrl->state &= ~FD_CTRL_INTR;
}
} }
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) 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]); fd_reset(&fdctrl->drives[i]);
fdctrl_reset_fifo(fdctrl); fdctrl_reset_fifo(fdctrl);
if (do_irq) if (do_irq)
fdctrl_raise_irq(fdctrl, 0x20); fdctrl_raise_irq(fdctrl, 0xc0);
} }
static inline fdrive_t *drv0 (fdctrl_t *fdctrl) 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) */ /* Status B register : 0x01 (read-only) */
static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
{ {
fdctrl_reset_irq(fdctrl);
FLOPPY_DPRINTF("status register: 0x00\n"); FLOPPY_DPRINTF("status register: 0x00\n");
return 0; 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) static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
{ {
fdctrl_reset_irq(fdctrl);
/* Reset mode */ /* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) { if (fdctrl->state & FD_CTRL_RESET) {
if (!(value & 0x04)) { if (!(value & 0x04)) {
@ -653,7 +657,6 @@ static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
{ {
uint32_t retval = 0; uint32_t retval = 0;
fdctrl_reset_irq(fdctrl);
/* Disk boot selection indicator */ /* Disk boot selection indicator */
retval |= fdctrl->bootsel << 2; retval |= fdctrl->bootsel << 2;
/* Tape indicators: never allowed */ /* 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) static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
{ {
fdctrl_reset_irq(fdctrl);
/* Reset mode */ /* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) { if (fdctrl->state & FD_CTRL_RESET) {
FLOPPY_DPRINTF("Floppy controler in RESET state !\n"); 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; uint32_t retval = 0;
fdctrl_reset_irq(fdctrl);
fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET); fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
if (!(fdctrl->state & FD_CTRL_BUSY)) { if (!(fdctrl->state & FD_CTRL_BUSY)) {
/* Data transfer allowed */ /* Data transfer allowed */
@ -703,7 +704,6 @@ static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
/* Data select rate register : 0x04 (write) */ /* Data select rate register : 0x04 (write) */
static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
{ {
fdctrl_reset_irq(fdctrl);
/* Reset mode */ /* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) { if (fdctrl->state & FD_CTRL_RESET) {
FLOPPY_DPRINTF("Floppy controler in RESET state !\n"); 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; uint32_t retval = 0;
fdctrl_reset_irq(fdctrl);
if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE || if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
drv1(fdctrl)->drflags & FDRIVE_REVALIDATE) drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
retval |= 0x80; 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[5] = cur_drv->sect;
fdctrl->fifo[6] = FD_SECTOR_SC; fdctrl->fifo[6] = FD_SECTOR_SC;
fdctrl->data_dir = FD_DIR_READ; fdctrl->data_dir = FD_DIR_READ;
if (fdctrl->state & FD_CTRL_BUSY) if (fdctrl->state & FD_CTRL_BUSY) {
DMA_release_DREQ(fdctrl->dma_chann); DMA_release_DREQ(fdctrl->dma_chann);
fdctrl->state &= ~FD_CTRL_BUSY;
}
fdctrl_set_fifo(fdctrl, 7, 1); 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; uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
fdctrl = opaque; fdctrl = opaque;
fdctrl_reset_irq(fdctrl);
if (!(fdctrl->state & FD_CTRL_BUSY)) { if (!(fdctrl->state & FD_CTRL_BUSY)) {
FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
return 0; return 0;
@ -1049,7 +1049,6 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
uint32_t retval = 0; uint32_t retval = 0;
int pos, len; int pos, len;
fdctrl_reset_irq(fdctrl);
cur_drv = get_cur_drv(fdctrl); cur_drv = get_cur_drv(fdctrl);
fdctrl->state &= ~FD_CTRL_SLEEP; fdctrl->state &= ~FD_CTRL_SLEEP;
if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) { 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 /* Switch from transfert mode to status mode
* then from status mode to command 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); fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
else } else {
fdctrl_reset_fifo(fdctrl); fdctrl_reset_fifo(fdctrl);
fdctrl_reset_irq(fdctrl);
}
} }
FLOPPY_DPRINTF("data register: 0x%02x\n", retval); 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; fdrive_t *cur_drv;
fdctrl_reset_irq(fdctrl);
cur_drv = get_cur_drv(fdctrl); cur_drv = get_cur_drv(fdctrl);
/* Reset mode */ /* Reset mode */
if (fdctrl->state & FD_CTRL_RESET) { if (fdctrl->state & FD_CTRL_RESET) {
@ -1583,7 +1583,9 @@ enqueue:
case 0x4A: case 0x4A:
/* READ_ID */ /* READ_ID */
FLOPPY_DPRINTF("treat READ_ID command\n"); 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; break;
case 0x4C: case 0x4C:
/* RESTORE */ /* RESTORE */
@ -1688,3 +1690,9 @@ enqueue:
} }
} }
} }
static void fdctrl_result_timer(void *opaque)
{
fdctrl_t *fdctrl = opaque;
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
}