mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 20:19:44 +00:00
FDC fix 3/10 (Hervé Poussineau):
- Fixes status A and status B registers. It removes one Sun4m mutation. Also removes the internal FD_CTRL_INTR flag. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4283 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
746d6de7fe
commit
8c6a4d7742
91
hw/fdc.c
91
hw/fdc.c
@ -323,6 +323,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
|
||||
int dma_pos, int dma_len);
|
||||
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
|
||||
|
||||
static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl);
|
||||
static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
|
||||
static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
|
||||
static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
|
||||
@ -339,7 +340,6 @@ enum {
|
||||
FD_CTRL_RESET = 0x02,
|
||||
FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
|
||||
FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
|
||||
FD_CTRL_INTR = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -361,8 +361,8 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
FD_REG_0 = 0x00,
|
||||
FD_REG_STATUSB = 0x01,
|
||||
FD_REG_SRA = 0x00,
|
||||
FD_REG_SRB = 0x01,
|
||||
FD_REG_DOR = 0x02,
|
||||
FD_REG_TDR = 0x03,
|
||||
FD_REG_MSR = 0x04,
|
||||
@ -420,6 +420,26 @@ enum {
|
||||
FD_SR0_RDYCHG = 0xc0,
|
||||
};
|
||||
|
||||
enum {
|
||||
FD_SRA_DIR = 0x01,
|
||||
FD_SRA_nWP = 0x02,
|
||||
FD_SRA_nINDX = 0x04,
|
||||
FD_SRA_HDSEL = 0x08,
|
||||
FD_SRA_nTRK0 = 0x10,
|
||||
FD_SRA_STEP = 0x20,
|
||||
FD_SRA_nDRV2 = 0x40,
|
||||
FD_SRA_INTPEND = 0x80,
|
||||
};
|
||||
|
||||
enum {
|
||||
FD_SRB_MTR0 = 0x01,
|
||||
FD_SRB_MTR1 = 0x02,
|
||||
FD_SRB_WGATE = 0x04,
|
||||
FD_SRB_RDATA = 0x08,
|
||||
FD_SRB_WDATA = 0x10,
|
||||
FD_SRB_DR0 = 0x20,
|
||||
};
|
||||
|
||||
enum {
|
||||
FD_DOR_SELMASK = 0x01,
|
||||
FD_DOR_nRESET = 0x04,
|
||||
@ -472,6 +492,8 @@ struct fdctrl_t {
|
||||
target_phys_addr_t io_base;
|
||||
/* Controller state */
|
||||
QEMUTimer *result_timer;
|
||||
uint8_t sra;
|
||||
uint8_t srb;
|
||||
uint8_t state;
|
||||
uint8_t dma_en;
|
||||
uint8_t cur_drv;
|
||||
@ -506,15 +528,10 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
|
||||
uint32_t retval;
|
||||
|
||||
switch (reg & 0x07) {
|
||||
case FD_REG_0:
|
||||
if (fdctrl->sun4m) {
|
||||
// Identify to Linux as S82078B
|
||||
retval = fdctrl_read_statusB(fdctrl);
|
||||
} else {
|
||||
retval = (uint32_t)(-1);
|
||||
}
|
||||
case FD_REG_SRA:
|
||||
retval = fdctrl_read_statusA(fdctrl);
|
||||
break;
|
||||
case FD_REG_STATUSB:
|
||||
case FD_REG_SRB:
|
||||
retval = fdctrl_read_statusB(fdctrl);
|
||||
break;
|
||||
case FD_REG_DOR:
|
||||
@ -617,6 +634,9 @@ static void fdc_save (QEMUFile *f, void *opaque)
|
||||
{
|
||||
fdctrl_t *s = opaque;
|
||||
|
||||
/* Controller state */
|
||||
qemu_put_8s(f, &s->sra);
|
||||
qemu_put_8s(f, &s->srb);
|
||||
qemu_put_8s(f, &s->state);
|
||||
qemu_put_8s(f, &s->dma_en);
|
||||
qemu_put_8s(f, &s->cur_drv);
|
||||
@ -661,6 +681,9 @@ static int fdc_load (QEMUFile *f, void *opaque, int version_id)
|
||||
if (version_id != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Controller state */
|
||||
qemu_get_8s(f, &s->sra);
|
||||
qemu_get_8s(f, &s->srb);
|
||||
qemu_get_8s(f, &s->state);
|
||||
qemu_get_8s(f, &s->dma_en);
|
||||
qemu_get_8s(f, &s->cur_drv);
|
||||
@ -712,9 +735,11 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
|
||||
/* Change IRQ state */
|
||||
static void fdctrl_reset_irq (fdctrl_t *fdctrl)
|
||||
{
|
||||
if (!(fdctrl->sra & FD_SRA_INTPEND))
|
||||
return;
|
||||
FLOPPY_DPRINTF("Reset interrupt\n");
|
||||
qemu_set_irq(fdctrl->irq, 0);
|
||||
fdctrl->state &= ~FD_CTRL_INTR;
|
||||
fdctrl->sra &= ~FD_SRA_INTPEND;
|
||||
}
|
||||
|
||||
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
|
||||
@ -725,9 +750,9 @@ static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
|
||||
fdctrl->int_status = status;
|
||||
return;
|
||||
}
|
||||
if (~(fdctrl->state & FD_CTRL_INTR)) {
|
||||
if (!(fdctrl->sra & FD_SRA_INTPEND)) {
|
||||
qemu_set_irq(fdctrl->irq, 1);
|
||||
fdctrl->state |= FD_CTRL_INTR;
|
||||
fdctrl->sra |= FD_SRA_INTPEND;
|
||||
}
|
||||
FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
|
||||
fdctrl->int_status = status;
|
||||
@ -741,6 +766,10 @@ static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
|
||||
FLOPPY_DPRINTF("reset controller\n");
|
||||
fdctrl_reset_irq(fdctrl);
|
||||
/* Initialise controller */
|
||||
fdctrl->sra = 0;
|
||||
fdctrl->srb = 0xc0;
|
||||
if (!fdctrl->drives[1].bs)
|
||||
fdctrl->sra |= FD_SRA_nDRV2;
|
||||
fdctrl->cur_drv = 0;
|
||||
/* FIFO state */
|
||||
fdctrl->data_pos = 0;
|
||||
@ -769,11 +798,24 @@ static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
|
||||
return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
|
||||
}
|
||||
|
||||
/* Status A register : 0x00 (read-only) */
|
||||
static uint32_t fdctrl_read_statusA (fdctrl_t *fdctrl)
|
||||
{
|
||||
uint32_t retval = fdctrl->sra;
|
||||
|
||||
FLOPPY_DPRINTF("status register A: 0x%02x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Status B register : 0x01 (read-only) */
|
||||
static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
|
||||
{
|
||||
FLOPPY_DPRINTF("status register: 0x00\n");
|
||||
return 0;
|
||||
uint32_t retval = fdctrl->srb;
|
||||
|
||||
FLOPPY_DPRINTF("status register B: 0x%02x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Digital output register : 0x02 */
|
||||
@ -809,6 +851,23 @@ static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
|
||||
}
|
||||
}
|
||||
FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
|
||||
|
||||
/* Motors */
|
||||
if (value & FD_DOR_MOTEN0)
|
||||
fdctrl->srb |= FD_SRB_MTR0;
|
||||
else
|
||||
fdctrl->srb &= ~FD_SRB_MTR0;
|
||||
if (value & FD_DOR_MOTEN1)
|
||||
fdctrl->srb |= FD_SRB_MTR1;
|
||||
else
|
||||
fdctrl->srb &= ~FD_SRB_MTR1;
|
||||
|
||||
/* Drive */
|
||||
if (value & 1)
|
||||
fdctrl->srb |= FD_SRB_DR0;
|
||||
else
|
||||
fdctrl->srb &= ~FD_SRB_DR0;
|
||||
|
||||
/* Drive motors state indicators */
|
||||
if (value & FD_DOR_MOTEN1)
|
||||
fd_start(drv1(fdctrl));
|
||||
|
Loading…
Reference in New Issue
Block a user