|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2018 [email protected]
4: //
5:
6: #include <algorithm>
7: #include <fcntl.h>
8: #include <sys/stat.h>
9: #include <sys/mman.h>
10: #include "scsitarget.h"
11: #include "scsi.h"
12: #include "configfile.h"
13: #include "mystring.h"
14:
15: //
16: // SCSI コマンドクラス
17: //
18: class SCSICmd
19: {
20: public:
21: SCSICmd(SCSITarget *p) {
22: parent = p;
23: }
24: virtual ~SCSICmd() { }
25:
26: // コマンドフェーズを開始する。
27: // コマンドバイト列が揃ったところでコールされるので、
28: // 必要な処理を行い、次のフェーズ (SCSI::Phase::*) を返す。
29: virtual uint8 Command(const std::vector<uint8>& cmds) {
30: // 何もしない系コマンドなら次はステータスフェーズ
31: return SCSI::Phase::Status;
32: }
33:
34: // データインフェーズを開始する。
35: // データインフェーズ開始時にコールされるので、
36: // ホストに転送するデータを用意し、
37: // *ptr にデータの先頭、戻り値にデータ長を返す。
38: virtual uint DataInBegin(const uint8 **ptr) {
39: return 0;
40: }
41:
42: // データアウトフェーズを開始する。
43: // データアウトフェーズ開始時にコールされるので、
44: // ホストからのデータ受信用バッファを用意し、
45: // *ptr にバッファ、戻り値にバッファ長を返す。
46: virtual uint DataOutBegin(uint8 **ptr) {
47: return 0;
48: }
49:
50: // データイン、データアウトフェーズ完了時にコールされる。
51: virtual void DataDone() { }
52:
53: // ステータスフェーズを開始する。
54: // ステータス (SCSI::StatusByte::*) を返す。
55: virtual uint Status() {
56: return SCSI::StatusByte::Good;
57: }
58:
59: // メッセージインフェーズを開始する。
60: // メッセージ (SCSI::MsgByte::*) を返す。
61: virtual uint MsgIn() {
62: return SCSI::MsgByte::CommandComplete;
63: }
64:
65: protected:
66: // このコマンドを呼び出したデバイス
67: SCSITarget *parent = NULL;
68: };
69:
70: // $00 TestUnitReady コマンド (共通)
71: // とりあえず何もせず正常を返すだけでいい。
72: class SCSICmdTestUnitReady : public SCSICmd
73: {
74: typedef SCSICmd inherited;
75: public:
76: SCSICmdTestUnitReady(SCSITarget *p) : inherited(p) { }
77: virtual ~SCSICmdTestUnitReady() { }
78: };
79:
80: // $03 RequestSense コマンド (共通)
81: class SCSICmdRequestSense: public SCSICmd
82: {
83: typedef SCSICmd inherited;
84: public:
85: SCSICmdRequestSense(SCSITarget *p) : inherited(p) { }
86: virtual ~SCSICmdRequestSense() { }
87:
88: virtual uint8 Command(const std::vector<uint8>& cmds) {
89: parent->putlog(1, "RequestSense %d", cmds[4]);
90:
91: // この内容は全く不正。でっちあげである。
92:
93: len = (uint)cmds[4];
94: mem[0] = 0x80 | 0x70;
95: mem[1] = 0;
96: mem[2] = 0; // No Sense
97: mem[3] = 0;
98: mem[4] = 0;
99: mem[5] = 0;
100: mem[6] = 0;
101: mem[7] = 0; // 追加センスデータ長
102:
103: return SCSI::Phase::DataIn;
104: }
105:
106: virtual uint DataInBegin(const uint8 **ptr) {
107: *ptr = mem;
108: return len;
109: }
110:
111: private:
112: uint len = 0;
113: uint8 mem[256] {};
114: };
115:
116: // $08 Read(6) コマンド (ダイレクトアクセスデバイス)
117: class SCSICmdRead6 : public SCSICmd
118: {
119: typedef SCSICmd inherited;
120: public:
121: SCSICmdRead6(SCSITarget *p)
122: : inherited(p)
123: {
124: hdparent = dynamic_cast<SCSIHD*>(p);
125: }
126: virtual ~SCSICmdRead6() { }
127:
128: virtual uint8 Command(const std::vector<uint8>& cmds) {
129: uint32 lba;
130: uint32 blks;
131:
132: lba = (cmds[1] & 0x1f) << 16;
133: lba |= cmds[2] << 8;
134: lba |= cmds[3];
135: blks = cmds[4];
136:
137: // XXX 範囲チェック
138: // READ(6) の blks == 0 は 256 を意味する。
139: // なお READ(10) ではこの変換は無い。
140: if (blks == 0) {
141: blks = 256;
142: }
143: dataptr = hdparent->mem + (lba * hdparent->blocksize);
144: datalen = blks * parent->blocksize;
145:
146: parent->putlog(1, "READ6 $%x %d", lba, blks);
147:
148: return SCSI::Phase::DataIn;
149: }
150:
151: virtual uint DataInBegin(const uint8 **ptr) {
152: *ptr = dataptr;
153: return datalen;
154: }
155:
156: private:
157: SCSIHD *hdparent = NULL;
158: uint8 *dataptr = NULL; // 今回の Read の先頭
159: uint datalen = 0; // 今回の Read のバイト数
160: };
161:
162: // $0a Write(6) コマンド (ダイレクトアクセスデバイス)
163: class SCSICmdWrite6 : public SCSICmd
164: {
165: typedef SCSICmd inherited;
166: public:
167: SCSICmdWrite6(SCSITarget *p)
168: : inherited(p)
169: {
170: hdparent = dynamic_cast<SCSIHD*>(p);
171: databuf = NULL;
172: datalen = 0;
173: }
174: virtual ~SCSICmdWrite6() {
175: if (databuf) {
176: delete[] databuf;
177: }
178: }
179:
180: virtual uint8 Command(const std::vector<uint8>& cmds) {
181: uint32 blks;
182:
183: lba = (cmds[1] & 0x1f) << 16;
184: lba |= cmds[2] << 8;
185: lba |= cmds[3];
186: blks = cmds[4];
187:
188: // XXX 範囲チェック
189: // WRITE(6) の blks == 0 は 256 を意味する。
190: // なお WRITE(10) ではこの変換は無い。
191: if (blks == 0) {
192: blks = 256;
193: }
194: datalen = blks * parent->blocksize;
195: databuf = new uint8[datalen];
196:
197: parent->putlog(1, "WRITE6 $%x %d", lba, blks);
198:
199: return SCSI::Phase::DataOut;
200: }
201:
202: virtual uint DataOutBegin(uint8 **ptr) {
203: *ptr = databuf;
204: return datalen;
205: }
206:
207: virtual void DataDone() {
208: if (hdparent->writeprotect == false)
209: memcpy(hdparent->mem + (lba * hdparent->blocksize),
210: databuf, datalen);
211: }
212:
213: private:
214: SCSIHD *hdparent = NULL;
215: uint8 *databuf = NULL; // 今回の Write バッファ
216: uint datalen = 0; // 今回の Write のバイト数
217: uint32 lba = 0; // 今回の Write の LBA
218: };
219:
220: // $12 Inquiry コマンド (共通)
221: class SCSICmdInquiry : public SCSICmd
222: {
223: typedef SCSICmd inherited;
224: public:
225: // inq, len は INQUIRY 応答データ
226: SCSICmdInquiry(SCSITarget *p, const uint8 *inq, uint len)
227: : inherited(p)
228: {
229: inquiry_buf = inq;
230: inquiry_len = len;
231: }
232: virtual ~SCSICmdInquiry() { }
233:
234: virtual uint8 Command(const std::vector<uint8>& cmds) {
235: inquiry_len = std::min(inquiry_len, (uint)cmds[4]);
236:
237: return SCSI::Phase::DataIn;
238: }
239:
240: virtual uint DataInBegin(const uint8 **ptr) {
241: *ptr = inquiry_buf;
242: return inquiry_len;
243: }
244:
245: private:
246: // Inquiry データは SCSI 種別で異なる
247: const uint8 *inquiry_buf = NULL;
248: uint inquiry_len = 0;
249: };
250:
251: // $15 ModeSelect(6) コマンド (共通)
252: class SCSICmdModeSelect6 : public SCSICmd
253: {
254: typedef SCSICmd inherited;
255: public:
256: // ModeSelect コマンドではホストからブロック長が指定される。
257: // blocksizep はその指定されたブロック長を書き戻す場所。
258: SCSICmdModeSelect6(SCSITarget *p)
259: : inherited(p)
260: {
261: modebuf = NULL;
262: len = 0;
263: }
264: virtual ~SCSICmdModeSelect6() {
265: if (modebuf) {
266: delete[] modebuf;
267: }
268: }
269:
270: virtual uint8 Command(const std::vector<uint8>& cmds) {
271: // 指定されたバッファ長のメモリを確保。
272: len = cmds[4];
273: modebuf = new uint8[len];
274: return SCSI::Phase::DataOut;
275: }
276:
277: virtual uint DataOutBegin(uint8 **ptr) {
278: *ptr = modebuf;
279: return len;
280: }
281:
282: virtual void DataDone() {
283: // Mode Select(6) のデータは以下の構造で並んでいる。
284: // ヘッダ
285: // ブロックディスクリプタ#1
286: // :
287: // ブロックディスクリプタ#n
288: // パラメータページ #1
289: // :
290: // パラメータページ #m
291:
292: const SCSI::ModeParamHdr *hdr = (const SCSI::ModeParamHdr *)modebuf;
293:
294: if (hdr->block_desc_len > 0) {
295: const SCSI::BlockDesc *desc =
296: (const SCSI::BlockDesc *)(modebuf + sizeof(*hdr));
297: uint blocksize;
298: blocksize = (desc->block_size[0]) << 16;
299: blocksize |= (desc->block_size[1]) << 8;
300: blocksize |= (desc->block_size[2]);
301:
302: // ブロック長を書き戻す
303: parent->blocksize = blocksize;
304: }
305: };
306:
307: private:
308: uint8 *modebuf = NULL;
309: uint len = 0;
310: };
311:
312: // $25 ReadCapacity コマンド (ダイレクトアクセスデバイス)
313: class SCSICmdReadCapacity : public SCSICmd
314: {
315: typedef SCSICmd inherited;
316: public:
317: SCSICmdReadCapacity(SCSITarget *p)
318: : inherited(p)
319: {
320: hdparent = dynamic_cast<SCSIHD*>(p);
321:
322: // 応答データは
323: // +00.L 最終論理ブロックアドレス
324: // +04.L ブロック長
325: uint32 blksize = hdparent->blocksize;
326: uint32 lastblk = (hdparent->memlen / blksize) - 1;
327: databuf[0] = lastblk >> 24;
328: databuf[1] = lastblk >> 16;
329: databuf[2] = lastblk >> 8;
330: databuf[3] = lastblk;
331: databuf[4] = blksize >> 24;
332: databuf[5] = blksize >> 16;
333: databuf[6] = blksize >> 8;
334: databuf[7] = blksize;
335: }
336: virtual ~SCSICmdReadCapacity() { }
337:
338: virtual uint8 Command(const std::vector<uint8>& cmds) {
339: uint8 pmi;
340: // PMI=1 は未サポート
341: pmi = cmds[8] & 0x01;
342: if (pmi != 0) {
343: PANIC("SCSI ReadCapacity PMI=1 not supported");
344: }
345:
346: return SCSI::Phase::DataIn;
347: }
348:
349: virtual uint DataInBegin(const uint8 **ptr) {
350: *ptr = databuf;
351: return sizeof(databuf);
352: }
353:
354: private:
355: SCSIHD *hdparent = NULL;
356: uint8 databuf[8] {};
357: };
358:
359: // $28 Read(10) コマンド (ダイレクトアクセスデバイス)
360: class SCSICmdRead10 : public SCSICmd
361: {
362: typedef SCSICmd inherited;
363: public:
364: SCSICmdRead10(SCSITarget *p)
365: : inherited(p)
366: {
367: hdparent = dynamic_cast<SCSIHD*>(p);
368: }
369: virtual ~SCSICmdRead10() { }
370:
371: virtual uint8 Command(const std::vector<uint8>& cmds) {
372: uint32 lba;
373: uint32 blks;
374:
375: if ((cmds[1] & 0x01)) {
376: PANIC("SCSI Read(10) RelAdr not supported");
377: }
378:
379: lba = cmds[2] << 24;
380: lba |= cmds[3] << 16;
381: lba |= cmds[4] << 8;
382: lba |= cmds[5];
383:
384: blks = cmds[7] << 8;
385: blks |= cmds[8];
386:
387: // XXX 範囲チェック
388: dataptr = hdparent->mem + (lba * hdparent->blocksize);
389: datalen = blks * parent->blocksize;
390:
391: parent->putlog(1, "READ10 $%x %d", lba, blks);
392:
393: return SCSI::Phase::DataIn;
394: }
395:
396: virtual uint DataInBegin(const uint8 **ptr) {
397: *ptr = dataptr;
398: return datalen;
399: }
400:
401: private:
402: SCSIHD *hdparent = NULL;
403: uint8 *dataptr = 0; // 今回の Read の先頭
404: uint datalen = 0; // 今回の Read のバイト数
405: };
406:
407: // サポートしていないコマンドを受け取った時の処理。
408: class SCSICmdNotSupportedCommand : public SCSICmd
409: {
410: typedef SCSICmd inherited;
411: public:
412: SCSICmdNotSupportedCommand(SCSITarget *p) : inherited(p) { }
413: virtual ~SCSICmdNotSupportedCommand() { }
414:
415: // Command は何もせずステータスに移るだけなので基底のやつでいい
416:
417: virtual uint Status() {
418: return SCSI::StatusByte::CheckCondition;
419: }
420: };
421:
422: //
423: // SCSI ターゲットデバイス基本クラス
424: //
425:
426: // コンストラクタ
427: SCSITarget::SCSITarget(SCSIHostDevice *h, int id, SCSI::DevType type)
428: {
429: host = h;
430: logname = host->GetLogName();
431: devtype = type;
432: ID = id;
433: phase = SCSI::Phase::BusFree;
434: }
435:
436: // デストラクタ
437: SCSITarget::~SCSITarget()
438: {
439: }
440:
441: // フェーズを newphase に遷移する
442: void
443: SCSITarget::SetPhase(uint newphase)
444: {
445: // フェーズ遷移時に ATN をチェック。
446: // バスフリーフェーズ・アービトレーションフェーズでは ATN はセットできない。
447: // ので、それら以外で ATN が立ってる時だけ処理が必要。
448: if (phase != SCSI::Phase::BusFree &&
449: phase != SCSI::Phase::Arbitration &&
450: GetATN())
451: {
452: // lastmsg は CommandComplete に初期化してあり、CommandComplete には
453: // 解除義務はないので、1回目は必ず default に落ちるという寸法。
454: switch (lastmsg) {
455: case SCSI::MsgByte::Disconnect:
456: case SCSI::MsgByte::InitiatorDetectedError:
457: case SCSI::MsgByte::Abort:
458: case SCSI::MsgByte::MessageReject:
459: case SCSI::MsgByte::NoOperation:
460: case SCSI::MsgByte::MessageParityError:
461: case SCSI::MsgByte::BusDeviceReset:
462: case SCSI::MsgByte::AbortTag:
463: case SCSI::MsgByte::ClearQueue:
464: case SCSI::MsgByte::InitiateRecovery:
465: case SCSI::MsgByte::ReleaseRecovery:
466: case SCSI::MsgByte::TerminateIOProcess:
467: // 2バイトコードは未対応
468: // 解除義務があるので、継続してたらバスフリーへ移行。
469: newphase = SCSI::Phase::BusFree;
470: break;
471: default:
472: // 解除義務はないので、継続して受け付ける。
473: // (1回目もここに来る)
474: nextphase = newphase;
475: newphase = SCSI::Phase::MsgOut;
476: break;
477: }
478: }
479:
480: // MsgOut フェーズを抜ける際には必ず lastmsg を CommandComplete に戻す。
481: // CommandComplete が1回目フラグも兼ねているので。
482: if (phase == SCSI::Phase::MsgOut && newphase != SCSI::Phase::MsgOut) {
483: lastmsg = SCSI::MsgByte::CommandComplete;
484: }
485:
486: // フェーズ遷移
487: phase = newphase;
488: switch (newphase) {
489: case SCSI::Phase::BusFree:
490: // 自身の状態を変更
491: BusFreePhase();
492: // バスの状態を変更 (バスを管理してるのはここではホストの基本クラス)
493: host->B_BusFree(ID);
494: // ホストに状態変更を通知
495: host->BusRelease();
496: break;
497: case SCSI::Phase::Arbitration:
498: case SCSI::Phase::Selection:
499: case SCSI::Phase::Reselection:
500: // ?
501: break;
502: case SCSI::Phase::DataOut:
503: DataOutPhase();
504: break;
505: case SCSI::Phase::DataIn:
506: DataInPhase();
507: break;
508: case SCSI::Phase::Command:
509: CommandPhase();
510: break;
511: case SCSI::Phase::Status:
512: StatusPhase();
513: break;
514: case SCSI::Phase::MsgOut:
515: MsgOutPhase();
516: break;
517: case SCSI::Phase::MsgIn:
518: MsgInPhase();
519: break;
520: }
521: }
522:
523: // セレクション成功。
524: void
525: SCSITarget::Selected()
526: {
527: SetPhase(SCSI::Phase::Command);
528: SetREQ(true);
529: }
530:
531: void
532: SCSITarget::Ack()
533: {
534: lastdata = GetDATA();
535: SetREQ(false);
536: putlog(3, "#%d data=%02x", ID, lastdata);
537: }
538:
539: // バスフリーフェーズ
540: void
541: SCSITarget::BusFreePhase()
542: {
543: lastdata = 0;
544: lastmsg = 0;
545: }
546:
547: void
548: SCSITarget::DataOutPhase()
549: {
550: SetMSG(false);
551: SetCD(false);
552: SetIO(false);
553: putlog(3, "#%d Target DataOutPhase", ID);
554: }
555:
556: void
557: SCSITarget::DataInPhase()
558: {
559: SetMSG(false);
560: SetCD(false);
561: SetIO(true);
562: putlog(3, "#%d Target DataInPhase", ID);
563: }
564:
565: void
566: SCSITarget::CommandPhase()
567: {
568: SetMSG(false);
569: SetCD(true);
570: SetIO(false);
571: putlog(3, "#%d Target CommandPhase", ID);
572: }
573:
574: void
575: SCSITarget::StatusPhase()
576: {
577: SetMSG(false);
578: SetCD(true);
579: SetIO(true);
580: putlog(3, "#%d Target StatusPhase", ID);
581: }
582:
583: void
584: SCSITarget::MsgOutPhase()
585: {
586: SetMSG(true);
587: SetCD(true);
588: SetIO(false);
589: putlog(3, "#%d Target MsgOutPhase", ID);
590: }
591:
592: void
593: SCSITarget::MsgInPhase()
594: {
595: SetMSG(true);
596: SetCD(true);
597: SetIO(true);
598: putlog(3, "#%d Target MsgInPhase", ID);
599: }
600:
601: // データインフェーズの処理。
602: uint
603: SCSITarget::ExecDataIn(const uint8 **ptr)
604: {
605: // コマンド固有のデータインフェーズの処理
606: uint len = cmd->DataInBegin(ptr);
607:
608: // ステータスフェーズに移行
609: SetPhase(SCSI::Phase::Status);
610:
611: return len;
612: }
613:
614: // データアウトフェーズの処理。
615: uint
616: SCSITarget::ExecDataOut(uint8 **ptr)
617: {
618: // コマンド固有のデータアウトフェーズの処理
619: uint len = cmd->DataOutBegin(ptr);
620:
621: // ステータスフェーズに移行
622: SetPhase(SCSI::Phase::Status);
623:
624: return len;
625: }
626:
627: // コマンドフェーズの処理。
628: // イニシエータが必要な長さ分のコマンドをホスト OS から受信したところで
629: // イニシエータ側から呼ばれて、コマンドの処理を行う。
630: // 処理後は次のフェーズに遷移する。
631: void
632: SCSITarget::ExecCommand(const std::vector<uint8>& argcmds)
633: {
634: cmds = argcmds;
635:
636: const char *cmdname = SCSI::GetCommandName(cmds[0]);
637: if (cmdname != NULL) {
638: putlog(1, "#%d $%02x %s", ID, cmds[0], cmdname);
639: } else {
640: putlog(1, "#%d $%02x unknown command", ID, cmds[0]);
641: }
642:
643: // コマンドを選択。
644: // まずデバイス固有のコマンドをサーチ。
645: cmd = ExecDeviceCommand();
646: // 派生クラス側で選択されなければ、こちらでサーチ。
647: if (cmd == NULL) {
648: switch (cmds[0]) {
649: case SCSI::Command::TestUnitReady:
650: cmd = new SCSICmdTestUnitReady(this);
651: break;
652:
653: case SCSI::Command::RequestSense:
654: cmd = new SCSICmdRequestSense(this);
655: break;
656:
657: case SCSI::Command::ModeSelect6:
658: cmd = new SCSICmdModeSelect6(this);
659: break;
660:
661: default:
662: // サポートしていないコマンド
663: const char *cname = SCSI::GetCommandName(cmds[0]);
664: std::string name;
665: if (cname) {
666: name = string_format(" %s", cname);
667: }
668: putlog(0, "未実装 SCSI コマンド $%02x%s len=%zd",
669: cmds[0], name.c_str(), cmds.size());
670:
671: cmd = new SCSICmdNotSupportedCommand(this);
672: break;
673: }
674: }
675:
676: uint newphase = cmd->Command(cmds);
677: SetPhase(newphase);
678: }
679:
680: SCSICmd *
681: SCSITarget::ExecDeviceCommand()
682: {
683: PANIC("should not reached");
684: }
685:
686: // ステータスバイトを取得およびデータアウトフェーズ完了処理。
687: uint8
688: SCSITarget::GetStatusByte()
689: {
690: // データフェーズの完了処理をここで行う。
691: cmd->DataDone();
692:
693: // XXX まだコマンド側からログが出せないのでとりあえず
694: if (cmds[0] == SCSI::Command::ModeSelect6) {
695: putlog(2, "#%d Mode Select 論理ブロック長 = %d", ID, blocksize);
696: }
697:
698: // ステータスバイトを取得。
699: uint statusbyte = cmd->Status();
700:
701: // メッセージインフェーズに移行。
702: SetPhase(SCSI::Phase::MsgIn);
703: return statusbyte;
704: }
705:
706: uint8
707: SCSITarget::GetMessageByte()
708: {
709: // メッセージを取得。
710: uint messagebyte = cmd->MsgIn();
711:
712: // CommandComplete メッセージを正常に送信したらバスフリーフェーズに移行。
713: // 実際には正常に送信できたら、だけど。
714: if (messagebyte == SCSI::MsgByte::CommandComplete) {
715: SetPhase(SCSI::Phase::BusFree);
716: }
717:
718: // コマンドクラスを解放
719: // ここでいいか。
720: delete cmd;
721: cmd = NULL;
722:
723: return messagebyte;
724: }
725:
726:
727: //
728: // SCSI HD
729: //
730:
731: // コンストラクタ
732: SCSIHD::SCSIHD(SCSIHostDevice *h, int id)
733: : inherited(h, id, SCSI::HD)
734: {
735: devname = "SCSIHD";
736: logname = "scsihd";
737:
738: fd = -1;
739: }
740:
741: // デストラクタ
742: SCSIHD::~SCSIHD()
743: {
744: }
745:
746: // イメージファイルの読み込み
747: bool
748: SCSIHD::Init()
749: {
750: struct stat st;
751:
752: const std::string myname = string_format("%s(%s,ID%d)",
753: devname, host->GetConfigName(), ID);
754: const std::string keybody = string_format("%s_id%d_",
755: host->GetConfigName(), ID);
756: const std::string imgkey = string_format("%s%s",
757: keybody.c_str(), "image");
758: const std::string wpkey = string_format("%s%s",
759: keybody.c_str(), "writeprotect");
760:
761: // devtype があって image がないのは異常状態なのでエラー
762: const std::string& filename = gConfig->ReadStr(imgkey);
763: if (filename == "") {
764: gConfig->Err(imgkey, "not specified");
765: return false;
766: }
767:
768: writeprotect = (bool)gConfig->ReadInt(wpkey);
769: if (writeprotect) {
770: putmsg(0, "%s: write protected", myname.c_str());
771: }
772:
773: const std::string path = gConfig->GetConfigDir() + filename;
774: fd = open(path.c_str(), O_RDWR);
775: if (fd == -1) {
776: warn("%s cannot open %s", myname.c_str(), path.c_str());
777: return false;
778: }
779:
780: if (fstat(fd, &st) == -1) {
781: warn("%s cannot stat %s", myname.c_str(), path.c_str());
782: close(fd);
783: return false;
784: }
785:
786: memlen = st.st_size;
787: mem = (uint8 *)mmap(NULL, memlen, PROT_READ | PROT_WRITE,
788: MAP_SHARED, fd, 0);
789: if (mem == MAP_FAILED) {
790: warn("%s cannot mmap %s", myname.c_str(), path.c_str());
791: close(fd);
792: return false;
793: }
794:
795: return true;
796: }
797:
798: // HD 固有のコマンドの処理。
799: // こちらで処理すれば次フェーズを返す。そうでなければ None を返す。
800: SCSICmd *
801: SCSIHD::ExecDeviceCommand()
802: {
803: switch (cmds[0]) {
804: case SCSI::Command::Read6:
805: return new SCSICmdRead6(this);
806:
807: case SCSI::Command::Write6:
808: return new SCSICmdWrite6(this);
809:
810: case SCSI::Command::Inquiry:
811: // これは共通コマンドだけど引数だけ違う
812: return new SCSICmdInquiry(this, inquiry_data, sizeof(inquiry_data));
813:
814: case SCSI::Command::ReadCapacity:
815: return new SCSICmdReadCapacity(this);
816:
817: case SCSI::Command::Read10:
818: return new SCSICmdRead10(this);
819:
820: default:
821: // それ以外は基本クラス側で処理する。
822: return NULL;
823: }
824: }
825:
826: // HD の inquiry データ
827: /*static*/ const uint8
828: SCSIHD::inquiry_data[36] = {
829: 0x00, // 00 Qualifier + DeviceType
830: 0x00, // 01 RMB
831: 0x40, // 02 ISO version
832: 0x00, // 03 Response Data Format?
833: 36 - 4, // 04 追加データ長
834: 0, // 05 Reserved
835: 0, // 06 Reserved
836: 0x00, // 07
837: 'V', 'E', 'N', 'D', 'E', 'R', ' ', ' ',
838: 'P', 'R', 'O', 'D', 'U', 'C', 'T', ' ',
839: 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ',
840: '0', '1', '2', '3',
841: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.