|
|
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.