Exemple #1
0
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 );
}
Exemple #2
0
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 );
}