þa‹Rþw,*þ m_<þhý oUþ nSystem-wide$COMPACT NOLIST OPTIMIZE(3) DEBUG ROM $LARGE (SomeWhere EXPORTS CpDelay, CpSetKeyHandler, CpCatchAll, Upper, CpAddressOf, MakeCheckSum, ConLineOut, GPIBDriver, OsDskDriver, BubbleDriver, KeyRoutine) OsNewBoot: DO; /* This is os.newboot.plm. This resides in prom */ /* and will try to boot a compass (shadow) in the */ /* following order: bubble, winch, floppy. It will */ /* a character (b, w, f) at 0:ffff to indicate which*/ /* device to use. This trace will be used by the */ /* resides on disk. */ $INCLUDE (`w0`incs`plmlits.inc~text~) $INCLUDE (`w0`incs`os.device.inc~text~) /* constants */ DCL bootDrive LIT '0'; /* This is always 0 */ DCL bootStart LIT '200h'; DCL bootLength LIT '800h'; DCL systemPageSize LIT '200h'; DCL gpibIndex LIT '0'; DCL bubbleIndex LIT '1'; DCL winchIndex LIT '2'; DCL floppyIndex LIT '3'; DCL chipIndex LIT '4'; DCL numBootDevices LIT '4'; DCL numBootDevicesPlus1 LIT '5'; DCL floppyAddr LIT '5'; DCL winAddr LIT '4'; DCL chipAddr LIT '6'; DCL bubbleAddr LIT 'nullByte'; DCL eOK LIT '0'; DCL readKey LIT '2'; DCL keyboardEnable LIT '5'; DCL on LIT '1'; DCL off LIT '0'; DCL cr LIT '0dh'; DCL lf LIT '0ah'; DCL romBootChar LIT '72h'; /* 'r' */ DCL bootTraceIndex LIT '22'; $EJ /* variables */ DCL bootAddress BYTE AT (20006h); DCL buffer (1) BYTE AT (20000h); DCL gMsStatus MsStatusType AT (1f000h); DCL gBootPtr PTR; DCL gEntryPoint PTR; DCL gpPromVars PTR; DCL gPromVars BASED gpPromVars (1) BYTE; DCL gPl ParamListType; DCL gOldKeyHandler PTR; DCL gBootCharacter BYTE; DCL gChar BYTE PUBLIC; DCL gErrors (numBootDevicesPlus1) WORD EXTERNAL; /* moved to cp.task.asm. If numBootDevicesPlus1 changed */ /* then change it there */ DCL gDt (numbootDevicesPlus1) STRUCTURE (entryPoint PTR, intAddr BYTE, name BYTE) PUBLIC DATA (@GPIBDriver, nullByte, 'g', @BubbleDriver, nullByte, 'b', @OsDskDriver, winAddr, 'w', @OsDskDriver, floppyAddr, 'f', @OsDskDriver, chipAddr, 'c'); DCL copyRight (*) BYTE PUBLIC DATA ('Copyright (c) 1984 GRiD Systems Corporation'); $EJ /* externals */ KeyRoutine : PROCEDURE EXTERNAL; END; CpDelay : PROCEDURE (time) EXTERNAL; DCL time WORD; END; CpSetKeyHandler : PROCEDURE (pRoutine) PTR EXTERNAL; DCL pRoutine PTR; END; CpCatchAll : PROCEDURE (command, theData) WORD EXTERNAL; DCL (command, theData) WORD; END; Upper : PROCEDURE (char) BYTE EXTERNAL; DCL char BYTE; END; CpAddressOf : PROCEDURE PTR EXTERNAL; END; MakeCheckSum : PROCEDURE (pBuffer, length) WORD EXTERNAL; DCL pBuffer PTR; DCL length WORD; END; ConLineOut : PROCEDURE (pBuffer, length) EXTERNAL; DCL pBuffer PTR; DCL length WORD; END; RomBoot : PROCEDURE PTR EXTERNAL; END; /* gpib */ GPIBDriver : PROCEDURE (req, pPl, pError) EXTERNAL; DCL req WORD; DCL (pPl, pError) PTR; END; /* floppy and winchester */ OsDskDriver : PROCEDURE (req, pPl, pError) EXTERNAL; DCL req WORD; DCL (pPl, pError) PTR; END; /* bubble */ BubbleDriver : PROCEDURE (req, pPl, pError) EXTERNAL; DCL req WORD; DCL (pPl, pError) PTR; END; $EJ /* SetUpPl */ SetUpPl : PROCEDURE (pbuf, length, intAddr) REENTRANT; DCL pBuf PTR; DCL length WORD; DCL intAddr BYTE; CALL SETB(0, @gPl, SIZE(gPl)); gPl.intAddr = intAddr; gPl.pBuffer = pBuf; gPl.length = length; END; /* DoRead */ DoRead : PROCEDURE (bytePos, pbuf, length, index) WORD REENTRANT; DCL (bytePos, length, j, done, index, pagesize, error) WORD; DCL pBuf PTR; DCL buffer BASED pBuf (1) BYTE; done = 0; pageSize = gMsStatus.pageSize; DO j = 0 TO (length / pageSize) - 1; CALL SetupPl(@buffer(done), pageSize, gDt(index).intAddr); gPl.position = bytePos / pageSize; CALL gEntryPoint (DOUBLE(ddRead), @gPl, @error); IF error <> eOK THEN RETURN (error); done = done + pageSize; bytePos = bytePos + pageSize; END; RETURN (eOK); END; $EJ /* ShortKeyRoutine */ ShortKeyRoutine : PROCEDURE CLEAN; DCL char BYTE; DCL dummy PTR; /* Phil told me to write this gross code */ /* By the way, 20h = 'a' - 'A' */ gChar = Upper(LOW(CpCatchAll(readKey, 0))); IF (gChar >= 'A') AND (gChar <= 'Z') THEN gChar = gChar + 20h; IF (gChar = 'h') THEN gChar = 'w'; gBootCharacter = gChar; END; $EJ /* SetTimeOut */ SetTimeOut : PROCEDURE (intAddr, timeOut) REENTRANT; DCL intAddr BYTE; DCL (timeOut, error) WORD; DCL status STRUCTURE (req BYTE, len WORD); IF intAddr <> nullByte THEN DO; status.req = 2; status.len = timeOut; CALL SetUpPl(@status, SIZE(status), intAddr); CALL gEntryPoint(DOUBLE(ddSetStatus), @gPl, @error); END; END; $EJ /* TryIt */ TryIt : PROCEDURE (index) BOOLEAN REENTRANT; DCL (index, error, same) WORD; DCL intAddr BYTE; gEntryPoint = gDt(index).entryPoint; intAddr = gDt(index).intAddr; IF gErrors(index) <> eOK THEN RETURN (FALSE); CALL SetTimeOut(intAddr, 1000); CALL SetUpPl(@gMsStatus, SIZE(gMsStatus), intAddr); CALL gEntryPoint(DOUBLE(ddGetStatus), @gPl, @error); CALL SetTimeOut(intAddr, 15000); IF error <> eOK THEN DO; CALL SetUpPl(@error, 0, intAddr); CALL gEntryPoint(DOUBLE(ddDeactivate), @gPl, @error); RETURN (FALSE); END; error = DoRead(0, @buffer, systemPageSize, index); IF error <> eOK THEN RETURN (FALSE); same = CMPB(@buffer, @('System Disk!'), 12); IF same <> nullWord THEN DO; /* check for Ms-Dos boot */ IF (buffer(510) = 55h) AND (buffer(511) = 0aah) THEN DO; gBootPtr = @buffer; END; ELSE RETURN (FALSE); END; ELSE DO; gBootPtr = @bootAddress; error = DoRead(bootStart, @buffer, bootLength, index); IF (MakeCheckSum(@buffer, bootLength) <> 0) THEN DO; CALL ConLineOut(@('Cannot boot: Checksum error', cr, lf), 29); RETURN (FALSE); END; END; gPromVars(bootTraceIndex) = gDt(index).name; RETURN (error = eOK); END; /* TryToBootRom */ TryToBootRom : PROCEDURE BOOLEAN; gBootPtr = RomBoot; gPromVars(bootTraceIndex) = romBootChar; RETURN (gBootPtr <> nullPtr); END; $EJ /* Boot */ Boot : PROCEDURE REENTRANT; DCL booted BOOLEAN; DCL j WORD; CALL CpDelay(1000); /* delay for bubble */ DO WHILE TRUE; DO j = 0 TO numBootDevices; /* initialize each device */ CALL SETB(0, @gPl, SIZE(gPl)); gPl.intAddr = gDt(j).intAddr; gEntryPoint = gDt(j).entryPoint; CALL gEntryPoint (DOUBLE (ddInitialize), @gPl, @gErrors(j)); END; IF gBootCharacter = 'r' THEN DO; booted = TryToBootRom; END; ELSE IF gBootCharacter = 'f' THEN DO; booted = TryIt(floppyIndex); IF NOT(booted) THEN DO; booted = TryIt(chipIndex); END; END; ELSE IF gBootCharacter = 'w' THEN DO; booted = TryIt(winchIndex); END; ELSE IF gBootCharacter = 'b' THEN DO; booted = TryIt(bubbleIndex); END; ELSE DO; booted = TryToBootRom; IF NOT(booted) THEN DO; DO j = 1 TO numBootDevices; booted = TryIt(j); IF booted THEN GOTO LoopExit; END; END; END; LoopExit: IF booted THEN DO; j = CpCatchAll(keyboardEnable, off); /* disable keyboard */ gOldKeyHandler = CpSetKeyHandler(gOldKeyHandler); CALL SETW(0, 400h, 9600/2); /* clear screen */ CALL gBootPtr; END; CALL ConLineOut(@('Cannot boot: Storage medium error', cr, lf), 35); CALL CpDelay(2000); /* delay for person to decide */ END; END; $EJ /* DoBoot */ DoBoot : PROCEDURE CLEAN; DCL j WORD; gpPromVars = CpAddressOf; gOldKeyHandler = CpSetKeyHandler(@KeyRoutine); j = CpCatchAll(keyboardEnable, on); /* enable keyboard */ CALL Boot; END; END;