*----------------------------------------------------------- Title[BootstrapMain.mc...August 11, 1981 2:16 PM...Taft]; * Bootstrap is a microprogram that cooperates with the Baseboard to fill the * Dorado IM with "Initial" microcode when a boot occurs. *----------------------------------------------------------- % WARNING: This program must be placed in the "last N" words of the Dorado microstore. Somehow, it must be guaranteed that this code does not share IM locations with the microcode it bootstraps. Changes in the size or location of this program must be arranged cooperatively with the Baseboard processor's code. WARNING: This program writes ALUFM; consequently the association between operator symbols in the micro assembly language (like, "+", "-", "or", "#") and what ALU function actually occurs when such symbol gets used depends entirely upon convention. Ie., D1Lang may cause the ALUF of the micro instructions to contain, say, "5" when + gets used. If the programs writes into ALUFM, at location 5, a value that causes the processor to perform "-", then the processor will subtract rather than add. The ALU operations that are written by Bootstrap are A XOR B, A+1, and NOT A. Additionally, the BaseBoard writes NOT B before giving control to Bootstrap. All other operations are verboten in Bootstrap! Program Overview ---------------- The Baseboard forces this program into IM and releases control to it with machine errors disabled (when the program gets control RM and T may have parity errors). Bootstrap assembles IM words that are provided by the Baseboard and writes them into sequential locations of IM beginning at a location specified by the Baseboard. When Bootstrap has finished assembling words provided by the Baseboard it transfers control to "InitialLoc", the entry point to the Initial microcode that has been loaded, where more initialization gets done. When program initialization is complete, the program enables errors (Stack, RM, and T parity errors) via the manifold system. Then it notifies the baseboard that all is well, and then finds and loads the appropriate emulator microcode from disk or Ethernet, which in turn boots the operating system via the disk or Ethernet. IM layout (see definitions in BootDefs): pages ~63 - 75: Initial & its friends page 76: LoadRam -- brought in with Initial page 77: Bootstrap Bootstrap is loaded "manually" by the Baseboard. Bootstrap then brings in Initial and LoadRam from the BaseBoard and starts it. Initial loads some emulator into main memory and then calls LoadRam to load it into IM. At that point, Initial and Bootstrap are no longer needed and may be overlaid by the emulator; only LoadRam need stay around. Baseboard - Bootstrap Conventions --------------------------------- Bootstrap reads data from the Baseboard by reading the CPReg. First it reads a starting address value (two bytes) and a count (two bytes). Then it reads instructions (four bytes each) and writes them into IM. The last two bytes the Baseboard transmits to Bootstrap contain a 16 bit checksum that the "Initial" microcode checks. Whenever the Baseboard transmits bytes to the Dorado, Bootstrap assembles the bytes left to right. The Baseboard provides IM bytes in the following format: 0 <7 bits> 1 <3 bit dispatch> The dispatch encodes the following information: x00 left half, 17th bit is 0 x01 right half, 17th bit is 1 x10 IM right half, 17th bit is 0 x11 IM right half, 17th bit is 1 If x = 0 THEN use correct parity ELSE write bad parity. The first two CPReg values that Bootstrap reads from the Baseboard assemble into the starting IM address where subsequent instructions will be written. The next two CPReg values assemble into a "hunk" count. Each hunk contains 4 Dorado instructions = 8 half instructions. Thus Bootsrap loads Cnt with a half-word count that is 8 * hunk count. The 3-bit dispatch is a convention that applies to reading Dorado instructions only; ie., those two bits are zero when the Baseboard transmits "data" rather than instructions to the Dorado. Bootstrap Initialization ------------------------ The Baseboard writes bootsrap into the Dorado's IM, and it initializes ALUFM with "B" (ALUFM[0] _ 25B) Further initialization must be provided by Bootstrap itself: Bootstrap must initialize ALUFM values other than "B", and it must synchronize with the Baseboard. Synchronization occurs by waiting for the high order bit change value (from zero to one or one to zero). Note, the program reads these values from CPreg by using the "RWCPreg" function. The Baseboard starts Bootstrap with CPReg[0] = 1. Bootstrap must read the starting address and the hunk count. It converts the hunk count into a half-word count. Second-stage initialization --------------------------- The microcode that is loaded and started by Bootstrap is called "Initial". Its responsibilities are as follows: It reads a two byte checksum and compares the checksum against the computed checksum from all other values read from CPReg. It writes RM, STACK, and T with valid data -- to prevent parity errors. It initializes ALUFM. It initializes the memory system enough to prevent unexpected errors. When done with all this, Initial sets a bit in the Baseboard using the manifold system, telling the Baseboard that this stage of the boot has been successful. It then does more complete initialization and loads and starts the appropriate emulator microcode from the disk or Ethernet. % TopLevel; OnPage[BootstrapPage]; Set[BootstrapAddr, LShift[BootstrapPage, 6]]; *----------------------------------------------------------- Bootstrap: At[BootstrapLoc], * Started here by BaseBoard *----------------------------------------------------------- TaskingOff; * Initialize ALUFM for A XOR B, A+1, and NOT A. (Baseboard already loaded B.) * (Assembling this microcode will give a "Field ALUF already set" error * if the ALUFM addresses for the operations don't agree with the * ones in D1Alu.mc.) T_ AFM10; ALUFMRW_ T, ALUF[10], A XOR B; T_ AFM12; ALUFMRW_ T, ALUF[12], A+1; T_ AFM16; ALUFMRW_ T, ALUF[16], NOT A; *----------------------------------------------------------- * Read beginning loc and hunk count. * We don't care which RBase we use, but we must init chkSum, loc, cnt. *----------------------------------------------------------- ChkSum_ T XOR T; * ChkSum_ A0 Tag_ T XOR T, Call[ReadBB]; * Tag_ A0, for BaseBoard sync Loc_ LSH[T, 10], Call[ReadBB]; * Bytes 0, 1 = loc T_ LDF[T, 10, 0]; Loc_ (Loc) XOR T, Call[ReadBB]; * Really OR -- bits are disjoint Byte1_ LSH[T, 10], Call[ReadBB]; * Bytes 2, 3 = hunk count T_ LDF[T, 10, 0]; Byte1_ (Byte1) XOR T; * Hunk count * 8 = half-word count Byte1_ LSH[Byte1, 3]; Cnt_ Byte1; *----------------------------------------------------------- * This is the main loop that reads bytes from the base board and then * writes them into IM. Note that each half word gets assembled by * reading two bytes. The second byte (right half) of each word contains * extra bits that distinguish whether to set the 17th bit of IM * and whether or not to use good parity when writing IM. *----------------------------------------------------------- BootByteL: Branch[BootStage2, Cnt=0&-1]; * Branch if count ran out Nop; * Placement Call[ReadBB]; * Get left half byte Byte1_ LSH[T, 10], Call[ReadBB]; * Get dispatch & right half byte BTemp_ LDF[T, 3, 10]; * BTemp_ 3 dispatch bits BTemp_ LSH[BTemp, 1]; * Spread targets (for placement) T_ LDF[T, 10, 0]; * Construct full data word T_ T XOR (Byte1); BigBDispatch_ BTemp; Link_ Loc, Branch[Write000]; * Link_ IM address to write Set[WriteX, Add[BootstrapAddr, 20]]; * 0 mod 20 Write000: At[WriteX, 0], IMLHR0'POK_ T; * Left half, 17th bit = zero. Branch[BootByteL]; Write001: At[WriteX, 2], IMLHR0POK_ T; * Left half, 17th bit = one. Branch[BootByteL]; Write010: At[WriteX, 4], IMRHB'POK_ T; * Right half, 17th bit = zero. Loc_ (Loc)+1, Branch[BootByteL]; Write011: At[WriteX, 6], IMRHBPOK_ T; * Right half, 17th bit = one. Loc_ (Loc)+1, Branch[BootByteL]; Write100: At[WriteX, 10], IMLHR0'PBad_ T; * Left half, 17th bit = zero. Branch[BootByteL]; Write101: At[WriteX, 12], IMLHR0PBad_ T; * Left half, 17th bit = one. Branch[BootByteL]; Write110: At[WriteX, 14], IMRHB'PBad_ T; * Right half, 17th bit = zero. Loc_ (Loc)+1, Branch[BootByteL]; Write111: At[WriteX, 16], IMRHBPBad_ T; * Right half, 17th bit = one. Loc_ (Loc)+1, Branch[BootByteL]; *----------------------------------------------------------- * Exit from main loop -- go run the Initial microcode we have loaded. *----------------------------------------------------------- BootStage2: BranchExternal[InitialLoc]; *----------------------------------------------------------- ReadBB: Subroutine, At[ReadBBLoc], * Read a byte from Baseboard. * Enter with Tag containing sync bit. * Exit with ChkSum and Tag updated and T = data from BaseBoard. *----------------------------------------------------------- Q_ Link; * Save return link * Caution: RWCPReg puts unsynchronized data on the BMux! * Therefore, load it into a register before testing the tag bit, * and read it again before believing the data. T_ RWCPReg; PD_ (Tag) XOR T; T_ RWCPReg, Branch[.-2, ALU<0]; * Wait until CPReg[0] = Tag[0] Tag_ NOT (Tag), Link_ Q; ChkSum_ (ChkSum) XOR T, Return; (1540)