|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2018 [email protected] ! 4: // ! 5: // SCSI ! 6: // ! 7: ! 8: #include "scsi.h" ! 9: #include "scheduler.h" ! 10: #include "scsitarget.h" ! 11: #include "mystring.h" ! 12: #include "configfile.h" ! 13: ! 14: // フェーズ名を返す。 ! 15: const char * ! 16: SCSI::GetPhaseName(uint phase) ! 17: { ! 18: if (phase < countof(phasename)) { ! 19: return phasename[phase]; ! 20: } else { ! 21: return NULL; ! 22: } ! 23: } ! 24: ! 25: // cmd に対応するコマンド名を返す。 ! 26: const char * ! 27: SCSI::GetCommandName(uint8 cmd) ! 28: { ! 29: if (cmd < countof(commandname)) { ! 30: return commandname[cmd]; ! 31: } else { ! 32: return NULL; ! 33: } ! 34: } ! 35: ! 36: // フェーズ名 ! 37: /*static*/ const char * const ! 38: SCSI::phasename[Phase::MAX] = ! 39: { ! 40: "DataOut", // 0 ! 41: "DataIn", // 1 ! 42: "Command", // 2 ! 43: "Status", // 3 ! 44: "4?", // 4 ! 45: "5?", // 5 ! 46: "MsgOut", // 6 ! 47: "MsgIn", // 7 ! 48: "BusFree", // 8 ! 49: "Arbitration", // 9 ! 50: "Selection", // 10 ! 51: "Reselection", // 11 ! 52: }; ! 53: ! 54: // コマンド名 ! 55: /*static*/ const char * const ! 56: SCSI::commandname[Command::MAX] = ! 57: { ! 58: "TestUnitReady", // 00 ! 59: "RezeroUnit", // 01 ! 60: NULL, // 02 ! 61: "RequestSense", // 03 ! 62: "FormatUnit", // 04 ! 63: NULL, // 05 ! 64: NULL, // 06 ! 65: "ReassignBlocks", // 07 ! 66: "Read(6)", // 08 ! 67: NULL, // 09 ! 68: "Write(6)", // 0a ! 69: "Seek(6)", // 0b ! 70: NULL, // 0c ! 71: NULL, // 0d ! 72: NULL, // 0e ! 73: NULL, // 0f ! 74: ! 75: NULL, // 10 ! 76: NULL, // 11 ! 77: "Inquiry", // 12 ! 78: NULL, // 13 ! 79: NULL, // 14 ! 80: "ModeSelect(6)", // 15 ! 81: "Reserve", // 16 ! 82: "Release", // 17 ! 83: "Copy", // 18 ! 84: NULL, // 19 ! 85: "ModeSense(6)", // 1a ! 86: "StartStopUnit", // 1b ! 87: "ReceiveDiagnosticResults", // 1c ! 88: "SendDiagnostic", // 1d ! 89: "PreventAllowMediumRemoval", // 1e ! 90: NULL, // 1f ! 91: ! 92: NULL, // 20 ! 93: NULL, // 21 ! 94: NULL, // 22 ! 95: NULL, // 23 ! 96: NULL, // 24 ! 97: "ReadCapacity", // 25 ! 98: NULL, // 26 ! 99: NULL, // 27 ! 100: "Read(10)", // 28 ! 101: NULL, // 29 ! 102: "Write(10)", // 2a ! 103: "Seek(10)", // 2b ! 104: NULL, // 2c ! 105: NULL, // 2d ! 106: "WriteAndVerify(10)", // 2e ! 107: "Verify(10)", // 2f ! 108: ! 109: "SearchDataHigh(10)", // 30 ! 110: "SearchDataEqual(10)", // 31 ! 111: "SearchDataLow(10)", // 32 ! 112: "SetLimits", // 33 ! 113: "PreFetch", // 34 ! 114: "SynchronizeCache", // 35 ! 115: "LockUnlockCache", // 36 ! 116: "ReadDefectData(10)", // 37 ! 117: NULL, // 38 ! 118: "Compare", // 39 ! 119: "CopyAndVerify", // 3a ! 120: "WriteBuffer", // 3b ! 121: "ReadBuffer", // 3c ! 122: NULL, // 3d ! 123: "ReadLong", // 3e ! 124: "WriteLong", // 3f ! 125: ! 126: "ChangeDefinition", // 40 ! 127: "WriteSame", // 41 ! 128: NULL, // 42 ! 129: NULL, // 43 ! 130: NULL, // 44 ! 131: NULL, // 45 ! 132: NULL, // 46 ! 133: NULL, // 47 ! 134: NULL, // 48 ! 135: NULL, // 49 ! 136: NULL, // 4a ! 137: NULL, // 4b ! 138: "LogSelect", // 4c ! 139: "LogSense", // 4d ! 140: NULL, // 4e ! 141: NULL, // 4f ! 142: NULL, // 50 ! 143: NULL, // 51 ! 144: NULL, // 52 ! 145: NULL, // 53 ! 146: NULL, // 54 ! 147: "ModeSelect(10)", // 55 ! 148: NULL, // 56 ! 149: NULL, // 57 ! 150: NULL, // 58 ! 151: NULL, // 59 ! 152: "ModeSense(10)", // 5a ! 153: }; ! 154: ! 155: // ! 156: // SCSI ホストデバイス (基本クラス) ! 157: // ! 158: ! 159: // コンストラクタ ! 160: SCSIHostDevice::SCSIHostDevice() ! 161: { ! 162: } ! 163: ! 164: // デストラクタ ! 165: SCSIHostDevice::~SCSIHostDevice() ! 166: { ! 167: } ! 168: ! 169: // SCSI デバイスオブジェクトの生成 ! 170: bool ! 171: SCSIHostDevice::Create() ! 172: { ! 173: for (int id = 0; id < 8; id++) { ! 174: const std::string key = string_format("%s_id%d_devtype", ! 175: GetConfigName(), id); ! 176: int devtype = gConfig->ReadInt(key); ! 177: switch (devtype) { ! 178: default: ! 179: case SCSI::None: ! 180: target[id] = NULL; ! 181: break; ! 182: case SCSI::HD: ! 183: target[id] = new SCSIHD(this, id); ! 184: break; ! 185: } ! 186: } ! 187: return true; ! 188: } ! 189: ! 190: // SCSIHostDevice クラスに書いてあるけど ! 191: // このへんは SCSI バスの挙動。 ! 192: ! 193: // 各バスフェーズへ遷移する ! 194: ! 195: // バスフリーフェーズへ遷移する。 ! 196: // 基本的にターゲットが使用する。 ! 197: void ! 198: SCSIHostDevice::B_BusFree(int id) ! 199: { ! 200: if (!IsBusFree()) { ! 201: // バスフリーに変化した時刻を記録 ! 202: BusPhaseTime = gScheduler->GetVirtTime(); ! 203: } ! 204: NegateSEL(id); ! 205: NegateBSY(id); ! 206: SetMSG(false); ! 207: SetCD(false); ! 208: SetIO(false); ! 209: SetATN(false); ! 210: SetREQ(false); ! 211: SetACK(false); ! 212: SetDATA(0); ! 213: putlog(3, "BusFree"); ! 214: } ! 215: ! 216: // アービトレーションフェーズを起動する。 ! 217: // id はアービトレーションを行おうとしているデバイスの ID。 ! 218: // バスフリー状態で呼び出すこと。 ! 219: bool ! 220: SCSIHostDevice::Arbitration(int id) ! 221: { ! 222: assert(IsBusFree()); ! 223: ! 224: AssertBSY(id); ! 225: SetDATA(1 << id); ! 226: ! 227: putlog(3, "Arbitration invoked by ID=%d", id); ! 228: return true; ! 229: } ! 230: ! 231: // アービトレーションフェーズの完了確認。 ! 232: // id はアービトレーションを行おうとしているデバイスの ID。 ! 233: bool ! 234: SCSIHostDevice::ArbitrationAck(int id) ! 235: { ! 236: // 自分より上位の ID がいればアービトレーション失敗なのだが、 ! 237: // ここでは複数のデバイスが同時にアービトレーションフェーズに入ることは ! 238: // ないので、アービトレーションは必ず成功するとする。 ! 239: if (0 && GetDATA() > (1 << id)) { ! 240: NegateBSY(id); ! 241: putlog(3, "Arbitration loose ID=%d", id); ! 242: return false; ! 243: } ! 244: AssertSEL(id); ! 245: return true; ! 246: } ! 247: ! 248: // イニシエータによるセレクションフェーズの起動。 ! 249: void ! 250: SCSIHostDevice::InitiatorSelection(int targetid) ! 251: { ! 252: NegateBSY(myid); ! 253: SetDATA((1 << myid) | (1 << targetid)); ! 254: AssertSEL(myid); ! 255: } ! 256: ! 257: // (イニシエータによる)セレクションへのターゲットの応答。 ! 258: void ! 259: SCSIHostDevice::TargetSelectionAck(int targetid) ! 260: { ! 261: assert(GetDATA() & (1 << targetid)); ! 262: ! 263: // targetid がセレクトされた ! 264: AssertBSY(targetid); ! 265: tgtid = targetid; ! 266: putlog(3, "Target selected ID=%d", targetid); ! 267: } ! 268: ! 269: void ! 270: SCSIHostDevice::InitiatorSelectionAck() ! 271: { ! 272: NegateSEL(myid); ! 273: } ! 274: ! 275: // リセレクションフェーズ ! 276: ! 277: void ! 278: SCSIHostDevice::TargetReselection(int targetid, int initiatorID) ! 279: { ! 280: SetIO(true); ! 281: SetDATA((1 << initiatorID) | (1 << targetid)); ! 282: NegateBSY(targetid); ! 283: } ! 284: ! 285: int ! 286: BitToID(int x) ! 287: { ! 288: return 31 - __builtin_clz(x); ! 289: } ! 290: ! 291: void ! 292: SCSIHostDevice::InitiatorReselectionAck() ! 293: { ! 294: tgtid = BitToID(GetDATA() & ~(1 << myid)); ! 295: AssertBSY(myid); ! 296: } ! 297: ! 298: void ! 299: SCSIHostDevice::TargetReselectionAck(int targetid) ! 300: { ! 301: AssertBSY(targetid); ! 302: NegateSEL(targetid); ! 303: target[targetid]->Selected(); ! 304: } ! 305: ! 306: void ! 307: SCSIHostDevice::InitiatorReselectionAck2() ! 308: { ! 309: NegateBSY(myid); ! 310: } ! 311: ! 312: //////// ! 313: ! 314: // データバスに data をセット ! 315: void ! 316: SCSIHostDevice::SetDATA(uint8 data) ! 317: { ! 318: DATA = data; ! 319: putlog(3, "BUS DATA = $%02x", DATA); ! 320: } ! 321: ! 322: // REQ 信号線をセット ! 323: void ! 324: SCSIHostDevice::SetREQ(bool val) ! 325: { ! 326: // 同じなら何もしない ! 327: if (REQ == val) { ! 328: return; ! 329: } ! 330: ! 331: REQ = val; ! 332: putlog(4, "BUS REQ = %d", REQ); ! 333: } ! 334: ! 335: // ACK 信号線をセット ! 336: void ! 337: SCSIHostDevice::SetACK(bool val) ! 338: { ! 339: // 同じなら何もしない ! 340: if (ACK == val) { ! 341: return; ! 342: } ! 343: ! 344: ACK = val; ! 345: putlog(4, "BUS ACK = %d", ACK); ! 346: } ! 347: ! 348: // RST 信号線をセット ! 349: void ! 350: SCSIHostDevice::SetRST(bool val) ! 351: { ! 352: // 同じなら何もしない ! 353: if (RST == val) { ! 354: return; ! 355: } ! 356: ! 357: RST = val; ! 358: putlog(3, "BUS RST = %d", RST); ! 359: } ! 360: ! 361: // SEL 信号線をアサート ! 362: void ! 363: SCSIHostDevice::AssertSEL(int id) ! 364: { ! 365: // 同じなら何もしない ! 366: if (SEL & (1 << id)) { ! 367: return; ! 368: } ! 369: ! 370: SEL |= 1 << id; ! 371: putlog(3, "BUS SEL = %02x", SEL); ! 372: } ! 373: ! 374: // SEL 信号線をネゲート ! 375: void ! 376: SCSIHostDevice::NegateSEL(int id) ! 377: { ! 378: // 同じなら何もしない ! 379: if ((SEL & (1 << id)) == 0) { ! 380: return; ! 381: } ! 382: ! 383: SEL &= ~(1 << id); ! 384: putlog(3, "BUS SEL = %02x", SEL); ! 385: } ! 386: ! 387: // BSY 信号線をアサート ! 388: void ! 389: SCSIHostDevice::AssertBSY(int id) ! 390: { ! 391: // 同じなら何もしない ! 392: if (BSY & (1 << id)) { ! 393: return; ! 394: } ! 395: ! 396: BSY |= 1 << id; ! 397: putlog(3, "BUS BSY = %02x", BSY); ! 398: } ! 399: ! 400: // BSY 信号線をネゲート ! 401: void ! 402: SCSIHostDevice::NegateBSY(int id) ! 403: { ! 404: // 同じなら何もしない ! 405: if ((BSY & (1 << id)) == 0) { ! 406: return; ! 407: } ! 408: ! 409: BSY &= ~(1 << id); ! 410: putlog(3, "BUS BSY = %02x", BSY); ! 411: } ! 412: ! 413: // MSG 信号線をセット ! 414: void ! 415: SCSIHostDevice::SetMSG(bool val) ! 416: { ! 417: // 同じなら何もしない ! 418: if (MSG == val) { ! 419: return; ! 420: } ! 421: ! 422: MSG = val; ! 423: putlog(3, "BUS MSG = %d", MSG); ! 424: } ! 425: ! 426: // C/D 信号線をセット ! 427: void ! 428: SCSIHostDevice::SetCD(bool val) ! 429: { ! 430: // 同じなら何もしない ! 431: if (CD == val) { ! 432: return; ! 433: } ! 434: ! 435: CD = val; ! 436: static const char *cdstr[] = { ! 437: "Data", ! 438: "Ctrl", ! 439: }; ! 440: putlog(3, "BUS CD = %d(%s)", CD, cdstr[CD]); ! 441: } ! 442: ! 443: // I/O 信号線をセット ! 444: void ! 445: SCSIHostDevice::SetIO(bool val) ! 446: { ! 447: // 同じなら何もしない ! 448: if (IO == val) { ! 449: return; ! 450: } ! 451: ! 452: IO = val; ! 453: static const char *iostr[] = { ! 454: "Out", ! 455: "In", ! 456: }; ! 457: putlog(3, "BUS IO = %d(%s)", IO, iostr[IO]); ! 458: } ! 459: ! 460: // ATN 信号線をセット ! 461: void ! 462: SCSIHostDevice::SetATN(bool val) ! 463: { ! 464: // 同じなら何もしない ! 465: if (ATN == val) { ! 466: return; ! 467: } ! 468: ! 469: ATN = val; ! 470: putlog(3, "BUS ATN = %d", ATN); ! 471: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.