Exemplo n.º 1
0
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 */

}
Exemplo n.º 2
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 */

}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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 );
}