From 38f19f7c9f59631362360888c8e80ac019d8d240 Mon Sep 17 00:00:00 2001 From: SarahW Date: Wed, 4 Mar 2020 22:03:08 +0000 Subject: [PATCH] Better implementation of FDC 'not found' errors - can now distinguish missing address mark (eg disc not present or track not formatted), sector not found, wrong cylinder and bad cylinder. --- src/disc.c | 2 +- src/disc.h | 2 +- src/disc_fdi.c | 3 +- src/disc_sector.c | 79 +++++++++++++++++++++++++++++++++++------------ src/fdc.c | 36 ++++++++++++++++++--- src/fdc.h | 10 ++++++ 6 files changed, 106 insertions(+), 26 deletions(-) diff --git a/src/disc.c b/src/disc.c index b2e0a0c..6b76b9b 100644 --- a/src/disc.c +++ b/src/disc.c @@ -143,7 +143,7 @@ void disc_poll() { disc_notfound--; if (!disc_notfound) - fdc_notfound(); + fdc_notfound(FDC_STATUS_AM_NOT_FOUND); } } diff --git a/src/disc.h b/src/disc.h index d8e33a5..714af06 100644 --- a/src/disc.h +++ b/src/disc.h @@ -37,7 +37,7 @@ void fdc_callback(); int fdc_data(uint8_t dat); void fdc_spindown(); void fdc_finishread(); -void fdc_notfound(); +void fdc_notfound(int reason); void fdc_datacrcerror(); void fdc_headercrcerror(); void fdc_writeprotect(); diff --git a/src/disc_fdi.c b/src/disc_fdi.c index 498a623..1393bc2 100644 --- a/src/disc_fdi.c +++ b/src/disc_fdi.c @@ -3,6 +3,7 @@ #include "ibm.h" #include "disc.h" #include "disc_fdi.h" +#include "fdc.h" #include "fdi2raw.h" static struct @@ -314,7 +315,7 @@ void fdi_poll() if (fdi_revs == 3) { // pclog("Not found!\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_NOT_FOUND); fdi_inread = fdi_inreadaddr = 0; return; } diff --git a/src/disc_sector.c b/src/disc_sector.c index b7805d6..26759bf 100644 --- a/src/disc_sector.c +++ b/src/disc_sector.c @@ -46,7 +46,9 @@ static int disc_intersector_delay = 0; static uint8_t disc_sector_fill; static int cur_sector, cur_byte; static int index_count; - + +static int disc_sector_status; + void disc_sector_reset(int drive, int side) { disc_sector_count[drive][side] = 0; @@ -90,6 +92,8 @@ void disc_sector_readsector(int drive, int sector, int track, int side, int rate disc_sector_sector = sector; disc_sector_n = sector_size; index_count = 0; + + disc_sector_status = FDC_STATUS_AM_NOT_FOUND; } void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size) @@ -103,6 +107,8 @@ void disc_sector_writesector(int drive, int sector, int track, int side, int rat disc_sector_sector = sector; disc_sector_n = sector_size; index_count = 0; + + disc_sector_status = FDC_STATUS_AM_NOT_FOUND; } void disc_sector_readaddress(int drive, int track, int side, int rate) @@ -114,6 +120,8 @@ void disc_sector_readaddress(int drive, int track, int side, int rate) disc_sector_side = side; disc_sector_drive = drive; index_count = 0; + + disc_sector_status = FDC_STATUS_AM_NOT_FOUND; } void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill) @@ -179,7 +187,7 @@ void disc_sector_poll() if (index_count > 1) { // pclog("Find sector not found\n"); - fdc_notfound(); + fdc_notfound(disc_sector_status); disc_sector_state = STATE_IDLE; break; } @@ -187,10 +195,11 @@ void disc_sector_poll() disc_sector_side != s->h, disc_sector_sector != s->r, fdc_get_bitcell_period() != get_bitcell_period());*/ - if (cur_byte || disc_sector_track != s->c || - disc_sector_side != s->h || - disc_sector_sector != s->r || - disc_sector_n != s->n || + if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() && + fdd_can_read_medium(disc_sector_drive ^ fdd_swap)) + disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/ + + if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() || !fdd_can_read_medium(disc_sector_drive ^ fdd_swap) || disc_intersector_delay) @@ -198,6 +207,16 @@ void disc_sector_poll() advance_byte(); break; } + if (disc_sector_track != s->c || + disc_sector_side != s->h || + disc_sector_sector != s->r || + disc_sector_n != s->n) + { + if (disc_sector_track != s->c) + disc_sector_status = (disc_sector_track == 0xff) ? FDC_STATUS_BAD_CYLINDER : FDC_STATUS_WRONG_CYLINDER; + advance_byte(); + break; + } disc_sector_state = STATE_READ_SECTOR; case STATE_READ_SECTOR: // pclog("STATE_READ_SECTOR: cur_byte=%i %i\n", cur_byte, disc_intersector_delay); @@ -218,10 +237,14 @@ void disc_sector_poll() if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_AM_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } + if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() && + fdd_can_read_medium(disc_sector_drive ^ fdd_swap)) + disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/ + if (cur_byte || !index_count || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { @@ -244,14 +267,14 @@ void disc_sector_poll() if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_AM_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } if (index_count) { // pclog("Find next sector hit end of track\n"); - fdc_notfound(); + fdc_notfound(disc_sector_status); disc_sector_state = STATE_IDLE; break; } @@ -277,10 +300,15 @@ void disc_sector_poll() if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_AM_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } + + if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() && + fdd_can_read_medium(disc_sector_drive ^ fdd_swap)) + disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/ + if (writeprot[disc_sector_drive]) { fdc_writeprotect(); @@ -290,20 +318,27 @@ void disc_sector_poll() if (index_count > 1) { // pclog("Write find sector not found\n"); - fdc_notfound(); + fdc_notfound(disc_sector_status); disc_sector_state = STATE_IDLE; break; } - if (cur_byte || disc_sector_track != s->c || - disc_sector_side != s->h || - disc_sector_sector != s->r || - disc_sector_n != s->n || + if (cur_byte || fdc_get_bitcell_period() != get_bitcell_period() || disc_intersector_delay) { advance_byte(); break; } + if (disc_sector_track != s->c || + disc_sector_side != s->h || + disc_sector_sector != s->r || + disc_sector_n != s->n) + { + if (disc_sector_track != s->c) + disc_sector_status = (disc_sector_track == 0xff) ? FDC_STATUS_BAD_CYLINDER : FDC_STATUS_WRONG_CYLINDER; + advance_byte(); + break; + } disc_sector_state = STATE_WRITE_SECTOR; case STATE_WRITE_SECTOR: data = fdc_getdata(cur_byte == ((128 << s->n) - 1)); @@ -323,14 +358,19 @@ void disc_sector_poll() if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_AM_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } + + if (!cur_byte && fdc_get_bitcell_period() == get_bitcell_period() && + fdd_can_read_medium(disc_sector_drive ^ fdd_swap)) + disc_sector_status = FDC_STATUS_NOT_FOUND; /*Disc readable, assume address marker found*/ + if (index_count) { // pclog("Find next sector hit end of track\n"); - fdc_notfound(); + fdc_notfound(disc_sector_status); disc_sector_state = STATE_IDLE; break; } @@ -343,6 +383,7 @@ void disc_sector_poll() disc_sector_state = STATE_READ_ADDRESS; case STATE_READ_ADDRESS: fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0); + advance_byte(); disc_sector_state = STATE_IDLE; break; @@ -362,13 +403,13 @@ void disc_sector_poll() if (!(fdd_can_read_medium(disc_sector_drive ^ fdd_swap))) { // pclog("Medium is of a density not supported by the drive\n"); - fdc_notfound(); + fdc_notfound(FDC_STATUS_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } if (fdc_get_bitcell_period() != get_bitcell_period()) { - fdc_notfound(); + fdc_notfound(FDC_STATUS_NOT_FOUND); disc_sector_state = STATE_IDLE; break; } diff --git a/src/fdc.c b/src/fdc.c index 070d05b..514bc07 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -5,12 +5,23 @@ #include "disc.h" #include "disc_sector.h" #include "dma.h" +#include "fdc.h" #include "fdd.h" #include "io.h" #include "pic.h" #include "timer.h" #include "x86.h" +#define ST1_DE (1 << 5) +#define ST1_ND (1 << 2) +#define ST1_NW (1 << 1) +#define ST1_MA (1 << 0) + +#define ST2_DD (1 << 5) +#define ST2_WC (1 << 4) /*Wrong cylinder*/ +#define ST2_BC (1 << 1) /*Bad cylinder*/ +#define ST2_MD (1 << 0) + static int fdc_reset_stat = 0; /*FDC*/ typedef struct FDC @@ -790,7 +801,6 @@ uint8_t fdc_read(uint16_t addr, void *priv) void fdc_callback() { int temp; - int doseek = 0; int drive; // pclog("fdc_callback %i\n", discint); @@ -1187,15 +1197,33 @@ void fdc_finishread() // rpclog("fdc_finishread\n"); } -void fdc_notfound() +void fdc_notfound(int reason) { +// pclog("fdc_notfound: reason=%i\n", reason); timer_disable(&fdc.timer); fdc_int(); fdc.stat=0xD0; fdc.res[4]=0x40|(fdc.head?4:0)|fdc.drive; - fdc.res[5]=5; - fdc.res[6]=0; + switch (reason) + { + case FDC_STATUS_AM_NOT_FOUND: + fdc.res[5] = ST1_ND | ST1_MA; + fdc.res[6] = 0; + break; + case FDC_STATUS_NOT_FOUND: + fdc.res[5] = ST1_ND; + fdc.res[6] = 0; + break; + case FDC_STATUS_WRONG_CYLINDER: + fdc.res[5] = ST1_ND; + fdc.res[6] = ST2_WC; + break; + case FDC_STATUS_BAD_CYLINDER: + fdc.res[5] = ST1_ND; + fdc.res[6] = ST2_WC | ST2_BC; + break; + } fdc.res[7] = fdc.rw_track; fdc.res[8] = fdc.head; fdc.res[9] = fdc.sector; diff --git a/src/fdc.h b/src/fdc.h index ff8d540..f0aecce 100644 --- a/src/fdc.h +++ b/src/fdc.h @@ -24,3 +24,13 @@ void fdc_update_boot_drive(int boot_drive); void fdc_update_densel_polarity(int densel_polarity); void fdc_update_densel_force(int densel_force); void fdc_update_drvrate(int drive, int drvrate); + + + +enum +{ + FDC_STATUS_AM_NOT_FOUND, + FDC_STATUS_NOT_FOUND, + FDC_STATUS_WRONG_CYLINDER, + FDC_STATUS_BAD_CYLINDER +};