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

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

unix.superglobalmegacorp.com

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