mirror of
https://github.com/rdolbeau/NuBusFPGA.git
synced 2024-12-23 01:30:32 +00:00
DMA + IRQ for RAM Disk
This commit is contained in:
parent
6040bca13a
commit
c08acd77ed
@ -27,6 +27,9 @@ OSErr changeIRQ(AuxDCEPtr dce, char en, OSErr err) {
|
|||||||
if (SIntInstall(dStore->siqel, dce->dCtlSlot)) {
|
if (SIntInstall(dStore->siqel, dce->dCtlSlot)) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
write_reg(dce, GOBOFB_DEBUG, 0x88888888);
|
||||||
|
write_reg(dce, GOBOFB_DEBUG, dStore->siqel);
|
||||||
|
write_reg(dce, GOBOFB_DEBUG, dStore->siqel->sqLink);
|
||||||
} else {
|
} else {
|
||||||
if (SIntRemove(dStore->siqel, dce->dCtlSlot)) {
|
if (SIntRemove(dStore->siqel, dce->dCtlSlot)) {
|
||||||
return err;
|
return err;
|
||||||
|
@ -20,7 +20,7 @@ __attribute__ ((section (".text.fbdriver"))) short fbIrq(const long sqParameter)
|
|||||||
asm volatile("" : "+d" (p_D1), "+d" (p_D2));
|
asm volatile("" : "+d" (p_D1), "+d" (p_D2));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
irq = (*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)));
|
irq = (*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+GOBOFB_INTR_CLEAR)));
|
||||||
if (irq) {
|
if (irq & 1) {
|
||||||
vblproto myVbl = *(vblproto**)0x0d28;
|
vblproto myVbl = *(vblproto**)0x0d28;
|
||||||
*((volatile unsigned int*)(sqParameter+GOBOFB_BASE+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...
|
myVbl((sqParameter>>24)&0xf); // cleaner to use dStore->slot ? but require more code...
|
||||||
@ -34,8 +34,8 @@ __attribute__ ((section (".text.fbdriver"))) short fbIrq(const long sqParameter)
|
|||||||
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
OSErr cNuBusFPGAOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
||||||
{
|
{
|
||||||
OSErr ret = noErr;
|
OSErr ret = noErr;
|
||||||
write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000);
|
/* write_reg(dce, GOBOFB_DEBUG, 0xBEEF0000); */
|
||||||
write_reg(dce, GOBOFB_DEBUG, (unsigned long)dce->dCtlDevBase);
|
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)dce->dCtlDevBase); */
|
||||||
|
|
||||||
if (dce->dCtlStorage == nil)
|
if (dce->dCtlStorage == nil)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "NuBusFPGADrvr.h"
|
#include "NuBusFPGADrvr.h"
|
||||||
|
#include "NuBusFPGARAMDskDrvr.h"
|
||||||
|
|
||||||
#include <Traps.h>
|
#include <Traps.h>
|
||||||
#include <ROMDefs.h>
|
#include <ROMDefs.h>
|
||||||
@ -23,10 +24,11 @@ UInt32 Primary(SEBlock* seblock) {
|
|||||||
busMode = 1;
|
busMode = 1;
|
||||||
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
|
SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ???
|
||||||
|
|
||||||
PRIM_WRITEREG(GOBOFB_VBL_MASK, 0);// disable interrupts
|
PRIM_WRITEREG(GOBOFB_VBL_MASK, 0);// disable interrupts on FB
|
||||||
|
PRIM_WRITEREG(DMA_IRQ_CTL, revb(0x2));// disable/clear interrupts on DSK
|
||||||
|
|
||||||
PRIM_WRITEREG(GOBOFB_DEBUG, 0x87654321);// trace
|
/* PRIM_WRITEREG(GOBOFB_DEBUG, 0x87654321);// trace */
|
||||||
PRIM_WRITEREG(GOBOFB_DEBUG, busMode);// trace
|
/* PRIM_WRITEREG(GOBOFB_DEBUG, busMode);// trace */
|
||||||
|
|
||||||
hres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_HRES)); // fixme: endianness
|
hres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_HRES)); // fixme: endianness
|
||||||
vres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_VRES)); // fixme: endianness
|
vres = __builtin_bswap32((UInt32)PRIM_READREG(GOBOFB_VRES)); // fixme: endianness
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
#include "NuBusFPGADrvr.h"
|
#include "NuBusFPGADrvr.h"
|
||||||
|
|
||||||
#ifdef ENABLE_DMA
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long blk_todo;
|
unsigned long blk_todo;
|
||||||
unsigned long blk_done;
|
unsigned long blk_done;
|
||||||
@ -21,26 +20,24 @@ typedef struct {
|
|||||||
void *ioBuffer;
|
void *ioBuffer;
|
||||||
int write;
|
int write;
|
||||||
} ram_dsk_op;
|
} ram_dsk_op;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct RAMDrvContext {
|
struct RAMDrvContext {
|
||||||
DrvSts2 drvsts;
|
DrvSts2 drvsts;
|
||||||
|
ram_dsk_op op;
|
||||||
char slot;
|
char slot;
|
||||||
#ifdef ENABLE_DMA
|
#ifdef ENABLE_DMA
|
||||||
|
char irqen;
|
||||||
unsigned int dma_blk_size;
|
unsigned int dma_blk_size;
|
||||||
unsigned int dma_blk_size_mask;
|
unsigned int dma_blk_size_mask;
|
||||||
unsigned int dma_blk_size_shift;
|
unsigned int dma_blk_size_shift;
|
||||||
unsigned long dma_blk_base;
|
unsigned long dma_blk_base;
|
||||||
unsigned long dma_mem_size;
|
unsigned long dma_mem_size;
|
||||||
SlotIntQElement *siqel;
|
SlotIntQElement *siqel;
|
||||||
ram_dsk_op op;
|
|
||||||
char irqen;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DRIVE_SIZE_BYTES ((256ul-8ul)*1024ul*1024ul) // FIXME: mem size minus fb size
|
#define DRIVE_SIZE_BYTES ((256ul-8ul)*1024ul*1024ul) // FIXME: mem size minus fb size
|
||||||
|
|
||||||
#ifdef ENABLE_DMA
|
|
||||||
/* FIXME; should be auto-generated for CSR addresses... */
|
/* FIXME; should be auto-generated for CSR addresses... */
|
||||||
/* WARNING: 0x00100800 is the offset to GOBOFB_BASE !! */
|
/* WARNING: 0x00100800 is the offset to GOBOFB_BASE !! */
|
||||||
#define DMA_BLK_SIZE (0x00100800 | 0x00)
|
#define DMA_BLK_SIZE (0x00100800 | 0x00)
|
||||||
@ -56,15 +53,15 @@ struct RAMDrvContext {
|
|||||||
|
|
||||||
#define DMA_IRQSTATUS (0x00100800 | 0x34)
|
#define DMA_IRQSTATUS (0x00100800 | 0x34)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ctrl */
|
/* ctrl */
|
||||||
OSErr changeRAMdskIRQ(AuxDCEPtr dce, char en, OSErr err) __attribute__ ((section (".text.dskdriver")));
|
OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) __attribute__ ((section (".text.dskdriver")));
|
||||||
OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
OSErr cNuBusFPGARAMDskCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
||||||
/* open, close */
|
/* open, close */
|
||||||
OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
||||||
OSErr cNuBusFPGARAMDskClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
OSErr cNuBusFPGARAMDskClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
||||||
/* prime */
|
/* prime */
|
||||||
|
short dskIrq(const long sqParameter) __attribute__ ((section (".text.dskdriver")));
|
||||||
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
||||||
/* status */
|
/* status */
|
||||||
OSErr cNuBusFPGARAMDskStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
OSErr cNuBusFPGARAMDskStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.dskdriver")));
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "NuBusFPGARAMDskDrvr.h"
|
#include "NuBusFPGARAMDskDrvr.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
|
|
||||||
OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) {
|
OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) {
|
||||||
struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
|
struct RAMDrvContext *ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
|
||||||
|
|
||||||
@ -19,11 +18,12 @@ OSErr changeRAMDskIRQ(AuxDCEPtr dce, char en, OSErr err) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
write_reg(dce, DMA_IRQ_CTL, en ? 0x3 : 0x2); // 0x2: always clear pending interrupt
|
write_reg(dce, DMA_IRQ_CTL, en ? revb(0x3) : revb(0x2)); // 0x2: always clear pending interrupt
|
||||||
ctx->irqen = en;
|
ctx->irqen = en;
|
||||||
}
|
}
|
||||||
return noErr;
|
return noErr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#pragma parameter __D0 cNuBusFPGARAMDskCtl(__A0, __A1)
|
#pragma parameter __D0 cNuBusFPGARAMDskCtl(__A0, __A1)
|
||||||
|
@ -14,32 +14,6 @@ __attribute__ ((section (".text.dskdriver"))) static inline int dupAddDrive(unsi
|
|||||||
return num; // should cost nothing, num is already in D0
|
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>
|
#include <ROMDefs.h>
|
||||||
|
|
||||||
#pragma parameter __D0 cNuBusFPGARAMDskOpen(__A0, __A1)
|
#pragma parameter __D0 cNuBusFPGARAMDskOpen(__A0, __A1)
|
||||||
@ -101,6 +75,9 @@ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
|||||||
ctx = *(struct RAMDrvContext **)dce->dCtlStorage;
|
ctx = *(struct RAMDrvContext **)dce->dCtlStorage;
|
||||||
ctx->slot = slot;
|
ctx->slot = slot;
|
||||||
|
|
||||||
|
// disable IRQ for now
|
||||||
|
write_reg(dce, DMA_IRQ_CTL, revb(0x2)); // 0x1 would enable irq, 0x2 is auto-clear so we make sure there's no spurious IRQ pending ; should be already done by Pirmary
|
||||||
|
|
||||||
dsptr = &ctx->drvsts;
|
dsptr = &ctx->drvsts;
|
||||||
// dsptr->track /* current track */
|
// dsptr->track /* current track */
|
||||||
dsptr->writeProt = 0; /* bit 7 = 1 if volume is locked */
|
dsptr->writeProt = 0; /* bit 7 = 1 if volume is locked */
|
||||||
@ -150,24 +127,26 @@ OSErr cNuBusFPGARAMDskOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
|||||||
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_base); */
|
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_base); */
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_mem_size); */
|
/* write_reg(dce, GOBOFB_DEBUG, ctx->dma_mem_size); */
|
||||||
|
|
||||||
if (1) {
|
{
|
||||||
SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement));
|
SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement));
|
||||||
|
|
||||||
if (siqel == NULL) {
|
if (siqel == NULL) {
|
||||||
return openErr;
|
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->sqType = sIQType;
|
||||||
siqel->sqPrio = 7;
|
siqel->sqPrio = 7;
|
||||||
siqel->sqAddr = dskIrq;
|
siqel->sqAddr = dskIrq;
|
||||||
siqel->sqParm = (long)dce;
|
siqel->sqParm = (long)dce;
|
||||||
ctx->siqel = siqel;
|
ctx->siqel = siqel;
|
||||||
ctx->irqen = 0;
|
ctx->irqen = 0;
|
||||||
write_reg(dce, GOBOFB_DEBUG, siqel);
|
|
||||||
write_reg(dce, GOBOFB_DEBUG, ctx);
|
ctx->op.blk_todo = 0;
|
||||||
|
ctx->op.blk_done = 0;
|
||||||
|
ctx->op.blk_offset = 0;
|
||||||
|
ctx->op.blk_doing = 0;
|
||||||
|
ctx->op.ioBuffer = 0;
|
||||||
|
ctx->op.write = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ __attribute__ ((section (".text.dskdriver"))) static inline void waitSome(unsign
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
__attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
|
__attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
|
||||||
if (ctx->op.blk_todo > 0) {
|
if (ctx->op.blk_todo > 0) {
|
||||||
ctx->op.blk_doing = ctx->op.blk_todo;
|
ctx->op.blk_doing = ctx->op.blk_todo;
|
||||||
@ -17,13 +18,15 @@ __attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMD
|
|||||||
}
|
}
|
||||||
write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + ctx->op.blk_offset));
|
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_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_done += ctx->op.blk_doing;
|
||||||
ctx->op.blk_todo -= ctx->op.blk_doing;
|
ctx->op.blk_todo -= ctx->op.blk_doing;
|
||||||
ctx->op.blk_offset += ctx->op.blk_doing;
|
ctx->op.blk_offset += ctx->op.blk_doing;
|
||||||
|
write_reg(dce, DMA_BLK_CNT, revb((ctx->op.write ? 0x80000000ul : 0x00000000ul) | ctx->op.blk_doing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
__attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
|
__attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(struct RAMDrvContext *ctx, const AuxDCEPtr dce) {
|
||||||
unsigned long count, max_count, delay;
|
unsigned long count, max_count, delay;
|
||||||
unsigned long blk_cnt, status;
|
unsigned long blk_cnt, status;
|
||||||
@ -49,23 +52,125 @@ __attribute__ ((section (".text.dskdriver"))) static OSErr waitForHW(struct RAMD
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Devices 1-34 (p54) */
|
#ifdef ENABLE_DMA
|
||||||
#pragma parameter __D0 cNuBusFPGARAMDskPrime(__A0, __A1)
|
/* see the comment for the FB irq */
|
||||||
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
#pragma parameter __D0 dskIrq(__A1)
|
||||||
{
|
__attribute__ ((section (".text.dskdriver"))) short dskIrq(const long sqParameter) {
|
||||||
OSErr ret = noErr;
|
register unsigned long p_D1 asm("d1"), p_D2 asm("d2");
|
||||||
|
AuxDCEPtr dce;
|
||||||
struct RAMDrvContext *ctx;
|
struct RAMDrvContext *ctx;
|
||||||
|
unsigned int irq;
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0003); */
|
short ret;
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, pb->ioTrap); */
|
asm volatile("" : "+d" (p_D1), "+d" (p_D2));
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosMode); */
|
dce = (AuxDCEPtr)sqParameter;
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
|
|
||||||
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosOffset); */
|
|
||||||
|
|
||||||
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
|
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
|
||||||
|
ret = 0;
|
||||||
|
irq = revb(read_reg(dce, DMA_IRQSTATUS));
|
||||||
|
if (irq & 1) {
|
||||||
|
unsigned int irqctrl = revb(read_reg(dce, DMA_IRQ_CTL));
|
||||||
|
irqctrl |= 0x2; // irq clear
|
||||||
|
write_reg(dce, DMA_IRQ_CTL, revb(irqctrl));
|
||||||
|
if (ctx->op.blk_todo > 0) {
|
||||||
|
startOneOp(ctx, dce);
|
||||||
|
} else {
|
||||||
|
if (ctx->op.blk_doing > 0) {
|
||||||
|
ctx->op.blk_doing = 0; // reset just in case
|
||||||
|
IODone((DCtlPtr)dce, noErr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
asm volatile("" : : "d" (p_D1), "d" (p_D2));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
|
__attribute__ ((section (".text.dskdriver"))) static OSErr doAsync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct RAMDrvContext *ctx) {
|
||||||
|
OSErr ret = noErr;
|
||||||
|
|
||||||
|
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
|
||||||
|
unsigned long abs_offset = 0;
|
||||||
|
/* IOParamPtr: Devices 1-53 (p73) */
|
||||||
|
/* **** WHERE **** */
|
||||||
|
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
|
||||||
|
case fsAtMark:
|
||||||
|
abs_offset = dce->dCtlPosition;
|
||||||
|
break;
|
||||||
|
case fsFromStart:
|
||||||
|
abs_offset = pb->ioPosOffset;
|
||||||
|
break;
|
||||||
|
case fsFromMark:
|
||||||
|
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* **** WHAT **** */
|
||||||
|
/* Devices 1-33 (p53) */
|
||||||
|
if ((pb->ioTrap & 0x00FF) == aRdCmd) {
|
||||||
|
if(!(pb->ioPosMode & 0x40)) { // rdVerify, let's ignore it for now
|
||||||
|
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)) {
|
||||||
|
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;
|
||||||
|
/* should we do it now ? */
|
||||||
|
pb->ioActCount = pb->ioReqCount;
|
||||||
|
dce->dCtlPosition = abs_offset + pb->ioReqCount;
|
||||||
|
pb->ioPosOffset = dce->dCtlPosition;
|
||||||
|
if (ctx->op.blk_todo > 0) {
|
||||||
|
startOneOp(ctx, dce);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blk_cnt || status) {
|
||||||
|
ret = readErr;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((pb->ioTrap & 0x00FF) == aWrCmd) {
|
||||||
|
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)) {
|
||||||
|
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;
|
||||||
|
/* should we do it now ? */
|
||||||
|
pb->ioActCount = pb->ioReqCount;
|
||||||
|
dce->dCtlPosition = abs_offset + pb->ioReqCount;
|
||||||
|
pb->ioPosOffset = dce->dCtlPosition;
|
||||||
|
if (ctx->op.blk_todo > 0) {
|
||||||
|
startOneOp(ctx, dce);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (blk_cnt || status) {
|
||||||
|
ret = writErr;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = paramErr;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif // ENABLE_DMA
|
||||||
|
|
||||||
|
__attribute__ ((section (".text.dskdriver"))) static OSErr doSync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct RAMDrvContext *ctx) {
|
||||||
|
OSErr ret = noErr;
|
||||||
|
|
||||||
if (ctx) {
|
|
||||||
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
|
unsigned char* superslot = (unsigned char*)(((unsigned long)ctx->slot) << 28ul);
|
||||||
unsigned long abs_offset = 0;
|
unsigned long abs_offset = 0;
|
||||||
/* IOParamPtr: Devices 1-53 (p73) */
|
/* IOParamPtr: Devices 1-53 (p73) */
|
||||||
@ -163,14 +268,81 @@ OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
|||||||
ret = paramErr;
|
ret = paramErr;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
ctx->op.blk_doing = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Devices 1-34 (p54) */
|
||||||
|
#pragma parameter __D0 cNuBusFPGARAMDskPrime(__A0, __A1)
|
||||||
|
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
||||||
|
{
|
||||||
|
OSErr ret = noErr;
|
||||||
|
struct RAMDrvContext *ctx;
|
||||||
|
unsigned long abs_offset = 0;
|
||||||
|
/* IOParamPtr: Devices 1-53 (p73) */
|
||||||
|
/* **** WHERE **** */
|
||||||
|
switch(pb->ioPosMode & 0x000F) { // ignore rdVerify
|
||||||
|
case fsAtMark:
|
||||||
|
abs_offset = dce->dCtlPosition;
|
||||||
|
break;
|
||||||
|
case fsFromStart:
|
||||||
|
abs_offset = pb->ioPosOffset;
|
||||||
|
break;
|
||||||
|
case fsFromMark:
|
||||||
|
abs_offset = dce->dCtlPosition + pb->ioPosOffset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0003); */
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, pb->ioTrap); */
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosMode); */
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, pb->ioPosOffset); */
|
||||||
|
|
||||||
|
ctx = *(struct RAMDrvContext**)dce->dCtlStorage;
|
||||||
|
|
||||||
|
if (ctx) {
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
|
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) &&
|
||||||
|
(!(pb->ioTrap & (1<<noQueueBit)))) {
|
||||||
|
ret = changeRAMDskIRQ(dce, 1, (pb->ioTrap & 0x00FF) == aWrCmd ? writErr : readErr);
|
||||||
|
if (ret != noErr) {
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
// DMA-ifiable & queuable, go async
|
||||||
|
ret = doAsync(pb, dce, ctx);
|
||||||
|
// no IODone if ongoing, done at interrupt time
|
||||||
|
if (ret != noErr)
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
goto done;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_DMA
|
||||||
|
ret = changeRAMDskIRQ(dce, 0, (pb->ioTrap & 0x00FF) == aWrCmd ? writErr : readErr);
|
||||||
|
#endif
|
||||||
|
if (ret)
|
||||||
|
goto done;
|
||||||
|
ret = doSync(pb, dce, ctx);
|
||||||
|
if (!(pb->ioTrap & (1<<noQueueBit))) {
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = offLinErr; /* r/w requested for an off-line drive */
|
ret = offLinErr; /* r/w requested for an off-line drive */
|
||||||
|
if (!(pb->ioTrap & (1<<noQueueBit)))
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (!(pb->ioTrap & (1<<noQueueBit)))
|
|
||||||
IODone((DCtlPtr)dce, ret);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,7 @@ class goblin(Module, AutoCSR):
|
|||||||
videoctrl = Signal() # reg 0x8
|
videoctrl = Signal() # reg 0x8
|
||||||
|
|
||||||
vbl_signal = Signal(reset = 0) # reg 0xC
|
vbl_signal = Signal(reset = 0) # reg 0xC
|
||||||
self.comb += irq_line.eq(~vbl_signal | m_vbl_disable) # active low
|
self.comb += irq_line.eq(~vbl_signal | m_vbl_disable) # irq_line is active low
|
||||||
|
|
||||||
if (endian == "big"):
|
if (endian == "big"):
|
||||||
low_byte = slice(0, 8)
|
low_byte = slice(0, 8)
|
||||||
@ -557,7 +557,7 @@ class goblin(Module, AutoCSR):
|
|||||||
# bt_addr
|
# bt_addr
|
||||||
0x0: [ NextValue(bus.dat_r[low_byte], bt_mode), ],
|
0x0: [ NextValue(bus.dat_r[low_byte], bt_mode), ],
|
||||||
0x2: [ NextValue(bus.dat_r[low_byte], videoctrl), ],
|
0x2: [ NextValue(bus.dat_r[low_byte], videoctrl), ],
|
||||||
0x3: [ NextValue(bus.dat_r[low_byte], vbl_signal), ],
|
0x3: [ NextValue(bus.dat_r[low_byte], ~irq_line), ], # irq_line is active low
|
||||||
"default": [ NextValue(bus.dat_r, 0xDEADBEEF)],
|
"default": [ NextValue(bus.dat_r, 0xDEADBEEF)],
|
||||||
0x10: [ NextValue(bus.dat_r, hres), ], # hres (r/o) # FIXME: endianess
|
0x10: [ NextValue(bus.dat_r, hres), ], # hres (r/o) # FIXME: endianess
|
||||||
0x11: [ NextValue(bus.dat_r, vres), ], # vres (r/o) # FIXME: endianess
|
0x11: [ NextValue(bus.dat_r, vres), ], # vres (r/o) # FIXME: endianess
|
||||||
|
@ -15,8 +15,8 @@ class NuBus(Module):
|
|||||||
platform = soc.platform
|
platform = soc.platform
|
||||||
self.add_sources(platform)
|
self.add_sources(platform)
|
||||||
|
|
||||||
led0 = platform.request("user_led", 0)
|
#led0 = platform.request("user_led", 0)
|
||||||
led1 = platform.request("user_led", 1)
|
#led1 = platform.request("user_led", 1)
|
||||||
|
|
||||||
# Signals for tri-stated nubus access
|
# Signals for tri-stated nubus access
|
||||||
# slave
|
# slave
|
||||||
@ -264,8 +264,8 @@ class NuBus(Module):
|
|||||||
fromsbus_fifo_din = Record(soc.fromsbus_layout)
|
fromsbus_fifo_din = Record(soc.fromsbus_layout)
|
||||||
self.comb += fromsbus_fifo.din.eq(fromsbus_fifo_din.raw_bits())
|
self.comb += fromsbus_fifo.din.eq(fromsbus_fifo_din.raw_bits())
|
||||||
|
|
||||||
self.comb += led0.eq(~dma_fsm.ongoing("Idle"))
|
#self.comb += led0.eq(~dma_fsm.ongoing("Idle"))
|
||||||
self.comb += led1.eq(burst)
|
#self.comb += led1.eq(burst)
|
||||||
|
|
||||||
dma_fsm.act("Reset",
|
dma_fsm.act("Reset",
|
||||||
NextState("Idle")
|
NextState("Idle")
|
||||||
|
@ -15,8 +15,8 @@ class NuBus(Module):
|
|||||||
platform = soc.platform
|
platform = soc.platform
|
||||||
self.add_sources(platform)
|
self.add_sources(platform)
|
||||||
|
|
||||||
led0 = platform.request("user_led", 0)
|
#led0 = platform.request("user_led", 0)
|
||||||
led1 = platform.request("user_led", 1)
|
#led1 = platform.request("user_led", 1)
|
||||||
|
|
||||||
nub_clk = ClockSignal(cd_nubus)
|
nub_clk = ClockSignal(cd_nubus)
|
||||||
nub_resetn = ~ResetSignal(cd_nubus)
|
nub_resetn = ~ResetSignal(cd_nubus)
|
||||||
@ -353,8 +353,8 @@ class NuBus(Module):
|
|||||||
fromsbus_fifo_din = Record(soc.fromsbus_layout)
|
fromsbus_fifo_din = Record(soc.fromsbus_layout)
|
||||||
self.comb += fromsbus_fifo.din.eq(fromsbus_fifo_din.raw_bits())
|
self.comb += fromsbus_fifo.din.eq(fromsbus_fifo_din.raw_bits())
|
||||||
|
|
||||||
self.comb += led0.eq(~dma_fsm.ongoing("Idle"))
|
#self.comb += led0.eq(~dma_fsm.ongoing("Idle"))
|
||||||
self.comb += led1.eq(burst)
|
#self.comb += led1.eq(burst)
|
||||||
|
|
||||||
dma_fsm.act("Reset",
|
dma_fsm.act("Reset",
|
||||||
NextState("Idle")
|
NextState("Idle")
|
||||||
|
@ -349,11 +349,17 @@ 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.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_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))
|
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")
|
irq_line = self.platform.request("nmrq_3v3_n") # active low
|
||||||
fb_irq = Signal()
|
fb_irq = Signal() # active low
|
||||||
dma_irq = Signal()
|
dma_irq = Signal() # active low
|
||||||
|
led0 = platform.request("user_led", 0)
|
||||||
|
led1 = platform.request("user_led", 1)
|
||||||
|
self.comb += [
|
||||||
|
led0.eq(~fb_irq),
|
||||||
|
led1.eq(~dma_irq),
|
||||||
|
]
|
||||||
|
|
||||||
self.comb += irq_line.eq(fb_irq | dma_irq)
|
self.comb += irq_line.eq(fb_irq & dma_irq) # active low, enable if one is low
|
||||||
|
|
||||||
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
||||||
platform=platform,
|
platform=platform,
|
||||||
|
Loading…
Reference in New Issue
Block a user