//D0I2.BCPL -- machine-dependent part of Init2() // Last edited: 1 March 1982 //Implements final machine-dependent init when starting Midas, doing //"Run-Prog", or doing "Boot". All initialization needed to restore //the display to its initial arrangement should be carried out. get "mcommon.d" get "d0.d" manifest [ get "d0regmem.d" ] external [ // OS SetBlock; Zero // MINIT0 @MBlock; MStatus // MINIT2 Initialized // MASM @WssCSS; WssCS1; ResetsCSS; ResetsCS1; Wait; GetStorage // MDATA MDATAtab; MADDRtab; @BitsChecked; @HighAddress; @AddrIncrement MCTimeOut // MIDAS MidasSwat // MMENU @WsMarkA; AbortingCFile // MMPRGN UpdateMPDValues // MCMD WnsCS1D; WnsCSSD; SetAbortPure; CmdAbort; @CmdAbortAct // MGO @CantContinue // D0I0 HWStatus; BPTable; BootTable; NBootInst // D0TABLES @MEMNAM; @MEMLEN // D0ASM recvbyte; recvword; sendbyte; sendword; @utilin; @utilout d0recvbyte; d0recvword; d0sendbyte; d0sendword ReadPrinter; WritePrinter // D0REG ReadAllRegs // D0MEM readrr; sovlcurr // D0GO Stop; d0Stop // D0VM SetVirtP; IMstab; RMstab // Defined here InitHardware; DefMemName ] static [ DefMemName KernelStartLoc = #7000 //********may change if kernel.mb changes BootEStr; BootEFlg ] //Result is 0 or an alternate command-menu forming procedure used //to select among several target machines. let InitHardware() = valof [ //Check engineering number to determine whether Midas is running on an //Alto (EngNum = 0 to 3), Dolphin (EngNum=4), or Dorado (EngNum=5). //Different printer interface is used on the Dolphin, and Midas won't run //on a Dorado. let EngNum = (table[ #61014; #1401 ] )() EngNum = EngNum rshift 12 test EngNum < 5 ifso if EngNum eq 4 do [ Init2Boot = D0Init2Boot Init2WaitAck = D0Init2WaitAck SendBootByte = D0SendBootByte recvbyte,recvword = d0recvbyte,d0recvword sendbyte,sendword = d0sendbyte,d0sendword Stop = d0Stop ] ifnot MidasSwat(2019) //"Midas only runs on Altos and Dolphins" SetVirtP(false) DefMemName = MEMNAM!VMx //Clear the breakpoint table SetBlock(BPTable,#7777,BPlen*4) //Zero the error counters and initialize test-control stuff in fake //memories. Zero(MDATAtab,MDATAlen*3) Zero(MADDRtab,MADDRlen*2) MBlock(BitsChecked,table [ -1; -1; #170000 ] , 3) SetBlock(HighAddress,-1,2) AddrIncrement!1 = 1 //Initialize inverted tables for FastSearch //(Can't use GetZStorage becasue it is swapped out) let IMstablen = MEMLEN!(IMXx+IMXx+1) rshift (BlockShift+1) IMstab = GetStorage(IMstablen); Zero(IMstab,IMstablen) let RMstablen = (MEMLEN!(RMx+RMx+1)+1) rshift 1 RMstab = GetStorage(RMstablen); Zero(RMstab,RMstablen) MStatus>>MStatus.MachRunning = false // MStatus>>MStatus.MachRunning = not CheckStopped() sovlcurr = 0 //clear last overlay number if HWStatus>>HWStatus.ConnectedMachine eq -1 do [ CantContinue = didBoot //If the boot fails, indicate that we are connected anyway HWStatus>>HWStatus.ConnectedMachine = 0 ResetsCSS(); ResetsCS1() for BootFailCount = 0 to 9 do [ Init2Boot() Wait(2000) //200 msec to let it boot let BootBad = false //Transfer m-i from MIM to hardware for I = BootTable by 3 to BootTable+((NBootInst-1)*3) do [ if SendBootWord(I!2 & #7777) then if SendBootWord(I!0) then if SendBootWord(I!1) then if SendBootByte(I!2 rshift 12) then loop BootBad = true MCTimeOut!6 = (I-BootTable)/3 //How far into boot break ] test BootBad ifso [ BootEStr = "Communication error during KERNEL transmission" BootEFlg = true ] ifnot //start kernel [ if SendBootByte(#200 % (KernelStartLoc rshift 8)) then if SendBootByte(KernelStartLoc & #377) do //**What is this waiting for??? [ for i = 0 to #20000 do [ if Init2WaitAck() eq 0 then break ] if recvbyte() eq #100 do //Successfully booted [ ReadAllRegs() if BootFailCount ne 0 do [ WssCSS("Boot succeeded after ") WnsCSSD(BootFailCount); WssCSS(" failures") ] resultis 0 ] ] BootEStr = "KERNEL did not start up" BootEFlg = false ] ] SetAbortPure(lv BootAbort,nil) resultis BootFailMenu //Boot failed return ] UpdateMPDValues(); resultis 0 ] and BootAbort(nil,nil,nil) be [ ReadAllRegs() if MStatus>>MStatus.CFileStream ne 0 then AbortingCFile = 1 CmdAbort() ] and BootFailMenu(S,nil) be [ WssCSS("Boot failed 10 times: ") WssCSS(BootEStr) if BootEFlg do [ WssCS1(((MCTimeOut!7 & #170000) ne 0 ? "Uack didn't drop after acknowledge", ((MCTimeOut!7 & #7400) ne 0 ? "Didn't receive Uack", ((MCTimeOut!7 & #360) ne 0 ? "Uack not clear initially","Direction incorrect")))) WssCS1(" transmitting microinstruction ") WnsCS1D(MCTimeOut!6) ] WsMarkA(CmdAbortAct) ] and Init2Boot() be //**Alto only [ //Set quiescent state @utilout = not #440; @utilout = not #40440; @utilout = not #440 //Boot it @utilout = not #400; @utilout = not #40400; @utilout = not #400 //Set quiescent state @utilout = not #440; @utilout = not #40440; @utilout = not #440 ] and D0Init2Boot() be //**Dolphin only [ WritePrinter(#20400) WritePrinter(#400) WritePrinter(#20400) ] and Init2WaitAck() = valof //**Alto only [ @utilout = not #1400 resultis (@utilin & #10000) ] and D0Init2WaitAck() = valof //**Dolphin only [ resultis (ReadPrinter() & #4000) ] //Send one byte to D0 via printer interface. //We expect the d0 to have uack cleared, bus direction set //read nibble 1, keep drive off, utilout is inverted, utilin is not and SendBootByte(bite) = valof //**Alto only [ @utilout = not #1400 let tst = nil //Check for direction incorrect (count in nib3) if (@utilin & #10000) eq 0 then [ MCTimeOut!7 = MCTimeOut!7 + 1; resultis false ] //Check for write ack not clear initially (count in nib2) if (@utilin & #40000) ne 0 then [ MCTimeOut!7 = MCTimeOut!7 + #20; resultis false ] //Set the upper byte to quiescent state (boot bit high), drive data @utilout = not #40; @utilout = not #40040; @utilout = not #40 //Load low byte of tester output register @utilout = not bite; @utilout = not (bite % #100000) @utilout = not bite //Send iack (?write strobe?) @utilout = not #240; @utilout = not #40240; @utilout = not #240 //The d0 should respond instantly by raising write ack (#2000). The //bit we expect is the second bit of nibble 1, on Utilin[01] //Set to read nibble from tester @utilout = not #1000 //Check for write ack not coming up (count in nib1) if (@utilin & #40000) eq 0 then [ MCTimeOut!7 = MCTimeOut!7 + #400; resultis false ] //Drop isend (?write strobe?), keeping boot bit high, turn drive off @utilout = not #40; @utilout = not #40440; @utilout = not #440 //Expect the d0 to drop write ack immediately @utilout = not #1400 //Check for write ack not dropping immediately (count in nib0) if (@utilin & #40000) ne 0 then [ MCTimeOut!7 = MCTimeOut!7 + #10000; resultis false ] resultis true ] //NOTE: The only difference between use of the printer interface during //booting and during regular operation is that during booting wprinter is //acknowledged by the #10000 bit in rprinter becoming 1; during normal //operation it is acknowledged by the #100000 bit becoming 1. and D0SendBootByte(bite) = valof //**Midas running on Dolphin only [ WritePrinter(#20400) //#20000 = not booting // #400 = debugger's direction to debugger let tst = nil //Tiny delay //Verify debuggee's direction to debuggee (count errors in nib3) if (ReadPrinter() & #4000) eq 0 then [ MCTimeOut!7 = MCTimeOut!7 + 1; resultis false ] //Verify debuggee's write ack clear initially (count errors in nib2) if (ReadPrinter() & #10000) ne 0 then [ MCTimeOut!7 = MCTimeOut!7 + #20; resultis false ] //Set the upper byte to quiescent state (boot bit high), drive data WritePrinter(#20000+bite) tst = nil WritePrinter(#120000+bite) //Turn on write strobe tst = nil //Tiny delay //The D0 should respond instantly by raising boot write ack (#10000). //Check for write ack not coming up (count errors in nib1) if (ReadPrinter() & #10000) eq 0 then [ MCTimeOut!7 = MCTimeOut!7 + #400; resultis false ] //Turn off write strobe and leave direction bit in a good state WritePrinter(#20400) tst = nil //Tiny delay //Check for write ack not dropping immediately (count in nib0) if (ReadPrinter() & #10000) ne 0 then [ MCTimeOut!7 = MCTimeOut!7 + #10000; resultis false ] resultis true ] and SendBootWord(wurd) = valof [ if SendBootByte(wurd rshift 8) then if SendBootByte(wurd & #377) then resultis true resultis false ]