static void start_write_id( upd_fdc *f ) { int i; upd_fdc_drive *d = f->current_drive; d->fdd.data = f->mf ? 0x4e : 0xff; for( i = 40; i > 0; i-- ) /* write 40 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); if( f->mf ) /* MFM */ for( i = 40; i > 0; i-- ) /* write another 40 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); d->fdd.data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_preset( f ); if( f->mf ) { /* MFM */ d->fdd.data = 0xffc2; for( i = 3; i > 0; i-- ) { /* write 3 0xc2 with clock mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); } } d->fdd.data = 0x00fc | ( f->mf ? 0x0000 : 0xff00 ); /* write index mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); d->fdd.data = f->mf ? 0x4e : 0xff; /* postindex GAP */ for( i = 26; i > 0; i-- ) /* write 26 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); if( f->mf ) /* MFM */ for( i = 24; i > 0; i-- ) /* write another 24 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); f->main_status |= UPD_FDC_MAIN_DATAREQ | UPD_FDC_MAIN_DATA_WRITE; f->data_offset = 0; event_add_with_data( tstates + 2 * /* 1/10 revolution: 1 * 200 / 1000 */ machine_current->timings.processor_speed / 100, timeout_event, f ); }
void upd_fdc_write_data( upd_fdc *f, libspectrum_byte data ) { int i, terminated = 0; unsigned int u; upd_fdc_drive *d; if( !( f->main_status & UPD_FDC_MAIN_DATAREQ ) || ( f->main_status & UPD_FDC_MAIN_DATA_READ ) ) return; if( f->main_status & UPD_FDC_MAIN_BUSY && f->state == UPD_FDC_STATE_EXE ) { /* execution phase WRITE/FORMAT */ d = f->current_drive; if( f->cmd->id == UPD_CMD_WRITE_ID ) { /* FORMAT */ /* at the index hole... */ f->data_register[f->data_offset + 5] = data; /* read id fields */ f->data_offset++; if( f->data_offset == 4 ) { /* C, H, R, N done => format track */ event_remove_type( timeout_event ); d->fdd.data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_preset( f ); if( f->mf ) { /* MFM */ d->fdd.data = 0xffa1; for( i = 3; i > 0; i-- ) { /* write 3 0xa1 with clock mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } } d->fdd.data = 0x00fe | ( f->mf ? 0x0000 : 0xff00 ); /* write id mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); for( i = 0; i < 4; i++ ) { d->fdd.data = f->data_register[i + 5]; /* write id fields */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } d->fdd.data = f->crc >> 8; fdd_read_write_data( &d->fdd, FDD_WRITE ); /* write crc1 */ d->fdd.data = f->crc & 0xff; fdd_read_write_data( &d->fdd, FDD_WRITE ); /* write crc2 */ d->fdd.data = f->mf ? 0x4e : 0xff; for( i = 11; i > 0; i-- ) /* write 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); if( f->mf ) /* MFM */ for( i = 11; i > 0; i-- ) /* write another 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_WRITE ); d->fdd.data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_preset( f ); if( f->mf ) { /* MFM */ d->fdd.data = 0xffa1; for( i = 3; i > 0; i-- ) { /* write 3 0xa1 with clock mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } } d->fdd.data = 0x00fb | ( f->mf ? 0x0000 : 0xff00 ); /* write data mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); d->fdd.data = f->data_register[4]; /* write filler byte */ for( i = f->rlen; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } d->fdd.data = f->crc >> 8; fdd_read_write_data( &d->fdd, FDD_WRITE ); /* write crc1 */ d->fdd.data = f->crc & 0xff; fdd_read_write_data( &d->fdd, FDD_WRITE ); /* write crc2 */ d->fdd.data = f->mf ? 0x4e : 0xff; for( i = f->data_register[3]; i > 0; i-- ) { /* GAP */ fdd_read_write_data( &d->fdd, FDD_WRITE ); } f->data_offset = 0; f->data_register[2]--; /* prepare next sector */ }
libspectrum_byte upd_fdc_read_data( upd_fdc *f ) { libspectrum_byte r; upd_fdc_drive *d = f->current_drive; if( !( f->main_status & UPD_FDC_MAIN_DATAREQ ) || !( f->main_status & UPD_FDC_MAIN_DATA_READ ) ) return 0xff; if( f->state == UPD_FDC_STATE_EXE ) { /* READ_DATA/READ_DIAG */ f->data_offset++; /* count read bytes */ fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); /* read a byte */ /* Speedlock hack */ if( f->speedlock > 0 && !d->fdd.do_read_weak ) { /* do not conflict with fdd weak reads */ if( f->data_offset < 64 && d->fdd.data != 0xe5 ) f->speedlock = 2; /* W.E.C Le Mans type ... */ else if( ( f->speedlock > 1 || f->data_offset < 64 ) && !( f->data_offset % 29 ) ) { d->fdd.data ^= f->data_offset; /* mess up data */ crc_add( f, d ); /* mess up crc */ } } /* EOSpeedlock hack */ r = d->fdd.data & 0xff; if( f->data_offset == f->rlen ) { /* send only rlen byte to host */ while( f->data_offset < f->sector_length ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); f->data_offset++; } } if( ( f->cmd->id == UPD_CMD_READ_DIAG && f->data_offset == f->rlen ) || ( f->cmd->id == UPD_CMD_READ_DATA && f->data_offset == f->sector_length ) ) { /* read the CRC */ fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( f->crc != 0x000 ) { f->status_register[2] |= UPD_FDC_ST2_DATA_ERROR; f->status_register[1] |= UPD_FDC_ST1_CRC_ERROR; if( f->cmd->id == UPD_CMD_READ_DATA ) { /* READ DIAG not aborted! */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; cmd_result( f ); /* set up result phase */ return r; } } if( f->cmd->id == UPD_CMD_READ_DATA ) { if( f->ddam != f->del_data ) { /* we read a not 'wanted' sector... so */ if( f->data_register[5] > f->data_register[3] ) /* if we want to read more... */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; cmd_result( f ); /* set up result phase */ return r; } f->rev = 2; f->main_status &= ~UPD_FDC_MAIN_DATAREQ; start_read_data( f ); } else { /* READ DIAG */ f->data_register[3]++; /*FIXME ??? */ f->data_register[5]--; if( f->data_register[5] == 0 ) { /* no more */ cmd_result( f ); /* set up result phase */ return r; } f->main_status &= ~UPD_FDC_MAIN_DATAREQ; start_read_diag( f ); } } return r; } if( f->state != UPD_FDC_STATE_RES ) return 0xff; if( f->cmd->id == UPD_CMD_SENSE_DRIVE ) { /* 1 */ r = f->status_register[3]; } else if( f->cmd->id == UPD_CMD_SENSE_INT ) { /* 2 */ r = f->sense_int_res[f->cmd->res_length - f->cycle]; } else if( f->cmd->res_length - f->cycle < 3 ) { r = f->status_register[f->cmd->res_length - f->cycle]; } else { r = f->data_register[f->cmd->res_length - f->cycle - 2]; } f->cycle--; if( f->cycle == 0 ) { f->state = UPD_FDC_STATE_CMD; f->main_status |= UPD_FDC_MAIN_DATAREQ; f->main_status &= ~UPD_FDC_MAIN_DATADIR; f->main_status &= ~UPD_FDC_MAIN_BUSY; if( f->intrq < UPD_INTRQ_READY ) f->intrq = UPD_INTRQ_NONE; } return r; }
static int read_datamark( upd_fdc *f ) { upd_fdc_drive *d = f->current_drive; int i; if( f->mf ) { /* double density (MFM) */ for( i = 40; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.data == 0x4e ) /* read next */ continue; if( d->fdd.data == 0x00 ) /* go to PLL sync */ break; f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; /* something wrong... */ } for( ; i > 0; i-- ) { crc_preset( f ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.data == 0x00 ) continue; if( d->fdd.data == 0xffa1 ) /* got to a1 mark */ break; f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; } for( i = d->fdd.data == 0xffa1 ? 2 : 3; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.data != 0xffa1 ) { f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; } } fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.data < 0x00f8 || d->fdd.data > 0x00fb ) { /* !fb deleted mark */ f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; } if( d->fdd.data != 0x00fb ) f->ddam = 1; else f->ddam = 0; return 0; } else { /* SD -> FM */ for( i = 30; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.data == 0xff ) /* read next */ continue; if( d->fdd.data == 0x00 ) /* go to PLL sync */ break; f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; /* something wrong... */ } for( ; i > 0; i-- ) { crc_preset( f ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.data == 0x00 ) continue; if( d->fdd.data >= 0xfff8 && d->fdd.data <= 0xfffb ) /* !fb deleted mark */ break; f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; } if( i == 0 ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.data < 0xfff8 || d->fdd.data > 0xfffb ) { /* !fb deleted mark */ f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; } } if( d->fdd.data != 0x00fb ) f->ddam = 1; else f->ddam = 0; return 0; } f->status_register[2] |= UPD_FDC_ST2_MISSING_DM; return 1; }
static void start_write_data( upd_fdc *f ) { int i; upd_fdc_drive *d = f->current_drive; multi_track_next: if( f->first_rw || f->read_id || f->data_register[5] > f->data_register[3] ) { if( !f->read_id ) { if( !f->first_rw ) f->data_register[3]++; f->first_rw = 0; f->rev = 2; f->read_id = 1; } while( f->rev ) { i = f->current_drive->disk.i >= f->current_drive->disk.bpt ? 0 : f->current_drive->disk.i; /* start position */ if( seek_id( f ) == 0 ) f->rev = 0; else f->id_mark = UPD_FDC_AM_NONE; i = f->current_drive->disk.bpt ? ( f->current_drive->disk.i - i ) * 200 / f->current_drive->disk.bpt : 200; if( i > 0 ) { event_add_with_data( tstates + i * /* i * 1/20 revolution */ machine_current->timings.processor_speed / 1000, fdc_event, f ); return; } } f->read_id = 0; if( f->id_mark == UPD_FDC_AM_NONE ) { /* not found/crc error */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; goto abort_write_data; } for( i = 11; i > 0; i-- ) /* "delay" 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_READ ); if( f->mf ) /* MFM */ for( i = 11; i > 0; i-- ) /* "delay" another 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_READ ); d->fdd.data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_preset( f ); if( f->mf ) { /* MFM */ d->fdd.data = 0xffa1; for( i = 3; i > 0; i-- ) { /* write 3 0xa1 with clock mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } } d->fdd.data = ( f->del_data ? 0x00f8 : 0x00fb ) | ( f->mf ? 0x0000 : 0xff00 ); /* write data mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add( f, d ); } else { f->data_register[1]++; /* next track */ f->data_register[3] = 1; /* first sector */ if( f->mt ) { goto multi_track_next; } abort_write_data: f->state = UPD_FDC_STATE_RES; /* end of execution phase */ f->cycle = f->cmd->res_length; /* end of cylinder is set if: * 1. sector data is read completely * (i.e. no other errors occur like no data. * 2. sector being read is same specified by EOT * 3. terminal count is not received * note: in +3 uPD765 never got TC */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; f->status_register[1] |= UPD_FDC_ST1_EOF_CYLINDER; f->main_status &= ~UPD_FDC_MAIN_EXECUTION; f->intrq = UPD_INTRQ_RESULT; cmd_result( f ); return; } f->main_status |= UPD_FDC_MAIN_DATAREQ | UPD_FDC_MAIN_DATA_WRITE; f->data_offset = 0; event_remove_type( timeout_event ); event_add_with_data( tstates + 4 * /* 2 revolution: 2 * 200 / 1000 */ machine_current->timings.processor_speed / 10, timeout_event, f ); }
/* Read next ID into f->id_* return 0 if found an ID return 1 if found but with CRC error return 2 if not found ID */ static int read_id( upd_fdc *f ) { int i; upd_fdc_drive *d = f->current_drive; f->status_register[1] &= ~( UPD_FDC_ST1_CRC_ERROR | UPD_FDC_ST1_MISSING_AM | UPD_FDC_ST1_NO_DATA ); f->id_mark = UPD_FDC_AM_NONE; i = f->rev; while( i == f->rev && d->fdd.ready ) { fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.index ) f->rev--; crc_preset( f ); if( f->mf ) { /* double density (MFM) */ if( d->fdd.data == 0xffa1 ) { crc_add( f, d ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; if( d->fdd.data != 0xffa1 ) continue; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; if( d->fdd.data != 0xffa1 ) continue; } else { /* no 0xa1 with missing clock... */ continue; } } fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.index ) f->rev--; if( f->mf ) { /* double density (MFM) */ if( d->fdd.data != 0x00fe ) continue; } else { /* single density (FM) */ if( d->fdd.data != 0xfffe ) continue; } crc_add( f, d ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; f->id_track = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; f->id_head = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; f->id_sector = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; f->id_length = d->fdd.data > MAX_SIZE_CODE ? MAX_SIZE_CODE : d->fdd.data; f->sector_length = 0x80 << f->id_length; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add( f, d ); if( d->fdd.index ) f->rev--; if( f->crc != 0x0000 ) { f->status_register[1] |= UPD_FDC_ST1_CRC_ERROR | UPD_FDC_ST1_NO_DATA; f->id_mark = UPD_FDC_AM_ID; return 1; /* found but CRC error */ } else { f->id_mark = UPD_FDC_AM_ID; return 0; /* found and OK */ } } if(!d->fdd.ready) f->rev = 0; f->status_register[1] |= UPD_FDC_ST1_MISSING_AM | UPD_FDC_ST1_NO_DATA; /*FIXME _NO_DATA? */ return 2; /* not found */ }
libspectrum_byte wd_fdc_dr_read( wd_fdc *f ) { wd_fdc_drive *d = f->current_drive; if( f->state == WD_FDC_STATE_READ ) { f->data_offset++; /* count read bytes */ fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); /* read a byte */ if( d->fdd.data > 0xff ) { /* no data */ f->status_register |= WD_FDC_SR_RNF; f->status_register &= ~WD_FDC_SR_BUSY; f->status_type = WD_FDC_STATUS_TYPE2; f->state = WD_FDC_STATE_NONE; wd_fdc_set_intrq( f ); wd_fdc_reset_datarq( f ); } else { f->data_register = d->fdd.data; if( f->data_offset == f->sector_length ) { /* read the CRC */ fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); /* FIXME: make this per-FDC */ event_remove_type( timeout_event ); /* clear the timeout */ if( f->crc == 0x0000 && f->data_multisector ) { f->sector_register++; f->rev = 5; wd_fdc_reset_datarq( f ); event_add_with_data( tstates + /* 5 revolutions: 5 * 200 / 1000 */ machine_current->timings.processor_speed, timeout_event, f ); event_add_with_data( tstates + 2 * /* 20 ms delay */ machine_current->timings.processor_speed / 100, fdc_event, f ); } else { f->status_register &= ~WD_FDC_SR_BUSY; if( f->crc == 0x0000 ) f->status_register &= ~WD_FDC_SR_CRCERR; else f->status_register |= WD_FDC_SR_CRCERR; f->status_type = WD_FDC_STATUS_TYPE2; f->state = WD_FDC_STATE_NONE; wd_fdc_set_intrq( f ); wd_fdc_reset_datarq( f ); } } } } else if( f->state == WD_FDC_STATE_READID ) { switch( f->data_offset ) { case 0: /* track */ f->data_register = f->id_track; break; case 1: /* head */ f->data_register = f->id_head; break; case 2: /* sector */ f->data_register = f->id_sector; break; case 3: /* length */ f->data_register = f->id_length; break; case 4: /* crc1 */ f->data_register = f->crc >> 8; break; case 5: /* crc2 */ f->sector_register = f->id_track; f->data_register = f->crc & 0xff; f->status_register &= ~WD_FDC_SR_BUSY; f->status_type = WD_FDC_STATUS_TYPE2; f->state = WD_FDC_STATE_NONE; event_remove_type( timeout_event ); /* clear the timeout */ wd_fdc_set_intrq( f ); wd_fdc_reset_datarq( f ); break; default: break; } f->data_offset++; } else if( f->state == WD_FDC_STATE_READTRACK ) {
static void wd_fdc_type_ii_seek( wd_fdc *f ) { libspectrum_byte b = f->command_register; wd_fdc_drive *d = f->current_drive; int i; event_remove_type( fdc_event ); if( f->id_mark == WD_FDC_AM_NONE ) { f->read_id = 1; while( f->rev ) { i = f->current_drive->disk.i >= f->current_drive->disk.bpt ? 0 : f->current_drive->disk.i; /* start position */ if( !read_id( f ) ) { if( ( f->data_check_head != -1 && f->data_check_head != f->id_head ) || ( f->id_track != f->track_register || f->id_sector != f->sector_register ) ) { f->id_mark = WD_FDC_AM_NONE; } } else { f->id_mark = WD_FDC_AM_NONE; } i = f->current_drive->disk.bpt ? ( f->current_drive->disk.i - i ) * 200 / f->current_drive->disk.bpt : 200; if( i > 0 ) { event_add_with_data( tstates + i * /* i * 1/20 revolution */ machine_current->timings.processor_speed / 1000, fdc_event, f ); return; } else if( f->id_mark != WD_FDC_AM_NONE ) { break; } } } f->read_id = 0; if( f->id_mark == WD_FDC_AM_NONE ) { f->status_register |= WD_FDC_SR_RNF; f->status_register &= ~WD_FDC_SR_BUSY; f->state = WD_FDC_STATE_NONE; wd_fdc_set_intrq( f ); return; } if( f->state == WD_FDC_STATE_READ ) { if( f->id_mark == WD_FDC_AM_ID ) read_datamark( f ); if( f->id_mark == WD_FDC_AM_NONE ) { /* not found */ f->status_register |= WD_FDC_SR_RNF; f->status_register &= ~WD_FDC_SR_BUSY; f->state = WD_FDC_STATE_NONE; wd_fdc_set_intrq( f ); return; } if( f->ddam ) f->status_register |= WD_FDC_SR_SPINUP; /* set deleted data mark */ wd_fdc_set_datarq( f ); f->data_offset = 0; } else { f->ddam = b & 0x01; for( i = 11; i > 0; i-- ) /* "delay" 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_READ ); wd_fdc_set_datarq( f ); f->data_offset = 0; if( f->dden ) for( i = 11; i > 0; i-- ) /* "delay" another 11 GAP byte */ fdd_read_write_data( &d->fdd, FDD_READ ); d->fdd.data = 0x00; for( i = f->dden ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_preset( f ); if( f->dden ) { /* MFM */ d->fdd.data = 0xffa1; for( i = 3; i > 0; i-- ) { /* write 3 0xa1 with clock mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add(f, d); } } d->fdd.data = ( f->ddam ? 0x00f8 : 0x00fb ) | ( f->dden ? 0x0000 : 0xff00 ); /* write data mark */ fdd_read_write_data( &d->fdd, FDD_WRITE ); crc_add(f, d); } event_remove_type( timeout_event ); event_add_with_data( tstates + /* 5 revolutions: 5 * 200 / 1000 */ machine_current->timings.processor_speed, timeout_event, f ); }
static int read_datamark( wd_fdc *f ) { wd_fdc_drive *d = f->current_drive; int i; f->id_mark = WD_FDC_AM_NONE; if( f->dden ) { /* double density (MFM) */ for( i = 40; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.data == 0x4e ) /* read next */ continue; if( d->fdd.data == 0x00 ) /* go to PLL sync */ break; return 1; /* something wrong... */ } for( ; i > 0; i-- ) { crc_preset( f ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.data == 0x00 ) continue; if( d->fdd.data == 0xffa1 ) /* got to a1 mark */ break; return 1; } for( i = d->fdd.data == 0xffa1 ? 2 : 3; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.data != 0xffa1 ) return 1; } fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.data < 0x00f8 || d->fdd.data > 0x00fb ) /* !fb deleted mark */ return 1; if( d->fdd.data != 0x00fb ) f->ddam = 1; else f->ddam = 0; f->id_mark = WD_FDC_AM_DATA; return 0; } else { /* SD -> FM */ for( i = 30; i > 0; i-- ) { fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.data == 0xff ) /* read next */ continue; if( d->fdd.data == 0x00 ) /* go to PLL sync */ break; return 1; /* something wrong... */ } for( ; i > 0; i-- ) { crc_preset( f ); fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.data == 0x00 ) continue; if( d->fdd.data >= 0xfff8 && d->fdd.data <= 0xfffb ) /* !fb deleted mark */ break; return 1; } if( i == 0 ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.data < 0xfff8 || d->fdd.data > 0xfffb ) /* !fb deleted mark */ return 1; } if( d->fdd.data != 0x00fb ) f->ddam = 1; else f->ddam = 0; f->id_mark = WD_FDC_AM_DATA; return 0; } return 1; }
/* return 0 if found an ID return 1 if not found ID return 2 if found but with CRC error (READ ADDRESS command) */ static int read_id( wd_fdc *f ) { int i = f->rev; wd_fdc_drive *d = f->current_drive; f->id_mark = WD_FDC_AM_NONE; if( f->rev <= 0 ) return 1; while( i == f->rev ) { crc_preset( f ); if( f->dden ) { /* double density (MFM) */ fdd_read_write_data( &d->fdd, FDD_READ ); if( d->fdd.index ) f->rev--; crc_add(f, d); if( d->fdd.data == 0xffa1 ) { fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; if( d->fdd.data != 0xffa1 ) continue; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; if( d->fdd.data != 0xffa1 ) continue; } else { /* no 0xa1 with missing clock... */ continue; } } fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; if( f->dden ) { /* double density (MFM) */ if( d->fdd.data != 0x00fe ) continue; } else { /* single density (FM) */ if( d->fdd.data != 0xfffe ) continue; } fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; f->id_track = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; f->id_head = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; f->id_sector = d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; f->id_length = d->fdd.data; f->sector_length = 0x80 << d->fdd.data; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; fdd_read_write_data( &d->fdd, FDD_READ ); crc_add(f, d); if( d->fdd.index ) f->rev--; if( f->crc != 0x0000 ) { f->status_register |= WD_FDC_SR_CRCERR; f->id_mark = WD_FDC_AM_ID; return 2; } else { f->status_register &= ~WD_FDC_SR_CRCERR; f->id_mark = WD_FDC_AM_ID; return 0; } } return 1; }