*----------------------------------------------------------- Title[AEm0.mc...February 10, 1983 1:52 PM...Taft]; * Alto Emulator initialization and software boot sequence. *----------------------------------------------------------- MC[defaultPartition, 5]; *----------------------------------------------------------- * 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: T_ defaultPartition; * Default disk region DefaultDisk_ T, Branch[SW]; * 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]; T_ defaultPartition; * Default disk region DefaultDisk_ T; ETemp4_ T+1, Branch[InitMapWarm]; * ETemp4_ odd, start existing core image Subroutine; EmuInitPC: T_ EMU, CoReturn; * Return EMU start PC TopLevel; DontKnowRBase; SW: ETemp4_ A0; * Note this is a cold boot * Back here from InitMapWarm 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? 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: * 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)+1, ETemp0_ MD; Fetch_ T, T_ A0, ETemp1_ MD, ETemp0, Branch[EBoot, R even]; * Branch if BS key was down *----------------------------------------------------------- * Disk boot. *----------------------------------------------------------- * If any of the digits 1 through 5 is pressed down, reset the default disk * partition to that number. ETemp2_ 17C; * Init retry count PD_ MD, Call[SelectPartitionIfKey]; * Test "1" key PD_ LSH[ETemp1, 1], Call[SelectPartitionIfKey]; * Test "2" key PD_ ETemp1, Call[SelectPartitionIfKey]; * Test "3" key PD_ LSH[ETemp0, 1], Call[SelectPartitionIfKey]; * Test "4" key PD_ ETemp0, Call[SelectPartitionIfKey]; * Test "5" key * Disk boot (cont'd) * Make up disk command starting at location 1. * Note that it will be overwritten by data, but boot files are * specially constructed to make that be ok. ETemp3=0 here. DiskBoot: T_ (Store_ 1S)+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 T_ (Store_ T)-1, DBuf_ ETemp3; Store_ T, DBuf_ 1C; * 521b_ 1b -- address of disk command * Wait up to 1 second for disk status to appear in location 2 T_ (R400)+(30C); * VM 430 = real time clock Fetch_ T, ETemp0_ 33C; ETemp0_ (ETemp0)+MD; * Now + 27*39 ms KWait: Fetch_ T, ETemp1_ DoneStatus; PD_ (ETemp0)-MD-1; Fetch_ 2S, Branch[KBootTimeout, ALU<0]; PD_ (ETemp1) AND MD; PD_ (3S) AND MD, 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[DiskBoot, 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; DefaultDisk_ 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. *----------------------------------------------------------- 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; *----------------------------------------------------------- * 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];