*----------------------------------------------------------- Title[DiskBootTransfer.mc...June 29, 1982 1:41 PM...Taft]; * Simple disk driver for transfers between Pilot boot files and memory, * using the PilotDisk microcode. *----------------------------------------------------------- * Microcode and germ files are kept in Pilot boot files. * These are standard Pilot files, with the addition that wherever there * is a break in the run of pages, the bootChainLink of the last page * of the run points to the first page of the next run. Additionally, * the file ends with a bootChainLink of [-1, -1]. Set[XTask, IP[EMU]]; KnowRBase[AEmRegs]; *----------------------------------------------------------- BootTransfer: * Transfer page(s) to or from disk boot file * Enter: IOCB points to I/O command block, which must be at an odd address * and have the following fields already set up as desired: * drive, pageCount, command, diskAddress, dataPtr, diskLabel * The remainder of the IOCB must be zeroed. * Call by SCall[BootTransfer] * Returns +1: unrecoverable error occurred * +2: transfer completed successfully: * if IOCB.count = 0 then all pages have been transferred. * if #0, end-of-file was reached before the end of the transfer. * The command block is updated in the standard manner by the disk microcode; * specifically, the diskAddress and diskLabel.filePageLo are updated * to describe the first page not (successfully) transferred, as is * the dataPtr if incrementDataPtr was specified in the command. * If the label was checked, the diskLabel.bootChainLink contains the * corresponding data from the last label successfully checked. * Clobbers T, Q, BTemp0, BTemp1 *----------------------------------------------------------- Subroutine; T← (IOCB)+(IOCB.headerPtr); BTemp0← T-(Sub[IOCB.headerPtr!, IOCB.diskHeader!]C); Store← T, DBuf← BTemp0; * iocb.headerPtr ← @iocb.diskHeader T← (IOCB)+(IOCB.labelPtr); BTemp0← T+(Sub[IOCB.diskLabel!, IOCB.labelPtr!]C); Store← T, DBuf← BTemp0; * iocb.labelPtr ← @iocb.diskLabel BTemp1← 17C; * Max number of retries * BootTransfer (cont'd) BootTransferLp: T← IOCB, RBase← RBase[RTC430]; EventTemp1← T← (Store← T)+1, DBuf← 0C; * iocb.next ← 0 EventTemp0← (Store← T)-1, DBuf← IOCBSealValue; * iocb.seal ← IOCBSealValue Fetch← EventTemp1, T← CSB.next; * MD← 0 for first iteration of wait loop PD← Store← T, DBuf← EventTemp0; * csb.next ← iocb -- start the command. * ALU<0 for first iteration of wait loop * Wait up to 2 seconds for the command to execute (sufficient time for transferring * ~3500 pages, minus time lost to seeks). T← (RTC430)+1, FreezeBC; * Now + 65536 32-us ticks = ~ 2 seconds Fetch← EventTemp1, PD← MD, * Wait for iocb.seal to become zero Branch[BootTransferTimeout, ALU>=0]; PD← (RTC430)-T-1, Branch[.-1, ALU#0]; RBase← RBase[AEmRegs]; * Command finished. iocb.pageCount=0 means completed OK, #0 means an error occurred T← (IOCB)+(IOCB.pageCount); T← (Fetch← T)+(Sub[IOCB.labelStatus!, IOCB.pageCount!]C); * Carry← 0 Fetch← T, PD← MD; BTemp0← A0, Branch[BootTransferDone, ALU=0]; * Error occurred. See if it was a label check error. T← DPF[BTemp0, 2, 4, MD]; * Mask out readOnly and cylOffset from status PD← T XOR (DS.checkErr); * Label check error and no others? T← (IOCB)+(Add[IOCB.diskLabel!, Lab.bootChainLink!]C), Branch[BootOtherError, ALU#0]; * Label check error. If the bootChainLink of the last successfully-read label * is nonzero, it is the disk address of a new run of pages (-1 => end of file). T← (Fetch← T)+1; T← (Fetch← T)-1, BTemp0← MD, Q← MD; PD← (BTemp0) OR MD; BTemp0← (BTemp0)+1, Branch[BootLabelError, ALU=0]; * Start new run of pages; and zero the bootChainLink so that if it was wrong * the ensuing label check error won't cause us to come back here. * iocb.diskAddress ← iocb.diskLabel.bootChainLink; iocb.diskLabel.bootChainLink ← [0, 0] T← (Store← T)+1, DBuf← 0C, Branch[BootEOF, ALU=0]; * Carry← 0 Store← T, DBuf← 0C; T← (IOCB)+(IOCB.diskAddress); T← (Store← T)+1, DBuf← Q, BTemp0← MD; Store← T, DBuf← BTemp0, Branch[BootTransferLp]; * Other error, retry. BootOtherError: PD← (BTemp1) AND (7C), Branch[BootDiskError, R<0]; BTemp1← (BTemp1)-1, Branch[BootTransferLp, ALU#0]; T← CSB.cylinder; * Every 8 retries, do a restore Store← T, DBuf← -1C, Branch[BootTransferLp]; BootTransferTimeout: RBase← RBase[AEmRegs]; * Timed out (disk probably not on-line) BootDiskError: BTemp0← T-T, Branch[BootEOF]; * Too many retries; Carry← 1 BootLabelError: BTemp0← T-T, Branch[BootEOF]; * Label error not due to hitting end of run * On exit, failure is indicated by carry=1, success by carry=0. * BTemp0 = 0; T = @CSB.next (or pointer to some place that's harmless to store 0 into). BootEOF: T← CSB.next; BootTransferDone: Store← T, DBuf← BTemp0, * Zap command chain Return[Carry']; * Return +1 if carry=1, +2 if carry=0