From 6040bca13ac2c3619eb318e01b4db2ff515b2825 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sat, 8 Oct 2022 10:39:18 +0200 Subject: [PATCH] refactor ram dsk driver a bit more, some work toward multiplexed interrupt --- .../DeclROM/NuBusFPGADrvr_OpenClose.c | 22 ++++-- .../DeclROM/NuBusFPGARAMDskDrvr.h | 20 ++++- .../DeclROM/NuBusFPGARAMDskDrvr_Ctrl.c | 26 +++++++ .../DeclROM/NuBusFPGARAMDskDrvr_OpenClose.c | 51 ++++++++++++- .../DeclROM/NuBusFPGARAMDskDrvr_Prime.c | 73 ++++++++----------- nubus-to-ztex-gateware/goblin_fb.py | 1 + nubus-to-ztex-gateware/nubus_to_fpga_soc.py | 12 ++- 7 files changed, 148 insertions(+), 57 deletions(-) diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c index e0f21eb..f33e3fe 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGADrvr_OpenClose.c @@ -14,14 +14,20 @@ typedef void(*vblproto)(short); */ #pragma parameter __D0 fbIrq(__A1) __attribute__ ((section (".text.fbdriver"))) short fbIrq(const long sqParameter) { - /* AuxDCEPtr dce = (AuxDCEPtr)sqParameter; */ - /* NuBusFPGADriverGlobalsHdl dStoreHdl = (NuBusFPGADriverGlobalsHdl)dce->dCtlStorage; */ - /* NuBusFPGADriverGlobalsPtr dStore = *dStoreHdl; */ - vblproto myVbl = *(vblproto**)0x0d28; - /* write_reg(dce, GOBOFB_INTR_CLEAR, 0); */ - *((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)) = 0; - myVbl((sqParameter>>24)&0xf); // cleaner to use dStore->slot ? but require more code... - return 1; + register unsigned long p_D1 asm("d1"), p_D2 asm("d2"); + unsigned int irq; + short ret; + asm volatile("" : "+d" (p_D1), "+d" (p_D2)); + ret = 0; + irq = (*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR))); + if (irq) { + vblproto myVbl = *(vblproto**)0x0d28; + *((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)) = 0; + myVbl((sqParameter>>24)&0xf); // cleaner to use dStore->slot ? but require more code... + ret = 1; + } + asm volatile("" : : "d" (p_D1), "d" (p_D2)); + return ret; } #pragma parameter __D0 cNuBusFPGAOpen(__A0, __A1) diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h index 70de270..4cd2dd3 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h @@ -12,6 +12,17 @@ #include "NuBusFPGADrvr.h" +#ifdef ENABLE_DMA +typedef struct { + unsigned long blk_todo; + unsigned long blk_done; + unsigned long blk_offset; + unsigned long blk_doing; + void *ioBuffer; + int write; +} ram_dsk_op; +#endif + struct RAMDrvContext { DrvSts2 drvsts; char slot; @@ -21,6 +32,9 @@ struct RAMDrvContext { unsigned int dma_blk_size_shift; unsigned long dma_blk_base; unsigned long dma_mem_size; + SlotIntQElement *siqel; + ram_dsk_op op; + char irqen; #endif }; @@ -32,7 +46,7 @@ struct RAMDrvContext { #define DMA_BLK_SIZE (0x00100800 | 0x00) #define DMA_BLK_BASE (0x00100800 | 0x04) #define DMA_MEM_SIZE (0x00100800 | 0x08) -//#define DMA_IRQ_CTL (0x00a00800 | 0x0c) // IRQ not connected +#define DMA_IRQ_CTL (0x00100800 | 0x0c) #define DMA_BLK_ADDR (0x00100800 | 0x10) #define DMA_DMA_ADDR (0x00100800 | 0x14) #define DMA_BLK_CNT (0x00100800 | 0x18) @@ -40,8 +54,12 @@ struct RAMDrvContext { #define DMA_STATUS (0x00100800 | 0x2c) #define DMA_STATUS_CHECK_BITS (0x01F) +#define DMA_IRQSTATUS (0x00100800 | 0x34) + #endif + /* ctrl */ +OSErr changeRAMdskIRQ(AuxDCEPtr dce, char en, OSErr err) __attribute__ ((section (".text.dskdriver"))); OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver"))); /* open, close */ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver"))); diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Ctrl.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Ctrl.c index 53a0599..804eb6a 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Ctrl.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Ctrl.c @@ -1,5 +1,31 @@ #include "NuBusFPGARAMDskDrvr.h" + + +OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) { + struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage; + + if (en != ctx->irqen) { + /* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0005); */ + /* write_reg(dce, GOBOFB_DEBUG, en); */ + + if (en) { + if (SIntInstall(ctx->siqel, dce->dCtlSlot)) { + return err; + } + } else { + if (SIntRemove(ctx->siqel, dce->dCtlSlot)) { + return err; + } + } + + write_reg(dce, DMA_IRQ_CTL, en ? 0x3 : 0x2); // 0x2: always clear pending interrupt + ctx->irqen = en; + } + return noErr; +} + + #pragma parameter __D0 cNuBusFPGARAMDskCtl(__A0, __A1) OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) { diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_OpenClose.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_OpenClose.c index d315a80..c2deb56 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_OpenClose.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_OpenClose.c @@ -14,6 +14,32 @@ __attribute__ ((section (".text.dskdriver"))) static inline int dupAddDrive(unsi return num; // should cost nothing, num is already in D0 } + +/* see the comment for the FB irq */ +#pragma parameter __D0 dskIrq(__A1) +__attribute__ ((section (".text.dskdriver"))) short dskIrq(const long sqParameter) { + register unsigned long p_D1 asm("d1"), p_D2 asm("d2"); + AuxDCEPtr dce; + struct RAMDrvContext *ctx; + unsigned int irq; + short ret; + asm volatile("" : "+d" (p_D1), "+d" (p_D2)); + dce = (AuxDCEPtr)sqParameter; + ctx = *(struct RAMDrvContext**)dce->dCtlStorage; + ret = 0; + irq = revb(*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+DMA_IRQSTATUS))); + *((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_DEBUG)) = 0x11111111; + *((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_DEBUG)) = irq; + if (irq & 1) { + unsigned int irqctrl = revb(*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+DMA_IRQ_CTL))); + irqctrl |= 0x2; // irq clear + *((volatile unsigned int*)(sqParameter+GOBOFB_BASE+DMA_IRQ_CTL)) = revb(irqctrl); + ret = 1; + } + asm volatile("" : : "d" (p_D1), "d" (p_D2)); + return ret; +} + #include #pragma parameter __D0 cNuBusFPGARAMDskOpen(__A0, __A1) @@ -123,6 +149,26 @@ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) /* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_shift); */ /* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_base); */ /* write_reg(dce, GOBOFB_DEBUG, ctx->dma_mem_size); */ + + if (1) { + SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement)); + + if (siqel == NULL) { + return openErr; + } + + // disable IRQ for now + write_reg(dce, DMA_IRQ_CTL, 0x2); // 0x1 would enable irq, 0x2 is auto-clear so we make sure there's no spurious IRQ pending + + siqel->sqType = sIQType; + siqel->sqPrio = 7; + siqel->sqAddr = dskIrq; + siqel->sqParm = (long)dce; + ctx->siqel = siqel; + ctx->irqen = 0; + write_reg(dce, GOBOFB_DEBUG, siqel); + write_reg(dce, GOBOFB_DEBUG, ctx); + } #endif // auto-mount @@ -131,8 +177,6 @@ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) pbr.volumeParam.ioVRefNum = dsptr->dQDrive; ret = PBMountVol(&pbr); } - - } SwapMMUMode ( &busMode ); @@ -145,13 +189,14 @@ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) OSErr cNuBusFPGARAMDskClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) { OSErr ret = noErr; - //RAMDrvContext *ctx = *(RAMDrvContext**)dce->dCtlStorage; + struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage; /* dce->dCtlDevBase = 0xfc000000; */ /* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0001); */ if (dce->dCtlStorage) { + //DisposePtr((Ptr)ctx->siqel); /* HUnlock(dce->dCtlStorage); */ /* not needed before DisposeHandle */ DisposeHandle(dce->dCtlStorage); dce->dCtlStorage = NULL; diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c index ea12cda..14ad501 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c @@ -9,36 +9,27 @@ __attribute__ ((section (".text.dskdriver"))) static inline void waitSome(unsign } } -typedef struct { - unsigned long blk_todo; - unsigned long blk_done; - unsigned long blk_offset; - unsigned long blk_doing; - void *ioBuffer; - int write; -} ram_dsk_op; - -__attribute__ ((section (".text.dskdriver"))) static void startOneOp(const struct RAMDrvContext *ctx, const AuxDCEPtr dce, ram_dsk_op *op) { - if (op->blk_todo > 0) { - op->blk_doing = op->blk_todo; - if (op->blk_doing > 65535) { // fixme: read HW max - op->blk_doing = 32768; // nice Po2 +__attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMDrvContext *ctx, const AuxDCEPtr dce) { + if (ctx->op.blk_todo > 0) { + ctx->op.blk_doing = ctx->op.blk_todo; + if (ctx->op.blk_doing > 65535) { // fixme: read HW max + ctx->op.blk_doing = 32768; // nice Po2 } - write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + op->blk_offset)); - write_reg(dce, DMA_DMA_ADDR, revb(op->ioBuffer + (op->blk_done << ctx->dma_blk_size_shift))); - write_reg(dce, DMA_BLK_CNT, revb((op->write ? 0x80000000ul : 0x00000000ul) | op->blk_doing)); - op->blk_done += op->blk_doing; - op->blk_todo -= op->blk_doing; - op->blk_offset += op->blk_doing; + write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + ctx->op.blk_offset)); + write_reg(dce, DMA_DMA_ADDR, revb(ctx->op.ioBuffer + (ctx->op.blk_done << ctx->dma_blk_size_shift))); + write_reg(dce, DMA_BLK_CNT, revb((ctx->op.write ? 0x80000000ul : 0x00000000ul) | ctx->op.blk_doing)); + ctx->op.blk_done += ctx->op.blk_doing; + ctx->op.blk_todo -= ctx->op.blk_doing; + ctx->op.blk_offset += ctx->op.blk_doing; } } -__attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(const struct RAMDrvContext *ctx, const AuxDCEPtr dce, ram_dsk_op *op) { +__attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(struct RAMDrvContext *ctx, const AuxDCEPtr dce) { unsigned long count, max_count, delay; unsigned long blk_cnt, status; OSErr ret = noErr; - max_count = 32 * op->blk_doing; - delay = (op->blk_doing >> 4); + max_count = 32 * ctx->op.blk_doing; + delay = (ctx->op.blk_doing >> 4); if (delay > 65536) delay = 65536; waitSome(delay); @@ -54,7 +45,7 @@ __attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(const struc if (status) status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS; } if (blk_cnt || status) { - ret = op->write ? writErr : readErr; + ret = ctx->op.write ? writErr : readErr; } return ret; } @@ -103,19 +94,18 @@ OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) if ((((unsigned long)pb->ioBuffer & ctx->dma_blk_size_mask) == 0) && (((unsigned long)pb->ioReqCount & ctx->dma_blk_size_mask) == 0) && (((unsigned long)abs_offset & ctx->dma_blk_size_mask) == 0)) { - ram_dsk_op op; unsigned long blk_cnt, status; blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF; status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS; if ((blk_cnt == 0) && (status == 0)) { - op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift; - op.blk_done = 0; - op.blk_offset = abs_offset >> ctx->dma_blk_size_shift; - op.ioBuffer = pb->ioBuffer; - op.write = 0; - while (op.blk_todo > 0) { - startOneOp(ctx, dce, &op); - ret = waitForHW(ctx, dce, &op); + ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift; + ctx->op.blk_done = 0; + ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift; + ctx->op.ioBuffer = pb->ioBuffer; + ctx->op.write = 0; + while (ctx->op.blk_todo > 0) { + startOneOp(ctx, dce); + ret = waitForHW(ctx, dce); if (ret != noErr) goto done; } @@ -141,19 +131,18 @@ OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) if ((((unsigned long)pb->ioBuffer & ctx->dma_blk_size_mask) == 0) && (((unsigned long)pb->ioReqCount & ctx->dma_blk_size_mask) == 0) && (((unsigned long)abs_offset & ctx->dma_blk_size_mask) == 0)) { - ram_dsk_op op; unsigned long blk_cnt, status; blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF; status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS; if ((blk_cnt == 0) && (status == 0)) { - op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift; - op.blk_done = 0; - op.blk_offset = abs_offset >> ctx->dma_blk_size_shift; - op.ioBuffer = pb->ioBuffer; - op.write = 1; - while (op.blk_todo > 0) { - startOneOp(ctx, dce, &op); - ret = waitForHW(ctx, dce, &op); + ctx->op.blk_todo = pb->ioReqCount >> ctx->dma_blk_size_shift; + ctx->op.blk_done = 0; + ctx->op.blk_offset = abs_offset >> ctx->dma_blk_size_shift; + ctx->op.ioBuffer = pb->ioBuffer; + ctx->op.write = 1; + while (ctx->op.blk_todo > 0) { + startOneOp(ctx, dce); + ret = waitForHW(ctx, dce); if (ret != noErr) goto done; } diff --git a/nubus-to-ztex-gateware/goblin_fb.py b/nubus-to-ztex-gateware/goblin_fb.py index 75dd60b..e21c259 100644 --- a/nubus-to-ztex-gateware/goblin_fb.py +++ b/nubus-to-ztex-gateware/goblin_fb.py @@ -557,6 +557,7 @@ class goblin(Module, AutoCSR): # bt_addr 0x0: [ NextValue(bus.dat_r[low_byte], bt_mode), ], 0x2: [ NextValue(bus.dat_r[low_byte], videoctrl), ], + 0x3: [ NextValue(bus.dat_r[low_byte], vbl_signal), ], "default": [ NextValue(bus.dat_r, 0xDEADBEEF)], 0x10: [ NextValue(bus.dat_r, hres), ], # hres (r/o) # FIXME: endianess 0x11: [ NextValue(bus.dat_r, vres), ], # vres (r/o) # FIXME: endianess diff --git a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py index 508a2e7..3b95f85 100644 --- a/nubus-to-ztex-gateware/nubus_to_fpga_soc.py +++ b/nubus-to-ztex-gateware/nubus_to_fpga_soc.py @@ -349,6 +349,11 @@ class NuBusFPGA(SoCCore): self.submodules.tosbus_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.tosbus_layout), depth=1024//data_width)) self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "nubus", "read": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_layout), depth=512//data_width)) self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_req_layout), depth=512//data_width)) + irq_line = self.platform.request("nmrq_3v3_n") + fb_irq = Signal() + dma_irq = Signal() + + self.comb += irq_line.eq(fb_irq | dma_irq) self.submodules.exchange_with_mem = ExchangeWithMem(soc=self, platform=platform, @@ -362,6 +367,8 @@ class NuBusFPGA(SoCCore): do_checksum = False, clock_domain="nubus") + self.comb += dma_irq.eq(self.exchange_with_mem.irq) + if (sampling): self.submodules.nubus = nubus_full_sampling.NuBus(soc=self, burst_size=burst_size, @@ -388,15 +395,14 @@ class NuBusFPGA(SoCCore): self.submodules.stat = nubus_stat.NuBusStat(nubus=self.nubus, platform=platform) self.bus.add_slave("Stat", self.stat.bus_slv, SoCRegion(origin=self.mem_map.get("stat", None), size=0x1000, cached=False)) - if (goblin): if (not hdmi): self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga") - self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="vga", irq_line=self.platform.request("nmrq_3v3_n"), endian="little", hwcursor=False, truecolor=True) # clock_domain for the VGA side, goblin is running in cd_sys + self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="vga", irq_line=fb_irq, endian="little", hwcursor=False, truecolor=True) # clock_domain for the VGA side, goblin is running in cd_sys else: self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi"), clock_domain="hdmi") - self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="hdmi", irq_line=self.platform.request("nmrq_3v3_n"), endian="little", hwcursor=False, truecolor=True) # clock_domain for the HDMI side, goblin is running in cd_sys + self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=goblin_res, clock_domain="hdmi", irq_line=fb_irq, endian="little", hwcursor=False, truecolor=True) # clock_domain for the HDMI side, goblin is running in cd_sys self.bus.add_slave("goblin_bt", self.goblin.bus, SoCRegion(origin=self.mem_map.get("goblin_bt", None), size=0x1000, cached=False)) #pad_user_led_0 = platform.request("user_led", 0) #pad_user_led_1 = platform.request("user_led", 1)