--- nono/vm/dmac.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/dmac.h 2026/04/29 17:04:58 1.1.1.9 @@ -1,41 +1,150 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // #pragma once #include "device.h" +#include "monitor.h" +#include "scheduler.h" +#include struct DMAC { - static const int CSR = 0x00; // .B - static const int CER = 0x01; // .B - static const int DCR = 0x04; // .B - static const int OCR = 0x05; // .B - static const int SCR = 0x06; // .B - static const int CCR = 0x07; // .B - static const int MTC = 0x0a; // .W - static const int MAR = 0x0c; // .L - static const int DAR = 0x14; // .L - static const int BTC = 0x1a; // .W - static const int BAR = 0x1c; // .L - static const int NIV = 0x25; // .B - static const int EIV = 0x27; // .B - static const int MFC = 0x29; // .B - static const int CPR = 0x2d; // .B - static const int DFC = 0x31; // .B - static const int BFC = 0x39; // .B - static const int GCR = 0x3f; // .B (ch#3のみ) + static const uint32 CSR = 0x00; // .B + static const uint32 CER = 0x01; // .B + static const uint32 DCR = 0x04; // .B + static const uint32 OCR = 0x05; // .B + static const uint32 SCR = 0x06; // .B + static const uint32 CCR = 0x07; // .B + static const uint32 MTC = 0x0a; // .W + static const uint32 MAR = 0x0c; // .L + static const uint32 DAR = 0x14; // .L + static const uint32 BTC = 0x1a; // .W + static const uint32 BAR = 0x1c; // .L + static const uint32 NIV = 0x25; // .B + static const uint32 EIV = 0x27; // .B + static const uint32 MFC = 0x29; // .B + static const uint32 CPR = 0x2d; // .B + static const uint32 DFC = 0x31; // .B + static const uint32 BFC = 0x39; // .B + static const uint32 GCR = 0x3f; // .B (ch#3のみ) + + // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // CSR | COC | BTC | NDT | ERR | ACT | --- | PCT | PCS | + // + static const uint32 CSR_COC = 0x80; // Channel Operation Complete + static const uint32 CSR_BTC = 0x40; // Block Transfer Complete + static const uint32 CSR_NDT = 0x20; // Normal Device Termination + static const uint32 CSR_ERR = 0x10; // Error Bit + static const uint32 CSR_ACT = 0x08; // Channel Active + static const uint32 CSR_PCT = 0x02; // PCL Transition + static const uint32 CSR_PCS = 0x01; // PCL Input Line State + + // CER + static const uint32 CER_NO_ERROR = 0x00; // No Error + static const uint32 CER_CONFIG = 0x01; // Configuration Error + static const uint32 CER_OPER_TIMING = 0x02; // Operation Timing Error + static const uint32 CER_ADDR_MAR = 0x05; // Address error in MAR + static const uint32 CER_ADDR_DAR = 0x06; // Address error in DAR + static const uint32 CER_ADDR_BAR = 0x07; // Address error in BAR + static const uint32 CER_BUS_MAR = 0x09; // Bus error in MAR + static const uint32 CER_BUS_DAR = 0x0a; // Bus error in DAR + static const uint32 CER_BUS_BAR = 0x0b; // Bus error in BAR + static const uint32 CER_COUNT_MTC = 0x0d; // Count error in MTC + static const uint32 CER_COUNT_BTC = 0x0f; // Count error in BTC + static const uint32 CER_EXT_ABORT = 0x10; // External Abort + static const uint32 CER_SOFT_ABORT = 0x11; // Software Abort + + // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // DCR | XRM | DTYP | DPS | --- | PCL | + static const uint32 DCR_XRM_BURST = 0; // Burst Transfer + static const uint32 DCR_XRM_CYCLE_WO_HOLD = 2; // Cycle Steal without Hold + static const uint32 DCR_XRM_CYCLE_WITH_HOLD = 3;// Cycle Steal with Hold + static const uint32 DCR_DTYP_68000 = 0; // 68000 devices + static const uint32 DCR_DTYP_6800 = 1; // 6800 devices + static const uint32 DCR_DTYP_ACK = 2; // Devices with ACK + static const uint32 DCR_DTYP_ACK_REDY = 3; // Devices with ACK+READY + static const uint32 DCR_DPS_8BIT = 0; // 8bit port + static const uint32 DCR_DPS_16BIT = 1; // 16bit port + static const uint32 DCR_PCL_STATUS = 0; // Status Input + static const uint32 DCR_PCL_STATUS_INTR = 1; // Status Input with Interrupt + static const uint32 DCR_PCL_PULSE = 2; // Start Pulse + static const uint32 DCR_PCL_ABORT = 3; // Abort Input + + // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // OCR | DIR | --- | SIZE | CHAIN | REQG | + // + static const uint32 OCR_DIR_MtoD = 0; // Memory to Device + static const uint32 OCR_DIR_DtoM = 1; // Device to Memory + static const uint32 OCR_SIZE_8BIT = 0; // 8bit + static const uint32 OCR_SIZE_16BIT = 1; // 16bit + static const uint32 OCR_SIZE_32BIT = 2; // 32bit + static const uint32 OCR_SIZE_8BIT_UP = 3; // 8bit (Non-Pack Operation) + static const uint32 OCR_CHAIN_NOCHAIN = 0; // Chain operation is disabled + static const uint32 OCR_CHAIN_ARRAY = 2; // Array Chaining + static const uint32 OCR_CHAIN_LINK = 3; // Linked Array Chaining + static const uint32 OCR_REQG_AUTO_LIM = 0; // Auto Request (Limited) + static const uint32 OCR_REQG_AUTO_MAX = 1; // AUto Request (Max) + static const uint32 OCR_REQG_EXTERNAL = 2; // External Request + static const uint32 OCR_REQG_AUTOFIRST = 3; // Auto first then ext. + + // | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 | + // SCR | --- --- --- --- | MAC | DAC | + static const uint32 SCR_NO_COUNT = 0; // Does not count + static const uint32 SCR_COUNT_UP = 1; // Count up + static const uint32 SCR_COUNT_DOWN = 2; // Count down + + // CCR + static const uint32 CCR_STR = 0x80; // Start Operation + static const uint32 CCR_CNT = 0x40; // Continue Operation + static const uint32 CCR_HLT = 0x20; // Halt Operation + static const uint32 CCR_SAB = 0x10; // Software Abort + static const uint32 CCR_INT = 0x08; // Interrupt Enable // 各チャンネル - struct channel { - uint8 csr; + struct Channel { + // 二次変数など + int ch; // チャンネル番号 + const char *desc; // チャンネルの用途(モニタ表示用) + DMACDevice *parent; + + // レジスタ + + // CSR + uint8 csr; // COC,BTC,NDT,ERR を保持 + bool active; // ACT + bool pcl; // PCL の状態 (High が true) + bool prev_pcl; // 前回の PCL の状態 (High が true) + bool IsINTR() const { // CSR の割り込み要因が立っていれば true + // XXX PCT は未対応 + return (csr & (CSR_COC | CSR_BTC | CSR_NDT | CSR_ERR)); + } + uint8 cer; uint8 dcr; + uint32 GetXRM() const { return (dcr >> 6); } + uint32 GetDTYP() const { return (dcr >> 4) & 3; } + uint32 GetDPS() const { return (dcr >> 3) & 1; } + uint32 GetPCL() const { return (dcr & 3); } + uint8 ocr; + uint32 GetDIR() const { return (ocr >> 7); } + uint32 GetSIZE() const { return (ocr >> 4) & 3; } + uint32 GetCHAIN() const { return (ocr >> 2) & 3; } + uint32 GetREQG() const { return (ocr & 3); } + + // 転送種別 (DPS と SIZE から決まる) + uint32 xfertype; + uint8 scr; + uint32 GetMAC() const { return (scr >> 2) & 3; } + uint32 GetDAC() const { return (scr & 3); } + uint8 ccr; + uint16 mtc; uint32 mar; uint32 dar; @@ -47,30 +156,62 @@ struct DMAC uint8 cpr; uint8 dfc; uint8 bfc; + + uint8 PeekCSR() const; + void WriteCSR(uint32 data); + void WriteCCR(uint32 data); + + // 転送開始 + void StartTransfer(); } chan[4]; // 全体 uint8 gcr; }; -class DMACDevice - : public IODevice +class DMACDevice : public IODevice { - typedef IODevice inherited; + using inherited = IODevice; static const int baseaddr = 0xe84000; public: DMACDevice(); - virtual ~DMACDevice(); + virtual ~DMACDevice() override; + + void ResetHard() override; - virtual uint64 Read8(uint32 addr); - virtual uint64 Write8(uint32 addr, uint32 data); - virtual uint64 Peek8(uint32 addr); + // 転送 + void StartTransfer(DMAC::Channel *chan); + void AbortTransfer(DMAC::Channel *chan); + void Transfer(Event& ev); + int64 TransferM8toD8(DMAC::Channel *chan); + int64 TransferD8toM8(DMAC::Channel *chan); + + // 割り込みアクノリッジ + int InterruptAcknowledge(); + + protected: + // BusIO インタフェース + static const uint NPORT = 256; + uint64 Read(uint32 offset); + uint64 Write(uint32 offset, uint32 data); + uint64 Peek(uint32 offset); private: - void write_csr(int ch, uint32 data); - void write_ccr(int ch, uint32 data); + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + void MonitorReg4(TextScreen&, + int x, int y, uint32 reg, const char * const *names); + + // 割り込み信号線の状態を変更 + void ChangeInterrupt(); struct DMAC dmac {}; + std::array event {}; + + Monitor monitor { this }; + + static const char * const errnames[]; }; + +extern std::unique_ptr gDMAC;