{File name: [Idun]TridentInitial.mc 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: Dennis Grundler 1-Sep-84 22:24:03 Add copyright notice. Last edited by: Amy Fasnacht 7-Oct-83 11:59:00 Use IOPage references in Dandelion.dfn Murage 19-Sep-83 18:49:21 - fixed Germ request initialization to get correct location. Murage - 28-Jul-83 13:57:57 - remove addressing bug caused by growth of germ request-data address offset beyond byte size. Murage - 22-Jul-83 11:07:00 - Accomodate changes for Germ as a result of going over to 32-bit procedure descriptors. 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:} { Copyright (C) 1981, 1982, 1983 by Xerox Corporation. All rights reserved. } {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[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[germMapOffset, 2]; Set[germPageHigh, 0]; {virtual page number of origin of germ -- 1B} Set[germPageLow, 1]; Set[sFirstGermRequestLow, 001'b]; {start of germ request in SD - high byte} Set[sFirstGermRequestLow, 240'b]; {start of germ request in SD - low byte} 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.devOrd, Add[sFirstGermRequestLow, 03'b]]; 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} {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 ¬ IOPageHigh, c3; rC ¬ IOPage, L3¬ 1, c1; {CSB address} 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, c3, at[1, 10, SetRst3Ret]; {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; {hard microcode (quick exit), pick up diagnostic table entry from first page of boot file} 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: {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; 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; Noop, c1, at[3, 10, L3BLTRet]; Noop, 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; 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¬ bootDeviceError, GOTOABS[Maintenance2Loc], c1, at[2, 10, xferLblVerRet]; 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¬ nextPage, L3¬ 3, c3; CALL[doVvr2], c1; 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: 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; MAR¬ [rDrh, IOCBdataPtrLo+0], c1; MDR¬ rF, 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¬ bootDeviceError, GOTOABS[Maintenance2Loc], c1; {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