static void start_read_diag( upd_fdc *f ) { int i; if( !f->read_id ) { f->rev = 2; f->read_id = 1; } if( 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 ) != 2 ) f->rev = 0; 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 ) { f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; f->status_register[1] |= UPD_FDC_ST1_EOF_CYLINDER; goto abort_read_diag; } if( f->id_track != f->data_register[1] || f->id_sector != f->data_register[3] || f->data_register[2] != f->id_head ) { f->status_register[1] |= UPD_FDC_ST1_NO_DATA; } if( f->id_track != f->data_register[1] ) { /*FIXME UPD765 set it always? */ f->status_register[2] |= UPD_FDC_ST2_WRONG_CYLINDER; if( f->id_track == 0xff ) f->status_register[2] |= UPD_FDC_ST2_BAD_CYLINDER; } if( read_datamark( f ) > 0 ) { /* not found */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; goto abort_read_diag; } f->main_status |= UPD_FDC_MAIN_DATAREQ | UPD_FDC_MAIN_DATA_READ; 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 ); return; abort_read_diag: f->state = UPD_FDC_STATE_RES; /* end of execution phase */ f->cycle = f->cmd->res_length; f->main_status &= ~UPD_FDC_MAIN_EXECUTION; f->intrq = UPD_INTRQ_RESULT; cmd_result( f ); }
static void start_read_data( upd_fdc *f ) { int i; skip_deleted_sector: 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_read_data; } if( read_datamark( f ) > 0 ) { /* not found */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; goto abort_read_data; } if( f->ddam != f->del_data ) { f->status_register[2] |= UPD_FDC_ST2_CONTROL_MARK; if( f->sk ) { f->data_register[3]++; goto skip_deleted_sector; /* or not deleted but we want to read deleted */ } } } else { if( f->mt ) { f->data_register[1]++; /* next track */ f->data_register[3] = 1; /* first sector */ goto multi_track_next; } abort_read_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 */ if( !f->status_register[0] && !f->status_register[1] ) { f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; f->status_register[1] |= UPD_FDC_ST1_EOF_CYLINDER; } if( !( f->status_register[0] & ( UPD_FDC_ST0_INT_ABNORM | UPD_FDC_ST0_INT_READY ) ) ) { f->data_register[1]++; /* next track */ f->data_register[3] = 1; /* first sector */ } f->main_status &= ~UPD_FDC_MAIN_EXECUTION; f->intrq = UPD_INTRQ_RESULT; cmd_result( f ); return; } f->main_status |= UPD_FDC_MAIN_DATAREQ; if( f->cmd->id != UPD_CMD_SCAN ) f->main_status |= UPD_FDC_MAIN_DATA_READ; 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 ); }
static void wd_fdc_type_ii_seek( wd_fdc *f ) { libspectrum_byte b = f->command_register; fdd_t *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 = d->disk.i >= d->disk.bpt ? 0 : d->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 = d->disk.bpt ? ( d->disk.i - i ) * 200 / d->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 */ f->data_offset = 0; wd_fdc_set_datarq( f ); } else { f->ddam = b & 0x01; for( i = 11; i > 0; i-- ) /* "delay" 11 GAP byte */ fdd_read_data( d ); 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_data( d ); d->data = 0x00; for( i = f->dden ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_write_data( d ); crc_preset( f ); if( f->dden ) { /* MFM */ d->data = 0xffa1; for( i = 3; i > 0; i-- ) { /* write 3 0xa1 with clock mark */ fdd_write_data( d ); crc_add(f, d); } } d->data = ( f->ddam ? 0x00f8 : 0x00fb ) | ( f->dden ? 0x0000 : 0xff00 ); /* write data mark */ fdd_write_data( d ); 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 ); }