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

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

unix.superglobalmegacorp.com

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