*----------------------------------------------------------- Title[AEm0.mc...January 27, 1984 3:08 PM...Taft]; * Alto Emulator initialization and software boot sequence. *----------------------------------------------------------- *----------------------------------------------------------- * Canonical place to restart the Alto Emulator running as DHT or AHT task. * Display task branches here when it sees the boot button down. *----------------------------------------------------------- TopLevel; Set[XTask, IP[DHT]]; DontKnowRBase; Boot: Call[TasksOff]; Call[EmuInitPC]; * Set emulator PC to "SW" LdTPC← T, TaskingOn; Block, Branch[.]; *----------------------------------------------------------- * Start at StartEmulator during a full initialization (from InitMap). * Start at SW during a self-initiated "hot boot" (forced by display task). * Start at RestartEmulator for "soft-restart" -- restart I/O devices and * resume the Alto emulator, without disturbing registers or main memory. * Start at MBS to start an already-loaded core image whose starting PC is * in location 0 (this is the convention for Ether-bootable programs). *----------------------------------------------------------- Set[XTask, IP[EMU]]; DontKnowRBase; * For full initialization, reset the default disk partition and * request "cold boot" (reset memory). StartEmulator: ETemp4← A0, Branch[ResumeEmulator]; * For emulator soft-restart, request "hot boot" (don't disturb memory). RestartEmulator: At[RestartEmulatorLoc], Call[TasksOff]; ETemp4← T-T-1, Branch[InitMapWarm]; * for starting a core image loaded by Midas MBS: At[MBEmulatorLoc], Call[TasksOff]; * Returns with T=0 ETemp4← T+1, Branch[InitMapWarm]; * ETemp4← odd, start existing core image Subroutine; EmuInitPC: T← EMU, CoReturn; * Return EMU start PC TopLevel; DontKnowRBase; SW: T← 2C; ETemp4← T; * Full boot but don't change partition * Back here from InitMapWarm * ETemp4 signals what to do: * -1 => soft restart (resume emulator after microcode initialization) * 0 => full boot * 1 => start core image that has been loaded manually (e.g., by Midas) * 2 => full boot without changing disk partition ResumeEmulator: TaskingOff; RBase← RBase[AEmRegs]; R400← 400C, Call[SetupBRs]; * returns with MemBase set up T← T-T-1, ETemp4, Branch[InitTasks, R<0]; * Skip following stuff if hot boot Cry← T← A0, NoReschedule; InsSetOrEvent← T; * Disable event counters NWW← 100000C; * Start with interrupts disabled spAC0← T← Add[nspAC0]C; * Set up alto emulator RM constants spAC1← T← T+1, IFUReset; spAC2← T← T+1, Cnt← 2S; spAC3← T+1, Call[RestoreALUFM]; * Restore ALUFM variables * make sure keys are all 1's -- core image does not contain page 376b T← (R400) XOR (177434C); T← (Store← T) + 1, DBuf← -1C, Branch[., Cnt#0&-1]; * 177034 .. 177036 Store← T, T← DBuf← -1C; * 177037 *----------------------------------------------------------- * 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. T = -1 here. ETemp0← 17C; Link← T; 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. Nop; * Placement 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[AEmuNext, R<0]; * Want to boot? PD← ETemp4, Branch[ABoot, R Even]; * Yes, Alto emulator Branch[StartMB]; * starting midas loaded memory *----------------------------------------------------------- * Alto software boot sequence. * Read keyboard to decide whether to boot from disk or Ethernet. *----------------------------------------------------------- ABoot: * If appropriate, reset the disk partition to the maximum possible. RBase← RBase[DefaultPartition], Branch[.+2, ALU#0]; DefaultPartition← MaxPartition; RBase← RBase[AEmRegs]; * Wait at least 100 ms to allow terminal to update all keyboard words. * There are 5 of these, sent at 17 ms intervals. T← (R400)+(30C); * RTC = VM 430 ETemp0← (Fetch← T)-(10C); Store← ETemp0, DBuf← 0C; * Zero the display list (VM 420) ETemp0← (3S)+MD; * now + 3*39 ms PD← (ETemp0)-MD; Fetch← T, Branch[.-1, ALU>=0]; ETemp3← A0, IFUReset; * ETemp3 used in DiskBoot T← (R400) XOR (177434C); * VM 177034 = first keyboard word T← (Fetch← T)+1; T← (Fetch← T)+(2C), ETemp0← MD; * ETemp0← word 0 T← (Fetch← T)-1, ETemp1← MD; * ETemp1← word 1 Fetch← T, T← A0, ETemp2← MD, * ETemp2← word 3 ETemp0, Branch[EBoot, R even]; * Branch if BS key was down *----------------------------------------------------------- * Disk boot. *----------------------------------------------------------- * If any of the digits 1 through 9 is pressed down, reset the default disk * partition as specified (1 through 5 => partitions 1 through 5; * 6 through 9 => partitions 16 through 19). PD← MD, Call[SelectPartitionIfKey]; * "1" -- MD = word 2 here PD← LSH[ETemp1, 1], Call[SelectPartitionIfKey]; * "2" PD← ETemp1, Call[SelectPartitionIfKey]; * "3" PD← LSH[ETemp0, 1], Call[SelectPartitionIfKey]; * "4" PD← ETemp0, Call[SelectPartitionIfKey]; * "5" T← 17C; PD← LSH[ETemp0, 2], Call[SelectPartitionIfKey]; * "6" => 16 PD← LSH[ETemp0, 4], Call[SelectPartitionIfKey]; * "7" => 17 PD← LSH[ETemp2, 5], Call[SelectPartitionIfKey]; * "8" => 18 PD← LSH[ETemp1, 6], Call[SelectPartitionIfKey]; * "9" => 19 * Disk boot (cont'd) * Make up disk command starting at location 431 (cursor bit map). * Code depends on command block address being odd. ETemp3=0 here. DiskBoot: ETemp2← 17C; * Init retry count DiskBootRetry: T← (R400)+(31C); T← (Store← T)+1, DBuf← ETemp3; * next CB pointer = 0 T← (Store← T)+1, DBuf← ETemp3; * initial status = 0 ETemp0← (Store← T)+1, DBuf← ACmmdSeal; * read command T← (R400)+(2C); ETemp0← (Store← ETemp0)+1, DBuf← T, * Store both header and label at 402 Branch[., R even]; * This instruction is executed twice ETemp0← (Store← ETemp0)+1, DBuf← 1C; * Store data at 1 ETemp0← (Store← ETemp0)+1, DBuf← 0C, * Normal and error interrupts = 0 Branch[., R odd]; * This instruction is executed twice PD← (ETemp2) AND (7C); * Every 8 retries do a restore first T← (ETemp0)+1, Branch[.+2, ALU=0]; * Unused word Store← T, DBuf← 0C, Branch[.+2]; * diskAddr = 0 Store← T, DBuf← 1C; * diskAddr = 0 and restore * Issue the disk command. T← (R400)+(123C); * 523B T← (Store← T)-1, DBuf← -1C; * previous diskAddr unknown ETemp1← (Store← T)-1, DBuf← 0C; T← (R400)+(31C); Store← ETemp1, DBuf← T; * 521b← 431b -- address of disk command * Wait up to 1 second for disk status to appear in location 432 T← (R400)+(30C); * VM 430 = real time clock Fetch← T, ETemp0← 33C; ETemp0← (ETemp0)+MD; * Now + 27*39 ms KWait: ETemp1← (Fetch← T)+(2C); * VM 432 = status for disk command PD← (ETemp0)-MD-1; Fetch← ETemp1, ETemp1← DoneStatus, Branch[KBootTimeout, ALU<0]; PD← (ETemp1) AND (MD), ETemp1← MD; PD← (ETemp1) AND (377C), Branch[KWait, ALU=0]; * error bits in status word ETemp2← (ETemp2)-1, Branch[.+2, ALU#0]; T← 1C, Branch[Start]; * Successful, PC←1 and run the code Branch[DiskBootRetry, ALU>=0]; * too many tries? DiskBootError: Branch[EBoot]; * If hard error, do an Ether boot instead KBootTimeout: Branch[EBoot]; * If timeout, do an Ether boot instead *----------------------------------------------------------- SelectPartitionIfKey: * Facilitates testing keys for partition selection. * Increments T; then, if ALU>=0 upon entry, sets the disk partition to T * and branches to DiskBoot instead of returning. *----------------------------------------------------------- Subroutine; T← T+1, Branch[.+2, ALU>=0]; Return; DefaultPartition← T, Branch[DiskBoot]; *----------------------------------------------------------- SetupBRs: * Initialize all Base Registers. * EmuBRHiReg contains the high part of MDS, the BR defining the 64K region * within which the Alto Emulator executes. It was set by InitMap. * Clobbers T and ETemp0. *----------------------------------------------------------- Subroutine; T← LShift[37, 10]C; * MemBase addressed from A[3:7] DoBRs: ETemp0← A0, MemBase← T; BRHi← EmuBRHiReg; T← T-(400C); BRLo← ETemp0, Branch[DoBRs, ALU>=0]; * IO base registers used for negative indexing {EmuBRHiValX,,xxx} T← (EmuBRHiReg)-1, MemBase← EIBR; BRHi← T; MemBase← EOBR; BRHi← T; MemBase← MDS, 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, T=0. *----------------------------------------------------------- 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; T← A0, UseDMD, 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];