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

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 "monitor.h"
                     17: #include <array>
1.1       root       18: 
1.1.1.9   root       19: class DMACDevice;
1.1.1.8   root       20: class FDDDevice;
1.1.1.9   root       21: class PEDECDevice;
1.1.1.8   root       22: 
                     23: struct FDCCmdBuf
                     24: {
                     25:        union {
                     26:                uint8 buf[10];
1.1       root       27: 
1.1.1.8   root       28:                struct {
                     29:                        uint8 code;
                     30:                        union {
                     31:                                // READ DATA, READ DELETED DATA
                     32:                                // WRITE DATA, WRITE DELETED DATA
                     33:                                // READ DIAGNOSTIC
                     34:                                struct {
                     35:                                        uint8 hd_us;
                     36:                                        uint8 c;
                     37:                                        uint8 h;
                     38:                                        uint8 r;
                     39:                                        uint8 n;
                     40:                                        uint8 eot;
                     41:                                        uint8 gsl;
                     42:                                        uint8 dtl;
                     43:                                } data;
                     44: 
                     45:                                // SCAN EQUAL, SCAN LOW OR EQUAL, SCAN HIGH OR EQUAL
                     46:                                struct {
                     47:                                        uint8 hd_us;
                     48:                                        uint8 c;
                     49:                                        uint8 h;
                     50:                                        uint8 r;
                     51:                                        uint8 n;
                     52:                                        uint8 eot;
                     53:                                        uint8 gsl;
                     54:                                        uint8 dtl;
                     55:                                        uint8 stp;
                     56:                                } scan;
                     57: 
                     58:                                struct {
                     59:                                        uint8 us;
                     60:                                        uint8 ncn;
                     61:                                } seek;
                     62: 
                     63:                                struct {
                     64:                                        uint8 us;
                     65:                                } recalibrate;
                     66: 
                     67:                                struct {
                     68:                                        uint8 srt_hut;
                     69:                                        uint8 hlt_nd;
                     70:                                } specify;
                     71: 
                     72:                                // READ ID
                     73:                                struct {
                     74:                                        uint8 hd_us;
                     75:                                } read_id, sense_device_status;
                     76: 
                     77:                                struct {
                     78:                                        uint8 hd_us;
                     79:                                        uint8 n;
                     80:                                        uint8 sc;
                     81:                                        uint8 gpl;
                     82:                                        uint8 d;
                     83:                                } write_id;
                     84:                        };
                     85:                };
                     86:        };
                     87: 
                     88:        int len;
                     89: 
                     90:        void Clear() {
                     91:                len = 0;
                     92:        }
1.1       root       93: };
                     94: 
1.1.1.8   root       95: struct FDCResBuf
                     96: {
                     97:        union {
                     98:                uint8 buf[7];
                     99: 
                    100:                struct {
                    101:                        uint8 st0;
                    102:                        uint8 st1;
                    103:                        uint8 st2;
                    104:                        uint8 c;
                    105:                        uint8 h;
                    106:                        uint8 r;
                    107:                        uint8 n;
                    108:                } data;
                    109: 
                    110:                struct {
                    111:                        uint8 st0;
                    112:                        uint8 pcn;
                    113:                } interrupt_status;
                    114: 
                    115:                struct {
                    116:                        uint8 st3;
                    117:                } device_status;
                    118: 
                    119:                struct {
                    120:                        uint8 st0;
                    121:                } invalid;
                    122:        };
                    123: 
                    124:        int len {};
                    125:        int pos {};
                    126: 
                    127:        void Clear() {
                    128:                len = 0;
                    129:                pos = 0;
                    130:        }
                    131: 
                    132:        uint8 Take() {
                    133:                assert(pos < len);
                    134:                return buf[pos++];
                    135:        }
                    136: 
                    137:        uint8 Peek() {
                    138:                assert(pos < len);
                    139:                return buf[pos];
                    140:        }
1.1       root      141: };
                    142: 
1.1.1.8   root      143: 
1.1.1.6   root      144: class FDCDevice : public IODevice
1.1       root      145: {
1.1.1.2   root      146:        using inherited = IODevice;
1.1       root      147:        static const int baseaddr = 0xe94000;
                    148: 
                    149:  public:
1.1.1.8   root      150:        // サポートしているドライブ数上限
                    151:        static const int MAX_DRIVE = 4;
                    152: 
                    153:  private:
                    154:        // コマンド定義
                    155:        struct FDCCmd
                    156:        {
                    157:                uint8 code;
                    158:                uint8 mask;
                    159:                int cmdlen;
                    160:                void (FDCDevice::*func)();
                    161:                const char *name;
                    162:        };
                    163: 
                    164:        // ユニットのポーリング時の動作状態
                    165:        enum class UnitState {
                    166:                Idle,
                    167:                Seek,
                    168:                Recalibrate,
                    169:        };
                    170: 
                    171:        // ユニットの状態
                    172:        struct UnitInfo {
                    173:                // FDC が記憶しているヘッドがいることになっているシリンダ番号。
                    174:                // FDD の実際のヘッド位置とは必ずしも一致しない。
                    175:                int pcn;
                    176:                // シーク先のシリンダ番号
                    177:                int ncn;
                    178:                // ユニットごとの、前回調べた READY
                    179:                bool ready;
                    180:                // ポーリング時動作状態
                    181:                UnitState state;
                    182: 
                    183:                uint64 ready_time;      // READY になった時刻
                    184:        };
                    185: 
                    186:        // FDC の動作フェーズ
                    187:        enum fdc_phase_t {
                    188:                PHASE_COMMAND,
                    189:                PHASE_EXEC,
                    190:                PHASE_RESULT,
                    191:        };
                    192: 
                    193:        // マスタステータスレジスタ
                    194:        static const uint32 MSR_RQM             = 0x80;
                    195:        static const uint32 MSR_DIO             = 0x40;
                    196:        static const uint32 MSR_NDM             = 0x20;
                    197:        static const uint32 MSR_CB              = 0x10;
                    198:        static const bool DIOtoFDC              = false;
                    199:        static const bool DIOtoHost             = true;
                    200:        struct MSR {
                    201:                bool rqm;                               // Request For Master
                    202:                bool dio;                               // Data Input/Output
                    203:                bool ndm;                               // Non-DMA Mode
                    204:                bool cb;                                // FDC Busy
                    205:                std::array<bool, 4> db; // FDn Busy (注:seek中/割り込み保留中)
                    206:        };
                    207: 
                    208:        // ST0 レジスタ
                    209:        static const uint32 ST0_IC_NT   = 0x00;
                    210:        static const uint32 ST0_IC_AT   = 0x40;
                    211:        static const uint32 ST0_IC_IC   = 0x80;
                    212:        static const uint32 ST0_IC_AI   = 0xc0;
                    213:        static const uint32 ST0_SE              = 0x20;
                    214:        static const uint32 ST0_EC              = 0x10;
                    215:        static const uint32 ST0_NR              = 0x08;
                    216:        static const uint32 ST0_HD              = 0x04;
                    217:        static const uint32 ST0_US              = 0x03;
                    218:        struct ST0 {
                    219:                uint8 ic;                               // Interrupt Code
                    220:                bool se;                                // Seek End
                    221:                bool ec;                                // Equipment Check
                    222:                bool nr;                                // Not Ready
                    223:                bool hd;
                    224:                uint8 us;
                    225:        };
                    226: 
                    227:        // ST1 レジスタ
                    228:        static const uint32 ST1_EN              = 0x80;
                    229:        static const uint32 ST1_DE              = 0x20;
                    230:        static const uint32 ST1_OR              = 0x10;
                    231:        static const uint32 ST1_ND              = 0x04;
                    232:        static const uint32 ST1_NW              = 0x02;
                    233:        static const uint32 ST1_MA              = 0x01;
                    234:        struct ST1 {
                    235:                bool en;                                // End of Cylinder
                    236:                bool de;                                // Data Error
                    237:                bool overrun;                   // Over Run
                    238:                bool nd;                                // No Data
                    239:                bool nw;                                // Not Writable
                    240:                bool ma;                                // Missing Address Mark
                    241:        };
                    242: 
                    243:        // ST2 レジスタ
                    244:        static const uint32 ST2_CM              = 0x40;
                    245:        static const uint32 ST2_DD              = 0x20;
                    246:        static const uint32 ST2_NC              = 0x10;
                    247:        static const uint32 ST2_SH              = 0x08;
                    248:        static const uint32 ST2_SN              = 0x04;
                    249:        static const uint32 ST2_BC              = 0x02;
                    250:        static const uint32 ST2_MD              = 0x01;
                    251:        struct ST2 {
                    252:                bool cm;                                // Control Mark
                    253:                bool dd;                                // Data Error In Data Field
                    254:                bool nc;                                // No Cylinder
                    255:                bool sh;                                // Scan Equal Hit
                    256:                bool sn;                                // Scan Not Satisfied
                    257:                bool bc;                                // Bad Cylinder
                    258:                bool md;                                // Missing Addrss Mark in Data Field
                    259:        };
                    260: 
                    261:        // ST3 レジスタ
                    262:        static const uint32 ST3_FT              = 0x80;
                    263:        static const uint32 ST3_WP              = 0x40;
                    264:        static const uint32 ST3_RY              = 0x20;
                    265:        static const uint32 ST3_T0              = 0x10;
                    266:        static const uint32 ST3_TS              = 0x08;
                    267:        static const uint32 ST3_HD              = 0x04;
                    268:        static const uint32 ST3_US              = 0x03;
                    269:        struct ST3 {
                    270:                bool ft;                                // Fault
                    271:                bool wp;                                // Write Protect
                    272:                bool ry;                                // Ready
                    273:                bool t0;                                // Track 0
                    274:                bool ts;                                // Two Side
                    275:                bool hd;
                    276:                uint8 us;
                    277:        };
                    278: 
                    279:  public:
1.1       root      280:        FDCDevice();
1.1.1.10! root      281:        ~FDCDevice() override;
1.1       root      282: 
1.1.1.8   root      283:        bool Create() override;
1.1.1.9   root      284:        bool Init() override;
1.1.1.7   root      285:        void ResetHard(bool poweron) override;
                    286: 
1.1.1.8   root      287:        // READY 信号が変化したことの通知 (FDD から呼ばれる)
                    288:        void ReadyChanged(int unit, bool is_ready);
                    289: 
                    290:        // 強制レディ (OPM から呼ばれる)
1.1.1.7   root      291:        void SetForceReady(bool force_ready_);
1.1       root      292: 
1.1.1.8   root      293:        // DACK と TC 信号 (DMA から呼ばれる)
                    294:        void AssertDACK(bool tc);
                    295:        void NegateDACK();
                    296: 
1.1.1.2   root      297:  protected:
                    298:        // BusIO インタフェース
                    299:        static const uint32 NPORT = 4;
1.1.1.10! root      300:        busdata Read(uint32 offset);
        !           301:        busdata Write(uint32 offset, uint32 data);
        !           302:        busdata Peek(uint32 offset);
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);
                    312:        int PopDreg();
                    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: 
                    435:        int seek_srt {};                        // SEEK ステップレートタイマカウンタ
                    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.8   root      456:        Monitor monitor { this };
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.