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
80
hw/fdc.c
80
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 ||
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user