diff --git a/nubus-to-ztex-gateware/DeclROM/DepVideo.inc b/nubus-to-ztex-gateware/DeclROM/DepVideo.inc index 0e1226d..9e2a584 100644 --- a/nubus-to-ztex-gateware/DeclROM/DepVideo.inc +++ b/nubus-to-ztex-gateware/DeclROM/DepVideo.inc @@ -30,6 +30,7 @@ RB24s = HRES*4 DrHwNuBusFPGA = 0xBEEF /* placeholder for GoboFB */ DrHwNuBusFPGADsk = 0xBEEE /* placeholder for RAM Dsk */ DrHwNuBusFPGAAudio = 0xBEED /* placeholder for Audio */ +DrHwNuBusFPGASDCard = 0xBEEC /* placeholder for SD Card */ typeDrive = 0x1000 /* placeholder for RAM Dsk*/ typeAudio = 0x1001 /* placeholder for Audio*/ diff --git a/nubus-to-ztex-gateware/DeclROM/Makefile b/nubus-to-ztex-gateware/DeclROM/Makefile index cacdaef..0720df7 100644 --- a/nubus-to-ztex-gateware/DeclROM/Makefile +++ b/nubus-to-ztex-gateware/DeclROM/Makefile @@ -24,7 +24,8 @@ endif CSRC_VIDEO=NuBusFPGADrvr_OpenClose.c NuBusFPGADrvr_Ctrl.c NuBusFPGADrvr_Status.c NuBusFPGAPrimaryInit_Primary.c NuBusFPGAPrimaryInit_RamInit.c NuBusFPGASecondaryInit_Secondary.c CSRC_RAMDSK=NuBusFPGARAMDskDrvr_OpenClose.c NuBusFPGARAMDskDrvr_Ctrl.c NuBusFPGARAMDskDrvr_Prime.c NuBusFPGARAMDskDrvr_Status.c myrle.c -CSRC=${CSRC_VIDEO} ${CSRC_RAMDSK} +CSRC_SDCARD=NuBusFPGASDCardDrvr_OpenClose.c NuBusFPGASDCardDrvr_Ctrl.c NuBusFPGASDCardDrvr_Prime.c NuBusFPGASDCardDrvr_Status.c +CSRC=${CSRC_VIDEO} ${CSRC_RAMDSK} ${CSRC_SDCARD} CSRC_ASM=${CSRC:.c=.s} GEN_ASM=VidRomDef.s VidRomDir.s VidRomName.s VidRomRes.s VidRomRsrcDir.s diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h index 714eb79..60c144d 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr.h @@ -8,7 +8,7 @@ #include #include -#define ENABLE_DMA 1 +// #define ENABLE_DMA 1 #include "NuBusFPGADrvr.h" diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c index eb41c7e..0d22c2b 100644 --- a/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGARAMDskDrvr_Prime.c @@ -9,6 +9,8 @@ __attribute__ ((section (".text.dskdriver"))) static inline void waitSome(unsign } } +// CLEANME: use the proper CSR accessor from nubusfpga_csr_exchange_with_mem.h + #ifdef ENABLE_DMA __attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMDrvContext *ctx, const AuxDCEPtr dce) { if (ctx->op.blk_todo > 0) { @@ -17,7 +19,7 @@ __attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMD ctx->op.blk_doing = 32768; // nice Po2 } 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((uint32_t)(ctx->op.ioBuffer + (ctx->op.blk_done << ctx->dma_blk_size_shift)))); ctx->op.blk_done += ctx->op.blk_doing; ctx->op.blk_todo -= ctx->op.blk_doing; ctx->op.blk_offset += ctx->op.blk_doing; diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.h b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.h new file mode 100644 index 0000000..035d3bc --- /dev/null +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.h @@ -0,0 +1,119 @@ +#ifndef __NUBUSFPGARAMDSKDRVR_H__ +#define __NUBUSFPGARAMDSKDRVR_H__ + +#include +#include +#include +#include +#include +#include + +#include "NuBusFPGADrvr.h" + +struct SDCardContext { + DrvSts2 drvsts; + unsigned int dma_blk_size; + unsigned int dma_blk_size_mask; + unsigned int dma_blk_size_shift; + unsigned int dma_blk_per_sdblk; + unsigned int dma_blk_per_sdblk_lshift; + char slot; + char toto; + unsigned int max_rd_blk_len; + SlotIntQElement *siqel; +}; + +#include "nubusfpga_csr_common.h" +#include "../nubusfpga_csr_sdblock2mem.h" +#include "../nubusfpga_csr_sdcore.h" +//#include "../nubusfpga_csr_sdirq.h" +#include "../nubusfpga_csr_sdmem2block.h" +#include "../nubusfpga_csr_sdphy.h" + +#include "../nubusfpga_csr_exchange_with_sd.h" + +/* basically Litex BIOS code */ + +#ifndef CONFIG_CLOCK_FREQUENCY +#define CONFIG_CLOCK_FREQUENCY 100000000 +#endif + + +#define CLKGEN_STATUS_BUSY 0x1 +#define CLKGEN_STATUS_PROGDONE 0x2 +#define CLKGEN_STATUS_LOCKED 0x4 + +#define SD_CMD_RESPONSE_SIZE 16 + +#define SD_OK 0 +#define SD_CRCERROR 1 +#define SD_TIMEOUT 2 +#define SD_WRITEERROR 3 + +#define SD_SWITCH_CHECK 0 +#define SD_SWITCH_SWITCH 1 + +#define SD_SPEED_SDR12 0 +#define SD_SPEED_SDR25 1 +#define SD_SPEED_SDR50 2 +#define SD_SPEED_SDR104 3 +#define SD_SPEED_DDR50 4 + +#define SD_DRIVER_STRENGTH_B 0 +#define SD_DRIVER_STRENGTH_A 1 +#define SD_DRIVER_STRENGTH_C 2 +#define SD_DRIVER_STRENGTH_D 3 + +#define SD_GROUP_ACCESSMODE 0 +#define SD_GROUP_COMMANDSYSTEM 1 +#define SD_GROUP_DRIVERSTRENGTH 2 +#define SD_GROUP_POWERLIMIT 3 + +#define SDCARD_STREAM_STATUS_OK 0b000 +#define SDCARD_STREAM_STATUS_TIMEOUT 0b001 +#define SDCARD_STREAM_STATUS_DATAACCEPTED 0b010 +#define SDCARD_STREAM_STATUS_CRCERROR 0b101 +#define SDCARD_STREAM_STATUS_WRITEERROR 0b110 + +#define SDCARD_CTRL_DATA_TRANSFER_NONE 0 +#define SDCARD_CTRL_DATA_TRANSFER_READ 1 +#define SDCARD_CTRL_DATA_TRANSFER_WRITE 2 + +#define SDCARD_CTRL_RESPONSE_NONE 0 +#define SDCARD_CTRL_RESPONSE_SHORT 1 +#define SDCARD_CTRL_RESPONSE_LONG 2 +#define SDCARD_CTRL_RESPONSE_SHORT_BUSY 3 + +//#define SDCARD_DEBUG +//#define SDCARD_CMD23_SUPPORT /* SET_BLOCK_COUNT */ +#define SDCARD_CMD18_SUPPORT /* READ_MULTIPLE_BLOCK */ +#define SDCARD_CMD25_SUPPORT /* WRITE_MULTIPLE_BLOCK */ + +#ifndef SDCARD_CLK_FREQ_INIT +#define SDCARD_CLK_FREQ_INIT 400000 +#endif + +#ifndef SDCARD_CLK_FREQ +#define SDCARD_CLK_FREQ 25000000 +//#define SDCARD_CLK_FREQ 12500000 +#endif + + +/* ctrl */ +OSErr cNuBusFPGASDCardCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver"))); +/* open, close */ +OSErr cNuBusFPGASDCardOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver"))); +OSErr cNuBusFPGASDCardClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver"))); +void busy_wait(int d) __attribute__ ((section (".text.sddriver"))); +void delay(int d) __attribute__ ((section (".text.sddriver"))); +int sdcard_read(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) __attribute__ ((section (".text.sddriver"))); +int sdcard_write(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) __attribute__ ((section (".text.sddriver"))); +/* prime */ +OSErr cNuBusFPGASDCardPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver"))); +void waitSome(unsigned long bound) __attribute__ ((section (".text.sddriver"))); +/* status */ +OSErr cNuBusFPGASDCardStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) __attribute__ ((section (".text.sddriver"))); + +uint32_t rledec(uint32_t* out, const uint32_t* in, const uint32_t len) __attribute__ ((section (".text.sddriver"))); + +#endif diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.s b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.s new file mode 100644 index 0000000..8481b34 --- /dev/null +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr.s @@ -0,0 +1,23 @@ +NuBusFPGASDCardDrvr: + .word 0x4f00 /* 0x4f00: ctl, status, read, write, needsLock [Devices.a] */ + .word 0 + .word 0 + .word 0 + /* Entry point offset table */ + /* we can directly call the C version if it has the right calling convention */ + .word cNuBusFPGASDCardOpen - NuBusFPGASDCardDrvr /* open routine */ + .word cNuBusFPGASDCardPrime - NuBusFPGASDCardDrvr /* prime */ + .word cNuBusFPGASDCardCtl - NuBusFPGASDCardDrvr /* control */ + .word cNuBusFPGASDCardStatus- NuBusFPGASDCardDrvr /* status */ + .word cNuBusFPGASDCardClose - NuBusFPGASDCardDrvr /* close */ + +_NuBusFPGASDCardTitle: + .byte _NuBusFPGASDCardTitle_StringEnd-.-1 /* pascal string length */ + .ascii ".NuBusFPGASDCard_Drvr" +_NuBusFPGASDCardTitle_StringEnd: + .word 0 /* version number */ + + /* for entry points: */ + /* A0 pointer to driver parameter block */ + /* A1 pointer to driver device control entry */ + ALIGN 2 diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Ctrl.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Ctrl.c new file mode 100644 index 0000000..e992cfb --- /dev/null +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Ctrl.c @@ -0,0 +1,59 @@ +#include "NuBusFPGASDCardDrvr.h" + +#if 0 +OSErr changeSDCardIRQ(AuxDCEPtr dce, char en, OSErr err) { + struct SDCardContext *ctx = *(struct SDCardContext**)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 ? revb(0x3) : revb(0x2)); // 0x2: always clear pending interrupt + ctx->irqen = en; + } + return noErr; +} +#endif + + +#pragma parameter __D0 cNuBusFPGASDCardCtl(__A0, __A1) +OSErr cNuBusFPGASDCardCtl(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) +{ + OSErr ret = noErr; + struct SDCardContext *ctx; + + /* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0002); */ + /* write_reg(dce, GOBOFB_DEBUG, pb->csCode); */ + + ctx = *(struct SDCardContext**)dce->dCtlStorage; + + if (ctx) { + switch (pb->csCode) + { + case kFormat: + ret = noErr; + break; + default: + ret = controlErr; + break; + } + } else { + ret = offLinErr; /* r/w requested for an off-line drive */ + goto done; + } + + done: + if (!(pb->ioTrap & (1< + +/* FYI, missing in library with Retro68 */ +/* void AddDrive(short drvrRefNum, short drvNum, DrvQElPtr qEl); */ + +/* re-implement with Retro68 features */ +/* drVNum to high-order bits of num, drvrRefNum in low-order */ +/* not sure how to do "parameter" without output ? */ +#pragma parameter __D0 AddDrive(__D0, __A0) +__attribute__ ((section (".text.sddriver"))) static inline int dupAddDrive(unsigned long num, DrvQElPtr qEl) { + asm volatile(".word 0xA04E" : : "d" (num), "a" (qEl)); + return num; // should cost nothing, num is already in D0 +} + +static int sdcard_init(struct SDCardContext* sdcc, uint32_t sc) __attribute__ ((section (".text.sddriver"))); + +#include + +#pragma parameter __D0 cNuBusFPGASDCardOpen(__A0, __A1) +OSErr cNuBusFPGASDCardOpen(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) +{ + DrvSts2 *dsptr; // pointer to the DrvSts2 in our context + int drvnum = 1; + struct SDCardContext *ctx; + OSErr ret = noErr; + char busMode; + char slot; + + busMode = 1; + SwapMMUMode ( &busMode ); // to32 // this likely won't work on older MacII ??? + + if (dce->dCtlDevBase == 0) { // for some unknown reason, we get an empty dCtlDevBase... + if ((dce->dCtlSlot > 0xE) || (dce->dCtlSlot < 0x9)) { // safety net + SpBlock mySpBlock; + SInfoRecord mySInfoRecord; + mySpBlock.spResult = (long)&mySInfoRecord; + + mySpBlock.spSlot = 0x9; // start at first + mySpBlock.spID = 0; + mySpBlock.spExtDev = 0; + mySpBlock.spCategory = catProto; + mySpBlock.spCType = 0x1000; // typeDrive; + mySpBlock.spDrvrSW = drSwApple; + mySpBlock.spDrvrHW = 0xbeec; // DrHwNuBusFPGADsk + mySpBlock.spTBMask = 0; + ret = SNextTypeSRsrc(&mySpBlock); + if (ret) + goto done; + slot = mySpBlock.spSlot; + } else { + slot = dce->dCtlSlot; + } + dce->dCtlDevBase = 0xF0000000ul | ((unsigned long)slot << 24); + } + + /* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0000); */ + /* write_reg(dce, GOBOFB_DEBUG, dce->dCtlSlot); */ + + if (dce->dCtlStorage == nil) { + DrvQElPtr dq; + for(dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) { + if (dq->dQDrive >= drvnum) + drvnum = dq->dQDrive+1; + } + + ReserveMemSys(sizeof(struct SDCardContext)); + dce->dCtlStorage = NewHandleSysClear(sizeof(struct SDCardContext)); + if (dce->dCtlStorage == nil) { + ret = openErr; + goto done; + } + + HLock(dce->dCtlStorage); + + ctx = *(struct SDCardContext **)dce->dCtlStorage; + ctx->slot = slot; + ctx->toto = 0; // removeme + + /* init the SDCard, this will also fill out dsptr->driveSize & dsptr->driveS1 */ + if (!sdcard_init(ctx, dce->dCtlDevBase)) { + ret = openErr; + HUnlock(dce->dCtlStorage); + DisposeHandle(dce->dCtlStorage); + dce->dCtlStorage = NULL; + goto done; + } + + ctx->dma_blk_size = exchange_with_sd_blk_size_read(dce->dCtlDevBase); + ctx->dma_blk_size_mask = ctx->dma_blk_size - 1; // size is Po2 + ctx->dma_blk_size_shift = 0; + while ((1 << ctx->dma_blk_size_shift) < ctx->dma_blk_size) // fixme + ctx->dma_blk_size_shift++; + ctx->dma_blk_per_sdblk_lshift = 9 - ctx->dma_blk_size_shift; + ctx->dma_blk_per_sdblk = 1 << ctx->dma_blk_per_sdblk_lshift; // 512 / ctx->dma_blk_size + + dsptr = &ctx->drvsts; + // dsptr->track /* current track */ + dsptr->writeProt = 0; /* bit 7 = 1 if volume is locked */ + dsptr->diskInPlace = 8; /* disk in drive */ + // dsptr->installed /* drive installed */ + // dsptr->sides /* -1 for 2-sided, 0 for 1-sided */ + // dsptr->QLink /* next queue entry */ + dsptr->qType = 1; /* 1 for HD20 */ /* Files 2-85 (p173) : 1 to enable S1 */ + dsptr->dQDrive = drvnum; /* drive number */ + dsptr->dQRefNum = dce->dCtlRefNum; /* driver reference number */ + // dsptr->dQFSID /* file system ID */ + /* driveSize & driveS1 filled by sdcard_init */ + //dsptr->driveSize = ((DRIVE_SIZE_BYTES/512ul) & 0x0000FFFFul); /* (no comments in Disks.h) */ + //dsptr->driveS1 = ((DRIVE_SIZE_BYTES/512ul) & 0xFFFF0000ul) >> 16; /* */ + // dsptr->driveType + // dsptr->driveManf + // dsptr->driveChar + // dsptr->driveMisc + + // MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink); + + // write_reg(dce, GOBOFB_DEBUG, 0x0000DEAD); + + // add the drive + //MyAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink); + dupAddDrive((dsptr->dQRefNum & 0xFFFF) | (drvnum << 16), (DrvQElPtr)&dsptr->qLink); + +#if 0 + ctx->dma_blk_size = revb( read_reg(dce, DMA_BLK_SIZE) ); + ctx->dma_blk_size_mask = ctx->dma_blk_size - 1; // size is Po2 + ctx->dma_blk_size_shift = 0; + while ((1 << ctx->dma_blk_size_shift) < ctx->dma_blk_size) // fixme + ctx->dma_blk_size_shift++; + ctx->dma_blk_base = revb( read_reg(dce, DMA_BLK_BASE) ); + ctx->dma_mem_size = revb( read_reg(dce, DMA_MEM_SIZE) ); + /* write_reg(dce, GOBOFB_DEBUG, 0xD1580002); */ + /* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size); */ + /* write_reg(dce, GOBOFB_DEBUG, ctx->dma_blk_size_mask); */ + /* 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); */ + + { + SlotIntQElement *siqel = (SlotIntQElement *)NewPtrSysClear(sizeof(SlotIntQElement)); + + if (siqel == NULL) { + return openErr; + } + + siqel->sqType = sIQType; + siqel->sqPrio = 7; + siqel->sqAddr = dskIrq; + siqel->sqParm = (long)dce; + ctx->siqel = siqel; + ctx->irqen = 0; + + 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 + + // auto-mount + if (0) { + ParamBlockRec pbr; + pbr.volumeParam.ioVRefNum = dsptr->dQDrive; + ret = PBMountVol(&pbr); + } + } + + SwapMMUMode ( &busMode ); + + done: + return ret; +} + +#pragma parameter __D0 cNuBusFPGASDCardClose(__A0, __A1) +OSErr cNuBusFPGASDCardClose(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) +{ + OSErr ret = noErr; + struct SDCardContext *ctx = *(struct SDCardContext**)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; + } + return ret; +} + +/*-----------------------------------------------------------------------*/ +/* Helpers */ +/*-----------------------------------------------------------------------*/ + +#define max(x, y) (((x) > (y)) ? (x) : (y)) +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +/* In MacOS + Delay(unsigned long numTicks, unsigned long * finalTicks) + has ticks in 1/60th of a second or 16.6666 ms +*/ + +/* in NetBSD/sparc busy_wait is 1ms * d */ +void busy_wait(int d) { + waitSome(d * 20000); // improveme + return; +} +/* in NetBSD/sparc delay is 1us * d */ +void delay(int d) { + waitSome(d * 20); // improveme + return; +} + +/*-----------------------------------------------------------------------*/ +/* SDCard command helpers */ +/*-----------------------------------------------------------------------*/ + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_wait_cmd_done(uint32_t sc) { + unsigned int event; +#ifdef SDCARD_DEBUG + uint32_t r[SD_CMD_RESPONSE_SIZE/4]; +#endif + for (;;) { + event = sdcore_cmd_event_read(sc); +#ifdef SDCARD_DEBUG + printf("cmdevt: %08x\n", event); +#endif + delay(10); + if (event & 0x1) + break; + } +#ifdef SDCARD_DEBUG + csr_rd_buf_uint32(sc, sc->sc_bhregs_sdcore + (CSR_SDCORE_CMD_RESPONSE_ADDR - CSR_SDCORE_BASE), r, SD_CMD_RESPONSE_SIZE/4); + printf("%08x %08x %08x %08x\n", r[0], r[1], r[2], r[3]); +#endif + if (event & 0x4) + return SD_TIMEOUT; + if (event & 0x8) + return SD_CRCERROR; + return SD_OK; +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_wait_data_done(uint32_t sc) { + unsigned int event; + for (;;) { + event = sdcore_data_event_read(sc); +#ifdef SDCARD_DEBUG + printf("dataevt: %08x\n", event); +#endif + if (event & 0x1) + break; + delay(10); + } + if (event & 0x4) + return SD_TIMEOUT; + else if (event & 0x8) + return SD_CRCERROR; + return SD_OK; +} + +/*-----------------------------------------------------------------------*/ +/* SDCard clocker functions */ +/*-----------------------------------------------------------------------*/ + +/* round up to closest power-of-two */ +__attribute__ ((section (".text.sddriver"))) static inline uint32_t pow2_round_up(uint32_t r) { + r--; + r |= r >> 1; + r |= r >> 2; + r |= r >> 4; + r |= r >> 8; + r |= r >> 16; + r++; + return r; +} + +__attribute__ ((section (".text.sddriver"))) static inline void sdcard_set_clk_freq(uint32_t sc, uint32_t clk_freq, int show) { + uint32_t divider; + divider = clk_freq ? CONFIG_CLOCK_FREQUENCY/clk_freq : 256; + divider = pow2_round_up(divider); + divider = min(max(divider, 2), 256); +#ifdef SDCARD_DEBUG + show = 1; +#endif + if (show) { + /* this is the *effective* new clk_freq */ + clk_freq = CONFIG_CLOCK_FREQUENCY/divider; + /* + printf("Setting SDCard clk freq to "); + if (clk_freq > 1000000) + printf("%d MHz\n", clk_freq/1000000); + else + printf("%d KHz\n", clk_freq/1000); + */ + } + sdphy_clocker_divider_write(sc, divider); +} + +/*-----------------------------------------------------------------------*/ +/* SDCard commands functions */ +/*-----------------------------------------------------------------------*/ + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_command(uint32_t sc, uint32_t arg, uint8_t cmd, uint8_t rsp) { + sdcore_cmd_argument_write(sc, arg); + sdcore_cmd_command_write(sc, (cmd << 8) | rsp); + sdcore_cmd_send_write(sc, 1); + return sdcard_wait_cmd_done(sc); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_go_idle(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("CMD0: GO_IDLE\n"); +#endif + return sdcard_send_command(sc, 0, 0, SDCARD_CTRL_RESPONSE_NONE); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_ext_csd(uint32_t sc) { + uint32_t arg = 0x000001aa; +#ifdef SDCARD_DEBUG + printf("CMD8: SEND_EXT_CSD, arg: 0x%08x\n", arg); +#endif + return sdcard_send_command(sc, arg, 8, SDCARD_CTRL_RESPONSE_SHORT); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_cmd(uint32_t sc, uint16_t rca) { +#ifdef SDCARD_DEBUG + printf("CMD55: APP_CMD\n"); +#endif + return sdcard_send_command(sc, rca << 16, 55, SDCARD_CTRL_RESPONSE_SHORT); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_send_op_cond(uint32_t sc, int hcs) { + uint32_t arg = 0x10ff8000; + if (hcs) + arg |= 0x60000000; +#ifdef SDCARD_DEBUG + printf("ACMD41: APP_SEND_OP_COND, arg: %08x\n", arg); +#endif + return sdcard_send_command(sc, arg, 41, SDCARD_CTRL_RESPONSE_SHORT_BUSY); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_all_send_cid(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("CMD2: ALL_SEND_CID\n"); +#endif + return sdcard_send_command(sc, 0, 2, SDCARD_CTRL_RESPONSE_LONG); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_set_relative_address(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("CMD3: SET_RELATIVE_ADDRESS\n"); +#endif + return sdcard_send_command(sc, 0, 3, SDCARD_CTRL_RESPONSE_SHORT); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_cid(uint32_t sc, uint16_t rca) { +#ifdef SDCARD_DEBUG + printf("CMD10: SEND_CID\n"); +#endif + return sdcard_send_command(sc, rca << 16, 10, SDCARD_CTRL_RESPONSE_LONG); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_csd(uint32_t sc, uint16_t rca) { +#ifdef SDCARD_DEBUG + printf("CMD9: SEND_CSD\n"); +#endif + return sdcard_send_command(sc, rca << 16, 9, SDCARD_CTRL_RESPONSE_LONG); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_select_card(uint32_t sc, uint16_t rca) { +#ifdef SDCARD_DEBUG + printf("CMD7: SELECT_CARD\n"); +#endif + return sdcard_send_command(sc, rca << 16, 7, SDCARD_CTRL_RESPONSE_SHORT_BUSY); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_set_bus_width(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("ACMD6: SET_BUS_WIDTH\n"); +#endif + return sdcard_send_command(sc, 2, 6, SDCARD_CTRL_RESPONSE_SHORT); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_switch(uint32_t sc, unsigned int mode, unsigned int group, unsigned int value) { + unsigned int arg; + arg = (mode << 31) | 0xffffff; + arg &= ~(0xf << (group * 4)); + arg |= value << (group * 4); + //device_printf(sc->dk.sc_dev, "switch arg is 0x%08x\n", arg); +#ifdef SDCARD_DEBUG + printf("CMD6: SWITCH_FUNC\n"); +#endif + sdcore_block_length_write(sc, 64); + sdcore_block_count_write(sc, 1); + while (sdcard_send_command(sc, arg, 6, + (SDCARD_CTRL_DATA_TRANSFER_READ << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return sdcard_wait_data_done(sc); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_send_scr(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("CMD51: APP_SEND_SCR\n"); +#endif + sdcore_block_length_write(sc, 8); + sdcore_block_count_write(sc, 1); + while (sdcard_send_command(sc, 0, 51, + (SDCARD_CTRL_DATA_TRANSFER_READ << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return sdcard_wait_data_done(sc); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_app_set_blocklen(uint32_t sc, unsigned int blocklen) { +#ifdef SDCARD_DEBUG + printf("CMD16: SET_BLOCKLEN\n"); +#endif + return sdcard_send_command(sc, blocklen, 16, SDCARD_CTRL_RESPONSE_SHORT); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_write_single_block(uint32_t sc, unsigned int blockaddr) { +#ifdef SDCARD_DEBUG + printf("CMD24: WRITE_SINGLE_BLOCK\n"); +#endif + sdcore_block_length_write(sc, 512); + sdcore_block_count_write(sc, 1); + while (sdcard_send_command(sc, blockaddr, 24, + (SDCARD_CTRL_DATA_TRANSFER_WRITE << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return SD_OK; +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_write_multiple_block(uint32_t sc, unsigned int blockaddr, unsigned int blockcnt) { +#ifdef SDCARD_DEBUG + printf("CMD25: WRITE_MULTIPLE_BLOCK\n"); +#endif + sdcore_block_length_write(sc, 512); + sdcore_block_count_write(sc, blockcnt); + while (sdcard_send_command(sc, blockaddr, 25, + (SDCARD_CTRL_DATA_TRANSFER_WRITE << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return SD_OK; +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_read_single_block(uint32_t sc, unsigned int blockaddr) { +#ifdef SDCARD_DEBUG + printf("CMD17: READ_SINGLE_BLOCK\n"); +#endif + sdcore_block_length_write(sc, 512); + sdcore_block_count_write(sc, 1); + while (sdcard_send_command(sc, blockaddr, 17, + (SDCARD_CTRL_DATA_TRANSFER_READ << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return sdcard_wait_data_done(sc); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_read_multiple_block(uint32_t sc, unsigned int blockaddr, unsigned int blockcnt) { +#ifdef SDCARD_DEBUG + printf("CMD18: READ_MULTIPLE_BLOCK\n"); +#endif + sdcore_block_length_write(sc, 512); + sdcore_block_count_write(sc, blockcnt); + while (sdcard_send_command(sc, blockaddr, 18, + (SDCARD_CTRL_DATA_TRANSFER_READ << 5) | + SDCARD_CTRL_RESPONSE_SHORT) != SD_OK); + return sdcard_wait_data_done(sc); +} + +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_stop_transmission(uint32_t sc) { +#ifdef SDCARD_DEBUG + printf("CMD12: STOP_TRANSMISSION\n"); +#endif + return sdcard_send_command(sc, 0, 12, SDCARD_CTRL_RESPONSE_SHORT_BUSY); +} + +#if 0 +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_send_status(uint32_t sc, uint16_t rca) { +#ifdef SDCARD_DEBUG + printf("CMD13: SEND_STATUS\n"); +#endif + return sdcard_send_command(sc, rca << 16, 13, SDCARD_CTRL_RESPONSE_SHORT); +} +#endif + +#if 0 +__attribute__ ((section (".text.sddriver"))) static inline int sdcard_set_block_count(uint32_t sc, unsigned int blockcnt) { +#ifdef SDCARD_DEBUG + printf("CMD23: SET_BLOCK_COUNT\n"); +#endif + return sdcard_send_command(sc, blockcnt, 23, SDCARD_CTRL_RESPONSE_SHORT); +} +#endif + +__attribute__ ((section (".text.sddriver"))) static inline uint16_t sdcard_decode_rca(uint32_t sc) { + uint32_t r[SD_CMD_RESPONSE_SIZE/4]; + csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4); + return (r[3] >> 16) & 0xffff; +} + +__attribute__ ((section (".text.sddriver"))) static inline void sdcard_decode_cid(uint32_t sc) { + uint32_t r[SD_CMD_RESPONSE_SIZE/4]; + csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4); + /* aprint_normal_dev(sc->dk.sc_dev, */ + /* "CID Register: 0x%08x%08x%08x%08x " */ + /* "Manufacturer ID: 0x%x " */ + /* "Application ID 0x%x " */ + /* "Product name: %c%c%c%c%c " */ + /* "CRC: %02x " */ + /* "Production date(m/yy): %d/%d " */ + /* "PSN: %08x " */ + /* "OID: %c%c\n", */ + /* r[0], r[1], r[2], r[3], */ + /* (r[0] >> 16) & 0xffff, */ + /* r[0] & 0xffff, */ + /* (r[1] >> 24) & 0xff, (r[1] >> 16) & 0xff, */ + /* (r[1] >> 8) & 0xff, (r[1] >> 0) & 0xff, (r[2] >> 24) & 0xff, */ + /* r[3] & 0xff, */ + /* (r[3] >> 8) & 0x0f, (r[3] >> 12) & 0xff, */ + /* (r[3] >> 24) | (r[2] << 8), */ + /* (r[0] >> 16) & 0xff, (r[0] >> 8) & 0xff */ + /* ); */ +} + +__attribute__ ((section (".text.sddriver"))) static inline void sdcard_decode_csd(struct SDCardContext* sdcc, uint32_t sc) { + uint32_t r[SD_CMD_RESPONSE_SIZE/4]; + csr_rd_buf_uint32(sc, CSR_SDCORE_CMD_RESPONSE_ADDR, r, SD_CMD_RESPONSE_SIZE/4); + /* FIXME: only support CSR structure version 2.0 */ + //sc->max_rd_blk_len = (1 << ((r[1] >> 16) & 0xf)); + //sc->max_size_in_blk = ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 * 2; + uint32_t max_size_in_blk = ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 * 2; // weird spec in 512KiB unit + if (max_size_in_blk >= 4194304) // 2 GiB + max_size_in_blk = 4194303; // 2 GiB - 512 B + +#define MAX_DSK_SIZE_MB 80 + if (max_size_in_blk >= (MAX_DSK_SIZE_MB*(1048576/512))) // TEMPORARY FOR TESTING + max_size_in_blk = (MAX_DSK_SIZE_MB*(1048576/512)); // TEMPORARY FOR TESTING + + sdcc->drvsts.driveSize = max_size_in_blk & 0x0000FFFF; + sdcc->drvsts.driveS1 = (max_size_in_blk & 0xFFFF0000) >> 16; + sdcc->max_rd_blk_len = (1 << ((r[1] >> 16) & 0xf)); // READ_BL_LEN ? should always be 9 ? + /* aprint_normal_dev(sc->dk.sc_dev, */ + /* "CSD Register: 0x%08x%08x%08x%08x " */ + /* "Max data transfer rate: %d MB/s " */ + /* "Max read block length: %d bytes " */ + /* "Device size: %d GiB (%d blocks)\n", */ + /* r[0], r[1], r[2], r[3], */ + /* (r[0] >> 24) & 0xff, */ + /* sc->max_rd_blk_len, */ + /* ((r[2] >> 16) + ((r[1] & 0xff) << 16) + 1) * 512 / (1024 * 1024), */ + /* sc->max_size_in_blk */ + /* ); */ +} + +/*-----------------------------------------------------------------------*/ +/* SDCard user functions */ +/*-----------------------------------------------------------------------*/ +static int sdcard_init(struct SDCardContext* sdcc, uint32_t sc) { + uint16_t rca, timeout; + int res; + + /* Set SD clk freq to Initialization frequency */ + sdcard_set_clk_freq(sc, SDCARD_CLK_FREQ_INIT, 0); + busy_wait(1); + + for (timeout=1000; timeout>0; timeout--) { + /* Set SDCard in SPI Mode (generate 80 dummy clocks) */ + sdphy_init_initialize_write(sc, 1); + busy_wait(1); + + /* Set SDCard in Idle state */ + if (sdcard_go_idle(sc) == SD_OK) + break; + busy_wait(1); + } + if (timeout == 0) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard timeout (1)\n"); + return 0; + } + + /* Set SDCard voltages, only supported by ver2.00+ SDCards */ + if ((res = sdcard_send_ext_csd(sc)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_send_ext_csd failed\n"); + return 0; + } + + /* Set SD clk freq to Operational frequency */ + sdcard_set_clk_freq(sc, SDCARD_CLK_FREQ, 0); + busy_wait(1); + + /* Set SDCard in Operational state */ + for (timeout=1000; timeout>0; timeout--) { + sdcard_app_cmd(sc, 0); + if ((res = sdcard_app_send_op_cond(sc, 1)) != SD_OK) + break; + busy_wait(1); + } + if (timeout == 0) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard timeout (2)\n"); + return 0; + } + + /* Send identification */ + if ((res = sdcard_all_send_cid(sc)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_all_send_cid failed (%d)\n", res); + return 0; + } + sdcard_decode_cid(sc); + + /* Set Relative Card Address (RCA) */ + if ((res = sdcard_set_relative_address(sc)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_set_relative_address failed (%d)\n", res); + return 0; + } + rca = sdcard_decode_rca(sc); + //device_printf(sc->dk.sc_dev, "rca is 0x%08x\n", rca); + + /* Set CID */ + if ((res = sdcard_send_cid(sc, rca)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_send_cid failed (%d)\n", res); + return 0; + } +#ifdef SDCARD_DEBUG + /* FIXME: add cid decoding (optional) */ +#endif + + /* Set CSD */ + if ((res = sdcard_send_csd(sc, rca)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_send_csd failed (%d)\n", res); + return 0; + } + + sdcard_decode_csd(sdcc, sc); + + /* Select card */ + if ((res = sdcard_select_card(sc, rca)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_select_card failed (%d)\n", res); + return 0; + } + + /* Set bus width */ + if ((res = sdcard_app_cmd(sc, rca)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_app_cmd failed (%d)\n", res); + return 0; + } + if((res = sdcard_app_set_bus_width(sc)) != SD_OK){ + //aprint_error_dev(sc->dk.sc_dev, "sdcard_app_set_bus_width failed (%d)\n", res); + return 0; + } + + /* Switch speed */ + if ((res = sdcard_switch(sc, SD_SWITCH_SWITCH, SD_GROUP_ACCESSMODE, SD_SPEED_SDR25)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_switch failed (%d)\n", res); + return 0; + } + + /* Send SCR */ + /* FIXME: add scr decoding (optional) */ + if ((res = sdcard_app_cmd(sc, rca)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_app_cmd failed (%d)\n", res); + return 0; + } + if ((res = sdcard_app_send_scr(sc)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_app_send_scr failed (%d)\n", res); + return 0; + } + + /* Set block length */ + if ((res = sdcard_app_set_blocklen(sc, 512)) != SD_OK) { + //aprint_error_dev(sc->dk.sc_dev, "sdcard_app_set_blocklen failed (%d)\n", res); + return 0; + } + + return 1; +} + +#if 1 +__attribute__ ((section (".text.sddriver"))) static inline void do_copy_rev(uint32_t *src, uint32_t *dst, uint32_t size) { + uint32_t i; + for (i = 0 ; i < size/4 ; i++) { + dst[i] = revb(src[i]); + } +} +#endif + +__attribute__ ((section (".text.sddriver"))) static inline OSErr start_dma_read(uint32_t sc, struct SDCardContext *ctx, uint32_t count, uint8_t* buf) { + unsigned int dma_blk_cnt = count << ctx->dma_blk_per_sdblk_lshift; + + exchange_with_sd_blk_addr_write(sc, 0); + exchange_with_sd_dma_addr_write(sc, buf); + exchange_with_sd_blk_cnt_write(sc, dma_blk_cnt | 0x80000000); // MSb==1, read + return noErr; +} +__attribute__ ((section (".text.sddriver"))) static inline OSErr start_dma_write(uint32_t sc, struct SDCardContext *ctx, uint32_t count, uint8_t* buf) { + unsigned int dma_blk_cnt = count << ctx->dma_blk_per_sdblk_lshift; + + exchange_with_sd_blk_addr_write(sc, 0); + exchange_with_sd_dma_addr_write(sc, buf); + exchange_with_sd_blk_cnt_write(sc, dma_blk_cnt); // MSb==0, write + return noErr; +} +#if 0 +#define DMA_STATUS_CHECK_BITS (0x01F) +__attribute__ ((section (".text.sddriver"))) static inline OSErr wait_dma(uint32_t sc, uint32_t blk_count, OSErr err) { + unsigned long count, max_count, delay; + unsigned long blk_cnt, status; + OSErr ret = noErr; + max_count = 32 * blk_count; + delay = blk_count >> 2; + if (delay > 65536) + delay = 65536; + waitSome(delay); + count = 0; + blk_cnt = exchange_with_sd_blk_cnt_blk_cnt_read(sc); + status = exchange_with_sd_dma_status_read(sc) & DMA_STATUS_CHECK_BITS; + while (((blk_cnt != 0) || + (status != 0)) && + (count < max_count)) { + count ++; + waitSome(delay); + if (blk_cnt) blk_cnt = exchange_with_sd_blk_cnt_blk_cnt_read(sc); + if (status) status = exchange_with_sd_dma_status_read(sc) & DMA_STATUS_CHECK_BITS; + } + if (blk_cnt || status) { + ret = err; + } + return ret; +} +#endif + +int sdcard_read(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) { + while (count) { + uint32_t nblocks; + //uint64_t buf_hw_addr = ((uint64_t)((uint32_t)buf));// << 32; + uint32_t buf_hw_addr = (uint32_t)buf; // TEMPORARY FOR TESTING + uint32_t stage_addr_dma = 0x80000000; // DDR // TEMPORARY FOR TESTING + uint32_t stage_addr_cpu = sc << 4; // superslot // TEMPORARY FOR TESTING +#ifdef SDCARD_CMD18_SUPPORT + nblocks = count; + if (nblocks > 16) + nblocks = 16; +#else + nblocks = 1; +#endif + +#if 1 + /* Initialize DMA Writer */ + sdblock2mem_dma_enable_write(sc, 0); + /* sdblock2mem_dma_base_write takes an uint64_t */ + ////sdblock2mem_dma_base_write(sc, buf_hw_addr); + sdblock2mem_dma_base_write(sc, stage_addr_dma); + sdblock2mem_dma_length_write(sc, 512*nblocks); + sdblock2mem_dma_enable_write(sc, 1); +#else + start_dma_write(sc, ctx, nblocks, buf_hw_addr); // read from sdcard, write to memory +#endif + + /* Read Block(s) from SDCard */ +#ifdef SDCARD_CMD23_SUPPORT + sdcard_set_block_count(sc, nblocks); +#endif + if (nblocks > 1) + sdcard_read_multiple_block(sc, block, nblocks); + else + sdcard_read_single_block(sc, block); + +#if 1 + //int timeout = 64 * nblocks; + int timeout = 1024 * nblocks; + /* Wait for DMA Writer to complete */ + while (((sdblock2mem_dma_done_read(sc) & 0x1) == 0) && timeout) { + //delay(2); + delay(20); + timeout --; + } + if ((sdblock2mem_dma_done_read(sc) & 0x1) == 0) { + /* device_printf(sc->dk.sc_dev, "%s: SD card timeout\n", __PRETTY_FUNCTION__); */ + return 1; + } +#else + if (wait_dma(sc, nblocks, readErr) != noErr) + return 1; +#endif + + /* Stop transmission (Only for multiple block reads) */ + if (nblocks > 1) + sdcard_stop_transmission(sc); + + BlockMoveData((void*)stage_addr_cpu, (void*)buf_hw_addr, 512*nblocks); + //do_copy_rev((void*)stage_addr_cpu, (void*)buf_hw_addr, 512*nblocks); + + + /* Update Block/Buffer/Count */ + block += nblocks; + buf += 512*nblocks; + count -= nblocks; + } + + return 0; +} + +int sdcard_write(uint32_t sc, struct SDCardContext *ctx, uint32_t block, uint32_t count, uint8_t* buf) { + while (count) { + uint32_t nblocks; + //uint64_t buf_hw_addr = ((uint64_t)((uint32_t)buf));// << 32; + uint32_t buf_hw_addr = (uint32_t)buf; // TEMPORARY FOR TESTING + uint32_t stage_addr_dma = 0x80000000; // DDR // TEMPORARY FOR TESTING + uint32_t stage_addr_cpu = sc << 4; // superslot // TEMPORARY FOR TESTING +#ifdef SDCARD_CMD25_SUPPORT + nblocks = count; + if (nblocks > 16) + nblocks = 16; +#else + nblocks = 1; +#endif + + BlockMoveData((void*)buf_hw_addr, (void*)stage_addr_cpu, 512*nblocks); + //do_copy_rev((void*)buf_hw_addr, (void*)stage_addr_cpu, 512*nblocks); + +#if 1 + /* Initialize DMA Reader */ + sdmem2block_dma_enable_write(sc, 0); + /* sdblock2mem_dma_base_write takes an uint64_t */ + ////sdmem2block_dma_base_write(sc, buf_hw_addr); + sdmem2block_dma_base_write(sc, stage_addr_dma); + sdmem2block_dma_length_write(sc, 512*nblocks); + sdmem2block_dma_enable_write(sc, 1); +#else + start_dma_read(sc, ctx, nblocks, buf_hw_addr); // write to sdcard, read from memory +#endif + + /* Write Block(s) to SDCard */ +#ifdef SDCARD_CMD23_SUPPORT + sdcard_set_block_count(sc, nblocks); +#endif + if (nblocks > 1) + sdcard_write_multiple_block(sc, block, nblocks); + else + sdcard_write_single_block(sc, block); + + /* Stop transmission (Only for multiple block writes) */ + if (nblocks > 1) + sdcard_stop_transmission(sc); + +#if 1 + /* Wait for DMA Reader to complete */ + //int timeout = 64 * nblocks; + int timeout = 1024 * nblocks; + while (((sdmem2block_dma_done_read(sc) & 0x1) == 0) && timeout) { + //delay(2); + delay(20); + timeout --; + } + if ((sdmem2block_dma_done_read(sc) & 0x1) == 0) { + /* device_printf(sc->dk.sc_dev, "%s: SD card timeout\n", __PRETTY_FUNCTION__); */ + return 1; + } +#else + if (wait_dma(sc, nblocks, writErr) != noErr) + return 1; +#endif + + /* Update Block/Buffer/Count */ + block += nblocks; + buf += 512*nblocks; + count -= nblocks; + } + + return 0; +} diff --git a/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Prime.c b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Prime.c new file mode 100644 index 0000000..3abba08 --- /dev/null +++ b/nubus-to-ztex-gateware/DeclROM/NuBusFPGASDCardDrvr_Prime.c @@ -0,0 +1,111 @@ +#include "NuBusFPGASDCardDrvr.h" + +/* #include */ + +inline void waitSome(unsigned long bound) { + unsigned long i; + for (i = 0 ; i < bound ; i++) { + asm volatile("nop"); + } +} + +__attribute__ ((section (".text.sddriver"))) static OSErr doSync(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce, struct SDCardContext *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 + if (abs_offset & 0x01FF) { + ret = paramErr; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount; + goto done; + } + if (pb->ioReqCount & 0x01FF) { + ret = paramErr; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount; + goto done; + } + if (sdcard_read(dce->dCtlDevBase, ctx, abs_offset >> 9, pb->ioReqCount >> 9, pb->ioBuffer)) { + ret = readErr; + goto done; + } + } + pb->ioActCount = pb->ioReqCount; + dce->dCtlPosition = abs_offset + pb->ioReqCount; + pb->ioPosOffset = dce->dCtlPosition; + } else if ((pb->ioTrap & 0x00FF) == aWrCmd) { + if (abs_offset & 0x01FF) { + ret = paramErr; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount; + goto done; + } + if (pb->ioReqCount & 0x01FF) { + ret = paramErr; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x804) = abs_offset; + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x808) = pb->ioReqCount; + goto done; + } + if (sdcard_write(dce->dCtlDevBase, ctx, abs_offset >> 9, pb->ioReqCount >> 9, pb->ioBuffer)) { + ret = writErr; + goto done; + } + pb->ioActCount = pb->ioReqCount; + dce->dCtlPosition = abs_offset + pb->ioReqCount; + pb->ioPosOffset = dce->dCtlPosition; + } else { + ret = paramErr; + goto done; + } + done: + if (ret != noErr) + *(uint32_t*)(dce->dCtlDevBase | 0x00902000 | 0x800) = ret | (((pb->ioTrap & 0x00FF) == aRdCmd) ? 0x11000000 : 0x22000000); + return ret; +} + +/* Devices 1-34 (p54) */ +#pragma parameter __D0 cNuBusFPGASDCardPrime(__A0, __A1) +OSErr cNuBusFPGASDCardPrime(IOParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce) { + OSErr ret = noErr; + struct SDCardContext *ctx; + unsigned long abs_offset = 0; + + ctx = *(struct SDCardContext**)dce->dCtlStorage; + + if (ctx) { + ret = doSync(pb, dce, ctx); + if (!(pb->ioTrap & (1<ioTrap & (1<csCode); */ + + ctx = *(struct SDCardContext**)dce->dCtlStorage; + + if (ctx) { + switch (pb->csCode) + { + default: + ret = statusErr; + break; + } + } else { + ret = offLinErr; /* r/w requested for an off-line drive */ + goto done; + } + + done: + if (!(pb->ioTrap & (1<= 64bit left shift! */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshift-count-overflow" -__attribute__ ((section (".text.primary"))) static inline void csr_rd_buf_uint64(uint32_t a32, unsigned long a, uint64_t *buf, int cnt) +static inline void csr_rd_buf_uint64(uint32_t a32, unsigned long a, uint64_t *buf, int cnt) { _csr_rd_buf(a32, a, buf, cnt); } -__attribute__ ((section (".text.primary"))) static inline void csr_wr_buf_uint64(uint32_t a32, unsigned long a, +static inline void csr_wr_buf_uint64(uint32_t a32, unsigned long a, const uint64_t *buf, int cnt) { _csr_wr_buf(a32, a, buf, cnt); diff --git a/nubus-to-ztex-gateware/DeclROM/vid_decl_rom.s b/nubus-to-ztex-gateware/DeclROM/vid_decl_rom.s index 4315431..473f446 100644 --- a/nubus-to-ztex-gateware/DeclROM/vid_decl_rom.s +++ b/nubus-to-ztex-gateware/DeclROM/vid_decl_rom.s @@ -9,6 +9,7 @@ sRsrc_Board = 1 /* board sResource (>0 & <128) */ .include "VidRomDef.s" sRsrc_RAMDsk = 0x90 /* functional sResources */ +sRsrc_SDCard = 0x91 /* functional sResources */ sRsrc_HDMIAudio = 0xA0 /* functional sResources */ .global DeclROMDir @@ -122,7 +123,7 @@ _GoboFBDrvrDir: .section .text.begin .include "VidRomRes.s" - +/* ////////////////////////////////////////////// RAM DISK */ .section .text.begin ALIGN 2 _sRsrc_RAMDsk: @@ -158,7 +159,44 @@ _RAMDskDrvrDir: .include "NuBusFPGARAMDskDrvr.s" /* driver code */ /* _RAMDskEnd020Drvr: */ /* supplied by linker script */ +/* ////////////////////////////////////////////// SDCARD */ + .section .text.begin + ALIGN 2 +_sRsrc_SDCard: + OSLstEntry sRsrcType,_SDCardType /* video type descriptor */ + OSLstEntry sRsrcName,_SDCardName /* offset to driver name string */ + OSLstEntry sRsrcDrvrDir,_SDCardDrvrDir /* offset to driver directory */ + DatLstEntry sRsrcFlags,6 /* force 32 bits mode & open */ + DatLstEntry sRsrcHWDevId,2 /* hardware device ID */ + .long EndOfList /* end of list */ + + ALIGN 2 +_SDCardType: + .short catProto /* */ + .short typeDrive /* custom */ /* */ + .short drSwApple /* */ + .short DrHwNuBusFPGASDCard /* */ + +_SDCardName: + .string "SDCard_NuBusFPGA" /* video driver name */ + ALIGN 2 + .section .text.begin + .global _SDCardDrvrDir +_SDCardDrvrDir: + /* OSLstEntry sMacOS68020,_SDCardDrvrMacOS68020 */ /* driver directory for Mac OS */ + .long entry_SDCardDrvrMacOS68020 + .long EndOfList + + ALIGN 2 + .section .text.sddriver_init +/* _SDCardDrvrMacOS68020: */ /* supplied by linker script */ + .long _SDCardEnd020Drvr-. /* physical block size */ + .include "NuBusFPGASDCardDrvr.s" /* driver code */ +/* _SDCardEnd020Drvr: */ /* supplied by linker script */ + + +/* ////////////////////////////////////////////// HDMI AUDIO */ .section .text.begin ALIGN 2 _sRsrc_HDMIAudio: