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:
parent
bee3290936
commit
ed5fd2cce4
62
hw/fdc.c
62
hw/fdc.c
|
@ -125,14 +125,14 @@ 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",
|
||||
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",
|
||||
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);
|
||||
|
@ -240,7 +240,7 @@ 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)",
|
||||
FLOPPY_DPRINTF("User defined disk (%d %d %d)",
|
||||
nb_heads - 1, max_track, last_sect);
|
||||
} else {
|
||||
bdrv_get_geometry(drv->bs, &nb_sectors);
|
||||
|
@ -273,7 +273,7 @@ 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,
|
||||
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) {
|
||||
|
@ -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) {
|
||||
FLOPPY_DPRINTF("Reset interrupt\n");
|
||||
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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue