{File name: [Idun]LispTridentInitial.mc Lichtenberg 27-Jun-84 21:22:36 -- a stab at Lisp Initial Lichtenberg 28-Jun-84 21:16:17 -- Lisp lives on Trident!!!!!!! Lichtenberg 8-Jul-84 12:23:51 -- Put in code to build burp table on IOCB page Lichtenberg 8-Jul-84 16:14:23 -- Trident boot now automatic for 16k ctl store Description: first microcode read from the Trident disk, gets emulator microcode into CP memory, Author: Neely, Created: Neely ,December 11, 1981 12:38 PM Last Edited by Neely February 17, 1982 10:16 AM: - fix to boot link in ucode file & cyl cross. Last Edited by Neely February 17, 1982 7:02 AM: - fix to handle first page with boot link. Last Edited by Neely February 3, 1982 9:44 AM: - Moved RegDef of uDevOrd to dandelion.df. Last Edited by Neely February 2, 1982 4:16 PM: - Retries during Initial. Last Edited by Neely January 15, 1982 9:27 PM: - Fixed SD.Request.location.deviceOrdinal bug. Last Edited by Neely January 15, 1982 2:13 PM: - Fixed rCrhm = 1 bug. Last Edited by Neely January 14, 1982 2:37 PM: - Restored extract of filePageHi from BootID. Last Edited by Neely January 13, 1982 7:49 PM: - 30 secs., fixed multiDrive bug, filePageHi bug. Last Edited by Neely January 12, 1982 6:31 PM: - Fixed IOCB update and filePageHi bugs. Last Edited by Neely January 4, 1982 1:30 PM: - Fixed IOCBdiskLabel bug. Last Edited by Neely December 31, 1981 5:03 PM: - Fixed register bug @ xTest+1. Last Edited by Neely December 18, 1981 2:09 PM: - Fix NegBr probs and clientHeader probs. Last Edited by Neely December 17, 1981 5:46 PM: - IOCB.clientHeader_0/0/0 Last Edited by Neely December 17, 1981 10:09 AM: - Recal as well as Reset Last Edited by Neely December 15, 1981 5:14 PM: - Make all Rets [x, 10, z] Last Edited by Neely December 11, 1981 12:38 PM:} RegDef[uLinkPtr, U, 27{uTT}]; {uLinkPtr} {word offsets} {into Working Page} Set[WPinitCSB, 48]; Set[WPrdLblCtl, 42]; Set[WPverLblCtl, 46]; Set[WPvrrLabelParam, 40]; Set[WPvvrLabelParam, 44]; {into IOCBs} Set[IOCBcHeader, 0]; {clientHeader} Set[IOCBcHeaderCyl, 0]; {clientHeader.cylinder} Set[IOCBcHeaderHS, 1]; {clientHeader.head§or} Set[IOCBdataPtrLo, 4]; Set[IOCBdataPtrHi, 5]; Set[IOCBtries, 6]; Set[IOCBpageCount, 7]; Set[IOCBcStatus, 8]; {Controller Status} Set[IOCBdStatus, 9]; {Disk Status} Set[IOCBdHeader, 0A]; Set[IOCBdiskAdr, 0E]; Set[IOCBfilePageLo, 0F]; Set[IOCBseekDrive, 11]; Set[IOCBseekCyl, 12]; Set[IOCBseekHead, 13]; Set[IOCBhdrCtl, 16]; Set[IOCBlabelParam, 18]; Set[IOCBdataCtl, 1E]; Set[IOCBlabelParam, 18]; Set[IOCBlabelErrMask, 1B]; Set[IOCBclientLabel, 20]; Set[IOCBcLblFilePageLo, 25]; Set[IOCBcLblFilePageHi, 26]; Set[IOCBcLblBootLink, 28]; Set[IOCBcLblBootLink1, 29]; Set[IOCBdiskLabel, 30]; Set[IOCBdLblBootLink, 38]; {values } Set[vDStatusEndCyl, 40]; Set[vDStatusAnyAtten, 80]; Set[vCStatusLastField, 6]; {Last Field Mask} Set[vCStatusDataField, 6]; Set[vCStatusLblField, 4]; Set[vCStatusVerErrLRot8, 8]; Set[vCmdTagHd, 40]; Set[vCmdHd5, 5]; Set[vCmdTagCtl, 20]; Set[vCmdResetRecal, 0A]; Set[vLabelSize, 0A]; Set[vT300Heads, 19'd]; Set[vT80Heads, 5]; Set[vSecsPerTrack, 30'd]; {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} Set[germPageHigh, 0]; {virtual page number of origin of germ -- 1B} Set[germPageLow, 1]; Set[sFirstGermRequest, 320'b]; {start of germ request in SD} Set[sLastGermRequest, 377'b]; {end of germ request in SD} Set[RequestSize, 60'b]; {size of germ request in SD} Set[SD.Request.version, 320'b]; Set[RequestVersionHigh, 7]; Set[RequestVersionLow, 56'b]; Set[SD.Request.action, 321'b]; Set[bootPhysicalVolume, 2]; Set[SD.Request.location, 322'b]; Set[SD.Request.location.deviceType, 322'b]; Set[germPilotDisk, 64'd]; Set[SD.Request.location.devOrd, 323'b]; Set[bootNotEnoughBanks, 57'd]; {makes 257 error code if trident boots with 4k storage} Set[MicroDBNumber,3]; {second DB is microcode} DoneOnceOnlyInit: {Initialization} rE_ 0, c1; germStart_ rE, c2; Noop, c3; acR_ 2, c1; acR_ acR LRot8, c2; uBootStart_ acR, c3; {boot file starts at 200} {===========================================================================} {**** START of NEW CODE for LISP *****} {*} 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; {**** END of NEW CODE for LISP *****} {===========================================================================} {map virtual pages 0-255 to real pages 0-255, first we must save the current mapping of the lowest virtual pages} rBrh_ 1, c1; rCrh_ 1, c2; rB_ 0, c3; rC_ topPage, L3_ 0, c1; acR_ 0FF+1, CALL[L3BLT3], c2; acR_ present, c1, at[0, 10, L3BLTRet]; rC_ 0FF+1, c2; rB_ 0, c3; {set up identity map for benefit of the disk microcode} identityMap: MAR_ [rBrh, rB+0], BRANCH[$, InitIOCB], c1; MDR_ acR, rB_ rB+1, c2; acR_ acR+rC, CarryBr, GOTO[identityMap], c3; InitIOCB: rBrh _ 0, c2; rB _ 0FF+1, c3; {addr of IOCB} rD _ bUBitSignAdr, c1; KCtl _ rD LRot0, c2; {Select boot drive} Noop, c3; {Initialize IOCB.clientHeader=0/0/0} MAR _ [rBrh, IOCBcHeaderCyl+0], c1; MDR _ 0, c2; rCrh_ 0, c3; MAR _ [rBrh, IOCBcHeaderHS+0], c1; MDR _ 0, c2; rDrh_ 0, c3; {Merge drive info into IOCB. Uses rB=100=IOCBaddr & rD=bUBitSignAdr} rC _ rB+IOCBseekDrive, L0_ 0, c1; CALL[merge3], c2; rC _ rB+IOCBhdrCtl, L0_ 1, c1, at[0, 10, mergeRet]; CALL[merge3], c2; rC _ rB+IOCBdataCtl, L0_ 2, c1, at[1, 10, mergeRet]; CALL[merge3], c2; rC _ rB+WPrdLblCtl, L0_ 3, c1, at[2, 10, mergeRet]; CALL[merge3], c2; rC _ rB+WPverLblCtl, L0_ 4, c1, at[3, 10, mergeRet]; CALL[merge3], c2; [] _ rD LRot8,XDisp, c1, at[4, 10, mergeRet]; DISP4[CSBIndex], c2; rC _ 0, {drive 0} GOTO[IOCBDA], c3, at[8, 10, CSBIndex]; rC _ 4, {drive 1} GOTO[IOCBDA], c3, at[4, 10, CSBIndex]; rC _ 8, {drive 2} GOTO[IOCBDA], c3, at[2, 10, CSBIndex]; rC _ 0C, {drive 3} c3, at[1, 10, CSBIndex]; IOCBDA: MAR _ [rBrh, IOCBdiskAdr+0], c1; MDR _ rC, c2; acR _ rC, c3; acR _ RShift1 acR, c1; acR _ RShift1 acR, c2; uDevOrd _ acR, c3; InitCSB: rB _ rB+WPinitCSB, {adr Init vals for CSB} c1; rC _ rC+rB+1, c2; acR _ 0FF+1, c3; MAR _ [rCrh, rC+0], c1; MDR _ acR, c2; rCrh _ 1, c3; rC _ IOPageLow, L3_ 1, c1; {CSB at 14000} acR _ 10, CALL[L3BLT3], c2; {Set tiUnumHeads based on boot drive type(i.e. T80/T300)} {select head 5} rB _ U0400, c1, at[1, 10, L3BLTRet]; rB _ rB or vCmdHd5, L0 _ 0, c2; {Select Head 5} rC _ vCmdTagHd, CALL[SetRst1], c3;{delays after tagReset} Xbus _ KStatus, XwdDisp, {test bit 9&10} c3, at[0, 10, SetRst3Ret]; DISP2[DiskType, 1], c1; typeT300: acR _ vT300Heads, GOTO[setHeads], c2, at[3, 10, DiskType]; typeT80: acR _ vT80Heads, c2, at[1, 10, DiskType]; setHeads: tiUnumHeads _ acR, c3; rB _ U0400, c1; rB _ rB or vCmdResetRecal, L0 _ 1, c2; rC _ vCmdTagCtl, CALL[SetRst1], c3; {Reset Disk Check} rCrh _ 0, GOTO[rootPage], c3, at[1, 10, SetRst3Ret]; {===========================================================================} {**** START of NEW CODE for LISP *****} {** 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_ 03{B}0{dirtyRef}, BRANCH[$, MesaBoot2], c1; Q{100}_ 0FF+1, c2; nextId3: rBrh_ 1, c3; {acR{dirtyRef}, rB{10000}, Q{100}, map 2^12 pages as identity} 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, Zdone], c2; Zdone: rC _ rC LRot8, c3; Ybus _ 0E - rC, PgCarryBr{if rC is low or eq}, c1; acR _ 0B0{2mb+dirty}, BRANCH[ZnextId3, doneId], c2;{%%} {acR{2mb+dirty}, rB{10000}, Q{100}, map next 2^11 pages as identity} ZnextId: MAR_ [rBrh, rB+0], c1; MDR_ acR, acR _ acR + Q{100}, CarryBr, c2; rB_ rB+1, BRANCH[ZnextId, $], c3; ZincSeg: Ybus _ acR + 1{9}, NibCarryBr{2^12{11} more pages}, c1; acR _ acR + 1, BRANCH[ZnextId3, doneId], c2; ZnextId3: Noop, GOTO[ZnextId], c3; doneId: acR{dirty;page FF}_ ~0DF, c3; rCrh_1, c1; rC_ 040, c2; rC{14000} _ rC LRot8, c3; {acR{FF20}, rB{12000{11800}}, rCrh,rC{14000}, 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{4000}, ZeroBr, GOTO[Scrap], c3; doneScrp: Noop, c2; Noop, c3; {acR{-1}, rCrh,rC{14000}, change 65 map entries to protect the map and iopage to point to FF{-1}} Protect65: Map{14000}_ [rCrh, rC+0], c1; MDR_ acR{-1}, rC_ rC, ZeroBr, c2; rC_ rC - 0FF - 1, BRANCH[Protect65, $], c3; GOTO[InitIOCB],c1; {**** END of NEW CODE for LISP *****} {===========================================================================} {Now we're ready to read the root page.} {There is only one IOCB. DCB[0] points to it. DCB[0] can be used for any drive. The IOCB is initialized with a da=0/0/0 .} rootPage: rD_ 0FF+1, c1; {rD(rh)= addr of IOCB} rF _ 2, L3 _ 0, c2; {read data into pg. 2} acR _ 1, CALL[doVrr1], c3; {save the useful stuff from the physical volume root page} rC_ 2, c1, at[0, 10, xferGoodRet]; rB_ rC LRot8, c2; rB_ rB+bootingInfo, L3_ 2, c3; acR_ bootingInfoSize, CALL[L3BLT2], c1; {read the emulator boot file or the hard microcode} emuHard: []_ uDiagnostic, ZeroBr, c1, at[2, 10, L3BLTRet]; 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; {===========================================================================} {**** START of NEW CODE for LISP *****} 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: rB{7FFF}_ ~1 RRot1, rBrh_ 1, c1; rB{3FFF}_ rB RShift1, c2; rC _ 60{vacant}, c3; vacLp: MAR_ [rBrh{0C1}, 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 _ 26'b{INTERFACEspace}, CANCELBR[$, 1], c1; acR _ 20'b{INTERFACEbase=10000'b}, c2; acR _ acR LRot8, c3; rB _ 3{real interface page}, c1; rB{300} _ rB LRot8, c2; rBrh _ rB _ rB + 03{B}0{dirty}, c3; Map{161000} _ [acRrh,acR], c1; MDR _ rB{3B0}, c2; rC _ 0C{(NRealPages{3072})/256}, c3; MAR_ [rBrh, 15'b{MachineType} + 0], c1; MDR _ 6{\DANDELION}, c2; rC{C00} _ rC LRot8, c3; Q _ topPage{virtual}, c1; Q _ Q + 40,{ map not included} c2; Q{NRealPages} _ Q + {02}{0A8}{-56 mp301}0FF{+1}{bank 0 was not incl but}, c3; MAR_ [rBrh, 70'b{NRealPages} + 0], c1; MDR _ Q{NRealPages} {_ topPage}{rC{C00}}, c2; Noop, c3; {%% no segment crossing of FPTOVP[i-1] ptr ??? } {interpret FPTOVP setup} {for i{acR} _ 501'b to MaxRealPage{rC} } { unless FPTOVP[i-1]=none{-1} } { do MAP[FPTOVP[i-1]]:vp _ i } MAR_ [rBrh, 73'b{FPTOVPStart} + 0], c1; rBrh _ 1, c2; acR{F2Vpage} _ MD, c3; acR{F2VrealPage+1} _ acR + 2{file1=real2}{+1}, c1; acRrh _ acR _ acR LRot8, c2; acR _ acR and ~0FF, c3; acR{F2V+500b} _ acR + 40, c1; rC _ 0FF + 1, c2; rC{501b} _ rC + 41, c3; {interpret FPTOVP Loop } {acR: FPTOVP[i-1] ptr } {rB: FPTOVP[i-1]:vp } {rC: i _ 501b } {Q: NRealPages= C00 } {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{7FFF}, c3; Ybus _ rB + rB, NegBr, 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{NRealPages}, ZeroBr, c2; acR _ acR + 1, BRANCH[f2vLp, $], c3; {spin3: GOTO[spin3], c*;}{%%%} {done with interpret FPTOVP} Noop, c1; rBrh _ 1, c2; Noop, c3; rB _ 0FF, c1; rC _ 40, c2; rC{4000} _ rC LRot8, c3; {Map[IOPageVp=0FF] _ 500} MAR{100FF}_ [rBrh{1}, rB + 0], c1; MDR{4001} _ rC{4000} + 1, c2; rC{100} _ 0FF + 1, c3; rC{200} _ rC + rC, c1; rC{400} _ rC + rC, c2; uBootStart_ rC{400}, {GOTO[StartNewInit],} c3; bankTest: Q _ 0, c1; Bank _ rB _ 0, c2; btLoop: rC _ ~ PPort, BRANCH[$, {GOTO[}MultiBank], c3; btLL: rC _ (rC LRot8) xor Q, c1; Ybus _ rC and 3, NZeroBr, c2; Q _ Q + {0FF +} 1, BRANCH[$, NotEnoughBanks], c3; 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_ MicroDBNumber{3rd DB for Trident}, c3; {*** Changed for auto Lisp boot ***} MAR_ [rBrh, rC+0], c1; rC{400q}{100} _ 0FF + 1, c2; rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC{400}, c2; Noop,GOTO[StartNewInit], c3; {Tridents without 16k control store are not allowed yet} NotEnoughBanks: acR _ bootNotEnoughBanks, GOTOABS[Maintenance2Loc], c1; BackFromNewInit: c1; TOS{8002h} _ RRot1 5, c2; MCtl _ TOS{8002h}, GOTO[exitToEmulator], c3; {**** END of NEW CODE for LISP *****} {===========================================================================} {hard microcode (quick exit), pick up diagnostic table entry from first page of boot file} {===========================================================================} {**** START of NEW CODE for LISP *****} doDiag: rB _ 055{Mesa}, GOTO[doDiag2], c1; notLisp: rB _ 055{Mesa}, GOTO[doDiag2], c1; doDiag2: uLispBootMsg _ rB, c2; {**** END of NEW CODE for LISP *****} {===========================================================================} rB_ 2, c3; {boot file starts at 200} rB_ rB LRot8, c1; rC_ rC+1, c2; Noop, c3; MAR_ [rBrh, rC+0], c1; Noop, c2; rC_ MD, c3; rC_ rC+rB, c1; uBootStart_ rC, c2; GOTO[exitToEmulator], c3; {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_ 0FF+1, c3; MAR_ [rBrh, rB+0], c1; MDR_ vacant, L0_ 0B, c2; acR_ 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: 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; rD _ uDevOrd, c3; MAR _ [rBrh, SD.Request.location.devOrd+0], c1; MDR _ rD, c2; Noop, c3; MAR _ [rBrh, SD.Request.location.deviceType+0], c1; MDR _ germPilotDisk, c2; doneReq: 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+IOCBcHeader, L3_ 3, c2; {disk address of boot} acR_ 2, CALL[L3BLT], c3; {** New for Lisp: Copy addr of first page of boot file to IOCB page} rB_ bootDiskAddr, c1, at[3, 10, L3BLTRet]; {nil disk address?} rC_ rD or 80{uLinkPtr}{+{1}headerAddr}, L0_ 0E{*free?}, c2; {save for lisp} acR_ 2, CALL[BLT], c3; rB _ 82, {** New for Lisp - sets up loc of burp table}c1, at[0E, 10, subrRet]; uLinkPtr _ rB {** New for Lisp **}, c2; rB_ bootDiskAddr, c3; {nil disk address?} { ** End of new stuff for Lisp **} 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; rF_ nextPage, L3_ 1, c3; acR_ 1, CALL[doVrr2], c1; {read 1 starting at page 2} rC_ rD+IOCBclientLabel, c1, at[1, 10, xferGoodRet]; rB_ bootFileID, L3_ 4, c2; acR_ 6, CALL[L3BLT], c3; rE_ rE and 7F, c1, at[4, 10, L3BLTRet]; 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; Noop, c3; MAR_ [rDrh, IOCBcLblFilePageLo+0], c1,; rB_ bootDiskAddr, c2; rC_ MD, c3; {read low 16 bits of page #} rC_ rC+1, {reading first page is a special case} c1; filePage_ rC, c2; {restore disk address} rC_ rD+IOCBcHeader, L0_ 3, c3; acR_ 2, CALL[BLT2], c1; rF_ nextPage, L3_ 2, c1, at[3, 10, subrRet]; acR_ 1, CALL[doVvr3], c2; {read 1 starting at page 2} acR_ 0A, GOTOABS[Maintenance2Loc], c1, at[2, 10, xferLblVerRet]; {was bootDeviceError} acR_ nextPage, c1, at[2, 10, xferGoodRet]; acR_ acR+1, c2; nextPage_ acR, c3; MAR_ [rDrh, IOCBcLblFilePageHi+0], c1; acR_ ~7, c2; acR_ MD and acR, {Mask out 3bit Label flags} c3; MAR_ [rDrh, IOCBcLblFilePageHi+0], c1; MDR_ acR, c2; Noop, c3; {check for VERY special case of a boot link in the first page} MAR_ [rDrh, IOCBcLblBootLink+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, IOCBcLblBootLink1+0], c1; Noop, c2; rB_ MD, c3; []_ acR or rB, ZeroBr, c1; BRANCH[rbLink, rbNotLink], c2; rbLink: Noop, {boot link in the first page} c3; MAR_ [rDrh, IOCBcHeader+0], c1; MDR_ acR, c2; Noop, c3; MAR_ [rDrh, IOCBcHeader+1], c1; MDR_ rB, CANCELBR[$, 0], c2; acR _ 0, {to zero out boot link} c3; MAR_ [rDrh, IOCBcLblBootLink+0], c1; MDR_ acR, c2; Noop, c3; MAR_ [rDrh, IOCBcLblBootLink1+0], c1; MDR_ acR, c2; rbNotLink: rC_ labelTemplate, c3; rB_ rD+IOCBclientLabel, L0_ 6, c1; acR_ vLabelSize, CALL[BLT3], c2; {read the rest of the file from the Pilot Volume} readLoop: L1_ 1, c1, at[6, 10, subrRet]; CALL[pagesLeftInCylinder], c2; transferCount_ acR, NZeroBr, c1, at[1, 10, PLCRet]; BRANCH[$, readRun], c2; Noop, c3; {no pages left in cylinder, advance to next cylinder} MAR_ [rDrh, IOCBcHeaderHS+0], c1; MDR_ 0, c2; {start at head 0, sector 0} Noop, c3; MAR_ [rDrh, IOCBcHeaderCyl+0], c1; Noop, c2; acR_ MD, c3; MAR_ [rDrh, IOCBcHeaderCyl+0], L1_ 2, c1; MDR_ acR+1, CALL[pagesLeftInCylinder], c2; {step in one cylinder} Noop, c1, at[2, 10, PLCRet]; transferCount_ acR, c2; readRun: rF_ ~0FF, L3_ 3, c3;{** Was: rF _ nextPage} {*** New stuff for Lisp ***} {Transfer count reduced to 0FF} Ybus _ acR and rF, NZeroBr, c1; rF _ nextPage, BRANCH[oldTCnt,newTCnt],c2; oldTCnt: GOTO[readRun1],c3; newTCnt: acR _ 0FF, GOTO[readRun1], c3; readRun1: Ybus _ rF + acR, PgCarryBr{new transferCount}, c1; Noop, BRANCH[oldTC, newTC], c2; oldTC: Noop, GOTO[readRun2], c3; newTC: acR _ 0-rF, GOTO[readRun2], c3; readRun2: Noop, c1; Noop, c2; acR_ acR and 0FF, c3; {*** End New Stuff for Lisp ***} transferCount _ acR, CALL[doVvr2], c1; {TransferCount _ ACR for Lisp} rB_ transferCount, c1, at[3, 10, xferGoodRet]; acR_ filePage, c2; acR_ acR+rB, c3; {next page in file} filePage_ acR, c1; acR_ nextPage, c2; acR_ acR+rB, c3; {next page in memory} nextPage_ acR, c1; Noop, c2; GOTO[readLoop], c3; {burped while reading run of pages, controllerStatus in rF.} readBurp: MAR_ [rDrh, IOCBpageCount+0], {get # of sectors remaining} c1, at[3, 10, xferLblVerRet]; rB_ transferCount, c2; acR_ MD, {number sectors remaining} c3; acR_ rB - acR, {number sectors transferred} c1; transferCount_ acR, {zero is okay} c2; rE_ filePage, c3; rE_ rE+acR+1 {+1 because one sec read via Vrr}, c1; {file page for next label} filePage_ rE, c2; rB_ nextPage, c3; rB_ rB+acR+1 {+1 because one sec read via Vrr}, c1; {next available page for vvr} nextPage_ rB, c2; rF_ rB-1, L3_ 4, c3; {page used by vrr} acR_ 1, CALL[doVrr2], c1; {transfer 1 page} {Copy boot link to header, and check for end of file, FFFF in both words of boot link.} MAR_ [rDrh, IOCBdLblBootLink+0] ,c1,at[4, 10, xferGoodRet]; Noop, c2; acR_ MD, c3; MAR_ [rDrh, IOCBcHeader+0], c1; MDR_ acR, c2; Noop, c3; MAR_ [rDrh, IOCBdLblBootLink+1], c1; CANCELBR[$, 0], c2; rB_ MD, c3; MAR_ [rDrh, IOCBcHeader+1], c1; MDR_ rB, CANCELBR[$, 0], 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;{FFFF+1 or FFFF+1 = 0 => end} rC_ rD+IOCBclientLabel, BRANCH[rdBurp2, endRead], c1; rdBurp2: {*** New stuff for Lisp ***} Noop, c2; Noop, c3; {*1} MAR_ [rDrh, IOCBcHeader{headerAddr}+0], c1; MDR_ acR-1, c2; Noop, c3; {*2} MAR_ [rDrh, IOCBcHeader{headerAddr}+1], c1; MDR_ rB-1, CANCELBR[$, 0], c2; {*2} Q_ uLinkPtr, c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+0], c1; MDR_ filePage, c2; Noop, c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+1], c1; MDR_ acR-1, CANCELBR[$, 0], c2; Noop, c3; {*5} MAR_ [rDrh, Q{uLinkPtr}+2], c1; MDR_ rB-1, CANCELBR[$, 0], c2; Q{uLinkPtr} _ Q +3, PgCarryBr, c3; acR_ vLabelSize{labelSize}, BRANCH[there1, $], c1; {Noop,} L0_ 7, GOTO[there2], c2; there1: uLinkPtr _ Q{uLinkPtr+3}, L0_ 7, c2; there2: rB_ labelTemplate, CALL[BLT], c3; {*** End new stuff for Lisp ***} { rB_ labelTemplate, L0_ 7, c2; acR_ vLabelSize, CALL[BLT], c3;} MAR_ [rDrh, IOCBcLblFilePageLo+0], c1, at[7, 10, subrRet]; MDR_ filePage, c2; GOTO[readLoop], c3; endRead: 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} {doVvr and doVrr do either a vvr or vrr operation to the boot drive. TridentBootIOCB.bravo set up an IOCB that has. .microNext=0 .dcbOffset=0 (DCB[0] can be and is used for any drive) .headerParam=verify, IncrDataPtr=TRUE, firstIOCB=TRUE .dataParam=read Early parts of TridentInitial do the following. Set up DCB[0].microNext=ptr-to-the-only-IOCB, (never changed). Particularize IOCB based on boot drive. Additionally both vrr and vvr REQUIRE: acR=pageCount, rD(rh)=IOCB addr., rF=MemoryPageNumber, IOCB.clientHeader=Header, vvr also REQUIRES: IOCB.clientLabel=Label Both vrr and vvr RETURN: rD(rh) unchanged, rF=ControllerStatus, IOCB.clientHeader=last in run. IOCB.pageCount=upDated (0 If good completion) IOCB.dataPtr=last in run. vvr also RETURNS: IOCB.clientLabel=updated vrr also RETURNS: IOCB.clientLabel = IOCB.diskLabel as read} doVrr2: Noop, c2; doVrr3: Noop, c3; doVrr1: L1 _ 0, c1; rB _ rD+WPvrrLabelParam, CALL[doXfer], c2; rB _ rD+IOCBdiskLabel, c1, at[0, 10, doXferGoodRet]; rC _ rD+IOCBclientLabel, L0_ 1, c2; acR _ 0A, CALL[BLT], c3; xUpdateHS: MAR_ [rDrh, IOCBcHeaderHS+0], c1, at[1, 10, subrRet]; acR _ vSecsPerTrack, c2; rB_ MD, c3; {rB _ head sector} rC _ rB+1, c1; rC _ rC and 0FF, c2; []_ rC xor acR, ZeroBr, c3; BRANCH[$, xLastSec], c1; Noop, GOTO[xIncrHS] c2; xLastSec: rB _ rB or 0FF, c2;{so +1 yields sec=0 head+1} xIncrHS: rB _ rB+1, c3; MAR_ [rDrh, IOCBcHeaderHS+0], c1; MDR_ rB, pRet3, c2; {update head sector} RET[xferGoodRet], c3; doVvr2: Noop, c2; doVvr3: Noop, c3; doVvr1: L1 _ 1, c1; rB _ rD+WPvvrLabelParam, CALL[doXfer], c2; MAR_ [rDrh, IOCBcLblFilePageLo+0], c1, at[1, 10, doXferGoodRet]; Noop, c2; rB_ MD, c3; MAR_ [rDrh, IOCBcLblFilePageLo+0], c1; MDR_ rB+1, c2; {update client label} GOTO[xUpdateHS], c3; {doXfer completes the set-up of the IOCB and starts the microcode. It then waits for the inProgress bit to go off. If there were no errors, then it returns via pRet1/doXferGoodRet. If there is a PURE label verify error, then it returns via pRet3/xferLblVerRet. In either case rF has the status. For other error conditions doXfer retries the operation and if IOCB.tries goes to zero it goes to Maintenance2Loc with a bootDeviceError code.} doXfer: rF _ rF LRot8, c3; MAR_ [rDrh, IOCBpageCount+0], c1; MDR_ acR, c2; {set IOCB.pageCount} rC _ rD+IOCBlabelParam, c3; {** generalize TridentInitial to read past 0th segment} MAR_ [rDrh, IOCBdataPtrHi+0], c1; MDR_ rF and 0FF, c2; {IOCB.dataPtrLo} Noop, c3; MAR_ [rDrh, IOCBdataPtrLo+0], c1; MDR_ rF and ~0FF, L0_ 2, c2; {set IOCB.dataPtrLo} acR_ 4, CALL[BLT], c3; {vvr/vrr to labelParam} rB _ rD+IOCBcHeader, GOTO[Xzzy], c1, at[2, 10, subrRet]; XRetry: rB _ rD+IOCBcHeader, c1; Xzzy: rC _ rD+IOCBdHeader, L0_ 4, c2; acR _ 2, CALL[BLT], c3; MAR_ [rDrh, IOCBcLblFilePageLo+0], c1, at[4, 10, subrRet]; acR _ 0C0, c2; rB_ MD, c3; MAR_ [rDrh, IOCBfilePageLo+0], c1; MDR_ rB, c2; {set IOCB.filePageLo} acR _ acR LRot8, c3; MAR_ [rDrh, IOCBcStatus+0], c1; MDR_ acR, c2; {C000=InPrg&GoodComp} acR _ acR LRot12, {acR = 0C00} c3; MAR _ [rDrh, IOCBcHeader+1], c1; {get head, sector} CANCELBR[$, 2], LOOPHOLE[wok], c2; rB_ MD, c3; rB _ rB LRot8, c1; {sector, head} rB _ rB and 0FF, c2; rB_ rB or acR, c3; MAR_ [rDrh, IOCBseekHead+0], c1; MDR_ rB, c2; {set IOCB.seekHead} rC _ vCStatusVerErrLRot8, {used in err recovery} c3; MAR _ [rDrh, IOCBcHeader+0], c1; {get cylinder} rC _ rC LRot8, {used in err recovery} c2; rB_ MD, c3; MAR_ [rDrh, IOCBseekCyl+0], c1; MDR_ rB or acR, c2; {set IOCB.seekCyl} KCmd _ acR LRot0, c3; {0C00=ctlTest&firmEnab} MAR_ [rDrh, IOCBlabelErrMask+0], c1; rB_ vCStatusLastField, {used in err recovery} c2; rB_ MD or rB, {used in err recovery} c3; XWait: MAR _ [rDrh, IOCBcStatus+0], CANCELBR[$] c1; rC _ rC or vCStatusLblField, {used in err recovery} c2; rF_ MD, c3; acR _ U4000, c1; [] _ rF, NegBr, {Neg => still in Progress} c2; [] _ acR and rF, ZeroBr, BRANCH[$, XWait], c3; XDone: rB _ rB and rF, BRANCH[XOK, XErr], c1; XOK: pRet1, c2; RET[doXferGoodRet], c3; XErr: [] _ rB xor rC, ZeroBr, { 0 => label verify err } c2; BRANCH[XNotLblVer,XLblVer], c3; XLblVer: Noop, c1; pRet3, c2; RET[xferLblVerRet], c3; XNotLblVer: rB _ rB and vCStatusLastField, c1; rB _ rB xor vCStatusDataField, ZeroBr, {0=> data fld err} c2; BRANCH[XChkRetry,XAdjIOCB], c3; XAdjIOCB: MAR_ [rDrh, IOCBpageCount+0], c1; Noop, c2; rB_ MD, c3; MAR_ [rDrh, IOCBpageCount+0], c1; MDR_ rB+1, c2; Noop, c3; MAR_ [rDrh, IOCBdataPtrLo+0], c1; Noop, c2; rB_ MD, c3; MAR_ [rDrh, IOCBdataPtrLo+0], c1; MDR_ rB-1, c2; Noop, c3; XChkRetry: MAR_ [rDrh, IOCBtries+0], c1; Noop, c2; rB_ MD, c3; MAR_ [rDrh, IOCBtries+0], c1; MDR_ rB-1, ZeroBr, c2; BRANCH[XRetry, XHardErr], c3; XHardErr: acR_ 0B, GOTOABS[Maintenance2Loc], c1; {was bootDeviceError} {Uses data left in last header to compute pages left in cylinder, returns result in acR.} pagesLeftInCylinder: Noop, c3; MAR_ [rDrh, IOCBcHeader+1], c1; rB_ tiUnumHeads, 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-1, NegBr, c1; rB_ vSecsPerTrack, BRANCH[multiply, OffEnd], c2; OffEnd: acR_ 0, c3; {off the end of the cylinder} rE_ 0, c1; pRet1, GOTO[pgLft1], c2; {multiply, 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: Noop, c3; Q_ acR, c1; 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, c1; acR_ Q+vSecsPerTrack, pRet1, GOTO[pgLft1], c2; pgLft1: acR_ acR-rE, RET[PLCRet], c3; {This subroutine is used to transfer commands to the selected disk. Upon entry rB has the Bus value and rC has the Tag constant shifted right by 8. Subroutine must set the Bus in c1 and the Tag in c3 of click1. Then it must wait at least two clicks to reset the tag.} SetRst3: Noop, c3; SetRst1: KCmd _ rB LRot0, c1; rC _ rC LRot8, c2; KCmd _ (rB or rC) LRot0, c3; rC _ 10, {used in wait following tag reset} c1; Noop, c2; Noop, c3; {In c3 of click3 the tag is reset.} Noop, c1; Noop, c2; KCmd _ rB LRot0, c3; SRWait: CANCELBR[$], c1; rC _ rC - 1, ZeroBr, c2; BRANCH[$, SRWait], c3; pRet0, c1; RET[SetRst3Ret], c2; {L3BLT exists because there are too many calls on BLT} L3BLT2: Noop, c2; L3BLT3: Noop, c3; L3BLT: L0 _ 0, c1; CALL[BLT3], c2; Noop, c1, at[0, 10, subrRet]; pRet3, c2; RET[L3BLTRet], c3; {This subroutine performs: (rC^) _ (rC^) or (rD). Destroys acR} merge3: Noop, c3; merge1: MAR _ [rCrh, rC+0], c1; Noop, c2; acR _ MD, c3; MAR _ [rCrh, rC+0], c1; MDR _ acR or rD, pRet0, c2; RET[mergeRet], c3; (2048)\3264t1 1t0 368t1 1t0 261t1 1t0 4452t2 1t0 37t2 1t0 18t2 1t0 14t2 1t0 10t2 1t0 23t2 1t0 10t2 1t0 12t2 1t0 15t2 1t0 20t2 1t0 6837t2 12t0 59t2 13t0 46t2 6t0 2t2 10t0 8t2 12t0 11t2 8t0 33t2 8t0 11t2 4t0 33t2 79t0