commit not-yet-working micro-sd code
This commit is contained in:
parent
f9886f7280
commit
12690cfbf0
|
@ -30,6 +30,7 @@ RB24s = HRES*4
|
||||||
DrHwNuBusFPGA = 0xBEEF /* placeholder for GoboFB */
|
DrHwNuBusFPGA = 0xBEEF /* placeholder for GoboFB */
|
||||||
DrHwNuBusFPGADsk = 0xBEEE /* placeholder for RAM Dsk */
|
DrHwNuBusFPGADsk = 0xBEEE /* placeholder for RAM Dsk */
|
||||||
DrHwNuBusFPGAAudio = 0xBEED /* placeholder for Audio */
|
DrHwNuBusFPGAAudio = 0xBEED /* placeholder for Audio */
|
||||||
|
DrHwNuBusFPGASDCard = 0xBEEC /* placeholder for SD Card */
|
||||||
|
|
||||||
typeDrive = 0x1000 /* placeholder for RAM Dsk*/
|
typeDrive = 0x1000 /* placeholder for RAM Dsk*/
|
||||||
typeAudio = 0x1001 /* placeholder for Audio*/
|
typeAudio = 0x1001 /* placeholder for Audio*/
|
||||||
|
|
|
@ -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_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_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}
|
CSRC_ASM=${CSRC:.c=.s}
|
||||||
|
|
||||||
GEN_ASM=VidRomDef.s VidRomDir.s VidRomName.s VidRomRes.s VidRomRsrcDir.s
|
GEN_ASM=VidRomDef.s VidRomDir.s VidRomName.s VidRomRes.s VidRomRsrcDir.s
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
#include <Disks.h>
|
#include <Disks.h>
|
||||||
|
|
||||||
#define ENABLE_DMA 1
|
// #define ENABLE_DMA 1
|
||||||
|
|
||||||
#include "NuBusFPGADrvr.h"
|
#include "NuBusFPGADrvr.h"
|
||||||
|
|
||||||
|
|
|
@ -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
|
#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) {
|
||||||
|
@ -17,7 +19,7 @@ __attribute__ ((section (".text.dskdriver"))) static void startOneOp(struct RAMD
|
||||||
ctx->op.blk_doing = 32768; // nice Po2
|
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_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_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;
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
#ifndef __NUBUSFPGARAMDSKDRVR_H__
|
||||||
|
#define __NUBUSFPGARAMDSKDRVR_H__
|
||||||
|
|
||||||
|
#include <Files.h>
|
||||||
|
#include <Devices.h>
|
||||||
|
#include <Slots.h>
|
||||||
|
#include <MacErrors.h>
|
||||||
|
#include <MacMemory.h>
|
||||||
|
#include <Disks.h>
|
||||||
|
|
||||||
|
#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
|
|
@ -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
|
|
@ -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<<noQueueBit)))
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,873 @@
|
||||||
|
#include "NuBusFPGASDCardDrvr.h"
|
||||||
|
|
||||||
|
#include <Disks.h>
|
||||||
|
|
||||||
|
/* 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 <ROMDefs.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include "NuBusFPGASDCardDrvr.h"
|
||||||
|
|
||||||
|
/* #include <DriverServices.h> */
|
||||||
|
|
||||||
|
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<<noQueueBit))) {
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
} else {
|
||||||
|
ret = offLinErr; /* r/w requested for an off-line drive */
|
||||||
|
if (!(pb->ioTrap & (1<<noQueueBit)))
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include "NuBusFPGASDCardDrvr.h"
|
||||||
|
|
||||||
|
#pragma parameter __D0 cNuBusFPGASDCardStatus(__A0, __A1)
|
||||||
|
OSErr cNuBusFPGASDCardStatus(CntrlParamPtr pb, /* DCtlPtr */ AuxDCEPtr dce)
|
||||||
|
{
|
||||||
|
OSErr ret = noErr;
|
||||||
|
struct SDCardContext *ctx;
|
||||||
|
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, 0xDEAD0004); */
|
||||||
|
/* write_reg(dce, GOBOFB_DEBUG, pb->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<<noQueueBit)))
|
||||||
|
IODone((DCtlPtr)dce, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -269,7 +269,8 @@ int main(int argc, char **argv) {
|
||||||
fprintf(fd, "\tOSLstEntry\tsRsrc_GoboFB_R%hux%hu,_sRsrc_GoboFB_R%hux%hu/* video sRsrc List */\n", hres, vres, hres, vres);
|
fprintf(fd, "\tOSLstEntry\tsRsrc_GoboFB_R%hux%hu,_sRsrc_GoboFB_R%hux%hu/* video sRsrc List */\n", hres, vres, hres, vres);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(fd, "\tOSLstEntry\tsRsrc_RAMDsk,_sRsrc_RAMDsk\n");
|
//fprintf(fd, "\tOSLstEntry\tsRsrc_RAMDsk,_sRsrc_RAMDsk\n");
|
||||||
|
fprintf(fd, "\tOSLstEntry\tsRsrc_SDCard,_sRsrc_SDCard\n");
|
||||||
fprintf(fd, "\tOSLstEntry\tsRsrc_HDMIAudio,_sRsrc_HDMIAudio\n");
|
fprintf(fd, "\tOSLstEntry\tsRsrc_HDMIAudio,_sRsrc_HDMIAudio\n");
|
||||||
fprintf(fd, "\tDatLstEntry endOfList, 0\n");
|
fprintf(fd, "\tDatLstEntry endOfList, 0\n");
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,12 @@ SECTIONS {
|
||||||
*(.text.dskdriver_init)
|
*(.text.dskdriver_init)
|
||||||
*(.text.dskdriver)
|
*(.text.dskdriver)
|
||||||
PROVIDE(_RAMDskEnd020Drvr = .);
|
PROVIDE(_RAMDskEnd020Drvr = .);
|
||||||
|
|
||||||
|
PROVIDE(_SDCardDrvrMacOS68020 = .);
|
||||||
|
PROVIDE(entry_SDCardDrvrMacOS68020 = (0x02000000 | ((_SDCardDrvrMacOS68020 - _SDCardDrvrDir) & 0xFFFFFF)));
|
||||||
|
*(.text.sddriver_init)
|
||||||
|
*(.text.sddriver)
|
||||||
|
PROVIDE(_SDCardEnd020Drvr = .);
|
||||||
|
|
||||||
/* and at the end the ROM block, missing only the CRC */
|
/* and at the end the ROM block, missing only the CRC */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
/* from hw/common.h, +a32 */
|
/* from hw/common.h, +a32 */
|
||||||
|
|
||||||
|
#define CONFIG_CSR_DATA_WIDTH 32
|
||||||
|
|
||||||
/* CSR data width (subreg. width) in bytes, for direct comparson to sizeof() */
|
/* CSR data width (subreg. width) in bytes, for direct comparson to sizeof() */
|
||||||
#define CSR_DW_BYTES (CONFIG_CSR_DATA_WIDTH/8)
|
#define CSR_DW_BYTES (CONFIG_CSR_DATA_WIDTH/8)
|
||||||
#define CSR_OFFSET_BYTES 4
|
#define CSR_OFFSET_BYTES 4
|
||||||
|
@ -20,13 +22,13 @@
|
||||||
* | 4 | 1 1 1 1 2 2 2 2 |
|
* | 4 | 1 1 1 1 2 2 2 2 |
|
||||||
* | 8 | 1 1 1 1 1 1 1 1 |
|
* | 8 | 1 1 1 1 1 1 1 1 |
|
||||||
* +-----+-----------------+ */
|
* +-----+-----------------+ */
|
||||||
__attribute__ ((section (".text.primary"))) static inline int num_subregs(int csr_bytes)
|
static inline int num_subregs(int csr_bytes)
|
||||||
{
|
{
|
||||||
return (csr_bytes - 1) / CSR_DW_BYTES + 1;
|
return (csr_bytes - 1) / CSR_DW_BYTES + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a CSR of size 'csr_bytes' located at address 'a'. */
|
/* Read a CSR of size 'csr_bytes' located at address 'a'. */
|
||||||
__attribute__ ((section (".text.primary"))) static inline uint64_t _csr_rd(uint32_t a32, unsigned long a, int csr_bytes)
|
static inline uint64_t _csr_rd(uint32_t a32, unsigned long a, int csr_bytes)
|
||||||
{
|
{
|
||||||
uint64_t r = __builtin_bswap32(*((uint32_t*)(a32 + a)));
|
uint64_t r = __builtin_bswap32(*((uint32_t*)(a32 + a)));
|
||||||
for (int i = 1; i < num_subregs(csr_bytes); i++) {
|
for (int i = 1; i < num_subregs(csr_bytes); i++) {
|
||||||
|
@ -38,7 +40,7 @@ __attribute__ ((section (".text.primary"))) static inline uint64_t _csr_rd(uint3
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write value 'v' to a CSR of size 'csr_bytes' located at address 'a'. */
|
/* Write value 'v' to a CSR of size 'csr_bytes' located at address 'a'. */
|
||||||
__attribute__ ((section (".text.primary"))) static inline void _csr_wr(uint32_t a32, unsigned long a, uint64_t v, int csr_bytes)
|
static inline void _csr_wr(uint32_t a32, unsigned long a, uint64_t v, int csr_bytes)
|
||||||
{
|
{
|
||||||
int ns = num_subregs(csr_bytes);
|
int ns = num_subregs(csr_bytes);
|
||||||
for (int i = 0; i < ns; i++) {
|
for (int i = 0; i < ns; i++) {
|
||||||
|
@ -49,42 +51,42 @@ __attribute__ ((section (".text.primary"))) static inline void _csr_wr(uint32_t
|
||||||
|
|
||||||
// FIXME: - should we provide 24, 40, 48, and 56 bit csr_[rd|wr] methods?
|
// FIXME: - should we provide 24, 40, 48, and 56 bit csr_[rd|wr] methods?
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline uint8_t csr_rd_uint8(uint32_t a32, unsigned long a)
|
static inline uint8_t csr_rd_uint8(uint32_t a32, unsigned long a)
|
||||||
{
|
{
|
||||||
return _csr_rd(a32, a, sizeof(uint8_t));
|
return _csr_rd(a32, a, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_uint8(uint32_t a32, uint8_t v, unsigned long a)
|
static inline void csr_wr_uint8(uint32_t a32, uint8_t v, unsigned long a)
|
||||||
{
|
{
|
||||||
_csr_wr(a32, a, v, sizeof(uint8_t));
|
_csr_wr(a32, a, v, sizeof(uint8_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline uint16_t csr_rd_uint16(uint32_t a32, unsigned long a)
|
static inline uint16_t csr_rd_uint16(uint32_t a32, unsigned long a)
|
||||||
{
|
{
|
||||||
return _csr_rd(a32, a, sizeof(uint16_t));
|
return _csr_rd(a32, a, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_uint16(uint32_t a32, uint16_t v, unsigned long a)
|
static inline void csr_wr_uint16(uint32_t a32, uint16_t v, unsigned long a)
|
||||||
{
|
{
|
||||||
_csr_wr(a32, a, v, sizeof(uint16_t));
|
_csr_wr(a32, a, v, sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline uint32_t csr_rd_uint32(uint32_t a32, unsigned long a)
|
static inline uint32_t csr_rd_uint32(uint32_t a32, unsigned long a)
|
||||||
{
|
{
|
||||||
return _csr_rd(a32, a, sizeof(uint32_t));
|
return _csr_rd(a32, a, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_uint32(uint32_t a32, uint32_t v, unsigned long a)
|
static inline void csr_wr_uint32(uint32_t a32, uint32_t v, unsigned long a)
|
||||||
{
|
{
|
||||||
_csr_wr(a32, a, v, sizeof(uint32_t));
|
_csr_wr(a32, a, v, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline uint64_t csr_rd_uint64(uint32_t a32, unsigned long a)
|
static inline uint64_t csr_rd_uint64(uint32_t a32, unsigned long a)
|
||||||
{
|
{
|
||||||
return _csr_rd(a32, a, sizeof(uint64_t));
|
return _csr_rd(a32, a, sizeof(uint64_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_uint64(uint32_t a32, uint64_t v, unsigned long a)
|
static inline void csr_wr_uint64(uint32_t a32, uint64_t v, unsigned long a)
|
||||||
{
|
{
|
||||||
_csr_wr(a32, a, v, sizeof(uint64_t));
|
_csr_wr(a32, a, v, sizeof(uint64_t));
|
||||||
}
|
}
|
||||||
|
@ -159,34 +161,34 @@ __attribute__ ((section (".text.primary"))) static inline void csr_wr_uint64(uin
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_rd_buf_uint8(uint32_t a32, unsigned long a, uint8_t *buf, int cnt)
|
static inline void csr_rd_buf_uint8(uint32_t a32, unsigned long a, uint8_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_rd_buf(a32, a, buf, cnt);
|
_csr_rd_buf(a32, a, buf, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_buf_uint8(uint32_t a32, unsigned long a,
|
static inline void csr_wr_buf_uint8(uint32_t a32, unsigned long a,
|
||||||
const uint8_t *buf, int cnt)
|
const uint8_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_wr_buf(a32, a, buf, cnt);
|
_csr_wr_buf(a32, a, buf, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_rd_buf_uint16(uint32_t a32, unsigned long a, uint16_t *buf, int cnt)
|
static inline void csr_rd_buf_uint16(uint32_t a32, unsigned long a, uint16_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_rd_buf(a32, a, buf, cnt);
|
_csr_rd_buf(a32, a, buf, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_buf_uint16(uint32_t a32, unsigned long a,
|
static inline void csr_wr_buf_uint16(uint32_t a32, unsigned long a,
|
||||||
const uint16_t *buf, int cnt)
|
const uint16_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_wr_buf(a32, a, buf, cnt);
|
_csr_wr_buf(a32, a, buf, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_rd_buf_uint32(uint32_t a32, unsigned long a, uint32_t *buf, int cnt)
|
static inline void csr_rd_buf_uint32(uint32_t a32, unsigned long a, uint32_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_rd_buf(a32, a, buf, cnt);
|
_csr_rd_buf(a32, a, buf, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__ ((section (".text.primary"))) static inline void csr_wr_buf_uint32(uint32_t a32, unsigned long a,
|
static inline void csr_wr_buf_uint32(uint32_t a32, unsigned long a,
|
||||||
const uint32_t *buf, int cnt)
|
const uint32_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_wr_buf(a32, a, buf, cnt);
|
_csr_wr_buf(a32, a, buf, cnt);
|
||||||
|
@ -196,12 +198,12 @@ __attribute__ ((section (".text.primary"))) static inline void csr_wr_buf_uint32
|
||||||
* about a >= 64bit left shift! */
|
* about a >= 64bit left shift! */
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
|
#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);
|
_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)
|
const uint64_t *buf, int cnt)
|
||||||
{
|
{
|
||||||
_csr_wr_buf(a32, a, buf, cnt);
|
_csr_wr_buf(a32, a, buf, cnt);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
sRsrc_Board = 1 /* board sResource (>0 & <128) */
|
sRsrc_Board = 1 /* board sResource (>0 & <128) */
|
||||||
.include "VidRomDef.s"
|
.include "VidRomDef.s"
|
||||||
sRsrc_RAMDsk = 0x90 /* functional sResources */
|
sRsrc_RAMDsk = 0x90 /* functional sResources */
|
||||||
|
sRsrc_SDCard = 0x91 /* functional sResources */
|
||||||
sRsrc_HDMIAudio = 0xA0 /* functional sResources */
|
sRsrc_HDMIAudio = 0xA0 /* functional sResources */
|
||||||
|
|
||||||
.global DeclROMDir
|
.global DeclROMDir
|
||||||
|
@ -122,7 +123,7 @@ _GoboFBDrvrDir:
|
||||||
|
|
||||||
.section .text.begin
|
.section .text.begin
|
||||||
.include "VidRomRes.s"
|
.include "VidRomRes.s"
|
||||||
|
/* ////////////////////////////////////////////// RAM DISK */
|
||||||
.section .text.begin
|
.section .text.begin
|
||||||
ALIGN 2
|
ALIGN 2
|
||||||
_sRsrc_RAMDsk:
|
_sRsrc_RAMDsk:
|
||||||
|
@ -158,7 +159,44 @@ _RAMDskDrvrDir:
|
||||||
.include "NuBusFPGARAMDskDrvr.s" /* driver code */
|
.include "NuBusFPGARAMDskDrvr.s" /* driver code */
|
||||||
/* _RAMDskEnd020Drvr: */ /* supplied by linker script */
|
/* _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 /* <Category> */
|
||||||
|
.short typeDrive /* custom */ /* <Type> */
|
||||||
|
.short drSwApple /* <DrvrSw> */
|
||||||
|
.short DrHwNuBusFPGASDCard /* <DrvrHw> */
|
||||||
|
|
||||||
|
_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
|
.section .text.begin
|
||||||
ALIGN 2
|
ALIGN 2
|
||||||
_sRsrc_HDMIAudio:
|
_sRsrc_HDMIAudio:
|
||||||
|
|
Loading…
Reference in New Issue