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

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.8 ! root       19: class FDDDevice;
        !            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: 
        !            86:        int len;
        !            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       root      145:        static const int baseaddr = 0xe94000;
                    146: 
                    147:  public:
1.1.1.8 ! root      148:        // サポートしているドライブ数上限
        !           149:        static const int MAX_DRIVE = 4;
        !           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.4   root      279:        virtual ~FDCDevice() override;
1.1       root      280: 
1.1.1.8 ! root      281:        bool Create() override;
1.1.1.7   root      282:        void ResetHard(bool poweron) override;
                    283: 
1.1.1.8 ! root      284:        // READY 信号が変化したことの通知 (FDD から呼ばれる)
        !           285:        void ReadyChanged(int unit, bool is_ready);
        !           286: 
        !           287:        // 強制レディ (OPM から呼ばれる)
1.1.1.7   root      288:        void SetForceReady(bool force_ready_);
1.1       root      289: 
1.1.1.8 ! root      290:        // DACK と TC 信号 (DMA から呼ばれる)
        !           291:        void AssertDACK(bool tc);
        !           292:        void NegateDACK();
        !           293: 
        !           294:        // 接続されている FDD のリストを取得 (UI 用)
        !           295:        const std::vector<FDDDevice *>& GetFDD() const { return fdd_vector; }
        !           296: 
1.1.1.2   root      297:  protected:
                    298:        // BusIO インタフェース
                    299:        static const uint32 NPORT = 4;
1.1.1.5   root      300:        uint64 Read(uint32 offset);
                    301:        uint64 Write(uint32 offset, uint32 data);
                    302:        uint64 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
        !           420:        uint8 us {};                            // Unit Select
        !           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: 
        !           449:        Event phase_event { this };     // 状態遷移用
        !           450:        Event poll_event { this };      // ポーリング用
        !           451:        Event motor_event { this };     // モータ停止用
1.1       root      452: 
1.1.1.8 ! root      453:        Monitor monitor { this };
1.1       root      454: };
1.1.1.4   root      455: 
1.1.1.7   root      456: extern FDCDevice *gFDC;

unix.superglobalmegacorp.com

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