%File: Initial.mc Edited by Jim Frandeen, March 2, 1980 11:27 AM Delete Includes for Integration Procedure Edited by Joiner, February 28, 1980 2:54 PM recognize TOR for ether booting in bold Edited by Johnsson, February 4, 1980 5:00 PM % TITLE[Initial]; Insert[D0MPCodes]; *Error Codes for Fault Handler not in d0mpcodes MC[MOBCrash,202]; *Map Out of Bounds MC[H4PECrash,203]; *H4PE MC[MOB&H4PECrash,204]; *MOB and H4PE MC[MC2Crash,205]; *MC2 error when unable to handle it by RETURNing MC[MC22Crash,206]; *2 MC2 errors MC[MC1Crash,207]; *MC1 fault when emulator couldn't accept it MC[NStkCrash,166]; *Not Stack over/underflow (8 bits) SETTASK[17]; RV[REFR,77]; *memory refresh address RV[PipeReg,60]; *Pipe Ram Entry goes here MC[pPipeReg,360]; MC[pPipeReg2,362]; RV[PipeReg1,61]; RV[PipeReg2,62]; RV[PipeReg3,63]; RV[PipeReg4,64]; RV[PipeReg5,65]; SET[H4Disp,240]; SET[MC2ErDisp,260]; *The following registers hold the volatile state of the processor on a fault: RV[RXALU,76]; *ALU result and SALUF RV[RXAPC,75]; *APCTask&APC RV[RXCTASK,74]; *CTASK.NCIA RV[RXPPB,73]; *Page,Parity,BootReason RV[RXSTK,72]; *Stackpointer RV[RTMP,71]; *temporary RV[FFAULT,66]; SetTask[0]; RV[BootType, 20]; MC[pRTEMP1,IP[RTEMP1]]; Macro[LowHalf, and[#1,377]c]; Macro[HighHalf, and[#1,177400]c]; Set[InitBase, add[lshift[InitialPage, 10],100]]; SET[Qloc,ADD[InitBase,30]]; MC[QxL,AND[Qloc,377]]; MC[QxH,OR[150000,AND[Qloc,7400]]]; SET[QretLoc,Add[InitBase,32]]; MC[QRetL,AND[QretLoc,377]]; MC[QretH,AND[QretLoc,7400]]; Set[Task17Start, add[InitBase, 20]]; Set[Task16Start, add[InitBase, 22]]; *does a call => needs two locations Set[MidasStopLoc, add[InitBase, 25]]; *uses two locations Set[DeviceDispatch, add[InitBase, 40]]; OnPage[InitialPage]; SAAltoStart: BootType _ 0c, goto[Qtask], at[InitBase, 0]; SAPilotStart: BootType _ 1c, goto[Qtask], at[InitBase, 1]; EtherAltoStart: BootType _ 2c, goto[Qtask], at[InitBase, 2]; EtherPilotStart: BootType _ 3c, goto[Qtask], at[InitBase, 3]; EtherTestStart: BootType _ 17c, goto[Qtask], at[InitBase, 17]; Qtask: RTEMP _ QxL; *Quiesce tasks 15b - 1 RTEMP _ (RTEMP) or (QxH); RTEMP1 _ pRTEMP1; stkp _ RTEMP1; RTEMP1 _ QRetL; RTEMP1 _ (RTEMP1) or (QRetH); Qloop: APC&APCTASK _ RTEMP; initRET: return; *goes to Qx Qx: APC&APCTASK _ stack,call[initRET], AT[Qloc]; *Notify comes here. Leave task's TPC pointing at Qxy. Stack points at RTEMP1. Qxy: goto[initRET]; *must spend two instructions in the task Qret: lu _ ldf[RTEMP,0,3], AT[QretLoc]; *RTEMP1 points to this location RTEMP _ (RTEMP) - (10000c), dblgoto[ZapDevices, Qloop, alu=0]; ZapDevices: T _ RTEMP1 _ 177400C; RTEMP _ 300c; ZapDloop1: OUTPUT[RTEMP]; *send 300 to register 0 of all devices T _ RTEMP1 _ (RTEMP1) + (20c); goto[ZapDloop1,ALU<0]; T _ RTEMP1 _ 177400C; RTEMP _ 0c; ZapDloop2: OUTPUT[RTEMP]; *send 0 to register 0 of all devices T _ RTEMP1 _ (RTEMP1) + (20c); goto[ZapDloop2,ALU<0]; * Initialize tasks 17 and 16 RTEMP _ HighHalf[or[Task17Start,170000]]; RTEMP _ (RTEMP) or (LowHalf[Task17Start]); APC&APCTASK _ RTEMP, call[initRET]; RV[temp,51]; RV[initr0,52]; RV[initr1,53]; RV[initr2,64]; RV[initr3,65]; *Timers are cleared, refresh is running, start reason in BootType Task0: initr0 _ (50000C); * write fault instruction at[1] initr0 _ (initr0) or (150c); initr1 _ (65000C); initr1 _ (initr1) or (1c); initr2 _ (15C); initr3 _ (1C); t _ initr2 ; LU _ initr0; *T has data 2 APC&APCTASK _ initr3; WRITECS0&2; LU _ initr1; APC&APCTASK _ initr3; WRITECS1; T _ StartMapInit, call[ShowNumber]; goto[IMAP]; MemInitDone: Dispatch[BootType,14,4]; Disp[SAAlto]; * SA loader has two entry points depending on whether you want * Alto boot or Pilot boot. SAAlto: T _ StartDiskBoot, goto[SACommon], at[DeviceDispatch,0]; SAPilot: T _ StartDiskBootPilot, goto[SACommon], at[DeviceDispatch,1]; SACommon: call[ShowNumber]; LoadPage[SalLoaderPage]; BootType, dblgoto[SA4000Load, SA4000LoadPilot, REven]; * Ether loader takes a microcode boot file index (bfi) in T. The index * is used to select a boot file number (bfn) in the range 3000-3777. EtherAlto: BootType _ 1c, goto[EBCommon], at[DeviceDispatch,2]; EtherPilot: BootType _ 3c, goto[EBCommon], at[DeviceDispatch,3]; EtherTest: BootType _ 17c, goto[EBGo], at[DeviceDispatch,17]; * We know whether we want Alto or Pilot code. We must decide what IO * devices are on the machine. Only Display is interesting now. The * choices are: * UTLF, Dallas keyboard, UTVFC (bit clock rate 3) * CSL display & keyboard, UTVFC (bit clock rate 5) * The number entering in temp is incremented by 1 to select CSL display. EBCommon: T _ 0c; RTEMP _ 60c, call[SrShift]; * set all device tasks to 17 T _ 20c; RCNT _ (zero) - (T); * don't look forever T _ 3c; * use task 14 for test IDLoop: RTEMP _ 4c, call[SrShift]; T _ lshift[14,4]c; Input[RTEMP]; T _ 5000c; * UIB ID lu _ (lhmask[RTEMP]) xor (T); T _ 1000c, skip[alu#0]; * UTVFC ID GOTO[EBGo], BootType _ (BootType) + (4c); * TOR display lu _ (lhmask[RTEMP]) xor (T); RCNT _ (RCNT) + 1, skip[alu=0]; T _ 0c, dblgoto[IDLoop, NoDisplay, alu<0]; RTEMP _ ldf[RTEMP,10,5]; * get bit clock rate lu _ (RTEMP) xor (5c); skip[alu#0]; BootType _ (BootType) + 1; * CSL display EBGo: T _ (BootType) + (StartEtherBoot); T _ (BootType) + (T), call[ShowNumber];* StartEtherBoot+(2*bfi) LoadPage[EtherPage]; T _ BootType, gotop[EtherLoad]; NoDisplay: T _ NoUTVFC, goto[InitFail]; * return here with address of loaded code in T. MicrocodeLoaded: LP _ MicrocodeAddress, at [MicrocodeLoadedLoc]; T _ LPhi _ 0c; xfTemp1 _ T, LoadPage[LRJPage]; RTEMP1 _ 0c, gotop[LRJEnter]; * Enter with value in T, shift count in RTEMP. * Value is rotated right after each shift. SrShift: RTEMP1 _ T; RTEMP _ (RTEMP) - 1, GenSrClock; T _ RTEMP1 _ rcy[RTEMP1,1], goto[.-1, alu#0]; return; InitFail: RTEMP _ T, call[SNx]; goto[.]; ShowNumber: RTEMP _ T; SNx: LoadPage[0]; T _ (RTEMP) + (MPOffset), gotop[PNIP]; SetTask[17]; RTMP _ (400C), AT[Task17Start]; *set Printer idle, don't drive bus Printer _ RTMP; RTMP _ (100000C); ClearTimers: LOADTIMER[RTMP]; *Clear out all Timers RESETMEMERRS; *Clear any pending memory errors RTMP _ (RTMP) + 1; LU _ (RTMP) AND (17C); *there are 16d timers REFR _ (0C), GOTO[ClearTimers, ALU#0]; LU _ TIMER; *Set up the Refresh timer RTMP _ (50000C); RTMP _ (RTMP) OR (257C); *simple timer,value 10d,slot 17b LoadTimer[RTMP]; *Notify task 16 to set up timer task RTMP _ HighHalf[or[Task16Start,160000]]; RTMP _ (RTMP) OR (LowHalf[Task16Start]); APC&APCTASK _ RTMP, goto[InitRet]; SetTask[16]; Call[TimerRet], AT[Task16Start]; *Set TPC[16] to TimerTask *The simple timer task assumes slot 17 expired, since all others were cleared. TimerTask: Refresh[REFR]; lu _ Timer; *read timer to clear the wakeup REFR _ (REFR) + (20c); RTMP _ (50000C); *build timer constant RTMP _ (RTMP) OR (257C); *simple timer,value 10d,slot 17b AddToTimer[RTMP]; CheckStop: T _ (FFault) and (10000c); LU _ (Printer) AND (T) ; GOTO[MidasStop,ALU#0] ; TimerRet: RETURN; *Midas recognizes a mouse halt as a task 16 breakpoint that was *not set by the user. It continues from (absolute) MidasStop+1 MidasStop: LU _ T, goto[.], SetFault, at[MidasStopLoc]; MidasRestart: return, at[MidasStopLoc,1]; *Fault handler *Determine what to do based on the type of error and bits in FFAULT RM 366). *Bits in FFAULT are: * 0: MC2 errors RETURN if 1, crash if 0 * 2: H4PE errors from task 7 Return to the task that faulted rather * than crashing (because of Ethernet problem of delivering H4PE's * if a malformed packet arrives) * 3: Midas is present (1), so "crash" means breakpoint, else put a * code in MP and halt. * 15: MC1/StackOvf errors handled by notifying PFEntry in emulator (1), * or by crashing (0) *The following code (nearly a copy of the page 0 code in Kernel) sends *control to FaultStart after saving state, and FaultStart figures out whether *Midas is present and whether to send a breakpoint or a fault message. SetTask[17]; *Page Zero stuff * T _ APCTASK&APC, AT[1]; *Fault entry. Save APC first, then the other volatile regs. RXAPC _ T, At[100]; T _ CTask&NCIA, At[101]; RXCTask _ T, At[102]; T _ (SStkP&NStkP) xor (377C), At[103]; *uncomplement StkP RXStk _ T, At[104]; RTMP _ 20C, At[105]; *Set StkP to 20 in case stk ovf was pending StkP _ RTMP, At[106]; T _ (ALUResult&SALUF) xnor (0C), At[107]; *aluresult, saluf both read complemented RXALU _ T, At[110]; T _ Page&Par&Boot, LoadPage[0], At[111]; *page, parity, bootreason RXPPB _ T, ResetErrors, Goto[FaultStart], At[112]; FaultStart: lu _ (RXPPB) and (3000C), At[120]; *test R & CS parity Goto[RCSErr,ALU#0], lu _ (RXPPB) and (400C); *test memory error Goto[MC12Err,ALU#0], lu _ (RXPPB) and (4000C); *test stack ovf Goto[TryBP,ALU=0]; StkEr: Goto[Crash], T _ StkCrash; RCSErr: T _ RCSCrash, Goto[Crash]; TryBP: T _ BPCrash, Goto[Crash]; *Get here with error code in T. If Midas is present, breakpoint. Otherwise, *put the code into the maintenance panel and halt. Crash: lu _ LdF[FFAULT,3,1]; Goto[Midas,ALU#0], PipeReg5 _ (Lsh[PipeReg5,10]) or T; *save error code in right half of PipeReg5 RTMP _ MPOffset; T _ (RTMP) + (T), call[PNIP]; *add offset to fault code and then display it Goto[.]; Midas: RTMP _ 117c; *Reformat saved Pipe into RM 100-105 for Midas. Note that pipe info (other *than crash code and task number) is only interesting if CrashCode=205 StkP _ RTMP; SetTask[4]; *To allow symbolic names for RM 100-106 RV[MapEntryNumber,0]; RV[TaskNumber,1]; RV[RefType,2]; RV[CrashCode,3]; RV[CardNumber,4]; RV[MapFlags,5]; RV[QuadAddr,6]; RV[Syndrome,7]; SetTask[17]; T _ LdF[PipeReg,11,7]; *map row address PipeReg1 _ (Lsh[PipeReg1,7]) or T; *Map location (page number) in bits 2-17b... *goes into location 100 (but the bits are inverted) T _ LdF[PipeReg1,2,16], Call[FltPsh]; Stack _ (Stack) xnor (140000C); *now contains the virtual page number T _ 17C; *task number (upright)... T _ (LdF[PipeReg2,10,4]) xor T, Call[FltPsh]; *into location 101 T _ 17C; *reference type (upright)... T _ (LdF[PipeReg2,14,4]) xor T, Call[FltPsh]; *into location 102 T _ RHMask[PipeReg5], Call[FltPsh]; *Crash code into 103 T _ 7C; T _ (LdF[PipeReg5,4,3]) xor T, Call[FltPsh]; *Card no. (0..7) into 104 T _ 17C; T _ (LdF[PipeReg5,0,4]) xor T, Call[FltPsh]; *Map Flags (4 bits) into 105 T _ LdF[PipeReg4,12,6]; *Main column address (6 bits) T _ (Lsh[PipeReg3,6]) or T; *And Blk.1,,main row address T _ (Lsh[PipeReg5,16]) or T; *And Blk.0... *The (15-bit) quadword number within a 128k card. Bits 1:2 give block number. T _ (Zero) xnor T, Call[FltPsh]; *All upright into 106 T _ Rsh[PipeReg,10], Call[FltPsh]; *Interesting syndrome into 107 lu _ LdF[RXPPB,4,4]; *test parity register RTMP _ 177400C, Skip[ALU#0]; *Notify Midas at 7510b or 7512b RTMP _ (RTMP) or (110C), Goto[MidasNotify]; *Go overlay 'Break' RTMP _ (RTMP) or (112C); *Go overlay 'MidasFault' MidasNotify: APCTask&APC _ RTMP, Goto[PNret]; FltPsh: UseCTask, Stack&+1 _ T, Goto[PNret]; MC12Err: StkP _ RXSTK; *not stack error, restore pointer ReadPipe[PipeReg]; *get A pipe Dispatch[PipeReg,4,2]; *dispatch on H4pe, MapBnd Dispatch[PipeReg,0,2], Disp[NoH4BndEr]; *dispatch on MC2ErA', MC2ErB' NoH4BndEr: *test MC1ErA' bit lu _ (PipeReg) and (20000C), Disp[MC2ErAB], AT[H4Disp,0]; BndEr: T _ MOBCrash, Goto[Crash], AT[H4Disp,1]; *MOB error only H4Er: RTMP _ H4PECrash, Goto[Crash], AT[H4Disp,2]; *Note: the following is not quite correct, since a REAL MOB error will be *continued if it occurs with an H4PE. Life is hard... H4BndEr: RTMP _ MOB&H4PECrash, Goto[Crash], AT[H4Disp,3]; *H4PE & MOB *Both MC2 A & B error--crash MC2ErAB:T _ MC22Crash, Goto[Crash], AT[MC2ErDisp,0]; T _ LHMask[MemSyndrome], Goto[MC2Er], AT[MC2ErDisp,1]; *MC2A error ReadPipe[PipeReg], ResetMemErrs, Goto[MC2ErB1], AT[MC2ErDisp,2]; *MC2B error--read pipe entry Skip[ALU=0], ResetMemErrs, AT[MC2ErDisp,3]; *Branch if MC1ErA' = 0 ReadPipe[PipeReg], ResetMemErrs; *MC1B error--read pipe entry MC1Er: FFAULT, T _ MC1Crash, goto[Crash]; MC2ErB1:T _ Lsh[MemSyndrome,10]; MC2Er: ResetMemErrs; lu _ LdF[FFAULT,0,1]; *check for Return (1) or crash (0) *Stash the proper syndrome in PipeReg[0:7] PipeReg _ (RHMask[PipeReg]) or T, Skip[ALU#0]; T _ MC2Crash, Goto[Crash]; Return; *dummy version of DoInt. Task iff T<0 on entry. SetTask[0]; RV[R0,0]; DoInt: R0 _ T; R0, skip[R<0]; UseCTask; return; PNIP: usectask, RTEMP _ T; T _ APC&APCTask; RCNT _ T, ClearMPanel, call[.+1]; PNloop: RTEMP1 _ 4C; RTEMP1 _ (RTEMP1)-1, dblgoto[.+1,.,ALU<0]; RTEMP _ (RTEMP) - 1; lu _ ldf[RCNT,0,4], goto[PNdone, ALU<0]; skip[alu#0]; IncMPanel, return; * task =0, tasking ok IncMPanel, goto[PNloop]; * task #0, tasking not allowed PNdone: APC&APCTask _ RCNT; PNRet: return; :End[Initial]; (2048)\191b4B4669b147B