Esempio n. 1
0
static void
plusd_cn_write( libspectrum_word port GCC_UNUSED, libspectrum_byte b )
{
  int drive, side;
  int i;

  plusd_control_register = b;

  drive = ( b & 0x03 ) == 2 ? 1 : 0;
  side = ( b & 0x80 ) ? 1 : 0;

  /* TODO: set current_drive to NULL when bits 0 and 1 of b are '00' or '11' */
  for( i = 0; i < PLUSD_NUM_DRIVES; i++ ) {
    fdd_set_head( &plusd_drives[ i ], side );
  }
  fdd_select( &plusd_drives[ (!drive) ], 0 );
  fdd_select( &plusd_drives[ drive ], 1 );

  if( plusd_fdc->current_drive != &plusd_drives[ drive ] ) {
    if( plusd_fdc->current_drive->motoron ) {            /* swap motoron */
      fdd_motoron( &plusd_drives[ (!drive) ], 0 );
      fdd_motoron( &plusd_drives[ drive ], 1 );
    }
    plusd_fdc->current_drive = &plusd_drives[ drive ];
  }

  printer_parallel_strobe_write( b & 0x40 );
}
Esempio n. 2
0
static libspectrum_byte
opus_6821_access( libspectrum_byte reg, libspectrum_byte data,
                  libspectrum_byte dir )
{
    int drive, side;
    int i;

    switch( reg & 0x03 ) {
    case 0:
        if( dir ) {
            if( control_a & 0x04 ) {
                data_reg_a = data;

                drive = ( data & 0x02 ) == 2 ? 1 : 0;
                side = ( data & 0x10 )>>4 ? 1 : 0;

                for( i = 0; i < OPUS_NUM_DRIVES; i++ ) {
                    fdd_set_head( &opus_drives[ i ], side );
                }

                fdd_select( &opus_drives[ (!drive) ], 0 );
                fdd_select( &opus_drives[ drive ], 1 );

                if( opus_fdc->current_drive != &opus_drives[ drive ] ) {
                    if( opus_fdc->current_drive->motoron ) {        /* swap motoron */
                        fdd_motoron( &opus_drives[ (!drive) ], 0 );
                        fdd_motoron( &opus_drives[ drive ], 1 );
                    }
                    opus_fdc->current_drive = &opus_drives[ drive ];
                }
            } else {
                data_dir_a = data;
            }
        } else {
Esempio n. 3
0
static int
wd_fdc_spinup( wd_fdc *f, libspectrum_byte b )
{
  libspectrum_dword delay = 0;
  fdd_t *d = f->current_drive;

  if( f->state != WD_FDC_STATE_SEEK && ( b & 0x04 ) )
    delay = 30;

  if( f->type == WD1770 || f->type == WD1772 ) {

    if( !( f->status_register & WD_FDC_SR_MOTORON ) ) {
      f->status_register |= WD_FDC_SR_MOTORON;
      fdd_motoron( d, 1 );
      if( !( b & 0x08 ) )
        delay += 6 * 200;
    }
  } else {			/* WD1773/FD1793/WD2797 */
    event_remove_type( motor_off_event );
    if( f->state == WD_FDC_STATE_SEEK ) {
      if( b & 0x08 ) {
	f->head_load = 1;
        if( f->flags & WD_FLAG_BETA128 )
          fdd_motoron( d, 1 );
        else
	  fdd_head_load( d, 1 );
      } else if( !( b & 0x04 ) ) {	/* HLD reset only if V flag == 0 too */
	f->head_load = 0;
        if( !( f->flags & WD_FLAG_NOHLT ) && f->hlt_time > 0 ) f->hlt = 0;		/* reset the trigger */
        if( f->flags & WD_FLAG_BETA128 )
          fdd_motoron( d, 0 );
        else
	  fdd_head_load( d, 0 );
      }
      return 0;
    } else {
      f->head_load = 1;
      if( f->flags & WD_FLAG_BETA128 )
        fdd_motoron( d, 1 );
      else
        fdd_head_load( d, 1 );
      if( f->hlt_time > 0 )
        delay += f->hlt_time;
    }
  }

  /* For Type III commands on WD2797 */
  if( f->type == WD2797 && ( b & 0xc0 ) == 0xc0 && ( b & 0x30 ) != 0x10 )
    fdd_set_head( d, b & 0x02 ? 1 : 0 );

  if( delay ) {
    event_remove_type( fdc_event );
    event_add_with_data( tstates + delay *
    		    machine_current->timings.processor_speed / 1000,
			fdc_event, f );
    return 1;
  }
  return 0;
}
Esempio n. 4
0
static int
wd_fdc_spinup( wd_fdc *f, libspectrum_byte b )
{
  libspectrum_dword delay = 0;

  if( f->state != WD_FDC_STATE_SEEK && ( b & 0x04 ) )
    delay = 30;

  if( f->type == WD1770 || f->type == WD1772 ) {
    if( !( b & 0x08 ) &&
	!( f->status_register & WD_FDC_SR_MOTORON ) ) {
      f->status_register |= WD_FDC_SR_MOTORON;
      fdd_motoron( &f->current_drive->fdd, 1 );
      statusbar_update( 1 );
      delay += 6 * 200;
    }
  } else {			/* WD1773/FD1793 */
    event_remove_type( motor_off_event );
    if( f->state == WD_FDC_STATE_SEEK ) {
      if( b & 0x08 ) {
	f->head_load = 1;
        if( f->flags & WD_FLAG_BETA128 )
          fdd_motoron( &f->current_drive->fdd, 1 );
        else
	  fdd_head_load( &f->current_drive->fdd, 1 );
	statusbar_update( 1 );
      } else {
	f->head_load = 0;
        if( f->hlt_time > 0 ) f->hlt = 0;		/* reset the trigger */
        if( f->flags & WD_FLAG_BETA128 )
          fdd_motoron( &f->current_drive->fdd, 0 );
        else
	  fdd_head_load( &f->current_drive->fdd, 0 );
	statusbar_update( 0 );
      }
      return 0;
    } else {
      f->head_load = 1;
      if( f->flags & WD_FLAG_BETA128 )
        fdd_motoron( &f->current_drive->fdd, 1 );
      else
        fdd_head_load( &f->current_drive->fdd, 1 );
      statusbar_update( 1 );
      if( f->hlt_time > 0 )
        delay += f->hlt_time;
    }
  }
  if( delay ) {
    event_remove_type( fdc_event );
    event_add_with_data( tstates + delay * 
    		    machine_current->timings.processor_speed / 1000,
			fdc_event, f );
    return 1;
  }
  return 0;
}
static void
didaktik_aux_write( libspectrum_word port GCC_UNUSED, libspectrum_byte b )
{
  if( ( b & 0x01 ) != ( aux_register & 0x01 ) )
    fdd_select( &didaktik_drives[ 0 ], b & 0x01 ? 1 : 0 );
  if( ( b & 0x02 ) != ( aux_register & 0x02 ) )
    fdd_select( &didaktik_drives[ 1 ], b & 0x02 ? 1 : 0 );
  didaktik_fdc->current_drive = &didaktik_drives[ b & 0x02 ? 1 : 0 ];

  if( ( b & 0x04 ) != ( aux_register & 0x04 ) )
    fdd_motoron( &didaktik_drives[ 0 ], b & 0x04 ? 1 : 0 );
  if( ( b & 0x08 ) != ( aux_register & 0x08 ) )
    fdd_motoron( &didaktik_drives[ 1 ], b & 0x08 ? 1 : 0 );

  aux_register = b;
}
Esempio n. 6
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 */

}
Esempio n. 7
0
static void
wd_fdc_event( libspectrum_dword last_tstates GCC_UNUSED, int event,
	      void *user_data )
{
  wd_fdc *f = user_data;
  fdd_t *d = f->current_drive;

  if( event == timeout_event ) {
    if( f->state == WD_FDC_STATE_READ       ||
	f->state == WD_FDC_STATE_WRITE      ||
	f->state == WD_FDC_STATE_READTRACK  ||
	f->state == WD_FDC_STATE_WRITETRACK ||
	f->state == WD_FDC_STATE_READID        ) {
      f->state = WD_FDC_STATE_NONE;
      f->status_register |= WD_FDC_SR_LOST;
      f->status_register &= ~WD_FDC_SR_BUSY;
      wd_fdc_reset_datarq( f );
      wd_fdc_set_intrq( f );
    }
    return;
  }

  if( event == motor_off_event ) {
    if( f->type == WD1770 || f->type == WD1772 ) {
      f->status_register &= ~WD_FDC_SR_MOTORON;
      fdd_motoron( d, 0 );
    } else {						/* WD1773/FD1973 */
      f->head_load = 0;
      if( f->flags & WD_FLAG_BETA128 )
        fdd_motoron( d, 0 );
      else
        fdd_head_load( d, 0 );
    }
    return;
  }

  if( ( f->type == WD1773 || f->type == FD1793 || f->type == WD2797 ) &&
        f->hlt_time > 0 && f->head_load && !f->hlt )
    f->hlt = 1;

  if( ( ( f->type == WD1770 || f->type == WD1772 ) &&
	( f->status_register & WD_FDC_SR_MOTORON ) &&
	f->status_type == WD_FDC_STATUS_TYPE1 ) ||
      ( ( f->type == WD1773 || f->type == FD1793 || f->type == WD2797 ) &&
	( f->state == WD_FDC_STATE_SEEK ||
	  f->state == WD_FDC_STATE_SEEK_DELAY ) &&
	f->head_load ) ) {
    f->status_register |= WD_FDC_SR_SPINUP;
  }

  if( f->read_id ) {
    if( f->state == WD_FDC_STATE_VERIFY )
      wd_fdc_seek_verify_read_id( f );
    else if( ( f->state == WD_FDC_STATE_READ || f->state == WD_FDC_STATE_WRITE ) &&
	     f->datarq )
      f->datarq = 0, wd_fdc_set_datarq( f );
    else if( f->state == WD_FDC_STATE_READ || f->state == WD_FDC_STATE_WRITE )
      wd_fdc_type_ii_seek( f );
    else if( f->state == WD_FDC_STATE_READID )
      wd_fdc_type_iii( f );
  } else if( f->state == WD_FDC_STATE_SEEK || f->state == WD_FDC_STATE_SEEK_DELAY )
    wd_fdc_type_i( f );
  else if( f->state == WD_FDC_STATE_VERIFY )
    wd_fdc_seek_verify( f );
  else if( ( f->state == WD_FDC_STATE_READ || f->state == WD_FDC_STATE_WRITE ) &&
	   f->datarq )
    f->datarq = 0, wd_fdc_set_datarq( f );
  else if( f->state == WD_FDC_STATE_READ || f->state == WD_FDC_STATE_WRITE )
    wd_fdc_type_ii( f );
  else if( ( f->state == WD_FDC_STATE_READTRACK  ||
	     f->state == WD_FDC_STATE_READID     ||
	     f->state == WD_FDC_STATE_WRITETRACK   ) &&
	   f->datarq )
      f->datarq = 0, wd_fdc_set_datarq( f );
  else if( f->state == WD_FDC_STATE_READTRACK  ||
	   f->state == WD_FDC_STATE_READID     ||
	   f->state == WD_FDC_STATE_WRITETRACK    )
    wd_fdc_type_iii( f );
}
Esempio n. 8
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 );
}