void wd_fdc_master_reset( wd_fdc *f ) { fdd_t *d = f->current_drive; f->spin_cycles = 0; f->direction = 0; f->head_load = 0; if( d ) { if( f->flags & WD_FLAG_BETA128 ) fdd_motoron( d, 0 ); else fdd_head_load( d, 0 ); } f->read_id = 0; f->hlt = 1; if( !( f->flags & WD_FLAG_NOHLT ) && f->hlt_time > 0 ) f->hlt = 0; f->intrq = 0; f->datarq = 0; f->state = WD_FDC_STATE_NONE; f->status_type = WD_FDC_STATUS_TYPE1; if( d != NULL ) { while( !d->tr00 ) fdd_step( d, FDD_STEP_OUT ); } f->track_register = 0; f->sector_register = 0; f->data_register = 0; f->status_register = WD_FDC_SR_LOST; /* track 0 */ }
void wd_fdc_master_reset( wd_fdc *f ) { wd_fdc_drive *d = f->current_drive; f->spin_cycles = 0; f->direction = 0; f->head_load = 0; f->read_id = 0; if( f->hlt_time > 0 ) f->hlt = 0; f->intrq = 0; f->datarq = 0; f->state = WD_FDC_STATE_NONE; f->status_type = WD_FDC_STATUS_TYPE1; if( d != NULL ) { while( !d->fdd.tr00 ) fdd_step( &d->fdd, FDD_STEP_OUT ); } f->track_register = 0; f->sector_register = 0; f->data_register = 0; f->status_register = WD_FDC_SR_LOST; /* track 0 */ }
static void seek_step( upd_fdc *f ) { int i; upd_fdc_drive *d; for( i = 0; i < 4; i++ ) { /* look after all disk... */ if( f->main_status & ( 1 << i ) ) { /* this drive in seek state */ d = f->drive[i]; if( f->pcn[i] == f->ncn[i] && f->seek[i] == 2 && !d->fdd.tr00 ) { /* recalibrate fail */ f->seek[i] = 5; /* abnormal termination */ f->intrq = UPD_INTRQ_SEEK; f->status_register[0] |= UPD_FDC_ST0_EQUIP_CHECK; f->main_status &= ~( 1 << i ); continue; } if( f->pcn[i] == f->ncn[i] || ( f->seek[i] == 2 && d->fdd.tr00 ) ) { /* end of seek */ if( f->seek[i] == 2 ) /* recalibrate */ f->pcn[i] = 0; f->seek[i] = 4; /* normal termination */ f->intrq = UPD_INTRQ_SEEK; f->main_status &= ~( 1 << i ); continue; } if( !d->fdd.ready ) { if( f->seek[i] == 2 ) /* recalibrate */ f->pcn[i] = f->rec[i] - ( 77 - f->pcn[i] ); /* restore PCN */ f->seek[i] = 6; /* drive not ready termination */ f->intrq = UPD_INTRQ_READY; /* doesn't matter */ f->main_status &= ~( 1 << i ); } else if( f->pcn[i] != f->ncn[i] ) { /**FIXME if d->tr00 == 1 ??? */ fdd_step( &d->fdd, f->pcn[i] > f->ncn[i] ? FDD_STEP_OUT : FDD_STEP_IN ); f->pcn[i] += f->pcn[i] > f->ncn[i] ? -1 : 1; } } } if( f->main_status & 0x0f ) { /* there is at least one active seek */ event_add_with_data( tstates + f->stp_rate * machine_current->timings.processor_speed / 1000, fdc_event, f ); } return; }
static void seek_step( upd_fdc *f, int start ) { int i, j; fdd_t *d; if( start ) { i = f->us; /* Drive already in seek state? */ if( f->main_status & ( 1 << i ) ) return; /* Mark seek mode for fdd. It will be cleared by Sense Interrupt command */ f->main_status |= 1 << i; } else { /* Get drive in seek state that has completed the positioning */ i=0; for( j = 1; j < 4; j++) { if( f->seek_age[j] > f->seek_age[i] ) i = j; } if( f->seek[i] == 0 || f->seek[i] >= 4 ) { return; } } d = f->drive[i]; /* There is need to seek? */ if( f->pcn[i] == f->ncn[i] && f->seek[i] == 2 && !d->tr00 ) { /* recalibrate fail */ f->seek[i] = 5; /* abnormal termination */ f->seek_age[i] = 0; f->intrq = UPD_INTRQ_SEEK; f->status_register[0] |= UPD_FDC_ST0_EQUIP_CHECK; f->main_status &= ~( 1 << i ); return; } /* There is need to seek? */ if( f->pcn[i] == f->ncn[i] || ( f->seek[i] == 2 && d->tr00 ) ) { /* correct position */ if( f->seek[i] == 2 ) /* recalibrate */ f->pcn[i] = 0; f->seek[i] = 4; /* normal termination */ f->seek_age[i] = 0; f->intrq = UPD_INTRQ_SEEK; f->main_status &= ~( 1 << i ); return; } /* Drive not ready */ if( !d->ready ) { if( f->seek[i] == 2 ) /* recalibrate */ f->pcn[i] = f->rec[i] - ( 77 - f->pcn[i] ); /* restore PCN */ f->seek[i] = 6; /* drive not ready termination */ f->seek_age[i] = 0; f->intrq = UPD_INTRQ_READY; /* doesn't matter */ f->main_status &= ~( 1 << i ); return; } /* Send step */ if( f->pcn[i] != f->ncn[i] ) { /**FIXME if d->tr00 == 1 ??? */ fdd_step( d, f->pcn[i] > f->ncn[i] ? FDD_STEP_OUT : FDD_STEP_IN ); f->pcn[i] += f->pcn[i] > f->ncn[i] ? -1 : 1; /* Update age for active seek operations */ for( j = 0; j < 4; j++) { if( f->seek_age[j] > 0 ) f->seek_age[j]++; } f->seek_age[i] = 1; /* wait step completion */ event_add_with_data( tstates + f->stp_rate * machine_current->timings.processor_speed / 1000, fdc_event, f ); } return; }
static void wd_fdc_type_i( wd_fdc *f ) { libspectrum_byte b = f->command_register; fdd_t *d = f->current_drive; if( f->state == WD_FDC_STATE_SEEK_DELAY ) { /* after delay */ if( ( b & 0x60 ) != 0x00 ) /* STEP/STEP-IN/STEP-OUT */ goto type_i_verify; goto type_i_loop; } else { /* WD_FDC_STATE_SEEK */ f->status_register |= WD_FDC_SR_SPINUP; } if( ( b & 0x60 ) != 0x00 ) { /* STEP/STEP-IN/STEP-OUT */ if( b & 0x40 ) f->direction = b & 0x20 ? FDD_STEP_OUT : FDD_STEP_IN; if( b & 0x10 ) /* update? */ goto type_i_update; goto type_i_noupdate; } /* SEEK or RESTORE */ if ( !( b & 0x10 ) ) { /* RESTORE */ f->track_register = 0xff; f->data_register = 0; } type_i_loop: if( f->track_register != f->data_register ) { f->direction = f->track_register < f->data_register ? FDD_STEP_IN : FDD_STEP_OUT; type_i_update: f->track_register += f->direction == FDD_STEP_IN ? 1 : -1; type_i_noupdate: if( d->tr00 && f->direction == FDD_STEP_OUT ) { f->track_register = 0; } else { fdd_step( d, f->direction ); f->state = WD_FDC_STATE_SEEK_DELAY; event_remove_type( fdc_event ); event_add_with_data( tstates + f->rates[ b & 0x03 ] * machine_current->timings.processor_speed / 1000, fdc_event, f ); return; } } type_i_verify: if( b & 0x04 ) { if( f->type == WD1773 || f->type == FD1793 || f->type == WD2797 ) { f->head_load = 1; event_remove_type( motor_off_event ); if( f->flags & WD_FLAG_BETA128 ) fdd_motoron( d, 1 ); else fdd_head_load( d, 1 ); event_remove_type( fdc_event ); event_add_with_data( tstates + 15 * /* 15ms */ machine_current->timings.processor_speed / 1000, fdc_event, f ); } f->state = WD_FDC_STATE_VERIFY; if( ( f->type == WD1770 || f->type == WD1772 ) && !( f->status_register & WD_FDC_SR_MOTORON ) ) { f->status_register |= WD_FDC_SR_MOTORON; fdd_motoron( f->current_drive, 1 ); event_remove_type( fdc_event ); event_add_with_data( tstates + 12 * /* 6 revolution 6 * 200 / 1000 */ machine_current->timings.processor_speed / 10, fdc_event, f ); return; } wd_fdc_seek_verify( f ); return; } if( d->tr00 ) f->status_register |= WD_FDC_SR_LOST; else f->status_register &= ~WD_FDC_SR_LOST; f->state = WD_FDC_STATE_NONE; f->status_register &= ~WD_FDC_SR_BUSY; wd_fdc_set_intrq( f ); }