{File name: BLisp11SAx000Initial.mc Purcell 6-Feb-85 0:28:37 Daybreak compatable initial Purcell 5-Feb-85 12:32:38 observe IFPAGE[NActivePages] as FPTOVP limit Purcell 4-Feb-85 9:34:22 Declare DLion small VM DTiger Large VM {%5} Lichtenberg 9-Jan-85 8:39:28 - trimmed commented-out code Lichtenberg 2-Aug-84 1:28:03 fixed obscure leader pages bug. Lichtenberg 13-Jul-84 18:15:31 uIOPage finally right this time. Purcell 13-Jul-84 18:02:02 uIOPage was incorrectly set for lisp Purcell 2-Jul-84 14:15:55 zero oldIOPage Purcell 2-Jul-84 4:44:35 set uIOPage like mesa 10 before lisp {??} Purcell 1-Jul-84 23:37:15 use newIOPage and buffer it in oldIOPage Purcell 1-Jul-84 22:25:58 Added support for Quantum Q2080 Purcell 1-Jul-84 22:25:58 Accomodate changes for Germ as a result of going over to 32-bit procedure descriptors Purcell 1-Jul-84 22:25:58 Use IOPage offsets from Dandelion.df! Purcell 14-May-84 22:03:08 Mesa 11.0 Upgrade 2080 & germ Purcell 23-Feb-84 23:23:07 detect multibanks Purcell 15-Feb-84 2:29:05 load 4mb; scrap to page 0FF Purcell February 14, 1984 8:03 PM skip "zero banks" in FPTOVP Purcell February 6, 1984 12:40 PM Lisp MCtl _ 8002h Purcell January 19, 1984 7:53 PM; MIN[topPage, AC0] removed Purcell January 18, 1984 4:14 PM; mesa: MCtl 0, MIN[topPage, AC0] Purcell January 17, 1984 11:21 AM; added NewInit section Purcell January 17, 1984; renamed from nLispSAx000Initial.mc Purcell January 16, 1984 6:34 PM; correct test of vp>2^14 Purcell December 30, 1983 3:53 PM; max real mem 3-8MB Purcell December 27, 1983 3:06 PM; max real mem 2.0MB Purcell November 26, 1983 2:25 PM; {*0} max real mem 1.5MB Purcell April 16, 1983 5:32 PM; uses password 15e3 at 17 Purcell April 16, 1983 4:22 PM; try 800h pages $$ Purcell April 16, 1983 1:16 PM; don't bother refresh Purcell April 13, 1983 10:47 AM; uLispBootMsg{0DE}=55 to boot mesa Purcell April 6, 1983 8:44 AM; skip over interface page Purcell April 1, 1983 4:53 PM; new sysout booting Purcell March 21, 1983 10:27 PM; Quantum support Purcell March 6, 1983 2:56 PM; define uLinkPtr Purcell March 6, 1983 9:45 AM; store boot disk address in IOCBs.cpr Purcell December 6, 1982 6:39 PM: map for 4MB boot file Purcell November 28, 1982 1:18 PM: LispSAx000Initial: save boot link for Lisp Purcell November 22, 1982 9:03 AM: link _ 0D for BLT Purcell November 19, 1982 4:54 PM: boot Lisp instead of diagnostics File name: [Idun]SAx000Initial.mc Description: first microcode read from the disk, gets emulator microcode into CP memory, Author: Jarvis, Created: August 25, 1980, JGS November 18, 1981 8:58 AM: move germ to mds 0. Last Edited by Neely January 14, 1982 2:40 PM - change cons. for extracting filePageHi from BootId from 7 to 7F. Last Edited by Jim Frandeen October 22, 1981 1:12 PM: If diagnostics are not installed, boot Emulator instead of crashing. Last Edited by Fasnacht June 18, 1981 10:30 AM: delete SetGerm1000 at Last Edited by DDavies February 14, 1981 4:35 PM Last Edited by Jarvis March 24, 1981 11:46 AM} {disk definitions} {RegDef[uLispBootMsg, U, 0DE];} {also in Dandelisp.df} RegDef[uLinkPtr, U, 27{uTT}]; {uLinkPtr} RegDef[uFirstPage,U,49]; Set[hardMicrocodeFirstPage,13'd]; {null findSectorCmd for SA1000} Set[SA1000FindSectCmd, 20]; {have SA1000 reject Label and Data fields when looking for Headers} Set[SA1000HeaderLoopMsk, 43]; {control bits, low byte} {Set[stepBit, 80], Set[inBit, 40], Set[firmwareEnable, 20];} Set[SA4FindSect, 6], Set[SA1FindSect, 0]; {control bits, high byte} {Set[driveSelectBit, 4], Set[faultClearBit, 2];} {IOCB status error indicators} Set[badBits, 3F]; Set[verifyBit, 1]; {IO page offsets} {Set[diskCSB, 1];}{%} {IOCB page offsets} Set[statusAddr, 3]; {status word} {not used, used to be pointer to next IOCB, always 0} Set[seekAddr, 5]; {pointer to seek IOCB} Set[transferAddr, 6]; {pointer to transfer IOCB} Set[vrrAddr, 7]; {pointer to vrr parameter area} Set[vvrAddr, 8]; {pointer to vrr parameter area} Set[headerAddr, 9]; {header -- 2 words} Set[labelAddr, 0B]; {label -- 0A words} Set[labelPageLow, 10]; {low 16 bits of file page number} Set[miscBitsAddr, 11]; {filePageHi[0..6], unused[0..5], immutable[0], temporary[0], zeroSize[0]} Set[bootLink, 13]; {disk address of next run of pages in boot file} Set[labelSize, 0A]; {parameter area offsets} Set[sectors, 0]; {number of sectors to transfer} Set[headerLoopMsk, 6]; {specifies non-fatal errors when looking for a header} Set[dataPage, 0D]; {page number of data area in main storage} Set[haltWord, 0F]; {requires head in high 5 bits} Set[findWord, 10]; {requires head in high 5 bits} {transfer IOCB offsets} Set[parameters, 1]; {pointer to parameter area} {seek IOCB offsets} Set[cylinders, 0]; {-(number of cylinders to move heads)} Set[stepHigh, 6]; {set step level high} Set[stepLow, 8]; {set step level low} {Miscellaneous disk constants} Set[SA1000HeadCount, Sub[4,1]]; Set[SA4000HeadCount, Sub[4,1]]; Set[Q2040HeadCount, Sub[8,1]]; Set[Q2080HeadCount, Sub[7,1]]; RegDef[uVMFileSize, U, 6A]; Set[vmSizeLoc, 100'b]; Set[bigVMrefFlg, 75'b]; Set[NActivePages, 24'b]; Set[MachineType, 15'b]; Set[DANDELION, 6'b]; Set[NRealPages, 70'b]; Set[FPTOVPStart, 73'b]; {physical volume boot files} {useful data formats extracted from Boot.mesa BootFileType: TYPE= {hardMicrocode, softMicrocode, germ, pilot, debugger, debugee}; DiskFileID: TYPE= RECORD[fID: File.ID, firstPage: File.PageNumber, da: DiskAddress]; PVBootFiles: POINTER TO ARRAY BootFileType[hardMicrocode..pilot] OF DiskFileID= 2; After reading from the disk, PVBootFiles moved to memory location 2} Set[bootingInfo, 8]; {origin of PVBootFiles in physical volume root page} Set[DiskFileIDSize, 9]; {number of words in DiskFileID} Set[bootingInfoSize, Mul[DiskFileIDSize, 4]]; {size of PVBootFiles} {things salted away in page 0} Set[availableDevices, 0]; {devices available for booting, set up by Phase 0} Set[bootReadyFlag, 1]; {non-zero indicates boot file is ready} Set[hardFileID, 2]; {hard microcode DiskFileID, copied from physical volume root page} Set[emulatorFileID, 0B]; {emulator microcode DiskFileID, copied from physical volume root page} Set[germFileID, 14]; {germ DiskFileID, copied from physical volume root page} Set[bootFileID, 1D]; {working DiskFileID, copied from one of the above fileID's} Set[bootPage, 22]; Set[bootDiskAddr, 24]; Set[labelTemplate, 26]; {template label used by boot loading routines} {germ definitions Mesa 11} Set[sLastGermRequest, Add[sFirstGermRequestLow, 57'b]]; {end of germ request in SD} Set[RequestSize, 60'b]; {size of germ request in SD} Set[SD.Request.version, Add[sFirstGermRequestLow, 00'b]]; Set[RequestVersionHigh, 7]; Set[RequestVersionLow, 56'b]; Set[SD.Request.action, Add[sFirstGermRequestLow, 01'b]]; Set[bootPhysicalVolume, 2]; Set[SD.Request.location, Add[sFirstGermRequestLow, 02'b]]; Set[SD.Request.location.deviceType, Add[sFirstGermRequestLow, 02'b]]; Set[germPilotDisk, 64'd]; Set[SD.Request.location.deviceOrdinal, Add[sFirstGermRequestLow, 03'b]]; {germ definitions mesa10} DoneOnceOnlyInit: {For the four disk drives, the following applies: Q2040 - ~HeadSlelect16 = ~Sector. The two pins are connected physically. Q2040 - ~Sector = TRUE. Using positive logic. SA4000- ~SA1000/SA4000 = TRUE. Positive logic. SA1000- ~SA1000/SA4000 = FALSE & ~Sector = FALSE. Also positive logic.} {First modify the IOCB for an SA1000 if necessary} Xbus _ KStatus, XwdDisp, c1; {what type of disk is this?} acR _ 0FF+1, DISP2[SetSA1IOCB, 2], c2; {Point to table of IOCBs} {there is an SA1000 drive connected. Set the LabelDataTag bit in the HeaderLoopMsk and turn off the "Wait for Sector mark" command in the FindWord} SetSA1IOCB: {Test for SA1000 or Quantum depending on bit 9 of KTest after writing to bit H16 of KCtl: KTest[9]=0 => SA1000 KTest[9]=1 => Quantum Q2040. For the Quantum Q2080 KCtl[0]=~KTest[9]} rB _ 80, c3, at[2,4,SetSA1IOCB]; KCtl _ rB LRot8, c1; {Test for an SA1000 or Quantum} Xbus _ KTest, XwdDisp, c2; DISP2[IsSA1000orQuantum,1], c3; IsSA1000orQuantum: rB _ SA1000HeadCount {sa1000}, GOTO[FinishIsSA1000orQuantum], c1, at[1,4,IsSA1000orQuantum]; KCtl _ 0, c1, at[3,4,IsSA1000orQuantum]; {Test for a Quantum Q2040 or Q2080} Xbus _ KTest, XwdDisp, c2; DISP2[IsQ2040orQ2080,1], c3; IsQ2040orQ2080: rB _ Q2080HeadCount {Q2080}, GOTO[FinishIsSA1000orQuantum], c1, at[1,4,IsQ2040orQ2080]; rB _ Q2040HeadCount {Q2040}, GOTO[FinishIsSA1000orQuantum], c1, at[3,4,IsQ2040orQ2080]; {IsSA1000orQuantum: rB _ 7 {sa1000}, GOTO[FinishIsSA1000orQuantum], c2, at[3,4,IsSA1000orQuantum]; rB _ 3 {quantum}, GOTO[FinishIsSA1000orQuantum], c2, at[1,4,IsSA1000orQuantum];} FinishIsSA1000orQuantum: uQuantumSA1000MaxHeadNum _ rB, c2; acRrh _ 0 {Point to table of IOCBs}, c3; {JOIN} MAR _ [acRrh, vrrAddr+0], c1; {get addr of vrr parameters} rE _ SA1FindSect, c2; {prepare to set FindSectCmd} acR _ MD, c3; MAR _ [acRrh, acR+headerLoopMsk], c1; {set up new HeaderLoopMsk} MDR _ SA1000HeaderLoopMsk, LOOPHOLE[wok], CANCELBR[$,2], c2; UFindSect _ rE c3; {set FindSect mark cmd for SA1000.} MAR _ [acRrh, vvrAddr+0], c1; {get addr of vvr parameters} rE_ 0, c2; {set up source of 0 for below} acR _ MD, c3; MAR _ [acRrh, acR+headerLoopMsk], c1; {set up new HeaderLoopMsk} MDR _ SA1000HeaderLoopMsk, LOOPHOLE[wok], CANCELBR[DiskInitDone,2], c2; {Connected to an SA4000 so set the Find Sector Mark command properly} SetSA4IOCB: acR _ SA4FindSect, c3, at[3,4,SetSA1IOCB]; UFindSect _ acR, c1; rE_ 0, c2; {source of 0} DiskInitDone: germStart_ rE, c3; acRrh_ 1, c1; {set up stuff for IO page} currentCylinder_ rE, c2; acR_ badBits, c3; uBadBits_ acR, c1; acR_ driveSelectBit, c2; acR_ acR LRot8, c3; acR_ acR or firmwareEnable, c1; seekMask_ acR, {seek Mask_ drive select or firmwareEnable} c2; acR_ 4, c3; acR_ acR LRot8, c1; acR_ acR or 20, c2; haltBits_ acR, c3; {halt bits_ 420} acR_ 0F8, c1; acR_ acR LRot8, c2; headMask_ acR, c3; {headMask_ F800} acR_ 2, c1; acR_ acR LRot8, c2; uBootStart_ acR, c3; {boot file starts at 200} acR_ uDiagnostic, ZeroBr, c1; []_ acR{uDiagnostic} - 1, NZeroBr, BRANCH[pLispBoot, pMesaBoot], c2; pLispBoot: BRANCH[LispBoot, MesaBoot], c3; pMesaBoot: CANCELBR[MesaBoot, 1], c3; {map virtual pages 0-255 to real pages 0-255, first we must save the current mapping of the lowest virtual pages} MesaBoot2: uDiagnostic_ 0, c2; Noop, c3; MesaBoot: rB _ 0AA{Lisp}, c1; uLispBootMsg _ rB, c2; {MCtl _ 0} Noop, c3; mbjoin: rBrh_ 1, c1; rCrh_ 1, c2; rB_ 0, c3; rC_ topPage, L0_ 4, c1; acR_ 0FF+1, CALL[BLT3], c2; {BLT3[from: 10000, to: 1topPage, cnt: 100h]} {block transfer, takes count in acR, from in rB, and to in rC, returns first word past from block in rE} MesaIDMap: acR_ present, c1, at[4, 10, subrRet]; rC_ 0FF+1, c2; rB_ 0, rBrh_ 1, c3; {set up identity map for benefit of the disk microcode} identityMap: MAR_ [rBrh, rB+0], BRANCH[$, idDone], c1; MDR_ acR, rB_ rB+1, c2; acR_ acR+rC, CarryBr, GOTO[identityMap], c3; idDone: Noop, c2; Noop, GOTO[rootPage], c3; {** Lisp uses identity map for all of real memory for benefit of the disk microcode} LispBoot: rB_ 0, c1; Q _ 55{Mesa}, c2; []_ Q xor uLispBootMsg, ZeroBr, c3; acR_ 033{dirtyRef{+3 %B}}, BRANCH[$, MesaBoot2], c1; Q{100}_ 0FF+1, c2; nextId3: rBrh_ 1, c3; {acR{dirtyRef}, rB{10000}, Q{100}, map 2^12 pages as identity{+3seg %B} -- map in 1st 2 megabytes} nextId: MAR_ [rBrh, rB+0], c1; MDR_ acR, acR _ acR + Q{100}, CarryBr, c2; rB_ rB+1, BRANCH[nextId, $], c3; incSeg: acR _ acR + 1, NibCarryBr{2^12 pages}, c1; rC _ topPage{virtual}, BRANCH[nextId3, $], c2; doneId: acR{dirty;page FF}_ ~0DF, c3; { , c1; rC_ 0{FirstRealPageToMap}, c2; {**32mb WAS rC _ 40 for regular memory} rC{20000} _ rC LRot8, c3; } {acR{FF20}, rB{12000}, rCrh,rC{20000}, remaining vp's mapped to FF} Scrap: MAR_ [rBrh, rB+0], BRANCH[$, doneScrp], c1; Scrap2: MDR_ acR{-1}, rB_ rB+1, c2; Ybus _ rB {- rC{0}}, ZeroBr, GOTO[Scrap], c3; doneScrp: rCrh_1, c2; {**32mb: WAS rCrh _ 1 for regular memory} rC _ ~0FF, {=FF00} c3; {**32MB: We want to do 65k map entries} {acR{-1}, rCrh,rC, change 256 map entries to protect the map and old iopage (as known to sysout) to point to FF{-1}} {For Big VM, we have to protect all 256 entries + 1 for I/O page, since the map consumes all of segment 1 -- MPL} Protect256: Map{20000}_ [rCrh, rC+0], c1; MDR_ acR{-1}, rC_ rC, ZeroBr, c2; rC_ rC - 0FF - 1, BRANCH[Protect256, $], c3; {protect map entry for I/O page} rCrh _ 2, c1; rC _ 0, c2; , c3; Map _ [rCrh, rC+0], c1; {**32MB: Protect I/O page} MDR _ acR, c2; GOTO[MesaIDMap], c3; {Start flailing away at the disk. First read the physical volume root page} rootPage: rBrh_ 0, c1; rCrh_ 0, c2; rDrh_ 0, c3; rErh_ 1, c1; rD_ 0FF+1, c2; {base address of IOCB page} rE_ headerAddr, c3; MAR_ [rDrh, rE+0], c1; {cylinder 0} MDR_ 0, c2; rB_ 2, c3; {read starting at page 2} MAR_ [rDrh, rE+1], c1; {head 0, sector 0} MDR_ 0, CANCELBR[$, 0], L1_ 0, c2; acR_ 1, CALL[doVrr], c3; {read 1 sector} transferRet: Ybus_ acR and uBadBits, ZeroBr, c1, at[0, 10, transferRet]; transferIOCB_ rE, BRANCH[$, here1], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; {save the useful stuff from the physical volume root page} here1: rC_ 2, c3; {copy PVBootFiles} rB_ rC LRot8, c1; rB_ rB+bootingInfo, L0_ 0, c2; acR_ bootingInfoSize, CALL[BLT], c3; rC _ 2, c1, at[0, 10, subrRet]; rC _ rC LRot8, c2; rCrh _ 0, c3; MAR _ [rCrh, hardMicrocodeFirstPage + 0], c1; , c2; rC _ MD, c3; uFirstPage _ rC, c1; , c2; , c3; {read the emulator boot file or the hard microcode} emuHard: []_ uDiagnostic, ZeroBr, c1 ; rC_ bootFileID, BRANCH[$, emuHard0], c2; rB_ hardFileID, L0_ 8, GOTO[emuHard1], c3; emuHard0: rB_ emulatorFileID, L0_ 8, c3; emuHard1: acR_ DiskFileIDSize, CALL[BLT2], c1; acR_ 2, L2_ 0, c1, at[8, 10, subrRet]; nextPage_ acR, CALL[readBoot3], c2; rC_ uDiagnostic, ZeroBr, c1, at[0, 10, readBootRet]; acR_ nextPage, BRANCH[$, readGerm], c2; Noop, c3; Noop, c1; Ybus_ rC{uDiagnostic}-1, NZeroBr, c2; Noop, BRANCH[$, doDiag], c3; {test if we have lisp or diagnostics in real memory} rC _ 15{passH}, c1; rB _ 3, c2; rBrh{0} _ rB{300} _ rB LRot8, c3; MAR_ [rBrh, rB+0F{passA}], c1; rC{passH} _ rC LRot8, CANCELBR[$, 2], c2; rC _ MD xor rC, c3; rC _ rC xor 0E3{passL}, c1; Ybus _ rC, NZeroBr, c2; Noop, BRANCH[$, notLisp], c3; { We have Lisp; Restore the map.} {set map[0..3FFFF] to vacant and interpret FPTOVP} LispInit: rBrh_ 1, c1; rB _ rB xor ~rB, c2; {***32MB: we want it all!} rC _ 60{vacant}, c3; rDrh_ 0, c1; rD_ 0FF+1, c2; {base address of IOCB page} rE _ labelPageLow, c3; MAR _ [rDrh, rE+0], c1; , c2; rE _ MD, c3; {read number of pages xferred} uVMFileSize _ rE, c1; , c2; , c3; vacLp: MAR_ [rBrh, rB+0], ZeroBr, c1; MDR_ rC{vacant}, rB_ rB-1, NibCarryBr, BRANCH[$, vDone], c2; vac3: Noop, BRANCH[$, vacLp]{match to vacRef+1}, c3; vacRef: {Refresh,} c1; Xbus _ 1, XDisp, GOTO[vac3], c2; vDone: Noop, CANCELBR[$, 1], c3; {update Interface page and interpret FPTOVP} {Map[InterfacePageVp] _ 3} acRrh _ 6'b{INTERFACEspace}, CANCELBR[$, 1], c1; acR _ 0'b{INTERFACEbase}, c2; acR _ acR LRot8, c3; rB _ 3{real interface page}, c1; rB{300} _ rB LRot8, c2; rBrh _ rB _ rB + 030{%B}{dirty}, c3; Map{InterfacePage} _ [acRrh,acR], c1; MDR _ rB{330{%B}}, c2; , c3; MAR_ [rBrh, 15'b{MachineType} + 0], c1; MDR _ DANDELION{6}, c2; Q _ uVMFileSize, c3; {**32MB: Say we can't do big VM refs (DTiger will change to 1 later)}{%5} MAR _ [rBrh, bigVMrefFlg + 0], c1; MDR _ 0 {false}, c2; , c3; MAR _ [rBrh, vmSizeLoc + 0], c1; MDR _ Q, c2; , c3; Q _ topPage{virtual}, c1; Q _ Q + 40,{ map not included}{topPage was measured as if map were 32KB} c2; Q{NRealPages} _ Q + 0FF{+1}{bank 0 was not incl but}, c3; {%B 3 less segs Q _ Q - 0FF -1, c1; Q _ Q - 0FF -1, c2; Q _ Q - 0FF -1, c3; %B} MAR_ [rBrh, {24'b}NActivePages + 0], c1; , c2; rE{NActivePages} _ MD, c3; {%B 3 more segs} rE _ rE + 0FF + 1, c1; rE _ rE + 0FF + 1, c2; rE _ rE + 0FF + 1, c3; {%B} {MAR_ [rBrh, {70'b}NRealPages + 0]}, c1; {MDR _ Q{NRealPages}}, c2; Ybus _ Q - rE{NActivePages}, CarryBr{NRealPages>NActivePages}, c3; MAR_ [rBrh, {73'b}FPTOVPStart + 0], BRANCH[$, activeLm], c1; rE _ Q{NRealPages}, GOTO[limJn], c2; activeLm: Q _ rE{NActivePages}, GOTO[limJn], c2; limJn: acR{F2Vpage} _ MD, c3; rE _ rE - 0FF - 1, c1; rE _ rE - 0FF - 1, c2; rE _ rE - 0FF - 1, c3; MAR_ [rBrh, {70'b}NRealPages + 0], c1; MDR _ rE{NRealPages-gap}, c2; , c3; {interpret FPTOVP setup}{assume FPTOVP doesn't cross segment} {for i{rC} _ {201h}IOPage+1 to MIN[MaxRealPage, NActivePages{rD}]} { unless FPTOVP[i-1]=none{-1} } { do MAP[FPTOVP[i-1]]:vp _ i } Set[fpvpPageOff, Add[IOPageHigh, 1{file1=real2}]]; Set[IOPagePage, Rshift[IOPage, 8]]; {%B offset 3{dbGap} seg's} rC _ 3{dbGap}, c1; rC _ rC LRot8, c2; acR _ acR + rC, c3; {%B} acR{F2VrealPage+IOPageHigh} _ acR + fpvpPageOff, c1; acRrh _ acR _ acR LRot8, c2; acR _ acR and ~0FF, c3; acR{F2V+IOPagePage} _ acR + IOPagePage, c1; , c2; rBrh _ 1{MapSpace}, c3; Set[dbIOPageHigh, Add[IOPageHigh, 3{dbGap}]]; rC _ dbIOPageHigh, c1; {***32MB: Count = 201H now} rC _ rC LRot8, c2; rC _ rC + IOPagePage +1, c3; {interpret FPTOVP Loop } {acR: FPTOVP[i-1] ptr } {rB: FPTOVP[i-1]:vp } {rC: i{+dbGap} _ {201h}IOPage+1 } {Q: MIN[NRealPages{-dbGap},NActivePages]+dbGap } {rBrh: 10000{Map} } {spin2: GOTO[spin2], c*;}{%%%} f2vLp: MAR_ acR _ [acRrh, acR + 0], c1; {rB{7FFF} _ (rB xor ~rB) RShift1,} c2; rB{vp} _ MD {and rB}, c3; Ybus _ rB + 1, CarryBr{=1?}, c1; rC _ rC LRot8, XRefBr, BRANCH[$, none], c2; Ybus _ rC + 0F, NibCarryBr{nondisplay bank?}, BRANCH[$, fvMod], c3; MAR_ [rBrh{1}, rB + 0], BRANCH[fvNo, $], c1; MDR _ rC{i}, GOTO[none], c2; fvNo: Noop, GOTO[none], c2; fvMod: MAR_ [rBrh{1}, rB + 0], BRANCH[fvMNo, $], c1; MDR _ rC{i} + 70{move over flags to "dp" bit}, GOTO[none], c2; fvMNo: Noop, GOTO[none], c2; none: rC _ rC LRot8, CANCELBR[$, 1], c3; rC _ rC + 1, c1; Ybus _ rC xor Q{NActivePages}, ZeroBr, c2; acR _ acR + 1, BRANCH[f2vLp, $], c3; {done with interpret FPTOVP} rB _ 0FF, c1; rC _ 2, c2; {***32MB: I/O Page back where Mesa wanted it!!!} rBrh _ 1, c3; {Map[IOPageVp=0FF] _ {140}500'b} MAR{100FF}_ [rBrh{1}, rB + 0], c1; MDR{2} _ rC , c2; rC{100} _ 0FF + 1, c3; rC{200} _ rC + rC, c1; rC{400} _ rC + rC, c2; uBootStart_ rC{400}, c3; bankTest: Q _ 0, c1; Bank _ rB _ 0, c2; btLoop: rC _ ~ PPort, BRANCH[$, MultiBank], c3; btLL: rC _ (rC LRot8) xor Q, c1; Ybus _ rC and 3, NZeroBr, c2; Q _ Q + 1, BRANCH[$, StartNewInit{UniBank}], c3; {**32MB: Goes to StartNewInit now (used to be GoNewInit just before the I/O page was cleared)} Bank _ rB +4, c1; rB _ rB +4, NibCarryBr, GOTO[btLoop], c2; MultiBank: rB_ 4, c1; rBrh{0} _ rB{400h}_ rB LRot8, c2; {boot file starts at 200} rC_ 3{2nd .db}, c3; MAR_ [rBrh, rC+0], c1; rC{400q}{100} _ 0FF + 1, c2; rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC{400}, c2; , c3; {set vmsize large} acRrh _ 6'b{INTERFACEspace}, CANCELBR[$, 1], c1; acR _ 0'b{INTERFACEbase}, c2; acR _ acR LRot8, c3; Map{InterfacePage} _ [acRrh,acR], c1; , c2; rBrh _ rB _ MD, c3; {**32MB: DTigers can always do big VM refs}{%5} MAR _ [rBrh, bigVMrefFlg + 0], c1; MDR _ 1 {true}, c2; GOTO[StartNewInit], c3; {... magic things happen here... IF ANY I/O PAGE CLEANUP HAPPENS, DO IT BEFORE GOING TO NEWINIT! } BackFromNewInit: {**32MB: put I/O page in new format} TOS{8002h} _ RRot1 5, c1; MCtl _ TOS{8002h}, TOS _ 2, c2; uIOPage _ TOS{for 20000H}, GOTO[exitToEmulator], c3; {hard microcode (quick exit), get diagnostic table entry from first page of boot file} doDiag: rB _ 055{Mesa}, GOTO[doDiag2], c1; notLisp: rB _ 055{Mesa}, GOTO[doDiag2], c1; doDiag2: uLispBootMsg _ rB, c2; rB_ 2, c3; {boot file starts at 200} mbjoin1: rB_ rB LRot8, c1; rC_ uDiagnostic, c2; rC_ rC{uDiagnostic=1}+1, c3; MAR_ [rBrh, rC+0], c1; rC{400q}{100} _ 0FF + 1, c2; rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC{400}, c2; MCtl_ 0, GOTO[exitToEmulator], c3;{%mesa small mem} {read the germ} readGerm: germStart_ acR, c3; rB_ germFileID, c1; rC_ bootFileID, L0_ 9, c2; acR_ DiskFileIDSize, CALL[BLT], c3; L2_ 1, c1, at[9, 10, subrRet]; CALL[readBoot3], c2; { We now have the germ in real memory. Restore the map for pages 0-255. Then move the germ to MDS 0, starting at page 1. Initialize the Request in the germ's SD. } RestoreMap: rBrh_ 1, c1, at[1,10,readBootRet]; rCrh_ 1, c2; rB_ topPage, c3; rC_ 0, L0_ 5, c1; acR_ 0FF+1, CALL[BLT3], c2; {vacate the pages just used to restore the low ones} rB_ topPage, c1, at[5, 10, subrRet]; rC_ rB+1, c2; acR_ 20{0FF+1}, c3; MAR_ [rBrh, rB+0], c1; MDR_ vacant, L0_ 0B, c2; acR_ acR LRot8{acR-1}, CALL[BLT], c3; {Move germ to MDS 0, page 1} rC _ germStart, c1, at[0B, 10, subrRet]; rB _ rC LRot8, c2; rBrh _ 0, c3; rD _ nextPage, c1; rD _ rD - rC, ZeroBr, c2; transferCount _ rD, BRANCH[moveGerm1, $], c3; {number pages in germ} acR_ bootNullGerm, GOTOABS[Maintenance2Loc], c1; moveGerm1: germStart_ acR xor ~acR, c1; rFrh _ germPageHigh, rF _ 0 + germPageLow, c2; rF _ rF LRot8, c3; mg2: Map _ [rFrh, rF], c1; Noop, c2; rCrh _ rC _ MD, c3; acR _ 0FF + 1, c1; rC _ rC and ~0FF, L0 _ 0C, c2; CALL[BLT], c3; rF _ rF + 0FF + 1, c1, at[0C, 10, subrRet]; rD _ rD - 1, ZeroBr, c2; rE _ LShift1 0FF, SE _ 1, BRANCH[mg2, InitRequest], c3; {Initialize Request in germ's SD} InitRequest: {rE has 1FF = start of SD -1} rC _ sFirstGermRequestHigh, c1; rC _ rC LRot8, c2; {Constants use an 8-bit data path.} rE _ rE + rC + 1, {correct page} c3; Map _ rF _ [rFrh, rE + 0], c1; rC _ sFirstGermRequestLow, c2; rBrh _ rB _ MD, c3; {InitRequest: Map _ rF _ [rFrh, rE + 1], c1; rC _ sFirstGermRequest, c2; rBrh _ rB _ MD, c3; } ZeroReq: MAR _ [rBrh, rC+0], c1; MDR _ rD, rC _ rC + 1, PgCarryBr, c2; {rD zero from above} BRANCH[ZeroReq, $], c3; rD _ RequestVersionHigh, c1; rD _ rD LRot8, c2; rD _ rD or RequestVersionLow, c3; MAR _ [rBrh, SD.Request.version+0], c1; MDR _ rD, c2; Noop, c3; MAR _ [rBrh, SD.Request.action+0], c1; MDR _ bootPhysicalVolume, c2; Noop, c3; MAR _ [rBrh, SD.Request.location.deviceType+0], c1; MDR _ germPilotDisk, c2; doneReq: MCtl _ 0, GOTO[exitToEmulator], c3; {Read the first page of the bootFile. Calculate the proper label by reading the label from the disk and filing in the correct fileID and page number} readBoot3: Noop, c3; readBoot: rB_ bootDiskAddr, c1; rC_ rD+headerAddr, L0_ 1, c2; {disk address of boot} acR_ 2, CALL[BLT], c3; {block transfer, takes count in acR, from in rB, and to in rC, returns first word past from block in rE} rB_ bootDiskAddr, c1, at[1, 10, subrRet]; rC_ rD or 80{uLinkPtr}, L0_ 0E, c2; {save for lisp} acR_ 2, CALL[BLT], c3; rB _ 82, c1, at[0E, 10, subrRet]; uLinkPtr _ rB, c2; rB_ bootDiskAddr, c3; {nil disk address?} MAR_ [rBrh, rB+0], c1; rB_ rB+1, c2; acR_ MD, c3; MAR_ [rBrh, rB+0], c1; Noop, c2; acR_ acR or MD, c3; []_ acR, ZeroBr, c1; BRANCH[$, nilBootFile], c2; rB_ nextPage, L1_ 1, c3; acR_ 1, CALL[doVrr2], c1; {read 1 starting at page 2} []_ acR and uBadBits, ZeroBr, c1, at[1, 10, transferRet]; rC_ rD+labelAddr, BRANCH[$, here2], c2; {write fileID into label} acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; here2: rB_ bootFileID, L0_ 2, c3; acR_ 6, CALL[BLT2], c1; {+low 16 bits of page #} rE_ rE and 7F, c1, at[2, 10, subrRet]; rE_ rE LRot8, c2; {rE_ high bits of page#} rE_ LShift1 rE, c3; MAR_ [rCrh, rC+0], c1; acR_ 7, c2; acR_ MD and acR, c3; MAR_ [rCrh, rC+0], c1; MDR_ acR or rE, c2; rC_ rC-1, c3; MAR_ [rCrh, rC+0], c1; {read low 16 bits of page #} rB_ bootDiskAddr, c2; rC_ MD, c3; rC_ rC+1, {reading first page is a special case} c1; filePage_ rC, c2; {restore disk address} rC_ rD+headerAddr, L0_ 3, c3; acR_ 2, CALL[BLT2], c1; rB_ nextPage, L1_ 5, c1, at[3, 10, subrRet]; acR_ 1, CALL[doVvr3], c2; {read 1 starting at page 2} []_ acR and uBadBits, ZeroBr, c1, at[5, 10, transferRet]; acR_ nextPage, BRANCH[$, here3], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; here3: acR_ acR+1, c3; nextPage_ acR, c1; {label template} acR_ labelSize, c2; rB_ rD+labelAddr, L0_ 6, c3; rC_ labelTemplate, CALL[BLT2], c1; {read the rest of the file from the Pilot Volume} readLoop: L1_ 1, c1, at[6, 10, subrRet]; CALL[pagesLeftInCylinder3], c2; transferCount_ acR, ZeroBr, c1, at[1, 10, miscRet]; L1_ 4, BRANCH[readRun, $], c2; {no pages left in cylinder, advance to next cylinder} Noop, c3; {step in one cylinder} MAR_ [rDrh, headerAddr+1], c1; MDR_ 0, CANCELBR[$, 0], c2; {start at head 0, sector 0} Noop, c3; MAR_ [rDrh, headerAddr+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, headerAddr+0], L1_ 2, c1; MDR_ acR+1, CALL[pagesLeftInCylinder3], c2; Noop, c1, at[2, 10, miscRet]; transferCount_ acR, L1_ 4, c2; readRun: rB_ nextPage, CALL[doVvr], c3; rE_ acR and uBadBits, ZeroBr, c1, at[4, 10, transferRet]; rB_ transferCount, BRANCH[readBurp, $], c2; acR_ filePage, c3; acR_ acR+rB, c1; {next page in file} filePage_ acR, c2; acR_ nextPage, c3; acR_ acR+rB, c1; {next page in memory} nextPage_ acR, c2; GOTO[readLoop], c3; {burped while reading run of pages, status in acR. rB has number of sectors requested} readBurp: []_ rE and ~verifyBit, ZeroBr, c3; MAR_ [rDrh, vvrAddr+0], BRANCH[$, verifyError], c1; {get # of sectors remaining} acR_ bootDeviceError, GOTOABS[Maintenance3Loc], c2; {not a verify error} verifyError: rC_ acR LRot4, c2; {shift field bits} rE_ MD, c3; {parameter area} MAR_ [rDrh, rE+sectors], c1; rC_ rC and 0C, c2; acR_ MD, c3; {number sectors remaining} []_ rC xor 8, ZeroBr, c1; {label verify error?} acR_ rB-acR, BRANCH[$, verErr1], c2; {number sectors transferred} acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; {not in label} verErr1: transferCount_ acR, {zero is okay} c3; rE_ filePage, c1; rE_ rE+acR+1, c2; {file page for next label} filePage_ rE, c3; rB_ nextPage, c1; rB_ rB+acR+1, c2; {next available page for vvr} nextPage_ rB, c3; rB_ rB-1, L1_ 6, c1; {page used by vrr} acR_ 1, CALL[doVrr3], c2; {transfer 1 page} []_ acR and uBadBits, ZeroBr, c1, at[6, 10, transferRet]; BRANCH[$, verErr3], c2; acR_ bootDeviceError, GOTOABS[Maintenance1Loc], c3; verErr3: Noop, c3; {Copy boot link to header, and check for end of file, FFFF in both words of boot link.} {*1,2 Check for end of file before copying boot link to header} {*0 stop reading after 768Kw max real memory} MAR_ [rDrh, labelPageLow+0], c1; Noop, c2; acR_ MD, c3; acR_ acR LRot8, c1; Ybus _ acR - 0C, {NibCarryBr{vPage> 768*4},} c2; Noop, BRANCH[$, endRead1], c3; MAR_ [rDrh, bootLink+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, bootLink+1], c1; CANCELBR[$, 0], c2; rB_ MD, c3; Noop, c1; Noop, c2; []_ acR or rB, ZeroBr, c3; acR_ acR+1, BRANCH[rdBurp1, $], c1; acR_ bootBrokenChain, GOTOABS[Maintenance3Loc], c2; {boot chain link is zero} rdBurp1: rB_ rB+1, c2; []_ acR or rB, ZeroBr, c3; rC_ rD+labelAddr, BRANCH[rdBurp2, $], c1; GOTO[endRead], c2; {found end of chain, return} rdBurp2: Noop, c2; Noop, c3; MAR_ [rDrh, headerAddr+0], c1; MDR_ acR-1, c2; , c3; MAR_ [rDrh, headerAddr+1], c1; MDR_ rB-1, CANCELBR[$, 0], c2; Q_ uLinkPtr, c3; Temp _ filePage, c1; rK _ uFirstPage, c2; , c3; MAR_ [rDrh, Q{uLinkPtr}+0], c1; MDR_ Temp - rK, c2; Noop, c3; MAR_ [rDrh, Q{uLinkPtr}+1], c1; MDR_ acR-1, CANCELBR[$, 0], c2; Noop, c3; MAR_ [rDrh, Q{uLinkPtr}+2], c1; MDR_ rB - 1, CANCELBR[$, 0], c2; Q{uLinkPtr} _ Q +3, PgCarryBr, c3; acR_ labelSize, BRANCH[there1, $], c1; {Noop,} L0_ 7, GOTO[there2], c2; there1: uLinkPtr _ Q{uLinkPtr+3}, L0_ 7, c2; there2: rB_ labelTemplate, CALL[BLT], c3; MAR_ [rDrh, labelPageLow+0], c1, at[7, 10, subrRet]; MDR_ filePage, c2; GOTO[readLoop], c3; endRead: Noop, c3; endRead1:Noop, c1; pRet2, c2; RET[readBootRet], c3; {here if boot file pointer was zero} nilBootFile: []_ uDiagnostic, ZeroBr, c3; acR_ 1 {disk Boot}, BRANCH[noDiagnostics, $], c1; []_ germStart, ZeroBr, c2; BRANCH[noGerm, noEmulator], c3; noEmulator: acR_ bootNoEmulator, GOTOABS[Maintenance2Loc], c1; noGerm: acR_ bootNoGerm, GOTOABS[Maintenance2Loc], c1; {this code tries a disk boot if no hard microcode is installed} noDiagnostics: uDiagnostic_ 0, c2; bootDevice _ acR {disk Boot}, GOTO[emuHard], c3; {subroutines} doVvr3: Noop, c3; doVvr: MAR_ [rDrh, vvrAddr+0], c1; GOTO[doTransfer], c2; {does verify, read, read operation to the disk Takes number of sectors in acR, page number in rB, and disk address in header area. Returns status in acR Clobbers rE} doVrr2: Noop, c2; doVrr3: Noop, c3; doVrr: MAR_ [rDrh, vrrAddr+0], c1; {base of vrr parameters} CANCELBR[$, 0], c2; doTransfer: rE_ MD, c3; MAR_ [rDrh, rE+sectors], c1; {set up paramter area} MDR_ acR, c2; {sector count} Noop, c3; MAR_ [rDrh, rE+dataPage], c1; MDR_ rB - 1, CANCELBR[$, 0], c2; {first page in main storage} Noop, c3; MAR_ [rDrh, rD+ transferAddr], c1; {base of transferIOCB} acR_ rE, CANCELBR[$, 0], c2; {base of vrr parameter area} rE_ MD, c3; MAR_ [rDrh, rE+parameters], c1; MDR_ acR, CANCELBR[$, 0], c2; rC_ acR, c3; MAR_ [rDrh, headerAddr+1], c1; {read head} CANCELBR[$, 0], c2; acR_ MD, c3; acR_ acR LRot4, c1; acR_ acR RRot1, c2; acR_ acR and headMask, c3; acR_ acR or haltBits, c1; Noop, c2; Noop, c3; MAR_ [rDrh, rC+haltWord], c1; {write halt word} MDR_ acR, CANCELBR[$, 0], c2; acR_ acR or UFindSect, c3; MAR_ [rDrh, rC+findWord], c1; {write find word} MDR_ acR, CANCELBR[$, 0], L0_ 2, c2; rC_ rE, CALL[seek], c3; []_ acR and uBadBits, ZeroBr, L0_ 3, c1, at[2, 10, transferRet]; BRANCH[transferError, $], c2; rE_ rC, CALL[diskOp], c3; transferRet1: Noop, c1, at[3, 10, transferRet]; pRet1, c2; transferRet2: RET[transferRet], c3; transferError: GOTO[transferRet1], c3; {call with IOCB in rE, returns when disk operation complete with status in acR} {diskOp1: Noop, c1; diskOp2: Noop, c2; diskOp: acR_ IOPageLow, c3, at[2, 4]; MAR_ [acRrh, diskCSB+0], c1;}diskOp: Noop, c1; acRrh _ IOPageHigh, c2; {AEF 9/14/83 - why is this instruction at[2, 4]?} acR _ uIOPage, c3, at[2, 4]; MAR_ [acRrh, DiskCSBOffsetIOCB+0], c1; MDR_ rE, c2; Noop, c3; MAR_ [rDrh, statusAddr+0], c1; {set invalid status} MDR_ badBits, c2; acR_ firmwareEnable, c3; {start the transfer} KCtl_ acR LRot0, c1; transferWait: acR_ ~KStatus, CANCELBR[$, 0], c2, at[0F, 10, transferWait]; []_ acR LRot8, XDisp, c3; {test firmware busy} MAR_ [rDrh, statusAddr+0], BRANCH[$, transferWait], c1; pRet0, LOOPHOLE[natc], c2, at[0E, 10, transferWait]; acR_ MD, RET[transferRet], c3; {return status in acR} {call with current cylinder in currentCylinder, and desired cylinder in cylinder field of header} seek: MAR_ [rDrh, headerAddr+0], c1; rB_ currentCylinder, CANCELBR[$, 0], c2; acR_ MD, c3; {target} rB_ rB-acR, ZeroBr, c1; {delta number of cylinders} currentCylinder_ acR, BRANCH[$, noSeek], c2; []_ rB, NegBr, c3; acR_ 0, BRANCH[seekOut, $], c1; acR_ inBit, GOTO[seek1], c2; seekOut: rB_ -rB, c2; seek1: acR_ acR or seekMask, {enable firmware, drive select} c3; MAR_ [rDrh, seekAddr+0], c1; {address of seek IOCB} CANCELBR[$, 0], c2; rE_ MD, c3; MAR_ [rDrh, rE+cylinders], c1; MDR_ rB, c2; Noop, c3; MAR_ [rDrh, rE+stepHigh], c1; MDR_ acR or stepBit, CANCELBR[$, 0], c2; Noop, c3; MAR_ [rDrh, rE+stepLow], c1; MDR_ acR, CANCELBR[$, 0], c2; rE_ rE+1, GOTO[diskOp], c3; noSeek: acR_ 0, c3; Noop, c1; pRet0, GOTO[transferRet2], c2; {Be careful, these routines are device dependent! Only routines for SA1004 and SA4008 are supplied} {Uses data left in last header to compute pages left in cylinder, returns result in acR.} pagesLeftInCylinder3: Noop, c3; pagesLeftInCylinder: Noop, c1; {SA4000 or SA1000?} Xbus_ KStatus, XwdDisp, c2; BRANCH[SA1000Left, $, 2], c3; {SA4008, pages left in cylinder= (28-sector)+(8-head-1)*28} MAR_ [rDrh, headerAddr+1], c1, at[3,4,SA1000Left]; rB_ 7, CANCELBR[$, 0], c2; rE_ MD, c3; acR_ rE LRot8, c1; acR_ acR and 0FF, c2; {head} rE_ rE and 0FF, c3; {sector} acR_ rB-acR, NegBr, L0_ 0, c1; rB_ 28'd, BRANCH[multiply, $], c2; acR_ 0, c3; {off the end of the cylinder} OffEnd: rE_ 0, c1; pRet1, GOTO[pgLft1], c2; {return from multiply} divMultRet: acR_ Q+28'd, pRet1, GOTO[pgLft1], c2, at[0, 10, divMultRet]; {SA1004, pages left in cylinder= (16-sector)+(4-head-1)*16} SA1000Left: MAR_ [rDrh, headerAddr+1], c1, at[2,4,SA1000Left]; rB_ uQuantumSA1000MaxHeadNum, CANCELBR[$, 0], c2; rE_ MD, c3; acR_ rE LRot8, c1; acR_ acR and 0FF, c2; {head} rE_ rE and 0FF, c3; {sector} acR_ rB-acR, NegBr, c1; rB_ acR LRot4, BRANCH[SA1000More, $], c2; {(4-head-1)*16} acR_ 0, GOTO[OffEnd], c3; {off the end of the cylinder} SA1000More: Noop, c3; Noop, c1; acR_ rB+16'd, pRet1, c2; pgLft1: acR_ acR-rE, RET[miscRet], c3; {multiply, call with multiplier in rB, multiplicand in acR, uses rC, result left in Q timing: 45 cycles main loop is 3 cycles times 15 iterations 4 cycles last iteration 3 cycles preamble 1 cycles postamble total 53 cycles (2 MOD 3} multiply: Q_ acR, c*; acR_ 0'x, c2; rC_ 10'x, c3; mult0: []_ Q and 1, ZeroBr, c1; rC_ rC-1, ZeroBr, BRANCH[mult1, mult2], c2; mult1: acR_ DARShift1 (acR+rB), BRANCH[mult0, mult3], c3; mult2: acR_ acR DARShift1, BRANCH[mult0, mult3], c3; mult3: Q_ ~Q, pRet0, c1; RET[divMultRet], c*; {E N D}