Annotation of nono/vm/scsitarget.cpp, revision 1.1.1.1

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: };

unix.superglobalmegacorp.com

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