Annotation of nono/vm/fdc.h, revision 1.1.1.13

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.7   root        7: //
1.1.1.8   root        8: // FDC (uPD72065B) + I/O コントローラ
1.1.1.7   root        9: //
                     10: 
1.1       root       11: #pragma once
                     12: 
1.1.1.8   root       13: #include "device.h"
                     14: #include "fixedqueue.h"
                     15: #include <array>
1.1       root       16: 
1.1.1.9   root       17: class DMACDevice;
1.1.1.8   root       18: class FDDDevice;
1.1.1.9   root       19: class PEDECDevice;
1.1.1.8   root       20: 
                     21: struct FDCCmdBuf
                     22: {
                     23:        union {
                     24:                uint8 buf[10];
1.1       root       25: 
1.1.1.8   root       26:                struct {
                     27:                        uint8 code;
                     28:                        union {
                     29:                                // READ DATA, READ DELETED DATA
                     30:                                // WRITE DATA, WRITE DELETED DATA
                     31:                                // READ DIAGNOSTIC
                     32:                                struct {
                     33:                                        uint8 hd_us;
                     34:                                        uint8 c;
                     35:                                        uint8 h;
                     36:                                        uint8 r;
                     37:                                        uint8 n;
                     38:                                        uint8 eot;
                     39:                                        uint8 gsl;
                     40:                                        uint8 dtl;
                     41:                                } data;
                     42: 
                     43:                                // SCAN EQUAL, SCAN LOW OR EQUAL, SCAN HIGH OR EQUAL
                     44:                                struct {
                     45:                                        uint8 hd_us;
                     46:                                        uint8 c;
                     47:                                        uint8 h;
                     48:                                        uint8 r;
                     49:                                        uint8 n;
                     50:                                        uint8 eot;
                     51:                                        uint8 gsl;
                     52:                                        uint8 dtl;
                     53:                                        uint8 stp;
                     54:                                } scan;
                     55: 
                     56:                                struct {
                     57:                                        uint8 us;
                     58:                                        uint8 ncn;
                     59:                                } seek;
                     60: 
                     61:                                struct {
                     62:                                        uint8 us;
                     63:                                } recalibrate;
                     64: 
                     65:                                struct {
                     66:                                        uint8 srt_hut;
                     67:                                        uint8 hlt_nd;
                     68:                                } specify;
                     69: 
                     70:                                // READ ID
                     71:                                struct {
                     72:                                        uint8 hd_us;
                     73:                                } read_id, sense_device_status;
                     74: 
                     75:                                struct {
                     76:                                        uint8 hd_us;
                     77:                                        uint8 n;
                     78:                                        uint8 sc;
                     79:                                        uint8 gpl;
                     80:                                        uint8 d;
                     81:                                } write_id;
                     82:                        };
                     83:                };
                     84:        };
                     85: 
1.1.1.11  root       86:        uint len;
1.1.1.8   root       87: 
                     88:        void Clear() {
                     89:                len = 0;
                     90:        }
1.1       root       91: };
                     92: 
1.1.1.8   root       93: struct FDCResBuf
                     94: {
                     95:        union {
                     96:                uint8 buf[7];
                     97: 
                     98:                struct {
                     99:                        uint8 st0;
                    100:                        uint8 st1;
                    101:                        uint8 st2;
                    102:                        uint8 c;
                    103:                        uint8 h;
                    104:                        uint8 r;
                    105:                        uint8 n;
                    106:                } data;
                    107: 
                    108:                struct {
                    109:                        uint8 st0;
                    110:                        uint8 pcn;
                    111:                } interrupt_status;
                    112: 
                    113:                struct {
                    114:                        uint8 st3;
                    115:                } device_status;
                    116: 
                    117:                struct {
                    118:                        uint8 st0;
                    119:                } invalid;
                    120:        };
                    121: 
                    122:        int len {};
                    123:        int pos {};
                    124: 
                    125:        void Clear() {
                    126:                len = 0;
                    127:                pos = 0;
                    128:        }
                    129: 
                    130:        uint8 Take() {
                    131:                assert(pos < len);
                    132:                return buf[pos++];
                    133:        }
                    134: 
                    135:        uint8 Peek() {
                    136:                assert(pos < len);
                    137:                return buf[pos];
                    138:        }
1.1       root      139: };
                    140: 
1.1.1.8   root      141: 
1.1.1.6   root      142: class FDCDevice : public IODevice
1.1       root      143: {
1.1.1.2   root      144:        using inherited = IODevice;
1.1.1.11  root      145:        static const uint32 baseaddr = 0xe94000;
1.1       root      146: 
                    147:  public:
1.1.1.8   root      148:        // サポートしているドライブ数上限
1.1.1.11  root      149:        static const uint MAX_DRIVE = 4;
1.1.1.8   root      150: 
                    151:  private:
                    152:        // コマンド定義
                    153:        struct FDCCmd
                    154:        {
                    155:                uint8 code;
                    156:                uint8 mask;
                    157:                int cmdlen;
                    158:                void (FDCDevice::*func)();
                    159:                const char *name;
                    160:        };
                    161: 
                    162:        // ユニットのポーリング時の動作状態
                    163:        enum class UnitState {
                    164:                Idle,
                    165:                Seek,
                    166:                Recalibrate,
                    167:        };
                    168: 
                    169:        // ユニットの状態
                    170:        struct UnitInfo {
                    171:                // FDC が記憶しているヘッドがいることになっているシリンダ番号。
                    172:                // FDD の実際のヘッド位置とは必ずしも一致しない。
                    173:                int pcn;
                    174:                // シーク先のシリンダ番号
                    175:                int ncn;
                    176:                // ユニットごとの、前回調べた READY
                    177:                bool ready;
                    178:                // ポーリング時動作状態
                    179:                UnitState state;
                    180: 
                    181:                uint64 ready_time;      // READY になった時刻
                    182:        };
                    183: 
                    184:        // FDC の動作フェーズ
                    185:        enum fdc_phase_t {
                    186:                PHASE_COMMAND,
                    187:                PHASE_EXEC,
                    188:                PHASE_RESULT,
                    189:        };
                    190: 
                    191:        // マスタステータスレジスタ
                    192:        static const uint32 MSR_RQM             = 0x80;
                    193:        static const uint32 MSR_DIO             = 0x40;
                    194:        static const uint32 MSR_NDM             = 0x20;
                    195:        static const uint32 MSR_CB              = 0x10;
                    196:        static const bool DIOtoFDC              = false;
                    197:        static const bool DIOtoHost             = true;
                    198:        struct MSR {
                    199:                bool rqm;                               // Request For Master
                    200:                bool dio;                               // Data Input/Output
                    201:                bool ndm;                               // Non-DMA Mode
                    202:                bool cb;                                // FDC Busy
                    203:                std::array<bool, 4> db; // FDn Busy (注:seek中/割り込み保留中)
                    204:        };
                    205: 
                    206:        // ST0 レジスタ
                    207:        static const uint32 ST0_IC_NT   = 0x00;
                    208:        static const uint32 ST0_IC_AT   = 0x40;
                    209:        static const uint32 ST0_IC_IC   = 0x80;
                    210:        static const uint32 ST0_IC_AI   = 0xc0;
                    211:        static const uint32 ST0_SE              = 0x20;
                    212:        static const uint32 ST0_EC              = 0x10;
                    213:        static const uint32 ST0_NR              = 0x08;
                    214:        static const uint32 ST0_HD              = 0x04;
                    215:        static const uint32 ST0_US              = 0x03;
                    216:        struct ST0 {
                    217:                uint8 ic;                               // Interrupt Code
                    218:                bool se;                                // Seek End
                    219:                bool ec;                                // Equipment Check
                    220:                bool nr;                                // Not Ready
                    221:                bool hd;
                    222:                uint8 us;
                    223:        };
                    224: 
                    225:        // ST1 レジスタ
                    226:        static const uint32 ST1_EN              = 0x80;
                    227:        static const uint32 ST1_DE              = 0x20;
                    228:        static const uint32 ST1_OR              = 0x10;
                    229:        static const uint32 ST1_ND              = 0x04;
                    230:        static const uint32 ST1_NW              = 0x02;
                    231:        static const uint32 ST1_MA              = 0x01;
                    232:        struct ST1 {
                    233:                bool en;                                // End of Cylinder
                    234:                bool de;                                // Data Error
                    235:                bool overrun;                   // Over Run
                    236:                bool nd;                                // No Data
                    237:                bool nw;                                // Not Writable
                    238:                bool ma;                                // Missing Address Mark
                    239:        };
                    240: 
                    241:        // ST2 レジスタ
                    242:        static const uint32 ST2_CM              = 0x40;
                    243:        static const uint32 ST2_DD              = 0x20;
                    244:        static const uint32 ST2_NC              = 0x10;
                    245:        static const uint32 ST2_SH              = 0x08;
                    246:        static const uint32 ST2_SN              = 0x04;
                    247:        static const uint32 ST2_BC              = 0x02;
                    248:        static const uint32 ST2_MD              = 0x01;
                    249:        struct ST2 {
                    250:                bool cm;                                // Control Mark
                    251:                bool dd;                                // Data Error In Data Field
                    252:                bool nc;                                // No Cylinder
                    253:                bool sh;                                // Scan Equal Hit
                    254:                bool sn;                                // Scan Not Satisfied
                    255:                bool bc;                                // Bad Cylinder
                    256:                bool md;                                // Missing Addrss Mark in Data Field
                    257:        };
                    258: 
                    259:        // ST3 レジスタ
                    260:        static const uint32 ST3_FT              = 0x80;
                    261:        static const uint32 ST3_WP              = 0x40;
                    262:        static const uint32 ST3_RY              = 0x20;
                    263:        static const uint32 ST3_T0              = 0x10;
                    264:        static const uint32 ST3_TS              = 0x08;
                    265:        static const uint32 ST3_HD              = 0x04;
                    266:        static const uint32 ST3_US              = 0x03;
                    267:        struct ST3 {
                    268:                bool ft;                                // Fault
                    269:                bool wp;                                // Write Protect
                    270:                bool ry;                                // Ready
                    271:                bool t0;                                // Track 0
                    272:                bool ts;                                // Two Side
                    273:                bool hd;
                    274:                uint8 us;
                    275:        };
                    276: 
                    277:  public:
1.1       root      278:        FDCDevice();
1.1.1.10  root      279:        ~FDCDevice() override;
1.1       root      280: 
1.1.1.8   root      281:        bool Create() override;
1.1.1.9   root      282:        bool Init() override;
1.1.1.7   root      283:        void ResetHard(bool poweron) override;
                    284: 
1.1.1.8   root      285:        // READY 信号が変化したことの通知 (FDD から呼ばれる)
                    286:        void ReadyChanged(int unit, bool is_ready);
                    287: 
                    288:        // 強制レディ (OPM から呼ばれる)
1.1.1.7   root      289:        void SetForceReady(bool force_ready_);
1.1       root      290: 
1.1.1.8   root      291:        // DACK と TC 信号 (DMA から呼ばれる)
                    292:        void AssertDACK(bool tc);
                    293:        void NegateDACK();
                    294: 
1.1.1.2   root      295:  protected:
                    296:        // BusIO インタフェース
                    297:        static const uint32 NPORT = 4;
1.1.1.11  root      298:        busdata ReadPort(uint32 offset);
                    299:        busdata WritePort(uint32 offset, uint32 data);
                    300:        busdata PeekPort(uint32 offset);
                    301:        bool PokePort(uint32 offset, uint32 data);
1.1       root      302: 
                    303:  private:
                    304:        uint32 ReadData();
1.1.1.8   root      305:        void WriteDataReg(uint32);
1.1       root      306:        uint32 ReadDriveStatus();
                    307:        void WriteCmd(uint32);
                    308: 
1.1.1.8   root      309:        uint32 GetDriveStatus() const;
                    310:        void PushDreg(uint8);
1.1.1.11  root      311:        uint32 PopDreg();
1.1.1.8   root      312:        void RequestDataByte();
                    313: 
                    314:        uint8 GetMSR() const;
                    315:        uint8 GetST0() const;
                    316:        uint8 GetST1() const;
                    317:        uint8 GetST2() const;
                    318: 
                    319:        void CommandPhase();
                    320:        void ExecPhase();
                    321:        void ResultPhase();
                    322: 
1.1.1.13! root      323:        void CommandCallback(Event *);
        !           324:        void ResultCallback(Event *);
1.1.1.8   root      325: 
                    326:        void ChangeInterrupt();
                    327: 
                    328:        // シーク終了処理
                    329:        void SeekEnd();
                    330: 
                    331:        // データ転送
                    332:        void XferStart(bool is_write);
1.1.1.13! root      333:        void XferStartCallback(Event *);
        !           334:        void XferDataCallback(Event *);
        !           335:        void XferEndCallback(Event *);
1.1.1.8   root      336: 
                    337:        // FDC コマンド
                    338:        void CmdInvalid();
                    339:        void CmdReadDiagnostic();
                    340:        void CmdSpecify();
                    341:        void CmdSenseDeviceStatus();
                    342:        void CmdWriteData();
                    343:        void CmdReadData();
                    344:        void CmdRecalibrate();
                    345:        void CmdSenseInterruptStatus();
                    346:        void CmdWriteDeletedData();
                    347:        void CmdReadID();
                    348:        void CmdReadDeletedData();
                    349:        void CmdWriteID();
                    350:        void CmdSeek();
                    351:        void CmdVersion();
                    352:        void CmdScanEqual();
                    353:        void CmdScanLowOrEqual();
                    354:        void CmdScanHighOrEqual();
                    355:        void CmdResetStandby();
                    356:        void CmdSetStandby();
                    357:        void CmdSoftwareReset();
                    358: 
                    359:        // 未実装コマンドの共通部
                    360:        void CmdNotImplemented();
                    361: 
                    362:        // ユニット US0,US1 信号線の状態を変える
                    363:        void UnitSelect(uint8);
                    364: 
                    365:        // ドライブセレクト信号線の状態を変える
                    366:        void DriveSelect(uint8 sel);
                    367: 
                    368:        // READY 入力端子
                    369:        bool IsReady() const;
                    370: 
                    371:        // ポーリング
                    372:        void StartPoll();
1.1.1.13! root      373:        void PollEventCallback(Event *);
1.1.1.8   root      374:        bool PollReady(int);
                    375:        bool ExecSeek(int);
                    376: 
                    377:        // モータ停止用
1.1.1.13! root      378:        void MotorEventCallback(Event *);
1.1.1.8   root      379: 
                    380:        DECLARE_MONITOR_CALLBACK(MonitorUpdate);
                    381:        void MonitorReg(TextScreen&,
                    382:                int x, int y, uint8 reg, const char * const *names);
                    383: 
                    384:        // FDC が内部で記憶しているユニットごとの状態。
                    385:        // こちらは US をインデックスとしてアクセスすること。
                    386:        std::array<UnitInfo, MAX_DRIVE> unitinfo {};
                    387: 
                    388:        // 選択されている FDD
                    389:        FDDDevice *fdd {};
                    390: 
                    391:        // ドライブ数
                    392:        int ndrive {};
                    393: 
                    394:        // 接続されているドライブ。
                    395:        // fdd_list[] は配列なので歯抜けをサポート出来るが、今の所そのような
                    396:        // 設定をする方法がない (必要になったら考える)。
                    397:        std::unique_ptr<FDDDevice> fdd_list[MAX_DRIVE] /*{}*/;
                    398:        // 生ポインタを配列と同じ要領で格納したもの。
                    399:        std::vector<FDDDevice *> fdd_vector {};
                    400: 
                    401:        // SPECIFY で設定(初期化)する項目
                    402:        uint8 srt {};
                    403:        uint8 hut {};
                    404:        uint8 hlt {};
                    405:        bool nd {};                                     // Non DMA
                    406:        bool initialized {};            // SPECIFY で初期化されたかどうか
                    407: 
                    408:        // コマンド
                    409:        const FDCCmd *cmd {};           // 現在選択中のコマンド
                    410:        static const std::vector<FDCCmd> cmd_list;
                    411: 
                    412:        // FDC 内部状態
                    413:        fdc_phase_t phase {};           // 動作フェーズ
                    414:        FDCCmdBuf cmdbuf {};
                    415:        FDCResBuf resbuf {};
                    416:        FixedQueue<uint8, 1> dreg {};   // 内部データレジスタ
                    417: 
                    418:        bool hd {};                                     // Head address
1.1.1.10  root      419:        uint8 us {};                            // Unit Select (US0,US1) 出力信号
1.1.1.8   root      420:        bool tc {};                                     // TC 入力信号
                    421:        bool dack {};                           // DACK 入力信号
                    422: 
                    423:        bool mt {};                                     // Multi Track
                    424:        bool mf {};                                     // MFM
                    425:        bool sk {};                                     // Skip
                    426: 
                    427:        bool xfer_start {};
                    428:        bool xfer_enable {};
                    429:        bool xfer_write {};
                    430:        uint xfer_remain {};
                    431:        uint sect_remain {};
                    432:        int index_detected {};
                    433: 
1.1.1.11  root      434:        uint seek_srt {};                       // SEEK ステップレートタイマカウンタ
1.1.1.8   root      435: 
                    436:        MSR msr {};
                    437:        ST0 st0 {};
                    438:        ST1 st1 {};
                    439:        ST2 st2 {};
                    440: 
                    441:        // I/O コントローラ部
                    442:        uint8 drivectrl {};                     // ドライブコントロールレジスタ
                    443:        bool motor_on_bit {};           // アクセスドライブ選択レジスタの MOTOR_ON
                    444: 
                    445:        // OPM
                    446:        bool force_ready {};            // 強制レディ
                    447: 
1.1.1.9   root      448:        DMACDevice *dmac {};
                    449:        PEDECDevice *pedec {};
                    450: 
1.1.1.13! root      451:        Event *phase_event {};          // 状態遷移用
        !           452:        Event *poll_event {};           // ポーリング用
        !           453:        Event *motor_event {};          // モータ停止用
1.1       root      454: 
1.1.1.12  root      455:        Monitor *monitor {};
1.1       root      456: };
1.1.1.4   root      457: 
1.1.1.9   root      458: static inline FDCDevice *GetFDCDevice() {
                    459:        return Object::GetObject<FDCDevice>(OBJ_FDC);
                    460: }

unix.superglobalmegacorp.com

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