//--------------------------------------------------------------------------- // // X68000 EMULATOR "XM6" // // Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) // Copyright (C) 2014-2020 GIMONS // //--------------------------------------------------------------------------- #pragma once #include "hal/data_sample.h" #include "hal/pin_control.h" #include "shared/config.h" #include "shared/scsi.h" #include #include #include #include #include #include using namespace std; //--------------------------------------------------------------------------- // // Constant declarations (bus control timing) // //--------------------------------------------------------------------------- // SCSI Bus timings taken from: // https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-05.html const static int SCSI_DELAY_ARBITRATION_DELAY_NS = 2400; const static int SCSI_DELAY_ASSERTION_PERIOD_NS = 90; const static int SCSI_DELAY_BUS_CLEAR_DELAY_NS = 800; const static int SCSI_DELAY_BUS_FREE_DELAY_NS = 800; const static int SCSI_DELAY_BUS_SET_DELAY_NS = 1800; const static int SCSI_DELAY_BUS_SETTLE_DELAY_NS = 400; const static int SCSI_DELAY_CABLE_SKEW_DELAY_NS = 10; const static int SCSI_DELAY_DATA_RELEASE_DELAY_NS = 400; const static int SCSI_DELAY_DESKEW_DELAY_NS = 45; const static int SCSI_DELAY_DISCONNECTION_DELAY_US = 200; const static int SCSI_DELAY_HOLD_TIME_NS = 45; const static int SCSI_DELAY_NEGATION_PERIOD_NS = 90; const static int SCSI_DELAY_POWER_ON_TO_SELECTION_TIME_S = 10; // (recommended) const static int SCSI_DELAY_RESET_TO_SELECTION_TIME_US = 250 * 1000; // (recommended) const static int SCSI_DELAY_RESET_HOLD_TIME_US = 25; const static int SCSI_DELAY_SELECTION_ABORT_TIME_US = 200; const static int SCSI_DELAY_SELECTION_TIMEOUT_DELAY_NS = 250 * 1000; // (recommended) const static int SCSI_DELAY_FAST_ASSERTION_PERIOD_NS = 30; const static int SCSI_DELAY_FAST_CABLE_SKEW_DELAY_NS = 5; const static int SCSI_DELAY_FAST_DESKEW_DELAY_NS = 20; const static int SCSI_DELAY_FAST_HOLD_TIME_NS = 10; const static int SCSI_DELAY_FAST_NEGATION_PERIOD_NS = 30; // The DaynaPort SCSI Link do a short delay in the middle of transfering // a packet. This is the number of uS that will be delayed between the // header and the actual data. const static int SCSI_DELAY_SEND_DATA_DAYNAPORT_NS = 100'000; class bus_exception : public runtime_error { using runtime_error::runtime_error; }; class BUS : public PinControl { public: // Operation modes definition enum class mode_e { TARGET = 0, INITIATOR = 1 }; static int GetCommandByteCount(uint8_t); virtual bool Init(mode_e mode) = 0; virtual void Reset() = 0; virtual void Cleanup() = 0; phase_t GetPhase(); static phase_t GetPhase(int mci) { return phase_table[mci]; } // Get the string phase name, based upon the raw data static const char *GetPhaseStrRaw(phase_t current_phase); virtual uint32_t Acquire() = 0; virtual unique_ptr GetSample(uint64_t timestamp = 0) = 0; virtual int CommandHandShake(vector &) = 0; virtual int ReceiveHandShake(uint8_t *buf, int count) = 0; virtual int SendHandShake(uint8_t *buf, int count, int delay_after_bytes) = 0; // SEL signal event polling virtual bool PollSelectEvent() = 0; virtual bool GetSignal(int pin) const = 0; // Get SCSI input signal value virtual void SetSignal(int pin, bool ast) = 0; // Set SCSI output signal value static const int SEND_NO_DELAY = -1; // Passed into SendHandShake when we don't want to delay private: static const array phase_table; static const unordered_map phase_str_mapping; };