NetBoot/romdrv 0.9.6/romdrv.c
2020-12-01 10:38:20 +08:00

1 line
10 KiB
C

#include <Memory.h>
#include <Devices.h>
#include <Files.h>
#include <Disks.h>
#include <Errors.h>
#include <Events.h>
#include <OSUtils.h>
#define NEED_DRVSTAT 1
#define NEED_ACCRUN 1
/* If NEED_ACCRUN is set, the dNeedTime (0x60) flag should be set in the header, and the
* delayticks field in the header should be set to something sensible.
*/
//#define kRomDrvSize ((long)(524288L))
//#define kRomDrvSize ((long)(0x00700000L))
//#define kRomDrvLocation 0x40880000
unsigned long kRomDrvSize = 0x00780000L;
Ptr kRomDrvLocation = (Ptr)0x40880000;
Ptr* BufPtr = (Ptr*)0x10C;
Ptr* MemTop = (Ptr*)0x108;
#pragma parameter __D0 ReadXPRam(__D0, __D1, __A0)
short ReadXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _ReadXPRam};
typedef void (*RomDrvCopyFunc)(unsigned char *, unsigned char *, unsigned long);
struct RomDrvContext {
DrvSts2 drvsts;
Ptr origcopyfunc;
Ptr origdisk; /* keep unstripped pointers for Dispose*/
RomDrvCopyFunc copyfunc;
unsigned char * disk;
char initialized;
char useram;
char ram24;
char alreadyalloced;
};
typedef struct RomDrvContext RomDrvContext;
const unsigned char DiskIcon[258] = {
0xf, 0xff, 0xff, 0xe0, 0x10, 0x00, 0x00, 0x10, 0x10,
0x00, 0x00, 0x10, 0x11, 0xff, 0xff, 0x10, 0x12, 0x1, 0x00,
0x90, 0x12, 0x00, 0x81, 0x90, 0x12, 0x00, 0x7e, 0x90, 0x12,
0x11, 0x3c, 0x90, 0x12, 0x11, 0x3c, 0x90, 0x12, 0x1, 0x18,
0x90, 0x12, 0x1, 0x00, 0x90, 0x12, 0x3, 0x00, 0x90, 0x12,
0x00, 0x00, 0x90, 0x12, 0x8, 0x40, 0x90, 0x12, 0x7, 0x80,
0x90, 0x12, 0x00, 0x00, 0x90, 0x12, 0x00, 0x00, 0x90, 0x11,
0xff, 0xff, 0x10, 0x10, 0x00, 0x00, 0x10, 0x8, 0x00, 0x00,
0x20, 0x3f, 0xff, 0xff, 0xf8, 0x20, 0x00, 0x00, 0x8, 0x2f,
0xff, 0xff, 0xe8, 0x20, 0x00, 0x00, 0x8, 0x2f, 0xff, 0xff,
0xe8, 0x20, 0x00, 0x00, 0x8, 0x20, 0x00, 0x00, 0x8, 0x20,
0x00, 0xf, 0xe8, 0x2c, 0x00, 0x00, 0x8, 0x20, 0x00, 0x00,
0x68, 0x20, 0x00, 0x00, 0x8, 0x3f, 0xff, 0xff, 0xf8,
// mask
0xf, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f,
0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xf0, 0xf,
0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f,
0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f,
0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff,
0xf8, 0, 0};
/* AddDrive is declared in Files.h, but it's defined in MacOS.lib, which we don't want,
* so just shortcut the whole thing here.
*/
asm void RomDrvAddDrive(short drvrRefNum, short drvNum, DrvQElPtr dq) {
fralloc +
CLR.L D0
MOVE.W drvNum, D0
SWAP D0
MOVE.W drvrRefNum, D0
MOVEA.L dq, A0
0xA04E
frfree
RTS
}
#pragma parameter __D0 RomDrvStripAddress(__D0)
pascal Ptr RomDrvStripAddress(void *addr) = 0xA055;
void RomDrvCopy(unsigned char *source, unsigned char *dest, unsigned long count) {
signed char mode = true32b;
SwapMMUMode(&mode);
BlockMove(source, dest, count);
SwapMMUMode(&mode);
}
short RomDrvOpen(IOParamPtr p, DCtlPtr d) {
DrvSts2 *dsptr;
DrvQElPtr dq;
int drvnum = 1;
RomDrvContext *ctx;
for(dq = (DrvQElPtr)(GetDrvQHdr())->qHead; dq; dq = (DrvQElPtr)dq->qLink) {
if(dq->dQDrive >= drvnum) drvnum = dq->dQDrive+1;
}
d->dCtlStorage = NewHandleSysClear(sizeof(RomDrvContext));
HLock(d->dCtlStorage);
ctx = *(RomDrvContext**)d->dCtlStorage;
ctx->origcopyfunc = NewPtrSys(64);
if(!ctx->origcopyfunc) {
SysBeep(8);
return openErr;
}
BlockMove(&RomDrvCopy, ctx->origcopyfunc, 64);
ctx->copyfunc = (RomDrvCopyFunc)RomDrvStripAddress(ctx->origcopyfunc);
dsptr = &ctx->drvsts;
dsptr->writeProt = 0xF0;
dsptr->diskInPlace = 8;
dsptr->dQDrive = drvnum;
dsptr->dQRefNum = d->dCtlRefNum;
dsptr->driveSize = (kRomDrvSize/512L) & 0xFFFF;
dsptr->driveS1 = ((kRomDrvSize/512L) & 0xFFFF0000) >> 16;
RomDrvAddDrive(dsptr->dQRefNum, drvnum, (DrvQElPtr)&dsptr->qLink);
return noErr;
}
short RomDrvPrime(IOParamPtr p, DCtlPtr d) {
long off;
RomDrvContext *ctx;
char startup;
char ram;
if(!d->dCtlStorage) return offLinErr;
ctx = *(RomDrvContext**)d->dCtlStorage;
ReadXPRam(1, 4, &startup);
ReadXPRam(1, 5, &ram);
if(!ctx->initialized && startup) {
ctx->initialized = 1;
ctx->drvsts.writeProt = 0xFF;
ctx->origdisk = NULL;
ctx->disk = (unsigned char *)kRomDrvLocation;
if(ram) {
// Delay allocation until boot
ctx->useram = 1;
ctx->drvsts.writeProt = 0;
if (*((unsigned char *)0x0CB2)) {
if(((unsigned long)*BufPtr - kRomDrvSize) <= (( ((unsigned long)*MemTop) / 2) - (1024*1024))) {
d->dCtlFlags |= dNeedTimeMask;
d->dCtlDelay = 0x10;
} else {
*BufPtr -= kRomDrvSize;
ctx->origdisk = *BufPtr;
ctx->alreadyalloced = 1;
ctx->disk = (unsigned char *)ctx->origdisk;
BlockMoveData((unsigned char *)kRomDrvLocation, ctx->disk, kRomDrvSize);
}
} else {
d->dCtlFlags |= dNeedTimeMask;
d->dCtlDelay = 0x10;
}
}
}
if(!ctx->initialized) {
ctx->initialized = 1;
// check for 'r' held down.
if(!(*((unsigned char *)0x175) & 0x80)) {
/* If 'r' is not held down, remove ourselves from the drive queue */
DrvQElPtr dq;
QHdrPtr QHead = (QHdrPtr)0x308;
dq = (DrvQElPtr)QHead->qHead;
while((dq != (DrvQElPtr)(QHead->qTail)) && (dq->dQRefNum != d->dCtlRefNum))
dq = (DrvQElPtr)(dq->qLink);
if(dq->dQRefNum == d->dCtlRefNum) {
Dequeue((QElemPtr)dq, QHead);
if(ctx->origdisk) {
DisposePtr(ctx->origdisk);
ctx->origdisk = NULL;
}
DisposePtr(ctx->origcopyfunc);
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
}
d->dCtlStorage = NULL;
return offLinErr;
}
ctx->drvsts.writeProt = 0xFF;
ctx->origdisk = NULL;
ctx->disk = (unsigned char *)kRomDrvLocation;
// check if 'a' is also held down
if(*((unsigned char *)0x174) & 0x01) {
// Delay allocation until boot
ctx->useram = 1;
ctx->drvsts.writeProt = 0;
if (*((unsigned char *)0x0CB2)) {
if(((unsigned long)*BufPtr - kRomDrvSize) <= (( ((unsigned long)*MemTop) / 2) - (1024*1024))) {
d->dCtlFlags |= dNeedTimeMask;
d->dCtlDelay = 0x10;
} else {
*BufPtr -= kRomDrvSize;
ctx->origdisk = *BufPtr;
ctx->alreadyalloced = 1;
ctx->disk = (unsigned char *)ctx->origdisk;
BlockMoveData((unsigned char *)kRomDrvLocation, ctx->disk, kRomDrvSize);
}
} else {
d->dCtlFlags |= dNeedTimeMask;
d->dCtlDelay = 0x10;
}
}
}
switch(p->ioPosMode & 0x000F) {
case fsAtMark: off = d->dCtlPosition; break;
case fsFromStart: off = p->ioPosOffset; break;
case fsFromMark: off = d->dCtlPosition + p->ioPosOffset; break;
default: break;
}
if((p->ioTrap & 0x00ff) == aRdCmd) {
/* bit 6 indicates this should be a verify operation */
if(!(p->ioPosMode & 0x40)) {
unsigned long count = p->ioReqCount;
if(ctx->drvsts.writeProt == 0 && ctx->origdisk) {
// If the data is in RAM, we can access it in 24bit mode, and can
// avoid the overhead of the extra function call and 2 MMU switches.
if (!ctx->ram24) {
BlockMoveData(ctx->disk + off, p->ioBuffer, count);
} else {
ctx->copyfunc((unsigned char *)(ctx->disk + off), (unsigned char *)RomDrvStripAddress(p->ioBuffer), count);
}
} else {
ctx->copyfunc((unsigned char *)(ctx->disk + off), (unsigned char*)RomDrvStripAddress(p->ioBuffer), count);
}
p->ioActCount = count;
d->dCtlPosition = off + count;
p->ioPosOffset = d->dCtlPosition;
}
return noErr;
} else if(((p->ioTrap & 0x00ff) == aWrCmd) && (ctx->drvsts.writeProt == 0)) {
if (!ctx->ram24) {
BlockMoveData(p->ioBuffer, ctx->disk + off, p->ioReqCount);
} else {
ctx->copyfunc((unsigned char *)RomDrvStripAddress(p->ioBuffer), (unsigned char *)(ctx->disk + off), p->ioReqCount);
}
p->ioActCount = p->ioReqCount;
d->dCtlPosition = off + p->ioReqCount;
p->ioPosOffset = d->dCtlPosition;
return noErr;
}
return wPrErr;
}
short RomDrvClose(IOParamPtr p, DCtlPtr d) {
RomDrvContext *ctx;
if(!d->dCtlStorage) return noErr;
ctx = *(RomDrvContext**)d->dCtlStorage;
if(ctx->origdisk) DisposePtr(ctx->origdisk);
DisposePtr(ctx->origcopyfunc);
HUnlock(d->dCtlStorage);
DisposeHandle(d->dCtlStorage);
d->dCtlStorage = NULL;
return noErr;
}
short main(IOParamPtr p, DCtlPtr d, short cmd) {
switch(cmd) {
case 0: return RomDrvOpen(p, d);
case 1: return RomDrvPrime(p, d);
case 2:
if(((CntrlParamPtr)p)->csCode == 21) {
*(Ptr*)&((CntrlParamPtr)p)->csParam = (Ptr)&DiskIcon;
return noErr;
} else if(((CntrlParamPtr)p)->csCode == 22) {
*(Ptr*)&((CntrlParamPtr)p)->csParam = (Ptr)&DiskIcon;
return noErr;
}
#if NEED_ACCRUN
if(((CntrlParamPtr)p)->csCode == accRun) {
RomDrvContext *ctx;
if(!d->dCtlStorage) return noErr;
ctx = *(RomDrvContext**)d->dCtlStorage;
if(ctx->useram && !ctx->origdisk) {
if (*((unsigned char *)0x0CB2)) { /* if we're already in 32-bit mode, allocate like this */
ctx->origdisk = NewPtrSys(kRomDrvSize);
if(ctx->origdisk) {
ctx->disk = (unsigned char *)RomDrvStripAddress((Ptr)ctx->origdisk);
ctx->copyfunc((unsigned char *)kRomDrvLocation, ctx->disk, kRomDrvSize);
}
} else {
ctx->ram24 = 1;
ctx->origdisk = NewPtrSys(1); /* just a dummy pointer to make rest of code work */
ctx->disk = (unsigned char *)(8*1048576);
ctx->copyfunc((unsigned char *)kRomDrvLocation, ctx->disk, kRomDrvSize);
}
}
d->dCtlDelay = 0;
d->dCtlFlags &= ~dNeedTimeMask;
return noErr;
}
#endif
return controlErr;
case 3:
#if NEED_DRVSTAT
if(!d->dCtlStorage) return statusErr;
if(((CntrlParamPtr)p)->csCode == drvStsCode) {
BlockMove(*d->dCtlStorage, &((CntrlParamPtr)p)->csParam, sizeof(DrvSts2));
return noErr;
}
#endif
return statusErr;
case 4: return RomDrvClose(p, d);
default: return noErr;
}
}