private void Seek(int track, Type1CommandParams p) { _seekDestination = track; _seekError = false; // Schedule the first step of the heads _system.Scheduler.Schedule(_commandBeginNsec, p, SeekCallback); if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Seek to {0} initialized.", track); } }
private void SeekCallback(ulong skewNsec, object context) { if (_commandAbort) { // // Abort the seek, perform no head steps and update no registers. // if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Seek aborted by ForceInterrupt."); } return; } // Set the FDC busy status. _busy = true; if (_fdcTrack == _seekDestination) { // We've arrived. Everyone out of the car. // Clear the FDC Type I BUSY status _busy = false; // // Do a verification. Since we're not emulating the floppy at a level // low enough to verify header CRC and sector IDs, we assume those are OK // and only compare our Physical track counter with the FDC's track counter. // Type1CommandParams p = (Type1CommandParams)context; if (p.Verify && _drive.IsLoaded && (_fdcTrack != _drive.Track)) { _seekError = true; } _headLoaded = p.HeadLoad; RaiseInterrupt(); if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Seek to {0} (physical {1}) completed.", _seekDestination, _drive.Track); } } else { // Not there yet, move one step in the right direction. if (_fdcTrack < _seekDestination) { _fdcTrack++; _drive.SeekTo(_drive.Track + 1); } else { _fdcTrack--; _drive.SeekTo(_drive.Track - 1); } _system.Scheduler.Schedule(_stepTimeNsec, context, SeekCallback); if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Seek step to {0} (physical {1})", _fdcTrack, _drive.Track); } } }
private void Step(StepDirection direction, Type1CommandParams p) { if (direction != StepDirection.Last) { _stepDirection = direction; } _seekError = false; // Schedule a step of the heads. if (!_busy) { _system.Scheduler.Schedule( _commandBeginNsec, (timestampNsec, context) => { if (_commandAbort) { // // Abort the step, perform no head steps and update no registers. // if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Step aborted by ForceInterrupt."); } return; } if (!_busy) { // Raise the busy flag -- the command has been accepted. _busy = true; // Schedule the actual step _system.Scheduler.Schedule( _stepTimeNsec, (ts, ctx) => { switch (_stepDirection) { case StepDirection.Out: // one track closer to the outer edge _drive.SeekTo(_drive.Track - 1); if (p.Update) { _fdcTrack--; } break; case StepDirection.In: // one track closer to the inner edge _drive.SeekTo(_drive.Track + 1); if (p.Update) { _fdcTrack++; } break; default: throw new InvalidOperationException("Unepxected step type."); } if (p.Verify && _drive.IsLoaded && (_fdcTrack != _drive.Track)) { _seekError = true; } _headLoaded = p.HeadLoad; RaiseInterrupt(); // // Reset the busy flag, the step is complete. // _busy = false; if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Step to {0} (physical {1}) completed.", _seekDestination, _drive.Track); } }); } }); } if (Log.Enabled) { Log.Write(LogComponent.IOPFloppy, "Step {0} initialized.", _stepDirection); } }