2022-10-04 15:23:42 +00:00
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// X68000 EMULATOR "XM6"
|
|
|
|
|
//
|
|
|
|
|
// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
|
|
|
|
|
// Copyright (C) 2014-2020 GIMONS
|
|
|
|
|
//
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2022-12-03 04:20:27 +00:00
|
|
|
|
#include "hal/data_sample.h"
|
|
|
|
|
#include "hal/pin_control.h"
|
2022-11-10 06:44:06 +00:00
|
|
|
|
#include "shared/config.h"
|
|
|
|
|
#include "shared/scsi.h"
|
2022-10-04 15:23:42 +00:00
|
|
|
|
#include <array>
|
2022-12-03 04:20:27 +00:00
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <memory>
|
2022-10-04 15:23:42 +00:00
|
|
|
|
#include <unordered_map>
|
2022-12-03 04:20:27 +00:00
|
|
|
|
#include <vector>
|
|
|
|
|
#include <stdexcept>
|
2022-10-04 15:23:42 +00:00
|
|
|
|
using namespace std;
|
|
|
|
|
|
2022-12-03 04:20:27 +00:00
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// 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.
|
2023-11-15 06:51:21 +00:00
|
|
|
|
const static int SCSI_DELAY_SEND_DATA_DAYNAPORT_NS = 100'000;
|
2022-12-03 04:20:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class bus_exception : public runtime_error
|
2022-10-04 15:23:42 +00:00
|
|
|
|
{
|
2022-12-03 04:20:27 +00:00
|
|
|
|
using runtime_error::runtime_error;
|
|
|
|
|
};
|
2022-11-09 07:40:26 +00:00
|
|
|
|
|
2022-12-03 04:20:27 +00:00
|
|
|
|
class BUS : public PinControl
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// Operation modes definition
|
|
|
|
|
enum class mode_e {
|
|
|
|
|
TARGET = 0,
|
2023-11-14 15:03:25 +00:00
|
|
|
|
INITIATOR = 1
|
2022-12-03 04:20:27 +00:00
|
|
|
|
};
|
2022-11-09 07:40:26 +00:00
|
|
|
|
|
2022-12-03 04:20:27 +00:00
|
|
|
|
static int GetCommandByteCount(uint8_t);
|
2022-10-04 15:23:42 +00:00
|
|
|
|
|
2022-12-03 04:20:27 +00:00
|
|
|
|
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<DataSample> GetSample(uint64_t timestamp = 0) = 0;
|
|
|
|
|
virtual int CommandHandShake(vector<uint8_t> &) = 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_t, 8> phase_table;
|
|
|
|
|
|
|
|
|
|
static const unordered_map<phase_t, const char *> phase_str_mapping;
|
2022-10-04 15:23:42 +00:00
|
|
|
|
};
|