(FILECREATED "17-Oct-84 23:02:36" {ERIS}<LISPCORE>SOURCES>DISKDLION.;17 35819  

      changes to:  (RECORDS IOCBPAGE)

      previous date: " 1-Oct-84 15:19:06" {ERIS}<LISPCORE>SOURCES>DISKDLION.;16)


(* Copyright (c) 1984 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT DISKDLIONCOMS)

(RPAQQ DISKDLIONCOMS ((VARS DDFNS)
	(FNS \DL.DISKINIT \DL.RECALIBRATE \DL.SHUGART.XFERDISK \DL.TRANSFERPAGE \DL.TRI.INITIATE.IO 
	     \DL.TRI.XFERDISK \DL.ACTONVMEMFILE \DL.ACTONVMEMPAGE \DL.DISKSEEK \DL.XFERDISK 
	     \DL.DISKOP \D2V \V2CYL \DEBUGIOCB)
	(FNS INITDLIONDISK \CYLBOUNDCROSSP)
	(MACROS \DLDISK.GETSTATUS)
	(DECLARE: EVAL@COMPILE DONTCOPY (FILES (LOADCOMP)
					       LLFAULT)
		  (GLOBALVARS SEC/HD SEC/CYL HD/DRV \DISKTYPE \CONTROLLERTYPE))
	(DECLARE: DONTCOPY (RECORDS DLDISK.STATUS IOCBPAGE TRIDENTDCB TRIDENTIOCB)
		  (CONSTANTS \DL.ABORT-NR/WF/OVR \DL.ABORT-NR/WF/OVR/CRC 
			     \DL.ABORT-NR/WF/OVR/CRC/VERIFY \DL.READFIELD \DL.SEEKIOCBSTART 
			     \DL.VERIFYFIELD \DL.WRITEFIELD \DL.XFERIOCBSTART \DL.MINUSSTEP 
			     \DL.PLUSSTEP)
		  (CONSTANTS \TH.DR.COMMAND \TH.DR.CONTROL \TH.DR.ERRORMASK \TH.DR.OP \TH.DW.COMMAND 
			     \TH.DW.CONTROL \TH.DW.ERRORMASK \TH.DW.OP \TH.LN.COMMAND \TH.LN.CONTROL 
			     \TH.LN.ERRORMASK \TH.LN.OP \TH.LR.COMMAND \TH.LR.CONTROL 
			     \TH.LR.ERRORMASK \TH.LR.OP \TH.LV.COMMAND \TH.LV.CONTROL 
			     \TH.LV.ERRORMASK \TH.LV.OP \TH.LW.COMMAND \TH.LW.CONTROL 
			     \TH.LW.ERRORMASK \TH.LW.OP \TH.WW.CONTROL \DL.TRI.STARTCMD 
			     \TH.SEEK.HDCMD \TH.SEEK.CYLCMD)
		  (CONSTANTS \TH.HV.COMMAND \TH.HV.CONTROL \TH.HV.ERRORMASK \TH.HV.OP 
			     \DL.TRI.PASSWORD)
		  (CONSTANTS \TH.DOCTL.RESETDEVICECHECK \TH.DOCTL.SETHD5 \TH.NULLCTL.RESETDEVICECHECK 
			     \TH.NULLCTL.SETHD5))
	(DECLARE: DONTEVAL@LOAD DOCOPY (P (INITDLIONDISK)))))

(RPAQQ DDFNS (\DL.DISKINIT \DL.ACTONVMEMFILE \DL.ACTONVMEMPAGE \DL.DISKSEEK \DL.XFERDISK \DL.DISKOP 
			   \D2V \V2CYL \DL.RECALIBRATE \DL.SHUGART.XFERDISK \DL.SHUGARTINIT 
			   \DL.TRIDENTINIT \DL.TRI.INITIATE.IO \DL.TRI.XFERDISK \DEBUGIOCB 
			   \PvTransferPageNoSwap))
(DEFINEQ

(\DL.DISKINIT
  [LAMBDA NIL                                                (* mpl "29-Jul-84 15:26")

          (* * Determine controller type by looking on IOcB page for the password. yes, I know this is crude, but until I fix 
	  both initials, it'll have to do.)


    (COND
      [(EQ \DL.TRI.PASSWORD (fetch (TRIDENTIOCB TH.HEADER.OP) OF \IOCBPAGE))

          (* * If the password matches, we have a Trident (or SMD) disk. Try to figure out which disk it is)


	(SETQQ \CONTROLLERTYPE \TRIDENT)

          (* * Look at some remnants of trident initial to see if we're on a t80 / t300)


	(COND
	  ((NEQ 19 (FETCH (TRIDENTIOCB TH.HDSFROMINITIAL) OF \IOCBPAGE))
	    (SETQ SEC/HD 30)
	    (SETQ HD/DRV 5)
	    (SETQ SEC/CYL 150)
	    (SETQQ \DISKTYPE \T80))
	  (T (SETQ SEC/HD 30)
	     (SETQ HD/DRV 19)
	     (SETQ SEC/CYL 570)
	     (SETQQ \DISKTYPE \T300]
      (T 

          (* * Determines disk shape. \DEVICE.INPUT 3 is the KStatus register, \DEVICE.INPUT 6 is the KTest register.
	  WARNING: Both of these registers read as their complements!)


	 (SETQQ \CONTROLLERTYPE \SHUGART)

          (* * An SA4000 is easy. The SA4000 bit is set inb KStatus)


	 (COND
	   ((NEQ 0 (LOGAND 32 (\DEVICE.INPUT 3)))
	     (SETQQ \DISKTYPE \SA4000)
	     (SETQ SEC/HD 28)
	     (SETQ HD/DRV 8)
	     (SETQ SEC/CYL 224))
	   (T 

          (* * Turn on HeadSelect16 in KCtl, which is tied to Sector' for Q2080s)


	      (\DEVICE.OUTPUT 32768 3)
	      (COND
		((EQ 0 (LOGAND 64 (\DEVICE.INPUT 6)))

          (* * KStatus.notsector was low when we set HeadSelect16 high, so must be the old shugart SA1000)


		  (SETQQ \DISKTYPE \SA1000)
		  (SETQ SEC/HD 16)
		  (SETQ HD/DRV 4)
		  (SETQ SEC/CYL 64))
		(T 

          (* * Ktest.Sector' is false, so it must be a regular quantum. If it was a Q2080, bringing HS16 up would have brought
	  Sector up too)



          (* * Turn off the head select bit and see of Ktest.sector' changed)


		   (\DEVICE.OUTPUT 0 3)
		   (COND
		     ((NEQ 0 (LOGAND 64 (\DEVICE.INPUT 6)))

          (* * KStatus.notsector did not change. Must be a Q2040 with NotSector tied high)


		       (SETQQ \DISKTYPE \Q2040)
		       (SETQ SEC/HD 16)
		       (SETQ HD/DRV 8)
		       (SETQ SEC/CYL 128))
		     (T 

          (* * KStatus.notsector did change, so must be Q2080 with NotSector tied to HeadSelect16)


			(SETQQ \DISKTYPE \Q2080)
			(SETQ SEC/HD 16)
			(SETQ HD/DRV 7)
			(SETQ SEC/CYL 112])

(\DL.RECALIBRATE
  [LAMBDA NIL                                                (* mpl "28-May-84 09:32")
                                                             (* This function is used in the unlikely event that the
							     disk drive fails to seek correctly.
							     It will find track 0)
    (PROG ((PUNTCOUNTER 512))
          (while (NOT (fetch (DLDISK.STATUS TRACK00) of (\DLDISK.GETSTATUS)))
	     do (COND
		  ((ZEROP (SETQ PUNTCOUNTER (SUB1 PUNTCOUNTER)))
		    (RAID "Could not recalibrate drive")))
		(with IOCBPAGE \IOCBPAGE (SETQ SSEEKCMD1 (LOGOR 128 \DL.MINUSSTEP))
		      (SETQ SSEEKCMD2 \DL.MINUSSTEP)
		      (SETQ SCYLINDERDISPLACEMENT (\LOLOC -1)))
		(\DL.DISKOP \DL.SEEKIOCBSTART)
		(replace (IOCBPAGE HCYLINDER) of \IOCBPAGE with 0])

(\DL.SHUGART.XFERDISK
  [LAMBDA (CYL HD SEC BUFFER MODE LABEL RUNLENGTH NORAIDFLG)
                                                             (* hts: " 1-Oct-84 15:18")

          (* This is the new improved \DL.XFERDISK, capable of working with labels and retaining the same arguments the old 
	  one, but adding a few more: NORAIDFLG LABEL, MODE, If USERFLG is T, errors will be returned, or else RAID is called.
	  LABEL points to a LABEL record, Mode supplants WRITEFLG and can be VRR, VVR, VVW, or VWW.)


    (PROG ((RetryCount 10)
	   Status USERFLG (FLG NIL)
	   HeadAndSector)                                    (* Check for out of bounds triples and normalize)
          (SETQ HD (IPLUS HD (IQUOTIENT SEC SEC/HD)))
          (SETQ SEC (IMOD SEC SEC/HD))
          (SETQ CYL (IPLUS CYL (IQUOTIENT HD HD/DRV)))
          (SETQ HD (IMOD HD HD/DRV))
          (SETQ HeadAndSector (LOGOR (LLSH HD 8)
				     SEC))                   (* First thing to do is seek the new track)
      RETRY
          (\DL.DISKSEEK CYL)
      LP                                                     (* Compute and fill in the head and sector information 
							     for the IOCB's header field)
          (replace (IOCBPAGE HHEAD) of \IOCBPAGE with HD)
          (replace (IOCBPAGE HSECTOR) of \IOCBPAGE with SEC)
                                                             (* We can do variable length runs now, but these runs 
							     MUST be in contiguous pages of virtual memory.
							     Beware!)
          (replace (IOCBPAGE PRUNLENGTH) of \IOCBPAGE with (COND
							     (RUNLENGTH RUNLENGTH)
							     (T 1)))
                                                             (* If MODE not supplied, use value of WRITEFLG and set 
							     it.)
                                                             (* Now that we know what we're doing, dispatch on the 
							     mode and set up the rest of the parameters)
          (SELECTQ MODE
		   ((NIL VRR)
		     (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 12)
			   (SETQ PLABELCMD \DL.READFIELD)
			   (SETQ PLABELABORT \DL.ABORT-NR/WF/OVR/CRC)
			   (SETQ PDATACMD \DL.READFIELD)
			   (SETQ PDATALEN (LOGOR 256 32768))
			   (SETQ PDATAABORT \DL.ABORT-NR/WF/OVR/CRC)))
		   (VVR (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 11)
			      (SETQ PLABELCMD \DL.VERIFYFIELD)
			      (SETQ PLABELABORT \DL.ABORT-NR/WF/OVR/CRC/VERIFY)
			      (SETQ PDATACMD \DL.READFIELD)
			      (SETQ PDATALEN (LOGOR 256 32768))
			      (SETQ PDATAABORT \DL.ABORT-NR/WF/OVR/CRC)))
		   (VWW (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 12)
			      (SETQ PLABELCMD \DL.WRITEFIELD)
			      (SETQ PLABELABORT \DL.ABORT-NR/WF/OVR)
			      (SETQ PDATACMD \DL.WRITEFIELD)
			      (SETQ PDATALEN (LOGOR 256 32768))
			      (SETQ PDATAABORT \DL.ABORT-NR/WF/OVR)))
		   (VVW (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 11)
			      (SETQ PLABELCMD \DL.VERIFYFIELD)
			      (SETQ PLABELABORT \DL.ABORT-NR/WF/OVR/CRC/VERIFY)
			      (SETQ PDATACMD \DL.WRITEFIELD)
			      (SETQ PDATALEN (LOGOR 256 32768))
			      (SETQ PDATAABORT \DL.ABORT-NR/WF/OVR/CRC)))
		   ((T VRW)
		     (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 12)
			   (SETQ PLABELCMD \DL.READFIELD)
			   (SETQ PLABELABORT \DL.ABORT-NR/WF/OVR/CRC)
			   (SETQ PDATACMD \DL.WRITEFIELD)
			   (SETQ PDATALEN (LOGOR 256 32768))
			   (SETQ PDATAABORT \DL.ABORT-NR/WF/OVR)))
		   (PROGN (RAID "Invalid MODE for \DL.XFERDISK")))
                                                             (* Fill in the virtual page field)
          (replace (IOCBPAGE PVPAGE) of \IOCBPAGE with (SUB1 (fetch (POINTER PAGE#) of BUFFER)))
                                                             (* More important bit twiddling gibberish that I don't 
							     understand yet)
          (replace (IOCBPAGE PTERMCOND1) of \IOCBPAGE with (LOGOR (LOGAND (fetch (IOCBPAGE PTERMCOND1)
									     of \IOCBPAGE)
									  2047)
								  (LLSH (LOGAND HeadAndSector 65280)
									3)))
          (replace (IOCBPAGE PTERMCOND2) of \IOCBPAGE with (LOGOR (LOGAND (fetch (IOCBPAGE PTERMCOND2)
									     of \IOCBPAGE)
									  2047)
								  (LLSH (LOGAND HeadAndSector 65280)
									3)))
                                                             (* If we were given a label, we better put it on the 
							     IOCB page)
          (COND
	    ((AND LABEL (NEQ MODE (QUOTE VRR))
		  (NEQ MODE (QUOTE VRW)))
	      (\BLT (LOCF (fetch (IOCBPAGE LID) of \IOCBPAGE))
		    LABEL 10)))                              (* Finally, the moment has come..
							     Wake up the microcode)
          (SETQ Status (\DL.DISKOP \DL.XFERIOCBSTART))       (* For now, verify errors OK in the swapper)
          (with IOCBPAGE \IOCBPAGE (SETQ PLABELLEN 12)
		(SETQ PLABELCMD \DL.READFIELD)
		(SETQ PLABELABORT \DL.ABORT-NR/WF/OVR/CRC)
		(SETQ PDATACMD \DL.READFIELD)
		(SETQ PDATALEN (LOGOR 256 32768))
		(SETQ PDATAABORT \DL.ABORT-NR/WF/OVR/CRC))

          (* * If no error but verify error, then we can go about returning; otherwise, go on and try reading again.)


          (if (ZEROP (LOGAND Status 62))
	      then 

          (* * See if we have to return a label and do so if need be.)


		   (if [AND LABEL (MEMB MODE (QUOTE (VRR VRW T]
		       then (\BLT LABEL (LOCF (fetch (IOCBPAGE LID) of \IOCBPAGE))
				  10))

          (* * If there is a verify error, return the Status (which should be 1), else return T)


		   (RETURN (if (fetch (DLDISK.STATUS VERIFYERR) of Status)
			       then Status
			     else T)))
          (SETQ RetryCount (SUB1 RetryCount))
          (COND
	    ((ZEROP RetryCount)                              (* We have already recalibrated and tried ten more 
							     times and failed, so we're really stuck)
	      (COND
		[FLG (COND
		       (NORAIDFLG (RETURN Status))
		       (T (RAID "Hard disk error" Status]
		(T (RETURN Status)))                         (* Who knows? We might be lost.
							     Recalibrate and try again)
	      (\DL.RECALIBRATE)
	      (SETQ FLG T)
	      (GO RETRY))
	    (T (GO LP])

(\DL.TRANSFERPAGE
  [LAMBDA (DA BUFFER MODE LABEL RUNLENGTH NORAIDFLG)         (* mpl "26-Jun-84 23:26")
                                                             (* Same args as old \DL.XFERDISK but allows fixps as 
							     DAs)
    (\DL.XFERDISK (IQUOTIENT DA SEC/CYL)
		  (IQUOTIENT (IMOD DA SEC/CYL)
			     SEC/HD)
		  (IMOD (IMOD DA SEC/CYL)
			SEC/HD)
		  BUFFER MODE LABEL RUNLENGTH NORAIDFLG])

(\DL.TRI.INITIATE.IO
  [LAMBDA NIL                                                (* mpl " 2-Jul-84 08:47")
                                                             (* This function starts the microcode for the Trident 
							     disk)
                                                             (* Send wakeup to KCMD, register 13)
    (\DEVICE.OUTPUT \DL.TRI.STARTCMD 13)
    (until (ZEROP (LOGAND (fetch (TRIDENTIOCB TH.CONTROLLERSTATUS) of \IOCBPAGE)
			  32768)))
    (fetch (TRIDENTIOCB TH.CONTROLLERSTATUS) of \IOCBPAGE])

(\DL.TRI.XFERDISK
  [LAMBDA (CYL HD SEC BUFFER MODE LABEL RUNLENGTH NORAIDFLG)
                                                             (* hts: "27-Sep-84 11:57")

          (* This is \DL.TRI.XFERDISK, the lowest level driver for DLion Trident disks, capable of working with labels and 
	  retaining the same arguments the old one, but adding a few more: NORAIDFLG LABEL, MODE, If USERFLG is T, errors will
	  be returned, or else RAID is called. LABEL points to a LABEL record, Mode supplants WRITEFLG and can be VRR, VVR, 
	  VVW, or VWW.)


    (PROG ((RetryCount 10)
	   Status USERFLG (FLG NIL)
	   (Drive 0)
	   DriveMask)                                        (* Check for out of bounds triples and normalize)
          [SETQ DriveMask (LLSH 1 (IPLUS 8 (IDIFFERENCE 3 Drive]
          (SETQ HD (IPLUS HD (IQUOTIENT SEC SEC/HD)))
          (SETQ SEC (IMOD SEC SEC/HD))
          (SETQ CYL (IPLUS CYL (IQUOTIENT HD HD/DRV)))
          (SETQ HD (IMOD HD HD/DRV))                         (* no recal first time)
          (replace (TRIDENTDCB RECALIBRATE) of \IOPAGE with NIL)
      LP                                                     (* Compute and fill in the head and sector information 
							     for the IOCB's header field)
          [with TRIDENTIOCB \IOCBPAGE (SETQ TH.CYL CYL)
		(SETQ TH.HD HD)
		(SETQ TH.SEC SEC)
		(SETQ TH.CONTROLLERSTATUS 49152)
		(SETQ TH.DISKSTATUS 0)
		(SETQ TH.MICRONEXT 0)
		(SETQ TH.DCBOFFSET 0)
		[SETQ TH.LABELPTRLO (LOGAND 65280 (\LOLOC (LOCF (fetch (TRIDENTIOCB TH.READLABEL)
								   of \IOPAGE]
		(SETQ TH.LABELPTRHI (\HILOC (LOCF (fetch (TRIDENTIOCB TH.READLABEL) of \IOPAGE]
                                                             (* Copy client header to uCode header)
          (with TRIDENTIOCB \IOCBPAGE (SETQ TH.uCYL TH.CYL)
		(SETQ TH.uSEC TH.SEC)
		(SETQ TH.uHD TH.HD))                         (* Set up the SEEK portion of the IOCB)
          (with TRIDENTIOCB \IOCBPAGE (SETQ TH.SEEK.XFERMASK 0)
		(SETQ TH.SEEK.KDRIVE 63488)
		(SETQ TH.SEEK.KCYL (LOGOR \TH.SEEK.CYLCMD CYL))
		(SETQ TH.SEEK.KHEAD (LOGOR \TH.SEEK.HDCMD HD)))
                                                             (* Set up the HEADER portion of the IOCB)
          (with TRIDENTIOCB \IOCBPAGE (SETQ TH.HEADER.COMMAND \TH.HV.COMMAND)
		(SETQ TH.HEADER.CONTROL \TH.HV.CONTROL)
		(SETQ TH.HEADER.OP \TH.HV.OP)
		(SETQ TH.HEADER.ERRORMASK \TH.HV.ERRORMASK))
                                                             (* We can do variable length runs now, but these runs 
							     MUST be in contiguous pages of virtual memory.
							     Beware!)
          (replace (TRIDENTIOCB TH.PAGECOUNT) of \IOCBPAGE with (COND
								  (RUNLENGTH RUNLENGTH)
								  (T 1)))
                                                             (* Now that we know what we're doing, dispatch on the 
							     mode and set up the rest of the parameters)
          (SELECTQ MODE
		   ((NIL VRR)
		     (with TRIDENTIOCB \IOCBPAGE (SETQ TH.LABEL.OP \TH.LR.OP)
			   (SETQ TH.LABEL.ERRORMASK \TH.LR.ERRORMASK)
			   (SETQ TH.LABEL.CONTROL (LOGOR \TH.LR.CONTROL DriveMask))
			   (SETQ TH.LABEL.COMMAND \TH.LR.COMMAND)
			   (SETQ TH.DATA.OP \TH.DR.OP)
			   (SETQ TH.DATA.ERRORMASK \TH.DR.ERRORMASK)
			   (SETQ TH.DATA.CONTROL (LOGOR \TH.DR.CONTROL DriveMask))
			   (SETQ TH.DATA.COMMAND \TH.DR.COMMAND)))
		   (VVR (with TRIDENTIOCB \IOCBPAGE (SETQ TH.LABEL.OP \TH.LV.OP)
			      (SETQ TH.LABEL.ERRORMASK \TH.LV.ERRORMASK)
			      (SETQ TH.LABEL.CONTROL (LOGOR \TH.LV.CONTROL DriveMask))
			      (SETQ TH.LABEL.COMMAND \TH.LV.COMMAND)
			      (SETQ TH.DATA.OP \TH.DR.OP)
			      (SETQ TH.DATA.ERRORMASK \TH.DR.ERRORMASK)
			      (SETQ TH.DATA.CONTROL (LOGOR \TH.DR.CONTROL DriveMask))
			      (SETQ TH.DATA.COMMAND \TH.DR.COMMAND)))
		   (VWW (with TRIDENTIOCB \IOCBPAGE (SETQ TH.LABEL.OP \TH.LW.OP)
			      (SETQ TH.LABEL.ERRORMASK \TH.LW.ERRORMASK)
			      (SETQ TH.LABEL.CONTROL (LOGOR \TH.LW.CONTROL DriveMask))
			      (SETQ TH.LABEL.COMMAND \TH.LW.COMMAND)
			      (SETQ TH.DATA.OP \TH.DW.OP)
			      (SETQ TH.DATA.ERRORMASK \TH.DW.ERRORMASK)
			      (SETQ TH.DATA.CONTROL (LOGOR \TH.WW.CONTROL DriveMask))
			      (SETQ TH.DATA.COMMAND \TH.DW.COMMAND)))
		   (VVW (with TRIDENTIOCB \IOCBPAGE (SETQ TH.LABEL.OP \TH.LV.OP)
			      (SETQ TH.LABEL.ERRORMASK \TH.LV.ERRORMASK)
			      (SETQ TH.LABEL.CONTROL (LOGOR \TH.LV.CONTROL DriveMask))
			      (SETQ TH.DATA.OP \TH.DW.OP)
			      (SETQ TH.DATA.ERRORMASK \TH.DW.ERRORMASK)
			      (SETQ TH.DATA.CONTROL (LOGOR \TH.DW.CONTROL DriveMask))
			      (SETQ TH.DATA.COMMAND \TH.DW.COMMAND)))
		   ((T VRW)
		     (with TRIDENTIOCB \IOCBPAGE (SETQ TH.LABEL.OP \TH.LR.OP)
			   (SETQ TH.LABEL.ERRORMASK \TH.LR.ERRORMASK)
			   (SETQ TH.LABEL.CONTROL (LOGOR \TH.LR.CONTROL DriveMask))
			   (SETQ TH.LABEL.COMMAND \TH.LR.COMMAND)
			   (SETQ TH.DATA.OP \TH.DW.OP)
			   (SETQ TH.DATA.ERRORMASK \TH.DW.ERRORMASK)
			   (SETQ TH.DATA.CONTROL (LOGOR \TH.DW.CONTROL DriveMask))
			   (SETQ TH.DATA.COMMAND \TH.DW.COMMAND)))
		   (PROGN (RAID "Invalid MODE for \DL.TRI.XFERDISK")))
                                                             (* Fill in the virtual page field)
          (replace (TRIDENTIOCB TH.DATAPTRHI) of \IOCBPAGE with (\HILOC BUFFER))
          (replace (TRIDENTIOCB TH.DATAPTRLO) of \IOCBPAGE with (\LOLOC BUFFER))
                                                             (* If we were given a label, we better put it on the 
							     IOCB page)
          (COND
	    ((AND LABEL (NEQ MODE (QUOTE VRR))
		  (NEQ MODE (QUOTE VRW)))
	      (\BLT (LOCF (fetch (TRIDENTIOCB TH.WRITEVERIFYLABEL) of \IOCBPAGE))
		    LABEL 10)))                              (* why the hell does the uCode need this???)
          (replace (TRIDENTIOCB TH.FILEPAGELO) of \IOCBPAGE with (\GETBASE
								   (LOCF (fetch (TRIDENTIOCB 
										     TH.READLABEL)
									    of \IOCBPAGE))
								   5))
                                                             (* Finally, the moment has come..
							     Wake up the microcode)
                                                             (* The constant here removes uninteresting bits from 
							     the status)
          (replace (TRIDENTDCB MICRONEXT) of \IOPAGE with (\LOLOC \IOCBPAGE))
          (SETQ Status (LOGAND 56888 (\DL.TRI.INITIATE.IO)))

          (* * If we need to return a label, copy it out of the iocb page)


          (if [AND LABEL (MEMB MODE (QUOTE (VRR VRW T]
	      then (\BLT LABEL (LOCF (fetch (TRIDENTIOCB TH.READLABEL) of \IOCBPAGE))
			 10))                                (* only recal once)
          (replace (TRIDENTDCB RECALIBRATE) of \IOPAGE with NIL)
                                                             (* Trident controller indicates good completion in bit 
							     2 from left of controller status)
          (COND
	    ((NOT (ZEROP (LOGAND 16384 Status)))             (* Convert status to be same as for shugart status)
	      (RETURN T)))
          (SETQ RetryCount (SUB1 RetryCount))
          (COND
	    ((ZEROP RetryCount)                              (* We have already recalibrated and tried ten more 
							     times and failed, so we're really stuck)
	      (COND
		[FLG (COND
		       (NORAIDFLG (RETURN Status))
		       (T (RAID "Hard disk error" Status]
		(T [SETQ Status (LOGOR (COND
					 ((NOT (ZEROP (LOGAND Status 2048)))
					   1))
				       (COND
					 ((NOT (ZEROP (LOGAND Status 1024)))
					   2))
				       (COND
					 ((NOT (ZEROP (LOGAND Status 512)))
					   4]
		   (RETURN Status)))                         (* Who knows? We might be lost.
							     Recalibrate and try again)
	      (replace (TRIDENTDCB RECALIBRATE) of \IOPAGE with T)
	      (SETQ FLG T)
	      (GO LP))
	    (T (GO LP])

(\DL.ACTONVMEMFILE
  [LAMBDA (FILEPAGE BUFFER NPAGES WRITEFLAG)                 (* bvm: " 4-APR-83 12:58")
    (DECLARE (GLOBALVARS \FPTOVP))
    (FRPTQ NPAGES (\DL.ACTONVMEMPAGE (COND
				       (\FPTOVP              (* New way, page is in boot file)
                                                             (* Pilot page is zero-based, vmem page is one-base)
						(SUB1 FILEPAGE))
				       (T                    (* Old way, page is in sysout after initial core image)
					  (IPLUS 3069 FILEPAGE)))
				     BUFFER WRITEFLAG)

          (* the simple IPLUS here is actually converting from sysout file page number into a raw disk address.
	  Obviously, this will have to change, since it assumes, e.g., no bad pages in this region of the disk)


	   (SETQ BUFFER (\ADDBASE BUFFER WORDSPERPAGE))
	   (add FILEPAGE 1])

(\DL.ACTONVMEMPAGE
  [LAMBDA (FILEPAGE BUFFER WRITEFLAG)                        (* mpl "20-Jun-84 14:07")

          (* This fn brings in a page of the VMEM file. It scans over the bad page table, which contains a loose mapping of 
	  logical pages to physical pages.)



          (* I is the max number of entries in the table. It has been changed to 37 from 42 to eliminate contention with the 
	  floppy IOCB)


    (PROG ((LINKBASE (ADDBASE \IOCBPAGE 127))
	   (I 37))
      LP  [COND
	    ((OR (IGREATERP (\GETBASE LINKBASE 3)
			    FILEPAGE)
		 (EQ 0 (\GETBASE LINKBASE 3)))
	      (RETURN (\DL.XFERDISK (\GETBASE LINKBASE 1)
				    (LRSH (\GETBASE LINKBASE 2)
					  8)
				    (IPLUS (IDIFFERENCE FILEPAGE (\GETBASE LINKBASE 0))
					   (LOGAND (\GETBASE LINKBASE 2)
						   255))
				    BUFFER WRITEFLAG]
          (SETQ LINKBASE (\ADDBASE LINKBASE 3))
          (COND
	    ((EQ 0 I)
	      (RAID)
	      (RETURN)))
          (SETQ I (SUB1 I))
          (GO LP])

(\DL.DISKSEEK
  [LAMBDA (Cylinder)                                         (* mpl "27-May-84 17:51")

          (* Set DISPlacement to the difference between where we want to be and where we are. Negative DISP means step OUT in 
	  the positive direction)


    (PROG [MicrocodeSeekCommand (Displacement (IDIFFERENCE Cylinder (fetch (IOCBPAGE HCYLINDER)
								       of \IOCBPAGE]
                                                             (* Don't try to move zero cylinders)
          (COND
	    ((ZEROP Displacement)
	      (RETURN 0)))

          (* This magic constant is used by the microcode to form the step command. \DL.MINUSSTEP is the reverse step and 
	  \DL.PLUSSTEP is the forward step. You need this constant twice, but the second time it has a 128 OR'd into it.
	  as part of the step command microcode)


          (SETQ MicrocodeSeekCommand \DL.PLUSSTEP)

          (* The microcode always expects to see a negative number for the displacement, since it counts up to zero from it.
	  Thus, we have to make it negative if we are stepping to a cylinder that is farther out than we are now.)


          (COND
	    ((IGREATERP 0 Displacement)
	      (SETQ Displacement (IMINUS Displacement)))
	    (T (SETQ MicrocodeSeekCommand \DL.MINUSSTEP)))   (* Deposit the seek commands onto the IOCB Page)
          (replace (IOCBPAGE SSEEKCMD2) of \IOCBPAGE with MicrocodeSeekCommand)
          (replace (IOCBPAGE SSEEKCMD1) of \IOCBPAGE with (LOGOR MicrocodeSeekCommand 128))
                                                             (* Place the displacement value onto the IOCB Page)
          (replace (IOCBPAGE SCYLINDERDISPLACEMENT) of \IOCBPAGE with (ADD1 (LOGXOR Displacement 
										    65535)))
                                                             (* Finally, we should update the header record to 
							     indicate our new position)
          (replace (IOCBPAGE HCYLINDER) of \IOCBPAGE with Cylinder)

          (* ... and wake up the microcode to get things rolling! Note: the 338 below is another DLion magic number, and it 
	  refers to the distance into the I/O page + 256 where the beginning of the microprogram for the disk microcode is.
	  This is the beginning of the SEEK iocb. It is also used in \DL.RECALIBRATE, and the TRANSFER iocb is used in 
	  \DL.XFERDISK)


          (RETURN (\DL.DISKOP \DL.SEEKIOCBSTART])

(\DL.XFERDISK
  [LAMBDA (CYL HD SEC BUFFER MODE LABEL RUNLENGTH NORAIDFLG)
                                                             (* mpl " 2-Jul-84 20:14")
    (COND
      ((EQ \CONTROLLERTYPE (QUOTE \TRIDENT))                 (* We're using a trident)
	(\DL.TRI.XFERDISK CYL HD SEC BUFFER MODE LABEL RUNLENGTH NORAIDFLG))
      (T                                                     (* we're using a shugart)
	 (\DL.SHUGART.XFERDISK CYL HD SEC BUFFER MODE LABEL RUNLENGTH NORAIDFLG])

(\DL.DISKOP
  [LAMBDA (IOCB)                                             (* mpl "30-Jun-84 00:52")
                                                             (* Put something unreasonable onto the IOCB status so 
							     when it changes we will know it's over.)
    (replace (IOCBPAGE LASTIOCBSTATUS) of \IOCBPAGE with 256)
                                                             (* Start the microcode. There isn't a field in IOPAGE 
							     yet for this.)
    (\PUTBASE \IOPAGE 1 IOCB)                                (* Issue a FirmWare Enable)
    (\DEVICE.OUTPUT 32 3)                                    (* wait for it to change back)
    (until (ZEROP (LOGAND (fetch (IOCBPAGE LASTIOCBSTATUS) of \IOCBPAGE)
			  256)))                             (* return status)
    (fetch (IOCBPAGE LASTIOCBSTATUS) of \IOCBPAGE])

(\D2V
  [LAMBDA (CYL HDSEC)                                        (* lmm "13-DEC-82 17:40")
    (PROG ((HD (FOLDLO HDSEC 256))
	   (SEC (IMOD HDSEC 256)))
          (RETURN (IPLUS (ITIMES CYL SEC/CYL)
			 (ITIMES HD SEC/HD)
			 SEC])

(\V2CYL
  [LAMBDA (DA)                                               (* MPL "17-Jun-84 12:47")
                                                             (* returns the cylinder number of virtual disk address 
							     DA)
                                                             (* NOTE: This fn is no longer locked down, and uses 
							     FIXPs for DAs)
    (QUOTIENT DA SEC/CYL])

(\DEBUGIOCB
  [LAMBDA (MPCODE)                                           (* mpl " 2-Jul-84 08:51")
    (replace (IOPAGE DLMAINTPANEL) of \IOPAGE with (OR MPCODE 1200))
    (until (ZEROP (LOGAND (fetch (IOPAGE DLKBDAD1) of \IOPAGE)
			  1)))
    [until (NOT (ZEROP (LOGAND (fetch (IOPAGE DLKBDAD1) of \IOPAGE)
			       1]
    (replace (IOPAGE DLMAINTPANEL) of \IOPAGE with 1109])
)
(DEFINEQ

(INITDLIONDISK
  [LAMBDA NIL                                                (* MPL "17-Jun-84 12:29")
    (MAPC (QUOTE (\MAKENUMBER \SETGLOBALVAL.UFN \RPLPTR.UFN \HTFIND \SLOWIPLUS2 \SLOWIDIFFERENCE 
			      \SLOWLLSH1 \SLOWLLSH8 \SLOWLRSH1 \SLOWLRSH8 \SLOWLOGOR2 \SLOWLOGAND2 
			      \SLOWLOGXOR2 \SLOWIGREATERP \SLOWIQUOTIENT \SLOWITIMES2 IMOD IREMAINDER)
		 )
	  (FUNCTION \LOCKFN))
    (MAPC DDFNS (FUNCTION \LOCKFN))
    (MAPC (QUOTE (\SMALLNEGSPACE \IOCBPAGE \MDSTypeTable \HTCOLL \HTMAIN \VMBASEDP SEC/HD SEC/CYL 
				 HD/DRV \DISKTYPE \CONTROLLERTYPE))
	  (FUNCTION \LOCKVAR])

(\CYLBOUNDCROSSP
  [LAMBDA (DA1 DA2)                                          (* MPL "17-Jun-84 12:48")
    (NOT (EQUAL (\V2CYL DA1)
		(\V2CYL DA2])
)
(DECLARE: EVAL@COMPILE 

(PUTPROPS \DLDISK.GETSTATUS MACRO (NIL
  (\DEVICE.INPUT 3)))
)
(DECLARE: EVAL@COMPILE DONTCOPY 
(FILESLOAD (LOADCOMP)
	   LLFAULT)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS SEC/HD SEC/CYL HD/DRV \DISKTYPE \CONTROLLERTYPE)
)
)
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(ACCESSFNS DLDISK.STATUS ((TRACK00 (ZEROP (LOGAND DATUM 512)))
			  (HEADSELECT (LOGXOR (LRSH DATUM 11)
					      31))
			  (SA1000 (ZEROP (LOGAND DATUM 32)))
			  (DRIVENOTREADY (ZEROP (LOGAND DATUM 16)))
			  (WRITEFAULT (ZEROP (LOGAND DATUM 8)))
			  (OVERRUN (ZEROP (LOGAND DATUM 4)))
			  (CRCERR (ZEROP (LOGAND DATUM 2)))
			  (VERIFYERR (NOT (ZEROP (LOGAND DATUM 1))))))

(BLOCKRECORD IOCBPAGE ((NIL 3 WORD)
		       (LASTIOCBSTATUS WORD)
		       (NEXTIOCB WORD)
		       (SEEKIOCBLOC WORD)
		       (XFERIOCBLOC WORD)
		       (VRRIOCBLOC WORD)
		       (VVRIOCBLOC WORD)
		       (HCYLINDER WORD)
		       (HHEAD BYTE)
		       (HSECTOR BYTE)
		       (LID 5 WORD)
		       (LPAGELO WORD)
		       (LPAGEHI BITS 7)
		       (NIL BITS 6)
		       (LFLAGS BITS 3)
		       (LTYPE WORD)
		       (LBOOTLINKCHAIN1 WORD)
		       (LBOOTLINKCHAIN2 WORD)
		       (NIL 43 WORD)
		       (PRUNLENGTH WORD)
		       (NIL 6 WORD)
		       (PLABELCMD WORD)
		       (PLABELLEN WORD)
		       (NIL WORD)
		       (PLABELABORT WORD)
		       (PDATACMD WORD)
		       (PDATALEN WORD)
		       (PVPAGE WORD)
		       (PDATAABORT WORD)
		       (PTERMCOND1 WORD)
		       (PTERMCOND2 WORD)
		       (SCYLINDERDISPLACEMENT WORD)
		       (NIL 5 WORD)
		       (SSEEKCMD1 WORD)
		       (NIL WORD)
		       (SSEEKCMD2 WORD)
		       (NIL 9 WORD)
		       (NIL 21 WORD)
		       (RS232CGETIOCB 8 WORD)))

(BLOCKRECORD TRIDENTDCB ((PILOTNEXT WORD)
			 (MICRONEXT WORD)
			 (PILOTTAIL WORD)
			 (RECALIBRATE FLAG)
			 (SELECTMASK BITS 7)
			 (DISKTYPE BITS 3)
			 (DCBOFFSET BITS 4)))

(BLOCKRECORD TRIDENTIOCB ((TH.CYL WORD)
			  (TH.HD BYTE)
			  (TH.SEC BYTE)
			  (TH.LABELPTRLO WORD)
			  (TH.LABELPTRHI WORD)
			  (TH.DATAPTRLO WORD)
			  (TH.DATAPTRHI WORD)
			  (TH.RETRIES WORD)
			  (TH.PAGECOUNT WORD)
			  (TH.CONTROLLERSTATUS WORD)
			  (TH.DISKSTATUS WORD)
			  (TH.uCYL WORD)
			  (TH.uHD BYTE)
			  (TH.uSEC BYTE)
			  (NIL WORD)
			  (TH.MICRONEXT WORD)
			  (TH.DCBOFFSET WORD)
			  (TH.FILEPAGELO WORD)
			  (TH.SEEK.XFERMASK WORD)
			  (TH.SEEK.KDRIVE WORD)
			  (TH.SEEK.KCYL WORD)
			  (TH.SEEK.KHEAD WORD)
			  (TH.HEADER.OP WORD)
			  (TH.HEADER.COMMAND WORD)
			  (TH.HEADER.CONTROL WORD)
			  (TH.HEADER.ERRORMASK WORD)
			  (TH.LABEL.OP WORD)
			  (TH.LABEL.COMMAND WORD)
			  (TH.LABEL.CONTROL WORD)
			  (TH.LABEL.ERRORMASK WORD)
			  (TH.DATA.OP WORD)
			  (TH.DATA.COMMAND WORD)
			  (TH.DATA.CONTROL WORD)
			  (TH.DATA.ERRORMASK WORD)
			  (TH.WRITEVERIFYLABEL 10 WORD)
			  (NIL 5 WORD)
			  (TH.HDSFROMINITIAL WORD)
			  (TH.READLABEL 10 WORD)
			  (NIL 8 WORD)
			  (TH.DSB0.PILOTNEXT WORD)
			  (TH.DSB0.MICRONEXT WORD)
			  (TH.DSB0.PILOTTAIL WORD)
			  (TH.DSB0.SELECTDATA WORD)))
]

(DECLARE: EVAL@COMPILE 

(RPAQQ \DL.ABORT-NR/WF/OVR 28)

(RPAQQ \DL.ABORT-NR/WF/OVR/CRC 30)

(RPAQQ \DL.ABORT-NR/WF/OVR/CRC/VERIFY 31)

(RPAQQ \DL.READFIELD 1072)

(RPAQQ \DL.SEEKIOCBSTART 338)

(RPAQQ \DL.VERIFYFIELD 1074)

(RPAQQ \DL.WRITEFIELD 1083)

(RPAQQ \DL.XFERIOCBSTART 355)

(RPAQQ \DL.MINUSSTEP 1120)

(RPAQQ \DL.PLUSSTEP 1056)

(CONSTANTS \DL.ABORT-NR/WF/OVR \DL.ABORT-NR/WF/OVR/CRC \DL.ABORT-NR/WF/OVR/CRC/VERIFY \DL.READFIELD 
	   \DL.SEEKIOCBSTART \DL.VERIFYFIELD \DL.WRITEFIELD \DL.XFERIOCBSTART \DL.MINUSSTEP 
	   \DL.PLUSSTEP)
)

(DECLARE: EVAL@COMPILE 

(RPAQQ \TH.DR.COMMAND 11332)

(RPAQQ \TH.DR.CONTROL 61582)

(RPAQQ \TH.DR.ERRORMASK 1536)

(RPAQQ \TH.DR.OP 14)

(RPAQQ \TH.DW.COMMAND 11396)

(RPAQQ \TH.DW.CONTROL 61583)

(RPAQQ \TH.DW.ERRORMASK 512)

(RPAQQ \TH.DW.OP 13)

(RPAQQ \TH.LN.COMMAND 15364)

(RPAQQ \TH.LN.CONTROL 61588)

(RPAQQ \TH.LN.ERRORMASK 512)

(RPAQQ \TH.LN.OP 0)

(RPAQQ \TH.LR.COMMAND 11332)

(RPAQQ \TH.LR.CONTROL 61580)

(RPAQQ \TH.LR.ERRORMASK 1536)

(RPAQQ \TH.LR.OP 10)

(RPAQQ \TH.LV.COMMAND 11332)

(RPAQQ \TH.LV.CONTROL 61573)

(RPAQQ \TH.LV.ERRORMASK 3584)

(RPAQQ \TH.LV.OP 11)

(RPAQQ \TH.LW.COMMAND 11396)

(RPAQQ \TH.LW.CONTROL 61581)

(RPAQQ \TH.LW.ERRORMASK 512)

(RPAQQ \TH.LW.OP 9)

(RPAQQ \TH.WW.CONTROL 61455)

(RPAQQ \DL.TRI.STARTCMD 3072)

(RPAQQ \TH.SEEK.HDCMD 3072)

(RPAQQ \TH.SEEK.CYLCMD 3072)

(CONSTANTS \TH.DR.COMMAND \TH.DR.CONTROL \TH.DR.ERRORMASK \TH.DR.OP \TH.DW.COMMAND \TH.DW.CONTROL 
	   \TH.DW.ERRORMASK \TH.DW.OP \TH.LN.COMMAND \TH.LN.CONTROL \TH.LN.ERRORMASK \TH.LN.OP 
	   \TH.LR.COMMAND \TH.LR.CONTROL \TH.LR.ERRORMASK \TH.LR.OP \TH.LV.COMMAND \TH.LV.CONTROL 
	   \TH.LV.ERRORMASK \TH.LV.OP \TH.LW.COMMAND \TH.LW.CONTROL \TH.LW.ERRORMASK \TH.LW.OP 
	   \TH.WW.CONTROL \DL.TRI.STARTCMD \TH.SEEK.HDCMD \TH.SEEK.CYLCMD)
)

(DECLARE: EVAL@COMPILE 

(RPAQQ \TH.HV.COMMAND 11332)

(RPAQQ \TH.HV.CONTROL 63619)

(RPAQQ \TH.HV.ERRORMASK 3584)

(RPAQQ \TH.HV.OP 279)

(RPAQQ \DL.TRI.PASSWORD 279)

(CONSTANTS \TH.HV.COMMAND \TH.HV.CONTROL \TH.HV.ERRORMASK \TH.HV.OP \DL.TRI.PASSWORD)
)

(DECLARE: EVAL@COMPILE 

(RPAQQ \TH.DOCTL.RESETDEVICECHECK 9224)

(RPAQQ \TH.DOCTL.SETHD5 17413)

(RPAQQ \TH.NULLCTL.RESETDEVICECHECK 1032)

(RPAQQ \TH.NULLCTL.SETHD5 1029)

(CONSTANTS \TH.DOCTL.RESETDEVICECHECK \TH.DOCTL.SETHD5 \TH.NULLCTL.RESETDEVICECHECK 
	   \TH.NULLCTL.SETHD5)
)
)
(DECLARE: DONTEVAL@LOAD DOCOPY 
(INITDLIONDISK)
)
(PUTPROPS DISKDLION COPYRIGHT ("Xerox Corporation" 1984))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2099 29219 (\DL.DISKINIT 2109 . 4794) (\DL.RECALIBRATE 4796 . 5667) (
\DL.SHUGART.XFERDISK 5669 . 12379) (\DL.TRANSFERPAGE 12381 . 12830) (\DL.TRI.INITIATE.IO 12832 . 13419
) (\DL.TRI.XFERDISK 13421 . 22054) (\DL.ACTONVMEMFILE 22056 . 22949) (\DL.ACTONVMEMPAGE 22951 . 24055)
 (\DL.DISKSEEK 24057 . 26613) (\DL.XFERDISK 26615 . 27141) (\DL.DISKOP 27143 . 28063) (\D2V 28065 . 
28331) (\V2CYL 28333 . 28756) (\DEBUGIOCB 28758 . 29217)) (29220 30037 (INITDLIONDISK 29230 . 29861) (
\CYLBOUNDCROSSP 29863 . 30035)))))
STOP