This commit is contained in:
Zane Kaminski 2022-12-18 08:46:39 -05:00
parent 51d01f815f
commit ef6286d674
36 changed files with 1109 additions and 1745 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.DS_Store
obj/
.vscode/c_cpp_properties.json
.vscode/settings.json

View File

@ -5,12 +5,12 @@ LD=$(PREFIX)-ld
OBJCOPY=$(PREFIX)-objcopy
OBJDUMP=$(PREFIX)-objdump
all: bin/ROMBUS.bin obj/rombus.s obj/driver.s obj/driver_abs.sym
all: bin/ROMBUS_8M.bin obj/rombus.s obj/driver.s obj/driver_abs.sym
obj:
mkdir $@
mkdir -p $@
bin:
mkdir $@
mkdir -p $@
obj/entry.o: entry.s obj
@ -20,14 +20,38 @@ obj/entry_rel.sym: obj obj/entry.o
$(OBJDUMP) -t obj/entry.o > $@
obj/spi.o: spi.c obj
$(CC) -Wall -march=68020 -c -Os $< -o $@
obj/spi_hal.o: spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rx8.o: spi_rx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rx16.o: spi_rx16.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_tx8.o: spi_tx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_tx16.o: spi_tx16.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_rxtx8.o: spi_rxtx8.s spi_hal.s spi_hal_common.s obj
$(AS) $< -o $@
obj/spi_delay.o: spi_delay.s obj
$(AS) $< -o $@
obj/rombus.o: rombus.c obj
$(CC) -Wall -march=68030 -c -Os $< -o $@
$(CC) -Wall -march=68020 -c -Os $< -o $@
obj/rombus.s: obj obj/rombus.o
$(OBJDUMP) -d obj/rombus.o > $@
obj/driver.o: obj obj/entry.o obj/rombus.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rombus.o
obj/driver.o: obj obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
obj/spi_rx8.o obj/spi_rx16.o \
obj/spi_tx8.o obj/spi_tx16.o \
obj/spi_rxtx8.o
$(LD) -Ttext=40851D70 -o $@ obj/entry.o obj/rombus.o obj/spi.o obj/spi_hal.o \
obj/spi_rx8.o obj/spi_rx16.o \
obj/spi_tx8.o obj/spi_tx16.o \
obj/spi_rxtx8.o
obj/driver.s: obj obj/driver.o
$(OBJDUMP) -d obj/driver.o > $@
@ -35,11 +59,11 @@ obj/driver.s: obj obj/driver.o
obj/driver_abs.sym: obj obj/driver.o
$(OBJDUMP) -t obj/driver.o > $@
bin/driver.bin: bin obj/driver.o
$(OBJCOPY) -O binary obj/driver.o $@
bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
bin/baserom_rombus_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_abs.sym obj/entry_rel.sym
cp roms/baserom.bin $@ # Copy base rom
# Patch driver
dd if=bin/driver.bin of=$@ bs=1 seek=335248 skip=32 conv=notrunc # Copy driver code
@ -51,23 +75,19 @@ bin/baserom_romdisk_ramtest.bin: bin roms/baserom.bin bin/driver.bin obj/driver_
cat obj/entry_rel.sym | grep "[0-9]\s*DStatus" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335230 count=2 conv=notrunc
cat obj/entry_rel.sym | grep "[0-9]\s*DClose" | cut -c5-8 | xxd -r -p - | dd of=$@ bs=1 seek=335232 count=2 conv=notrunc
bin/baserom_romdisk_noramtest.bin: bin bin/baserom_romdisk_ramtest.bin
cp bin/baserom_romdisk_ramtest.bin $@ # Copy base rom
bin/baserom_rombus_noramtest.bin: bin bin/baserom_rombus_ramtest.bin
cp bin/baserom_rombus_ramtest.bin $@ # Copy base rom
# Disable RAM test
printf '\x4E\xD6' | dd of=$@ bs=1 seek=288736 count=2 conv=notrunc
printf '\x4E\xD6' | dd of=$@ bs=1 seek=289016 count=2 conv=notrunc
bin/ROMBUS.bin: bin bin/baserom_romdisk_noramtest.bin disks/RDisk7M5.dsk
bin/ROMBUS_8M.bin: bin bin/baserom_rombus_noramtest.bin disks/RDisk.dsk
# Copy base rom with ROM disk driver
cp bin/baserom_romdisk_noramtest.bin $@
# Patch ROM disk driver parameter table
printf '\x00\x01\x2A\x29' | dd of=$@ bs=1 seek=335260 count=4 conv=notrunc # Patch CDR patch offset
printf '\x40\x89\x2A\x14' | dd of=$@ bs=1 seek=335268 count=4 conv=notrunc # Patch CDR name address
printf '\x44' | dd of=$@ bs=1 seek=335273 count=1 conv=notrunc # Patch CDR disable byte
cp bin/baserom_rombus_noramtest.bin $@
printf '\x00\x78\x00\x00' | dd of=$@ bs=1 seek=335276 count=4 conv=notrunc # Patch ROM disk size
# Copy ROM disk image
dd if=disks/RDisk7M5.dsk of=$@ bs=1024 seek=512 conv=notrunc
dd if=disks/RDisk.dsk of=$@ bs=1024 seek=512 conv=notrunc
.PHONY: clean
clean:

Binary file not shown.

Binary file not shown.

22
entry.s
View File

@ -8,13 +8,27 @@
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
dc.l 0x00000000, 0x00000000, 0x00000000, 0x00000000
SDiskSig:
.ascii "\5SDisk\0"
RDiskSig:
.ascii "\5RDisk\0"
.align 4
RDiskDBGDisPos:
dc.l 0x00000031
RDiskCDRDisPos:
dc.l 0xFFFFFFFF
RDiskDBGNameAddr:
dc.l 0x4088002A
RDiskCDRNameAddr:
dc.l 0x00000000
RDiskDBGDisByte:
dc.b 0x44
RDiskCDRDisByte:
dc.b 0x44
RDiskRAMRequired:
.ascii "16"
.align 4
RDiskSize:
dc.l 0x00780000
SDiskSize:
dc.l 0x80000000
DOpen:
movem.l %A0-%A1, -(%SP)

View File

@ -1,89 +0,0 @@
# path to RETRO68
RETRO68=~/Retro68-build/toolchain
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/rdisk7M5.s obj/driver7M5.s obj/entry_rel.sym obj/driver_abs.sym
obj:
mkdir obj
bin:
mkdir bin
obj/entry.o: entry.s obj
$(AS) $< -o $@
obj/entry_rel.sym: obj obj/entry.o
$(OBJDUMP) -t obj/entry.o > $@
obj/rdisk7M5.o: rdisk.c obj
$(CC) -Wall -DRDiskSize=7864320 $(CFLAGS) $< -o $@
obj/rdisk7M5.s: obj obj/rdisk7M5.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/driver7M5.o: obj obj/entry.o obj/rdisk7M5.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/driver7M5.o
$(OBJDUMP) -t obj/driver7M5.o > $@
bin/driver7M5.bin: bin obj/driver7M5.o
$(OBJCOPY) -O binary obj/driver7M5.o $@
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
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=RDisk7M5.dsk of=$@ bs=1024 seek=512 count=7680 conv=notrunc # copy disk image
bin/rom8M_swap.bin: bin bin/rom8M.bin
dd if=bin/rom8M.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/iisi_swap.bin bin/rom8M_swap.bin
cat bin/rom8M_swap.bin > $@
cat bin/iisi_swap.bin >> $@
.PHONY: clean
clean:
rm -fr bin obj

Binary file not shown.

View File

@ -1,84 +0,0 @@
.EQU killCode, 1
.EQU noQueueBit, 9
.EQU kioTrap, 6
.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 RDOpen
movem.l (%SP)+, %A0-%A1
rts
DClose:
movem.l %A0-%A1, -(%SP)
bsr RDClose
movem.l (%SP)+, %A0-%A1
rts
DPrime:
movem.l %A0-%A1, -(%SP)
bsr RDPrime
movem.l (%SP)+, %A0-%A1
bra.b IOReturn
DControl:
movem.l %A0-%A1, -(%SP)
bsr RDCtl
movem.l (%SP)+, %A0-%A1
cmpi.w #killCode, kcsCode(%A0)
bne.b IOReturn
rts
DStatus:
movem.l %A0-%A1, -(%SP)
bsr RDStat
movem.l (%SP)+, %A0-%A1
IOReturn:
move.w kioTrap(%A0), %D1
btst #noQueueBit, %D1
beq.b Queued
NotQueued:
tst.w %D0
ble.b ImmedRTS
clr.w %D0
ImmedRTS:
move.w %D0, kioResult(%A0)
rts
Queued:
move.l JIODone, -(%SP)
rts

View File

@ -1,361 +0,0 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#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;
}

View File

@ -1,179 +0,0 @@
#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

View File

@ -1,220 +0,0 @@
#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<n> is the command sequense of CMD55-CMD<n> */
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;
}

View File

@ -1,29 +0,0 @@
#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

164
old/spi.c
View File

@ -1,164 +0,0 @@
#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);
}
}
}

View File

@ -1,17 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#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

View File

@ -1,34 +0,0 @@
.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

23
priv_syscall.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _PRIV_SYSCALL_H
#define _PRIV_SYSCALL_H
#include <Disks.h>
#include <OSUtils.h>
#pragma parameter __D0 PSReadXPRAM(__D0, __D1, __A0)
OSErr PSReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
#pragma parameter __D0 PSAddDrive(__D1, __D0, __A0)
OSErr PSAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
// Figure out the first available drive number >= 5
static int PSFindDrvNum() {
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;
}
#endif

100
rdisk.c
View File

@ -1,100 +0,0 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include <Quickdraw.h>
#include "rombus.h"
#include "rdisk.h"
OSErr RDOpen(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Find first available drive number for ROM drive
drvNum = RBFindDrvNum();
// Set ROM drive status
c->rdStatus.track = 0;
c->rdStatus.writeProt = -1; // nonzero is write protected
c->rdStatus.diskInPlace = 8; // 8 is nonejectable disk
c->rdStatus.installed = 1; // drive installed
c->rdStatus.sides = 0;
c->rdStatus.qType = 0;
c->rdStatus.dQDrive = drvNum;
c->rdStatus.dQFSID = 0;
c->rdStatus.dQRefNum = d->dCtlRefNum;
c->rdStatus.driveSize = RDiskSize / 512;
//c->rdStatus.driveS1 = (RDiskSize / 512) >> 16;
// Decompress ROM disk icon
src = &RDiskIconCompressed[0];
dst = &c->rdIcon[0];
UnpackBits(&src, &dst, RDISK_ICON_SIZE);
// Add ROM disk to drive queue and return
return RBAddDrive(c->rdStatus.dQRefNum, c->rdStatus.dQDrive, (DrvQElPtr)&c->rdStatus.qLink);
}
OSErr RDPrime(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Return disk offline error if virtual disk not inserted
if (!c->rdStatus.diskInPlace) { return offLinErr; }
// Get pointer to ROM disk buffer
disk = 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) { return wPrErr;
} else { return noErr; } //FIXME: Fail if cmd isn't read or write?
// Update count and 1position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
OSErr RDCtl(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Handle control request based on csCode
switch (p->csCode) {
case kFormat: return controlErr;
case kVerify:
if (!c->rdStatus.diskInPlace) { return controlErr; }
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->rdStatus.diskInPlace) {
PostEvent(diskEvt, c->rdStatus.dQDrive);
}
return controlErr; // Eject not allowed so return error
case kDriveIcon: case kMediaIcon: // Get icon
*(Ptr*)p->csParam = (Ptr)c->rdIcon;
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)
*(long*)p->csParam = 0x00000411;
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = RDiskSize / 512;
return noErr;
default: return controlErr;
}
}
OSErr RDStat(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
BlockMove(&c->rdStatus, &p->csParam, sizeof(DrvSts2));
return noErr;
default: return statusErr;
}
}
void RDClose(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c) { }

101
rdisk.h
View File

@ -1,101 +0,0 @@
#ifndef RDISK_H
#define RDISK_H
#include "rombus.h"
#define RDiskBuf ((char*)0x40880000)
#define RDiskSize (*(const unsigned long*)0x40851D98)
OSErr RDOpen(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr RDInit(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr RDPrime(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr RDCtl(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr RDStat(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr RDClose(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
#define RDISK_ICON_SIZE (285)
#define RDISK_COMPRESSED_ICON_SIZE (87)
const char 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
};
#endif

266
rombus.c
View File

@ -5,53 +5,71 @@
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include <Quickdraw.h>
#include "rombus.h"
#include "rdisk.h"
#include "sdisk.h"
#include "spi.h"
#include "priv_syscall.h"
// Decode keyboard/PRAM settings
static void RBDecodeSettings(Ptr unmountROM, Ptr unmountSD, Ptr mountSD) {
// Decode keyboard settings
static void RBDecodeKeySettings(RBStorage_t *c) {
// Sample R, S, X keys repeatedly
char r = 0, s = 0, x = 0;
long tmax = TickCount() + 60;
for (long i = 0; i < 1000000; i++) {
r |= RBIsRPressed();
s |= RBIsSPressed();
x |= RBIsXPressed();
r |= IsRPressed();
s |= IsSPressed();
x |= IsXPressed();
if (r || s || x) { break; }
if (TickCount() > tmax) { break; }
}
// Read PRAM
char legacy_startup;
RBReadXPRAM(1, 4, &legacy_startup);
// Decode settings: unmount (don't boot), mount (after boot), RAM disk
if (x) { // X disables SD
*unmountROM = 1; // Unmount ROM disk volume
*unmountSD = 1; // Unmount SD volume
*mountSD = 0; // Don't mount SD later
} else if (r) { // R boots from ROM disk and mount SD later
*unmountROM = 0; // Don't unmount so we boot from ROM
*unmountSD = 1; // Unmount SD volume so we don't boot from it
*mountSD = 1; // Mount SD later
} else if (s) { // S boots from SD
*unmountROM = 1; // Unmount ROM disk volume so we don't boot from it
*unmountSD = 0; // Don't unmount so we boot from SD
*mountSD = 0; // No need to mount SD later since already mounted
} else if (legacy_startup & 0x04) { // Boot from SD
*unmountROM = 1; // Unmount ROM disk volume so we don't boot from it
*unmountSD = 0; // Don't unmount so we boot from SD
*mountSD = 0; // No need to mount later since already mounted
} else {
*unmountROM = !(legacy_startup & 0x01); // Unmount ROM disk if saved in PRAM
*unmountSD = 1; // Unmount SD volume so we don't boot from it
*mountSD = !(legacy_startup & 0x08); // Mount SD later if setting
// Decode settings
if (x) { // Unmount everything
c->unmountROMEN = 1;
c->unmountSDEN = 1;
c->mountROMEN = 0;
c->mountSDEN = 0;
} else if (s) { // Boot from SD, don't mount ROM
c->unmountROMEN = 1;
c->unmountSDEN = 0;
c->mountROMEN = 1;
c->mountSDEN = 0;
} else if (r) { // Boot from ROM, mount SD
c->unmountROMEN = 0;
c->unmountSDEN = 1;
c->mountROMEN = 0;
c->mountSDEN = 1;
}
}
// Decode PRAM settings
static OSErr RBDecodePRAMSettings(RBStorage_t *c) {
// Read PRAM
char legacy_startup, legacy_ram;
PSReadXPRAM(1, 4, &legacy_startup);
PSReadXPRAM(1, 5, &legacy_ram);
// Decoded settings
const char opt_disable = legacy_startup & (1<<7);
const char opt_boot_sd = legacy_startup & (1<<2);
const char opt_boot_rom = legacy_startup & (1<<0);
const char opt_mount_sd = legacy_startup & (1<<3);
const char opt_mount_rom = legacy_startup & (1<<4);
// Old settings for ROM SIMM (not used here)
//const char opt_old_mount_rom = !(legacy_startup & (1<<1));
//const char opt_old_ram = legacy_ram & (1<<0);
// Set based on decoded settings
if (opt_disable) { return -1; }
else {
c->unmountROMEN = !opt_boot_rom;
c->unmountSDEN = !opt_boot_sd;
c->mountROMEN = opt_mount_rom && !opt_boot_rom;
c->mountSDEN = opt_mount_sd && !opt_boot_sd;
}
return noErr;
}
// Switch to 32-bit mode and copy
#pragma parameter C24(__A0, __A1, __D0)
void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long byteCount) {
@ -61,31 +79,24 @@ void __attribute__ ((noinline)) C24(Ptr sourcePtr, Ptr destPtr, unsigned long by
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;
#pragma parameter __D0 RBClose(__A0, __A1)
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}
#pragma parameter __D0 RBOpen(__A0, __A1)
OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
int drvNum;
RBStorage_t *c;
char legacy_startup;
char *src, *dst;
OSErr ret;
// Do nothing if already opened
if (d->dCtlStorage) { return noErr; }
// Do nothing if inhibited
RBReadXPRAM(1, 4, &legacy_startup);
if (legacy_startup & 0x80) { return noErr; }
// Allocate storage struct
d->dCtlStorage = NewHandleSysClear(sizeof(RBStorage_t));
if (!d->dCtlStorage) { return openErr; }
@ -94,36 +105,67 @@ OSErr RBOpen(IOParamPtr p, DCtlPtr d) {
HLock(d->dCtlStorage);
c = *(RBStorage_t**)d->dCtlStorage;
// Populate both drives' DrvSts and add each to drive queue
if (ret = RDOpen(p, d ,c) != noErr) { return ret; }
if (ret = SDOpen(p, d ,c) != noErr) { return ret; }
// Do nothing if inhibited
if (RBDecodePRAMSettings(c) != noErr) {
RBClose(p, d);
return openErr;
}
// Iff mount enabled, enable accRun to post disk inserted event later
if (c->mountROMEN || c->mountSDEN) { d->dCtlFlags |= dNeedTimeMask; }
else { d->dCtlFlags &= ~dNeedTimeMask; }
// Set accRun delay
d->dCtlDelay = 150; // (150 ticks is 2.5 sec.)
// Find first available drive number
drvNum = PSFindDrvNum();
//TODO: set c->sdSize
// Set drive status
c->sdStatus.track = 0;
c->sdStatus.writeProt = 0; // nonzero is write protected
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
c->sdStatus.installed = 1; // drive installed
c->sdStatus.sides = 0;
c->sdStatus.qType = 1;
c->sdStatus.dQDrive = drvNum;
c->sdStatus.dQFSID = 0;
c->sdStatus.dQRefNum = d->dCtlRefNum;
c->sdStatus.driveSize = c->sdSize / 512;
c->sdStatus.driveS1 = (c->sdSize / 512) >> 16;
// Decompress icon
#ifdef RB_COMPRESS_ICON_ENABLE
char *src = &SDIconCompressed[0];
char *dst = &c->sd[0];
UnpackBits(&src, &dst, RB_ICON_SIZE);
#endif
// Add drive to drive queue and return
PSAddDrive(c->sdStatus.dQRefNum, drvNum, (DrvQElPtr)&c->sdStatus.qLink);
return noErr;
}
// Init is called at beginning of first prime (read/write) call
static void RBInit(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
char unmountROM, unmountSD;
static void RBBootInit(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Mark init done
c->initialized = 1;
// Decode settings
RBDecodeSettings(&unmountROM, &c->mountROM, &unmountSD, &c->mountSD);
// Unmount if requested
if (unmountROM) { c->rdStatus.diskInPlace = 0; }
if (unmountSD) { c->sdStatus.diskInPlace = 0; }
// Decode key settings
RBDecodeKeySettings(c);
// If mount enabled, enable accRun to post disk inserted event later
if (c->mountROM || c->mountSD) {
d->dCtlDelay = 150; // Set accRun delay (150 ticks is 2.5 sec.)
d->dCtlFlags |= dNeedTimeMask; // Enable accRun
}
// Unmount if not booting from ROM disk
if (c->unmountSDEN) { c->sdStatus.diskInPlace = 0; }
// Iff mount disabled, disable accRun
if (!c->mountSDEN || !c->mountROMEN) { d->dCtlFlags &= ~dNeedTimeMask; }
}
#pragma parameter __D0 RBPrime(__A0, __A1)
OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
RBStorage_t *c;
char cmd;
Ptr disk;
// Return disk offline error if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
@ -131,13 +173,17 @@ OSErr RBPrime(IOParamPtr p, DCtlPtr d) {
c = *(RBStorage_t**)d->dCtlStorage;
// Initialize if this is the first prime call
if (!c->initialized) { RBInit(p, d, c); }
if (!c->initialized) { RBBootInit(p, d, c); }
switch (p->ioVRefNum) {
case c->rdStatus.dQDrive: return RDPrime(p, d, c);
case c->sdStatus.dQDrive: return SDPrime(p, d, c);
default: return statusErr;
}
// Return disk offline error if virtual disk not inserted
if (!c->sdStatus.diskInPlace) { return offLinErr; }
//TODO: Read/write
// Update count and position/offset, then return
d->dCtlPosition += p->ioReqCount;
p->ioActCount = p->ioReqCount;
return noErr;
}
#pragma parameter __D0 RBCtl(__A0, __A1)
@ -147,60 +193,60 @@ OSErr RBCtl(CntrlParamPtr p, DCtlPtr d) {
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RBStorage_t**)d->dCtlStorage;
// Handle control request csCodes common to both volumes
// Handle control request based on csCode
switch (p->csCode) {
case killCode: return noErr;
case kFormat:
if (!c->sdStatus.diskInPlace || c->sdStatus.writeProt) {
return controlErr;
}
//TODO: Format
return noErr;
case kVerify:
if (!c->sdStatus.diskInPlace) { return controlErr; }
return noErr;
case accRun:
if (c->mountSD) { // Request to mount SD disk
c->initialized = 1; // Mark init done
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->sdStatus.dQDrive); // Post disk inserted event
return noErr;
} else if (c->mountROM) { // Request to mount ROM disk
c->rdStatus.diskInPlace = 8; // 8 is nonejectable disk
PostEvent(diskEvt, c->rdStatus.dQDrive); // Post disk inserted event
return noErr;
} else { // Nothing to mount
d->dCtlFlags &= ~dNeedTimeMask; // Disable accRun
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
case kDriveIcon: case kMediaIcon: // Get icon
#ifdef RB_COMPRESS_ICON_ENABLE
*(Ptr*)p->csParam = (Ptr)c->sd;
#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->sdStatus.writeProt) { *(long*)p->csParam = 0x00000400; }
else { *(long*)p->csParam = 0x00000400; }
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = c->sdSize / 512;
return noErr;
case killCode: return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->sdStatus.diskInPlace) {
PostEvent(diskEvt, c->sdStatus.dQDrive);
}
// Dispatch based on volume reference number
switch (p->ioVRefNum) {
case c->rdStatus.dQDrive: return RDCtl(p, d, c);
case c->sdStatus.dQDrive: return SDCtl(p, d, c);
return controlErr; // Eject not allowed so return error
default: return controlErr;
}
}
#pragma parameter __D0 RBStat(__A0, __A1)
OSErr RBStat(CntrlParamPtr p, DCtlPtr d) {
RBStorage_t *c;
// Fail if dCtlStorage null
if (!d->dCtlStorage) { return notOpenErr; }
// Dereference dCtlStorage to get pointer to our context
c = *(RBStorage_t**)d->dCtlStorage;
// Dispatch based on volume reference number
switch (p->ioVRefNum) {
case c->rdStatus.dQDrive: return RDStat(p, d, c);
case c->sdStatus.dQDrive: return SDStat(p, d, c);
// 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 RBClose(__A0, __A1)
OSErr RBClose(IOParamPtr p, DCtlPtr d) {
// If dCtlStorage not null, dispose of it
if (!d->dCtlStorage) { return noErr; }
RBStorage_t *c = *(RBStorage_t**)d->dCtlStorage;
RDClose(p, d, c);
SDClose(p, d, c);
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}

207
rombus.h
View File

@ -1,36 +1,201 @@
#ifndef ROMBUS_H
#define ROMBUS_H
#ifndef _RDISK_H
#define _RDISK_H
#define BufPtr ((Ptr*)0x10C)
#define MemTop ((Ptr*)0x108)
#define RDiskBuf ((char*)0x40880000)
#define MMU32bit ((char*)0xCB2)
#pragma parameter __D0 RBReadXPRAM(__D0, __D1, __A0)
OSErr RBReadXPRAM(short numBytes, short whichByte, Ptr dest) = {0x4840, 0x3001, 0xA051};
#define RDiskDBGDisPos (*(const unsigned long*)0x40851D98)
#define RDiskCDRDisPos (*(const unsigned long*)0x40851D9C)
#define RDiskDBGDisByte (*(const char*)0x40851DA8)
#define RDiskCDRDisByte (*(const char*)0x40851DA9)
#define RDiskSize (*(const unsigned long*)0x40851DAC)
#pragma parameter __D0 RBAddDrive(__D1, __D0, __A0)
OSErr RBAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) = {0x4840, 0x3001, 0xA04E};
#define RB_COMPRESS_ICON_ENABLE
static inline char RBIsSPressed() { return *((volatile char*)0x174) & 0x02; }
static inline char RBIsXPressed() { return *((volatile char*)0x174) & 0x80; }
static inline char RBIsRPressed() { return *((volatile char*)0x175) & 0x80; }
static inline char IsRPressed() { return *((volatile char*)0x175) & 0x80; }
static inline char IsSPressed() { return *((volatile char*)0x174) & 0x02; }
static inline char IsXPressed() { return *((volatile char*)0x174) & 0x80; }
#define RDISK_ICON_SIZE (285)
#define SDISK_ICON_SIZE (285)
typedef struct RBStorage_s {
DrvSts2 rdStatus;
#define RB_ICON_SIZE (285)
typedef struct RDiskStorage_s {
DrvSts2 sdStatus;
long long sdSize;
char initialized;
char mountROM;
char mountSD;
char rdIcon[RDISK_ICON_SIZE+8];
char sdIcon[SDISK_ICON_SIZE+8];
char unmountSDEN;
char mountSDEN;
char unmountROMEN;
char mountROMEN;
#ifdef RB_COMPRESS_ICON_ENABLE
char sd[RB_ICON_SIZE+8];
#endif
} RBStorage_t;
typedef void (*RBCopy_t)(Ptr, Ptr, unsigned long);
#define copy24(s, d, b) { RBCopy_t f = C24; f(s, d, b); }
typedef void (*RDiskCopy_t)(Ptr, Ptr, unsigned long);
#define copy24(s, d, b) { RDiskCopy_t f = C24; f(s, d, b); }
#define PackBits_Repeat(count) (-1 * (count - 1))
#define PackBits_Literal(count) (count - 1)
#define RDISK_COMPRESSED_ICON_SIZE (87)
#ifdef RB_COMPRESS_ICON_ENABLE
#include <Quickdraw.h>
const char SDIconCompressed[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 RDiskIcon[RB_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

99
sdisk.c
View File

@ -1,99 +0,0 @@
#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#include <Quickdraw.h>
#include "rombus.h"
#include "sdisk.h"
static char SPI_SetCS(char cs) {
}
static void SPI_TX8(char d) {
}
static char SPI_RX8(char d) {
}
static void SPI_TX8_Slow(char d) {
}
static char SPI_RX8_Slow(char d) {
}
OSErr SDOpen(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Find first available drive number for SD drive
drvNum = RBFindDrvNum();
// Set SD drive status
c->sdStatus.track = 0;
c->sdStatus.writeProt = 0; // zero is writable
c->sdStatus.diskInPlace = 8; // 8 is nonejectable disk
c->sdStatus.installed = 1; // drive installed
c->sdStatus.sides = 0;
c->sdStatus.qType = 1;
c->sdStatus.dQDrive = drvNum;
c->sdStatus.dQFSID = 0;
c->sdStatus.dQRefNum = d->dCtlRefNum;
c->sdStatus.driveSize = SDiskSize / 512;
c->sdStatus.driveS1 = (SDiskSize / 512) >> 16;
// Decompress SD disk icon
src = &SDiskIconCompressed[0];
dst = &c->sdIcon[0];
UnpackBits(&src, &dst, SDISK_ICON_SIZE);
// Add SD disk to drive queue and return
return RBAddDrive(c->sdStatus.dQRefNum, c->sdStatus.dQDrive, (DrvQElPtr)&c->sdStatus.qLink);
}
OSErr SDPrime(IOParamPtr p, DCtlPtr d, RBStorage_t *c) {
return controlErr;
}
OSErr SDCtl(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Handle control request based on csCode
switch (p->csCode) {
case kFormat: return controlErr;
case kVerify:
if (!c->sdStatus.diskInPlace) { return controlErr; }
return noErr;
case kEject:
// "Reinsert" disk if ejected illegally
if (c->sdStatus.diskInPlace) {
PostEvent(diskEvt, c->sdStatus.dQDrive);
}
return controlErr; // Eject not allowed so return error
case kDriveIcon: case kMediaIcon: // Get icon
*(Ptr*)p->csParam = (Ptr)c->sdIcon;
return noErr;
case kDriveInfo:
// high word (bytes 2 & 3) clear
// byte 1 = primary + fixed media + internal
// byte 0 = drive type (0x00 is ??)
*(long*)p->csParam = 0x00000400;
return noErr;
case 24: // Return SCSI partition size
*(long*)p->csParam = SDiskSize / 512;
return noErr;
default: return controlErr;
}
}
OSErr SDStat(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c) {
// Handle status request based on csCode
switch (p->csCode) {
case kDriveStatus:
BlockMove(&c->sdStatus, &p->csParam, sizeof(DrvSts2));
return noErr;
default: return statusErr;
}
}
void SDClose(IOParamPtr p, DCtlPtr d, RBStorage_t *c) { }

100
sdisk.h
View File

@ -1,100 +0,0 @@
#ifndef SDISK_H
#define SDISK_H
#include "rombus.h"
#define SDiskSize (*(const unsigned long*)0x40851D9C)
OSErr SDOpen(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr SDInit(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr SDPrime(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr SDCtl(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr SDStat(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
OSErr SDClose(CntrlParamPtr p, DCtlPtr d, RBStorage_t *c);
#define SDISK_ICON_SIZE (285)
#define SDISK_COMPRESSED_ICON_SIZE (86)
const char SDiskIconCompressed[SDISK_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),
26, 'G', 'a', 'r', 'r', 'e', 't', 't', '\'', 's', ' ',
'W', 'o', 'r', 'k', 's', 'h', 'o', 'p', ' ',
'S', 'D', ' ', 'D', 'i', 's', 'k', 0
};
#endif

129
spi.c Normal file
View File

@ -0,0 +1,129 @@
#include "spi.h"
#include "spi_hal.h"
static int _search_lt(char *buf, int stride, int threshold) {
for (int i = 1; i < 256; i++) {
if (buf[i * stride] < threshold) { return 1; }
}
return 0;
}
int _spi_hal_rx8_nops, _spi_hal_tx8_nops;
int _spi_hal_rx16_nops, _spi_hal_tx16_nops;
int _spi_hal_rxtx8_nops;
short *_spi_reg_rx16;
char *_spi_reg_tx16;
short *_spi_reg_rd16;
int spi_init(int swap) {
short buf16[256];
char *buf8 = (char*)&buf16;
for (int i = 0; i < 8; i++) {
spi_hal_rx8(SPI_REG_TIMER8, buf8, 256, i);
_spi_hal_rx8_nops = i;
_spi_hal_tx8_nops = i > 0 ? i - 1 : 0;
if (!_search_lt(buf8, 1, 8)) { break; }
}
for (int i = 0; i < 16; i++) {
spi_hal_rx16(SPI_REG_TIMER16, buf16, 256, i);
_spi_hal_rx16_nops = i;
_spi_hal_tx16_nops = i > 0 ? i - 1 : 0;
if (!_search_lt(buf8, 2, 8)) { break; }
}
for (int i = 0; i < 8; i++) {
spi_hal_rxtx8(SPI_REG_EMPTY, SPI_REG_TIMER16, buf8, buf8, 256, i);
_spi_hal_rxtx8_nops = i;
if (!_search_lt(buf8, 1, 8)) { break; }
}
_spi_reg_rx16 = swap ? SPI_REG_RX16S : SPI_REG_RX16;
_spi_reg_tx16 = swap ? SPI_REG_TX16S : SPI_REG_TX16;
_spi_reg_rd16 = swap ? SPI_REG_RD16S : SPI_REG_RD16;
return 0;
}
void spi_cs(int cs) {
if (cs) { SPI_REG_CSR_SET_CS(); }
else { SPI_REG_CSR_CLR_CS(); }
}
char spi_txrx8_slow(char txd) {
char rxd = 0;
for (int i = 7; i >= 0; i--) {
spi_delay(64);
SPI_REG_CSR_CLR_SCK();
spi_delay(64);
SPI_REG_SET_MOSI((txd >> i) & 1);
rxd = (rxd << 1) | SPI_REG_CSR_GET_MISO();
SPI_REG_CSR_SET_SCK();
}
spi_delay(64);
SPI_REG_CSR_CLR_SCK();
return rxd;
}
char spi_txrx8(char txd) {
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
return *SPI_REG_RD8;
}
char spi_rxtx8(char txd) {
char rxd = *SPI_REG_RD8;
spi_hal_tx8(SPI_REG_TX8, &txd, 1, _spi_hal_tx8_nops);
return rxd;
}
#define UNROLL_LENGTH 5
void spi_rx(char txd, char *rxb, unsigned int length) {
if (length == 0) { return; } // Return if length 0
// Word-align rx pointer by transferring 0/1 bytes
if ((int)rxb & 1) {
*(rxb++) = spi_rxtx8(txd);
length--;
}
// Set tx pattern
reg_write16(SPI_REG_ST16, smear8to32(txd));
// Transfer all but 0-65 bytes
for (int i = length >> (UNROLL_LENGTH +1); i > 0; i--) {
// Transfer 2^UNROLL_LENGTH words (2 * 2^UNROLL_LENGTH bytes)
spi_hal_rx16(_spi_reg_rx16, rxb, UNROLL_LENGTH, _spi_hal_rx16_nops);
}
// Transfer remaining 1-32 words (2-64 bytes)
spi_hal_rx16(_spi_reg_rx16, rxb, length >> 1, _spi_hal_rx16_nops);
// Transfer remaining byte if any
if (length & 1) { *(rxb++) = spi_rxtx8(txd); }
}
void spi_tx(char *txb, unsigned int length) {
if (length == 0) { return; } // Return if length 0
// Word-align tx pointer by transferring 0/1 bytes
if ((int)txb & 1) {
spi_rxtx8(*(txb++));
length--;
}
// Transfer all but 0-65 bytes
for (; length > UNROLL_LENGTH; length -= UNROLL_LENGTH) {
spi_hal_tx16(_spi_reg_tx16, txb, UNROLL_LENGTH, _spi_hal_tx16_nops);
}
// Transfer remaining 1-32 words (2-64 bytes)
spi_hal_tx16(_spi_reg_tx16, txb, length >> 1, _spi_hal_tx16_nops);
// Transfer remaining byte if any
if (length & 1) { spi_rxtx8(*(txb++)); }
}
char spi_rd8() { return *SPI_REG_RD8; }
short spi_rd16() { return *_spi_reg_rd16; }

20
spi.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _SPI_H
#define _SPI_H
#include <stddef.h>
int spi_init();
void spi_cs(int cs);
char spi_txrx8_slow(char txd);
char spi_txrx8(char txd);
char spi_rxtx8(char txd);
void spi_tx(char *txb, unsigned int length);
void spi_rx(char txd, char *rxb, unsigned int length);
char spi_rd8();
short spi_rd16();
#endif

79
spi_hal.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef _SPI_HAL_H
#define _SPI_HAL_H
#pragma parameter spi_delay(__D0)
extern void spi_delay(char iterations);
#pragma parameter _reg_write8(__A0, __D0, __D1)
extern void _reg_write8(void *addr, char data, int tmp);
static inline void reg_write8(void *addr, char data) { _reg_write8(addr, data, 0); }
#pragma parameter _reg_write16(__A0, __D0, __D1)
extern void _reg_write16(void *addr, short data, int tmp);
static inline void reg_write16(void *addr, short data) { _reg_write16(addr, data, 0); }
#pragma parameter __D0 smear8to32(__D0)
extern long smear8to32(char data);
// Read transfer registers
#define SPI_REG_RX8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_RX16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RX16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RD8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_RD16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_RD16S ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
#define SPI_REG_TIMER8 ((char*) 0x00000000) // A[01:00]==2'b00, D[31:24]==ret
#define SPI_REG_TIMER16 ((short*) 0x00000000) // A[01:00]==2'b00, D[31:16]==ret
// Write transfer registers
#define SPI_REG_TX8 ((char*) 0x00000000) // A[07:00]==arg
#define SPI_REG_TX16 ((char*) 0x00000000) // A[15:00]==arg
#define SPI_REG_TX16S ((char*) 0x00000000) // A[05:00]==arg
#define SPI_REG_ST16 ((char*) 0x00000000) // A[15:00]==arg
#define SPI_REG_EMPTY ((char*) 0x00000000)
// Control/status register (read/write)
#define SPI_REG_RD_CSR ((char*) 0x00000000)
#define SPI_REG_WR_CSR ((char*) 0x00000000)
#define SPI_REG_CSR_BIT_nDET (0)
#define SPI_REG_CSR_GET_nDET() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_nDET) & 1)
#define SPI_REG_CSR_BIT_MISO (1)
#define SPI_REG_CSR_GET_MISO() ((*SPI_REG_RD_CSR>>SPI_REG_CSR_BIT_MISO) & 1)
#define SPI_REG_CSR_BIT_SCK (2)
#define SPI_REG_CSR_SET_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_SCK))
#define SPI_REG_CSR_CLR_SCK() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_SCK))
#define SPI_REG_CSR_BIT_CS (3)
#define SPI_REG_CSR_SET_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR | (1<<SPI_REG_CSR_BIT_CS))
#define SPI_REG_CSR_CLR_CS() reg_write16(SPI_REG_WR_CSR, *SPI_REG_RD_CSR & ~(1<<SPI_REG_CSR_BIT_CS))
#define SPI_REG_SET_MOSI(x) reg_write16(SPI_REG_ST16, x ? 0xFFFF : 0x0000)
#pragma parameter _spi_hal_rx8(__A0, __A2, __A4, __D0, __D1, __D2)
extern void _spi_hal_rx8(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rx8(void *reg, void *rx, int length, int nops) {
_spi_hal_rx8(reg, rx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_rx16(__A0, __A2, __A4, __D0, __D1, __D2)
extern void _spi_hal_rx16(void *reg, void *rx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rx16(void *reg, void *rx, int length, int nops) {
_spi_hal_rx16(reg, rx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_tx8(__A0, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_tx8(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_tx8(void *reg, void *tx, int length, int nops) {
_spi_hal_tx8(reg, tx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_tx16(__A0, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_tx16(void *reg, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_tx16(void *reg, void *tx, int length, int nops) {
_spi_hal_tx16(reg, tx, 0, length, nops, 0);
}
#pragma parameter _spi_hal_rxtx8(__A0, __A1, __A2, __A3, __A4, __D0, __D1, __D2)
extern void _spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, void *tmp, int length, int nops, int tmp2);
static inline void spi_hal_rxtx8(void *reg, void *read, void *rx, void *tx, int length, int nops) {
_spi_hal_rxtx8(reg, read, rx, tx, 0, length, nops, 0);
}
#endif

49
spi_hal.s Normal file
View File

@ -0,0 +1,49 @@
.global spi_delay
.global _reg_write16
.global _reg_write8
.global smear8to32
* delay calling convention
* D0 - iterations
spi_delay:
subq.w #1, %D0
bne.b spi_delay
rts
* reg_write calling convention
* A0 - address
* D0 - data (clobbered)
* D1 - clobbered
_reg_write8:
move.l %A0, %D1
andi.l #0xFFFFFF00, %D1
andi.l #0x000000FF, %D0
or %D1, %D0
movea %D0, %A0
move.l (%A0), %D0
rts
_reg_write16:
move.l %A0, %D1
andi.l #0xFFFF0000, %D1
andi.l #0x0000FFFF, %D0
or %D1, %D0
movea %D0, %A0
move.l (%A0), %D0
rts
* smear8to32 calling convention
* D0 - data in/out
smear8to32:
andi.l #0xFF, %D0
move.l %D0, %D1
lsl.w #8, %D1
or.w %D1, %D0
lsl.w #8, %D1
or.w %D1, %D0
lsl.w #8, %D1
or.w %D1, %D0
rts

98
spi_hal_common.s Normal file
View File

@ -0,0 +1,98 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
* D2 - clobbered (save SR)
* D3 - clobbered (save CACR)
.macro spi_call table, maxnops
* Limit %D0 (length) to 1-256
subq.w #1, %D0
andi.l #0xFF, %D0
addq.w #1, %D0
* Limit %D1 (nops) based on maxnops
.if \maxnops == 1
andi.l #1, %D1
.elseif \maxnops == 3
andi.l #3, %D1
.elseif \maxnops == 7
andi.l #7, %D1
.elseif \maxnops == 15
andi.l #15, %D1
.elseif \maxnops != 0
.error
.endif
* Convert length to offset
* %D0 = -%D0 (-length)
neg.l %D0
* %D0 = %D0 + 256 (-length + 256)
add.l #256, %D0
.if \maxnops != 0
* Combine nops with offset to get lookup table index
* %D1 = %D1 * 4 * 256 (nops * 256)
lsl.l #8, %D1
* %D0 = %D0 + %D1 (offset + nops*256)
or.l %D1, %D0
.endif
* Get index of entry point from lookup table
* %D0 = table[%D0] (table[4*(length+nops*256)])
move.l (\table - ., %PC, %D0.w : 4), %D0
* Save status register and disable interrupts
move.w %SR, %D2
ori.w #0x0700, %SR
* Save CACR in %D3
movec %CACR, %D3
* Copy CACR to %D1
move.l %D3, %D1
* Clear CACR bits:
* DE ('040 enable data cache) (31)
* WA ('030 write allocate) (13)
* DBE ('030 data burst enable) (12)
* CD ('030 clear data cache) (11)
* CED ('030 clear entry in data cache) (10)
* FD ('030 freeze data cache) (9)
* ED ('030 enable data cache) (8)
andi.l #0x7FFFC0FF, %D1
* Set '030 CACR bits:
* FD (freeze data cache) (9)
ori.w #0x0200, %D1
* Move back into CACR
movec.l %D1, %CACR
* Jump to entry point
* (table + table[length*4 + nops*4*256])
jmp (\table - ., %PC, %D0.l)
* Return statement for use with parameter checking
ret: rts
.endm
.macro lookup_table base, nbase, stride, n
dc.l \nbase - \base
dc.l \nbase + \stride - \base
dc.l \nbase + \stride+\stride - \base
dc.l \nbase + \stride+\stride+\stride - \base
.if \n > 0
lookup_table \base, \nbase + \stride+\stride+\stride+\stride, \stride, \n-4
.endif
.endm
.macro unroll_table macro, nops, n
.rept \n
\macro \nops
.endr
move.w %D2, %SR
movec.l %D3, %CACR
rts
.endm

73
spi_rx16.s Normal file
View File

@ -0,0 +1,73 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_rx16
.include "spi_hal_common.s"
.macro _spi_hal_rx16_iteration nops
move.w (%A0), (%A2)+
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rx16:
spi_call _spi_hal_rx16_lookup, 15
.align 16
_spi_hal_rx16_lookup:
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_0, 2, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_1, 4, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_2, 6, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_3, 8, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_4, 10, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_5, 12, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_6, 14, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_7, 16, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_8, 18, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_9, 20, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_10, 22, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_11, 24, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_12, 26, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_13, 28, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_14, 30, 256
lookup_table _spi_hal_rx16_lookup, _spi_hal_rx16_table_15, 32, 256
.align 16
_spi_hal_rx16_table_0: unroll_table _spi_hal_rx16_iteration, 0, 256
.align 16
_spi_hal_rx16_table_1: unroll_table _spi_hal_rx16_iteration, 1, 256
.align 16
_spi_hal_rx16_table_2: unroll_table _spi_hal_rx16_iteration, 2, 256
.align 16
_spi_hal_rx16_table_3: unroll_table _spi_hal_rx16_iteration, 3, 256
.align 16
_spi_hal_rx16_table_4: unroll_table _spi_hal_rx16_iteration, 4, 256
.align 16
_spi_hal_rx16_table_5: unroll_table _spi_hal_rx16_iteration, 5, 256
.align 16
_spi_hal_rx16_table_6: unroll_table _spi_hal_rx16_iteration, 6, 256
.align 16
_spi_hal_rx16_table_7: unroll_table _spi_hal_rx16_iteration, 7, 256
.align 16
_spi_hal_rx16_table_8: unroll_table _spi_hal_rx16_iteration, 8, 256
.align 16
_spi_hal_rx16_table_9: unroll_table _spi_hal_rx16_iteration, 9, 256
.align 16
_spi_hal_rx16_table_10: unroll_table _spi_hal_rx16_iteration, 10, 256
.align 16
_spi_hal_rx16_table_11: unroll_table _spi_hal_rx16_iteration, 11, 256
.align 16
_spi_hal_rx16_table_12: unroll_table _spi_hal_rx16_iteration, 12, 256
.align 16
_spi_hal_rx16_table_13: unroll_table _spi_hal_rx16_iteration, 13, 256
.align 16
_spi_hal_rx16_table_14: unroll_table _spi_hal_rx16_iteration, 14, 256
.align 16
_spi_hal_rx16_table_15: unroll_table _spi_hal_rx16_iteration, 15, 256

49
spi_rx8.s Normal file
View File

@ -0,0 +1,49 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_rx8
.include "spi_hal_common.s"
.macro _spi_hal_rx8_iteration nops
move.b (%A0), (%A2)+
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rx8:
spi_call _spi_hal_rx8_lookup, 7
.align 16
_spi_hal_rx8_lookup:
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_0, 2, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_1, 4, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_2, 6, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_3, 8, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_4, 10, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_5, 12, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_6, 14, 256
lookup_table _spi_hal_rx8_lookup, _spi_hal_rx8_table_7, 16, 256
.align 16
_spi_hal_rx8_table_0: unroll_table _spi_hal_rx8_iteration, 0, 256
.align 16
_spi_hal_rx8_table_1: unroll_table _spi_hal_rx8_iteration, 1, 256
.align 16
_spi_hal_rx8_table_2: unroll_table _spi_hal_rx8_iteration, 2, 256
.align 16
_spi_hal_rx8_table_3: unroll_table _spi_hal_rx8_iteration, 3, 256
.align 16
_spi_hal_rx8_table_4: unroll_table _spi_hal_rx8_iteration, 4, 256
.align 16
_spi_hal_rx8_table_5: unroll_table _spi_hal_rx8_iteration, 5, 256
.align 16
_spi_hal_rx8_table_6: unroll_table _spi_hal_rx8_iteration, 6, 256
.align 16
_spi_hal_rx8_table_7: unroll_table _spi_hal_rx8_iteration, 7, 256

62
spi_rxtx8.s Normal file
View File

@ -0,0 +1,62 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
* spi single calling convention
* A0 - ROM register
* A1 - readback address
* D0 - data
* D1 - clobbered
.global _spi_hal_rxtx8
.global _spi_hal_rxtx8single
.include "spi_hal_common.s"
.macro _spi_hal_rxtx8_iteration nops
move.b (%A1), (%A2)+
move.b (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_rxtx8:
spi_call _spi_hal_rxtx8_lookup, 7
_spi_hal_rxtx8_single:
move.b (%A1), %D0
move.b (%A0, %D1.W), %D1
rts
.align 16
_spi_hal_rxtx8_lookup:
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_0, 8, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_1, 10, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_2, 12, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_3, 14, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_4, 16, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_5, 18, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_6, 20, 256
lookup_table _spi_hal_rxtx8_lookup, _spi_hal_rxtx8_table_7, 22, 256
.align 16
_spi_hal_rxtx8_table_0: unroll_table _spi_hal_rxtx8_iteration, 0, 256
.align 16
_spi_hal_rxtx8_table_1: unroll_table _spi_hal_rxtx8_iteration, 1, 256
.align 16
_spi_hal_rxtx8_table_2: unroll_table _spi_hal_rxtx8_iteration, 2, 256
.align 16
_spi_hal_rxtx8_table_3: unroll_table _spi_hal_rxtx8_iteration, 3, 256
.align 16
_spi_hal_rxtx8_table_4: unroll_table _spi_hal_rxtx8_iteration, 4, 256
.align 16
_spi_hal_rxtx8_table_5: unroll_table _spi_hal_rxtx8_iteration, 5, 256
.align 16
_spi_hal_rxtx8_table_6: unroll_table _spi_hal_rxtx8_iteration, 6, 256
.align 16
_spi_hal_rxtx8_table_7: unroll_table _spi_hal_rxtx8_iteration, 7, 256

74
spi_tx16.s Normal file
View File

@ -0,0 +1,74 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_tx16
.include "spi_hal_common.s"
.macro _spi_hal_tx16_iteration nops
move.w (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_tx16:
spi_call _spi_hal_tx16_lookup, 15
.align 16
_spi_hal_tx16_lookup:
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_0, 6, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_1, 8, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_2, 10, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_3, 12, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_4, 14, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_5, 16, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_6, 18, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_7, 20, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_8, 22, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_9, 24, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_10, 26, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_11, 28, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_12, 30, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_13, 32, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_14, 34, 256
lookup_table _spi_hal_tx16_lookup, _spi_hal_tx16_table_15, 36, 256
.align 16
_spi_hal_tx16_table_0: unroll_table _spi_hal_tx16_iteration, 0, 256
.align 16
_spi_hal_tx16_table_1: unroll_table _spi_hal_tx16_iteration, 1, 256
.align 16
_spi_hal_tx16_table_2: unroll_table _spi_hal_tx16_iteration, 2, 256
.align 16
_spi_hal_tx16_table_3: unroll_table _spi_hal_tx16_iteration, 3, 256
.align 16
_spi_hal_tx16_table_4: unroll_table _spi_hal_tx16_iteration, 4, 256
.align 16
_spi_hal_tx16_table_5: unroll_table _spi_hal_tx16_iteration, 5, 256
.align 16
_spi_hal_tx16_table_6: unroll_table _spi_hal_tx16_iteration, 6, 256
.align 16
_spi_hal_tx16_table_7: unroll_table _spi_hal_tx16_iteration, 7, 256
.align 16
_spi_hal_tx16_table_8: unroll_table _spi_hal_tx16_iteration, 8, 256
.align 16
_spi_hal_tx16_table_9: unroll_table _spi_hal_tx16_iteration, 9, 256
.align 16
_spi_hal_tx16_table_10: unroll_table _spi_hal_tx16_iteration, 10, 256
.align 16
_spi_hal_tx16_table_11: unroll_table _spi_hal_tx16_iteration, 11, 256
.align 16
_spi_hal_tx16_table_12: unroll_table _spi_hal_tx16_iteration, 12, 256
.align 16
_spi_hal_tx16_table_13: unroll_table _spi_hal_tx16_iteration, 13, 256
.align 16
_spi_hal_tx16_table_14: unroll_table _spi_hal_tx16_iteration, 14, 256
.align 16
_spi_hal_tx16_table_15: unroll_table _spi_hal_tx16_iteration, 15, 256

50
spi_tx8.s Normal file
View File

@ -0,0 +1,50 @@
* spi calling convention
* A0 - ROM register
* A1 - readback address
* A2 - RX buffer
* A3 - TX buffer
* A4 - clobbered
* D0 - length (clobbered)
* D1 - nops (clobbered)
.global _spi_hal_tx8
.include "spi_hal_common.s"
.macro _spi_hal_tx8_iteration nops
move.b (%A3)+, %D1
move.b (%A0, %D1.W), %D1
.rept \nops
nop
.endr
.endm
.align 16
_spi_hal_tx8:
spi_call _spi_hal_tx8_lookup, 7
.align 16
_spi_hal_tx8_lookup:
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_0, 6, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_1, 8, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_2, 10, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_3, 12, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_4, 14, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_5, 16, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_6, 18, 256
lookup_table _spi_hal_tx8_lookup, _spi_hal_tx8_table_7, 20, 256
.align 16
_spi_hal_tx8_table_0: unroll_table _spi_hal_tx8_iteration, 0, 256
.align 16
_spi_hal_tx8_table_1: unroll_table _spi_hal_tx8_iteration, 1, 256
.align 16
_spi_hal_tx8_table_2: unroll_table _spi_hal_tx8_iteration, 2, 256
.align 16
_spi_hal_tx8_table_3: unroll_table _spi_hal_tx8_iteration, 3, 256
.align 16
_spi_hal_tx8_table_4: unroll_table _spi_hal_tx8_iteration, 4, 256
.align 16
_spi_hal_tx8_table_5: unroll_table _spi_hal_tx8_iteration, 5, 256
.align 16
_spi_hal_tx8_table_6: unroll_table _spi_hal_tx8_iteration, 6, 256
.align 16
_spi_hal_tx8_table_7: unroll_table _spi_hal_tx8_iteration, 7, 256