Annotation of nono/vm/scsicmd.cpp, revision 1.1.1.6

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.3   root        7: //
1.1       root        8: // SCSI コマンド
1.1.1.3   root        9: //
1.1       root       10: 
                     11: #include "scsicmd.h"
                     12: #include "scsidev.h"
                     13: 
                     14: #define LUN    (cmdseq[1] >> 5)
                     15: 
1.1.1.6 ! root       16: // LUN != 0 のリクエストをエラーにする (ExecCommand() 内で使う)。
1.1       root       17: #define CheckLUN       do {    \
                     18:        if (LUN != 0) { \
                     19:                parent->sensekey = SCSI::SenseKey::NotReady;    \
                     20:                parent->senseasc = SCSI::ASC::LogicalUnitNotSupported;  \
                     21:                status_byte = SCSI::StatusByte::CheckCondition; \
                     22:                return SCSI::XferPhase::Status; \
                     23:        }       \
                     24: } while (0)
1.1.1.6 ! root       25: // メディアがなければエラーにする (ExecCommand() 内で使う)。
1.1       root       26: #define CheckMedium    do {    \
                     27:        if (disk->IsMediumLoaded() == false) {  \
                     28:                parent->sensekey = SCSI::SenseKey::NotReady;    \
                     29:                parent->senseasc = SCSI::ASC::MediumNotPresent; \
                     30:                status_byte = SCSI::StatusByte::CheckCondition; \
                     31:                return SCSI::XferPhase::Status; \
                     32:        }       \
                     33: } while (0)
                     34: 
                     35: 
                     36: //
                     37: // SCSI コマンドの基本クラス
                     38: //
                     39: 
                     40: // コンストラクタ
                     41: SCSICmd::SCSICmd(SCSITarget *parent_)
                     42:        : parent(parent_)
                     43: {
                     44: }
                     45: 
                     46: // デストラクタ
                     47: SCSICmd::~SCSICmd()
                     48: {
                     49: }
                     50: 
                     51: // コマンドフェーズ
                     52: SCSI::XferPhase
1.1.1.6 ! root       53: SCSICmd::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root       54: {
                     55:        // コマンド開始前に直前のセンスデータをクリア
                     56:        parent->ClearSense();
                     57: 
                     58:        CheckLUN;
                     59: 
                     60:        return SCSI::XferPhase::Status;
                     61: }
                     62: 
                     63: 
                     64: //
                     65: // SCSI コマンド: サポートしていないコマンド
                     66: //
                     67: 
                     68: // コンストラクタ
                     69: SCSICmdNotSupportedCommand::SCSICmdNotSupportedCommand(SCSITarget *parent_)
                     70:        : inherited(parent_)
                     71: {
                     72: }
                     73: 
                     74: // コマンドフェーズ
                     75: SCSI::XferPhase
1.1.1.6 ! root       76: SCSICmdNotSupportedCommand::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root       77: {
                     78:        // XXX センスキーよく分からんけどとりあえず
                     79:        parent->sensekey = SCSI::SenseKey::IllegalRequest;
                     80:        parent->senseasc = SCSI::ASC::InvalidCommandOperationCode;
                     81:        status_byte = SCSI::StatusByte::CheckCondition;
                     82: 
                     83:        return SCSI::XferPhase::Status;
                     84: }
                     85: 
                     86: 
                     87: //
                     88: // SCSI コマンド 0x03 RequestSense (共通)
                     89: //
                     90: //    +---+---+---+---+---+---+---+---+
                     91: //  0 |         Operation Code        |
                     92: //    +-----------+-------------------+
                     93: //  1 |    LUN    |         0         |
                     94: //    +-------+---+-------------------+
                     95: //  2 |               0               |
                     96: //  3 |               0               |
                     97: //    +-------------------------------+
                     98: //  4 |        アロケーション長       |
                     99: //    +-------------------------------+
                    100: //  5 |          Control Byte         |
                    101: //    +-------------------------------+
                    102: 
                    103: // コンストラクタ
                    104: SCSICmdRequestSense::SCSICmdRequestSense(SCSITarget *parent_)
                    105:        : inherited(parent_)
                    106: {
                    107: }
                    108: 
                    109: // コマンドフェーズ
                    110: SCSI::XferPhase
1.1.1.6 ! root      111: SCSICmdRequestSense::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      112: {
                    113:        CheckLUN;
                    114: 
                    115:        // 応答のセンスデータは SCSI-2 形式(最小18バイト) を実装。
                    116:        // 今の所、センスキー、ASC、ASCQ だけで返せる内容にだけ対応している。
                    117:        // これ以外のフィールドを返す必要が出来たらまた考えること。
                    118:        uint sensekey = parent->sensekey;
                    119:        uint senseasc = parent->senseasc;
                    120:        parent->putlogf(1, lstr("%s -> %s asc=$%04x",
                    121:                SCSI::GetCommandName(cmdseq[0]),
                    122:                SCSI::GetSenseKeyDisp(sensekey).c_str(),
                    123:                senseasc));
                    124: 
                    125:        // 送信用に取り出した後でセンスデータをクリア
                    126:        // (reqlen によって実際に送信したかどうかは問わない)
                    127:        parent->ClearSense();
                    128: 
                    129:        buf.clear();
                    130:        buf.resize(18);
                    131:        buf[0]  = 0x70;                         // Valid=0、エラーコード 0x70
                    132:        buf[1]  = 0;                            // セグメント番号(?)
                    133:        buf[2]  = sensekey;                     // センスキー (上位4ビットは今の所 0)
                    134:        buf[3]  = 0;                            // Information
                    135:        buf[4]  = 0;                            // Information
                    136:        buf[5]  = 0;                            // Information
                    137:        buf[6]  = 0;                            // Information
                    138:        buf[7]  = 0;                            // 追加センスデータ長 0
                    139:        buf[8]  = 0;                            // Command specific Information
                    140:        buf[9]  = 0;                            // Command specific Information
                    141:        buf[10] = 0;                            // Command specific Information
                    142:        buf[11] = 0;                            // Command specific Information
                    143:        buf[12] = senseasc >> 8;
                    144:        buf[13] = senseasc & 0xff;
                    145:        buf[14] = 0;                            // FRU
                    146:        buf[15] = 0;                            // センスキー固有情報
                    147:        buf[16] = 0;                            // センスキー固有情報
                    148:        buf[17] = 0;                            // センスキー固有情報
                    149:        // 追加センスデータなし
                    150: 
                    151:        // アロケーション長が 0 なら送信せずに終了。
                    152:        // XXX 送信せずにってステータスフェーズに移るってことだろうか?
                    153:        uint reqlen = cmdseq[4];
                    154:        if (reqlen == 0) {
                    155:                return SCSI::XferPhase::Status;
                    156:        }
                    157:        // 本来の応答データ長か reqlen の短いほうまで。
                    158:        if (reqlen < buf.size()) {
                    159:                buf.resize(reqlen);
                    160:        }
                    161:        return SCSI::XferPhase::DataIn;
                    162: }
                    163: 
                    164: 
                    165: //
                    166: // SCSI コマンド 0x08 Read(6)  (DA / CD-ROM)
                    167: //               0x28 Read(10) (DA / CD-ROM)
                    168: //
                    169: // Read(6):
                    170: //    +---+---+---+---+---+---+---+---+
                    171: //  0 |     Operation Code = 0x08     |
                    172: //    +-----------+-------------------+
                    173: //  1 |    LUN    |                   |
                    174: //    +-----------+                   |
                    175: //  2 |      論理ブロックアドレス     |
                    176: //  3 |                               |
                    177: //    +-------------------------------+
                    178: //  4 |    転送データ長 (0 なら 256)  |
                    179: //    +-------------------------------+
                    180: //  5 |          Control Byte         |
                    181: //    +-------------------------------+
                    182: //
                    183: // Read(10):
                    184: //    +---+---+---+---+---+---+---+---+
                    185: //  0 |     Operation Code = 0x28     |
                    186: //    +-----------+-----------+---+---+
                    187: //  1 |    LUN    |DPO|FUA|   0   |Rel|
                    188: //    +-----------+-----------+---+---+
                    189: //  2 |                               |
                    190: //  3 |      論理ブロックアドレス     |
                    191: //  4 |                               |
                    192: //  5 |                               |
                    193: //    +-------------------------------+
                    194: //  6 |               0               |
                    195: //    +-------------------------------+
                    196: //  7 |          転送データ長         |
                    197: //  8 |       (0 なら転送しない)      |
                    198: //    +-------------------------------+
                    199: //  9 |          Control Byte         |
                    200: //    +-------------------------------+
                    201: 
                    202: // コンストラクタ
                    203: SCSICmdRead::SCSICmdRead(SCSIDisk *parent_)
                    204:        : inherited(parent_)
                    205: {
                    206:        disk = parent_;
                    207: }
                    208: 
                    209: // コマンドフェーズ
                    210: SCSI::XferPhase
1.1.1.6 ! root      211: SCSICmdRead::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      212: {
                    213:        uint32 lba;
                    214:        uint32 blks;
                    215: 
                    216:        // コマンド開始前に直前のセンスデータをクリア
                    217:        parent->ClearSense();
                    218: 
                    219:        CheckLUN;
                    220:        CheckMedium;
                    221: 
1.1.1.5   root      222:        const uint8 cmd = cmdseq[0];
1.1       root      223:        if (cmd == SCSI::Command::Read10) {
                    224:                if ((cmdseq[1] & 0x01)) {
                    225:                        parent->putlogf(0, lstr("%s RelAdr not supported",
                    226:                                SCSI::GetCommandName(cmd)));
                    227:                }
                    228:                lba  = cmdseq[2] << 24;
                    229:                lba |= cmdseq[3] << 16;
                    230:                lba |= cmdseq[4] << 8;
                    231:                lba |= cmdseq[5];
                    232:                blks  = cmdseq[7] << 8;
                    233:                blks |= cmdseq[8];
                    234:        } else {
                    235:                lba  = (cmdseq[1] & 0x1f) << 16;
                    236:                lba |=  cmdseq[2] << 8;
                    237:                lba |=  cmdseq[3];
                    238:                blks =  cmdseq[4];
                    239:                // Read(6) の blks == 0 は 256 ブロック転送を意味する。
                    240:                if (blks == 0) {
                    241:                        blks = 256;
                    242:                }
                    243:        }
                    244: #if !defined(NO_READWRITE_LOG)
                    245:        parent->putlogf(1, lstr("%s LBA=0x%x blks=0x%x",
                    246:                SCSI::GetCommandName(cmd), lba, blks));
                    247: #endif
                    248: 
                    249:        uint64 start = (uint64)lba * parent->GetBlocksize();
                    250:        uint64 len = (uint64)blks * parent->GetBlocksize();
                    251:        uint64 end = start + len;
                    252: 
                    253:        if (end > disk->GetSize()) {
                    254:                parent->sensekey = SCSI::SenseKey::IllegalRequest;
                    255:                parent->senseasc = SCSI::ASC::InvalidFieldInCDB;
                    256:                status_byte = SCSI::StatusByte::CheckCondition;
                    257:                return SCSI::XferPhase::Status;
                    258:        }
                    259:        buf.resize(len);
                    260:        disk->Read(buf, start);
                    261: 
                    262:        // 平均シークタイム
                    263:        optime = disk->GetSeekTime();
                    264: 
                    265:        return SCSI::XferPhase::DataIn;
                    266: }
                    267: 
                    268: 
                    269: //
                    270: // SCSI コマンド 0x0a Write(6)  (DA / CD-ROM)
                    271: //               0x2a Write(10) (DA / CD-ROM)
                    272: //
                    273: // Write(6):
                    274: //    +---+---+---+---+---+---+---+---+
                    275: //  0 |     Operation Code = 0x0a     |
                    276: //    +-----------+-------------------+
                    277: //  1 |    LUN    |                   |
                    278: //    +-----------+                   |
                    279: //  2 |      論理ブロックアドレス     |
                    280: //  3 |                               |
                    281: //    +-------------------------------+
                    282: //  4 |    転送データ長 (0 なら 256)  |
                    283: //    +-------------------------------+
                    284: //  5 |          Control Byte         |
                    285: //    +-------------------------------+
                    286: //
                    287: // Write(10):
                    288: //    +---+---+---+---+---+---+---+---+
                    289: //  0 |     Operation Code = 0x2a     |
                    290: //    +-----------+-----------+---+---+
                    291: //  1 |    LUN    |DPO|FUA|   0   |Rel|
                    292: //    +-----------+-----------+---+---+
                    293: //  2 |                               |
                    294: //  3 |      論理ブロックアドレス     |
                    295: //  4 |                               |
                    296: //  5 |                               |
                    297: //    +-------------------------------+
                    298: //  6 |               0               |
                    299: //    +-------------------------------+
                    300: //  7 |          転送データ長         |
                    301: //  8 |       (0 なら転送しない)      |
                    302: //    +-------------------------------+
                    303: //  9 |          Control Byte         |
                    304: //    +-------------------------------+
                    305: 
                    306: // コンストラクタ
                    307: SCSICmdWrite::SCSICmdWrite(SCSIDisk *parent_)
                    308:        : inherited(parent_)
                    309: {
                    310:        disk = parent_;
                    311: }
                    312: 
                    313: // コマンドフェーズ
                    314: SCSI::XferPhase
1.1.1.6 ! root      315: SCSICmdWrite::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      316: {
                    317:        // コマンド開始前に直前のセンスデータをクリア
                    318:        parent->ClearSense();
                    319: 
                    320:        CheckLUN;
                    321:        CheckMedium;
                    322: 
                    323:        cmd = cmdseq[0];
                    324:        if (cmd == SCSI::Command::Write10) {
                    325:                lba  = cmdseq[2] << 24;
                    326:                lba |= cmdseq[3] << 16;
                    327:                lba |= cmdseq[4] << 8;
                    328:                lba |= cmdseq[5];
                    329:                blks  = cmdseq[7] << 8;
                    330:                blks |= cmdseq[8];
                    331:        } else {
                    332:                lba  = (cmdseq[1] & 0x1f) << 16;
                    333:                lba |=  cmdseq[2] << 8;
                    334:                lba |=  cmdseq[3];
                    335:                blks =  cmdseq[4];
                    336:                // Write(6) の blks == 0 は 256 ブロック転送を意味する。
                    337:                if (blks == 0) {
                    338:                        blks = 256;
                    339:                }
                    340:        }
                    341: 
                    342:        if (((uint64)lba + blks) * parent->GetBlocksize() > disk->GetSize()) {
                    343:                parent->sensekey = SCSI::SenseKey::IllegalRequest;
                    344:                parent->senseasc = SCSI::ASC::InvalidFieldInCDB;
                    345:                status_byte = SCSI::StatusByte::CheckCondition;
                    346:                return SCSI::XferPhase::Status;
                    347:        }
                    348: 
                    349:        // 平均シークタイム
                    350:        optime = disk->GetSeekTime();
                    351: 
                    352:        recvbytes = blks * parent->GetBlocksize();
                    353:        return SCSI::XferPhase::DataOut;
                    354: }
                    355: 
                    356: // データアウトフェーズ完了
                    357: SCSI::XferPhase
                    358: SCSICmdWrite::DoneDataOut()
                    359: {
                    360: #if !defined(NO_READWRITE_LOG)
                    361:        parent->putlogf(1, lstr("%s LBA=0x%x blks=0x%x",
                    362:                SCSI::GetCommandName(cmd), lba, blks));
                    363: #endif
                    364:        uint64 start = (uint64)lba * parent->GetBlocksize();
                    365:        if (disk->Write(buf, start) == false) {
                    366:                parent->sensekey = SCSI::SenseKey::HardwareError;
                    367:                parent->senseasc = SCSI::ASC::PeripheralDeviceWriteFault;
                    368:                status_byte = SCSI::StatusByte::CheckCondition;
                    369:        }
                    370:        return SCSI::XferPhase::Status;
                    371: }
                    372: 
                    373: 
                    374: //
                    375: // SCSI コマンド 0x12 Inquiry (共通)
                    376: //
                    377: //    +---+---+---+---+---+---+---+---+
                    378: //  0 |         Operation Code        |
                    379: //    +-----------+---------------+---+
                    380: //  1 |    LUN    |       0       | E | E:Enable Vital Product Data
                    381: //    +-----------+---------------+---+
                    382: //  2 |          ページコード         |
                    383: //    +-------------------------------+
                    384: //  3 |               0               |
                    385: //    +-------------------------------+
                    386: //  4 |        アロケーション長       |
                    387: //    +-------------------------------+
                    388: //  5 |          Control Byte         |
                    389: //    +-------------------------------+
                    390: //
                    391: // 応答
                    392: //    +---+---+---+---+---+---+---+---+
                    393: //  0 | Qualifier | Device Type Code  |
                    394: //    +---+-------+-------------------+
                    395: //  1 |RMB|    Device Type Modifier   |
                    396: //    +---+---+-----------+-----------+
                    397: //  2 |ISO ver| ECMA ver  | ANSI ver  |
                    398: //    +---+---+-------+---------------+
                    399: //  3 | A | T |   0   |ResponseFormat |
                    400: //    +---+---+-------+---------------+
                    401: //  4 |       追加データ長 (n-4)      |
                    402: //    +-------------------------------+
                    403: //  5 |               0               |
                    404: //  6 |               0               |
                    405: //    +---+---+---+---+---+---+---+---+
                    406: //  7 |Rel|W32|W16|Syn|Lnk| 0 |CQ |SR |
                    407: //    +---+---+---+---+---+---+---+---+
                    408: //  8 |      ベンダ文字列 (8Byte)     |
                    409: //    :                               :
                    410: // 15 |                               |
                    411: //    +-------------------------------+
                    412: // 16 |   プロダクト文字列 (16Byte)   |
                    413: //    :                               :
                    414: // 31 |                               |
                    415: //    +-------------------------------+
                    416: // 32 | プロダクト版数文字列 (4Byte)  |
                    417: //    :                               :
                    418: // 35 |                               |
                    419: //    +-------------------------------+
                    420: // 36         以下ベンダ固有
                    421: 
                    422: // コンストラクタ
                    423: SCSICmdInquiry::SCSICmdInquiry(SCSITarget *parent_)
                    424:        : inherited(parent_)
                    425: {
                    426: }
                    427: 
                    428: // コマンドフェーズ
                    429: SCSI::XferPhase
1.1.1.6 ! root      430: SCSICmdInquiry::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      431: {
                    432:        // コマンド開始前に直前のセンスデータをクリア
                    433:        parent->ClearSense();
                    434: 
                    435:        uint reqlen = (uint)cmdseq[4];
1.1.1.5   root      436:        parent->putlogf(1, lstr("%s LUN=%u reqlen=$%02x",
1.1       root      437:                SCSI::GetCommandName(cmdseq[0]), LUN, reqlen));
                    438: 
                    439:        // 基本の 36バイト分を用意した上でデバイスに問い合わせ。
                    440:        // これ以上必要ならデバイス側で伸ばしてもよい。
                    441:        buf.resize(36);
                    442:        std::fill(buf.begin(), buf.end(), 0);
                    443:        if (parent->Inquiry(buf, LUN) == false) {
                    444:                status_byte = SCSI::StatusByte::CheckCondition;
                    445:                return SCSI::XferPhase::Status;
                    446:        }
                    447: 
                    448:        // 本来の応答データ長か reqlen の短いほうまで。
1.1.1.5   root      449:        uint origlen = buf.size();
1.1       root      450:        if (reqlen < origlen) {
                    451:                buf.resize(reqlen);
                    452:        }
                    453: 
                    454:        if (parent->loglevel >= 2) {
                    455:                // 応答をダンプ、ここで表示する長さは本来の応答データ長
                    456:                std::string str = string_format("%s Response len=$%02x:",
                    457:                        SCSI::GetCommandName(cmdseq[0]), origlen);
                    458:                // 一方ダンプは実際の送信長
                    459:                for (int i = 0; i < buf.size(); i++) {
                    460:                        if (i % 8 == 0 && i != 0) {
                    461:                                str += " ";
                    462:                        }
                    463:                        str += string_format(" %02x", buf[i]);
                    464:                }
                    465:                parent->putlogn("%s", str.c_str());
                    466:        }
                    467: 
                    468:        return SCSI::XferPhase::DataIn;
                    469: }
                    470: 
                    471: 
                    472: //
                    473: // SCSI コマンド 0x15 ModeSelect(6)  (共通)
                    474: //               0x55 ModeSelect(10) (共通)
                    475: //
                    476: // ModeSelect(6):
                    477: //    +---+---+---+---+---+---+---+---+
                    478: //  0 |     Operation Code = 0x15     |
                    479: //    +-----------+---+-----------+---+
                    480: //  1 |    LUN    |PF |     0     |SP | PF:PageFormat, SP:SavePages
                    481: //    +-----------+---+-----------+---+
                    482: //  2 |               0               |
                    483: //  3 |               0               |
                    484: //    +-------------------------------+
                    485: //  4 |      パラメータリスト長       |
                    486: //    +-------------------------------+
                    487: //  5 |          Control Byte         |
                    488: //    +-------------------------------+
                    489: //
                    490: // ModeSelect(10):
                    491: //    +---+---+---+---+---+---+---+---+
                    492: //  0 |     Operation Code = 0x55     |
                    493: //    +-----------+---+-----------+---+
                    494: //  1 |    LUN    |PF |     0     |SP | PF:PageFormat, SP:SavePages
                    495: //    +-----------+---+-----------+---+
                    496: //  2 |                               |
                    497: //  3 |                               |
                    498: //  4 |               0               |
                    499: //  5 |                               |
                    500: //  6 |                               |
                    501: //    +-------------------------------+
                    502: //  7 |      パラメータリスト長       |
                    503: //  8 |               0               |
                    504: //    +-------------------------------+
                    505: //  9 |          Control Byte         |
                    506: //    +-------------------------------+
                    507: //
                    508: // 応答: (モードパラメータヘッダ、6の時)
                    509: //    +-------------------------------+
                    510: //  0 |      モードパラメータ長       | (このバイトを含まずこれ以降)
                    511: //    +-------------------------------+
                    512: //  1 |        メディアタイプ         |
                    513: //    +-------------------------------+
                    514: //  2 |     デバイス固有パラメータ    |
                    515: //    +-------------------------------+
                    516: //  3 |   ブロックディスクリプタ長 m  |
                    517: //    +-------------------------------+
                    518: //
                    519: //    (モードパラメータヘッダ、10の時)
                    520: //    +-------------------------------+
                    521: //  0 |      モードパラメータ長       | (このフィールドを含まずこれ以降?)
                    522: //  1 |                               |
                    523: //    +-------------------------------+
                    524: //  2 |        メディアタイプ         |
                    525: //    +-------------------------------+
                    526: //  3 |     デバイス固有パラメータ    |
                    527: //    +-------------------------------+
                    528: //  4 |               0               |
                    529: //  5 |               0               |
                    530: //    +-------------------------------+
                    531: //  6 |   ブロックディスクリプタ長 m  |
                    532: //  7 |                               |
                    533: //    +-------------------------------+
                    534: //
                    535: //    (ブロックディスクリプタ) * m 個
                    536: //    +-------------------------------+
                    537: //  0 |        デンシティコード       | (デバイスタイプごとに固有)
                    538: //    +-------------------------------+
                    539: //  1 |                               |
                    540: //  2 |          ブロック数           |
                    541: //  3 |                               |
                    542: //    +-------------------------------+
                    543: //  4 |               0               |
                    544: //    +-------------------------------+
                    545: //  5 |                               |
                    546: //  6 |          ブロック長           |
                    547: //  7 |                               |
                    548: //    +-------------------------------+ ブロックディスクリプタここまで
                    549: //
                    550: //    (パラメータページ) * ? 個
                    551: //    +---+---+-----------------------+
                    552: //  0 |PS | 0 |     ページコード      | PS:Parameter Savable
                    553: //    +---+---+-----------------------+
                    554: //  1 |           ページ長            | (このバイトを含まずこれ以降の長さ)
                    555: //    +-------------------------------+
                    556: //  2 |  ページコード固有のパラメータ |
                    557: //    :                               :
                    558: //    |                               |
                    559: //    +-------------------------------+
                    560: 
                    561: // コンストラクタ
                    562: SCSICmdModeSelect::SCSICmdModeSelect(SCSITarget *parent_)
                    563:        : inherited(parent_)
                    564: {
                    565: }
                    566: 
                    567: // コマンドフェーズ
                    568: SCSI::XferPhase
1.1.1.6 ! root      569: SCSICmdModeSelect::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      570: {
                    571:        // コマンド開始前に直前のセンスデータをクリア
                    572:        parent->ClearSense();
                    573: 
                    574:        CheckLUN;
                    575: 
                    576:        cmd = cmdseq[0];
                    577:        if (cmd == SCSI::Command::ModeSelect10) {
                    578:                recvbytes  = cmdseq[7] << 8;
                    579:                recvbytes |= cmdseq[8];
                    580:        } else {
                    581:                recvbytes = cmdseq[4];
                    582:        }
                    583: 
                    584:        parent->putlogf(1, lstr("%s len=$%02x",
                    585:                SCSI::GetCommandName(cmd), recvbytes));
                    586: 
                    587:        return SCSI::XferPhase::DataOut;
                    588: }
                    589: 
                    590: // データアウトフェーズ完了
                    591: SCSI::XferPhase
                    592: SCSICmdModeSelect::DoneDataOut()
                    593: {
                    594:        uint block_desc_len;
                    595:        const uint8 *desc;
                    596: 
                    597:        // ヘッダの構造と長さが ModeSelect(6)/(10) で違う
                    598:        if (cmd == SCSI::Command::ModeSelect10) {
                    599:                block_desc_len  = buf[6] << 8;
                    600:                block_desc_len |= buf[7];
                    601:                desc = &buf[8];
                    602:        } else {
                    603:                block_desc_len = buf[3];
                    604:                desc = &buf[4];
                    605:        }
                    606: 
                    607:        if (block_desc_len > 0) {
                    608:                // ブロックディスクリプタの構造は ModeSelect(6)/(10) で共通
                    609:                uint blocksize;
                    610:                blocksize  = desc[5] << 16;
                    611:                blocksize |= desc[6] << 8;
                    612:                blocksize |= desc[7];
                    613: 
                    614:                // ブロック長を書き戻す
                    615:                parent->SetBlocksize(blocksize);
                    616:        }
                    617: 
                    618:        return SCSI::XferPhase::Status;
                    619: }
                    620: 
                    621: 
                    622: //
                    623: // SCSI コマンド 0x1a ModeSense(6)  (共通)
                    624: //               0x5a ModeSense(10) (共通)
                    625: //
                    626: // ModeSense(6):
                    627: //    +---+---+---+---+---+---+---+---+
                    628: //  0 |     Operation Code = 0x1a     |
                    629: //    +-----------+---+---+-----------+
                    630: //  1 |    LUN    | 0 |DBD|     0     | DBD:Disable Block Descriptors
                    631: //    +-------+---+---+---+-----------+
                    632: //  2 |   PC  |       Page Code       | PC:Page Control
                    633: //    +-------+-----------------------+
                    634: //  3 |               0               |
                    635: //    +-------------------------------+
                    636: //  4 |        アロケーション長       |
                    637: //    +-------------------------------+
                    638: //  5 |          Control Byte         |
                    639: //    +-------------------------------+
                    640: //
                    641: // ModeSense(10):
                    642: //    +---+---+---+---+---+---+---+---+
                    643: //  0 |     Operation Code = 0x5a     |
                    644: //    +-----------+---+---+-----------+
                    645: //  1 |    LUN    |LLA|DBD|     0     | DBD:Disable Block Descriptors
                    646: //    +-------+---+---+---+-----------+ LLA:Long LBA Accepted
                    647: //  2 |   PC  |       Page Code       | PC:Page Control
                    648: //    +-------+-----------------------+
                    649: //  3 |           SubPageCode         |
                    650: //    +-------------------------------+
                    651: //  4 |                               |
                    652: //  5 |               0               |
                    653: //  6 |                               |
                    654: //    +-------------------------------+
                    655: //  7 |        アロケーション長       |
                    656: //  8 |                               |
                    657: //    +-------------------------------+
                    658: //  9 |          Control Byte         |
                    659: //    +-------------------------------+
                    660: 
                    661: // コンストラクタ
                    662: SCSICmdModeSense::SCSICmdModeSense(SCSITarget *parent_)
                    663:        : inherited(parent_)
                    664: {
                    665: }
                    666: 
                    667: // コマンドフェーズ
                    668: SCSI::XferPhase
1.1.1.6 ! root      669: SCSICmdModeSense::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      670: {
                    671:        uint reqlen;
                    672: 
                    673:        // コマンド開始前に直前のセンスデータをクリア
                    674:        parent->ClearSense();
                    675: 
                    676:        CheckLUN;
                    677: 
                    678:        uint cmd = cmdseq[0];
                    679:        pc = (PC)(cmdseq[2] >> 6);
                    680:        pagecode = (cmdseq[2] & 0x3f);
                    681:        if (cmd == SCSI::Command::ModeSense10) {
                    682:                reqlen  = cmdseq[7] << 8;
                    683:                reqlen |= cmdseq[8];
                    684:        } else {
                    685:                reqlen = cmdseq[4];
                    686:        }
                    687:        bool dbd = (cmdseq[1] & 0x08);
                    688: 
                    689:        if (parent->loglevel >= 1) {
                    690:                log = string_format("%s %s",
                    691:                        SCSI::GetCommandName(cmd),
                    692:                        SCSI::GetModePageDisp(pagecode).c_str());
                    693:                if (pc != PC::Current) {
1.1.1.5   root      694:                        log += string_format(" PC=%u", (uint)pc);
1.1       root      695:                }
                    696:        }
                    697: 
                    698:        // ヘッダを用意。
                    699: 
                    700:        // メディアタイプ。
                    701:        // XXX 実際にはデバイス種別ごとに定義があるが、とりあえず 0 でよさげ
                    702:        const uint8 mediatype = 0;
                    703:        // デバイス固有パラメータを取得
                    704:        uint8 devspec = parent->GetDeviceSpecificParam();
                    705:        // ブロックディスクリプタ長 (バイト数)
                    706:        uint8 bdlen = dbd ? 0 : 8;
                    707: 
                    708:        // ヘッダは (6) と (10) で形式が違う。
                    709:        // モードパラメータ長(全長)は最後に代入する。
                    710:        buf.clear();
                    711:        if (cmd == SCSI::Command::ModeSense10) {
                    712:                buf.resize(8);
                    713:                buf[2] = mediatype;
                    714:                buf[3] = devspec;
                    715:                buf[6] = bdlen >> 8;
                    716:                buf[7] = bdlen;
                    717:        } else {
                    718:                buf.resize(4);
                    719:                buf[1] = mediatype;
                    720:                buf[2] = devspec;
                    721:                buf[3] = bdlen;
                    722:        }
                    723: 
                    724:        // ブロックディスクリプタ
                    725:        if (dbd == false) {
                    726:                // ブロック数とブロックサイズ
                    727:                uint32 blocks = 0;
                    728:                uint32 blocklen = parent->GetBlocksize();
                    729:                const SCSIDisk *disk = dynamic_cast<const SCSIDisk*>(parent);
                    730:                if (disk) {
                    731:                        blocks = disk->GetSize() / blocklen;
                    732:                }
                    733: 
                    734:                // 1バイトずつ追加していくほうが楽…。
                    735:                // デンシティコードは実際にはデバイスごとだが、だいたい 0 でよさげ。
                    736:                buf.emplace_back(0);                                            // +0 デンシティコード
                    737:                buf.emplace_back((blocks >> 16) & 0xff);        // +1 ブロック数
                    738:                buf.emplace_back((blocks >>  8) & 0xff);        // +2 ブロック数
                    739:                buf.emplace_back( blocks        & 0xff);        // +3 ブロック数
                    740:                buf.emplace_back(0);                                            // +4 reserved
                    741:                buf.emplace_back((blocklen >> 16) & 0xff);      // +5 ブロック長
                    742:                buf.emplace_back((blocklen >>  8) & 0xff);      // +6 ブロック長
                    743:                buf.emplace_back( blocklen        & 0xff);      // +7 ブロック長
                    744:        }
                    745: 
1.1.1.2   root      746:        // モードページ
1.1       root      747:        if (pagecode == SCSI::ModePage::AllPages) {
                    748:                // サポートしているのを全部送る。
                    749:                if (parent->loglevel >= 1) {
                    750:                        log += " " + SCSI::GetModePageDisp(pagecode);
                    751:                        log += "->";
                    752:                }
1.1.1.2   root      753:                for (auto& pair : Pagelist) {
1.1       root      754:                        auto code = pair.first;
1.1.1.2   root      755:                        auto func = pair.second;
1.1       root      756: 
1.1.1.2   root      757:                        if ((this->*(func))() != ModePageResult::Failed) {
1.1       root      758:                                if (parent->loglevel >= 1) {
                    759:                                        log += " " + SCSI::GetModePageDisp(code);
                    760:                                }
                    761:                        }
                    762:                }
                    763:        } else {
                    764:                // 指定されたページコードを送る。
1.1.1.4   root      765:                ModePageResult r = ModePageResult::NotSupported;
1.1.1.2   root      766:                for (auto& pair : Pagelist) {
1.1       root      767:                        auto code = pair.first;
1.1.1.2   root      768:                        auto func = pair.second;
1.1       root      769: 
                    770:                        if (pagecode == code) {
1.1.1.2   root      771:                                r = (this->*(func))();
1.1       root      772:                                break;
                    773:                        }
                    774:                }
                    775: 
                    776:                // Failed は対応しない/できないと分かっているページ、
1.1.1.4   root      777:                // NotSupported は未実装や知らないページ。
1.1       root      778:                if (r <= ModePageResult::Failed) {
                    779:                        if (parent->loglevel >= 1) {
1.1.1.4   root      780:                                if (r == ModePageResult::NotSupported) {
                    781:                                        parent->putlogn("%s not supported", log.c_str());
1.1       root      782:                                } else {
                    783:                                        parent->putlogn("%s", log.c_str());
                    784:                                }
                    785:                        }
                    786:                        parent->sensekey = SCSI::SenseKey::IllegalRequest;
                    787:                        parent->senseasc = SCSI::ASC::InvalidFieldInCDB;
                    788:                        status_byte = SCSI::StatusByte::CheckCondition;
                    789:                        return SCSI::XferPhase::Status;
                    790:                }
                    791:        }
                    792: 
                    793:        parent->putlogf(1, [&] { return log; });
                    794: 
                    795:        // モードパラメータ長は自フィールドを含まない長さ
                    796:        if (cmd == SCSI::Command::ModeSelect10) {
                    797:                uint buflen = buf.size() - 2;
                    798:                buf[0] = buflen >> 8;
                    799:                buf[1] = buflen;
                    800:        } else {
                    801:                uint buflen = buf.size() - 1;
                    802:                buf[0] = buflen;
                    803:        }
                    804: 
                    805:        // 本来の応答データ長か reqlen の短いほうまで
                    806:        if (reqlen < buf.size()) {
                    807:                buf.resize(reqlen);
                    808:        }
                    809:        return SCSI::XferPhase::DataIn;
                    810: }
                    811: 
1.1.1.2   root      812: // ページを送信する順(=昇順)に (手動で) 並べること。
                    813: // ただし 0x00 (VendorSpecific) は最後。
                    814: #define PAGE(code, func)       \
                    815:        { SCSI::ModePage::code, &SCSICmdModeSense::func }
                    816: /*static*/ const std::vector<std::pair<uint8, SCSICmdModeSense::PageFunc>>
                    817: SCSICmdModeSense::Pagelist {
                    818:        PAGE(/*04*/RigidDiskGeometry,   AddNotSupportedPage),
                    819:        PAGE(/*05*/FlexibleDisk,                AddNotSupportedPage),
                    820:        PAGE(/*08*/CachingPage,                 AddCachingPage),
                    821:        PAGE(/*00*/VendorSpecific,              AddEmptyPage),
                    822: };
                    823: 
1.1       root      824: // サポートしないページ
                    825: //
                    826: // ページコード 04 RigidDiskGeometry (DA)
                    827: //  -> 生イメージからジオメトリを求めるのは意味ないので実装しない。
                    828: // ページコード 05 FlexibleDisk (DA)
                    829: //  -> ジオメトリなどのパラメータがメインっぽいので実装しない。
1.1.1.2   root      830: SCSICmdModeSense::ModePageResult
1.1       root      831: SCSICmdModeSense::AddNotSupportedPage()
                    832: {
                    833:        return ModePageResult::Failed;
                    834: }
                    835: 
                    836: // 空のページ
1.1.1.2   root      837: SCSICmdModeSense::ModePageResult
1.1       root      838: SCSICmdModeSense::AddEmptyPage()
                    839: {
                    840:        std::vector<uint8> page(2);
                    841:        page[0] = pagecode;                             // +0 ページコード
                    842:        page[1] = page.size() - 2;              // +1 このバイト以降のページ長
                    843: 
                    844:        buf.insert(buf.end(), page.begin(), page.end());
                    845:        buf[0] += page.size();
                    846:        return ModePageResult::Success;
                    847: }
                    848: 
                    849: // ページコード 08 CachingPage (DA, MO, CD-ROM)
1.1.1.2   root      850: SCSICmdModeSense::ModePageResult
1.1       root      851: SCSICmdModeSense::AddCachingPage()
                    852: {
1.1.1.3   root      853:        // XXX この assert いる?
                    854:        assert(dynamic_cast<const SCSIDisk*>(parent) != NULL);
1.1       root      855: 
                    856:        // とりあえずパラメータはなんもなし。
                    857:        // PC::Changeable でも全部 0 なのでこのままでいい。
                    858:        std::vector<uint8> page(12);
                    859:        page[0] = pagecode;                             // +0 ページコード
                    860:        page[1] = page.size() - 2;              // +1 このバイト以降のページ長
                    861:        // +2 WCE, MF, RCD フラグ
                    862:        // +3 データの保持優先度
                    863:        // +4 プリフェッチ抑止ブロック数
                    864:        // +6 最小プリフェッチ
                    865:        // +8 最大プリフェッチ
                    866:        // +10 最大プリフェッチ制限ブロック数
                    867: 
                    868:        buf.insert(buf.end(), page.begin(), page.end());
                    869:        buf[0] += page.size();
                    870:        return ModePageResult::Success;
                    871: }
                    872: 
                    873: 
                    874: //
                    875: // SCSI コマンド 0x1b StartStopUnit (DA / CD-ROM)
                    876: //
                    877: //    +---+---+---+---+---+---+---+---+
                    878: //  0 |         Operation Code        |
                    879: //    +-----------+---------------+---+
                    880: //  1 |    LUN    |         0     | I | I:Immediate
                    881: //    +-----------+---------------+---+
                    882: //  2 |               0               |
                    883: //  3 |               0               |
                    884: //    +-----------------------+---+---+
                    885: //  4 |               0       |L/E| S | L/E:Load/Eject, S:Start
                    886: //    +-----------------------+---+---+
                    887: //  5 |          Control Byte         |
                    888: //    +-------------------------------+
                    889: 
                    890: // コンストラクタ
                    891: SCSICmdStartStopUnit::SCSICmdStartStopUnit(SCSIDisk *parent_)
                    892:        : inherited(parent_)
                    893: {
                    894:        disk = parent_;
                    895: }
                    896: 
                    897: // コマンドフェーズ
                    898: SCSI::XferPhase
1.1.1.6 ! root      899: SCSICmdStartStopUnit::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      900: {
                    901:        bool immed = (cmdseq[1] & 0x01);
                    902:        if (immed) {
                    903:                parent->putlogf(1, lstr("%s Immed=1 not supported",
                    904:                        SCSI::GetCommandName(cmdseq[0])));
                    905:        }
                    906: 
                    907:        bool loej  = (cmdseq[4] & 0x02);
                    908:        bool start = (cmdseq[4] & 0x01);
1.1.1.5   root      909:        parent->putlogf(1, lstr("%s LoEj=%u Start=%u",
1.1       root      910:                SCSI::GetCommandName(cmdseq[0]), (loej ? 1 : 0), (start ? 1 : 0)));
                    911: 
                    912:        if (disk->IsRemovableDevice()) {
                    913:                // LoEj Start
                    914:                // x    0               媒体へのアクセスを不可にする?
                    915:                // x    1               媒体へのアクセスを可にする?
                    916:                // 1    0               媒体のアンロード
                    917:                // 1    1               媒体のロード
                    918:                //
                    919:                // らしいけど、イジェクトのみ対応
                    920:                if (loej) {
                    921:                        if (disk->IsMediumLoaded()) {
                    922:                                disk->UnloadDisk();
                    923:                        } else {
                    924:                                // メディアがロードされてない時にトレイを開ける動作に
                    925:                                // 相当するのは「ファイルダイアログを出す」だが伝わるだろうか
                    926:                                parent->putlogf(0, lstr("%s Loading not supported",
                    927:                                        SCSI::GetCommandName(cmdseq[0])));
                    928:                        }
                    929:                } else {
                    930:                        parent->putlogf(0, lstr("%s LoEj=0 not supported",
                    931:                                SCSI::GetCommandName(cmdseq[0])));
                    932:                }
                    933:        } else {
                    934:                // 固定デバイスなら黙って成功しておく?
                    935:        }
1.1.1.6 ! root      936:        return inherited::ExecCommand(cmdseq);
1.1       root      937: }
                    938: 
                    939: 
                    940: //
                    941: // SCSI コマンド 0x1e PreventAllowMediumRemoval (DA / CD-ROM)
                    942: //
                    943: //    +---+---+---+---+---+---+---+---+
                    944: //  0 |         Operation Code        |
                    945: //    +-----------+-------------------+
                    946: //  1 |    LUN    |         0         |
                    947: //    +-----------+-------------------+
                    948: //  2 |               0               |
                    949: //  3 |               0               |
                    950: //    +---------------------------+---+
                    951: //  4 |               0           | P | P:Prevent
                    952: //    +---------------------------+---+
                    953: //  5 |          Control Byte         |
                    954: //    +-------------------------------+
                    955: 
                    956: // XXX コマンドとしてはダイレクトアクセスデバイスに対しても発行できるが、
                    957: // その時どう応答すべきかは要調査
                    958: 
                    959: // コンストラクタ
                    960: SCSICmdPreventAllowMediumRemoval::SCSICmdPreventAllowMediumRemoval(
                    961:        SCSIDisk *parent_)
                    962:        : inherited(parent_)
                    963: {
                    964:        disk = parent_;
                    965: }
                    966: 
                    967: // コマンドフェーズ
                    968: SCSI::XferPhase
1.1.1.6 ! root      969: SCSICmdPreventAllowMediumRemoval::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root      970: {
                    971:        // コマンド開始前に直前のセンスデータをクリア
                    972:        parent->ClearSense();
                    973: 
                    974:        CheckLUN;
                    975:        CheckMedium;
                    976: 
                    977:        // PreventMediumRemoval() は状態変化でログレベル 1 で表示してるので、
                    978:        // ここではログレベル 2 で常に表示にしておく。
                    979:        uint prevent = cmdseq[4] & 1;
1.1.1.5   root      980:        parent->putlogf(2, lstr("%s prevent=%u",
1.1       root      981:                SCSI::GetCommandName(cmdseq[0]), prevent));
                    982: 
                    983:        disk->PreventMediumRemoval(prevent);
                    984:        return SCSI::XferPhase::Status;
                    985: }
                    986: 
                    987: 
                    988: //
                    989: // SCSI コマンド 0x25 ReadCapacity      (DA)
                    990: //               0x25 ReadCDROMCapacity (CD-ROM)
                    991: //
                    992: //    +---+---+---+---+---+---+---+---+
                    993: //  0 |         Operation Code        |
                    994: //    +-----------+---------------+---+
                    995: //  1 |    LUN    |       0       |Rel|
                    996: //    +-----------+---------------+---+
                    997: //  2 |                               |
                    998: //  3 |      論理ブロックアドレス     |
                    999: //  4 |      (PMI=0 なら 0)           |
                   1000: //  5 |                               |
                   1001: //    +-------------------------------+
                   1002: //  6 |               0               |
                   1003: //  7 |               0               |
                   1004: //    +---------------------------+---+
                   1005: //  8 |               0           |PMI|
                   1006: //    +---------------------------+---+
                   1007: //  9 |          Control Byte         |
                   1008: //    +-------------------------------+
                   1009: //
                   1010: // CD-ROM デバイスでは同じ 0x25 で Read CDROM Capacity というコマンド名。
                   1011: // Read CDROM Capacity のほうはオーディオ CD の場合の意味分けが追加されて
                   1012: // いるが、たぶんデータ CD だけを扱ううちはダイレクトアクセスデバイスの
                   1013: // Read Capacity と同じでいいはず。
                   1014: 
                   1015: // コンストラクタ
                   1016: SCSICmdReadCapacity::SCSICmdReadCapacity(SCSIDisk *parent_)
                   1017:        : inherited(parent_)
                   1018: {
                   1019:        disk = parent_;
                   1020: }
                   1021: 
                   1022: // コマンドフェーズ
                   1023: SCSI::XferPhase
1.1.1.6 ! root     1024: SCSICmdReadCapacity::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root     1025: {
                   1026:        // コマンド開始前に直前のセンスデータをクリア
                   1027:        parent->ClearSense();
                   1028: 
                   1029:        CheckLUN;
                   1030:        CheckMedium;
                   1031: 
                   1032:        // PMI=1 は未サポート
                   1033:        if ((cmdseq[8] & 0x01) != 0) {
                   1034:                parent->putlogf(0, lstr("%s PMI=1 not supported",
                   1035:                        SCSI::GetCommandName(cmdseq[0])));
                   1036:        }
                   1037: 
                   1038:        // 応答データは
                   1039:        // +00.L 最終論理ブロックアドレス
                   1040:        // +04.L ブロック長
                   1041:        uint32 blksize = parent->GetBlocksize();
                   1042:        uint32 lastblk = (disk->GetSize() / blksize) - 1;
                   1043:        parent->putlogf(1, lstr("%s -> lastblk=$%x blksize=$%x",
                   1044:                SCSI::GetCommandName(cmdseq[0]), lastblk, blksize));
                   1045:        buf.resize(8);
                   1046:        buf[0] = lastblk >> 24;
                   1047:        buf[1] = lastblk >> 16;
                   1048:        buf[2] = lastblk >> 8;
                   1049:        buf[3] = lastblk;
                   1050:        buf[4] = blksize >> 24;
                   1051:        buf[5] = blksize >> 16;
                   1052:        buf[6] = blksize >> 8;
                   1053:        buf[7] = blksize;
                   1054: 
                   1055:        return SCSI::XferPhase::DataIn;
                   1056: }
                   1057: 
                   1058: 
                   1059: //
                   1060: // SCSI コマンド 0x43 ReadTOC (CD-ROM)
                   1061: //
                   1062: //    +---+---+---+---+---+---+---+---+
                   1063: //  0 |         Operation Code        |
                   1064: //    +-----------+-----------+---+---+
                   1065: //  1 |    LUN    |     0     |MSF| 0 |
                   1066: //    +-----------+-----------+---+---+
                   1067: //  2 |               0               |
                   1068: //  3 |               0               |
                   1069: //  4 |               0               |
                   1070: //  5 |               0               |
                   1071: //    +-------------------------------+
                   1072: //  6 |          開始トラック         |
                   1073: //    +-------------------------------+
                   1074: //  7 |        アロケーション長       |
                   1075: //  8 |                               |
                   1076: //    +-------------------------------+
                   1077: //  9 |          Control Byte         |
                   1078: //    +-------------------------------+
                   1079: 
                   1080: // コンストラクタ
                   1081: SCSICmdReadTOC::SCSICmdReadTOC(SCSIDisk *parent_)
                   1082:        : inherited(parent_)
                   1083: {
                   1084:        disk = parent_;
                   1085: }
                   1086: 
                   1087: // コマンドフェーズ
                   1088: SCSI::XferPhase
1.1.1.6 ! root     1089: SCSICmdReadTOC::ExecCommand(std::vector<uint8>& cmdseq)
1.1       root     1090: {
                   1091:        // コマンド開始前に直前のセンスデータをクリア
                   1092:        parent->ClearSense();
                   1093: 
                   1094:        CheckLUN;
                   1095:        CheckMedium;
                   1096: 
                   1097:        // MSF 形式は未実装
                   1098:        if ((cmdseq[1] & 0x02)) {
1.1.1.4   root     1099:                parent->putlogf(0, lstr("ReadTOC MSF=1 (NOT IMPLEMENTED)"));
1.1       root     1100:        }
                   1101: 
                   1102:        // 開始トラックが 0 なら、媒体上の先頭トラックからを意味する。
                   1103:        // ここでは1トラック目から始まることにしてみる。
1.1.1.5   root     1104:        const uint TrackStart = 1;
                   1105:        const uint TrackMax = 1;
1.1       root     1106: 
1.1.1.5   root     1107:        uint start = cmdseq[6];
1.1       root     1108:        if (start == 0) {
                   1109:                start = TrackStart;
                   1110:        }
                   1111: 
                   1112:        // イニシエータが用意しているバッファ長
1.1.1.5   root     1113:        uint reqlen = (cmdseq[7] << 8) | cmdseq[8];
1.1       root     1114: 
                   1115:        // start は送られてきた情報が知りたいだろう
                   1116:        parent->putlogf(1, lstr("%s start=$%x len=$%x",
                   1117:                SCSI::GetCommandName(cmdseq[0]), cmdseq[6], reqlen));
                   1118: 
                   1119:        // ヘッダ4バイト + トラックディスクリプタ(8バイト) * トラック数で、
                   1120:        // ここではトラックは常に1つ。
                   1121:        buf.clear();
                   1122:        buf.resize(4 + 8 * 1);
                   1123: 
                   1124:        // TOC データ長はこの2バイトのフィールドを含まないバイト数で、
                   1125:        // 開始トラック以降の有効な全トラック数。
1.1.1.5   root     1126:        uint tocdatalen = 2;
1.1       root     1127:        if (start <= TrackMax) {
                   1128:                tocdatalen += (TrackMax - start) * 8;
                   1129:        }
                   1130:        // 開始論理アドレス
                   1131:        uint32 address = 0;
                   1132: 
                   1133:        // ヘッダ
                   1134:        buf[0]  = tocdatalen >> 8;      // TOC データ長
                   1135:        buf[1]  = tocdatalen;           // TOC データ長
                   1136:        buf[2]  = start;                        // 先頭トラック番号
                   1137:        buf[3]  = TrackMax;                     // 最終トラック番号
                   1138:        // トラック1
                   1139:        buf[4]  = 0;                            // Reserved
                   1140:        buf[5]  = 0x06;                         // ADR=0(?)、データトラック
                   1141:        buf[6]  = 1;                            // トラック番号
                   1142:        buf[7]  = 0;                            // Reserved
                   1143:        buf[8]  = address >> 24;        // 論理アドレス
                   1144:        buf[9]  = address >> 16;        // 論理アドレス
                   1145:        buf[10] = address >> 8;         // 論理アドレス
                   1146:        buf[11] = address;                      // 論理アドレス
                   1147: 
                   1148:        // 本来の応答データ長か reqlen の短いほうまで
                   1149:        if (reqlen < buf.size()) {
                   1150:                buf.resize(reqlen);
                   1151:        }
                   1152: 
                   1153:        return SCSI::XferPhase::DataIn;
                   1154: }
1.1.1.6 ! root     1155: 
        !          1156: //
        !          1157: // SCSI コマンド 0xa0 ReportLUNs
        !          1158: //
        !          1159: //    +---+---+---+---+---+---+---+---+
        !          1160: //  0 |         Operation Code        |
        !          1161: //    +-----------+-------------------+
        !          1162: //  1 |  Ignored  |         0         |
        !          1163: //    +-------------------------------+
        !          1164: //  2 |          Select Report        |
        !          1165: //    +-------------------------------+
        !          1166: //  3 |               0               |
        !          1167: //  4 |               0               |
        !          1168: //  5 |               0               |
        !          1169: //    +-------------------------------+
        !          1170: //  6 |                               |
        !          1171: //  7 |        アロケーション長       |
        !          1172: //  8 |                               |
        !          1173: //  9 |                               |
        !          1174: //    +-------------------------------+
        !          1175: // 10 |               0               |
        !          1176: //    +-------------------------------+
        !          1177: // 11 |          Control Byte         |
        !          1178: //    +-------------------------------+
        !          1179: 
        !          1180: // Response:
        !          1181: //    +-------------------------------+
        !          1182: //  0 |                               |
        !          1183: //  1 |         LUN リスト長          |
        !          1184: //  2 | (先頭8バイト以降のバイト数?)  |
        !          1185: //  3 |                               |
        !          1186: //    +-------------------------------+
        !          1187: //  4 |                               |
        !          1188: //  5 |               0               |
        !          1189: //  6 |                               |
        !          1190: //  7 |                               |
        !          1191: //    +-------------------------------+
        !          1192: //    +-------+-----------------------+ [0]
        !          1193: //  8 |   0   |        Bus ID         |
        !          1194: //    +-------+-----------------------+
        !          1195: //  9 |    Single Level LUN Address   |
        !          1196: //    +-------------------------------+
        !          1197: // 10 |    Second Level LUN Address   |
        !          1198: // 11 |                               |
        !          1199: //    +-------------------------------+
        !          1200: // 12 |    Third Level LUN Address    |
        !          1201: // 13 |                               |
        !          1202: //    +-------------------------------+
        !          1203: // 14 |    Fourth Level LUN Address   |
        !          1204: // 15 |                               |
        !          1205: //    +-------------------------------+ [1]
        !          1206: //                   :

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.