mirror of
https://github.com/elliotnunn/NetBoot.git
synced 2024-10-11 03:23:38 +00:00
1 line
10 KiB
C
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;
|
|
}
|
|
} |