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