*----------------------------------------------------------- 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;