*-----------------------------------------------------------
Title[InitialSelectMain.mc...June 19, 1982  2:06 PM...Taft];
* Control for microcode selection and booting.
*-----------------------------------------------------------

%
InitialSelectMain is the top-level module for the various flavors of
microcode that can be installed on the Initial area of the disk.
It controls subsequent loading of microcode from disk, Ethernet, or
an overlay pasted onto the end of InitialSelect itself.

This microcode has many entry points, with the following effects:

InitialDiskEntry:  Unconditionally loads the installed Pilot "soft" microcode
(the one pointed to by the softMicrocode entry of the physical volume root page,
installed by Othello's "Pilot microcode fetch" command).

InitialOverlayEntry:  If the "P" key is down, operates the same as InitialDiskEntry.
Otherwise loads the next microcode overlay from the same .eb file that the
currently-running microcode came from.

InitialEtherMesaEntry:  If the "P" key is down, operates the same as InitialDiskEntry.
Otherwise, loads DoradoMesa.eb from an Ethernet boot server.

InitialEtherSmalltalkEntry, InitialEtherLispEntry, InitialEtherCedarEntry,
InitialEtherTestEntry:  as for InitialEtherMesa except for the emulator chosen.
%

Set[InitialEtherMesaEntryLoc, 400];
Set[InitialEtherSmalltalkEntryLoc, 401];
Set[InitialEtherLispEntryLoc, 402];
Set[InitialEtherCedarEntryLoc, 403];
Set[InitialEtherTestEntryLoc, 404];
Set[InitialDiskEntryLoc, 405];
Set[InitialOverlayEntryLoc, 406];

TopLevel;
Set[XTask, IP[EMU]];

*-----------------------------------------------------------
* Entry points.
* Entry conditions: LoadRam has just been executed (to start this microcode).
* This means Tasking is off, IFU reset, etc.; however, the I/O devices are
* NOT quiescent.  Memory system is in a good state with at least the first 64K mapped.
* The keyboard words are still valid, having been read by the BaseBoard Initial
* program before this microcode was loaded.
*-----------------------------------------------------------

* Set flags that remember what to do:
*  T[0]=0 => Ether-boot microcode whose BFN is given in T[8:15]
*  T[0]=1 => overlay next microcode if T[15]=1, else always boot from disk.

	T← 110C, Branch[ISelCommon], At[InitialEtherMesaEntryLoc];
	T← 111C, Branch[ISelCommon], At[InitialEtherSmalltalkEntryLoc];
	T← 112C, Branch[ISelCommon], At[InitialEtherLispEntryLoc];
	T← 113C, Branch[ISelCommon], At[InitialEtherCedarEntryLoc];
	T← 114C, Branch[ISelCommon], At[InitialEtherTestEntryLoc];
	T← 177400C, Branch[ISelCommon], At[InitialDiskEntryLoc];
	T← 177401C, Branch[ISelCommon], At[InitialOverlayEntryLoc];

*-----------------------------------------------------------
* Common InitialSelect code.
* First, reset all I/O devices, since their former microcode is no longer around.
*-----------------------------------------------------------
ISelCommon:
	RBase← RBase[AEmRegs];
	DummyRef← LRItem, B← MD;	* Capture start adr of next overlay, if any
	Q← VALo;
	BTemp2← T, MemBase← IOBR;
	T← A0, TaskingOff;		* Not strictly necessary, but aids debugging
	BRLo← T;
	T← (BRHi← T)+1;
	StkP← T;			* StkP← 1, useful later
	R400← 400C;
	BTemp0← T← 2000C;
	T← T OR (251C), Call[WriteManifold]; * 2251 => turn on IOReset
	T← (BTemp0) OR (253C), Call[WriteManifold]; * 2253 => turn off IOReset

*-----------------------------------------------------------
* Now decide what to do:
* If "P" is down, load the Pilot "soft" microcode from the disk.
* Otherwise select among disk, Ethernet, or overlay depending on the entry point
* that was taken.
*-----------------------------------------------------------
	Call[JNKInitPC];		* Fire up junk task
	LdTPC← T, Wakeup[JNK];
	T← (R400) XOR (177434C);	* VM 177034 = first keyboard word
	Fetch← T, Call[DSKInitPC];	* Fire up the disk microcode, in case needed
	LdTPC← T, Wakeup[DSK];
	T← MD, TaskingOn;
	PD← T AND (20C);		* Now check the keyboard bit fetched earlier
	BootDataPtr← 1000C, Branch[LoadFromDisk, ALU=0];
	T← BTemp2, Branch[LoadFromEthernet, R>=0];
	BTemp2, Branch[LoadFromOverlay, R odd];
	Branch[LoadFromDisk];

*-----------------------------------------------------------
* Load microcode from the disk.
*-----------------------------------------------------------
LoadFromDisk:
	BTemp2← Desc.bi.softMicrocode;	* What to boot
	SCall[DiskBootSoft];		* Load starting at 1000 to skip overhead page
	 Branch[.+2];			* Failed, give up
	ETemp0← A0, Call[CheckChecksumAndLoad]; * Load if checksum is OK

DiskMicrocodeBootFailed:
	Breakpoint, Branch[.];

*-----------------------------------------------------------
* Load microcode from the Ethernet.  T = desired boot file number.
*-----------------------------------------------------------
LoadFromEthernet:
	Stack← T;			* The desired boot file number
	BootDataPtr← 1400C, SCall[EtherMicrocodeBoot]; * Boot microcode from Ethernet
	 Branch[EtherMicrocodeBootFailed]; * Failed, give up
	ETemp0← A0, Call[CheckChecksumAndLoad]; * Load if checksum is OK
	T← Stack;			* Bad checksum; try loading it once more
	BootDataPtr← 1400C, SCall[EtherMicrocodeBoot];
	 Branch[EtherMicrocodeBootFailed]; * Failed, give up
	ETemp0← A0, Call[CheckChecksumAndLoad]; * Load if checksum is OK

EtherMicrocodeBootFailed:
	Breakpoint, Branch[.];

*-----------------------------------------------------------
* Load microcode from overlay.  Q = address of first Item in that overlay.
* Note that the entire enclosing .eb file has already been checksummed
* by the guy who loaded us (presumably the BaseBoard Initial program).
*-----------------------------------------------------------
LoadFromOverlay:
	T← Q, Branch[CallLoadRam];


*-----------------------------------------------------------
CheckChecksumAndLoad:
* Checks the checksum of a loaded microcode image, and if it is OK then
* call LoadRam on it, never to return.  Returns only if the checksum is not OK.
* Enter: BootDataPtr = address of last word loaded +1
*	ETemp0 = 0
* Assumes that the microcode was loaded starting at 1400B.
* Returns with T=0, if it returns at all.
* Clobbers T, BootDataPtr, ETemp0
*-----------------------------------------------------------
Subroutine;

	T← (BootDataPtr)-(1400C)-1;	* T← (# words loaded)-1
	BootDataPtr← (BootDataPtr)-(Cnt← T)-1; * BootDataPtr← 1400, Cnt← (# words loaded)-1

* Not the world's fastest checksum loop, but who cares?
	BootDataPtr← (Fetch← BootDataPtr)+1;
	ETemp0← (ETemp0)+MD, Branch[.-1, Cnt#0&-1];

	T← 1400C, Branch[.+2, ALU=0];	* Done checksumming; OK?
	T← A0, Return;			* No
TopLevel;
CallLoadRam:
	LRFlag← A0, BRLo← T, BranchExternal[LShift[LoadRamPage, 6]]; * Yes, dive into it!

* Since we don't actually include LoadRam, MicroD must be locked out of
* the page that it occupies:
IMReserve[LoadRamPage, 0, 100];


*-----------------------------------------------------------
WriteManifold:
* Enter with T = address to strobe using UseDMD.
* Uses Cnt, T.
*-----------------------------------------------------------
Subroutine;

	Cnt← 13S;
WriteManLp:
	PD← A0, MidasStrobe← T;
	PD← T-T-1, Branch[., ALU=0];	* Delay 2 cycles
	T← T LSH 1, Branch[WriteManLp, Cnt#0&-1];
	UseDMD, Return;


*-----------------------------------------------------------
OutputGetsT:
* Handy global subroutine executes Output← T.
*-----------------------------------------------------------
Subroutine;
	Output← T, Return, Global;