	.TITLE	IOSUBRAMS - NONPAGED RANDOM ACCESS MASS STORAGE I/O RELATED ROUTINES
	.IDENT	'X-8'
 
;
;****************************************************************************
;*									    *
;*  COPYRIGHT (c) 1978, 1980, 1982, 1984, 1991 BY			    *
;*  DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.		    *
;*  ALL RIGHTS RESERVED.						    *
;* 									    *
;*  THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED   *
;*  ONLY IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE   *
;*  INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER   *
;*  COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY   *
;*  OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE IS  HEREBY   *
;*  TRANSFERRED.							    *
;* 									    *
;*  THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE   *
;*  AND  SHOULD  NOT  BE  CONSTRUED AS  A COMMITMENT BY DIGITAL EQUIPMENT   *
;*  CORPORATION.							    *
;* 									    *
;*  DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS   *
;*  SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.		    *
;* 									    *
;*									    *
;****************************************************************************
;
; AUTHOR: D. N. CUTLER 16-MAR-1977
;
; MODIFIED BY:
;
;	X-8	GCE0412		Glenn C. Everhart	12-Feb-1996
;		Add in a check (which exists in the VAX version already)
;		that the RVNs are the same when combining map pointers in
;		MAPVBLK. Failure to do this has caused some customer file
;		corruption.
;	X-7	LSS0304		Leonard S. Szubowicz	 16-Feb-1994
;		Merge of edit OpenVMS AXP edit X-12.
;		Fix for CLD CFS.8499: Fix routine IOC$MAPVBLK to handle file
;		extents that are greater or equal to 4 Gbytes (2**24 blocks).
;		This implicit restriction wasn't noticed when the WCB COUNT
;		cell was promoted from a word to a longword.
;
;	X-6	VBK		Vaikom B. Krishnan	16-Jan-1992
;		Change IOC$MAPVBLK to account for the new WCB map pointer
;		format. The map pointers are now 12 bytes long and are of
;		form: a longword count, followed by a longword starting
;		LBN, followed by a byte RVN (the remaining bytes on this
;		longword are reserved for alignment).
;
;		This change is to support disks larger than 8 GB. Note that
;		with the new WCB map pointer format there is no need for
;		the fix described in X-5, so back out X-5.
;
;	X-5	VBK		Vaikom B. Krishnan	14-Nov-1991
;		Add support for disks larger than 8GB: such disks have
;		LBNs that are 4 bytes long (instead of the ususal 3 bytes)
;		in their window control blocks. The RVN field for map
;		pointers of such disks is zero because they cannot be 
;		part of volume sets.
;
;	 X-4	JFD0031		James F. Dunham		16-Sep-1991
;		JRL		John R. Lawson Jr.	09-March-1991
;		In support of Files-11 C/D controlled volume sets, detect
;		volume set members which are not currently MOUNT'ed, and force
;		a window-turn operation. This action will allow the ACP
;		controlling this volume set to correctly determine what action
;		to perform so that the IOC$MAPVBLK request can complete.
;
;	**** Re-adjust module ident to match VSC generation number ****
;
;	X-19	ACG0556		Andrew C. Goldstein,	25-Aug-1988  15:34
;		Don't set IRP$V_END_PAST_HWM in IOC$MAPVBLK. It's not
;		necessary and causes problems elsewhere.
;
;	X-17	SJF		Stu Farnham		27-Jul-1987
;		Make TBIS comply with SRM rev H
;
;	X-16	ACG0536		Andrew C. Goldstein,	8-Jan-1987  18:16
;		Fix magtape map failure path in IOC$MAPVBLK
;
;	X-15	WCT0015		Ward C. Travis		 6-Jan-1987
;		Update  outdated  SMPLOCK,  SMPUNLOCK uses  to  LOCK,
;		UNLOCK for SMP.
;
;	X-14	WMC0001		Wayne Cardoza		25-Nov-1986
;		Change JSB to BSBW.
;
;	X-13	ACG0525		Andrew C. Goldstein,	14-Aug-1986  17:49
;		Redesign highwater marking to handle concurrent I/O
;
;	X-12	RNG0012		Rod Gamache		24-Sep-1986
;		Go back to using FILSYS lock in IOC$MAPVBLK.
;
;	X-11	RNG0011		Rod Gamache		11-Sep-1986
;		Fix UNLOCK of FILSYS from previous edit.
;
;	X-10	SJF		Stu Farnham		9-Sep-1986
;		Temp workaround spinlock ordering prob. by having
;		IOC$MAPVBLK acquire SCS instead of FILSYS
;
;	X-9	SJF		Stu Farnham		3-Sep-1986
;		Synch IOC$MAPVBLK via FILSYS spinlock
;
;	X-7	SJF		Stu Farnham		6-Jul-1986
;		Fix merge errors
;
;	X-5	KL 0002		Keith Loepere		12-Jun-1986
;		Handle window turns for IO$_DSE.
;
;	X-4	SF04001		Stephen Fiorelli	31-May-1986
;		Fix broken branch.
;
;	X-3	KL 0001		Keith Loepere		14-Mar-1986
;		Add support for advancing the highwater mark.
;
;	X-1A3	RNG4003		Rod Gamache		11-Nov-1985
;		Conditionally release spinlock in IOC$MAPVBLK.
;
;	X-1A2	RNG4002		Rod Gamache		29-Oct-1985
;		Change FIPL's to FLCK's for second SMP baselevel.
;
;	V02-005	ACG0237		Andrew C. Goldstein,	9-Dec-1981  11:39
;		Add cathedral window support; check mapping against
;		file size in FCB
;
;	V02-004	GRR2004		Greg R. Robert,		14-Jun-1981
;		Added alternate entry point to IOC$CVTLOGPHY
;
;	V02-003	ACG0176		Andrew C. Goldstein,	6-Jun-1980  13:54
;		Redirect UCB to file's UCB on unsuccessful virtual map
;
;**
;
;
; NONPAGED RANDOM ACCESS MASS STORAGE I/O RELATED ROUTINES
;
; MACRO LIBRARY CALLS
;
 
	$DEVDEF				;DEFINE DEVICE CHARACTERISTIC BITS
	$DYNDEF				;DEFINE DATA STRUCTURE TYPE CODES
	$FCBDEF				;DEFINE FCB OFFSETS
	$IPLDEF				;DEFINE INTERRUPT PRIORITY LEVELS
	$IRPDEF				;DEFINE IRP OFFSETS
	$PRDEF				;DEFINE PROCESSOR REGISTERS
	$PTEDEF				;DEFINE PAGE TABLE ENTRY FIELDS
	$RVTDEF				;DEFINE RVT OFFSETS
	$SSDEF				;DEFINE I/O STATUS CODES
	$UCBDEF				;DEFINE UCB OFFSETS
	$VADEF				;DEFINE VIRTUAL ADDRESS FIELDS
	$WCBDEF				;DEFINE WCB OFFSETS

	.SBTTL	APPLY ECC CORRECTION
;+
; IOC$APPLYECC - APPLY ECC CORRECTION
;
; THIS ROUTINE IS CALLED TO APPLY AN ECC CORRECTION TO DATA THAT HAS BEEN
; TRANSFERED INTO MEMORY FROM A DISK DEVICE.
;
; INPUTS:
;
;	R0 = NUMBER OF BYTES OF DATA THAT WERE TRANSFERED UP TO, BUT NOT
;		INCLUDING, BLOCK TO BE CORRECTED (MUST BE A MULTIPLE OF 512
;		BYTES).
;	R5 = DEVICE UNIT UCB ADDRESS.
;
;	UCB$W_BCNT(R5) = LENGTH OF TRANSFER IN BYTES.
;	UCB$W_EC1(R5) = STARTING BIT NUMBER OF ERROR BURST.
;	UCB$W_EC2(R5) = EXCLUSIVE OR CORRECTION PATTERN.
;	UCB$L_SVAPTE(R5) = SYSTEM VIRTUAL ADDRESS OF PAGE TABLE THAT MAPS
;		THE TRANSFER.
;
; OUTPUTS:
;
;	THE CORRECTION PATTERN IS EXCLUSIVE OR'ED WITH THE DATA IN MEMORY
;	PROVIDING THE NECESSARY CORRECTION.
;
;	R3 IS PRESERVED ACROSS CALL.
;-
 
	DECLARE_PSECT	EXEC$NONPAGED_CODE
	UNIVERSAL_SYMBOL	IOC$APPLYECC
;IOC$APPLYECC::				;APPLY ECC CORRECTION
	PUSHR	#^M<R3,R4>		;SAVE REGISTERS
	MOVZWL	UCB$W_EC1(R5),R2	;GET STARTING BIT NUMBER OF ERROR BURST
	DECL	R2			;CONVERT TO RELATIVE BIT NUMBER
	BICB3	#^XF8,R2,R1		;ISOLATE PATTERN SHIFT COUNT
	DIVL	#8,R2			;CALCULATE RELATIVE BYTE OFFSET IN BLOCK
	ADDL	R0,R2			;CALCULATE RELATIVE OFFSET IN BUFFER
	MOVZWL	UCB$W_EC2(R5),R0	;GET EXCLUSIVE OR CORRECTION PATTERN
	ASHL	R1,R0,R0		;SHIFT PATTERN TO PROPER POSITION
	MOVL	#3,R4			;SET LOOP COUNT
10$:	CMPW	R2,UCB$W_BCNT(R5)	;BYTE OFFSET WITHIN RANGE?
	BGEQU	40$			;IF GEQU NO
	MOVZWL	UCB$W_BOFF(R5),R1	;GET BYTE OFFSET IN PAGE
	ADDL	R2,R1			;CALCULATE BYTE OFFSET OF TRANFER PTE
	ASHL	#-VA$S_BYTE,R1,R1	;CALCULATE LONGWORD OFFSET TO TRANSFER PTE
	MOVL	@UCB$L_SVAPTE(R5)[R1],R3 ;GET TRANSFER PTE
	BLSS	20$			;IF LSS VALID PTE
	BSBW	IOC$PTETOPFN		;CONVERT TO VALID PTE
20$:	MULL3	#4,UCB$L_SVPN(R5),R1	;CALCULATE BYTE OFFSET TO SYSTEM PTE
	PUSHL 	R2
	ASHL	#VA$S_BYTE-2,R1,R2	;CONVERT SVPN TO SYSTEM VIRTUAL ADDRESS
	BBSS	#VA$V_SYSTEM,R2,30$	;SET SYSTEM VIRTUAL ADDRESS BIT
30$:	INVALIDATE_TB	R2,-		;INVALIDATE TRANSLATION BUFFER
	 INST1=<INSV R3,#PTE$V_PFN,#PTE$S_PFN,@W^MMG$GL_SPTBASE[R1]>
					;MOVE TRANSFER PTE INTO SYSTEM PAGE TABLE
	ADDL3	UCB$W_BOFF(R5),(SP),R3	;CALCULATE BYTE OFFSET IN BLOCK
	INSV	R3,#VA$V_BYTE,#VA$S_BYTE,R2 ;INSERT BYTE OFFSET IN BLOCK
	XORB	R0,(R2)			;CORRECT MEMORY BYTE
	ASHL	#-8,R0,R0		;SHIFT NEXT CORRECTION BYTE INTO PLACE
	ADDL3	#1,(SP)+,R2		;UPDATE OFFSET IN BUFFER
	SOBGTR	R4,50$			;ANY MORE CORRECTIONS TO MAKE?
40$:	POPR	#^M<R3,R4>		;RESTORE REGISTERS
	BISW	#UCB$M_ECC,UCB$W_DEVSTS(R5) ;SET ECC CORRECTION MADE
	RSB				;

50$:	BRW	10$			;BRANCH ASSIST


	.SBTTL	CONVERT LOGICAL BLOCK TO PHYSICAL ADDRESS
;+
; IOC$CVTLOGPHY - CONVERT LOGICAL BLOCK TO PHYSICAL ADDRESS
;
; THIS ROUTINE IS CALLED TO CONDITIONALLY CONVERT A LOGICAL BLOCK NUMBER
; TO A PHYSICAL DISK ADDRESS AND STORE THE RESULT IN THE I/O PACKET.
;
; INPUTS:
;
;	R0 = LOGICAL BLOCK NUMBER TO BE CONVERTED.
;	R3 = I/O PACKET ADDRESS.
;	R5 = DEVICE UNIT UCB ADDRESS.
;
; OUTPUTS:
;
;	IF UCB$V_NOCNVRT IS CLEAR IN UCB$W_DEVSTS, THE LOGICAL BLOCK NUMBER
;	IS CONVERTED TO A PHYSICAL DISK ADDRESS USING THE DISK GEOMETRY PARA-
;	METERS IN THE UCB. THE RESULT IS STORED IN THE MEDIA ADDRESS LONGWORD
;	OF THE I/O PACKET.
;
;	IF UCB$V_NOCNVRT IS SET, THE BLOCK NUMBER IS STORED IN THE MEDIA ADDRESS
;	LONGWORD WITHOUT CONVERSION.
;
;	IF THE ROUTINE IS ENTERED AT IOC$CVTLOGPHYU, THEN UCB$V_NOCNVRT IS
;	IGNORED.
;
;	R3 IS PRESERVED ACROSS CALL.
;-

	.ENABLE	LOCAL_BLOCK

	UNIVERSAL_SYMBOL	IOC$CVTLOGPHY
;IOC$CVTLOGPHY::				;CONVERT LOGICAL BLOCK TO PHYSICAL ADDRESS
	MOVL	R0,IRP$L_MEDIA(R3)	;ASSUME NO CONVERSION
	BBS	#UCB$V_NOCNVRT,UCB$W_DEVSTS(R5),10$ ;BYPASS CONVERSION IF SET

	UNIVERSAL_SYMBOL	IOC$CVTLOGPHYU
;IOC$CVTLOGPHYU::			;UNCONDITIONAL ENTRY POINT
	MOVZBL	UCB$L_DEVDEPEND(R5),R2	;GET NUMBER OF SECTORS PER TRACK
	CLRL	R1			;CLEAR HIGH PART OF DIVIDEND
	EDIV	R2,R0,R0,IRP$L_MEDIA(R3) ;CALCULATE SECTOR NUMBER AND STORE
	MOVZBL	UCB$L_DEVDEPEND+1(R5),R2 ;GET NUMBER OF TRACKS PER CYLINDER
	EDIV	R2,R0,R0,R1		;CALCULATE TRACK AND CYLINDER
	MOVB	R1,IRP$L_MEDIA+1(R3)	;STORE TRACK NUMBER
	MOVW	R0,IRP$L_MEDIA+2(R3)	;STORE CYLINDER NUMBER
10$:	RSB				;

	.DISABLE LOCAL_BLOCK


	.SBTTL	MAP VIRTUAL TO LOGICAL BLOCK
;+
; IOC$MAPVBLK - MAP VIRTUAL TO LOGICAL BLOCK
;
; THIS ROUTINE IS CALLED TO MAP A VIRTUAL BLOCK TO A LOGICAL BLOCK USING A
; MAPPING WINDOW.
;
; INPUTS:
;
;	R0 = VIRTUAL BLOCK NUMBER.
;	R1 = NUMBER OF BYTES TO MAP.
;	R2 = ADDRESS OF WINDOW MAPPING BLOCK.
;	R3 = ADDRESS OF IO REQUEST PACKET
;		(ONLY NEEDED FOR DISK DEVICES)
;	R5 = UCB ADDRESS OF DEVICE UNIT.
;
; OUTPUTS:
;
;	R0 LOW BIT CLEAR INDICATES A TOTAL MAPPING FAILURE.
;
;		R2 = NUMBER OF UNMAPPED BYTES.
;
;	R0 LOW BIT SET INDICATES PARTIAL MAP WITH:
;
;		R1 = LOGICAL BLOCK NUMBER OF FIRST BLOCK.
;		R2 = NUMBER OF UNMAPPED BYTES.
;		R5 = UCB ADDRESS OF DEVICE UNIT (POSSIBLY MODIFIED).
;
;	R3 IS PRESERVED ACROSS CALL.
;-
 
	.ENABLE	LOCAL_BLOCK

	UNIVERSAL_SYMBOL	IOC$MAPVBLK
;IOC$MAPVBLK::				;MAP VIRTUAL TO LOGICAL BLOCK
	LOCK	LOCKNAME=FILSYS,-	;SYNC ACCESS TO WINDOW WITH FILE SYSTEM
		SAVIPL=-(SP)		;SAVE CURRENT IPL
	PUSHR	#^M<R1,R3,R4,R6,R7,R8,R9>	;SAVE REGISTERS
	MOVAB	-1(R0),R7		;SAVE START VBN -1
	MOVL	R2,R3			;GET COPY OF WINDOW ADDRESS
;
; THE WINDOW MAY CONSIST OF A CHAIN OF WCB SEGMENTS. SEARCH THROUGH THE
; CHAIN UNTIL WE FIND ONE WHICH IS BEYOND THE DESIRED VBN OR WE REACH
; THE END OF THE CHAIN.
;
10$:	CMPB	WCB$B_TYPE(R3),#DYN$C_WCB ;SEE IF THIS IS REALLY A WINDOW
	BEQL	20$			;IF NEQ NO
	BUG_CHECK STRNOTWCB,FATAL	;STRUCTURE IS NOT A WINDOW BLOCK

20$:	CMPL	R0,WCB$L_STVBN(R3)	;CHECK VBN AGAINST START VBN OF WINDOW
	BLSSU	40$			;BRANCH IF VBN PRECEDES WINDOW
	MOVL	R3,R2			;ELSE ADVANCE TO THIS WINDOW SEGMENT
	MOVL	WCB$L_LINK(R2),R3	;LOOK AT NEXT WINDOW SEGMENT
	BNEQ	10$			;BRANCH TO LOOK AT IF IT EXISTS

40$:	MOVZWL	WCB$W_NMAP(R2),R3	;GET COUNT OF RETRIEVAL POINTERS
	BEQL	60$			;BRANCH IF EMPTY WINDOW
	MOVAL	WCB$L_STVBN(R2),R4	;POINT TO STARTING VBN
	SUBL	(R4)+,R0		;SUBTRACT STARTING VBN FROM DESIRED
	BBS	#DEV$V_SQD,UCB$L_DEVCHAR(R5),70$ ;IF SET, SEQUENTIAL DEVICE
	BLSSU	60$			;BRANCH IF VBN PRECEDES WINDOW

	ASSUME	WCB$L_P1_COUNT EQ WCB$L_STVBN+4
	ASSUME	WCB$L_COUNT    EQ 0
	ASSUME	WCB$L_LBN      EQ 4
	ASSUME	WCB$B_RVN      EQ 8
	ASSUME	WCB$C_MAP_PTR_LENGTH EQ 12
;
; SCAN THE WINDOW, SUBTRACTING THE COUNT FIELD OF EACH POINTER FROM THE
; CURRENT RELATIVE BLOCK NUMBER.
;
 
50$:	MOVL	(R4)+,R9		;GET COUNT FIELD OF RETRIEVAL POINTER
	SUBL	R9,R0			;SUBTRACT FROM RELATIVE BLOCK NUMBER
	BLSSU	80$			;BRANCH IF VBN LOCATED IN THIS POINTER
	ADDL	#8,R4			;SKIP LBN AND RVN FIELDS OF POINTER
	SOBGTR	R3,50$			;LOOP THRU WINDOW
					;VBN IS BEYOND WINDOW
60$:	CLRL	R8			;INDICATE NO BLOCKS MAPPED
	MOVL	WCB$L_ORGUCB(R2),R5	;REDIRECT UCB TO VOLUME CONTAINING THE FILE
	BRB	100$			;RETURN FAILURE
 
;
; DEVICE IS A SEQUENTIAL DEVICE. FIRST MAPPING POINTER CONTAINS THE UCB ADDRESS
; OF THE CURRENT VOLUME THAT IS BEING PROCESSED. ALL BYTES ALWAYS MAP.
;
 
70$:	MOVL	(R4),R5			;GET CURRENT VOLUME UCB ADDRESS
	BRW	220$			;
 
;
; FOUND THE RETRIEVAL POINTER CONTAINING THE STARTING VBN. R0 NOW
; CONTAINS A NEGATIVE VALUE WHICH IS THE NUMBER OF BLOCKS BETWEEN
; THE STARTING VBN AND THE END OF THE POINTER.
;
 
80$:	MNEGL	R0,R8			;SAVE # BLOCKS MAPPED PAST START VBN
	ADDL	(R4)+,R9		;FIRST LBN BEYOND THIS POINTER
	ADDL3	R9,R0,R1		;COMPUTE STARTING LBN
	MOVL	(R4)+, R0		;GET RVN FIELD
 
;
; IF THE NEXT RETRIEVAL POINTER IS CONTIGUOUS WITH THE ONE FOUND, ADD
; IN ITS COUNT TO HANDLE THE CASE WHERE A TRANSFER SPANS TWO POINTERS.
; NOTE THAT THE GREATEST NUMBER OF CONTIGUOUS POINTERS A TRANSFER CAN
; SPAN IS TWO.
;
 
	DECL	R3			;SEE IF THERE IS ANOTHER POINTER
	BLEQ	90$			;BRANCH IF NONE
	MOVL	(R4)+,R3		;GET COUNT OF NEXT RETRIEVAL POINTER
	CMPL	R9,(R4)			;SEE IF THE NEXT POINTER IS CONTIGUOUS
	BNEQ	90$			;BRANCH IF NOT
; Ensure that the RVN of the new block matches the old one. R0 holds the
; current RVN, and 4(R4) is the next RVN. Compare these and do NOT take the
; pointers as contiguous unless they match.
	CMPL	R0,4(R4)		;Do RVNs match?
	BNEQ	90$			;If not, do not treat as contig transfer
	ADDL	R3,R8			;ADD TO # BLOCKS MAPPED
 
90$:	MOVZBL	R0,R0			;EXTRACT RVN (R1 ALREADY HAS STARTING LBN)
	BEQL	100$			;BRANCH IF NOT VOLUME SET
	MOVL	WCB$L_RVT(R2),R6	;GET RELATIVE VOLUME TABLE ADDR
	CMPB	R0,RVT$B_NVOLS(R6)	;VOLUME MAPPED WITHIN UCBLST?
	BGTRU	120$			;NO, FORCE WINDOWTURN
	MOVL	RVT$L_UCBLST-4(R6)[R0],R5 ;GET THE RIGHT UCB ADDRESS
	BEQL	120$			;IF ZERO, FORCE WINDOWTURN
;
; CHECK THE RANGE OF VBN'S PROVIDED BY THE MAP POINTER AGAINST THE
; FILE SIZE RECORDED IN THE FCB. REDUCE IT IF THE FCB INDICATES A
; SMALLER FILE SIZE THAN THE WINDOW.
;

100$:	BBS	#WCB$V_NOTFCP,WCB$B_ACCESS(R2),210$ ;SKIP CHECK IF NO FCB
	BBS	#DEV$V_SQD,UCB$L_DEVCHAR(R5),210$ ;OR IF MAGTAPE
	MOVL	WCB$L_FCB(R2),R6	;GET FCB ADDRESS
	SUBL3	R7,FCB$L_FILESIZE(R6),R4 ;COMPUTE BLOCKS TO PHYSICAL EOF
	BLEQU	120$			;BRANCH IF VBN PAST END OF FILE
	CMPL	R8,R4			;COMPARE AGAINST BLOCKS MAPPED
	BLEQU	110$			;BRANCH IF LESS MAPPED BY WINDOW
	MOVL	R4,R8			;ELSE LIMIT TO FILE SIZE

;
; FOR READ I/O'S, CHECK THE RANGE OF VBN'S PROVIDED BY THE MAP POINTER
; AGAINST THE CURRENT HIGHWATER MARK AND SET THE APPROPRIATE STATUS
; FLAGS. LIMIT THE LENGTH OF THE TRANSFER TO HIGHWATER MARK. BY
; CHECKING READS HERE, HIGHWATER MARK FLAGGING AND CHECKING IS DONE ON
; A SEGMENT BY SEGMENT BASIS. WRITES MUST BE FLAGGED FOR THE ENTIRE
; I/O, AND HENCE ARE HANDLED IN SYSACPFDT.
;

110$:	MOVL	4(SP),R3		;GET BACK IRP ADDRESS
	BBC	#IRP$V_FUNC,IRP$W_STS(R3),210$ ;BRANCH IF THIS IS A WRITE
	BICB	#IRP$M_START_PAST_HWM!IRP$M_END_PAST_HWM,-
		IRP$W_STS2(R3)		;INIT HIGHWATER MARK FLAGS
	INCL	R7			;BACK TO TRUE START VBN
	SUBL3	R7,FCB$L_HIGHWATER(R6),R7 ;BLOCKS TO HIGHWATER
	BGTRU	130$			;BRANCH IF NOT PAST HWM
	TSTL	FCB$L_HIGHWATER(R6)	;SEE IF HIGHWATER MARKING IS ON
	BEQL	210$			;BRANCH IF NOT
	BISB	#IRP$M_START_PAST_HWM,IRP$W_STS2(R3) ;NOTE PAST HIGHWATER MARK
120$:	CLRL	R8			;INDICATE NO BLOCKS MAPPED
	BRB	210$			;AND EXIT

130$:	CMPL	R8,R7			;DOES THE TRANSFER EXTEND PAST HIGHWATER
	BLEQU	210$			;BRANCH IF NOT
	MOVL	R7,R8			;LIMIT READ TO HIGHWATER MARK

;
; SEE IF THE ENTIRE TRANSFER IS MAPPED CONTIGUOUSLY.
;
 
210$:	CLRL	R0			;ASSUME FAILURE
	ASHL	#9,R8,R8		;CONVERT TO # BYTES MAPPED
	BVS	250$			;IF INT OVERFLOW THEN TOTAL MAP
	BEQL	240$			;BRANCH IF NO BLOCKS MAPPED
	INCL	G^PMS$GL_HIT		;COUNT A WINDOW HIT
	SUBL	R8,(SP)			;SUBTRACT FROM BYTES DESIRED
	BGEQU	230$			;BRANCH IF NOT TOTAL MAP
220$:	CLRL	(SP)			;ZERO INDICATES COMPLETE MAP
230$:	MOVL	#SS$_NORMAL,R0		;INDICATE SUCCESS
240$:	POPR	#^M<R2,R3,R4,R6,R7,R8,R9>	;RESTORE REGISTERS
	UNLOCK	LOCKNAME=FILSYS,-	;RELEASE WINDOW LOCK
		NEWIPL=(SP)+,-		;RESTORE IPL
		CONDITION=RESTORE	;CONDITIONALLY RELEASE SPINLOCK
	RSB				;

	; Integer overflow occurred when converting the number of blocks
	; mapped by this extent to a byte count.  This implies that the
	; requested tranfer must be entirely mapped by this extent since
	; a requested byte count is restricted to a positive 32-bit value.
	; (Routines EXE$READCHKR and EXE$WRITECHKR in SYSQIOFDT.MAR)  
	;
250$:	INCL	G^PMS$GL_HIT		;COUNT A WINDOW HIT
	BRB	220$			;GO AND HANDLE AS A COMPLETE MAP

	.DISABLE LOCAL_BLOCK

	.SBTTL	UPDATE TRANSFER PARAMETERS
;+
; IOC$UPDATRANSP - UPDATE TRANSFER PARAMETERS
;
; THIS ROUTINE IS CALLED TO UPDATE THE TRANSFER PARAMETERS AFTER A DISK ERROR
; HAS BEEN DISCOVERED BUT GOOD DATA WAS TRANSFERED.
;
; INPUTS:
;
;	R0 = NUMBER OF BYTES OF DATA THAT WERE TRANSFERED (MUST BE A MULTIPLE
;		OF 512 BYTES).
;	R5 = DEVICE UNIT UCB ADDRESS.
;
;	UCB$W_BCNT(R5) = LENGTH OF TRANSFER IN BYTES.
;	UCB$W_DA(R5) = CURRENT SECTOR AND TRACK ADDRESS.
;	UCB$W_DC(R5) = CURRENT CYLINDER ADDRESS.
;	UCB$L_SVAPTE(R5) = SYSTEM VIRTUAL ADDRESS OF PAGE TABLE THAT MAPS
;		THE TRANSFER.
;
; OUTPUTS:
;
;	THE NUMBER OF BYTES REMAINING TO BE TRANSFERED, THE SYSTEM VIRTUAL
;	ADDRESS OF THE NEXT PTE, AND THE CURRENT DISK ADDRESS OF THE TRANSFER
;	ARE UPDATED.
;
;	R3 IS PRESERVED ACROSS CALL.
;-
 
	UNIVERSAL_SYMBOL	IOC$UPDATRANSP
;IOC$UPDATRANSP::			;UPDATE TRANSFER PARAMETERS
	SUBW	R0,UCB$W_BCNT(R5)	;CALCULATE REMAINING BYTES TO TRANSFER
	ASHL	#-7,R0,R0		;CALCULATE PTE LONGWORDS TO SKIP OVER
	ADDL	R0,UCB$L_SVAPTE(R5)	;UPDATE SYSTEM VIRTUAL ADDRESS OF NEXT PTE
	DIVL	#4,R0			;CALCULATE NUMBER OF SECTORS TRANSFERED
	ADDB	R0,UCB$W_DA(R5)		;UPDATE SECTOR ADDRESS
 
;
; RIPPLE CARRY FROM SECTOR TO TRACK AND FROM TRACK TO CYLINDER
;
 
10$:	CMPB	UCB$L_DEVDEPEND(R5),UCB$W_DA(R5) ;SECTOR OVERFLOW?
	BGTRU	20$			;IF GTRU NO
	SUBB	UCB$L_DEVDEPEND(R5),UCB$W_DA(R5) ;SUBTRACT OUT A TRACK
	INCB	UCB$W_DA+1(R5)		;INCREMENT TRACK ADDRESS
	CMPB	UCB$L_DEVDEPEND+1(R5),UCB$W_DA+1(R5) ;TRACK OVERFLOW?
	BGTRU	10$			;IF GTRU NO
	SUBB	UCB$L_DEVDEPEND+1(R5),UCB$W_DA+1(R5) ;SUBTRACT OUT A CYLINDER
	INCW	UCB$W_DC(R5)		;UPDATE CYLINDER ADDRESS
	BRB	10$			;
20$:	RSB				;

	.SBTTL	SENSE DISK'S SIZE FDT ROUTINE
;+
; IOC$SENSEDISK - SENSE DISK'S SIZE FDT ROUTINE
;
; THIS ROUTINE IS THE STANDARD SENSEMODE/SENSECHAR FDT ROUTINE FOR
; DISK DEVICES.  IT OBTAINS THE DISK'S SIZE, IN LOGICAL BLOCKS, FROM THE
; UCB (UCB$L_MAXBLOCK) AND IMMEDIATELY COMPLETES THE I/O REQUEST WITH
; THE SECOND LONGWORD OF THE FINAL I/O STATUS EQUAL TO THE DISK'S SIZE.
;
; INPUTS:
;
;	R0 = SCRATCH.
;	R1 = SCRATCH.
;	R2 = SCRATCH.
;	R3 = ADDRESS OF I/O REQUEST PACKET.
;	R4 = CURRENT PROCESS PCB ADDRESS.
;	R5 = ASSIGNED DEVICE UCB ADDRESS.
;	R6 = ADDRESS OF CCB.
;	R7 = I/O FUNCTION CODE BIT NUMBER.
;	R8 = FUNCTION DECISION TABLE DISPATCH ADDRESS.
;	R9 = SCRATCH.
;	R10 = SCRATCH.
;	R11 = SCRATCH.
;	AP = ADDRESS OF FIRST FUNCTION DEPENDENT PARAMETER.
;
; OUTPUTS:
;
;	THE DISK'S SIZE, IN LOGICAL BLOCKS, IS OBTAINED FROM THE UCB
;	AND THE I/O IS COMPLETED WITH THE SECOND I/O STATUS LONGWORD
;	EQUAL TO THE DISK'S SIZE.
;-
 
	UNIVERSAL_SYMBOL	IOC$SENSEDISK
;IOC$SENSEDISK::				;SENSE DISK'S SIZE
	MOVL	UCB$L_MAXBLOCK(R5),R1	;GET DISK'S SIZE IN LOGICAL BLOCKS
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
	JMP	G^EXE$FINISHIO		;FINISH I/O OPERATION
 
	.END
