Annotation of nono/vm/spc.h, revision 1.1.1.18

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.12  root        7: //
                      8: // SPC (MB89352)
                      9: //
                     10: 
1.1       root       11: #pragma once
                     12: 
                     13: #include "device.h"
1.1.1.12  root       14: #include "event.h"
1.1       root       15: #include "fixedqueue.h"
1.1.1.17  root       16: #include "mainapp.h"
1.1.1.18! root       17: #include "scsi.h"
        !            18: #include "scsibus.h"
1.1       root       19: 
1.1.1.14  root       20: class InterruptDevice;
1.1.1.18! root       21: class SCSIDomain;
1.1.1.16  root       22: class SCSIHostDevice;
1.1.1.14  root       23: 
1.1       root       24: struct SPC
                     25: {
1.1.1.16  root       26:        static const uint BDID = 0x0;   // $E96021 RW  $E100_0000
                     27:        static const uint SCTL = 0x1;   // $E96023 RW  $E100_0004
                     28:        static const uint SCMD = 0x2;   // $E96025 RW  $E100_0008
                     29:        static const uint TMOD = 0x3;   // (MB89352 にはない)
                     30:        static const uint INTS = 0x4;   // $E96029 RW  $E100_0010
                     31:        static const uint PSNS = 0x5;   // $E9602B R-  $E100_0014
                     32:        static const uint SDGC = 0x5;   // $E9602B -W  $E100_0014
                     33:        static const uint SSTS = 0x6;   // $E9602D R-  $E100_0018
                     34:        static const uint SERR = 0x7;   // $E9602F R-  $E100_001C
                     35:        static const uint PCTL = 0x8;   // $E96031 RW  $E100_0020
                     36:        static const uint MBC  = 0x9;   // $E96033 R-  $E100_0024
                     37:        static const uint DREG = 0xa;   // $E96035 RW  $E100_0028
                     38:        static const uint TEMP = 0xb;   // $E96037 RW  $E100_002C
                     39:        static const uint TCH  = 0xc;   // $E96039 RW  $E100_0030
                     40:        static const uint TCM  = 0xd;   // $E9603B RW  $E100_0034
                     41:        static const uint TCL  = 0xe;   // $E9603D RW  $E100_0038
                     42:        static const uint EXBF = 0xf;   // (MB89352 にはない)
1.1       root       43: 
                     44: 
                     45:        // SCTL レジスタ
                     46:        // 全ビットを保持。
                     47:        uint8 sctl;
1.1.1.16  root       48:        static const uint SCTL_RESET            = 0x80; // Reset & Disable
                     49:        static const uint SCTL_CTL_RESET        = 0x40; // Control Reset
                     50:        static const uint SCTL_DIAG_MODE        = 0x20; // Diag Mode
                     51:        static const uint SCTL_ARBIT_EN         = 0x10; // Arbitration Enable
                     52:        static const uint SCTL_PARITY_EN        = 0x08; // Parity Enable
                     53:        static const uint SCTL_SEL_EN           = 0x04; // Select Enable
                     54:        static const uint SCTL_RESEL_EN         = 0x02; // Reselect Enable
                     55:        static const uint SCTL_INTR_EN          = 0x01; // Interrupt Enable
1.1       root       56: 
                     57:        // SCMD レジスタ
1.1.1.2   root       58:        // 全ビットを保持。
1.1       root       59:        uint8 scmd;
1.1.1.16  root       60:        static const uint SCMD_CMD_MASK         = 0xe0; // Command code
                     61:        static const uint SCMD_RST_OUT          = 0x10; // RST Out
                     62:        static const uint SCMD_INTERCEPT        = 0x08; // Intersept Transfer
                     63:        static const uint SCMD_PROGRAM          = 0x04; // Program Transfer
                     64:        static const uint SCMD_TERM_MODE        = 0x01; // Termination Mode
1.1       root       65: 
                     66:        // INTS レジスタ
1.1.1.7   root       67:        //
                     68:        // 内部変数 ints は割り込み状態を一度に判別するため SERR レジスタの
                     69:        // xfer ビット(SERR_XFER_OUT) もここの bit8 に含めている。
                     70:        // 残りの下位8ビットは INTS と同じ。
                     71:        //
                     72:        //               | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
                     73:        // INTS          |SEL |RESL|DIS |CMPL|SERV|TOUT|HERR|REST|
                     74:        //            b8
                     75:        // ints変数 |xfer|SEL |RESL|DIS |CMPL|SERV|TOUT|HERR|REST|
                     76:        //
                     77:        uint16 ints;
1.1.1.16  root       78:        static const uint INTS_SELECTED         = 0x80; // Selected
                     79:        static const uint INTS_RESELECTED       = 0x40; // Reselected
                     80:        static const uint INTS_DISCONNECTED     = 0x20; // Disconnected
                     81:        static const uint INTS_COMPLETE         = 0x10; // Command Complete
                     82:        static const uint INTS_SERV_REQ         = 0x08; // Service Required
                     83:        static const uint INTS_TIMEOUT          = 0x04; // Time Out
                     84:        static const uint INTS_HARD_ERR         = 0x02; // SPC Hard Error
                     85:        static const uint INTS_RESET_COND       = 0x01; // Reset Condition
1.1       root       86: 
1.1.1.16  root       87:        static const uint INTS_XFER_OUT         = 0x100;        // SERR_XFER_OUT
1.1.1.7   root       88: 
                     89:        // 割り込みマスク (INTS_RESET_COND はノンマスカブル割り込み)
                     90:        uint16 ints_mask;
1.1.1.16  root       91:        static const uint INTS_ENABLE_MASK      = 0x01ff;
                     92:        static const uint INTS_DISABLE_MASK     = 0x0001;
1.1.1.7   root       93: 
1.1       root       94:        // PSNS レジスタ
                     95:        uint8 psns;
1.1.1.16  root       96:        static const uint PSNS_REQ                      = 0x80;
                     97:        static const uint PSNS_ACK                      = 0x40;
                     98:        static const uint PSNS_ATN                      = 0x20;
                     99:        static const uint PSNS_SEL                      = 0x10;
                    100:        static const uint PSNS_BSY                      = 0x08;
                    101:        static const uint PSNS_MSG                      = 0x04;
                    102:        static const uint PSNS_CD                       = 0x02;
                    103:        static const uint PSNS_IO                       = 0x01;
1.1       root      104: 
                    105:        // SDGC レジスタ
                    106:        uint8 sdgc;
1.1.1.16  root      107:        static const uint SDGC_XFER_ENABLE      = 0x20;
1.1       root      108: 
                    109:        // SSTS レジスタ
                    110:        // 上位4ビットを保持。下位4ビットは読み出し時に生成。
                    111:        uint8 ssts;
1.1.1.16  root      112:        static const uint SSTS_CONN_INIT        = 0x80; // Connected (Initiator)
                    113:        static const uint SSTS_CONN_TARG        = 0x40; // Connected (Target)
                    114:        static const uint SSTS_SPC_BUSY         = 0x20; // SPC Busy
                    115:        static const uint SSTS_IN_PROGRESS      = 0x10; // Transfer in Progress
                    116:        static const uint SSTS_RST_IN           = 0x08; // SCSI RST In
                    117:        static const uint SSTS_TC_ZERO          = 0x04; // TC=0
                    118:        static const uint SSTS_DREG_FULL        = 0x02; // DREG Status (Full)
                    119:        static const uint SSTS_DREG_EMPTY       = 0x01; // DREG Status (Empty)
1.1       root      120: 
                    121:        // SERR レジスタ
1.1.1.7   root      122:        // XFER_OUT 以外の4つの有効ビットを保持。
                    123:        // XFER_OUT は ints が担当している。
1.1       root      124:        uint8 serr;
1.1.1.16  root      125:        static const uint SERR_DATAERR_SCSI     = 0x80; // Data Error: SCSI
                    126:        static const uint SERR_DATAERR_SPC      = 0x40; // Data Error: SPC
                    127:        static const uint SERR_XFER_OUT         = 0x20; // Xfer Out
                    128:        static const uint SERR_TC_PARITY_ERR= 0x08;     // TC Parity Error
                    129:        static const uint SERR_SHORT_XFER       = 0x02; // Short Transfer Period
1.1       root      130: 
                    131:        // PCTL レジスタ
1.1.1.11  root      132:        // BusFree INT Enable は独立して保持。
                    133:        // MSG, CD, IO の3ビットは pctl_out で保持。
1.1       root      134:        bool busfree_intr_enable;
1.1.1.11  root      135:        uint8 pctl_out;
1.1.1.16  root      136:        static const uint PCTL_MASK                     = 0x87; // 書き込みマスク
                    137:        static const uint PCTL_BFINT_EN         = 0x80; // BusFree INT Enable
                    138:        static const uint PCTL_MSG                      = 0x04;
                    139:        static const uint PCTL_CD                       = 0x02;
                    140:        static const uint PCTL_IO                       = 0x01;
1.1       root      141: 
                    142:        FixedQueue<uint8, 8> dreg;      // DREG レジスタ
                    143: 
                    144:        uint8 temp_in;  // TEMP レジスタ (SCSI -> MPU)
                    145:        uint8 temp_out; // TEMP レジスタ (MPU -> SCSI)
                    146:        uint32 tc;              // TC
                    147: 
                    148:        uint32 GetTCL() const { return tc & 0x0000ff; } // TCL
                    149: 
                    150:        // MBC (内部の読み込み専用レジスタ)
                    151:        // TC の下位4ビットが読めるらしい
                    152:        uint8 mbc() const {
                    153:                return tc & 15;
                    154:        }
                    155: };
                    156: 
1.1.1.16  root      157: class SPCDevice : public IODevice
1.1       root      158: {
1.1.1.16  root      159:        using inherited = IODevice;
1.1       root      160:  public:
1.1.1.3   root      161:        SPCDevice();
1.1.1.15  root      162:        ~SPCDevice() override;
1.1       root      163: 
1.1.1.18! root      164:        void SetLogLevel(int loglevel_) override;
1.1.1.16  root      165:        bool Create() override;
1.1.1.4   root      166:        bool Init() override;
1.1.1.12  root      167:        void ResetHard(bool poweron) override;
1.1       root      168: 
1.1.1.18! root      169:        SCSIDomain *GetDomain() const noexcept { return domain.get(); }
1.1       root      170: 
1.1.1.8   root      171:        // BusIO インタフェース
                    172:        // (内蔵 ROM からのアクセス用に特別に public にしてある)
1.1.1.16  root      173:        busdata WritePort(uint32 offset, uint32 data);
1.1.1.3   root      174:  protected:
                    175:        static const uint32 NPORT = 16;
1.1.1.16  root      176:        busdata ReadPort(uint32 offset);
                    177:        busdata PeekPort(uint32 offset);
                    178:        bool PokePort(uint32 offset, uint32 data);
1.1.1.3   root      179: 
1.1       root      180:  private:
1.1.1.10  root      181:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    182: 
1.1.1.5   root      183:        void MonitorReg(TextScreen&,
                    184:                int x, int y, uint32 reg, const char * const *names);
1.1       root      185: 
1.1.1.16  root      186:        // バスフリーになった (SCSIHostDevice からのコールバック)
                    187:        void BusFreeCallback(uint id);
                    188: 
                    189:        // ターゲットがセレクションに応答した (SCSIHostDevice からのコールバック)
                    190:        void SelectionAckCallback();
                    191: 
                    192:        // 情報転送フェーズで REQ を立てた (SCSIHostDevice からのコールバック)
                    193:        void TransferReqCallback();
                    194: 
1.1       root      195:        // SCTL レジスタへの書き込み
                    196:        void WriteSCTL(uint32);
1.1.1.7   root      197:        // 割り込みマスクの再構成
                    198:        void MakeIntsMask();
1.1       root      199: 
                    200:        // SCMD レジスタへの書き込み
                    201:        void WriteSCMD(uint32);
                    202: 
                    203:        // INTS レジスタへの書き込み
                    204:        void WriteINTS(uint32);
1.1.1.3   root      205:        // 表示のための前回値
                    206:        uint32 prev_ints {};
1.1       root      207: 
                    208:        // INTS 設定
                    209:        void SetINTS(uint32);
1.1.1.7   root      210:        // INTS レジスタ値の取得
                    211:        uint32 GetINTS() const;
                    212:        // 割り込み信号線の状態を変える
                    213:        void ChangeInterrupt();
1.1       root      214: 
                    215:        // PSNS レジスタ値の取得
                    216:        uint32 GetPSNS() const;
                    217: 
                    218:        // SSTS レジスタ値の取得
                    219:        uint32 GetSSTS() const;
1.1.1.3   root      220:        // 表示のための前回値
                    221:        uint32 prev_ssts {};
1.1       root      222: 
1.1.1.7   root      223:        // SERR レジスタ値の取得
                    224:        uint32 GetSERR() const;
                    225: 
1.1.1.11  root      226:        // PCTL レジスタへの書き込み
                    227:        void WritePCTL(uint32);
1.1       root      228:        // PCTL レジスタ値の取得
                    229:        uint32 GetPCTL() const;
                    230: 
1.1.1.3   root      231:        // DREG レジスタアクセス
1.1.1.15  root      232:        busdata ReadDREG();
                    233:        busdata WriteDREG(uint32 data);
1.1.1.3   root      234: 
1.1       root      235:        // バスフリーフェーズに移行する
                    236:        void BusFree();
1.1.1.2   root      237:        // 直近のバスフリーフェーズになった時刻
                    238:        // (アービトレーション/セレクション開始時に使う)
                    239:        uint64 last_busfree_time {};
                    240:        // バスをリリースする
                    241:        void BusRelease();
1.1       root      242: 
                    243:        // Select コマンド実行
                    244:        void SelectCommand();
1.1.1.6   root      245:        void Arbitration1(Event& ev);
                    246:        void Arbitration2(Event& ev);
                    247:        void Selection1(Event& ev);
                    248:        void SelectionTimeout(Event& ev);
1.1.1.2   root      249: 
                    250:        // SetATN コマンド実行
                    251:        void SetATNCommand();
                    252:        // セレクションフェーズで ATN を立てる
1.1.1.6   root      253:        bool set_atn_in_selection {};
1.1       root      254: 
                    255:        // Transfer コマンド実行
                    256:        void TransferCommand();
1.1.1.6   root      257:        void HardwareTransfer(Event& ev);
1.1.1.3   root      258:        void TransferComplete();
1.1.1.2   root      259:        // Transfer コマンド実行中なら true
1.1.1.6   root      260:        bool transfer_command_running {};
1.1       root      261: 
                    262:        // SCSI コマンド
                    263:        void ExecCommand();
                    264: 
1.1.1.18! root      265:        //
        !           266:        // 信号線制御
        !           267:        // (ソースコード的なショートカットのため)
        !           268:        //
        !           269:        bool GetRST() const                             { return bus->GetRST(); }
        !           270:        void AssertRST()                                { bus->AssertRST(); }
        !           271:        void NegateRST()                                { bus->NegateRST(); }
        !           272:        bool GetREQ() const                             { return bus->GetREQ(); }
        !           273:        void AssertREQ()                                { bus->AssertREQ(); }
        !           274:        void NegateREQ()                                { bus->NegateREQ(); }
        !           275:        bool GetACK() const                             { return bus->GetACK(); }
        !           276:        void AssertACK()                                { bus->AssertACK(); }
        !           277:        void NegateACK()                                { bus->NegateACK(); }
        !           278:        bool GetATN() const                             { return bus->GetATN(); }
        !           279:        void AssertATN()                                { bus->AssertATN(); }
        !           280:        void NegateATN()                                { bus->NegateATN(); }
        !           281:        uint8 GetSEL() const                    { return bus->GetSEL(); }
        !           282:        void AssertSEL()                                { bus->AssertSEL(myid); }
        !           283:        void NegateSEL()                                { bus->NegateSEL(myid); }
        !           284:        uint8 GetBSY() const                    { return bus->GetBSY(); }
        !           285:        void AssertBSY()                                { bus->AssertBSY(myid); }
        !           286:        void NegateBSY()                                { bus->NegateBSY(myid); }
        !           287:        bool GetMSG() const                             { return bus->GetMSG(); }
        !           288:        bool GetCD() const                              { return bus->GetCD(); }
        !           289:        bool GetIO() const                              { return bus->GetIO(); }
        !           290:        SCSI::XferPhase GetXfer() const { return bus->GetXfer(); }
        !           291:        void SetXfer(uint8 val)                 { bus->SetXfer(val); }
        !           292:        SCSI::Phase GetPhase() const    { return bus->GetPhase(); }
        !           293:        uint8 GetData() const                   { return bus->GetData(); }
        !           294:        void SetData(uint8 val) const   { bus->SetData(val); }
        !           295: 
1.1       root      296:        // レジスタ
                    297:        struct SPC spc {};
                    298: 
1.1.1.3   root      299:        // VM 種別
1.1.1.13  root      300:        VMType vmtype {};
1.1       root      301: 
1.1.1.16  root      302:        // イニシエータの SCSI ID (参照箇所が多いのでコピー)
                    303:        uint myid {};
                    304: 
1.1       root      305:        // SPC に入力されるクロック周期 [nsec]
1.1.1.16  root      306:        uint64 t_CLF {};
1.1.1.6   root      307: 
                    308:        // アクセスウェイト
1.1.1.15  root      309:        busdata read_wait {};
                    310:        busdata write_wait {};
1.1.1.6   root      311: 
1.1.1.16  root      312:        // モニタ表示用
                    313:        uint32 baseaddr {};
                    314:        uint32 regoffset {};
                    315: 
1.1.1.7   root      316:        // 割り込み信号線の接続先デバイス
                    317:        InterruptDevice *interrupt {};
                    318: 
1.1       root      319:        // イベント
1.1.1.16  root      320:        Event phase_event { this };
                    321:        Event timer_event { this };
                    322: 
1.1.1.18! root      323:        // SCSI 管理
        !           324:        std::unique_ptr<SCSIDomain> domain /*{}*/;
        !           325: 
        !           326:        // SCSI ホストアダプタ
        !           327:        SCSIHostDevice *host {};
        !           328: 
        !           329:        // SCSI バス
        !           330:        std::unique_ptr<SCSIBus> bus /*{}*/;
1.1.1.10  root      331: 
1.1.1.17  root      332:        Monitor *monitor {};
1.1       root      333: };
                    334: 
1.1.1.14  root      335: static inline SPCDevice *GetSPCDevice() {
                    336:        return Object::GetObject<SPCDevice>(OBJ_SPC);
                    337: }

unix.superglobalmegacorp.com

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