*-----------------------------------------------------------
Title[DiskBootSoft.mc...November 23, 1982  4:27 PM...Taft];
* Pilot "soft" boot -- loads a microcode or germ file designated by
* one of the pointers in the physical volume root page.
*-----------------------------------------------------------

TopLevel;
RBase← RBase[BBRegs];
Set[XTask, IP[EMU]];


*-----------------------------------------------------------
DiskBootSoft:
* Enter: BootDataPtr = address of base of block (in first 64K of memory)
*	   into which to load the microcode image
*	BTemp2 = Descriptor-relative offset of BootingInfo for file to be booted
*	RBase = BBRegs
*	MemBase = IOBR
* Real memory has been mapped contiguously at the bottom of virtual memory,
* and IOBR contains zero.
* I/O devices have been initialized and are quiescent.
* Call by: SCall[DiskBootSoft]
* Returns +1: Failed
*	+2: Succeeded; BootDataPtr updated to point to last word loaded +1 (mod 2↑16)
* Clobbers T, Q, BTemp0, BTemp1
* Also clobbers memory page 0 by reading the physical volume root page into it.
*-----------------------------------------------------------

Subroutine;
	DMBLink← Link;
TopLevel;

* Set up an IOCB in the Display CSB's cursor region so that we can perhaps diagnose
* boot failures by inspecting the screen with a magnifying glass. Note that the
* IOCB overflows the end of the cursor region into the border pattern region.
	IOCB← Or[DCSB.cursorBitMap!, 1]C;
	T← Sub[sizeIOCB!, 1]C;
	Cnt← T;
	T← (Store← T)+1, DBuf← 0C, Branch[., Cnt#0&-1]; * Zero out the IOCB
	T← CSB.cylinder;
	Store← T, DBuf← 77777C;		* Don't know where disk is positioned

* Transfer the Descriptor.
* Know all of IOCB is zero at this point, so only set nonzero entries.
* In particular, drive = diskAddress = dataPtr = 0
	T← (IOCB)+(IOCB.pageCount);
	T← (Store← T)+1, DBuf← 1C;	* One page
	Store← T, DBuf← 274C;		* command ← [check, read, read]
	SCall[BootTransfer];		* Transfer the Descriptor
	 PD← T-T, Branch[DiskSBootRet];	* Failed, Carry← 1

* Make sure the seal and version are ok
	T← (Fetch← Add[Desc.seal!]S)+1;
	Fetch← T, T← MD, BTemp0← HighByte[DescSealValue];
	BTemp0← (BTemp0) OR (LowByte[DescSealValue]);
	BTemp0← (BTemp0) XOR T, T← MD;
	T← T XOR (DescCurrentVersionValue);
	PD← (BTemp0) OR T;
	T← (IOCB)+(IOCB.pageCount), Branch[.+2, ALU=0];
	 PD← T-T, Branch[DiskSBootRet];	* Bad Descriptor, Carry← 1

* DiskBootSoft (cont'd)

* Set up to transfer the selected boot file
	T← (Store← T)+1, DBuf← 77777C;	* Transfer as many pages as exist
	BTemp0← 100000C;		* incrementDataPtr ← TRUE
	BTemp0← (BTemp0) OR (254C);	* command ← [check, check, read]
	BTemp0← (Store← T)+1, DBuf← BTemp0;

* IOCB.diskAddress ← Descriptor.bootingInfo[bootFileType].diskAddress
	T← (BTemp2)+(DFID.da);
	BTemp1← T, Cnt← 1S, Call[BootBlt]; * Want to move 2 words, actually do 3

* IOCB.dataPtr ← BootDataPtr
	T← (IOCB)+(IOCB.dataPtr);
	Store← T, DBuf← BootDataPtr;

* IOCB.diskLabel.fileID ← Descriptor.bootingInfo[bootFileType].fID;
* IOCB.diskLabel.filePageLo ← Descriptor.bootingInfo[bootFileType].firstPage;
	BTemp0← T+(Sub[IOCB.diskLabel!, IOCB.dataPtr!]C);
	T← (BTemp2)+(DFID.fID);
	BTemp1← T, Cnt← 4S, Call[BootBlt]; * Move 6 words

* IOCB.diskLabel.filePageHi ← 0;
* IOCB.diskLabel.type ← -1;  -- all boot files have this type
* IOCB.diskLabel.bootChainLink ← 0;
	BTemp0← (Store← BTemp0)+1, DBuf← 0C;
	BTemp0← (Store← BTemp0)+1, DBuf← -1C;
	BTemp0← (Store← BTemp0)+1, DBuf← 0C;
	Store← BTemp0, DBuf← 0C;
	SCall[BootTransfer];		* Transfer the boot file
	 PD← T-T, Branch[DiskSBootRet];	* Failed, Carry← 1
	T← (IOCB)+(IOCB.dataPtr), Call[FetchGetsT]; * Get updated dataPtr; Carry← 0

* Carry=0 if completed successfully, 1 if unsuccessfully.
DiskSBootRet:
	Link← DMBLink, T← MD;
Subroutine;
	BootDataPtr← T, Return[Carry'];	* This clobbers BootDataPtr on fail return


*-----------------------------------------------------------
BootBlt:	* Copy memory to and fro
* Enter: BTemp0 = first destination address
*	BTemp1 = first source address
*	Cnt = (# words to transfer)-2
* Exit:	BTemp0 and BTemp1 advanced by number of words transferred
* Clobbers T
*-----------------------------------------------------------
Subroutine;

	BTemp1← (Fetch← BTemp1)+1;
	BTemp1← (Fetch← BTemp1)+1, T← MD;
	BTemp0← (Store← BTemp0)+1, DBuf← T, Branch[.-1, Cnt#0&-1];
	BTemp0← (Store← BTemp0)+1, DBuf← MD, Return;