diff --git a/src/hdd/hdd_mfm_at.c b/src/hdd/hdd_mfm_at.c
index 966ed6021..67c0794fe 100644
--- a/src/hdd/hdd_mfm_at.c
+++ b/src/hdd/hdd_mfm_at.c
@@ -12,7 +12,7 @@
* based design. Most cards were WD1003-WA2 or -WAH, where the
* -WA2 cards had a floppy controller as well (to save space.)
*
- * Version: @(#)hdd_mfm_at.c 1.0.1 2017/09/17
+ * Version: @(#)hdd_mfm_at.c 1.0.2 2017/09/23
*
* Authors: Sarah Walker,
* Miran Grca,
@@ -31,13 +31,14 @@
#define MFM_TIME (TIMER_USEC*10)
+#define MFM_DEBUG 0
#define STAT_ERR 0x01
#define STAT_INDEX 0x02
-#define STAT_CORRECTED_DATA 0x04
+#define STAT_ECC 0x04
#define STAT_DRQ 0x08 /* data request */
#define STAT_DSC 0x10
-#define STAT_SEEK_COMPLETE 0x20
+#define STAT_WRFLT 0x20
#define STAT_READY 0x40
#define STAT_BUSY 0x80
@@ -59,94 +60,121 @@
typedef struct {
- int present;
- int hdc_num;
- int spt, hpc;
- int tracks;
- int cfg_spt;
- int cfg_hpc;
- int current_cylinder;
+ int8_t present, /* drive is present */
+ hdc_num, /* drive number in system */
+ steprate, /* current servo step rate */
+ spt, /* physical #sectors per track */
+ hpc, /* physical #heads per cylinder */
+ pad;
+ int16_t tracks; /* physical #tracks per cylinder */
+
+ int8_t cfg_spt, /* configured #sectors per track */
+ cfg_hpc; /* configured #heads per track */
+
+ int16_t curcyl; /* current track number */
} mfm_drive_t;
typedef struct {
- uint8_t status;
- uint8_t error;
- uint8_t secount,
- sector,
- head;
- uint16_t cylinder,
- cylprecomp;
- uint8_t command;
- uint8_t fdisk;
+ uint8_t precomp, /* 1: precomp/error register */
+ error,
+ secount, /* 2: sector count register */
+ sector, /* 3: sector number */
+ head, /* 6: head number + drive select */
+ command, /* 7: command/status */
+ status,
+ fdisk; /* 8: control register */
+ uint16_t cylinder; /* 4/5: cylinder LOW and HIGH */
- int pos;
- int drive_sel;
- int reset;
- int irqstat;
- int callback;
+ int8_t reset, /* controller in reset */
+ irqstat, /* current IRQ status */
+ drvsel, /* current selected drive */
+ pad;
- uint16_t buffer[256];
+ int pos; /* offset within data buffer */
+ int callback; /* callback delay timer */
- mfm_drive_t drives[MFM_NUM];
+ uint16_t buffer[256]; /* data buffer (16b wide) */
+
+ mfm_drive_t drives[MFM_NUM]; /* attached drives */
} mfm_t;
static __inline void irq_raise(mfm_t *mfm)
{
- if (!(mfm->fdisk&2))
- picint(1 << 14);
+ /* If not already pending.. */
+ if (! mfm->irqstat) {
+ /* If enabled in the control register.. */
+ if (! (mfm->fdisk&0x02)) {
+ /* .. raise IRQ14. */
+ picint(1<<14);
+ }
- mfm->irqstat=1;
+ /* Remember this. */
+ mfm->irqstat = 1;
+ }
}
static __inline void irq_lower(mfm_t *mfm)
{
- picintc(1 << 14);
+ /* If raised.. */
+ if (mfm->irqstat) {
+ /* If enabled in the control register.. */
+ if (! (mfm->fdisk&0x02)) {
+ /* .. drop IRQ14. */
+ picintc(1<<14);
+ }
+
+ /* Remember this. */
+ mfm->irqstat = 0;
+ }
}
-static void
-irq_update(mfm_t *mfm)
-{
- if (mfm->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(mfm->fdisk & 2))
- picint(1 << 14);
-}
-
-
-/* Return the sector offset for the current register values. */
+/*
+ * Return the sector offset for the current register values.
+ *
+ * According to the WD1002/WD1003 technical reference manual,
+ * this is not done entirely correct. It specifies that the
+ * parameters set with the SET_DRIVE_PARAMETERS command are
+ * to be used only for multi-sector operations, and that any
+ * such operation can only be executed AFTER these parameters
+ * have been set. This would imply that for regular single
+ * transfers, the controller uses (or, can use) the actual
+ * geometry information...
+ */
static int
get_sector(mfm_t *mfm, off64_t *addr)
{
- mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
+ mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
- if (drive->current_cylinder != mfm->cylinder) {
+ if (drive->curcyl != mfm->cylinder) {
pclog("WD1003(%d) sector: wrong cylinder\n");
return(1);
}
if (mfm->head > drive->cfg_hpc) {
pclog("WD1003(%d) get_sector: past end of configured heads\n",
- mfm->drive_sel);
+ mfm->drvsel);
return(1);
}
if (mfm->sector >= drive->cfg_spt+1) {
pclog("WD1003(%d) get_sector: past end of configured sectors\n",
- mfm->drive_sel);
+ mfm->drvsel);
return(1);
}
#if 1
/* We should check this in the SET_DRIVE_PARAMETERS command! --FvK */
if (mfm->head > drive->hpc) {
- pclog("WD1003(%d) get_sector: past end of heads\n", mfm->drive_sel);
+ pclog("WD1003(%d) get_sector: past end of heads\n", mfm->drvsel);
return(1);
}
if (mfm->sector >= drive->spt+1) {
- pclog("WD1003(%d) get_sector: past end of sectors\n", mfm->drive_sel);
+ pclog("WD1003(%d) get_sector: past end of sectors\n", mfm->drvsel);
return(1);
}
#endif
@@ -162,22 +190,167 @@ get_sector(mfm_t *mfm, off64_t *addr)
static void
next_sector(mfm_t *mfm)
{
- mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
+ mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
- mfm->sector++;
- if (mfm->sector == (drive->cfg_spt+1)) {
+ if (++mfm->sector == (drive->cfg_spt+1)) {
mfm->sector = 1;
- mfm->head++;
- if (mfm->head == drive->cfg_hpc) {
+ if (++mfm->head == drive->cfg_hpc) {
mfm->head = 0;
mfm->cylinder++;
- if (drive->current_cylinder < drive->tracks)
- drive->current_cylinder++;
+ if (drive->curcyl < drive->tracks)
+ drive->curcyl++;
}
}
}
+static void
+mfm_cmd(mfm_t *mfm, uint8_t val)
+{
+ mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
+
+ if (! drive->present) {
+ /* This happens if sofware polls all drives. */
+ pclog("WD1003(%d) command %02x on non-present drive\n",
+ mfm->drvsel, val);
+ mfm->command = 0xff;
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+
+ return;
+ }
+
+ irq_lower(mfm);
+ mfm->error = 0;
+
+ switch (val & 0xf0) {
+ case CMD_RESTORE:
+ drive->steprate = (val & 0x0f);
+#if MFM_DEBUG
+ pclog("WD1003(%d) restore, step=%d\n",
+ mfm->drvsel, drive->steprate);
+#endif
+ drive->curcyl = 0;
+ mfm->status = STAT_READY|STAT_DSC;
+ mfm->command = 0x00;
+ irq_raise(mfm);
+ break;
+
+ case CMD_SEEK:
+ drive->steprate = (val & 0x0f);
+ mfm->command = (val & 0xf0);
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+ break;
+
+ default:
+ switch (val) {
+ case CMD_READ:
+ case CMD_READ+1:
+ case CMD_READ+2:
+ case CMD_READ+3:
+#if MFM_DEBUG
+ pclog("WD1003(%d) read, opt=%d\n",
+ mfm->drvsel, val&0x03);
+#endif
+ mfm->command = (val & 0xf0);
+ if (val & 2)
+ fatal("WD1003: READ with ECC\n");
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+ break;
+
+ case CMD_WRITE:
+ case CMD_WRITE+1:
+ case CMD_WRITE+2:
+ case CMD_WRITE+3:
+#if MFM_DEBUG
+ pclog("WD1003(%d) write, opt=%d\n",
+ mfm->drvsel, val & 0x03);
+#endif
+ mfm->command = (val & 0xf0);
+ if (val & 2)
+ fatal("WD1003: WRITE with ECC\n");
+ mfm->status = STAT_DRQ|STAT_DSC;
+ mfm->pos = 0;
+ break;
+
+ case CMD_VERIFY:
+ case CMD_VERIFY+1:
+ mfm->command = (val & 0xfe);
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+ break;
+
+ case CMD_FORMAT:
+ mfm->command = val;
+ mfm->status = STAT_DRQ|STAT_BUSY;
+ mfm->pos = 0;
+ break;
+
+ case CMD_DIAGNOSE:
+ mfm->command = val;
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+ break;
+
+ case CMD_SET_PARAMETERS:
+ /*
+ * NOTE:
+ *
+ * We currently just set these parameters, and
+ * never bother to check if they "fit within"
+ * the actual parameters, as determined by the
+ * image loader.
+ *
+ * The difference in parameters is OK, and
+ * occurs when the BIOS or operating system
+ * decides to use a different translation
+ * scheme, but either way, it SHOULD always
+ * fit within the actual parameters!
+ *
+ * We SHOULD check that here!! --FvK
+ */
+ if (drive->cfg_spt == 0) {
+ /* Only accept after RESET or DIAG. */
+ drive->cfg_spt = mfm->secount;
+ drive->cfg_hpc = mfm->head+1;
+ pclog("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n",
+ mfm->drvsel, drive->tracks,
+ drive->cfg_spt, drive->cfg_hpc);
+ } else {
+ pclog("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n",
+ mfm->drvsel, drive->tracks,
+ drive->cfg_spt, drive->cfg_hpc);
+ }
+ mfm->command = 0x00;
+ mfm->status = STAT_READY|STAT_DSC;
+ mfm->error = 1;
+ irq_raise(mfm);
+ break;
+
+ default:
+ pclog("WD1003: bad command %02X\n", val);
+ mfm->status = STAT_BUSY;
+ timer_process();
+ mfm->callback = 200*MFM_TIME;
+ timer_update_outstanding();
+ break;
+ }
+ }
+}
+
+
static void
mfm_writew(uint16_t port, uint16_t val, void *priv)
{
@@ -201,150 +374,52 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
-#if 0
+#if MFM_DEBUG > 1
pclog("WD1003 write(%04x, %02x)\n", port, val);
#endif
switch (port) {
- case 0x1f0: /* data */
+ case 0x01f0: /* data */
mfm_writew(port, val | (val << 8), priv);
return;
- case 0x1f1: /* write precompenstation */
- mfm->cylprecomp = val;
+ case 0x01f1: /* write precompenstation */
+ mfm->precomp = val;
return;
- case 0x1f2: /* sector count */
+ case 0x01f2: /* sector count */
mfm->secount = val;
return;
- case 0x1f3: /* sector */
+ case 0x01f3: /* sector */
mfm->sector = val;
return;
- case 0x1f4: /* cylinder low */
+ case 0x01f4: /* cylinder low */
mfm->cylinder = (mfm->cylinder & 0xff00) | val;
return;
- case 0x1f5: /* cylinder high */
+ case 0x01f5: /* cylinder high */
mfm->cylinder = (mfm->cylinder & 0xff) | (val << 8);
return;
- case 0x1f6: /* drive/head */
+ case 0x01f6: /* drive/head */
mfm->head = val & 0xF;
- mfm->drive_sel = (val & 0x10) ? 1 : 0;
- if (mfm->drives[mfm->drive_sel].present)
- mfm->status = STAT_READY | STAT_DSC;
+ mfm->drvsel = (val & 0x10) ? 1 : 0;
+ if (mfm->drives[mfm->drvsel].present)
+ mfm->status = STAT_READY|STAT_DSC;
else
mfm->status = 0;
return;
- case 0x1f7: /* command register */
- if (! mfm->drives[mfm->drive_sel].present) {
- /*
- * We should not panic on this, as some systems
- * (like several old UNIX systems like Microport
- * SystemV/AT) poll both drives...
- */
- pclog("WD1003(%d) command %02x on non-present drive\n",
- mfm->drive_sel, val);
- mfm->command = 0xff;
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- return;
- }
-
- irq_lower(mfm);
- mfm->command = val;
- mfm->error = 0;
-
- switch (val & 0xf0) {
- case CMD_RESTORE:
- mfm->command &= ~0x0f; /* mask off step rate */
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- break;
-
- case CMD_SEEK:
- mfm->command &= ~0x0f; /* mask off step rate */
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- break;
-
- default:
- switch (val) {
- case CMD_READ:
- case CMD_READ+1:
- case CMD_READ+2:
- case CMD_READ+3:
- mfm->command &= ~0x03;
- if (val & 2)
- fatal("WD1003: READ with ECC\n");
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- break;
-
- case CMD_WRITE:
- case CMD_WRITE+1:
- case CMD_WRITE+2:
- case CMD_WRITE+3:
- mfm->command &= ~0x03;
- if (val & 2)
- fatal("WD1003: WRITE with ECC\n");
- mfm->status = STAT_DRQ|STAT_DSC;
- mfm->pos = 0;
- break;
-
- case CMD_VERIFY:
- case CMD_VERIFY+1:
- mfm->command &= ~0x01;
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200 * MFM_TIME;
- timer_update_outstanding();
- break;
-
- case CMD_FORMAT:
- mfm->status =STAT_DRQ|STAT_BUSY;
- mfm->pos = 0;
- break;
-
- case CMD_SET_PARAMETERS:
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 30*MFM_TIME;
- timer_update_outstanding();
- break;
-
- case CMD_DIAGNOSE:
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- break;
-
- default:
- pclog("WD1003: bad command %02X\n", val);
- mfm->status = STAT_BUSY;
- timer_process();
- mfm->callback = 200*MFM_TIME;
- timer_update_outstanding();
- break;
- }
- }
+ case 0x01f7: /* command register */
+ mfm_cmd(mfm, val);
break;
- case 0x3f6: /* device control */
+ case 0x03f6: /* device control */
+ val &= 0x0f;
if ((mfm->fdisk & 0x04) && !(val & 0x04)) {
- mfm->reset = 1;
mfm->status = STAT_BUSY;
+ mfm->reset = 1;
timer_process();
mfm->callback = 500*MFM_TIME;
timer_update_outstanding();
@@ -357,9 +432,7 @@ mfm_write(uint16_t port, uint8_t val, void *priv)
timer_process();
timer_update_outstanding();
}
-
mfm->fdisk = val;
- irq_update(mfm);
break;
}
}
@@ -374,8 +447,8 @@ mfm_readw(uint16_t port, void *priv)
ret = mfm->buffer[mfm->pos >> 1];
mfm->pos += 2;
if (mfm->pos >= 512) {
- mfm->pos=0;
- mfm->status = STAT_READY | STAT_DSC;
+ mfm->pos = 0;
+ mfm->status = STAT_READY|STAT_DSC;
if (mfm->command == CMD_READ) {
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount) {
@@ -385,7 +458,7 @@ mfm_readw(uint16_t port, void *priv)
mfm->callback = 6*MFM_TIME;
timer_update_outstanding();
} else {
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 0);
}
}
}
@@ -401,35 +474,35 @@ mfm_read(uint16_t port, void *priv)
uint8_t ret = 0xff;
switch (port) {
- case 0x1f0: /* data */
+ case 0x01f0: /* data */
ret = mfm_readw(port, mfm) & 0xff;
break;
- case 0x1f1: /* error */
+ case 0x01f1: /* error */
ret = mfm->error;
break;
- case 0x1f2: /* sector count */
+ case 0x01f2: /* sector count */
ret = mfm->secount;
break;
- case 0x1f3: /* sector */
+ case 0x01f3: /* sector */
ret = mfm->sector;
break;
- case 0x1f4: /* CYlinder low */
+ case 0x01f4: /* CYlinder low */
ret = (uint8_t)(mfm->cylinder&0xff);
break;
- case 0x1f5: /* Cylinder high */
+ case 0x01f5: /* Cylinder high */
ret = (uint8_t)(mfm->cylinder>>8);
break;
- case 0x1f6: /* drive/head */
- ret = (uint8_t)(0xa0 | mfm->head | (mfm->drive_sel?0x10:0));
+ case 0x01f6: /* drive/head */
+ ret = (uint8_t)(0xa0 | mfm->head | (mfm->drvsel?0x10:0));
break;
- case 0x1f7: /* Status */
+ case 0x01f7: /* Status */
irq_lower(mfm);
ret = mfm->status;
break;
@@ -437,7 +510,7 @@ mfm_read(uint16_t port, void *priv)
default:
break;
}
-#if 0
+#if MFM_DEBUG > 1
pclog("WD1003 read(%04x) = %02x\n", port, ret);
#endif
@@ -448,12 +521,16 @@ mfm_read(uint16_t port, void *priv)
static void
do_seek(mfm_t *mfm)
{
- mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
+ mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
+#if MFM_DEBUG
+ pclog("WD1003(%d) seek(%d) max=%d\n",
+ mfm->drvsel,mfm->cylinder,drive->tracks);
+#endif
if (mfm->cylinder < drive->tracks)
- drive->current_cylinder = mfm->cylinder;
+ drive->curcyl = mfm->cylinder;
else
- drive->current_cylinder = drive->tracks-1;
+ drive->curcyl = drive->tracks-1;
}
@@ -461,145 +538,138 @@ static void
do_callback(void *priv)
{
mfm_t *mfm = (mfm_t *)priv;
- mfm_drive_t *drive = &mfm->drives[mfm->drive_sel];
+ mfm_drive_t *drive = &mfm->drives[mfm->drvsel];
off64_t addr;
mfm->callback = 0;
if (mfm->reset) {
- mfm->status = STAT_READY | STAT_DSC;
+#if MFM_DEBUG
+ pclog("WD1003(%d) reset\n", mfm->drvsel);
+#endif
+ mfm->status = STAT_READY|STAT_DSC;
mfm->error = 1;
mfm->secount = 1;
mfm->sector = 1;
mfm->head = 0;
mfm->cylinder = 0;
- drive->cfg_spt = 0; /* we need new parameters after reset! */
+
+ drive->steprate = 0x0f; /* default steprate */
+ drive->cfg_spt = 0; /* need new parameters */
+
mfm->reset = 0;
+
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 0);
+
return;
}
switch (mfm->command) {
- case CMD_RESTORE:
- drive->current_cylinder = 0;
- mfm->status = STAT_READY | STAT_DSC;
- irq_raise(mfm);
- break;
-
case CMD_SEEK:
+#if MFM_DEBUG
+ pclog("WD1003(%d) seek, step=%d\n",
+ mfm->drvsel, drive->steprate);
+#endif
do_seek(mfm);
- mfm->status = STAT_READY | STAT_DSC;
+ mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
break;
case CMD_READ:
+#if MFM_DEBUG
+ pclog("WD1003(%d) read(%d,%d,%d)\n",
+ mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
+#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
- mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
+ mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
- hdd_image_read(drive->hdc_num, addr, 1,(uint8_t *)mfm->buffer);
+ hdd_image_read(drive->hdc_num, addr, 1, (uint8_t *)mfm->buffer);
mfm->pos = 0;
- mfm->status = STAT_DRQ | STAT_READY | STAT_DSC;
+ mfm->status = STAT_DRQ|STAT_READY|STAT_DSC;
irq_raise(mfm);
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_WRITE:
+#if MFM_DEBUG
+ pclog("WD1003(%d) write(%d,%d,%d)\n",
+ mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
+#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
- mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
+ mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
hdd_image_write(drive->hdc_num, addr, 1,(uint8_t *)mfm->buffer);
- irq_raise(mfm);
+ mfm->status = STAT_READY|STAT_DSC;
mfm->secount = (mfm->secount - 1) & 0xff;
if (mfm->secount) {
- mfm->status = STAT_DRQ | STAT_READY | STAT_DSC;
+ /* More sectors to do.. */
+ mfm->status |= STAT_DRQ;
mfm->pos = 0;
next_sector(mfm);
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
} else {
- mfm->status = STAT_READY | STAT_DSC;
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 0);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 0);
}
+ irq_raise(mfm);
break;
case CMD_VERIFY:
+#if MFM_DEBUG
+ pclog("WD1003(%d) verify(%d,%d,%d)\n",
+ mfm->drvsel, mfm->cylinder, mfm->head, mfm->sector);
+#endif
do_seek(mfm);
mfm->pos = 0;
- mfm->status = STAT_READY | STAT_DSC;
+ mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_FORMAT:
+#if MFM_DEBUG
+ pclog("WD1003(%d) format(%d,%d)\n",
+ mfm->drvsel, mfm->cylinder, mfm->head);
+#endif
do_seek(mfm);
if (get_sector(mfm, &addr)) {
mfm->error = ERR_ID_NOT_FOUND;
- mfm->status = STAT_READY | STAT_DSC | STAT_ERR;
+ mfm->status = STAT_READY|STAT_DSC|STAT_ERR;
irq_raise(mfm);
break;
}
hdd_image_zero(drive->hdc_num, addr, mfm->secount);
- mfm->status = STAT_READY | STAT_DSC;
+ mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
- update_status_bar_icon(SB_HDD | HDD_BUS_MFM, 1);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 1);
break;
case CMD_DIAGNOSE:
- mfm->error = 1; /*No error detected*/
- mfm->status = STAT_READY | STAT_DSC;
- irq_raise(mfm);
- break;
-
- case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
- /*
- * NOTE:
- *
- * We currently just set these parameters, and never
- * bother to check if they "fit within" the actual
- * parameters, as determined by the image loader.
- *
- * The difference in parameters is OK, and occurs
- * when the BIOS or operating system decides to use
- * a different translation scheme, but either way,
- * it SHOULD always fit within the actual parameters!
- *
- * We SHOULD check that here!! --FvK
- */
- if (drive->cfg_spt == 0) {
- drive->cfg_spt = mfm->secount;
- drive->cfg_hpc = mfm->head+1;
- pclog("WD1003(%d) parameters: tracks=%d, spt=%i, hpc=%i\n",
- mfm->drive_sel,drive->tracks,
- drive->cfg_spt,drive->cfg_hpc);
- } else {
- /*
- * For debugging the weirdness that happens
- * while trying to install Microport SysV/AT,
- * which issues several calls with changing
- * parameters. --FvK
- */
- pclog("WD1003(%d) parameters: tracks=%d,spt=%i,hpc=%i (IGNORED)\n",
- mfm->drive_sel,drive->tracks,drive->cfg_spt,drive->cfg_hpc);
- }
- mfm->status = STAT_READY | STAT_DSC;
+#if MFM_DEBUG
+ pclog("WD1003(%d) diag\n", mfm->drvsel);
+#endif
+ drive->steprate = 0x0f;
+ mfm->error = 1;
+ mfm->status = STAT_READY|STAT_DSC;
irq_raise(mfm);
break;
default:
pclog("WD1003(%d) callback on unknown command %02x\n",
- mfm->drive_sel, mfm->command);
- mfm->status = STAT_READY | STAT_ERR | STAT_DSC;
+ mfm->drvsel, mfm->command);
+ mfm->status = STAT_READY|STAT_ERR|STAT_DSC;
mfm->error = ERR_ABRT;
irq_raise(mfm);
break;
@@ -614,6 +684,7 @@ loadhd(mfm_t *mfm, int c, int d, const wchar_t *fn)
if (! hdd_image_load(d)) {
drive->present = 0;
+
return;
}
@@ -638,14 +709,16 @@ mfm_init(void)
c = 0;
for (d=0; d= MFM_NUM) break;
+
+ pclog("WD1003(%d): (%S) geometry %d/%d/%d\n", c, hdc[d].fn,
+ (int)hdc[d].tracks, (int)hdc[d].hpc, (int)hdc[d].spt);
+
+ if (++c >= MFM_NUM) break;
}
}
- mfm->status = STAT_READY | STAT_DSC; /* drive is ready */
+ mfm->status = STAT_READY|STAT_DSC; /* drive is ready */
mfm->error = 1; /* no errors */
io_sethandler(0x01f0, 1,
@@ -657,6 +730,8 @@ mfm_init(void)
timer_add(do_callback, &mfm->callback, &mfm->callback, mfm);
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 0);
+
return(mfm);
}
@@ -674,6 +749,8 @@ mfm_close(void *priv)
}
free(mfm);
+
+ update_status_bar_icon(SB_HDD|HDD_BUS_MFM, 0);
}