*----------------------------------------------------------- Title[PilotLeftovers.mc...May 2, 1984 5:08 PM...Willie-Sue]; * Pilot-related stuff that doesn't seem to belong anywhere else. * A lot of this originally came from the Alto emulator. *----------------------------------------------------------- TopLevel; % *----------------------------------------------------------- The microcode is started in one of the following ways: 1. Loaded by Midas and started at InitMap. 2. Self-restarted at Boot by display task in response to 1-push boot. 3. Restarted by BaseBoard at InitMap in response to 2-push boot. 4. Boot-loaded by BaseBoard/Initial and started at BootOrStart. 5. Loaded by software (RunPilot, MesaNetExec) and started at BootOrStart. In cases 1-4, we want to go through the full memory system initialization and Germ bootstrap sequence. In case 5, software has already set up memory with the appropriate stuff (presumably some flavor of Germ), and we do NOT want to disturb it. The problem is to distinguish cases 4 and 5, since they both enter at BootOrStart. (This is a consequence of having only one .eb file for both purposes, and thus only one public starting address.) We handle this by the following kludge: if page 37002 (the first page of the Germ) is already mapped then case 5 is assumed; otherwise case 4. % *----------------------------------------------------------- *----------------------------------------------------------- * Display task branches here on a 1-push boot (case 2). *----------------------------------------------------------- Set[XTask, IP[DHT]]; DontKnowRBase; Boot: Call[TasksOff]; Call[EmuInitPC]; LdTPC← T, TaskingOn; Block; * should never awaken again, since we did an I/O Reset. Breakpoint, Branch[.]; Subroutine; EmuInitPC: T← EMU, CoReturn; * Return EMU start PC TopLevel; Branch[InitMap]; *----------------------------------------------------------- * .eb-format microcode image is started here (cases 4 and 5). *----------------------------------------------------------- Set[XTask, IP[EMU]]; MC[FirstMapDirtyBitsAddr, LSHIFT[360, 10]]; * last 20C pages MC[SetVacant, 140000]; MC[TestVacant, 30000]; BootOrStart: At[BootOrStartLoc], RBase← RBase[RTemp0]; Call[TasksOff]; T← 37000C; T← T OR (2C); Call[SetBRForPage]; * Read Map[37002B] RMap← RTemp0, Call[TestForVacant]; branch[.+2, alu#0]; Branch[InitMap]; * vacant, do full map/mem init Fetch← RTemp0, T← 3000C; * test if page contains valid data T← T OR (354C); pd← T XOR (Md); * word 0 of germ is 3354C on Dorado branch[.+2, alu = 0]; * branch if valid Branch[InitMap]; * invalid (word 0 # 3354C) RBase← RBase[RealPages]; Call[GetMemConfig]; * registers not set RBase← RBase[RTemp0], T← T-T-1, Branch[.+2]; * not vacant, fall through *----------------------------------------------------------- * InitMap returns here when done. *----------------------------------------------------------- StartEmulator: T← A0; * Full initialization RBase← RBase[AEmRegs]; ETemp4← T, TaskingOff; R400← 400C, Call[SetupBRs]; * returns with MemBase set up T← A0, NoReschedule; InsSetOrEvent← T; * Disable event counters MaintPanel← A0, IFUReset; Call[RestoreALUFM]; * Restore ALUFM variables * make sure keys are all 1's -- core image does not contain page 376b T← (R400) XOR (177433C); ETemp1← T-T-1, Cnt← 6S; * Initialize 177033B..177041B T← (Store← T)+1, DBuf← ETemp1, Branch[., Cnt#0&-1]; *----------------------------------------------------------- * appropriate the last 64K of virtual memory, and use the last 16 pages for the extra * map dirty bits * start from the low end of virtual emmory and find the first vacant page, then then use * the preceeding pages of real memory for the map dirty bits. *----------------------------------------------------------- RBase← RBase[RTemp0]; Membase ← MapBitsBR, RTemp1← A0; * check if MapBitsBR has real already been assigned RMap← RTemp1; Call[WaitForMap]; T← VaHi; RBase← RBase[RealPages], T← T + 1; PD← (VirtualBanks) XOR T; branch[.+2, alu#0], T← (VirtualBanks) - 1; branch[InitTasks]; * don't do again BrHi← T; T← RealPages, RBase← RBase[RTemp0]; RTemp5← RSH[T, 14]; * no. of pages needed for dirty bits T← FirstMapDirtyBitsAddr; BrLo← T, RTemp0← A0; Membase← LPtr, T← RTemp1← A0; RTemp2← (BrLo← T); Find1: T← (BrHi← RTemp1); Find2: RMap← RTemp2; Call[TestForVacant]; branch[FoundVacant, alu=0], RTemp2← (RTemp2) + (400C); branch[Find2, alu#0]; RTemp1← (RTemp1) + 1, branch[Find1]; * RTemp2 now points 2 pages (1000C) beyond the last page mapped into memory * RTemp1 has hi part of address in LPtr * RTemp0 still has 0 * use RTemp4 to address relative to MapDirtyBR FoundVacant: RTemp4← A0; RTemp3← SetVacant; RTemp2← (RTemp2) - (1000C); Found1: branch[.+2, carry], RTemp1← (RTemp1) - 1; BrHi← RTemp1; BrLo← RTemp2; * Flush all munches in this page before setting vacant RTemp6← A0, Cnt← 17S; RTemp6← Flush← RTemp6, Carry20, Branch[., Cnt#0&-1]; TIOA← RTemp3; Map← 0s, Mapbuf← RTemp0; * set real page to zero, mark as vacant Call[WaitForMap]; * returns with previous real page in T Membase← MapBitsBR; TIOA← RTemp0; * set flag to zero Map← RTemp4, Mapbuf← T; Call[WaitForMap]; RTemp5← (RTemp5) - 1; branch[Found2, alu<=0]; RTemp4← (RTemp4) + (400C); Membase← LPtr; RTemp2← (RTemp2) - (400C), branch[Found1]; Found2: RBase← RBase[ETemp0], Branch[InitTasks]; *----------------------------------------------------------- * Wait for map, returns current real page in T *----------------------------------------------------------- Subroutine; WaitForMap: PD← T - T - 1; T← PRef, branch[., alu<0]; * wait for map Return, T← Not (Map'); * Returns with alu=0 test for vacant TestForVacant: PD← PRef; T← NOT (Map'), branch[.+2, alu>=0]; * wait for map PD← PRef, branch[.-1]; T← NOT (Errors'); * flags nop; T← T AND (TestVacant); PD← T XOR (TestVacant), Return; Toplevel; *----------------------------------------------------------- * Task initialization routines all work according to the following pattern: * XXXInitPC: * T← XXX, CoReturn; * T← task number * first instruction of task initialization; * Thus, calling XXXInitPC loads Link with the PC of the first instruction * of the init routine and T with the task number. These are precisely * the arguments needed to do a LdTPC! * Note: leave FF free in calls to the XXXInitPC routines. * ETemp4 = 0 if booting, -1 if restarting emulator. *----------------------------------------------------------- InitTasks: * First, init all non-emulator task PCs to -1. ETemp1 = -1 here. ETemp0← 17C; Link← ETemp1; ETemp0← (ETemp0)-1, LdTPC← ETemp0; Branch[.-2, ALU#0]; * Now init specific task PCs Call[JNKInitPC]; LdTPC← T, Wakeup[JNK]; Call[EOTInitPC]; LdTPC← T, Wakeup[EOT]; Call[EITInitPC]; LdTPC← T, Wakeup[EIT]; Call[DSKInitPC]; LdTPC← T, Wakeup[DSK]; Call[FLTInitPC]; LdTPC← T, Wakeup[FLT]; Call[AUTInitPC]; LdTPC← T, Wakeup[AUT]; * Display task initialization is slightly complicated, because the tasks * must be set up according to whether the Alto terminal is hooked to the * DispY board or the DispM board. * DisplayInitConfig figures out what the configuration is, and sets a flag. * Next, DHTInitPC and DWTInitPC return the starting PCs and task numbers * for special (non-Alto terminal) microcode that may be present, or for * dummy microcode in DisplayMain otherwise. * Finally, THTInitPC and TWTInitPC return the starting PCs and task numbers * for the Alto terminal microcode; the task numbers will be either AHT/AWT * or DHT/DWT, depending on whether or not the DispM board is installed. * If no DispM board is installed, this initialization will override the * earlier DHT/DWT task initialization. * Note: THTInitPC handles its own wakeup, since there's no way to * issue Wakeup to a task given as a variable. IFUReset; * Here to break consecutive .+1 constraints Call[DisplayInitConfig]; KnowRBase[TWTRegion]; Call[DHTInitPC]; * For special display microcode LdTPC← T, Wakeup[DHT]; Call[DWTInitPC]; LdTPC← T; Call[THTInitPC]; * For Alto terminal microcode LdTPC← T; Call[TWTInitPC]; LdTPC← T, RBase← RBase[AEmRegs]; ETemp4, TaskingOn, Branch[.+2, R<0]; * Want to boot? Branch[GermBoot]; * Yes, go boot the Germ Branch[MGo]; * No, just start the Mesa emulator *----------------------------------------------------------- SetupBRs: * Initialize all Base Registers. * Clobbers T and ETemp. *----------------------------------------------------------- Subroutine; T← LShift[37, 10]C; * MemBase addressed from A[3:7] DoBRs: ETemp← A0, MemBase← T; * Init all registers to {0, 0} BRHi← ETemp; T← T-(400C); BRLo← ETemp, Branch[DoBRs, ALU>=0]; MemBase← IOBR, Return; * return with correct MemBase *----------------------------------------------------------- TasksOff: * Reset all I/O devices. * This is now accomplished simply by issuing an IOReset. * IOReset is controlled by the manifold register addressed by 2240-2257, * which has the following things in it (DMAdr[0:11]): * Bit 8: EclUp (normally 1) * Bit 9: EnableRfPd' (normally 0) * Bit 10: IOReset' (normally 1) * Bit 11: RunRfsh (normally 1) * Returns with TaskingOff, RBase=AEmRegs. *----------------------------------------------------------- Subroutine; TaskingOff; T← A0, RBase← RBase[ETemp4]; ETemp4← Link; TopLevel; TIOA← T; * Don't address any IO register ETemp1← 2000C; T← (ETemp1) OR (251C), Call[SetDMuxAddress]; * IOReset' ← 0 UseDMD; T← (ETemp1) OR (253C), Call[SetDMuxAddress]; * IOReset' ← 1 Subroutine; Link← ETemp4; UseDMD, Return; *----------------------------------------------------------- RestoreALUFM: * Restores the ALUFM variables to their standard values. * Clobbers T *----------------------------------------------------------- Subroutine; T← AFM15; ALUFMRW← T, ALUF[15]; T← AFM17; ALUFMRW← T, ALUF[17], Return; *----------------------------------------------------------- * some locations for doing code patching * make sure FF is not used for LONGGO *----------------------------------------------------------- LX0: TaskingOn; TaskingOn, PD← T; TaskingOn, Branch[.+2, ALU=0]; TaskingOn; TaskingOn, PD← T; TaskingOn, Branch[.+2, ALU#0]; TaskingOn; LX7: TaskingOn, Branch[LX0]; TopLevel;