mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-01 13:51:43 +00:00
7372996cf8
* Do not use the proprietary system timer for the DaynaPort delay work-around
109 lines
4.0 KiB
C++
109 lines
4.0 KiB
C++
//---------------------------------------------------------------------------
|
||
//
|
||
// 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 <array>
|
||
#include <cstdint>
|
||
#include <memory>
|
||
#include <unordered_map>
|
||
#include <vector>
|
||
#include <stdexcept>
|
||
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<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;
|
||
};
|