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

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

unix.superglobalmegacorp.com

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