예제 #1
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 {
예제 #2
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 );
}
예제 #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;
}
예제 #4
0
void
wd_fdc_cr_write( wd_fdc *f, libspectrum_byte b )
{
  fdd_t *d = f->current_drive;

  wd_fdc_reset_intrq( f );

  if( ( b & 0xf0 ) == 0xd0 ) {			/* Type IV - Force Interrupt */
    event_remove_type( fdc_event );
    f->status_register &= ~( WD_FDC_SR_BUSY   | WD_FDC_SR_WRPROT |
			     WD_FDC_SR_CRCERR | WD_FDC_SR_IDX_DRQ );
    f->state = WD_FDC_STATE_NONE;
    f->status_type = WD_FDC_STATUS_TYPE1;
    wd_fdc_reset_datarq( f );

    if( b & 0x08 )
      wd_fdc_set_intrq( f );
    else if( b & 0x04 ) {
      d->fdc_index = wd_fdc_wait_index;
      d->fdc = f;
    }

    if( d->tr00 )
      f->status_register |= WD_FDC_SR_LOST;
    else
      f->status_register &= ~WD_FDC_SR_LOST;

    wd_fdc_spinup( f, b & 0xf7 ); /* spinup motor, but we do not have a 'h' bit!  */

    return;
  }

  if( f->status_register & WD_FDC_SR_BUSY )
    return;

  f->command_register = b;
  f->status_register |= WD_FDC_SR_BUSY;

  /* keep spindle motor on: */
  event_remove_type( motor_off_event );

  if( !( b & 0x80 ) ) {                         /* Type I */
    f->state = WD_FDC_STATE_SEEK;
    f->status_type = WD_FDC_STATUS_TYPE1;
    f->status_register &= ~( WD_FDC_SR_CRCERR | WD_FDC_SR_RNF |
			     WD_FDC_SR_IDX_DRQ );
    wd_fdc_reset_datarq( f );

    f->rev = 5;
    if( wd_fdc_spinup( f, b ) )
      return;
    wd_fdc_type_i( f );
  } else if( !( b & 0x40 ) ) {                  /* Type II */
    if( f->type == WD1773 || f->type == FD1793 ) {
      if( !disk_ready( f ) ) {
        f->status_register &= ~WD_FDC_SR_BUSY;
        f->state = WD_FDC_STATE_NONE;
        wd_fdc_set_intrq( f );
        return;
      }
    }
    if( f->type == WD1773 && b & 0x02 )
      f->data_check_head = b & 0x08 ? 1 : 0;
    else if( f->type == WD2797 )
      f->data_check_head = b & 0x02 ? 1 : 0;
    else
      f->data_check_head = -1;

    /* WD2797 (and FD1797) can read sectors with non-IBM-compatible
       sector length codes */
    f->non_ibm_len_code = ( f->type == WD2797 && !( b & 0x08 ) ) ? 1 : 0;

    f->state = b & 0x20 ? WD_FDC_STATE_WRITE : WD_FDC_STATE_READ;
    f->status_type = WD_FDC_STATUS_TYPE2;
    f->status_register &= ~( WD_FDC_SR_WRPROT | WD_FDC_SR_RNF |
			     WD_FDC_SR_IDX_DRQ| WD_FDC_SR_LOST|
			     WD_FDC_SR_SPINUP );

    if( f->type == WD2797 ) fdd_set_head( d, b & 0x02 ? 1 : 0 );

    f->rev = 5;
    if( wd_fdc_spinup( f, b ) )
      return;
    wd_fdc_type_ii( f );
  } else if( ( b & 0x30 ) != 0x10 ) {           /* Type III */
    if( f->type == WD1773 || f->type == FD1793 || f->type == WD2797 ) {
      if( !disk_ready( f ) ) {
        f->status_register &= ~WD_FDC_SR_BUSY;
        f->state = WD_FDC_STATE_NONE;
        wd_fdc_set_intrq( f );
        return;
      }
    }

    f->state = b & 0x20 ? ( b & 0x10 ?
			    WD_FDC_STATE_WRITETRACK : WD_FDC_STATE_READTRACK ) :
		WD_FDC_STATE_READID;
    f->status_type = WD_FDC_STATUS_TYPE2;
    f->status_register &= ~( WD_FDC_SR_SPINUP | WD_FDC_SR_RNF |
			     WD_FDC_SR_IDX_DRQ| WD_FDC_SR_LOST );

    f->rev = 5;
    if( wd_fdc_spinup( f, b ) )
      return;
    wd_fdc_type_iii( f );
  }
}