mirror of
https://github.com/rdolbeau/NuBusFPGA.git
synced 2025-01-08 13:29:26 +00:00
refactor ram dsk driver a bit more, some work toward multiplexed interrupt
This commit is contained in:
parent
fb0a291b70
commit
6040bca13a
@ -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)
|
||||
|
@ -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")));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 <ROMDefs.h>
|
||||
|
||||
#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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user