Example #1
0
        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);
            }
        }
Example #2
0
        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);
                }
            }
        }
Example #3
0
        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);
            }
        }