RASCSI/src/raspberrypi/scsi.h
Uwe Seimet ddeede2beb
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:

- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 16:53:53 +02:00

239 lines
5.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//---------------------------------------------------------------------------
//
// X68000 EMULATOR "XM6"
//
// Copyright (C) 2001-2006 (ytanaka@ipc-tokai.or.jp)
// Copyright (C) 2014-2020 GIMONS
//
// [ SCSI Common Functionality ]
//
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
//===========================================================================
//
// SCSI Bus
//
//===========================================================================
class BUS
{
public:
// Operation modes definition
enum mode_e {
TARGET = 0,
INITIATOR = 1,
MONITOR = 2,
};
// Phase definitions
enum phase_t : BYTE {
busfree,
arbitration,
selection,
reselection,
command,
execute, // Execute phase is an extension of the command phase
datain,
dataout,
status,
msgin,
msgout,
reserved // Unused
};
BUS() {}
virtual ~BUS() {}
// Basic Functions
virtual bool Init(mode_e mode) = 0;
virtual void Reset() = 0;
virtual void Cleanup() = 0;
phase_t GetPhase();
static phase_t GetPhase(DWORD mci)
{
return phase_table[mci];
}
// Get the string phase name, based upon the raw data
static const char* GetPhaseStrRaw(phase_t current_phase);
// Extract as specific pin field from a raw data capture
static inline DWORD GetPinRaw(DWORD raw_data, DWORD pin_num)
{
return ((raw_data >> pin_num) & 1);
}
virtual bool GetBSY() const = 0;
virtual void SetBSY(bool ast) = 0;
virtual bool GetSEL() const = 0;
virtual void SetSEL(bool ast) = 0;
virtual bool GetATN() const = 0;
virtual void SetATN(bool ast) = 0;
virtual bool GetACK() const = 0;
virtual void SetACK(bool ast) = 0;
virtual bool GetRST() const = 0;
virtual void SetRST(bool ast) = 0;
virtual bool GetMSG() const = 0;
virtual void SetMSG(bool ast) = 0;
virtual bool GetCD() const = 0;
virtual void SetCD(bool ast) = 0;
virtual bool GetIO() = 0;
virtual void SetIO(bool ast) = 0;
virtual bool GetREQ() const = 0;
virtual void SetREQ(bool ast) = 0;
virtual BYTE GetDAT() = 0;
virtual void SetDAT(BYTE dat) = 0;
virtual bool GetDP() const = 0; // Get parity signal
virtual DWORD Acquire() = 0;
virtual int CommandHandShake(BYTE *buf) = 0;
virtual int ReceiveHandShake(BYTE *buf, int count) = 0;
virtual int SendHandShake(BYTE *buf, int count, int delay_after_bytes) = 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
protected:
phase_t m_current_phase = phase_t::reserved;
private:
static const phase_t phase_table[8];
static const char* phase_str_table[];
};
namespace scsi_defs {
enum scsi_level : int {
SCSI_1_CCS = 1,
SCSI_2 = 2,
SPC = 3,
SPC_2 = 4,
SPC_3 = 5,
SPC_4 = 6,
SPC_5 = 7,
SPC_6 = 8
};
enum device_type : int {
DIRECT_ACCESS = 0,
PRINTER = 2,
PROCESSOR = 3,
CD_ROM = 5,
OPTICAL_MEMORY = 7,
COMMUNICATIONS = 9
};
enum scsi_command : int {
eCmdTestUnitReady = 0x00,
eCmdRezero = 0x01,
eCmdRequestSense = 0x03,
eCmdFormat = 0x04,
eCmdReassign = 0x07,
eCmdRead6 = 0x08,
// DaynaPort specific command
eCmdRetrieveStats = 0x09,
eCmdWrite6 = 0x0A,
eCmdSeek6 = 0x0B,
// DaynaPort specific command
eCmdSetIfaceMode = 0x0C,
// DaynaPort specific command
eCmdSetMcastAddr = 0x0D,
// DaynaPort specific command
eCmdEnableInterface = 0x0E,
eCmdSynchronizeBuffer = 0x10,
eCmdInquiry = 0x12,
eCmdModeSelect6 = 0x15,
eCmdReserve6 = 0x16,
eCmdRelease6 = 0x17,
eCmdModeSense6 = 0x1A,
eCmdStartStop = 0x1B,
eCmdSendDiag = 0x1D,
eCmdRemoval = 0x1E,
// ICD specific command
eCmdIcd = 0x1F,
eCmdReadCapacity10 = 0x25,
eCmdRead10 = 0x28,
eCmdWrite10 = 0x2A,
eCmdSeek10 = 0x2B,
eCmdVerify10 = 0x2F,
eCmdSynchronizeCache10 = 0x35,
eCmdReadDefectData10 = 0x37,
eCmdReadLong10 = 0x3E,
eCmdWriteLong10 = 0x3F,
eCmdReadToc = 0x43,
eCmdGetEventStatusNotification = 0x4A,
eCmdModeSelect10 = 0x55,
eCmdReserve10 = 0x56,
eCmdRelease10 = 0x57,
eCmdModeSense10 = 0x5A,
eCmdRead16 = 0x88,
eCmdWrite16 = 0x8A,
eCmdVerify16 = 0x8F,
eCmdSynchronizeCache16 = 0x91,
eCmdReadCapacity16_ReadLong16 = 0x9E,
eCmdWriteLong16 = 0x9F,
eCmdReportLuns = 0xA0
};
enum status : int {
GOOD = 0x00,
CHECK_CONDITION = 0x02,
CONDITION_MET = 0x04,
BUSY = 0x08,
INTERMEDIATE = 0x10,
INTERMEDIATE_CONDITION_MET = 0x14,
RESERVATION_CONFLICT = 0x18,
COMMAND_TERMINATED = 0x22,
QUEUE_FULL = 0x28
};
enum sense_key : int {
NO_SENSE = 0x00,
RECOVERED_ERROR = 0x01,
NOT_READY = 0x02,
MEDIUM_ERROR = 0x03,
HARDWARE_ERROR = 0x04,
ILLEGAL_REQUEST = 0x05,
UNIT_ATTENTION = 0x06,
DATA_PROTECT = 0x07,
BLANK_CHECK = 0x08,
VENDOR_SPECIFIC = 0x09,
COPY_ABORTED = 0x0a,
ABORTED_COMMAND = 0x0b,
VOLUME_OVERFLOW = 0x0d,
MISCOMPARE = 0x0e,
COMPLETED = 0x0f
};
enum asc : int {
NO_ADDITIONAL_SENSE_INFORMATION = 0x00,
WRITE_FAULT = 0x03,
READ_FAULT = 0x11,
INVALID_COMMAND_OPERATION_CODE = 0x20,
LBA_OUT_OF_RANGE = 0x21,
INVALID_FIELD_IN_CDB = 0x24,
INVALID_LUN = 0x25,
INVALID_FIELD_IN_PARAMETER_LIST = 0x26,
WRITE_PROTECTED = 0x27,
NOT_READY_TO_READY_CHANGE = 0x28,
POWER_ON_OR_RESET = 0x29,
MEDIUM_NOT_PRESENT = 0x3a,
LOAD_OR_EJECT_FAILED = 0x53
};
};