Google
 

Trailing-Edge - PDP-10 Archives - BB-M080K-SM - monitor-sources/phyp4.mac
There are 52 other files named phyp4.mac in the archive. Click here to see a list.
;------------------------- Autopatch Tape # 12 -------------------------
; UPD ID= 2164, SNARK:<6.1.MONITOR>PHYP4.MAC.49,   5-Jun-85 10:43:26 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1926, SNARK:<6.1.MONITOR>PHYP4.MAC.48,   7-May-85 21:41:49 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1831, SNARK:<6.1.MONITOR>PHYP4.MAC.47,  26-Apr-85 09:39:31 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1556, SNARK:<6.1.MONITOR>PHYP4.MAC.46,  20-Feb-85 17:30:44 by GRANT
;TCO 6.1.1200 - Call PHYSIO (routine SETDSN) to set drive serial number.
; UPD ID= 1297, SNARK:<6.1.MONITOR>PHYP4.MAC.45,   9-Jan-85 14:48:18 by GRANT
;TCO 6.1.1125 - Get drive serial number whenever a disk comes online.
; UPD ID= 1123, SNARK:<6.1.MONITOR>PHYP4.MAC.44,  21-Nov-84 15:22:17 by MCLEAN
;REVERSE STATE OF U1.VV
; UPD ID= 1113, SNARK:<6.1.MONITOR>PHYP4.MAC.43,  20-Nov-84 15:47:00 by MCLEAN
;REMOVE CHECKS FOR RP07 BUG ON VV
; UPD ID= 5078, SNARK:<6.MONITOR>PHYP4.MAC.40,  19-Nov-84 14:29:13 by MCLEAN
;SET VV WHEN OFFLINE
; UPD ID= 1093, SNARK:<6.1.MONITOR>PHYP4.MAC.40,  17-Nov-84 22:28:44 by MCLEAN
;BETTER CHOICE TO USE P4 INSTEAD OF T4 AT RP4LT4
; UPD ID= 1092, SNARK:<6.1.MONITOR>PHYP4.MAC.39,  17-Nov-84 22:25:22 by MCLEAN
;FIX LATENCY OPTIMIZATION FOR HOMEBLOCKS
; UPD ID= 992, SNARK:<6.1.MONITOR>PHYP4.MAC.38,   7-Nov-84 13:46:01 by MCLEAN
;FIX OPTIMIZATION TO HANDLE HOMEBLOCKS FIRST
; UPD ID= 4797, SNARK:<6.MONITOR>PHYP4.MAC.37,  11-Sep-84 11:50:18 by MCLEAN
;FIX RP4SSC IF DUAL PORTED RP07 AND OTHER PORT IS ENABLED
; UPD ID= 4556, SNARK:<6.MONITOR>PHYP4.MAC.36,  18-Jul-84 15:48:33 by MCLEAN
;FIXES FOR EXTENDED ADDRESSING
; UPD ID= 4547, SNARK:<6.MONITOR>PHYP4.MAC.35,  15-Jul-84 22:23:08 by PURRETTA
;Update copyright notice
; UPD ID= 4401, SNARK:<6.MONITOR>PHYP4.MAC.34,  27-Jun-84 22:32:03 by MCLEAN
;REMOVE RP4NSN
; UPD ID= 4251, SNARK:<6.MONITOR>PHYP4.MAC.33,  29-May-84 22:14:23 by MCLEAN
;ADD SUPPORT FOR DOP%PS
; UPD ID= 4175, SNARK:<6.MONITOR>PHYP4.MAC.32,   7-May-84 11:21:09 by MCLEAN
;MAKE RP4NSN A BUGINF
; UPD ID= 3421, SNARK:<6.MONITOR>PHYP4.MAC.31,   8-Jan-84 15:48:07 by MCLEAN
;MISSING CALL TO PHYDUA AT RP4ATN
; UPD ID= 3272, SNARK:<6.MONITOR>PHYP4.MAC.30,   7-Dec-83 11:02:50 by MCLEAN
;MOVE US.2PT EARLIER IN CODE
; UPD ID= 3210, SNARK:<6.MONITOR>PHYP4.MAC.29,  22-Nov-83 19:39:26 by MCLEAN
;TCO 6.1879 FIX RP4UNF SO THAT DUAL PORT DISKS WAIT FOR PORT
; UPD ID= 3179, SNARK:<6.MONITOR>PHYP4.MAC.28,  16-Nov-83 22:30:35 by MCLEAN
;MORE PORT RELEASE FIXES
; UPD ID= 3112, SNARK:<6.MONITOR>PHYP4.MAC.27,   7-Nov-83 21:27:32 by MCLEAN
;ADD PORT RELEASE DISPATCH
; UPD ID= 3002, SNARK:<6.MONITOR>PHYP4.MAC.26,   5-Oct-83 20:13:14 by MCLEAN
;TCO 6.1818 RE-ADJUST CODE FOR SECTION 1 OPERATION
; UPD ID= 2889, SNARK:<6.MONITOR>PHYP4.MAC.25,  12-Sep-83 13:28:28 by MCLEAN
;TCO 6.1797 CLEAR ACTIVE AND POSITION BITS IN THE UDB BEFORE DOING PACK ACK
; UPD ID= 2886, SNARK:<6.MONITOR>PHYP4.MAC.24,  11-Sep-83 21:00:42 by MCLEAN
;MORE 6.1714 WHICH WILL KEEP UNIT ACTIVE
; UPD ID= 2684, SNARK:<6.MONITOR>PHYP4.MAC.23,   6-Jul-83 23:47:02 by MCLEAN
;TCO 6.1714 AT RP4ATU THE REQUEST IS NOT ACTIVE SO DON'T CALL
; PHYPDN TO INDICATE THAT POSITIONING IS DONE WHEN WE ARE NOT
; POSITIONING.
; UPD ID= 2551, SNARK:<6.MONITOR>PHYP4.MAC.22,   2-Jun-83 13:32:30 by MCLEAN
;ADD CODE TO CHECK FOR DUAL PORT MODE CHANGES
; UPD ID= 2523, SNARK:<6.MONITOR>PHYP4.MAC.21,  25-May-83 20:51:39 by MCLEAN
;MORE TCO 6.1666 WE GOTTA DO THE CHECK EVERY TIME INCASE WE MISS IT
;THE FIRST TIME.
; UPD ID= 2510, SNARK:<6.MONITOR>PHYP4.MAC.20,  24-May-83 16:32:07 by MCLEAN
;TCO 6.1666 SET SERIAL NUMBER AT ONLINE TIME TOO.
; UPD ID= 2496, SNARK:<6.MONITOR>PHYP4.MAC.19,  20-May-83 23:45:52 by MCLEAN
;TCO 6.1649 MORE THOUGHTS ON PORT RELEASES...
; UPD ID= 2448, SNARK:<6.MONITOR>PHYP4.MAC.18,   9-May-83 16:07:56 by MCLEAN
;FIX TYPO IN PREVIOUS EDIT
; UPD ID= 2443, SNARK:<6.MONITOR>PHYP4.MAC.17,   6-May-83 14:40:42 by MCLEAN
;TCO 6.1649 SECOND PASS...
; UPD ID= 2428, SNARK:<6.MONITOR>PHYP4.MAC.16,   5-May-83 20:28:14 by MCLEAN
;TCO 6.1649 REMOVE SOME OF THE PORT RELEASES (FIRST PASS) AT THIS...
; UPD ID= 2202, SNARK:<6.MONITOR>PHYP4.MAC.15,   8-Apr-83 05:46:40 by WACHS
;TCO 6.1603 - Light US.2PT
; UPD ID= 2166, SNARK:<6.MONITOR>PHYP4.MAC.14,   5-Apr-83 15:20:54 by MILLER
;TCO 6.1592. Handle attention status at RP4CON
; UPD ID= 2151, SNARK:<6.MONITOR>PHYP4.MAC.13,   4-Apr-83 14:45:15 by MILLER
;TCO 6.1589. Set US.OMS if RPCERR is not hard error present
; UPD ID= 1720, SNARK:<6.MONITOR>PHYP4.MAC.12,  28-Jan-83 14:20:28 by DONAHUE
;TCO 6.1440 - Change RP4UNF to a Bugchk
; UPD ID= 1106, SNARK:<6.MONITOR>PHYP4.MAC.11,  24-Aug-82 12:18:39 by PAETZOLD
;More TCO 6.1228 - In the never ending search for the
; elegant solution, do not increment UDBRCT for skip reads
; UPD ID= 1088, SNARK:<6.MONITOR>PHYP4.MAC.10,  17-Aug-82 18:30:29 by PAETZOLD
;TCO 6.1228 - Update UDBRCT as well and UDBRVC for skip reads
; UPD ID= 1047, SNARK:<6.MONITOR>PHYP4.MAC.9,   6-Aug-82 14:47:47 by PAETZOLD
;TCO 6.1217 - Update UDBRVC for skip reads and not UDBRCT
; UPD ID= 906, SNARK:<6.MONITOR>PHYP4.MAC.8,   9-Jun-82 23:37:22 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 568, SNARK:<6.MONITOR>PHYP4.MAC.7,   1-Apr-82 07:37:40 by PAETZOLD
;TCO 6.1079 - Dont use ECC for IRFRVC functions
; UPD ID= 266, SNARK:<6.MONITOR>PHYP4.MAC.6,  22-Dec-81 05:06:46 by WACHS
;TCO 5.1641 Handle seize-done interrupts correctly
; UPD ID= 216, SNARK:<6.MONITOR>PHYP4.MAC.5,  23-Nov-81 07:43:05 by WACHS
;TCO 5.1617 Write a register first at RP4CON to seize the drive
; UPD ID= 199, SNARK:<6.MONITOR>PHYP4.MAC.4,  10-Nov-81 09:46:50 by WACHS
;TCO 5.1611 call OPI, DTE  header errors on an RP07
; UPD ID= 1849, SNARK:<6.MONITOR>PHYP4.MAC.3,  21-Apr-81 06:21:45 by WACHS
;TCO 5.1288 - Modify UDB definitions
; UPD ID= 1597, SNARK:<6.MONITOR>PHYP4.MAC.2,  27-Feb-81 07:21:23 by WACHS
;tco 6.1002 - Add code for dual-ported disks
; UPD ID= 1391, SNARK:<5.MONITOR>PHYP4.MAC.8,  31-Dec-80 08:55:30 by WACHS
;TCO 5.1222 - Add code for movement of packs from drive to drive
; UPD ID= 1334, SNARK:<5.MONITOR>PHYP4.MAC.7,   1-Dec-80 17:40:04 by LYONS
; UPD ID= 959, SNARK:<5.MONITOR>PHYP4.MAC.6,  25-Aug-80 15:10:44 by LYONS
; UPD ID= 957, SNARK:<5.MONITOR>PHYP4.MAC.5,  25-Aug-80 14:44:38 by LYONS
;tco 5.1062 - off by 1 bug in verification code
; UPD ID= 934, SNARK:<5.MONITOR>PHYP4.MAC.4,  20-Aug-80 15:00:43 by LYONS
;TCO 5.1062 - write verif; UPD ID= 737, SNARK:<5.MONITOR>PHYP4.MAC.3,   7-Jul-80 00:47:28 by DBELL
;TCO 5.1096 - ADD UDSCCK DISPATCH
; UPD ID= 364, SNARK:<4.1.MONITOR>PHYP4.MAC.10,  26-Mar-80 11:07:14 by DBELL
;TCO 4.1.1119 - MAKE CHANGES REQUIRED FOR RP20 DISKS
;<4.1.MONITOR>PHYP4.MAC.9, 15-Nov-79 15:37:08, EDIT BY DBELL
;TCO 4.2572 - MAKE PORT CONTENTION WORK PROPERLY AT RP4CN3 AND RP4ATU
;<OSMAN.MON>PHYP4.MAC.1, 10-Sep-79 16:00:38, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>PHYP4.MAC.7,  4-May-79 11:00:12, EDIT BY ENGEL
;USE INTERRUPTS TO FORCE RELEASE OF DUAP-PORT DEVICE (RP4CN3 & RP4ATU)
;<4.MONITOR>PHYP4.MAC.6,  5-Mar-79 15:53:41, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>PHYP4.MAC.5,  4-Dec-78 19:37:55, EDIT BY BOSACK
;TCO 4.2106 - DEFER ECC APPLICATION UNTIL DRIVE HAS SETTLED ON CYL
;<2MCLEAN>PHYP4.MAC.4, 30-Jul-78 15:16:13, Edit by MCLEAN
;<2MCLEAN>PHYP4.MAC.3, 30-Jul-78 14:46:26, Edit by MCLEAN
;<4.MONITOR>PHYP4.MAC.2, 22-Jul-78 22:11:23, Edit by MCLEAN
;<1MCLEAN>PHYP4.MAC.83,  6-May-78 21:45:28, Edit by MCLEAN
;<1MCLEAN>PHYP4.MAC.82,  6-May-78 21:40:57, Edit by MCLEAN
;ADD RP07 CODE
;<1MCLEAN>PHYP4.MAC.81,  6-May-78 21:40:37, Edit by MCLEAN
;<3.SM10-RELEASE-3>PHYP4.MAC.79,  3-Apr-78 18:49:52, Edit by MCLEAN
;FIX ATNXIT NOT TO CLEAR CHANNEL ON TRANSFERING DRIVE
;<3A.MONITOR>PHYP4.MAC.79,  8-Mar-78 23:58:51, Edit by MCLEAN
;CLEAR DRIVE AT ATNXIT
;<2BOSACK>PHYP4.MAC.77, 24-Feb-78 01:25:42, EDIT BY BOSACK
;CHANGE DEVICE/DATA ERROR FLAGGING
;<2BOSACK>PHYP4.MAC.76, 15-Feb-78 02:09:13, EDIT BY BOSACK
;<4.MONITOR>PHYP4.MAC.76,  1-Feb-78 14:52:23, Edit by MCLEAN
;FIX FOR NEW PHYUDB CALLING SEQ
;<2BOSACK>PHYP4.MAC.75, 30-Jan-78 02:37:06, EDIT BY BOSACK
;<2BOSACK>PHYP4.MAC.74, 27-Jan-78 02:14:45, EDIT BY BOSACK
;<2BOSACK>PHYP4.MAC.73, 25-Jan-78 03:46:02, EDIT BY BOSACK
;<2BOSACK>PHYP4.MAC.72, 25-Jan-78 03:40:58, EDIT BY BOSACK
;REORGANIZED DISK PHYSICAL PARAMETER TREATMENT
;CHANGED LATOPT TO USE UDB FOR PHYSICAL PARAMETERS
;MINOR (10USEC ON A 2050) SPEEDUPS
;<2BOSACK>PHYP4.MAC.71, 15-Jan-78 20:50:53, EDIT BY BOSACK
;<2BOSACK>PHYP4.MAC.70, 15-Jan-78 20:47:30, EDIT BY BOSACK
;CHANGES FOR RM03 ECC DIFFERENCES

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (C)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1985.
;ALL RIGHTS RESERVED.


	SEARCH PROLOG,SERCOD	;SYSTEM PARAMETERS
	TTITLE (PHYP4,,< - DEVICE DEPENDENT CODE FOR RP04 DISKS>)
	SUBTTL T.HESS, T WACHS/TAH/TW/LB/RM 2 JULY 75

	SEARCH PHYPAR		;PARAMETERS
	ENTRY RP4DSP		;FOR LIBRARY SEARCH
	SUBTTL PARAMETERS

;DRIVE REGISTERS

DO.DRC==(0B5)			;DRIVE CONTROL REGISTER
DO.SR==(1B5)			;STATUS REGISTER
DO.ER==(2B5)			;ERROR REGISTER
DO.AS==(4B5)			;ATTENTION SUMMARY
DO.DA==(5B5)			;DESIRED ADDRESS (TRACK/SECTOR)
DO.DT==(6B5)			;DRIVE TYPE
DO.LA==(7B5)			;LOOK AHEAD
DO.SN==(10B5)			;DRIVE SERIAL NUMBER
DO.OF==(11B5)			;OFFSET REGISTER
DO.DC==(12B5)			;DESIRED CYLINDER
DO.ER3==(15B5)			;ERROR REGISTER # 3
DO.ECP==(16B5)			;ECC POSITION
DO.ECB==(17B5)			;ECC BURST (PATTERN)

;DRIVE FUNCTIONS

DF.UNL==3			;UNLOAD
DF.SEK==5			;SEEK
DF.RCL==7			;RECALIBRATE
DF.CLR==11			;DRIVE CLEAR
DF.REL==13			;RELEASE (DUAL PORT)
DF.OFS==15			;OFFSET POSITION
DF.RTC==17			;RETURN TO CENTERLINE
DF.PST==21			;READIN PRESET
DF.ACK==23			;PACK ACKNOWLEDGE
DF.SRC==31			;SEARCH
DF.WRT==61			;WRITE DATA
DF.WTF==63			;WRITE FORMAT
DF.RED==71			;READ DATA
DF.RDF==73			;READ FORMAT

F22==100			;22-SECTOR MODE (SOFTWARE ONLY)
ERETRY==200			;ERROR RETRY (ECC FIXED 1ST PART) SOFTWARE ONLY
DXES==200000			;DISABLE STOP ON ERROR

;BITS IN CONTROL REGISTER

CR.DVA==4000			;DEVICE AVAILABLE - FOR DUAL PORT
;DRIVE STATUS REGISTER

DS.ATA==1B20			;ATTENTION
DS.ERR==1B21			;ERROR
DS.PIP==1B22			;POSITION IN PROGRESS
DS.MOL==1B23			;MEDIA ON LINE
DS.WRL==1B24			;WRITE LOCKED
DS.LST==1B25			;LAST SECTOR TRANSFERRED
DS.PGM==1B26			;PROGRAMMABLE (DUAL PORT)
DS.DPR==1B27			;DRIVE PRESENT
DS.DRY==1B28			;DRIVE READY
DS.VV==1B29			;VOLUME VALID

DS.GUD==DS.MOL!DS.DPR!DS.DRY!DS.VV
DS.MSK==DS.GUD!DS.ATA!DS.ERR!DS.PIP!DS.WRL	;MASK OF STATUS BITS TO CONSIDER

;DRIVE ERROR REGISTER

ER.DCK==1B20			;DRIVE CHECK
ER.UNS==1B21			;DRIVE UNSAFE
ER.OPI==1B22			;OPERATION INCOMPLETE
ER.DTE==1B23			;DRIVE TIMING ERROR
ER.WLE==1B24			;WRITE LOCK ERROR
ER.IAE==1B25			;INVALID ADDRESS ERROR
ER.AOE==1B26			;ADDRESS OVERFLOW ERROR
ER.CRC==1B27			;HEADER CRC ERROR
ER.HCE==1B28			;HEADER COMPARE ERROR
ER.ECH==1B29			;ECC HARD ERROR
ER.WCF==1B30			;WRITE CLOCK FAILURE
ER.FER==1B31			;FORMAT ERROR
ER.CPE==1B32			;CONTROL BUS PARITY ERROR
ER.RMR==1B33			;REGISTER MODIFICATION REFUSED
ER.ILR==1B34			;ILLEGAL REGISTER
ER.ILF==1B35			;ILLEGAL FUNCTION
ER.OFS==ER.DCK!ER.FER!ER.CRC!ER.HCE ;ERRORS ON WHICH TO TRY OFFSET

;OFFSET REGISTER

OF.F22==1B23			;22-SECTOR MODE
OF.ECI==1B24			;ERROR CORRECTION CODE INHIBIT

;ERROR REGISTER 3 STATUS BITS

E3.OCL==1B20			;OFF CYLINDER
E3.SKI==1B21			;SEEK INCOMPLETE
	SUBTTL ERROR RECOVERY/REPORTING DEFINITIONS
;RETRY COUNTS
POSCNT==3			;NUMBER OF TIMES TO RETRY ON POSITION FAILURE
DEVCNT==3			;RETRIES ON DEVICE ERROR (NOT DATA OR HEADER) BEFORE RECALIBRATE
				; MUST BE AT LEAST 3

RCLCNT==3			;RECALIBRATES AFTER DEVCNT TRIES (TIMES FOR COMPLETE CYCLE)
;STATUS BITS IN LH(UDBERR)
ES.HRD==1B0			;HARD ERROR
ES.ECC==1B1			;ECC-CORRECTED ERROR
ES.DAT==1B2			;DATA ERROR
ES.HDR==1B3			;HEADER ERROR
ES.DEV==1B4			;DEVICE ERROR (NEITHER DATA NOR HEADER)
ES.POS==1B5			;POSITIONING ERROR
ES.FER==1B6			;FORMAT ERROR (20-SECTOR PACK IN 22-SECT. MODE, ETC)


;UDB EXTENSIONS

RP.CNI==UDBDDD			;CONI OF RH GOES HERE
RP.CRC==RP.CNI+1		;DATAI RH CONTROL REGISTER
RP.DBF==RP.CRC+1		;DATAI RH DATA REGISTER
RP.CYL==RP.DBF+1		;NUMBER OF CYLINDERS PER UNIT
RP.SCL==RP.CYL+1		;NUMBER OF SECTORS PER CYLINDER
RP.SSF==RP.SCL+1		;NUMBER OF SECTORS PER SURFACE
RP.USU==RP.SSF+1		;NUMBER OF USEC PER LA REG UNIT
RP.USF==RP.USU+1		;SSF * 64 (LA REG UNITS)
RP.LST==RP.USF+1		;START OF LAST PAGE ON A CYLINDER

RP.REG==RP.LST+1		;DRIVE REGISTERS GO HERE

DR.CRC==0			;CONTROL REGISTER
DR.ST==1			;STATUS
DR.ER==2			;ERROR
DR.MT==3			;MAINTENANCE
DR.ATA==4			;ATTENTION SUMMARY
DR.DA==5			;DESIRED ADDRESS
DR.DT==6			;DRIVE TYPE
DR.LA==7			;LOOK AHEAD
DR.SN==10			;SERIAL NUMBER
DR.OF==11			;OFFSET
DR.DC==12			;DESIRED CYLINDER
DR.CA==13			;CURRENT ADDRESS
DR.ER2==14			;ERROR REGISTER # 2
DR.ER3==15			;ERROR REGISTER # 3
DR.ECP==16			;ECC POSITION
DR.ECB==17			;ECC BURST

L.RP4==RP.REG+20		;LENGTH OF RP04 UDB
;DISPATCH TABLE
RP4DSP:	JRST RP4INI		;0 - INITIATION
	JRST RP4SIO		;1 - START I/O
	JRST RP4INT		;2 - HANDLE INTERRUPT
	JRST RP4ERR		;3 - ERROR RECOVERY
	RET			;4 - HUNG DEVICE
	JRST RP4CNV		;5 - CONVERT BLK # TO CYLINDER/SURF-SEC
	JRST RP4LTM		;6 - LATENCY COMPUTATION
	JRST RP4POS		;7 - START POSITIONING
	JRST RP4ATN		;10- ATTENTION INTERRUPT
	JRST RP4PRQ		;11- SKIP IF POSITIONING REQUIRED
	JRST RP4STK		;12- STACK SECOND TRANSFER COMMAND
	RET			;13- CHECK EXISTANCE OF UNIT (NOT CALLED)
	RET			;14- CHECK FOR HALTED CONTROLLER (NOT CALLED)

	JRST RP4REL		;15- RELEASE PORT

;DISKS ARE CHECKED BY CALLING CNV AND CHECKING UDBPS1

RP4PRQ:	RETSKP		;IF ASKED, SAY ALWAYS

;TRANSLATION FROM MASSBUS TYPE TO INTERNAL BLOCKTYPE

XTYPE:	XWD .UTRP4,TY.RP4
	XWD .UTRP5,TY.RP5
	XWD .UTRP6,TY.RP6
	XWD .UTRP7,TY.R7F
	XWD .UTRP7,TY.R7M
	XWD .UTRM3,TY.RM3

NXTYPE==.-XTYPE
	SUBTTL INITIATION

;C(Q2) := UNIT NUMBER

RP4INI:	SAVEQ
	MOVE T3,[RP4DSP,,L.RP4]	;DISPATCH,,LENGTH
	CALL PHYUDB		;SET UP UDB
	RET			;RETURN IF NO SPACE
INIA:	MOVSI T2,DO.DT		;READ DRIVE TYPE REGISTER
	CALL RDREG		; ...
	ANDI T1,777		;MASK TO JUST DRIVE TYPE
				;CHECK FOR PORT GONE SINCE LAST READ
	JUMPE T1,[ MOVSI T2,DO.DT	;WRITE THE DAMN REGISTER SO WE WILL SEIZE IT
		CALL WTREG
		JRST INIA]	;DON'T CARE ABOUT ANSWER TRY AGAIN
	MOVSI T2,-NXTYPE	;SEARCH TABLE FOR INTERNAL UNIT TYPE
INI1:	MOVE T3,XTYPE(T2)	;GET TYPE WORD
	CAIN T1,(T3)		;MATCH?
	JRST INI2		;YES
	AOBJN T2,INI1		;NO - ANY LEFT
	BUG.(HLT,RP4UNF,PHYP4,HARD,<PHYP4 - Unit type not found>,<<T1,DRVTYP>>,<

Cause:	During initialization of a disk in the routine RP4INI, the
	hardware drive type of the disk was read, and then the XTYPE
	table was searched for the corresponding internal drive type.
	The search failed, indicating the disk was of an unknown type.

Data:	DRVTYP - Drive type

>)
INI2:	HLRZ T1,T3		;FOUND - GET INTERNAL TYPE CODE
	MOVE T4,T1		;COPY FOR UDB BUILD LATER
	MOVSI T2,-NDSKUT	;SEARCH TO FIND PHYSICAL PARAM TABLE
INI3:	CAMN T1,DSKUTP(T2)	;MATCH?
	JRST INI4		;YES
	AOBJN T2,INI3		;NO - LOOP
	BUG.(HLT,RP4PNF,PHYP4,SOFT,<PHYP4 - Disk physical parameters not found>,,<

Cause:	The routine RP4INI was called to initialize a UDB for a disk.
	It converted the hardware drive type into the internal drive
	type, and then looked in the physical parameter table (DSKUTP)
	for that type, so that the disk parameters could be obtained.
	The drive type could not be found.
>)
INI4:	MOVE T2,DSKSIZ(T2)	;GET POINTER TO PHYSICAL PARAMETER TABLE
	MOVEM T2,UDBSIZ(P3)	;SAVE IN UDB
	MOVE T3,CYLUNT(T2)	;GET NUMBER OF CYLINDERS
	MOVEM T3,RP.CYL(P3)	;SAVE COPY
	MOVE T3,SECCYL(T2)	;GET SECTORS PER CYLINDER
	MOVEM T3,RP.SCL(P3)	;SAVE
	SUB T3,SECPAG(T2)	;COMPUTE START OF LAST PAGE ON A CYL
	MOVEM T3,RP.LST(P3)	;SAVE
	MOVE T3,SECSRF(T2)	;GET SECTORS PER SURFACE
	MOVEM T3,RP.SSF(P3)	;SAVE
	LSH T3,6		;COMPUTE LATOPT UNITS PER SURF
	MOVEM T3,RP.USF(P3)	;SAVE
	MOVE T3,USSECU(T2)	;GET USEC PER LATOPT UNIT
	MOVEM T3,RP.USU(P3)	;SAVE
	MOVSI T2,DO.SR		;READ STATUS REGISTER
	CALL RDREG
	TLO T4,(US.PRQ)		;INDICATE POSITIONING REQUIRED
	TRNE T1,DS.WRL		;WRITE LOCKED?
	TLO T4,(US.WLK)		;YES - INDICATE IN STATUS
	TRNE T1,DS.PGM		;DUAL PORT IN PROGRAMMABLE MODE?
	TXO T4,US.PGM!US.2PT	;YES - INDICATE IN UNIT STATUS
	TRNN T1,DS.MOL		;MEDIA ON LINE?
	TLO T4,(US.OFS)		;SET OFF-LINE
	TXO T4,US.DSK		;THIS IS A DISK TYPE DEVICE
	IORM T4,UDBSTS(P3)	;SET UP STATUS AND CONFIGURATION
	TRNN T1,DS.VV		;VOLUME VALID?
	CALL RP4UP		;NO - ACK NOW
	CALL RP4DSN		;(P1,P3) GET DSN
	CALL PHYDUA		;(P3/) LOOK FOR ANOTHER PORT FOR THIS DRIVE
	MOVSI T2,DO.LA		;CHECK FOR STUCK SECTOR COUNTER
	CALL RDREG
	MOVE T4,T1		;SAVE FIRST VALUE
	MOVEI Q1,^D100000	;MAXIMUM NUMBER OF TIME TO TRY
INI5:	MOVSI T2,DO.LA		;NOW TRY FOR A DIFFERENT VALUE
	CALL RDREG
	CAME T1,T4		;STILL THE SAME?
	CALLRET RP4DIS		;NO - RELEASE DRIVE AND RETURN
	SOJGE Q1,INI5		;YES - TRY AGAIN
	MOVE T1,CDBADR(P1)	;GET CHANNEL ADDRESS
	MOVE T2,UDBAKA(P3)	;AND UNIT ADDRESS
	SKIPE UDBDSN(P3)	;DON'T BUGCHK IF THERE IS NO SERIAL NUMBER
				;THE PORT MAY BE ON THE OTHER SIDE
	BUG.(CHK,RP4SSC,PHYP4,HARD,<PHYP4 - Stuck sector counter>,<<T1,CDBADR>,<T2,UDBAKA>>,<

Cause:	During initialization of a disk unit in the routine RP4INI,
	the sector counter for the disk was examined to see if it
	was changing as it should.  After watching the value for
	100000 times, it never varied.

Action:	Call Field Service to fix the disk.

Data:	CDBADR - Channel address
	UDBAKA - Unit address
>)
	CALLRET RP4DIS		;RELEASE AND RETURN
	SUBTTL START I/O

;C(P4) := IORB , C(P3) := UDB , C(P3) := CDB

RP4SIO:	SAVEQ			;SAVE REGISTERS
	HRRZ T3,UDBERR(P3)	;GET FUNCTION IF ERROR RECOVERY
	JUMPN T3,RP4SI1		;ERROR RECOVERY?
	LDB T3,IRYFCN		;GET FCN
	CAILE T3,MXRP4F		;CHECK MAXIMUM LEGAL
	CAIL T3,MNRP4V		;BUT ALLOW VALIDITY FUNCTIONS
	JRST RP4SI1		;ITS OK
	BUG.(HLT,RP4FEX,PHYP4,SOFT,<PHYP4 - Illegal function>,,<

Cause:	The routine RP4SIO was called to start I/O for a unit, but
	the function code supplied in the IORB was out of range.
>)
RP4SI1:	HLRZ Q1,RP4FCN(T3)	;TRANSLATE TO HARDWARE BITS
	TRZ Q1,(XFRFLG)		;MASK
	CALL RP4CON		;CONNECT TO DRIVE
	 RET			;UNIT DOWN (MARKED OFL)
				;RETURNS T2 := CYLINDER , T3 = REMAINDER
	CALL GTHWSC		;GET HW FORMAT SURF/SEC IN T4
	HRLI T2,DO.DC		;SET DESIRED CYLINDER
	CALL WTREG		;WRITE IN REGISTER

	MOVSI T2,DO.OF		;OFFSET REGISTER
	TRZE Q1,F22		;IF 22-SECTOR MODE
	TROA T2,OF.ECI+OF.F22	; THEN CLEAR FMT22 IN OFFSET REGISTER
	TRNE Q1,DXES		;IF NOT STOPPING ON ERROR
	TRCA T2,OF.ECI		; CLEAR OFFSET , SET ECI
	TRNN Q1,10		;IF WRITING
	CALL WTREG		; THEN CLEAR OFFSET REGISTER

	MOVE T2,T4		;GET DISK ADDRESS
	HRLI T2,DO.DA		;DESIRED ADDRESS REGISTER
	JRST CHSTRT		;START CHANNEL & GIVE GOOD RETURN
;ROUTINE TO STACK A SECOND TRANSFER COMMAND

RP4STK:	LDB T1,IRYFCN		;GET FUNCTION
	CAILE T1,MXEXFN		;LEGAL?
	CAIL T1,MNRP4V		;AT EITHER END OF THE SCALE?
	JRST RP4ST1
	BUG.(HLT,RP4IF2,PHYP4,SOFT,<PHYP4 - Illegal function at STKIO>,,<

Cause:	The routine RP4STK was called to start stacked I/O for a
	unit, but the function code supplied in the IORB was out
	of range.
>)
RP4ST1:	HLRZ Q1,RP4FCN(T1)	;GET HW FUNCTION
	TRZ Q1,(XFRFLG)		;MASK
	CALL PHYBLK		;GET UNIT RELATIVE ADDRESS
	TXZ T2,IRBPAD		;REMOVE PHYSICAL ADDRESSING BIT
	CALL RP4CV1		;GET CYL,SECTOR WITHIN CYL IN T2,T3
	MOVEM T3,UDBPS2(P3)	;UPDATE SECTOR
	CALL GTHWSC		;GET HWFMT ADDRESS IN T4
	MOVE T2,T4		;COPY
	HRLI T2,DO.DA		;BUILD DATAO WORD
	CALLRET CHSTRT		;GO STACK THE COMMAND
;ROUTINE TO CONNECT TO A DESIRED UNIT

RP4CON:	SETO T4,		;SET A FLAG FOR TRYING OTHER PORT
RP4CN1:	MOVSI T2,DO.DT		;WRITE A READ-ONLY REGISTER TO SEIZE THE DRIVE
	CALL WTREG		;AND PREVENT THE OTHER PORT FROM GRABBING IT
	MOVSI T2,DO.DRC		;READ CONTROL REGISTER
	CALL RDREG		; IF IN A/B MODE
	TRNN T1,CR.DVA		;PORT AVAILABLE?
	JRST RP4CN3		;NO
	MOVSI T2,DO.SR		;STATUS REGISTER
	CALL RDREG		;GO READ IT
	TXNE T1,DS.PGM		;Programmable?
	TXZ T1,DS.ATA		;yes. Ignore attention status then as
				; dual-ported drives roll attentions!
	ANDI T1,DS.MSK		;MASK OUT DON'T CARES
	CAIE T1,DS.GUD		;DRIVE OK?
	JRST RPCERR		;CONNECT ERROR
	MOVSI T1,(US.WLK)	;CLEAR WRITE LOCKED
RP4CN2:	TLO T1,(US.OFS)		;CLEAR OFFLINE AND UNSAFE
	ANDCAM T1,UDBSTS(P3)	; ...
	CALL PHYBLK		;GET PHYSICAL DISK BLOCK
	TXZ T2,IRBPAD		;REMOVE PHYSICAL ADDRESSING BIT
	HLRZ T1,UDBERP(P3)	;GET BLOCKS DONE
	TRNE Q1,ERETRY
	ADD T2,T1		; START AT 1ST BLOCK NOT READ
	MOVE T1,Q1		;COPY FUNCTION WORD
	CALL RP4CV1		;GET CYLINDER AND SECTOR WITHIN CYLINDER
	MOVEM T2,UDBPS1(P3)	;SAVE CYLINDER
	MOVEM T3,UDBPS2(P3)	;SAVE SURFACE, SECTOR
	RETSKP			;SKIP RETURN

;HERE IF A DUAL PORT DRIVE IS IN USE ON THE OTHER PORT
;THIS IS TEMPORARY UNTIL A NEW BIT IS DEFINED TO HANDLE THIS EXPLICITLY.

RP4CN3:	SKIPE T1,UDB2ND(P3)	;IS DRIVE DUAL-PORTED?
	AOJE T4,RP4CN4		;YES. TRY (ONCE) TO RELEASE OTHER PORT
	MOVX T1,US.OFS!US.OMS	;INDICATE OFFLINE AND MESSAGE ALREADY SENT
	IORM T1,UDBSTS(P3)	;SO NO I/O IS ATTEMPTED
	HRRZ T1,UDBTWQ(P3)	;IS TWQ EMPTY?
	JUMPN T1,R		;NO. LEAVE UDBPS1 ALONE (CORRECT)
	CALL RP4CNV		;YES, GET CYLINDER FOR THIS REQUEST
	MOVEM T2,UDBPS1(P3)	;SAVE IN UDB FOR SEIZE-DONE INTERRUPT
	RET			;WE'LL BE INTERRUPTED WHEN DRIVE AVAILABLE

;HERE FOR DUAL-PORTED DISK, BOTH SIDES ARE KNOWN TO THE -20
;THIS CAN HAPPEN BECAUSE WRITING THE ATTENTION SUMMARY REGISTER (FOR ANOTHER DRIVE)
; WILL CAUSE THIS DRIVE TO SIEZE TO THAT PORT
RP4CN4:	PUSH P,P1		;SAVE CHAN
	HRRZ P1,UDBCDB(T1)	;POINT AT CHAN FOR OTHER PORT
	CALL RP4DIS		;DO A RELEASE ON THE OTHER PORT (!)
	POP P,P1		;NOW BACK TO THIS PORT
	JRST RP4CN1		;AND TRY AGAIN

;HERE IF WE DIDN'T GET NICE STATUS - CHECK WRITE LOCKED

RPCERR:	LDB T3,IRYFCN		;GET FCN
	CAIE T3,IRFWRT		;CHECK WRITING
	CAIN T3,IRFWTF		; OR WRITE FORMAT
	JRST RPCER1		;YES - CHECK ON-LINE
	CAIE T3,IRFWVC		;OK IF WRITE VALIDITY CHECK, TOO
	CAIE T1,DS.GUD+DS.WRL	;NO - WRITE LOCKED?
	JRST RPCER1		;NO - SOMETHING ELSE
	MOVEI T1,0		;YES - DONT CLEAR WLK
	JRST RP4CN2		;AND CONTINUE
RPCER1:	TRNN T1,DS.MOL		;MEDIA ON LINE?
	JRST [MOVSI T3,(US.OFS)	;NO -SET OFF LINE
		 JRST RPCER3]
	TRNE T1,DS.VV		;YES - VOLUME VALID?
	JRST RPCER2		;YES - SOMETHING ELSE IS WRONG
	MOVSI T1,(US.CHB)	;VOLUME CHANGED - MAY NEED TO CHECK HB
	SKIPL UDBSTR(P3)	;UNIT IN STR?
	TLO T1,(US.OIR)		;OPR INTERVENTION IF IN A STR
	IORM T1,UDBSTS(P3)	;YES - MUST CHECK HOME BLOCKS
	CALL RP4UP		;ACK DRIVE
	JRST RP4CON		;AND TRY IT NOW

;Here on bad status that we can't explain

RPCER2:	CALL RP4RDR		;Error. Read all registers
	CALL RP4CLR		;CLEAR DRIVE
	CALL RP4DIS		;RELEASE PORT
SETUNS:	MOVEI T3,0		;ACCUMULATE STATUS HERE
	MOVE T1,RP.REG+DR.ER(P3) ;GET ERROR REGISTER
	TRNE T1,ER.UNS		;FILE UNSAFE?
	TLO T3,(US.OFS)		;OFF-LINE + UNSAFE
	MOVE T1,RP.REG+DR.ST(P3) ;GET STATUS REGISTER
	TRNE T1,DS.WRL		;WRITE LOCKED?
	TLO T3,(US.WLK)		;YES.
	TXNN T3,US.WLK!US.OFS	;Any "hard" errors?
	TXO T3,US.OMS		;No. Do normal background polling then
RPCER3:	IORM T3,UDBSTS(P3)	;SET IN STATUS
	RET			;ERROR RETURN
;HERE TO DISCONNECT FROM A DUAL PORT DRIVE

RP4REL:	MOVSI T1,(US.POS)	;CHECK FOR POSITION IN PROGRESS
	TDNE T1,UDBSTS(P3)
	RET			;NOT POSITION IN PROGRESS
RP4DIS:	MOVSI T1,(US.PGM)	;IS THIS A VARIABLE DUAL PORT
	TDNN T1,UDBSTS(P3)	;DISK?
	RET			;NO.
	MOVE T2,[DO.DRC+DF.REL]	;DRIVE CONTROL REG, RELEASE PORT
	CALL WTREG		;SEND TO DRIVE
	RET

;HERE TO DETERMINE THE CYLINDER ASSOCIATED WITH AN IORB

;P3/ UDB
;P4/ IORB
;	CALL RP4CNV	;ENTERED BY CALL UDSCNV
;RETURNS+1(ALWAYS):
;T2/ CYLINDER (UDBPS1)
;T3/ SECTOR WITHIN CYLINDER (UDBPS2)

RP4CNV:	CALL PHYBLK		;GET UNIT RELATIVE BLOCK ADDRESS
	TXZ T2,IRBPAD		;REMOVE PHYSICAL ADDRESSING BIT
	LDB T1,IRYFCN		;GET FUNCTION FROM IORB
	CAILE T1,MXEXFN		;GREATER THAN MAXIMUM EXTERNAL FUNCTION?
	CAIL T1,MNRP4V		;BUT LESS THAN VALIDITY CHECKS
	SKIPN T1,RP4FCN(T1)	;OR HAVE NULL TABLE ENTRY?
	BUG.(HLT,RP4IFC,PHYP4,SOFT,<PHYP4 - Illegal function at CNV>,,<

Cause:	The routine RP4CNV was called to return the cylinder associated
	with an IORB.  The routine checked the function in the IORB, and
	it was illegal.
>) 		;HERE FOR NULL ENTRY OR BAD FUNCTION
RP4CV2:	HLRZS T1		;GET FUNCTION CODE AND FLAGS
	TRZ T1,(XFRFLG)		;MASK
RP4CV1:	HRRZ T3,RP.SCL(P3)	;GET SECTORS PER CYLINDER
;	TRNE T1,F22		;22 SECTOR MODE?
;	HRRZ T3,...		;GET SECTORS PER CYL IN 22 SEC MODE
	IDIVI T2,(T3)		;CONVERT
	RET

;VERY SPECIAL PURPOSE COMMON CODE TO TRANSLATE SECTOR WITHIN CYL
;IN T3 INTO HWFMT SURF/SECT ADDR IN T4

GTHWSC:	HRRZ T4,RP.SSF(P3)	;GET SECTORS PER SURFACE
;	TRNE Q1,F22		;22 SECTOR MODE?
;	HRRZ T4,....		;GET SECTORS PER SURFACE IN 22 SECTOR
	IDIVI T3,(T4)		;GET SURFACE AND SECTOR
	DPB T3,[POINT 5,T4,27]	; SET T4 TO DESIRED ADDRESS
	RET
SUBTTL LATENCY OPTIMIZATION

;HERE TO DETERMINE WHICH TRANSFER REQUEST TO THIS UNIT HAS
;THE SMALLEST LATENCY GREATER THAN A SPECIFIED MINIMUM.

;P1/ CDB
;P3/ UDB
;T1/ MINIMUM LATENCY IN MICROSECONDS (0 FOR COMMAND STACK COMPUTATION)
;	CALL UDSLTM(CDB)
;RETURNS+1:
;NO REQUESTS AVAILABLE
;RETURNS+2:
;T1/ LATENCY OF CLOSEST REQUEST GREATER THAN SPECIFIED MINIMUM (USEC)
;T2/ PREDECESSOR OF IORB CORRESPONDING TO TIME IN T1
;T3/ IORB CORRESPONDING TO TIME IN T1

;IF COMMAND STACKING COMPUTATION WAS REQUESTED, THE DISK IS ASSUMED TO
;BE ONE PAGE BEYOND THE CURRENT TRANSFER

;CLOBBERS P4,P5,P6

;REGISTER USAGE:
;T3/ MINIMUM LATENCY,,CURRENT UNIT POSITION
;T4/ BEST LATENCY SO FAR,,PREDECESSOR TO CURRENT IORB
;P4/ CURRENT IORB
;P5/ PREDECESSOR TO BEST IORB,,BEST IORB SO FAR

;NOTE:	IF THE ONLY REQUESTS AVAILABLE ARE BETWEEN THE CURRENT UNIT
;	POSITION AND THE MINIMUM LATENCY THRESHOLD, THE LATENCY OF
;	THE CLOSEST SUCH REQUEST IS RETURNED PLUS ONE REVOLUTION.
;	THIS ELIMINATES THE SPECIAL CASE CHECKS IN SCHLTM.

RP4LTM:	JUMPE T1,RP4LT6		;COMMAND STACKING COMPUTATION?
	HRRZ T2,RP.USU(P3)	;GET TIME PER 1/64. SECTOR UNIT
	IDIVI T1,(T2)		;CONVERT TIME TO UNITS
	HRLO P4,T1		;SAVE AND INITIALIZE CURRENT POSITION
	MOVEI T4,3		;MAXIMUM NUMBER OF TIMES TO READ POSITION
RP4LT1:	MOVSI T2,DO.LA		;READ LOOKAHEAD REGISTER
	CALL RDREG		; ...
	ANDI T1,3777		;MASK UNDEFINED BITS
	CAIN T1,(P4)		;SAME AS LAST READING?
	JRST RP4LT2		;YES - USE IT
	HRR P4,T1		;NO - SAVE THIS ONE
	SOJG T4,RP4LT1		;LOOP
RP4LT2:	MOVE T3,P4		;SAVE MIN LATENCY,,CURRENT POSITION
	HRROI T4,UDBTWQ(P3)	;INITIALIZE BEST LATENCY,,PREDECESSOR
	TLNN T3,-1		;IF STACKING,
	HRR T4,IRBLNK(T4)	;EXCLUDE HEAD
	SETZB P4,P5		;INITIALIZE CURRENT AND BEST IORBS
RP4LT3:	HRRZ T1,T4		;NEED ADDRESS
	HRRZ P4,IRBLNK(T1)	;SET CURRENT FROM PREDECESSOR
	JUMPE P4,RP4LT5		;END OF LIST?
	CALL PHYBLK		;NO - GET UNIT RELATIVE ADDRESS
	TXZ T2,IRBPAD		;REMOVE PHYSICAL ADDRESSING BIT
	MOVE T1,T2		;COPY
	HRRZ T2,RP.SCL(P3)	;GET SECTOR PER CYLINDER
	IDIVI T1,(T2)		;GET SECTOR WITHIN CYLINDER
	MOVE T1,T2		;COPY
	HRRZ T2,RP.SSF(P3)	;GET SECTORS PER SURFACE
	IDIVI T1,(T2)		;GET SECTOR WITHIN SURFACE
	MOVE T1,T2		;AS REMAINDER
	LSH T1,^D6		;CONVERT TO 1/64. SECTOR UNITS
	SUBI T1,(T3)		;COMPUTE DISTANCE TO THIS REQUEST
	SKIPGE T1		;IF NEGATIVE,
	ADD T1,RP.USF(P3)	;GET ABSOLUTE DISTANCE
	HLRZ T2,T3		;GET MINIMUM LATENCY SPECIFIED
	CAMGE T1,T2		;IS THIS REQUEST GREATER?
	ADD T1,RP.USF(P3)	;NO - MUST DO IT ONE REVOLUTION LATER
	HLRZ T2,T4		;COMPARE TO BEST LATENCY SO FAR
	CAMN P4,UDBCHB(P3)	;CHECK FOR HOMNBLOCK IT IS BEST
	JRST RP4HMB
	CAML T1,T2		;LESS?
	JRST RP4LT4		;NO - DO NEXT REQUEST
RP4HMB: HRL T4,T1		;YES - SAVE AS CURRENT BEST LAT
	MOVE P5,P4		;COPY CURRENT IORB
	HRL P5,T4		;COPY PREDECESSOR IORB
	JUMPE T1,RP4LT5		;IF ZERO LATENCY, CAN DO NO BETTER
	MOVEI P6,^D7		;RESET NUMBER OF REQUESTS TO SCAN
RP4LT4:	HRR T4,P4		;PREDECESSOR BECOMES CURRENT IORB
	CAME P4,UDBCHB(P3)	;IS THE THE HOMEBLOCK IORB?
	SOJG P6,RP4LT3		;LOOK AT NEXT IORB
RP4LT5:	JUMPE P5,RP4LTE		;IF NONE FOUND, ERROR
	HLRZ T1,T4		;GET BEST LATENCY FOUND
	HRRZ T2,RP.USU(P3)	;GET USEC PER UNIT
	IMULI T1,(T2)		;CONVERT BACK TO MICROSECONDS
	HLRZ T2,P5		;GET PREDECESSOR TO BEST IORB
	HRRZ T3,P5		;GET BEST IORB
	RETSKP

;HERE WHEN COMMAND STACKING COMPUTATION IS REQUESTED

RP4LT6:	MOVE T1,UDBPS2(P3)	;GET CURRENT SECTOR
	CAMN T1,RP.LST(P3)	;LAST PAGE ON A CYLINDER?
	RET			;YES - DONT
	ADDI T1,4		;ASSUME DISK IS AT THE NEXT PAGE
	HRRZ T2,RP.SSF(P3)	;GET SECTORS PER SURFACE
	IDIVI T1,(T2)		;COMPUTE ROTATIONAL POSITION
	LSH T2,^D6		;CONVERT TO HWFMT
	MOVE P4,T2		;COPY RESULT
	JRST RP4LT2		;JOIN COMMON CODE

RP4LTE:	BUG.(HLT,RP4LTF,PHYP4,SOFT,<PHYP4 - Failed to find TWQ entry at RP4LTM>,,<

Cause:	The routine RP4LTM was called to find the entry on the transfer
	wait queue that had the best latency.  After searching the
	queue, no IORB was found to return.  This routine should only
	be called when the transfer wait queue is nonempty.
>)
	RET
	SUBTTL POSTION REQUEST

;C(P4) := IORB , C(P3) := UDB , C(P1) := CDB

RP4POS:	HLRZ Q1,RP4FCN+IRFSEK	;GET OP CODE FOR SEEK
	CALL RP4CON		;SEE IF DRIVE THERE AND CONNECT
	 RET			;ERROR RETURN
	HRLI T2,DO.DC		;C(T2) := DESIRED CYLINDER
RP4MOV:	PUSH P,T2		;SAVE ARGUMENT
	MOVSI T2,DO.OF		;CLEAR OFFSET REGISTER
	CALL WTREG		;...
	MOVSI T2,DO.DA		;CLEAR POSSIBLE ILLEGAL
	CALL WTREG		; SECTOR FROM DESIRED ADDRESS
	POP P,T2		;RESTORE DESIRED CYLINDER
	JRST CHSTRT		;START CHANNEL & SKIP RETURN
	SUBTTL INTERRUPT PROCESSING

;ROUTINE TO HANDLE ATTENTION INTERRUPTS

RP4ATN:	SKIPE UDBDSN(P3)	;CHECK FOR SERIAL NUMBER
	IFSKP.
	   CALL RP4DSN		;(P1,P3/) NONE THERE, GO GET IT
	   CALL PHYDUA		;(P3/)	CHECK FOR ANOTHER PATH
	ENDIF.
	MOVSI T2,DO.SR		;SET TO READ STATUS REGISTER
	CALL RDREG		;...
	MOVX T3,US.PGM!US.2PT
	IORM T3,UDBSTS(P3)	;FIRST FORCE IT TO LOOK LIKE DUAL PORT
	TRNN T1,DS.PGM		;CHECK FOR DUAL PORT
	ANDCAM T3,UDBSTS(P3)	;MAKE IT SINGLE PORT
	TRNN T1,DS.MOL		;MEDIA ON-LINE?
	JRST RP4OFL		;NO - OFF-LINE INTERRUPT.
	MOVX T3,U1.VV		;YES, CHECK FOR VALID VOLUME
	TDNN T3,UDBST1(P3)	;IF NOT VALID THEN SET IT NO MATTER WHAT
	TRNN T1,DS.VV		;YES - VOLUME VALID?
	JRST RP4ATF		;NO - FREE INTERRUPT (ON-LINE)
	MOVE T2,UDBSTS(P3)	;GET STATUS OF DRIVE
	TLNN T2,(US.ACT)	;EXPECTING AN INTERRUPT FROM THIS DRIVE?
	JRST RP4ATU		;NO - MUST BE -11 LET GO OF IT
	CALL SETIRB		;GET ACTIVE IORB(PRESERVES T1)
	SKIPE T2,UDBERR(P3)	;IN ERROR RECOVERY?
	JRST ERRATN		;YES, HAVE TO USE A DISPATCH ADDRESS
	TRNE T1,DS.ERR		;NO, ERROR?
	JRST RP4ATE		;YES

;HERE ON INTERRUPT WITH NO ERRORS
RP4ATD:	AOS UDBSEK(P3)		;NOTE SEEK
	PUSH P,Q1		;PRESERVE REG
	SKIPE UDBERR(P3)	;IF IN ERROR RECOVERY AND JUST WON,
	CALL SFTSEK		;READ THE REGISTERS NOW - AT END
	 JFCL
	POP P,Q1		;RECOVER Q1
	TLO Q1,-1		;SET FLAG FOR UPPER LEVEL
ATNX0P:	CALL PHYPDN		;INFORM PHYSIO
ATNX0:	MOVEI P4,0		;NO SPECIFIC IORB TO RETURN
ATNXIT:	MOVEI T2,1		;POSITION BIT
	HRRZ T1,UDBAKA(P3)	;GET CURRENT CHANNEL ADDRESS
	ROT T2,(T1)		;THE BIT
	HRLI T2,DO.AS		;BUILD DATAO
	CALLRET WTREG		;WRITE ATTENTION SUMMARY REGISTER


RP4ATU:	MOVX T1,US.OFS!US.OIR!US.OMS!US.RTY ;DEVICE IS NOW OURS AGAIN
	ANDCAM T1,UDBSTS(P3)	;SO MAKE UNIT ONLINE AGAIN
	CALL RP4CLR		;CLEAR DRIVE JUST INCASE
	TLO Q1,-1		;SET TO RESTART I/O
	HRRZ T1,UDBTWQ(P3)	;IS TWQ EMPTY?
	JUMPN T1,ATNXIT		;NO, JUST EXIT. PHYSIO WILL RESTART
	HRRZ T1,UDBPWQ(P3)	;CHECK FOR POSITION REQUEST
	JUMPN T1,ATNX0P		;YES DECLARE POSITION DONE
	CALL RP4DIS		;RELEASE INCASE NO REQUEST AVAILABLE
	JRST ATNXIT		;JUST EXIT AND TRANSFER WILL RESTART


RP4ATE:	HRRZ T3,UDBAKA(P3)	;ERROR - GET UNIT #
	CAMN T3,CDBXFR(P1)	;SAME UNIT AS TRANSFER?
	JRST ATNX0		;YES - ERROR ON XFERING UNIT (IGNORE)
				; WILL HANDLE LATER IN XFER INTERRUPT CODE

;HERE IF AN ERROR ON A NON-TRANSFERRING DRIVE
	CALL RP4RDR		;READ ALL DRIVE REGISTERS
	MOVE T1,RP.REG+DR.ST(P3) ;GET STATUS REGISTER
	MOVE T2,RP.REG+DR.ER3(P3) ;GET ERROR REGISTER 3
	MOVE T3,RP.REG+DR.ER(P3) ;GET ERROR REGISTER
	TRNE T2,E3.SKI		;SEEK INCOMPLETE,
	TRNE T3,ER.UNS		; AND NOT UNSAFE?
	JRST RP4AT2		;NO - JUST SEEK ERROR
	TRNN T1,DS.DRY		;YES, DRIVE READY?
	JRST ATNX0		;NO - UNIT STILL DOING RECAL, WAIT
				;RECALIBRATE DONE, FALL INTO POSITIONING ERROR CODE

RP4AT2:	MOVSI T1,(ES.POS)	;INDICATE A POSITION ERROR
	IORM T1,UDBERR(P3)	;IN RECOVERY STATE WORD
	CALL RP4CDA		;CLEAR DA & DC
	MOVSI T1,(IS.ERR)	;FLAG ERROR IN IORB
	IORM T1,IRBSTS(P4)	; ...
	TLO P4,-1		;SET SEEK ERROR FLAG
	CALLRET RP4CLR		;RESET DEVICE AND RETURN TO CHANNEL


;ROUTINE TO GET THE DRIVE SERIAL NUMBER (AND CHECK FOR DUAL-PORTED TO US)
;ACCEPTS:	P1/ CDB
;		P3/ UDB
;RETURNS:	+1

RP4DSN:	MOVSI T2,DO.SN		;GET REGISTER
	CALL RDREG		;(T2,P1,P3/T1) READ SERIAL NUMBER
	MOVE T2,T1		;POSITION LOW-ORDER DSN WORD
	LDB T4,USYTYP		;NO, GET DRIVE TYPE
	MOVE T1,T4		;MAKE HIGH-ORDER DSN WORD
	IORI T1,400		;MAKE IT CLASS 144 DISK
	LSH T1,20		;PUT IT IN RIGHT POSITION
	CALL SETDSN		;(T1,T2,P3/) SET DSN
	RET
;HERE ON FREE INTERRUPT (PACK CAME ON LINE)
RP4ATF:	CALL RP4DSN		;(P1,P3/) GET THE DRIVE SERIAL NUMBER
	CALL PHYDUA		;(P3) CHECK FOR ANOTHER PATH
	MOVSI T1,(US.CHB)	;NEED TO CHECK HOME BLOCKS
	SKIPL UDBSTR(P3)	; ...
	TXO T1,US.OIR!US.OMS	;need operator intervention
	IORM T1,UDBSTS(P3)	;MUST CHECK HOME BLOCKS
	MOVX T1,US.ACT!US.POS	;RESET POSITION BITS
	ANDCAM T1,UDBSTS(P3)	;IN THE UDB
	MOVX T1,U1.VV		;SET VALID VLOLUME BIT
	ANDCAM T1,UDBST1(P3)
	CALL RP4UP		;ISSUE PACK ACK
	TLO Q1,-1		;SET FLAG FOR UPPER LEVEL
	JRST PHYONL		;INFORM PHYSIO

;HERE ON ATTENTION INTERRUPT IF DRIVE IS IN ERROR RECOVERY
ERRATN:	HRRZ T1,UDBERR(P3)	;GET FUNCTION BEING PERFORMED
	SKIPL T1,RP4FCN(T1)	;GET DISPATCH ADDRESS
	JRST [	HRRZS T1,T1	;RIGHT HALF ONLY
		JRST (T1)]	;GO PROCESS INTERRUPT
	HRRZ T3,UDBAKA(P3)	;GET THE UNIT # OF DRIVE IN ERROR
	CAME T3,CDBXFR(P1)	;IS IT THE TRANSFERRING DRIVE?
	CALL RP4CLR		;CLEAR DRIVE AND BACK TO CHANNEL
	JRST ATNX0		;DATA TRANSFER FUNCTION - DEFER


;HERE FOR INTERRUPTS OTHER THAN ATTENTION
RP4INT:	CALL SETIRB		;SET UP IORB INTO P4
	HRRZ T1,UDBERR(P3)	;GET FUNCTION IF ERR RECOV
	SKIPN T1		;IN ERROR RECOVERY?
	LDB T1,IRYFCN		;GET FCN CODE
	CAIG T1,MXRP4F		;CHECK IF LEGAL
	SKIPA
	CAIL T1,MNRP4V
	SKIPL T1,RP4FCN(T1)	;GET TABLE ENTRY
	BUG.(HLT,RP4ILF,PHYP4,HARD,<PHYP4 - Illegal function on interrupt>,,<

Cause:	The routine RP4INT was called by the channel routine to handle
	a non-attention interrupt.  The function code for the IORB that
	I/O was done for was either illegal, or else the function was
	one which did not transfer data.  Functions which do not transfer
	data should give an attention interrupt.
>)
	HRRZS T1,T1
	JRST 0(T1)		;THE LEAP OF FAITH
	SUBTTL READ/WRITE INTERRUPTS

RP4RED:
RP4WRT:	MOVSI T2,DO.OF		;CLEAR ECI
	TRNE T1,DXES		; IF THEY WERE ON (NEXT TO LAST TRY)
	CALL WTREG
	MOVSI T2,DO.SR		;READ THE STATUS REGISTER
	CALL RDREG		;...
	TRNN T1,DS.ERR		;ANY ERROR?
	CALL CKERR		;CHECK CHANNEL ERRORS ALSO
	 JRST RP4DER		;YES - GO DECODE
	CALL PHYCNT		;GET LENGTH OF TRANSFER
	LSH T1,-7		;AS BLOCKS
	LDB T2,IRYFCN		;GET FUNCTION CODE
	CAIE T2,IRFRED
	CAIN T2,IRFRVC		;READ?
	JRST [	ADDM T1,UDBRED(P3) ;YES
		CAIN T2,IRFRED	;IS IT A READ FUNCTION?
         	 AOS UDBRCT(P3)	;YES SO UPDATE READ COUNT
		CAIN T2,IRFRVC	;IS IT A SKIP READ FUNCTION?
		 AOS UDBRVC(P3)	;YES SO UPDATE SKIP READ COUNT
		JRST RP4WR1]
	ADDM T1,UDBWRT(P3)	; YES
	AOS UDBWCT(P3)		;UPDATE WRITE COUNT
RP4WR1:	SKIPE UDBERR(P3)	;WAS DRIVE BEING ERROR-RECOVERED?
	CALL RP4RDR		;YES, READ REGISTERS AT SUCCESS
	MOVSI T1,(CS.AC2)	;IF STACKED COMMAND ACTIVE
	TDNN T1,CDBSTS(P1)	;DONT RELEASE PORT
	CALL RP4DIS		;DISCONNECT IF DUAL PORT DRIVE
	RETSKP

;HERE IF ERROR DETECTED ON DATA XFER

RP4DER:	CALL RP4RDR		;READ ALL DRIVE REGISTERS
				;AND FALL INTO RP4IER

;HERE ON ALL INTERRUPT DETECTED TRANSFER ERRORS

RP4IER:	MOVSI T1,(IS.ERR)
	IORM T1,IRBSTS(P4)
	CALL RP4CLR		;CLEAR THE DRIVE
	RET

;HERE ON INTERRUPT AFTER LAST PART OF XFER DONE (ECC FIXED 1ST PART)
RP4ECF:	MOVSI T2,DO.SR		;READ THE STATUS REGISTER
	CALL RDREG
	TRNE T1,DS.ERR		;ERROR?
	JRST RP4DER		;YES, GO HANDLE IT
	CALL RP4RDR		;GET REGISTERS AT SUCCESS
	CALL RP4IER		;NO, NOW TELL PHYSIO ABOUT THE ERROR
	MOVSI T1,(ES.ECC)	;INDICATE AN ECC ERROR
	IORM T1,UDBERR(P3)	; IN THE ERROR WORD
	RET
	SUBTTL ERROR RECOVERY CODE, ENTERED BY PHYSIO ON ERROR
REPEAT 0,<
ENTERED BY PHYSIO WHEN IS.ERR IS ON IN THE IORB, WITH UDBERP SET UP.
ON THE FIRST ERROR THE STATUS WILL BE READ INTO THE ERROR BLOCK
ERROR RECOVERY WILL BE ATTEMPTED, AND A NON-SKIP RETURN TO PHYSIO
INDICATES THAT ERROR RECOVERY IS IN PROGRESS.
A SKIP-RETURN INDICATES THAT ERROR RECOVERY IS DONE (HARD ERROR)

IF ENTERED BY PHYSIO WITH IS.ERR OFF IN THE IORB, JUST READ THE FINAL
STATUS (SOFT, SO WE RECOVERED) INTO THE ERROR BLOCK, AND SKIP-RETURN
>

RP4ERR:	SAVEQ			;SAVE ACCUMULATORS
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK (IF PRESENT)
	MOVE Q2,UDBSTS(P3)	;Q2 CONTAINS STATUS,
	AOS Q3,UDBERC(P3)	;AND Q3 HAS THE RETRY COUNTER
	SOJN Q3,NOT1ST		;GO IF NOT THE FIRST TIME

;HERE ON FIRST ERROR, SAVE DRIVE AND CHANNEL REGISTERS
	JUMPE Q1,ERR1		;IF NO ERROR BLOCK, CANT SAVE REGISTERS
	HRLI T1,RP.REG(P3)	;BUILD BLT POINTER
	HRRI T1,SEBDAT+MB%REG(Q1) ;...
	BLT T1,SEBDAT+MB%REG+17(Q1) ;COPY REGISTERS
	MOVE T1,Q1		;COPY ERROR BLOCK
	MOVE T2,[-NEDAT,,EDAT]	;POINTER TO CONTROL TABLE
	CALL SEBCPY		;COPY DATA
	 JFCL
	CALL PHYBLK		;GET LOGICAL ADDRESS
	TXZ T2,IRBPAD		;REMOVE PHYSICAL ADDRESSING BIT
	MOVEM T2,SEBDAT+MB%LOC(Q1) ;SAVE

ERR1:	TLNN Q2,(US.POS)	;IF THIS IS A READ,
	LDB T1,IRYFCN		; AND AND THE DRIVE IS OFFSET,
	MOVE T2,RP.REG+DR.OF(P3) ; DUE TO A PREVIOUS SECTOR THAT WAS
	CAIE T1,IRFRVC
	CAIN T1,IRFRED		 ; RECOVERED AT OFFSET
	TRNN T2,377		 ; FOR WHICH WE DIDNT RETURN TO CENTERLINE,
	JRST NOT1ST
	MOVEI Q3,RTCNDX		; THEN RETURN TO CENTERLINE NOW
	JRST RP4OFS		; BEFORE "REAL" ERROR RECOVERY IS ATTEMPTED

NOT1ST:	MOVSI T1,(IS.IER)	;ERROR RECOVERY INHIBITED?
	TDNE T1,IRBSTS(P4)	; ??
	JRST HRDERR		;YES - ALL ERRORS ARE HARD
	MOVE T1,RP.REG+DR.ER(P3) ;GET THE ERROR REGISTER
	TRNE T1,ER.UNS		;UNSAFE?
	JRST [CALL SETUNS	;YES, MARK THE DRIVE UNSAFE
		JRST HRDERR]	;AND CALL IT A HARD ERROR
	MOVE T1,IRBSTS(P4)	;NO, ERROR BIT ON?
	TLNN T1,(IS.ERR)
	JRST [	TLNE Q2,(US.POS) ;SEEK ERROR?
		JRST SFTSEK	;YES
		LDB T1,IRYFCN	;SOFT ERROR, GET OPERATION
		CAIE T1,IRFRVC
		CAIN T1,IRFRED	;READ?
		AOS UDBSRE(P3)	;YES
		CAIE T1,IRFWVC
		CAIN T1,IRFWRT	;WRITE?
		AOS UDBSWE(P3)	;YES
		JRST RDFINL]	;GO READ REGISTERS
	MOVE T1,UDBERR(P3)	;YES, GET BITS FROM ERR WORD
	MOVE T2,RP.REG+DR.ST(P3)	;GET STATUS REGISTER
	TLNE T1,(ES.ECC)	;ECC RECOVERED FIRST PART?
	TRNE T2,DS.ERR		;WITH NO ERRORS
	SKIPA
	JRST RP4ECD		;YES, WE'RE NOW FINISHED
	TLNN Q2,(US.POS)	;NO, POSITIONING ERROR?
	AOJA Q3,ERXFER		;NO
	MOVSI T1,(ES.POS)	;YES, LIGHT A BIT
	IORM T1,UDBERR(P3)
	MOVSI T1,(IS.DVE)	;INDICATE DEVICE ERROR
	IORM T1,IRBSTS(P4)	; ...
	CAIL Q3,POSCNT		;TRIED ENOUGH?
	JRST HRDSEK		;YES, IT'S HARD
	JRST RP4RCL		;NO, RECALIBRATE AND TRY AGAIN

;TABLE OF DATA TO COPY AT INITIAL ERROR RECOVERY TIME

EDAT:	SEBPTR MB%CNI,SBTWD,RP.CNI(P3) ;CONI
	SEBPTR MB%D1I,SBTWD,RP.CRC(P3) ;TCR
	SEBPTR MB%D2I,SBTWD,RP.DBF(P3) ;BAR/DBF
	SEBPTR MB%CS0,SBTWD,CDBCS0(P1) ;CHANNEL STATUS 0
	SEBPTR MB%CS1,SBTWD,CDBCS1(P1) ;CHANNEL STATUS 1
	SEBPTR MB%CS2,SBTWD,CDBCS2(P1) ;CHANNEL STATUS 2
	SEBPTR MB%CC1,SBTWD,CDBCC1(P1) ;CCW 1
	SEBPTR MB%CC2,SBTWD,CDBCC2(P1) ;CCW 2
	SEBPTR MB%ICR,SBTWD,CDBICR(P1) ;INITIAL CONTROL REGISTER

NEDAT=.-EDAT
;HERE ON ERROR OF AN TRANSFERRING UNIT
ERXFER:	MOVE T1,RP.REG+DR.ER(P3) ;GET ERROR REGISTER
	TRNE T1,ER.DCK		;DATA CHECK,
	TRNE T1,ER.ECH		;AND NOT ECC HARD?
	SKIPA T2,UDBERR(P3)	;NO
	JRST ERRECC		;YES, ECC CAN FIX IT UP
	TRNN T1,ER.OFS		;ERROR FOR WHICH OFFSET MIGHT WIN?
	TLNE T2,(ES.DAT!ES.HDR!ES.FER)
	JRST DATERR		;YES, GO TO OFFSET CODE
	LDB T2,USYTYP		;MAYBE. GET DRIVE TYPE
	CAIN T2,.UTRP7		;IS IT AN RP07?
	TRNN T1,ER.OPI!ER.DTE 	;YES. OP INCOMPLETE OR DRIVE TIMING ERROR?
	JRST DEVERR		;NO, DEVICE ERROR
	JRST DATERR		;YES, THIS IS REALLY A HEADER ERROR.
ERRECC:	MOVE T1,RP.REG+DR.OF(P3) ;FIRST CHECK IF ECC WAS ON
	TRNE T1,OF.ECI		;IF NOT, DONT EVEN LOOK AT
	JRST DATERR		;ECC REGS
	LDB T1,IRYFCN		;GET THE IORB FUNCTION
	CAIN T1,IRFRVC		;IS IT READ VERIFY?
	 JRST DATERR		;YES...CAN NOT USE ECC THEN
	MOVE T1,UDBERC(P3)	;GET RETRY COUNT
	CAIG T1,3		;TIME TO TRY ECC YET?
	JRST DATERR		;NO
	MOVE Q3,RP.REG+DR.ECP(P3) ;GET ECC POSITION
	SOJL Q3,DATERR		;LOSE IF POSITION = 0
	CAIL Q3,^D36*^D128	;IS POSITION SANE?
	JRST DATERR		;NO - ACT LIKE ECH

;HERE ON ECC-CORRECTABLE ERROR
	MOVSI T1,(ES.ECC)	;FLAG AS ECC
	IORM T1,UDBERR(P3)	; ...
	EXCH P4,Q3		;MOVE POSITION TO BETTER AC
	IDIVI P4,^D36		;COMPUTE POSITION OF BURST
	MOVE T4,RP.REG+DR.ECB(P3) ;GET ERROR BURST
	EXCH P5,T4
	SETZ P6,		;POSITION THE MASK
	ROTC P5,(T4)
	EXCH P4,Q3		;RESTORE QUOTIENT
	CALL ECCADR		;GET START OF LAST SECTOR TRANSFERRED
	ADDI T1,(Q3)		;POINT TO FIRST ERROR WORD
	CALL PHYMOV		;GET THE DATA WORD
	MOVSS P5		;APPLY ECC MASK TO 1ST PART
	XOR T2,P5
	CALL PHYSTO		;AND STORE THE ANSWER
	ADDI T1,1		;POINT TO 2ND ERROR WORD
	CALL PHYMOV		;GET IT
	MOVSS P6		;FIX IT
	XOR T2,P6
	CALL PHYSTO		;AND STORE IT
	CALL ECCUCL		;UPDATE CCW LIST, RETURN NO OF WORDS TRANSFERRED OK
	 JRST RP4ECD		;DONE - ERROR WAS IN LAST BLOCK (OF 4)
	LSH T1,-7		;NOT DONE - NUMBER OF BLOCKS WE READ
	HRLM T1,UDBERP(P3)	;SAVE TO COMPUTE 1ST BLOCK OF XFER
	MOVEI T1,ECFNDX		;INDICATE READING LAST PART
	CALL SURTRY		; WHERE ECC FIXED UP THE FIRST PART
	CALL RP4CLR		;MAKE SURE THE DRIVE IS READY
	JRST RETRY		;GO START THE XFER

;HERE WHENN ECC IS DONE (LAST BLOCK OF PAGE OR AFTER THE REST IS READ)
RP4ECD:	MOVSI T1,(ES.ECC)	;INDICATE ECC-CORRECTED ERROR
	IORM T1,UDBERR(P3)
	MOVSI T1,(IS.ERR)	;CLEAR ERROR BIT, SOFT ERROR
	ANDCAM T1,IRBSTS(P4)	; ...
	AOS UDBSRE(P3)		;NOTE SOFT READ ERROR
	JRST RDFINL		;CLEAN UP AND EXIT
;HERE ON ERROR WHICH MIGHT BE RECOVERED BY OFFSET
DATERR:	MOVE T1,RP.REG+DR.ER(P3) ;GET ERROR REGISTER AGAIN
	SETZ T2,
	TRNE T1,ER.DCK		;DATA ERROR?
	TLO T2,(ES.DAT)		;YES
	TRNE T1,ER.FER		;FORMAT ERROR?
	TLO T2,(ES.FER)		;YES
	TRNE T1,ER.HCE!ER.CRC!ER.OPI!ER.DTE ;HEADER ERROR?
	TLO T2,(ES.HDR)		;YES
	IORM T2,UDBERR(P3)	;LIGHT ERROR BIT IN ERROR WORD
	MOVSI T2,(IS.DTE)	;INDICATE DATA ERROR
	IORM T2,IRBSTS(P4)	; ...
	MOVE Q3,UDBERC(P3)	;GET RETRY COUNTER
	SUBI Q3,^D16		;LESS THAN 16 RETRIES?
	JUMPL Q3,RETRY0		;IF SO, JUST TRY ONCE MORE
	CAIL Q3,^D13		;NO, TRIED ENOUGH?
	JRST HRDTER		;YES, FINISH UP
	TRNE Q3,1		;NO, TIME TO OFFSET?
	JRST RETRY		;NO, TRY 2ND TIME AT THIS OFFSET
	LSH Q3,-1		;YES, COMPUTE OFFSET VALUE
RP4OFS:	MOVEI T1,OFSNDX		;INDICATE AN OFFSET
	JRST RP4EPS		;AND GO DO IT
;HERE ON AN ERROR WHICH OFFSET WONT DO US ANY GOOD ON
DEVERR:	MOVSI T1,(ES.DEV)	;INDICATE DEVICE ERROR
	IORM T1,UDBERR(P3)
	MOVSI T1,(IS.DVE)	;INDICATE DEVICE ERROR
	IORM T1,IRBSTS(P4)	; ...
	EXCH P1,P5		;TEMP
	IDIVI Q3,DEVCNT		;RETRY COUNT/NO OF TIMES TO RETRY
	EXCH P1,P5		;TEMP
	CAILE Q3,RCLCNT		;RETRIED ENOUGH?
	JRST DEVER1		;YES, FINISH UP
	JUMPN P5,RETRY0		;NO, RETRY IF HAVENT TRIED (DEVCNT) TIMES
	JRST RP4RCL		;TRIED ENOUGH - RECALIBRATE AND TRY AGAIN

DEVER1:	SKIPA Q3,P5		;Q3= 0 (TRY WITH DXES) OR 1 (LAST TIME)

HRDTER:	SUBI Q3,^D13		; OR 2 (GIVE UP)
LSTERS:	JUMPG Q3,LSTER1		;TRY FOR AS MUCH AS WE CAN GET?
	LDB T2,IRYFCN		;YES, GET FUNCTION
	CAIE T2,IRFRED		;IF NOT PLAIN VANILLA READ OR WRITE,
	CAIN T2,IRFWRT
	JRST LSTER2		;(READ OR WRITE HEADERS AND DATA)
	CAIE T2,IRFRVC
	CAIN T2,IRFWVC
	JRST LSTER2
	JRST HRDERR		;THEN FORGET IT
LSTER2:	MOVEI T1,DXRNDX		;SET UP TO READ/WRITE
	CAIE T2,IRFRED		;WITH DXES AND ECI ON
	MOVEI T1,DXWNDX
	JRST RETRY1		;GO GET AS MUCH DONE AS POSSIBLE

LSTER1:	SOJE Q3,RETRY0		;1 LAST TIME IF Q3=1

;HERE IF THE ERROR IS HARD
HRDERR:	MOVSI T1,(IS.NRT!IS.DVE) ;INDICATE HARD ERROR
	IORM T1,IRBSTS(P4)	; ...
	MOVSI T1,(ES.HRD)	;LIGHT HARD-ERROR BIT
	IORM T1,UDBERR(P3)	; IN THE ERROR WORD
	LDB T1,IRYFCN		;GET FUNCTION
	CAIE T1,IRFRVC
	CAIN T1,IRFRED		;READ?
	AOS UDBHRE(P3)		;ACCOUNT
	CAIE T1,IRFWVC
	CAIN T1,IRFWRT		;WRITE?
	AOS UDBHWE(P3)		;YES

;HERE TO READ THE DRIVE REGISTERS AT END (SOFT OR HARD)
RDFINL:	CALL RDRFIN		;READ REGISTERS
ALLDON:	HRLZI T2,DO.OF	;CLEAR OFFSET REG AND ECI
	CALL WTREG		; ...
	CALL RP4DIS		;DISCONNECT IF DUAL PORT DRIVE
	RETSKP			;TELL PHYSIO WE SHOULDNT TRY ANY MORE

;HERE ON A SOFT SEEK ERROR

SFTSEK:	AOS UDBSPE(P3)		;ACCOUNT POSITION ERROR
	CALL RDRFIN		;READ FINAL REGISTERS
	RETSKP

;HERE ON A HARD SEEK ERROR

HRDSEK:	AOS UDBHPE(P3)		;NOTE HARD POSITION ERROR
	MOVSI T1,(ES.HRD)	; ...
	IORM T1,UDBERR(P3)
	MOVSI T1,(IS.NRT!IS.DVE)	;FLAG ERROR AS HARD
	IORM T1,IRBSTS(P4)	; ...
	CALL RDRFIN		;READ FINAL REGISTERS
	CALL RP4DIS		;DISCONNECT IF NEEDED
	RETSKP

RDRFIN:	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK AGAIN
	JUMPE Q1,R		;IF NO ERROR BLOCK, CANT SAVE INFORMATION
	MOVSI T1,-20		;20 DRIVE REGISTERS
	HRRI T1,RP.REG(P3)	;FROM THE UDB
	MOVEI T2,SEBDAT+MB%REG(Q1) ;INTO THE ERROR BLOCK
RDFIN1:	MOVE T3,(T1)		;GET A REGISTER
	HRLM T3,(T2)		;SAVE IN RH (FINAL STATUS)
	ADDI T2,1
	AOBJN T1,RDFIN1		;AND LOOP FOR MORE
	MOVE T1,RP.CNI(P3)	;GET CONI
	MOVEM T1,SEBDAT+MB%CIF(Q1) ;SAVE FINAL CONI
	MOVE T1,RP.CRC(P3)	;GET TCR FINAL
	MOVEM T1,SEBDAT+MB%D1F(Q1) ;SAVE
	MOVE T1,RP.DBF(P3)	;GET BAR
	MOVEM T1,SEBDAT+MB%D2F(Q1) ;AND SAVE
	RET
;HERE TO RECALIBRATE A DRIVE
RP4RCL:	MOVEI T1,RCLNDX		;RECALIBRATE
RP4EPS:	CALL SURTRY		;CLEAR THE ERROR BIT
	HRRZ Q1,UDBERR(P3)	;GET THE FUNCTION FOR RECOVERY
	HLRZ Q1,RP4FCN(Q1)	;GET THE HARDWARE BITS
	CALL RP4CON		;CONNECT TO THE DRIVE
	 JRST HRDERR		;ITS DOWN - LOSE
	SOS 0(P)		;CHSTRT WILL SKIP - RETURN
	MOVSI T2,DO.DC		;CLEAR DESIRED CYLINDER IF RECALIBRATE,
	CAIE Q1,DF.OFS
	JRST RP4MOV
	LDB T1,USYTYP		;GET DEVICE TYPE
	CAIN T1,.UTRP6		;RP06?
	SKIPA T2,OFSTB6(Q3)	;YES - GET SMALLER OFFSETS
	MOVE T2,OFSTBL(Q3)	;NO - GET DATAO OFFSET REGISTER FOR RP04,5
	CAIN T1,.UTRP7		;RP07?
	MOVE T2,OFSTB7(Q3)	;YES GET CORRECT OFFSETS
	CAIN T1,.UTRM3		;RM03?
	MOVE T2,OFSTB3(Q3)	;YES DIFFERENT OFFSETS
	TRNN T2,-1		;IF OFFSET = 0,
	MOVEI Q1,DF.RTC		;RETURN TO CENTERLINE
	JRST CHSTRT		;START THE OPERATION GOING AND RETURN TO PHYSIO

;HERE ON INTERRUPT AFTER A RECALIBRATE
ERRCLI:	CALL RP4CDA		;READIN PRESET TO CLEAR DRIVE
	MOVEI T1,SEKNDX		;START A SEEK GOING
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK IF PRESENT
	CALL RP4EPS
	SETZB P4,Q1		;INDICATE JUST DISMISS THE INTERRUPT
	RET			;AND RETURN


;HERE ON POSITION DONE INTERRUPT IF DRIVE IS IN ERROR RECOVERY
ERRPSI:	CALL RP4CDA		;READIN PRESET TO CLEAR THE DRIVE
	MOVSI T1,(US.POS)	;WAS ORIGINAL OP A SEEK?
	TDNE T1,UDBSTS(P3)	; ?
	JRST RP4ATD		; YES, SUCCESSFUL RECOVERY OF SEEK ERROR
RETRY0:	LDB T1,IRYFCN		;GET FUNCTION
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK IF PRESENT
RETRY1:	CALL SURTRY		;CLEAR ERROR BIT IN IDBSTS

;HERE TO RETRY A DATA-XFER OPERATION AFTER AN ERROR
RETRY:	HRRZ T1,CDBDSP(P1)	;GET CHANNEL DISPATCH
	CALL CDSSIO(T1)		;START IO
	 JRST HRDERR		; **TEMP** UNIT REFUSED RETRY - HARD ERROR
	SETZ P4,		;TELL PHYSIO TO DISMISS THE INTERRUPT
	RET			;AND WAIT FOR NEXT INTERRUPT

;ROUTINE TO SET UP FOR ERROR RETRY
SURTRY:	HRRM T1,UDBERR(P3)	;SAVE WHAT TO DO
	JRST SETIO		;CLEAR ERROR BITS FROM IORB
	SUBTTL MISC ROUTINES

;ROUTINE TO ISSUE PACK ACKNOWLEDGE AND RESET DRIVE

RP4UP:	MOVSI T2,DO.SR		;READ STATUS REGISTER
	CALL RDREG
	MOVE T4,UDBSTS(P3)	;GET STATUS
	TLZ T4,(US.PGM!US.WLK)	;CLEAR BITS FOR DUAL PORT AND WRITE LOCKED
	TRNE T1,DS.WRL		;WRITE LOCKED?
	TLO T4,(US.WLK)		;YES - INDICATE IN STATUS
	TRNE T1,DS.PGM		;DUAL PORT IN PROGRAMMABLE MODE?
	TLO T4,(US.PGM)		;YES - INDICATE IN UNIT STATUS
	MOVEM T4,UDBSTS(P3)	;SET UP STATUS AND CONFIGURATION
	CALL RP4CLR		;CLEAR DRIVE
	MOVEI T2,DF.ACK		;PACK ACKNOWLEDGE
	JRST WTREG		;DO IT

;ROUTINE TO CLEAR DRIVE

RP4CLR:	MOVEI T2,DF.CLR		;CLEAR FCN
	CALL WTREG		;...
	MOVSI T2,DO.AS		;GET ATTENTION SUMMARY REGISTER
	CALL RDREG		;...
	MOVEI T3,1		;BIT TO FIDDLE
	HRRZ T4,UDBAKA(P3)	;UNIT #
	LSH T3,(T4)		;FIDDLE TO CORRECT POSITION
	TDNN T1,T3		;ATTENTION NOW UP?
	RET			;NO - DONE
	MOVE T2,T3		;YES , ERROR CAN'T BE CLEARED
	HRLI T2,DO.AS
	JRST WTREG		;CLEAR BIT IN ATTENTION SUMMARY REGISTER

;ROUTINE TO READ RP04 REGISTERS ON ANY ERROR

RP4RDR:	SETZ T2,		;DRIVE NUMBER, START AT 0
	MOVSI T4,-20		;READ 20 REGISTERS
	HRRI T4,RP.REG(P3)	;STORE IN RP.REG
RP4RD1:	CALL RDREG		;READ A REGISTER
	MOVEM T1,(T4)		;SAVE IN UDB
	ADD T2,[10000,,]	;STEP TO NEXT REGISTER
	AOBJN T4,RP4RD1		;AND READ IT
	CALL ERRCNI		;DO CONI, DATAI'S OF RH
	MOVEM T1,RP.CNI(P3)	;SAVE CONI
	MOVEM T2,RP.CRC(P3)	;SAVE DATAI CRC
	MOVEM T3,RP.DBF(P3)	;SAVE DATAI DB
	RET			;ALL REGISTERS READ, RETURN

;ROUTINE TO CLEAR POSSIBLE GARBAGE FROM DRIVE REGISTERS

RP4CDA:	MOVEI T2,DF.PST		;ENSURE DA & DC DON'T GET LEFT
	JRST WTREG		;WITH FUNNY VALUES


;HERE TO MARK UNIT OFFLINE

RP4OFL:	ANDCAM T3,UDBSTS(P3)	;SET SINGLE PORT WHILE OFFLINE
	MOVX T3,U1.VV		;CLEAR VALID VOLUME FOR RP07'S
	IORM T3,UDBST1(P3)
	CALL PHYOFL		;SET OFF LINE
	JRST ATNXIT		;RETURN CLEARING ATTENTION
;FUNCTION TABLE

XFRFLG==1B0			;FUNCTION TRANSFERS DATA (MUST BE SIGN)
RP4FCN:	-1				;0 - ILLEGAL
	XFRFLG+<XWD DF.RED,RP4RED>	;1 - READ
	XFRFLG+<XWD DF.RDF,RP4RED>	;2 - READ FORMAT
	XFRFLG+<XWD DF.WRT,RP4WRT>	;3 - WRITE
	XFRFLG+<XWD DF.WTF,RP4WRT>	;4 - WRITE FORMAT
	DF.SEK,,ERRPSI		;5 - SEEK
SEKNDX==.-RP4FCN-1
MXEXFN==SEKNDX		;MAXIMUM EXTERNAL FUNCTION
	DF.RCL,,ERRCLI		;6 - RECALIBRATE
RCLNDX==.-RP4FCN-1
	XFRFLG+<XWD DF.RED+ERETRY,RP4ECF> ;7 - FINISH UP AFTER ECC FIXED PART OF XFER
ECFNDX==.-RP4FCN-1
	DF.OFS,,ERRPSI		;10 - OFFSET
OFSNDX==.-RP4FCN-1
	XFRFLG+<XWD DF.RED+DXES,RP4RED> ;11 - READ ALL DATA POSSIBLE
DXRNDX==.-RP4FCN-1
	XFRFLG+<XWD DF.WRT+DXES,RP4WRT> ;12 - WRITE ALL DATA POSSIBLE
DXWNDX==.-RP4FCN-1

MXRP4F==.-RP4FCN-1		;MAXIMUM LEGAL FCN
	0			;13 - NOT USED
	0			;14 - NOT USED
	0			;15 - NOT USED
MNRP4V==.-RP4FCN		; MIN LEGAL VALIDITY FUNCTION
	XFRFLG+<XWD DF.WRT,RP4WRT> ;16 - WRITE WITH VALIDITY CHECK
	XFRFLG+<XWD DF.RED,RP4RED> ;17 - READ WITH VALIDITY CHECK

;TABLE OF OFFSETS FOR RP04,5

OFSTBL:	DO.OF,,20		;OFFSET +400 MICRO INCHES
	DO.OF,,220		;-400
	DO.OF,,40		;+800
	DO.OF,,240		;-800
	DO.OF,,60		;+1200
	DO.OF,,260		;-1200
	DO.OF,,0		;RTC
RTCNDX==.-OFSTBL-1

;OFFSET TABLE FOR RP06
;NOTE: THIS TABLE MUST BE THE SAME LENGTH AS OFSTBL

OFSTB6:	DO.OF,,10		;+200 MICRO IN
	DO.OF,,210		;-200
	DO.OF,,20		;+400
	DO.OF,,220		;-400
	DO.OF,,30		;+600
	DO.OF,,230		;+600
	DO.OF,,0		;RTC

;...
;OFFSET TABLE FOR RM03
;NOTE: THIS TABLE MUST BE THE SAME LENGTH AS OFSTBL

OFSTB3:	DO.OF,,20		;+202 MICRO IN
	DO.OF,,220		;-200 MICRO IN
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC

;OFFSET TABLE FOR RP07
;NOTE: THIS TABLE MUST BE THE SAME LENGTH AS OFSTBL

OFSTB7:	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	DO.OF,,0		;RTC
	TNXEND			;FOR GOODNESS
	END