diff --git a/lib/drive.proto b/lib/drive.proto index 509959fe..e60a04b6 100644 --- a/lib/drive.proto +++ b/lib/drive.proto @@ -35,6 +35,15 @@ message DriveProto optional int32 tpi = 11 [ default = 96, (help) = "TPI of drive" ]; optional double rotational_period_ms = 12 [ default = 0, (help) = "Rotational period of the drive in milliseconds (0 to autodetect)"]; + + enum ErrorBehaviour { + NOTHING = 0; + JIGGLE = 1; + RECALIBRATE = 2; + } + + optional ErrorBehaviour error_behaviour = 15 + [ default = JIGGLE, (help) = "what to do when an error occurs during reads" ]; } // vim: ts=4 sw=4 et diff --git a/lib/fluxsource/fluxsource.h b/lib/fluxsource/fluxsource.h index 811952b3..a7dc04ad 100644 --- a/lib/fluxsource/fluxsource.h +++ b/lib/fluxsource/fluxsource.h @@ -19,10 +19,10 @@ class FlxFluxSourceProto; class FluxSourceIterator { public: - virtual ~FluxSourceIterator() {} + virtual ~FluxSourceIterator() {} - virtual bool hasNext() const = 0; - virtual std::unique_ptr next() = 0; + virtual bool hasNext() const = 0; + virtual std::unique_ptr next() = 0; }; class FluxSource @@ -31,33 +31,48 @@ public: virtual ~FluxSource() {} private: - static std::unique_ptr createCwfFluxSource(const CwfFluxSourceProto& config); - static std::unique_ptr createEraseFluxSource(const EraseFluxSourceProto& config); - static std::unique_ptr createFl2FluxSource(const Fl2FluxSourceProto& config); - static std::unique_ptr createFlxFluxSource(const FlxFluxSourceProto& config); - static std::unique_ptr createHardwareFluxSource(const HardwareFluxSourceProto& config); - static std::unique_ptr createKryofluxFluxSource(const KryofluxFluxSourceProto& config); - static std::unique_ptr createScpFluxSource(const ScpFluxSourceProto& config); - static std::unique_ptr createTestPatternFluxSource(const TestPatternFluxSourceProto& config); + static std::unique_ptr createCwfFluxSource( + const CwfFluxSourceProto& config); + static std::unique_ptr createEraseFluxSource( + const EraseFluxSourceProto& config); + static std::unique_ptr createFl2FluxSource( + const Fl2FluxSourceProto& config); + static std::unique_ptr createFlxFluxSource( + const FlxFluxSourceProto& config); + static std::unique_ptr createHardwareFluxSource( + const HardwareFluxSourceProto& config); + static std::unique_ptr createKryofluxFluxSource( + const KryofluxFluxSourceProto& config); + static std::unique_ptr createScpFluxSource( + const ScpFluxSourceProto& config); + static std::unique_ptr createTestPatternFluxSource( + const TestPatternFluxSourceProto& config); public: - static std::unique_ptr createMemoryFluxSource(const DiskFlux& flux); + static std::unique_ptr createMemoryFluxSource( + const DiskFlux& flux); static std::unique_ptr create(const FluxSourceProto& spec); - static void updateConfigForFilename(FluxSourceProto* proto, const std::string& filename); + static void updateConfigForFilename( + FluxSourceProto* proto, const std::string& filename); public: - virtual std::unique_ptr readFlux(int track, int side) = 0; + virtual std::unique_ptr readFlux( + int track, int side) = 0; virtual void recalibrate() {} - virtual bool isHardware() { return false; } + virtual void seek(int track) {} + virtual bool isHardware() + { + return false; + } }; class TrivialFluxSource : public FluxSource { public: std::unique_ptr readFlux(int track, int side); - virtual std::unique_ptr readSingleFlux(int track, int side) = 0; + virtual std::unique_ptr readSingleFlux( + int track, int side) = 0; }; #endif - diff --git a/lib/fluxsource/hardwarefluxsource.cc b/lib/fluxsource/hardwarefluxsource.cc index 165f7ed7..02f268f5 100644 --- a/lib/fluxsource/hardwarefluxsource.cc +++ b/lib/fluxsource/hardwarefluxsource.cc @@ -30,7 +30,9 @@ private: std::unique_ptr next() { - usbSetDrive(config.drive().drive(), config.drive().high_density(), config.drive().index_mode()); + usbSetDrive(config.drive().drive(), + config.drive().high_density(), + config.drive().index_mode()); usbSeek(_track); Bytes data = usbRead(_head, @@ -51,7 +53,7 @@ private: public: HardwareFluxSource(const HardwareFluxSourceProto& conf): _config(conf) { - measureDiskRotation(_oneRevolution, _hardSectorThreshold); + measureDiskRotation(_oneRevolution, _hardSectorThreshold); } ~HardwareFluxSource() {} @@ -59,8 +61,7 @@ public: public: std::unique_ptr readFlux(int track, int head) override { - return std::make_unique( - *this, track, head); + return std::make_unique(*this, track, head); } void recalibrate() override @@ -68,6 +69,11 @@ public: usbRecalibrate(); } + void seek(int track) override + { + usbSeek(track); + } + bool isHardware() override { return true; diff --git a/lib/readerwriter.cc b/lib/readerwriter.cc index 80b041d0..3e61a6fc 100644 --- a/lib/readerwriter.cc +++ b/lib/readerwriter.cc @@ -189,6 +189,26 @@ BadSectorsState combineRecordAndSectors(TrackFlux& trackFlux, return HAS_NO_BAD_SECTORS; } +static void adjustTrackOnError(FluxSource& fluxSource, int baseTrack) +{ + switch (config.drive().error_behaviour()) + { + case DriveProto::NOTHING: + break; + + case DriveProto::RECALIBRATE: + fluxSource.recalibrate(); + break; + + case DriveProto::JIGGLE: + if (baseTrack > 0) + fluxSource.seek(baseTrack - 1); + else + fluxSource.seek(baseTrack + 1); + break; + } +} + ReadResult readGroup(FluxSourceIteratorHolder& fluxSourceIteratorHolder, std::shared_ptr& trackInfo, TrackFlux& trackFlux, @@ -343,6 +363,7 @@ void writeTracksAndVerify(FluxSink& fluxSink, if (result != GOOD_READ) { + adjustTrackOnError(fluxSource, trackInfo->physicalTrack); Logger() << "bad read"; return false; } @@ -453,6 +474,7 @@ std::shared_ptr readAndDecodeTrack(FluxSource& fluxSource, break; } + adjustTrackOnError(fluxSource, trackInfo->physicalTrack); Logger() << fmt::format( "retrying; {} retries remaining", retriesRemaining); retriesRemaining--; @@ -584,7 +606,8 @@ void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink) unsigned index = 0; for (auto& trackInfo : locations) { - Logger() << OperationProgressLogMessage{index * 100 / (int)locations.size()}; + Logger() << OperationProgressLogMessage{ + index * 100 / (int)locations.size()}; index++; testForEmergencyStop();