From e02ef0f8d921aaadcbf1a4be8d52c94ee02d8764 Mon Sep 17 00:00:00 2001 From: Zane Kaminski Date: Sat, 22 May 2021 17:40:15 -0400 Subject: [PATCH] idk --- Makefile | 81 ++++++------- entry.s | 34 +++++- rdisk.c | 285 ------------------------------------------- rdisk.h | 195 ------------------------------ rombus.c | 361 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ rombus.h | 179 +++++++++++++++++++++++++++ sdmmc.c | 220 +++++++++++++++++++++++++++++++++ sdmmc.h | 29 +++++ spi.c | 164 +++++++++++++++++++++++++ spi.h | 17 +++ xfer.h | 11 ++ xfer.s | 34 ++++++ 12 files changed, 1078 insertions(+), 532 deletions(-) delete mode 100644 rdisk.c delete mode 100644 rdisk.h create mode 100644 rombus.c create mode 100644 rombus.h create mode 100644 sdmmc.c create mode 100644 sdmmc.h create mode 100644 spi.c create mode 100644 spi.h create mode 100644 xfer.h create mode 100644 xfer.s diff --git a/Makefile b/Makefile index dcb2124..b5f5fcd 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,15 @@ # path to RETRO68 -RETRO68=/Users/zane/Retro68-build/toolchain +RETRO68=~/Retro68-build/toolchain -PREFIX=$(RETRO68)/m68k-apple-macos -AS=$(RETRO68)/bin/m68k-apple-macos-as -CC=$(RETRO68)/bin/m68k-apple-macos-gcc -LD=$(RETRO68)/bin/m68k-apple-macos-ld -OBJCOPY=$(RETRO68)/bin/m68k-apple-macos-objcopy -OBJDUMP=$(RETRO68)/bin/m68k-apple-macos-objdump +PREFIX=$(RETRO68)/bin/m68k-apple-macos +AS=$(PREFIX)-as +CC=$(PREFIX)-gcc +LD=$(PREFIX)-ld +OBJCOPY=$(PREFIX)-objcopy +OBJDUMP=$(PREFIX)-objdump +CFLAGS=-march=68030 -c -Os -all: bin/rom16M_swap.bin obj/rdisk1M5.s obj/rdisk7M5.s obj/driver1M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym +all: bin/rom16M_swap.bin obj/rdisk7M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym obj: mkdir obj @@ -24,56 +25,42 @@ obj/entry_rel.sym: obj obj/entry.o $(OBJDUMP) -t obj/entry.o > $@ -obj/rdisk1M5.o: rdisk.c obj - $(CC) -DRDiskSize=1572864 -c -Os $< -o $@ - obj/rdisk7M5.o: rdisk.c obj - $(CC) -DRDiskSize=7864320 -c -Os $< -o $@ - -obj/rdisk1M5.s: obj obj/rdisk1M5.o - $(OBJDUMP) -d obj/rdisk1M5.o > $@ + $(CC) -Wall -DRDiskSize=7864320 $(CFLAGS) $< -o $@ obj/rdisk7M5.s: obj obj/rdisk7M5.o - $(OBJDUMP) -d obj/rdisk1M5.o > $@ + $(OBJDUMP) -d obj/rdisk7M5.o > $@ + + +obj/spi.o: spi.c obj + $(CC) -Wall $(CFLAGS) $< -o $@ + +obj/spi.s: obj obj/spi.o + $(OBJDUMP) -d obj/spi.o > $@ + + +obj/sdmmc.o: sdmmc.c obj + $(CC) -Wall $(CFLAGS) -Os $< -o $@ + +obj/sdmmc.s: obj obj/sdmmc.o + $(OBJDUMP) -d obj/sdmmc.o > $@ -obj/driver1M5.o: obj obj/entry.o obj/rdisk1M5.o - $(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk1M5.o obj/driver7M5.o: obj obj/entry.o obj/rdisk7M5.o - $(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk7M5.o - -obj/driver1M5.s: obj obj/driver1M5.o - $(OBJDUMP) -d obj/driver1M5.o > $@ + $(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rdisk7M5.o obj/spi.o obj/sdmmc.o obj/driver7M5.s: obj obj/driver7M5.o $(OBJDUMP) -d obj/driver7M5.o > $@ -obj/driver_abs.sym: obj obj/driver1M5.o - $(OBJDUMP) -t obj/driver1M5.o > $@ +obj/driver_abs.sym: obj obj/driver7M5.o + $(OBJDUMP) -t obj/driver7M5.o > $@ -bin/driver1M5.bin: bin obj/driver1M5.o - $(OBJCOPY) -O binary obj/driver1M5.o $@ - bin/driver7M5.bin: bin obj/driver7M5.o $(OBJCOPY) -O binary obj/driver7M5.o $@ - -bin/rom2M.bin: baserom.bin RDisk1M5.dsk bin bin/driver1M5.bin obj/driver_abs.sym obj/entry_rel.sym - cp baserom.bin $@ # Copy base rom - # Patch driver - dd if=bin/driver1M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code - printf '\x78' | dd of=$@ bs=1 seek=335168 count=1 conv=notrunc # Set resource flags - printf '\x4F' | dd of=$@ bs=1 seek=335216 count=1 conv=notrunc # Set driver flags - cat obj/entry_rel.sym | grep "DOpen" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335224 count=2 conv=notrunc - cat obj/entry_rel.sym | grep "DPrime" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335226 count=2 conv=notrunc - cat obj/entry_rel.sym | grep "DControl" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335228 count=2 conv=notrunc - cat obj/entry_rel.sym | grep "DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc - cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc - dd if=RDisk1M5.dsk of=$@ bs=1024 seek=512 count=1536 conv=notrunc # copy disk image - -bin/rom8M.bin: baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym obj/entry_rel.sym +bin/rom8M.bin: bin baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym obj/entry_rel.sym cp baserom.bin $@ # Copy base rom # Patch driver dd if=bin/driver7M5.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code @@ -86,15 +73,15 @@ bin/rom8M.bin: baserom.bin RDisk7M5.dsk bin bin/driver7M5.bin obj/driver_abs.sym cat obj/entry_rel.sym | grep "DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc dd if=RDisk7M5.dsk of=$@ bs=1024 seek=512 count=7680 conv=notrunc # copy disk image -bin/rom8M_swap.bin: bin/rom8M.bin +bin/rom8M_swap.bin: bin bin/rom8M.bin dd if=bin/rom8M.bin of=$@ conv=swab # swap bytes -bin/rom2M_swap.bin: bin/rom2M.bin - dd if=bin/rom2M.bin of=$@ conv=swab # swap bytes +bin/iisi_swap.bin: bin iisi.bin + dd if=iisi.bin of=$@ conv=swab # swap bytes -bin/rom16M_swap.bin: bin/rom2M_swap.bin bin/rom8M_swap.bin +bin/rom16M_swap.bin: bin/iisi_swap.bin bin/rom8M_swap.bin cat bin/rom8M_swap.bin > $@ - cat bin/rom2M_swap.bin >> $@ + cat bin/iisi_swap.bin >> $@ .PHONY: clean diff --git a/entry.s b/entry.s index a64a11b..ea864cf 100644 --- a/entry.s +++ b/entry.s @@ -4,33 +4,57 @@ .EQU kioResult, 16 .EQU kcsCode, 26 .EQU JIODone, 0x08FC +.GLOBAL RDiskSig +.GLOBAL RDiskDBGNamePos +.GLOBAL RDiskDBGDisPos +.GLOBAL RDiskDBGDisByte +.GLOBAL RDiskCDRNamePos +.GLOBAL RDiskCDRDisPos +.GLOBAL RDiskCDRDisByte dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000 dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000 + +RDiskSig: .ascii "\5RDisk\0" .align 4 +RDiskDBGDisPos: +dc.l 0x00000031 +RDiskCDRDisPos: +dc.l 0x00012CAF +RDiskDBGNameAddr: +dc.l 0x4088002A +RDiskCDRNameAddr: +dc.l 0x40892C96 +RDiskDBGDisByte: +dc.b 0x44 +RDiskCDRDisByte: +dc.b 0x44 +RDiskRAMRequired: +.ascii "16" +.align 4 DOpen: movem.l %A0-%A1, -(%SP) - bsr RDiskOpen + bsr RDOpen movem.l (%SP)+, %A0-%A1 rts DClose: movem.l %A0-%A1, -(%SP) - bsr RDiskClose + bsr RDClose movem.l (%SP)+, %A0-%A1 rts DPrime: movem.l %A0-%A1, -(%SP) - bsr RDiskPrime + bsr RDPrime movem.l (%SP)+, %A0-%A1 bra.b IOReturn DControl: movem.l %A0-%A1, -(%SP) - bsr RDiskControl + bsr RDCtl movem.l (%SP)+, %A0-%A1 cmpi.w #killCode, kcsCode(%A0) bne.b IOReturn @@ -38,7 +62,7 @@ DControl: DStatus: movem.l %A0-%A1, -(%SP) - bsr RDiskStatus + bsr RDStat movem.l (%SP)+, %A0-%A1 IOReturn: diff --git a/rdisk.c b/rdisk.c deleted file mode 100644 index 3a55e8b..0000000 --- a/rdisk.c +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "rdisk.h" - -// Decode keyboard/PRAM settings -static void RDiskDecodeSettings(RDiskStorage_t *c, Ptr unmount, Ptr mount, Ptr ram) { - // Decode settings - if (RDiskIsRPressed()) { // R boots from ROM disk - *unmount = 0; // Don't unmount so we boot from this drive - *mount = 0; // No need to mount later since we are boot disk - *ram = RDiskIsAPressed(); // A enables RAM disk - } else { - // Read PRAM - char legacy_startup, legacy_ram; - RDiskReadXPRAM(1, 4, &legacy_startup); - RDiskReadXPRAM(1, 5, &legacy_ram); - if (legacy_startup & 1) { // Boot from ROM disk - *unmount = 0; // Don't unmount so we boot from this drive - *mount = 0; // No need to mount later since we are boot disk - *ram = legacy_ram & 1; - } else if (legacy_startup & 2) { // Mount ROM disk - *unmount = 1; // Unmount to not boot from our disk - *mount = 1; // Mount in accRun - *ram = legacy_ram & 1; - } else { - *unmount = 1; // Unmount - *mount = 0; // Don't mount again - *ram = 0; // Don't allocate RAM disk - } - } -} - -// Switch to 32-bit mode and copy -#pragma parameter RDiskCopy24(__A0, __A1, __D0) -void RDiskCopy24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) { - char mode = true32b; - SwapMMUMode(&mode); - BlockMove(sourcePtr, destPtr, byteCount); - SwapMMUMode(&mode); -} - -// Figure out the first available drive number >= 5 -static int RDiskFindDrvNum() { - DrvQElPtr dq; - int drvNum = 5; - for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) { - if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; } - } - return drvNum; -} - -#pragma parameter __D0 RDiskOpen(__A0, __A1) -OSErr RDiskOpen(IOParamPtr p, DCtlPtr d) { - int drvNum; - RDiskStorage_t *c; - char legacy_startup, legacy_ram; - - // Do nothing if already opened - if (d->dCtlStorage) { return noErr; } - - // Do nothing if inhibited - RDiskReadXPRAM(1, 4, &legacy_startup); - RDiskReadXPRAM(1, 5, &legacy_ram); - if ((legacy_startup & 0x07) == 0x04) { return noErr; } - - // Allocate storage struct - d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t)); - if (!d->dCtlStorage) { return openErr; } - - // Lock our storage struct and get master pointer - HLock(d->dCtlStorage); - c = *(RDiskStorage_t**)d->dCtlStorage; - - // Find first available drive number - drvNum = RDiskFindDrvNum(); - - // Set drive status - //c->status.track = 0; - c->status.writeProt = -1; // nonzero is write protected - c->status.diskInPlace = 8; // 8 is nonejectable disk - c->status.installed = 1; // drive installed - //c->status.sides = 0; - //c->status.qType = 1; - c->status.dQDrive = drvNum; - //c->status.dQFSID = 0; - c->status.dQRefNum = d->dCtlRefNum; - c->status.driveSize = RDiskSize / 512; - //c->status.driveS1 = (RDiskSize / 512) >> 16; - - // Decompress icon - #ifdef RDISK_COMPRESS_ICON_ENABLE - char *src = &RDiskIconCompressed[0]; - char *dst = &c->icon[0]; - UnpackBits(&src, &dst, RDISK_ICON_SIZE); - #endif - - // Add drive to drive queue and return - RDiskAddDrive(c->status.dQRefNum, drvNum, (DrvQElPtr)&c->status.qLink); - return noErr; -} - -// Init is called at beginning of first prime (read/write) call -static void RDiskInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) { - char unmountEN, mountEN, ramEN; - // Mark init done - c->initialized = 1; - // Decode settings - RDiskDecodeSettings(c, &unmountEN, &mountEN, &ramEN); - - // If RAM disk enabled, try to allocate RAM disk buffer if not already - if (ramEN & !c->ramdisk) { - if (*MMU32bit) { // 32-bit mode - unsigned long minBufPtr, newBufPtr; - // Compute if there is enough high memory - minBufPtr = ((unsigned long)*MemTop / 2) + 1024; - newBufPtr = (unsigned long)*BufPtr - RDiskSize; - if (newBufPtr > minBufPtr && (unsigned long)*BufPtr > newBufPtr) { - // Allocate RAM disk buffer by lowering BufPtr - *BufPtr = (Ptr)newBufPtr; - // Set RAM disk buffer pointer. - c->ramdisk = *BufPtr; - // Copy ROM disk image to RAM disk - BlockMove(RDiskBuf, c->ramdisk, RDiskSize); - // Clearing write protect marks RAM disk enabled - c->status.writeProt = 0; - } - } else { // 24-bit mode - // Put RAM disk just past 8MB - c->ramdisk = (Ptr)(8 * 1024 * 1024); - // Copy ROM disk image to RAM disk - copy24(RDiskBuf, c->ramdisk, RDiskSize); - // Clearing write protect marks RAM disk enabled - c->status.writeProt = 0; - //FIXME: what if we don't have enough RAM? - // Will this wrap around and overwrite low memory? - // That's not the worst, since the system would just crash, - // but it would be better to switch to read-only status - } - } - - // Unmount if not booting from ROM disk - if (unmountEN) { c->status.diskInPlace = 0; } - - // If mount enabled, enable accRun to post disk inserted event later - if (mountEN) { - d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.) - d->dCtlFlags |= dNeedTimeMask; // Enable accRun - } -} - -#pragma parameter __D0 RDiskPrime(__A0, __A1) -OSErr RDiskPrime(IOParamPtr p, DCtlPtr d) { - RDiskStorage_t *c; - char cmd; - Ptr disk; - - // Return disk offline error if dCtlStorage null - if (!d->dCtlStorage) { return notOpenErr; } - // Dereference dCtlStorage to get pointer to our context - c = *(RDiskStorage_t**)d->dCtlStorage; - - // Initialize if this is the first prime call - if (!c->initialized) { RDiskInit(p, d, c); } - - // Return disk offline error if virtual disk not inserted - if (!c->status.diskInPlace) { return offLinErr; } - - // Get pointer to RAM or ROM disk buffer - disk = (c->ramdisk ? c->ramdisk : RDiskBuf) + d->dCtlPosition; - // Bounds checking - if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize || - d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; } - - // Service read or write request - cmd = p->ioTrap & 0x00FF; - if (cmd == aRdCmd) { // Read - // Read from disk into buffer. - if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); } - else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); } - } else if (cmd == aWrCmd) { // Write - // Fail if write protected or RAM disk buffer not set up - if (c->status.writeProt || !c->ramdisk) { return wPrErr; } - // Write from buffer into disk. - if (*MMU32bit) { BlockMove(p->ioBuffer, disk, p->ioReqCount); } - else { copy24(StripAddress(p->ioBuffer), disk, p->ioReqCount); } - } else { return noErr; } //FIXME: Fail if cmd isn't read or write? - - // Update count and position/offset, then return - d->dCtlPosition += p->ioReqCount; - p->ioActCount = p->ioReqCount; - return noErr; -} - -#pragma parameter __D0 RDiskControl(__A0, __A1) -OSErr RDiskControl(CntrlParamPtr p, DCtlPtr d) { - RDiskStorage_t *c; - // Fail if dCtlStorage null - if (!d->dCtlStorage) { return notOpenErr; } - // Dereference dCtlStorage to get pointer to our context - c = *(RDiskStorage_t**)d->dCtlStorage; - // Handle control request based on csCode - switch (p->csCode) { - case killCode: - return noErr; - case kFormat: - if (!c->status.diskInPlace || c->status.writeProt || - !c->ramdisk) { return controlErr; } - long zero[32]; - for (int i = 0; i < 32; i++) { zero[i] = 0; } - for (int i = 0; i < 32; i++) { - copy24((Ptr)zero, c->ramdisk + i * sizeof(zero), sizeof(zero)); - } - return noErr; - case kVerify: - if (!c->status.diskInPlace) { return controlErr; } - return noErr; - case kEject: - // "Reinsert" disk if ejected illegally - if (c->status.diskInPlace) { - PostEvent(diskEvt, c->status.dQDrive); - } - return controlErr; // Eject not allowed so return error - case accRun: - d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun - c->status.diskInPlace = 8; // 8 is nonejectable disk - PostEvent(diskEvt, c->status.dQDrive); // Post disk inserted event - return noErr; - case kDriveIcon: case kMediaIcon: // Get icon - #ifdef RDISK_COMPRESS_ICON_ENABLE - *(Ptr*)p->csParam = (Ptr)c->icon; - #else - *(Ptr*)p->csParam = (Ptr)RDiskIcon; - #endif - return noErr; - case kDriveInfo: - // high word (bytes 2 & 3) clear - // byte 1 = primary + fixed media + internal - // byte 0 = drive type (0x10 is RAM disk) / (0x11 is ROM disk) - if (c->status.writeProt) { *(long*)p->csParam = 0x00000410; } - else { *(long*)p->csParam = 0x00000411; } - return noErr; - case 24: // Return SCSI partition size - *(long*)p->csParam = RDiskSize / 512; - return noErr; - case 2351: // Post-boot - c->initialized = 1; // Skip initialization - d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.) - d->dCtlFlags |= dNeedTimeMask; // Enable accRun - return noErr; - default: return controlErr; - } -} - -#pragma parameter __D0 RDiskStatus(__A0, __A1) -OSErr RDiskStatus(CntrlParamPtr p, DCtlPtr d) { - RDiskStorage_t *c; - // Fail if dCtlStorage null - if (!d->dCtlStorage) { return notOpenErr; } - // Dereference dCtlStorage to get pointer to our context - c = *(RDiskStorage_t**)d->dCtlStorage; - // Handle status request based on csCode - switch (p->csCode) { - case kDriveStatus: - BlockMove(*d->dCtlStorage, &p->csParam, sizeof(DrvSts2)); - return noErr; - default: return statusErr; - } -} - -#pragma parameter __D0 RDiskClose(__A0, __A1) -OSErr RDiskClose(IOParamPtr p, DCtlPtr d) { - // If dCtlStorage not null, dispose of it - if (!d->dCtlStorage) { return noErr; } - RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage; - HUnlock(d->dCtlStorage); - DisposeHandle(d->dCtlStorage); - d->dCtlStorage = NULL; - return noErr; -} diff --git a/rdisk.h b/rdisk.h deleted file mode 100644 index 689ee88..0000000 --- a/rdisk.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef RDISK_H -#define RDISK_H - -//#define RDiskSize (0x00180000L) -#define RDiskBuf ((char*)0x40880000) -#define BufPtr ((Ptr*)0x10C) -#define MemTop ((Ptr*)0x108) -#define MMU32bit ((char*)0xCB2) - -#pragma parameter __D0 RDiskReadXPRAM(__D0, __D1, __A0) -OSErr RDiskReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051}; - -#pragma parameter __D0 RDiskAddDrive(__D1, __D0, __A0) -OSErr RDiskAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E}; - -static inline char RDiskIsRPressed() { return *((char*)0x175) & 0x80; } -static inline char RDiskIsAPressed() { return *((char*)0x174) & 0x01; } - -typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long); -#define copy24(s, d, b) { RDiskCopy_t copy24 = (RDiskCopy_t)RDiskCopy24; copy24(s, d, b); } - -//#define RDISK_COMPRESS_ICON_ENABLE -#define RDISK_ICON_SIZE (285) -typedef struct RDiskStorage_s { - DrvSts2 status; - char initialized; - Ptr ramdisk; - #ifdef RDISK_COMPRESS_ICON_ENABLE - char icon[RDISK_ICON_SIZE]; - #endif -} RDiskStorage_t; - -#define PackBits_Repeat(count) (-1 * (count - 1)) -#define PackBits_Literal(count) (count - 1) - -#define RDISK_COMPRESSED_ICON_SIZE (87) -#ifdef RDISK_COMPRESS_ICON_ENABLE -#include -const char const RDiskIconCompressed[RDISK_COMPRESSED_ICON_SIZE] = { - PackBits_Repeat(76), 0b00000000, /* - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, */ - PackBits_Repeat(4), 0b11111111, /* - 0b11111111, 0b11111111, 0b11111111, 0b11111111, */ - PackBits_Literal(36), - 0b10000000, 0b00000000, 0b00000000, 0b00000001, - 0b10001111, 0b00011110, 0b00111100, 0b01111001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001111, 0b00011110, 0b00111100, 0b01111001, - 0b11000000, 0b00000000, 0b00000000, 0b00000001, - 0b01010101, 0b01010101, 0b11010101, 0b01010101, - 0b01111111, 0b11111111, 0b01111111, 0b11111111, - PackBits_Repeat(12), 0b00000000, /* - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, */ - - PackBits_Repeat(76), 0b00000000, /* - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, */ - PackBits_Repeat(32), 0b11111111, /* - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, */ - PackBits_Literal(1), 0b01111111, - PackBits_Repeat(3), 0b11111111, /* - 0b01111111, 0b11111111, 0b11111111, 0b11111111, */ - PackBits_Literal(1), 0b01111111, - PackBits_Repeat(3), 0b11111111, /* - 0b01111111, 0b11111111, 0b11111111, 0b11111111, */ - PackBits_Repeat(12), 0b00000000, /* - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, */ - PackBits_Literal(29), - 27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ', - 'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ', - 'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0 -}; -#else -const char const RDiskIcon[RDISK_ICON_SIZE] = { - // Icon - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b10000000, 0b00000000, 0b00000000, 0b00000001, - 0b10001111, 0b00011110, 0b00111100, 0b01111001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001001, 0b00010010, 0b00100100, 0b01001001, - 0b10001111, 0b00011110, 0b00111100, 0b01111001, - 0b11000000, 0b00000000, 0b00000000, 0b00000001, - 0b01010101, 0b01010101, 0b11010101, 0b01010101, - 0b01111111, 0b11111111, 0b01111111, 0b11111111, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - // Mask - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b11111111, 0b11111111, 0b11111111, 0b11111111, - 0b01111111, 0b11111111, 0b11111111, 0b11111111, - 0b01111111, 0b11111111, 0b11111111, 0b11111111, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 0b00000000, 0b00000000, 0b00000000, 0b00000000, - 27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ', - 'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ', - 'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0 -}; -#endif - -#endif diff --git a/rombus.c b/rombus.c new file mode 100644 index 0000000..7a295ab --- /dev/null +++ b/rombus.c @@ -0,0 +1,361 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "rdisk.h" + +// Decode keyboard/PRAM settings +static void RDDecodeSettings(Ptr recoveryEN, Ptr unmountEN, Ptr mountEN) { + // Read PRAM + char legacy_startup; + RBReadXPRAM(1, 4, &legacy_startup); + + // Decode settings: boot from recovery, unmount (don't boot), mount (after boot) + if (RBIsRPressed()) { // R boots from ROM recovery + *recoveryEN = 1; // Enable recovery partition + *unmountEN = 0; // Unmount SD so we don't boot from it + *mountEN = 1; // Mount SD later + } else { + *recoveryEN = 0; // Disable recovery partition + if (legacy_startup & 0x10) { // Boot from SD disk + *unmountEN = 0; // Don't unmount so we boot from this drive + *mountEN = 0; // No need to mount later since we are boot disk + } else if (legacy_startup & 0x20) { // Mount SD disk under other boot volume + *unmountEN = 1; // Unmount to not boot from our disk + *mountEN = 1; // Mount in accRun + } else { + *unmountEN = 1; // Unmount + *mountEN = 0; // Don't mount again + } + } +} + +// Switch to 32-bit mode and copy +#pragma parameter C24(__A0, __A1, __D0) +void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) { + signed char mode = true32b; + SwapMMUMode(&mode); + BlockMove(sourcePtr, destPtr, byteCount); + SwapMMUMode(&mode); +} + +// Switch to 32-bit mode and get +#pragma parameter __D0 G24(__A2) +char __attribute__ ((noinline)) G24(Ptr pos) { + long ret; + signed char mode = true32b; + SwapMMUMode(&mode); + ret = *pos; // Peek + SwapMMUMode(&mode); + return ret; +} + +// Switch to 32-bit mode and set +#pragma parameter S24(__A2, __D3) +void __attribute__ ((noinline)) S24(Ptr pos, char patch) { + signed char mode = true32b; + SwapMMUMode(&mode); + *pos = patch; // Poke + SwapMMUMode(&mode); +} + +// Figure out the first available drive number >= 5 +static int RBFindDrvNum() { + DrvQElPtr dq; + int drvNum = 5; + for (dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) { + if (dq->dQDrive >= drvNum) { drvNum = dq->dQDrive + 1; } + } + return drvNum; +} + +static void RBOpenRDisk(RDiskStorage_t *c) { + int drvNum; + + // Find first available drive number for ROM recovery + drvNum = RBFindDrvNum(); + + // Set ROM recovery drive status + //c->rStatus.track = 0; + c->rStatus.writeProt = -1; // nonzero is write protected + c->rStatus.diskInPlace = 8; // 8 is nonejectable disk + c->rStatus.installed = 1; // drive installed + //c->rStatus.sides = 0; + //c->rStatus.qType = 1; + c->rStatus.dQDrive = drvNum; + //c->rStatus.dQFSID = 0; + c->rStatus.dQRefNum = d->dCtlRefNum; + c->rStatus.driveSize = RDiskSize / 512; + //c->rStatus.driveS1 = (RDiskSize / 512) >> 16; + + // Decompress icon + #ifdef RDISK_COMPRESS_ICON_ENABLE + char *src = &RDiskIconCompressed[0]; + char *dst = &c->rIcon[0]; + UnpackBits(&src, &dst, RDISK_ICON_SIZE); + #endif + + // Add RDisk to drive queue and return + RDiskAddDrive(c->rStatus.dQRefNum, drvNum, (DrvQElPtr)&c->rStatus.qLink); +} + +static void RBOpenSDisk(RDiskStorage_t *c) { + int drvNum; + + // Find first available drive number for SD disk + drvNum = RBFindDrvNum(); + + // Set SD disk drive status + //c->rStatus.track = 0; + c->rStatus.writeProt = 0; // 0 is writable + c->rStatus.diskInPlace = 8; // 8 is nonejectable disk + c->rStatus.installed = 1; // drive installed + //c->rStatus.sides = 0; + c->rStatus.qType = 1; + c->rStatus.dQDrive = drvNum; + //c->rStatus.dQFSID = 0; + c->rStatus.dQRefNum = d->dCtlRefNum; + c->rStatus.driveSize = SDiskSize / 512; + c->rStatus.driveS1 = (SDiskSize / 512) >> 16; + + // Decompress icon + #ifdef SDISK_COMPRESS_ICON_ENABLE + char *src = &SDiskIconCompressed[0]; + char *dst = &c->sIcon[0]; + UnpackBits(&src, &dst, SDISK_ICON_SIZE); + #endif + + // Add SDisk to drive queue and return + RDiskAddDrive(c->rstatus.dQRefNum, drvNum, (DrvQElPtr)&c->sStatus.qLink); +} + +#pragma parameter __D0 RBOpen(__A0, __A1) +OSErr RBOpen(IOParamPtr p, DCtlPtr d) { + RDiskStorage_t *c; + char legacy_startup; + + // Do nothing if already opened + if (d->dCtlStorage) { return noErr; } + + // Do nothing if inhibited + RBReadXPRAM(1, 4, &legacy_startup); + if (legacy_startup & 0x40) { return noErr; } + + // Allocate storage struct + d->dCtlStorage = NewHandleSysClear(sizeof(RDiskStorage_t)); + if (!d->dCtlStorage) { return openErr; } + + // Lock our storage struct and get master pointer + HLock(d->dCtlStorage); + c = *(RDiskStorage_t**)d->dCtlStorage; + + // Create RDisk and SDisk entries in drive queue, then return + RBOpenRDisk(c); + RBOpenSDisk(c); + return noErr; +} + +// Init is called at beginning of first prime (read/write) call +static void RBInit(IOParamPtr p, DCtlPtr d, RDiskStorage_t *c) { + char recoveryEN, unmountEN, mountEN; + // Mark init done + c->initialized = 1; + // Decode settings + RDDecodeSettings(&recoveryEN, &unmountEN, &mountEN); + + // Unmount if not booting from ROM disk + if (!recoveryEN) { c->rStatus.diskInPlace = 0; } + + // Unmount if not booting from ROM disk + if (unmountEN) { c->SStatus.diskInPlace = 0; } + + // If mount enabled, enable accRun to post disk inserted event later + if (mountEN) { + d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.) + d->dCtlFlags |= dNeedTimeMask; // Enable accRun + } +} + +static OSErr RDPrime(IOParamPtr p, DCtlPtr d) { + // Get pointer to correct position in ROM disk buffer + Ptr disk = RDiskBuf + d->dCtlPosition; + + // Return disk offline error if virtual disk not inserted + if (!c->rStatus.diskInPlace) { return offLinErr; } + + // Bounds checking + if (d->dCtlPosition >= RDiskSize || p->ioReqCount >= RDiskSize || + d->dCtlPosition + p->ioReqCount >= RDiskSize) { return paramErr; } + + // Service read or write request + cmd = p->ioTrap & 0x00FF; + if (cmd == aRdCmd) { + if (*MMU32bit) { BlockMove(disk, p->ioBuffer, p->ioReqCount); } + else { copy24(disk, StripAddress(p->ioBuffer), p->ioReqCount); } + } else if (cmd == aWrCmd) { return wPrErr; + } else { return noErr; } //FIXME: Fail if cmd isn't read or write? + + // Update count and position/offset, then return + d->dCtlPosition += p->ioReqCount; + p->ioActCount = p->ioReqCount; + return noErr; +} + +static OSErr SDPrime(IOParamPtr p, DCtlPtr d) { + +} + +#pragma parameter __D0 RBPrime(__A0, __A1) +OSErr RBPrime(IOParamPtr p, DCtlPtr d) { + RDiskStorage_t *c; + char cmd; + + // Return disk offline error if dCtlStorage null + if (!d->dCtlStorage) { return notOpenErr; } + // Dereference dCtlStorage to get pointer to our context + c = *(RDiskStorage_t**)d->dCtlStorage; + + // Initialize if this is the first prime call + if (!c->initialized) { RBInit(p, d, c); } + + if (p->ioVRefNum == c->sStatus.dQDrive) { + return SDPrime(p, d, c); + } else if (p->ioVRefNum == c->rStatus.dQDrive) { + return RDPrime(p, d, c); + } else { return nsvErr; } +} + +static OSErr RDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) { + // Handle control request based on csCode + switch (p->csCode) { + case kFormat: return controlErr; + case kVerify: + if (!c->rStatus.diskInPlace) { return controlErr; } + return noErr; + case kEject: + // "Reinsert" disk if ejected illegally + if (c->rStatus.diskInPlace) { + PostEvent(diskEvt, c->status.dQDrive); + } + return controlErr; // Eject not allowed so return error + case kDriveIcon: case kMediaIcon: // Get icon + #ifdef RDISK_COMPRESS_ICON_ENABLE + *(Ptr*)p->csParam = (Ptr)c->rIcon; + #else + *(Ptr*)p->csParam = (Ptr)RDiskIcon; + #endif + return noErr; + case kDriveInfo: + // high word (bytes 2 & 3) clear + // byte 1 = primary + fixed media + internal + // byte 0 = drive type (0x11 is ROM disk) + *(long*)p->csParam = 0x00000411; + return noErr; + case 24: // Return SCSI partition size + *(long*)p->csParam = RDiskSize / 512; + return noErr; + default: return controlErr; + } +} + +static OSErr SDCtl(CntrlParamPtr p, DCtlPtr d, RDiskStorage_t *c) { + // Handle control request based on csCode + switch (p->csCode) { + case kFormat: + // FIXME: implement SD format + return controlErr; + case kVerify: + // FIXME: implement SD verify + return noErr; + case kEject: + // "Reinsert" disk if ejected illegally + if (c->sStatus.diskInPlace) { + PostEvent(diskEvt, c->sStatus.dQDrive); + } + return controlErr; // Eject not allowed so return error + case kDriveIcon: case kMediaIcon: // Get icon + #ifdef SDISK_COMPRESS_ICON_ENABLE + *(Ptr*)p->csParam = (Ptr)c->sIcon; + #else + *(Ptr*)p->csParam = (Ptr)SDiskIcon; + #endif + return noErr; + case kDriveInfo: + // high word (bytes 2 & 3) clear + // byte 1 = primary + fixed media + internal + // byte 0 = drive type (0x01 is unspecified drive) + *(long*)p->csParam = 0x00000401; + return noErr; + case 24: // Return SCSI partition size + *(long*)p->csParam = SDiskSize / 512; + return noErr; + default: return controlErr; + } +} + +#pragma parameter __D0 RBCtl(__A0, __A1) +OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) { + RDiskStorage_t *c; + // Fail if dCtlStorage null + if (!d->dCtlStorage) { return notOpenErr; } + // Dereference dCtlStorage to get pointer to our context + c = *(RDiskStorage_t**)d->dCtlStorage; + // Handle control request based on csCode + switch (p->csCode) { + case killCode: + return noErr; + case accRun: + d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun + c->sStatus.diskInPlace = 8; // 8 is nonejectable disk + PostEvent(diskEvt, c->sStatus.dQDrive); // Post disk inserted event + return noErr; + case 2351: // Post-boot + c->initialized = 1; // Skip initialization + d->dCtlDelay = 30; // Set accRun delay (30 ticks is 0.5 sec.) + d->dCtlFlags |= dNeedTimeMask; // Enable accRun + return noErr; + } + + // Otherwise, dispatch to correct drive + if (p->ioVRefNum == c->sStatus.dQDrive) { + return SDCtl(p, d, c); + } else if (p->ioVRefNum == c->rStatus.dQDrive) { + return RDCtl(p, d, c); + } else { return nsvErr; } +} + +#pragma parameter __D0 RBStat(__A0, __A1) +OSErr RBStat(CntrlParamPtr p, DCtlPtr d) { + RDiskStorage_t *c; + // Fail if dCtlStorage null + if (!d->dCtlStorage) { return notOpenErr; } + // Dereference dCtlStorage to get pointer to our context + c = *(RDiskStorage_t**)d->dCtlStorage; + // Handle status request based on csCode + switch (p->csCode) { + case kDriveStatus: + // Otherwise, copy correct drive status + if (p->ioVRefNum == c->sStatus.dQDrive) { + BlockMove(&c->sStatus, &p->csParam, sizeof(DrvSts2)); + } else if (p->ioVRefNum == c->rStatus.dQDrive) { + BlockMove(&c->rStatus, &p->csParam, sizeof(DrvSts2)); + } else { return nsvErr; } + return noErr; + default: return statusErr; + } +} + +#pragma parameter __D0 RBClose(__A0, __A1) +OSErr RBClose(IOParamPtr p, DCtlPtr d) { + // If dCtlStorage not null, dispose of it + if (!d->dCtlStorage) { return noErr; } + //RDiskStorage_t *c = *(RDiskStorage_t**)d->dCtlStorage; + HUnlock(d->dCtlStorage); + DisposeHandle(d->dCtlStorage); + d->dCtlStorage = NULL; + return noErr; +} diff --git a/rombus.h b/rombus.h new file mode 100644 index 0000000..0e02990 --- /dev/null +++ b/rombus.h @@ -0,0 +1,179 @@ +#ifndef ROMBUS_H +#define ROMBUS_H + +#define RDiskBuf ((char*)0x408C0000) +#define SDiskSize (0x80000000L) +#define BufPtr ((Ptr*)0x10C) +#define MemTop ((Ptr*)0x108) +#define MMU32bit ((char*)0xCB2) + +#pragma parameter __D0 RBReadXPRAM(__D0, __D1, __A0) +OSErr RBReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051}; + +#pragma parameter __D0 RBAddDrive(__D1, __D0, __A0) +OSErr RBAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E}; + +static inline char RBIsRPressed() { return *((char*)0x175) & 0x80; } + +typedef struct RBStorage_s { + DrvSts2 sStatus; + DrvSts2 rStatus; + char initialized; +} RBStorage_t; + +typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long); +#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); } + +typedef char (*RDiskPeek_t)(Ptr); +#define peek24(a, d) { RDiskPeek_t f = G24; d = f(a); } + +typedef void (*RDiskPoke_t)(Ptr, char); +#define poke24(a, d) { RDiskPoke_t f = S24; f(a, d); } + +#define RDISK_ICON_SIZE (285) +const char RDiskIcon[RDISK_ICON_SIZE] = { + // Icon + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b10000000, 0b00000000, 0b00000000, 0b00000001, + 0b10001111, 0b00011110, 0b00111100, 0b01111001, + 0b10001001, 0b00010010, 0b00100100, 0b01001001, + 0b10001001, 0b00010010, 0b00100100, 0b01001001, + 0b10001001, 0b00010010, 0b00100100, 0b01001001, + 0b10001111, 0b00011110, 0b00111100, 0b01111001, + 0b11000000, 0b00000000, 0b00000000, 0b00000001, + 0b01010101, 0b01010101, 0b11010101, 0b01010101, + 0b01111111, 0b11111111, 0b01111111, 0b11111111, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + // Mask + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b01111111, 0b11111111, 0b11111111, 0b11111111, + 0b01111111, 0b11111111, 0b11111111, 0b11111111, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 27, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ', + 'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ', + 'R', 'O', 'M', ' ', 'D', 'i', 's', 'k', 0 +}; + +#define SDISK_ICON_SIZE (283) +const char const SDiskIcon[SDISK_ICON_SIZE] = { + // Icon + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b00000000, 0b00000000, 0b00010000, + 0b00000001, 0b00000001, 0b10000000, 0b11010000, + 0b00000001, 0b01101101, 0b10110110, 0b11010000, + 0b00000001, 0b01101101, 0b10110110, 0b11010000, + 0b00000001, 0b01101101, 0b10110110, 0b11010000, + 0b00000001, 0b01101101, 0b10110110, 0b11010000, + 0b00000001, 0b01101101, 0b10110110, 0b11010000, + 0b00000001, 0b00000000, 0b00000000, 0b00010000, + 0b00000001, 0b00000000, 0b00000000, 0b00010000, + 0b00000010, 0b00000000, 0b00000000, 0b00010000, + 0b00000100, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001110, 0b00000000, 0b00000000, 0b00010000, + 0b00000010, 0b00000000, 0b00000000, 0b00010000, + 0b00000010, 0b00000000, 0b00000000, 0b00010000, + 0b00000010, 0b00000000, 0b00000000, 0b00010000, + 0b00000100, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001000, 0b00000000, 0b00000000, 0b00010000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + // Mask + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000001, 0b11111111, 0b11111111, 0b11110000, + 0b00000011, 0b11111111, 0b11111111, 0b11110000, + 0b00000111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00000011, 0b11111111, 0b11111111, 0b11110000, + 0b00000011, 0b11111111, 0b11111111, 0b11110000, + 0b00000011, 0b11111111, 0b11111111, 0b11110000, + 0b00000111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00001111, 0b11111111, 0b11111111, 0b11110000, + 0b00000000, 0b00000000, 0b00000000, 0b00000000, + 25, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ', + 'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ', + 'R', 'O', 'M', 'B', 'U', 'S', 0 +}; + +#endif \ No newline at end of file diff --git a/sdmmc.c b/sdmmc.c new file mode 100644 index 0000000..048f678 --- /dev/null +++ b/sdmmc.c @@ -0,0 +1,220 @@ +#include "sdmmc.h" + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + +#define INIT_PORT() init_port() /* Initialize MMC control port (CS/CLK/DI:output, DO:input) */ +#define DLY_US(n) dly_us(n) /* Delay n microseconds */ +#define FORWARD(d) forward(d) /* Data in-time processing function (depends on the project) */ + +/* Definitions for MMC/SDC command */ +#define CMD0 (0x40+0) /* GO_IDLE_STATE */ +#define CMD1 (0x40+1) /* SEND_OP_COND (MMC) */ +#define ACMD41 (0xC0+41) /* SEND_OP_COND (SDC) */ +#define CMD8 (0x40+8) /* SEND_IF_COND */ +#define CMD16 (0x40+16) /* SET_BLOCKLEN */ +#define CMD17 (0x40+17) /* READ_SINGLE_BLOCK */ +#define CMD24 (0x40+24) /* WRITE_BLOCK */ +#define CMD55 (0x40+55) /* APP_CMD */ +#define CMD58 (0x40+58) /* READ_OCR */ + +/* Card type flags (CardType) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ + + + +static char CardType; /* 0:MMC, 1:SDv1, 2:SDv2, 3:Block addressing */ + + +/*-----------------------------------------------------------------------*/ +/* Send a command packet to MMC */ +/*-----------------------------------------------------------------------*/ +static char send_cmd(char cmd, long arg) +{ + char n, res; + + if (cmd & 0x80) { /* ACMD is the command sequense of CMD55-CMD */ + cmd &= 0x7F; + res = send_cmd(CMD55, 0); + if (res > 1) return res; + } + + /* Select the card */ + CS_H(); spi_rx(); + CS_L(); spi_rx(); + + /* Send a command packet */ + spi_tx(cmd); /* Start + Command index */ + s((BYTE)(arg >> 24)); /* Argument[31..24] */ + spi_tx((BYTE)(arg >> 16)); /* Argument[23..16] */ + spi_tx((BYTE)(arg >> 8)); /* Argument[15..8] */ + spi_tx((BYTE)arg); /* Argument[7..0] */ + n = 0x01; /* Dummy CRC + Stop */ + if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ + if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ + spi_tx(n); + + /* Receive a command response */ + n = 10; /* Wait for a valid response in timeout of 10 attempts */ + do { + res = spi_rx(); + } while ((res & 0x80) && --n); + + return res; /* Return with the response value */ +} + + + +/*-------------------------------------------------------------------------- + + Public Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Initialize Disk Drive */ +/*-----------------------------------------------------------------------*/ +sdstatus_t sdmmc_init() +{ + char n, cmd, ty, buf[4]; + uint tmr; + + CS_H(); + spi_skip(10); /* Dummy clocks */ + + ty = 0; + if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */ + if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */ + for (n = 0; n < 4; n++) buf[n] = spi_rx(); /* Get trailing return value of R7 resp */ + if (buf[2] == 0x01 && buf[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */ + for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state (ACMD41 with HCS bit) */ + if (send_cmd(ACMD41, 1UL << 30) == 0) break; + DLY_US(1000); + } + if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ + for (n = 0; n < 4; n++) buf[n] = spi_rx(); + ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 (HC or SC) */ + } + } + } else { /* SDv1 or MMCv3 */ + if (send_cmd(ACMD41, 0) <= 1) { + ty = CT_SD1; cmd = ACMD41; /* SDv1 */ + } else { + ty = CT_MMC; cmd = CMD1; /* MMCv3 */ + } + for (tmr = 1000; tmr; tmr--) { /* Wait for leaving idle state */ + if (send_cmd(cmd, 0) == 0) break; + DLY_US(1000); + } + if (!tmr || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */ + ty = 0; + } + } + CardType = ty; + release_spi(); + + return ty ? 0 : STA_NOINIT; +} + + +/*-----------------------------------------------------------------------*/ +/* Read partial sector */ +/*-----------------------------------------------------------------------*/ +sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count) +{ + DRESULT res; + char d; + uint bc, tmr; + + + if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */ + + res = RES_ERROR; + if (send_cmd(CMD17, sector) == 0) { /* READ_SINGLE_BLOCK */ + + tmr = 1000; + do { /* Wait for data packet in timeout of 100ms */ + DLY_US(100); + d = spi_rx(); + } while (d == 0xFF && --tmr); + + if (d == 0xFE) { /* A data packet arrived */ + bc = 514 - offset - count; + + /* Skip leading bytes */ + if (offset) spi_skip(offset); + + /* Receive a part of the sector */ + if (buff) { /* Store data to the memory */ + do + *buff++ = spi_rx(); + while (--count); + } else { /* Forward data to the outgoing stream */ + do { + d = spi_rx(); + FORWARD(d); + } while (--count); + } + + /* Skip trailing bytes and CRC */ + spi_skip(bc); + + res = RES_OK; + } + } + + release_spi(); + + return res; +} + + +/*-----------------------------------------------------------------------*/ +/* Write partial sector */ +/*-----------------------------------------------------------------------*/ +sdresult_t sdmmc_writep(const Ptr buf, long sc) +{ + DRESULT res; + UINT bc, tmr; + static UINT wc; + + res = RES_ERROR; + + if (buff) { /* Send data bytes */ + bc = (UINT)sc; + while (bc && wc) { /* Send data bytes to the card */ + spi_tx(*buff++); + wc--; bc--; + } + res = RES_OK; + } else { + if (sc) { /* Initiate sector write transaction */ + if (!(CardType & CT_BLOCK)) sc *= 512; /* Convert to byte address if needed */ + if (send_cmd(CMD24, sc) == 0) { /* WRITE_SINGLE_BLOCK */ + spi_tx(0xFF); spi_tx(0xFE); /* Data block header */ + wc = 512; /* Set byte counter */ + res = RES_OK; + } + } else { /* Finalize sector write transaction */ + bc = wc + 2; + while (bc--) spi_tx(0); /* Fill left bytes and CRC with zeros */ + if ((spi_rx() & 0x1F) == 0x05) { /* Receive data resp and wait for end of write process in timeout of 300ms */ + for (tmr = 10000; spi_rx() != 0xFF && tmr; tmr--) /* Wait for ready (max 1000ms) */ + DLY_US(100); + if (tmr) res = RES_OK; + } + release_spi(); + } + } + + return res; +} diff --git a/sdmmc.h b/sdmmc.h new file mode 100644 index 0000000..e2a49b6 --- /dev/null +++ b/sdmmc.h @@ -0,0 +1,29 @@ +#ifndef SDMMC_H +#define SDMMC_H + + +/* Status of Disk Functions */ +typedef char sdstatus_t; + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ + + +/* Results of Disk Functions */ +typedef enum sdmmc_result_e { + RES_OK = 0, /* 0: Function succeeded */ + RES_ERROR, /* 1: Disk error */ + RES_NOTRDY, /* 2: Not ready */ + RES_PARERR /* 3: Invalid parameter */ +} sdresult_t; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ +/*---------------------------------------*/ +sdstatus_t sdmmc_init(); +sdresult_t sdmmc_readp(Ptr buf, long sector, uint offset, uint count); +sdresult_t sdmmc_writep(const Ptr buf, long sc); + + +#endif diff --git a/spi.c b/spi.c new file mode 100644 index 0000000..4b918ff --- /dev/null +++ b/spi.c @@ -0,0 +1,164 @@ +#include "spi.h" + +/*-------------------------------------------------------------------------*/ +/* Platform dependent macros and functions needed to be modified */ +/*-------------------------------------------------------------------------*/ +#define CS_H() bset(P0) /* Set MMC CS "high" */ +#define CS_L() bclr(P0) /* Set MMC CS "low" */ +#define CK_H() bset(P1) /* Set MMC SCLK "high" */ +#define CK_L() bclr(P1) /* Set MMC SCLK "low" */ +#define DI_H() bset(P2) /* Set MMC DI "high" */ +#define DI_L() bclr(P2) /* Set MMC DI "low" */ +#define DO btest(P3) /* Test MMC DO (high:true, low:false) */ + + +// Command listing +/* T16: Transfer 16-bit + * First, the 16-bit value encoded in the address bits A[17:2] is latched. + * The data output mux is set to the current RXR and the cycle completes. + * Shortly after /AS rises, the SPI transfer engine begins + * transferring the latched value. + */ +/* T16S: Transfer 16-bit Swapped + * Same as T16L but read data is byte-swapped. + */ +/* MERT: Measure Elapsed time and Reset Timer + * The elapsed time since the last MERT command is returned in D[31:24] + * and the timer is reset. + */ +/* SKIP1: Skip Clocks with MOSI "1" + * + */ +/* SKIP0: Skip Clocks with MOSI "0" + * + */ +/* T8S: Transfer 8-bit Swapped + * Same as T8 but read data is byte-swapped. + */ +/* T8: Transfer 8-bit + * First, the 8-bit value encoded in the address bits A[9:2] is latched. + * The data output mux is set to the current RXR and the cycle completes. + * Shortly after /AS rises, the SPI transfer engine begins + * transferring the latched value. + */ +/* WRC: Write Command + * The command encoded in address bits A[9:2] is sent to the command target + * corresponding to the address bits A[15:10]. + * Command targets: + * $00 - Set bitbang + * A[2] - SCS value + */ +/* RDRXR: Read Receive Data Register + * The the current RXR is returned in D[31:16] and the cycle completes. + */ +/* RDRXRS: Read Receive Data Register Swapped + * Same as RDRXR but read data is byte-swapped. + */ +/* MAGIC: Write Command + * Write sequence $FF $00 $55 $AA $C1 $AD + * to enable registers at $40890000-$4097FFFF. + * Write anything else to disable them. + * Always reads 0xC1AD + */ + +// SPI controller address map: +// 40940000-4097FFFF (256 kB, D[31:16]) T16S. Write transfer data in A[17:2]. +// 40900000-4093FFFF (256 kB, D[31:16]) T16. Write transfer data in A[17:2]. +// 408C0000-408FFFFF (320 kB) reserved +// 408A0000-408AFFFF ( 64 kB, D[31:24]) WRC. Write port address in A[15:10] and data in A[9:2]. +// 40891C00-4089FFFF ( 55 kB) reserved +// 40892000-408923FF ( 1 kB, D[31:24]) MERT. +// 40891C00-40891FFF ( 1 kB) SKIP1. Write bytes to skip in A[9:2]. +// 40891800-40891BFF ( 1 kB) SKIP0. Write bytes to skip in A[9:2]. +// 40891400-408917FF ( 1 kB, D[31:16]) T8S. Write transfer data in A[9:2]. +// 40891000-408913FF ( 1 kB, D[31:16]) T8. Write transfer data in A[9:2]. +// 40890C00-40890FFF ( 1 kB, D[31:16]) RDRXRS. +// 40890800-40890BFF ( 1 kB, D[31:16]) RDRXR. +// 40890400-408907FF ( 1 kB) reserved +// 40890000-408903FF ( 1 kB, D[31:24]) MAGIC. Write magic numbers in A[9:2]. +// 40880000-408FFFFF ( 64 kB, D[31:00]) ROMBUS driver data + +#define RB_T16S(x) (*(volatile int*) (0x40940000 + ((x && 0xFFFF)<<02)) ) +#define RB_T16(x) (*(volatile int*) (0x40900000 + ((x && 0xFFFF)<<02)) ) +#define RB_RDS(a) (*(volatile char*) (0x408B0000 + ((a && 0x003F)<<10)) ) +#define RB_WRC(a,d) (*(volatile char*) (0x408A0000 + ((a && 0x003F)<<10) + + ((d && 0x00FF)<<02)) ) +#define RB_MERT(x) (*(volatile char*) (0x40892000 + ((x && 0xFFFF)<<02)) ) +#define RB_SKIP1(n) (*(volatile char*) (0x40891C00 + ((x && 0xFFFF)<<02)) ) +#define RB_SKIP0(n) (*(volatile char*) (0x40891800 + ((x && 0xFFFF)<<02)) ) +#define RB_T8S(x) (*(volatile int*) (0x40891400 + ((x && 0xFFFF)<<02)) ) +#define RB_T8(x) (*(volatile int*) (0x40891000 + ((x && 0xFFFF)<<02)) ) +#define RB_RDRXRS (*(volatile int*) (0x40890C00 + ((x && 0xFFFF)<<02)) ) +#define RB_RDRXR (*(volatile int*) (0x40890800 + ((x && 0xFFFF)<<02)) ) +#define RB_WRMOSI(x) (*(volatile char*) (0x40890400 + ((x && 0x0001)<<02)) ) +#define RB_MAGIC(x) (*(volatile char*) (0x40890000 + ((x && 0xFFFF)<<02)) ) + +#define SPI_GET_MISO(d) (d & 1) + +void spi_select() { + ret = *SPI_CMD_SEL0; + ret = *SPI_CMD_SEL1; + ret = *SPI_CMD_SEL2; + ret = *SPI_CMD_SEL3; +} +void spi_deselect() { + ret = *SPI_CMD_DES0; + ret = *SPI_CMD_DES1; + ret = *SPI_CMD_DES2; + ret = *SPI_CMD_DES3; +} + +void spi_tx_slow(char d) { + for (int i = 0; i < 8; i++) { + *SPI_CMD_BBA((0 & 0x02) | (d & 0x01)); + *SPI_CMD_BBA((1 & 0x02) | (d & 0x01)); + d >>= 1; + } + *SPI_CMD_BBA((0 & 0x02) | (0 & 0x01)); +} + +char spi_rx_slow() { + char ret = 0; + for (int i = 0; i < 8; i++) { + *SPI_CMD_BBA((0 & 0x02) | (1 & 0x01)); + *SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)); + ret = (ret << 1) + (*SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)) & 1); + } + return ret; +} + +void spi_skip_slow(int n) { + while (n-- > 0) { + for (int i = 0; i < 8; i++) { + *SPI_CMD_BBA((0 & 0x02) | (1 & 0x01)); + *SPI_CMD_BBA((1 & 0x02) | (1 & 0x01)); + } + } + *SPI_CMD_BBA((0 & 0x02) | (1 & 0x01)); +} + +void spi_tx_8(char d) { + *SPI_CMD_SH8(d); +} + +char spi_rx_8() { + *SPI_CMD_SH8(0xFF); + return *SPI_CMD_RD & 0xFF; +} + +void spi_tx_16(int d) { + *SPI_CMD_SH16(d); +} + +int spi_rx_16() { + *SPI_CMD_SH16(0xFFFF); + return *SPI_CMD_RD & 0xFFFF; +} + +void spi_skip(int n) { + while (n-- > 0) { + for (int i = 0; i < 8; i++) { + *SPI_CMD_SH8(0xFF); + } + } +} diff --git a/spi.h b/spi.h new file mode 100644 index 0000000..70ee2c5 --- /dev/null +++ b/spi.h @@ -0,0 +1,17 @@ +#ifndef SPI_H +#define SPI_H + +void spi_select(); +void spi_deselect(); + +void spi_tx_slow(char d); +char spi_rx_slow(); +void spi_skip_slow(int n); + +void spi_tx_8(char d); +char spi_rx_8(); +void spi_tx_16(int d); +int spi_rx_16(); +void spi_skip(int n); + +#endif diff --git a/xfer.h b/xfer.h new file mode 100644 index 0000000..bc81450 --- /dev/null +++ b/xfer.h @@ -0,0 +1,11 @@ +#ifndef RDISK_H +#define RDISK_H + +#pragma parameter xfer_s_256(__A0, __A1) +void xfer_s_256(Ptr srcreg, Ptr destmem); + +#pragma parameter xfer_s(__D0, __A0, __A1) +void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem); + + +#endif diff --git a/xfer.s b/xfer.s new file mode 100644 index 0000000..2c9b1d6 --- /dev/null +++ b/xfer.s @@ -0,0 +1,34 @@ + .macro xfer_in from, to + move.w (%A0), (%A1)+ + nop + nop + nop + .if \to-\from + xfer_in "(\from+1)" + .else + + .endif + .endm + + +;pragma parameter xfer_s_256(__A0, __A1) +;void xfer_s_256(Ptr srcreg, Ptr destmem); +xfer_256: + movem.l %D0/%A1-%A2, -(%SP) +xfer_256_loop: + xfer_s_in 0, 255 +xfer_256_end: + movem.l (%SP)+, %D0/%A1-%A2 + + +;pragma parameter xfer_s(__D0, __A0, __A1) +;void xfer_s(uint8_t numBytes, Ptr srcreg, Ptr destmem); +xfer: + movem.l %D0/%A1-%A2, -(%SP) + andi.l #0xFF, %D0 + subi.l #256, %D0 + neg.l %D0 + lsl.l #2, %D0 + addi.l #xfer_256, %D0 + movea.l %D0, %A2 + jmp %A2