static void start_write_id( upd_fdc *f ) { int i; fdd_t *d = f->current_drive; d->data = f->mf ? 0x4e : 0xff; for( i = 40; i > 0; i-- ) /* write 40 GAP byte */ fdd_write_data( d ); if( f->mf ) /* MFM */ for( i = 40; i > 0; i-- ) /* write another 40 GAP byte */ fdd_write_data( d ); d->data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_write_data( d ); crc_preset( f ); if( f->mf ) { /* MFM */ d->data = 0xffc2; for( i = 3; i > 0; i-- ) { /* write 3 0xc2 with clock mark */ fdd_write_data( d ); } } d->data = 0x00fc | ( f->mf ? 0x0000 : 0xff00 ); /* write index mark */ fdd_write_data( d ); d->data = f->mf ? 0x4e : 0xff; /* postindex GAP */ for( i = 26; i > 0; i-- ) /* write 26 GAP byte */ fdd_write_data( d ); if( f->mf ) /* MFM */ for( i = 24; i > 0; i-- ) /* write another 24 GAP byte */ fdd_write_data( d ); f->main_status |= UPD_FDC_MAIN_DATAREQ | UPD_FDC_MAIN_DATA_WRITE; f->data_offset = 0; event_add_with_data( tstates + 2 * /* 1/10 revolution: 1 * 200 / 1000 */ machine_current->timings.processor_speed / 100, timeout_event, f ); }
void upd_fdc_write_data( upd_fdc *f, libspectrum_byte data ) { int i, terminated = 0; unsigned int u; fdd_t *d; if( !( f->main_status & UPD_FDC_MAIN_DATAREQ ) || ( f->main_status & UPD_FDC_MAIN_DATA_READ ) ) return; if( f->main_status & UPD_FDC_MAIN_BUSY && f->state == UPD_FDC_STATE_EXE ) { /* execution phase WRITE/FORMAT */ d = f->current_drive; if( f->cmd->id == UPD_CMD_WRITE_ID ) { /* FORMAT */ /* at the index hole... */ f->data_register[f->data_offset + 5] = data; /* read id fields */ f->data_offset++; if( f->data_offset == 4 ) { /* C, H, R, N done => format track */ event_remove_type( timeout_event ); d->data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_write_data( d ); crc_preset( f ); if( f->mf ) { /* 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 = 0x00fe | ( f->mf ? 0x0000 : 0xff00 ); /* write id mark */ fdd_write_data( d ); crc_add( f, d ); for( i = 0; i < 4; i++ ) { d->data = f->data_register[i + 5]; /* write id fields */ fdd_write_data( d ); crc_add( f, d ); } d->data = f->crc >> 8; fdd_write_data( d ); /* write crc1 */ d->data = f->crc & 0xff; fdd_write_data( d ); /* write crc2 */ d->data = f->mf ? 0x4e : 0xff; for( i = 11; i > 0; i-- ) /* write 11 GAP byte */ fdd_write_data( d ); if( f->mf ) /* MFM */ for( i = 11; i > 0; i-- ) /* write another 11 GAP byte */ fdd_write_data( d ); d->data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_write_data( d ); crc_preset( f ); if( f->mf ) { /* 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 = 0x00fb | ( f->mf ? 0x0000 : 0xff00 ); /* write data mark */ fdd_write_data( d ); crc_add( f, d ); d->data = f->data_register[4]; /* write filler byte */ for( i = f->rlen; i > 0; i-- ) { fdd_write_data( d ); crc_add( f, d ); } d->data = f->crc >> 8; fdd_write_data( d ); /* write crc1 */ d->data = f->crc & 0xff; fdd_write_data( d ); /* write crc2 */ d->data = f->mf ? 0x4e : 0xff; for( i = f->data_register[3]; i > 0; i-- ) { /* GAP */ fdd_write_data( d ); } f->data_offset = 0; f->data_register[2]--; /* prepare next sector */ }
static void start_write_data( upd_fdc *f ) { int i; fdd_t *d = f->current_drive; 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_write_data; } for( i = 11; i > 0; i-- ) /* "delay" 11 GAP byte */ fdd_read_data( d ); if( f->mf ) /* MFM */ for( i = 11; i > 0; i-- ) /* "delay" another 11 GAP byte */ fdd_read_data( d ); d->data = 0x00; for( i = f->mf ? 12 : 6; i > 0; i-- ) /* write 6/12 zero */ fdd_write_data( d ); crc_preset( f ); if( f->mf ) { /* 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->del_data ? 0x00f8 : 0x00fb ) | ( f->mf ? 0x0000 : 0xff00 ); /* write data mark */ fdd_write_data( d ); crc_add( f, d ); } else { f->data_register[1]++; /* next track */ f->data_register[3] = 1; /* first sector */ if( f->mt ) { goto multi_track_next; } abort_write_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 */ f->status_register[0] |= UPD_FDC_ST0_INT_ABNORM; f->status_register[1] |= UPD_FDC_ST1_EOF_CYLINDER; f->main_status &= ~UPD_FDC_MAIN_EXECUTION; f->intrq = UPD_INTRQ_RESULT; cmd_result( f ); return; } f->main_status |= UPD_FDC_MAIN_DATAREQ | UPD_FDC_MAIN_DATA_WRITE; 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 ); }