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 {
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 ); }
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; }
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 ); } }