|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2018 [email protected] ! 4: // ! 5: ! 6: #pragma once ! 7: ! 8: #include "device.h" ! 9: ! 10: class SCSI ! 11: { ! 12: public: ! 13: // デバイス種別 ! 14: enum DevType { ! 15: None = 0, ! 16: HD = 1, ! 17: }; ! 18: ! 19: // フェーズは、バスフェーズと転送フェーズを一緒くたで扱う。 ! 20: // 0から7までは転送フェーズを表しているのでこの順序を守ること。 ! 21: // 8以上はバスフェーズを表している。 ! 22: struct Phase { // MSG CD IO ! 23: static const uint DataOut = 0x00; // 0 0 0 ! 24: static const uint DataIn = 0x01; // 0 0 1 ! 25: static const uint Command = 0x02; // 0 1 0 ! 26: static const uint Status = 0x03; // 0 1 1 ! 27: static const uint MsgOut = 0x06; // 1 1 0 ! 28: static const uint MsgIn = 0x07; // 1 1 1 ! 29: ! 30: static const uint BusFree = 8; ! 31: static const uint Arbitration = 9; ! 32: static const uint Selection = 10; ! 33: static const uint Reselection = 11; ! 34: ! 35: static const uint MAX = 12; // 最大値 +1 にすること ! 36: }; ! 37: ! 38: // コマンド。 ! 39: // ダイレクトアクセスデバイスのコマンドを元にしている。 ! 40: // シーケンシャルアクセスデバイスでは 0x01 が Rewind だったり ! 41: // 同じコードで違うコマンドのようだが、とりあえずそれは放置。 ! 42: struct Command { ! 43: // Group0 ! 44: static const uint TestUnitReady = 0x00; // 共通 ! 45: static const uint RezeroUnit = 0x01; ! 46: static const uint RequestSense = 0x03; // 共通 ! 47: static const uint FormatUnit = 0x04; ! 48: static const uint ReassignBlocks = 0x07; ! 49: static const uint Read6 = 0x08; ! 50: static const uint Write6 = 0x0a; ! 51: static const uint Seek6 = 0x0b; ! 52: static const uint Inquiry = 0x12; // 共通 ! 53: static const uint ModeSelect6 = 0x15; // 共通 ! 54: static const uint Reserve = 0x16; ! 55: static const uint Release = 0x17; ! 56: static const uint Copy = 0x18; // 共通 ! 57: static const uint ModeSense6 = 0x1a; ! 58: static const uint StartStopUnit = 0x1b; ! 59: static const uint ReceiveDiagnosticResults = 0x1c; // 共通 ! 60: static const uint SendDiagnostic = 0x1d; // 共通 ! 61: static const uint PreventAllowMediumRemoval = 0x1e; ! 62: // Group1 ! 63: static const uint ReadCapacity = 0x25; ! 64: static const uint Read10 = 0x28; ! 65: static const uint Write10 = 0x2a; ! 66: static const uint Seek10 = 0x2b; ! 67: // Group1 ! 68: static const uint WriteAndVerify10 = 0x2e; ! 69: static const uint Verify10 = 0x2f; ! 70: static const uint SearchDataHigh10 = 0x30; ! 71: static const uint SearchDataEqual10 = 0x31; ! 72: static const uint SearchDataLow10 = 0x32; ! 73: static const uint SetLimits = 0x33; ! 74: static const uint PreFetch = 0x34; ! 75: static const uint SynchronizeCache = 0x35; ! 76: static const uint LockUnlockCache = 0x36; ! 77: static const uint ReadDefectData10 = 0x37; ! 78: static const uint Compare = 0x39; // 共通 ! 79: static const uint CopyAndVerify = 0x3a; // 共通 ! 80: static const uint WriteBuffer = 0x3b; // 共通 ! 81: static const uint ReadBuffer = 0x3c; // 共通 ! 82: static const uint ReadLong = 0x3e; ! 83: static const uint WriteLong = 0x3f; ! 84: // Group2 ! 85: static const uint ChangeDefinition = 0x40; ! 86: static const uint WriteSame = 0x41; ! 87: static const uint LogSelect = 0x4c; // 共通 ! 88: static const uint LogSense = 0x4d; // 共通 ! 89: static const uint ModeSelect10 = 0x55; // 共通 ! 90: static const uint ModeSense10 = 0x5a; // 共通 ! 91: static const uint MAX = 0x5b; // 最大値+1にすること ! 92: }; ! 93: ! 94: // ステータスバイト ! 95: struct StatusByte { ! 96: static const uint8 Good = (0x00 << 1); ! 97: static const uint8 CheckCondition = (0x01 << 1); ! 98: static const uint8 ConditionMet = (0x02 << 1); ! 99: static const uint8 Busy = (0x04 << 1); ! 100: static const uint8 Intermediate = (0x08 << 1); ! 101: static const uint8 IntermediateCondMet = (0x0a << 1); ! 102: static const uint8 ReservationConflict = (0x0c << 1); ! 103: static const uint8 CommandTerminated = (0x11 << 1); ! 104: static const uint8 QueueFull = (0x14 << 1); ! 105: }; ! 106: ! 107: // メッセージバイト ! 108: struct MsgByte { ! 109: static const uint8 CommandComplete = 0x00; ! 110: static const uint8 ExtendMessage = 0x01; ! 111: static const uint8 SaveDataPointer = 0x02; ! 112: static const uint8 RestorePointers = 0x03; ! 113: static const uint8 Disconnect = 0x04; ! 114: static const uint8 InitiatorDetectedError = 0x05; ! 115: static const uint8 Abort = 0x06; ! 116: static const uint8 MessageReject = 0x07; ! 117: static const uint8 NoOperation = 0x08; ! 118: static const uint8 MessageParityError = 0x09; ! 119: static const uint8 LinkedCommandComplete = 0x0a; ! 120: static const uint8 LinkedCommandCompleteWithFlag = 0x0b; ! 121: static const uint8 BusDeviceReset = 0x0c; ! 122: static const uint8 AbortTag = 0x0d; ! 123: static const uint8 ClearQueue = 0x0e; ! 124: static const uint8 InitiateRecovery = 0x0f; ! 125: static const uint8 ReleaseRecovery = 0x10; ! 126: static const uint8 TerminateIOProcess = 0x11; ! 127: static const uint8 SimpleQueueTag = 0x20; ! 128: static const uint8 HeadOfQueueTag = 0x21; ! 129: static const uint8 OrderedQueueTag = 0x22; ! 130: static const uint8 IgnoreWideResidue = 0x23; ! 131: static const uint8 Identify = 0x80; // 0x80..0xff ! 132: }; ! 133: ! 134: // Mode Select(6) ヘッダ ! 135: struct ModeParamHdr { ! 136: uint8 mode_param_len; // ヘッダ以降のバイト数 ! 137: uint8 media_type; ! 138: uint8 device_specific_param; ! 139: uint8 block_desc_len; // 0 か 8の倍数 ! 140: } __packed; ! 141: ! 142: // Mode Select(6) ブロックディスクリプタ ! 143: struct BlockDesc { ! 144: uint8 density_code; ! 145: uint8 block_cnt[3]; // ブロック数 ! 146: uint8 reserved; ! 147: uint8 block_size[3]; // 論理ブロック長 (バイト) ! 148: } __packed; ! 149: ! 150: // フェーズ名を返す。 ! 151: static const char *GetPhaseName(uint); ! 152: ! 153: // SCSI コマンド名を返す。 ! 154: static const char *GetCommandName(uint8); ! 155: ! 156: private: ! 157: static const char * const phasename[Phase::MAX]; ! 158: static const char * const commandname[Command::MAX]; ! 159: }; ! 160: ! 161: class SCSIHostDevice : public IODevice ! 162: { ! 163: typedef IODevice inherited; ! 164: public: ! 165: SCSIHostDevice(); ! 166: virtual ~SCSIHostDevice(); ! 167: ! 168: virtual bool Create(); ! 169: ! 170: // このホストデバイスを示す接頭語を取得する ! 171: const char *GetConfigName() const { return config_name; } ! 172: ! 173: // ログ識別子を取得する ! 174: const std::string& GetLogName() const { return logname; } ! 175: ! 176: // 自身の SCSI ID (0..7) ! 177: int myid = 0; ! 178: ! 179: // SCSI ターゲット。[0] が ID0, … ! 180: // 未接続とイニシエータは NULL。 ! 181: SCSITarget *target[8] {}; ! 182: ! 183: // Select されているターゲット ID ! 184: // 選択されていない状態では -1 ! 185: int tgtid = 0; ! 186: ! 187: // Bus Phase ! 188: ! 189: // バスフェーズが変化した時刻 ! 190: uint64 BusPhaseTime = 0; ! 191: ! 192: // 各バスフェーズへ遷移する ! 193: void B_BusFree(int id); ! 194: ! 195: bool Arbitration(int id); ! 196: bool ArbitrationAck(int id); ! 197: ! 198: void InitiatorSelection(int targetid); ! 199: void TargetSelectionAck(int targetid); ! 200: void InitiatorSelectionAck(); ! 201: ! 202: void TargetReselection(int targetid, int initiatorID); ! 203: void InitiatorReselectionAck(); ! 204: void TargetReselectionAck(int targetid); ! 205: void InitiatorReselectionAck2(); ! 206: ! 207: #if 0 ! 208: // Xfer Phase ! 209: SCSI::XferPhase GetXferPhase() const { return xfer_phase; } ! 210: ! 211: // 各転送フェーズへ遷移する ! 212: void X_DataOut(); ! 213: void X_DataIn(); ! 214: void X_Command(); ! 215: void X_Status(); ! 216: void X_MsgOut(); ! 217: void X_MsgIn(); ! 218: #endif ! 219: ! 220: uint8 DATA = 0; ! 221: uint8 GetDATA() const { return DATA; } ! 222: void SetDATA(uint8 data); ! 223: ! 224: // 信号線はいずれも true でアサート ! 225: bool REQ = false; // REQ 信号 ! 226: bool GetREQ() const { return REQ; } ! 227: void SetREQ(bool val); ! 228: ! 229: bool ACK = false; // ACK 信号 ! 230: bool GetACK() const { return ACK; } ! 231: void SetACK(bool val); ! 232: ! 233: // RST も本来は OR-tied だが、ここではあまり意味がないので bool にする。 ! 234: bool RST = false; // RST 信号 ! 235: bool GetRST() const { return RST; } ! 236: void SetRST(bool val); ! 237: ! 238: uint8 SEL = false; // SEL 信号 ! 239: bool GetSEL() const { return SEL != 0; } ! 240: void AssertSEL(int id); ! 241: void NegateSEL(int id); ! 242: ! 243: uint8 BSY = false; // BSY 信号 ! 244: bool GetBSY() const { return BSY != 0; } ! 245: void AssertBSY(int id); ! 246: void NegateBSY(int id); ! 247: ! 248: bool MSG = false; // MSG 信号 ! 249: bool GetMSG() const { return MSG; } ! 250: void SetMSG(bool val); ! 251: ! 252: bool CD = false; // CD 信号 ! 253: bool GetCD() const { return CD; } ! 254: void SetCD(bool val); ! 255: ! 256: bool IO = false; // IO 信号 ! 257: bool GetIO() const { return IO; } ! 258: void SetIO(bool val); ! 259: ! 260: bool ATN = false; // ATN 信号 ! 261: bool GetATN() const { return ATN; } ! 262: void SetATN(bool val); ! 263: ! 264: // バスフリーフェーズなら true を返す ! 265: bool IsBusFree() const { ! 266: return (GetSEL() == false && GetBSY() == false); ! 267: } ! 268: ! 269: // ターゲットがバスフリーフェーズに移行した ! 270: virtual void BusRelease() { } ! 271: ! 272: protected: ! 273: // 設定ファイルに使われるこのホストデバイスを示す接頭語。 ! 274: // ("spc0" とか) ! 275: const char *config_name = NULL; ! 276: ! 277: #if 0 ! 278: SCSI::BusPhase bus_phase; ! 279: SCSI::XferPhase xfer_phase; ! 280: #endif ! 281: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.