NuBusFPGA/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c

182 lines
6.6 KiB
C
Raw Normal View History

#include "NuBusFPGARAMDskDrvr.h"
/* #include <DriverServices.h> */
static inline void waitSome(unsigned long bound) {
unsigned long i;
for (i = 0 ; i < bound ; i++) {
asm volatile("nop");
}
}
/* Devices 1-34 (p54) */
OSErr cNuBusFPGARAMDskPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
{
OSErr ret = noErr;
struct RAMDrvContext *ctx;
/* 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) {
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
2022-07-23 10:53:30 +00:00
#ifdef ENABLE_DMA
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580000); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)pb->ioBuffer); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
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)) {
unsigned long count, max_count, delay;
2022-07-23 10:53:30 +00:00
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
2022-07-23 10:53:30 +00:00
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
max_count = 4096 + 16 * blk_cnt;
/* if (max_count < 32) */
/* max_count = 32; */
delay = 16 * blk_cnt;
if (delay > 4096)
delay = 4096;
2022-07-23 10:53:30 +00:00
if ((blk_cnt == 0) && (status == 0)) {
write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + (abs_offset >> ctx->dma_blk_size_shift)));
write_reg(dce, DMA_DMA_ADDR, revb(pb->ioBuffer));
write_reg(dce, DMA_BLK_CNT, revb(0x00000000ul | (pb->ioReqCount >> ctx->dma_blk_size_shift)));
count = 0;
while (((blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF) != 0) && (count < max_count)) {
2022-07-23 10:53:30 +00:00
count ++;
waitSome(delay);
}
2022-07-23 10:53:30 +00:00
count = 0;
while ((((status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS)) != 0) && (count < max_count)) {
2022-07-23 10:53:30 +00:00
count ++;
waitSome(delay);
}
2022-07-23 10:53:30 +00:00
}
if (blk_cnt || status) {
return readErr;
2022-07-23 10:53:30 +00:00
BlockMoveData((superslot + abs_offset), pb->ioBuffer, pb->ioReqCount);
}
#ifdef DMA_DEBUG
else {
2022-07-23 10:53:30 +00:00
unsigned int k = 0;
while ((((unsigned long*)(superslot))[5] == 0x12345678) && (((unsigned long*)(superslot))[9] == 0x87654321) && (k < 7)) {
k++;
superslot += 64;
}
if ((((unsigned long*)(superslot))[5] != 0x12345678) || (((unsigned long*)(superslot))[9] != 0x87654321)) {
unsigned int i;
for (i = 0 ; i < pb->ioReqCount ; i+=4 ) {
if ((*(unsigned long*)(superslot + abs_offset + i)) != (*(unsigned long*)((char*)pb->ioBuffer + i))) {
((unsigned long*)(superslot))[0] = ctx->dma_blk_size;
((unsigned long*)(superslot))[1] = ctx->dma_blk_size_mask;
((unsigned long*)(superslot))[2] = ctx->dma_blk_size_shift;
((unsigned long*)(superslot))[3] = ctx->dma_blk_base;
((unsigned long*)(superslot))[4] = ctx->dma_mem_size;
((unsigned long*)(superslot))[5] = 0x12345678;
((unsigned long*)(superslot))[6] = pb->ioBuffer;
((unsigned long*)(superslot))[7] = pb->ioReqCount;
((unsigned long*)(superslot))[8] = abs_offset;
((unsigned long*)(superslot))[9] = 0x87654321;
((unsigned long*)(superslot))[10] = i;
((unsigned long*)(superslot))[11] = (*(unsigned long*)(superslot + abs_offset + i));
((unsigned long*)(superslot))[12] = (*(unsigned long*)((char*)pb->ioBuffer + i));
((unsigned long*)(superslot))[13] = (*(unsigned long*)(superslot + abs_offset + i + 4));
((unsigned long*)(superslot))[14] = (*(unsigned long*)((char*)pb->ioBuffer + i + 4));
i += 4;
}
}
}
}
#endif
2022-07-23 10:53:30 +00:00
} else
#endif
{
BlockMoveData((superslot + abs_offset), pb->ioBuffer, pb->ioReqCount);
}
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else if ((pb->ioTrap & 0x00FF) == aWrCmd) {
#ifdef ENABLE_DMA
2022-07-23 10:53:30 +00:00
/* write_reg(dce, GOBOFB_DEBUG, 0xD1580001); */
/* write_reg(dce, GOBOFB_DEBUG, (unsigned long)pb->ioBuffer); */
/* write_reg(dce, GOBOFB_DEBUG, pb->ioReqCount); */
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)) {
unsigned long count, max_count, delay;
2022-07-23 10:53:30 +00:00
unsigned long blk_cnt, status;
blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF;
2022-07-23 10:53:30 +00:00
status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS;
max_count = 4096 + 16 * blk_cnt;
/* if (max_count < 32) */
/* max_count = 32; */
delay = 16 * blk_cnt;
if (delay > 4096)
delay = 4096;
2022-07-23 10:53:30 +00:00
if ((blk_cnt == 0) && (status == 0)) {
write_reg(dce, DMA_BLK_ADDR, revb(ctx->dma_blk_base + (abs_offset >> ctx->dma_blk_size_shift)));
write_reg(dce, DMA_DMA_ADDR, revb(pb->ioBuffer));
write_reg(dce, DMA_BLK_CNT, revb(0x80000000ul | (pb->ioReqCount >> ctx->dma_blk_size_shift)));
count = 0;
while (((blk_cnt = revb(read_reg(dce, DMA_BLK_CNT)) & 0xFFFF) != 0) && (count < max_count)) {
2022-07-23 10:53:30 +00:00
count ++;
waitSome(delay);
}
2022-07-23 10:53:30 +00:00
count = 0;
while ((((status = revb(read_reg(dce, DMA_STATUS)) & DMA_STATUS_CHECK_BITS)) != 0) && (count < max_count)) {
2022-07-23 10:53:30 +00:00
count ++;
waitSome(delay);
}
2022-07-23 10:53:30 +00:00
}
if (blk_cnt || status) {
return writErr;
2022-07-23 10:53:30 +00:00
BlockMoveData(pb->ioBuffer, (superslot + abs_offset), pb->ioReqCount);
}
} else
#endif
{
BlockMoveData(pb->ioBuffer, (superslot + abs_offset), pb->ioReqCount);
}
pb->ioActCount = pb->ioReqCount;
dce->dCtlPosition = abs_offset + pb->ioReqCount;
pb->ioPosOffset = dce->dCtlPosition;
} else {
ret = paramErr;
goto done;
}
} else {
ret = offLinErr; /* r/w requested for an off-line drive */
goto done;
}
done:
return ret;
}