d 
 	.TITLE	NETDRIVER - PROCESS NETWORK I/O REQUESTS
,	.IDENT	/X01/

;
X; COPYRIGHT (C) 1977
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754
 ;
; THIS SOFTWARE IS FURNISHED  UNDER A LICENSE FOR USE ONLY ON A SINGLE
; COMPUTER  SYSTEM AND  MAY BE  COPIED ONLY WITH  THE INCLUSION OF THE
L; ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE, OR ANY OTHER COPIES THEREOF,
; MAY NOT BE PROVIDED OR  OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON
; EXCEPT FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE
x; TERMS.  TITLE TO AND  OWNERSHIP OF THE  SOFTWARE  SHALL AT ALL TIMES
; REMAIN IN DEC.
@;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
; AND SHOULD  NOT BE CONSTRUED  AS A COMMITMENT  BY DIGITAL  EQUIPMENT
l; CORPORATION.
;
4; DEC ASSUMES  NO  RESPONSIBILITY  FOR  THE USE OR  RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.

`	;++
	; FACILITY:	EXECUTIVE
(
;

; ABSTRACT:

;	THIS MODULE PROCESS USER ACP I/O REQUESTS.
T;
; ENVIRONMENT:
;	MODE = KERNEL
;--
	.PAGE
H	.SBTTL	HISTORY
; AUTHOR:	SCOTT G. DAVIS, CREATION DATE: 06-SEP-77
;
t; MODIFIED BY:
;
<;	, : VERSION
; 01	- 
	.PAGE
h	.SBTTL	DECLARATIONS
;
0; INCLUDE FILES:
;
	$CCBDEF
\	$CXBDEF
	$DYNDEF
$	$IPLDEF
	$IODEF
	$IRPDEF
P	$NETDEF
	$PRDEF
	$SSBDEF
|	$UCBDEF
	$VCBDEF
D
;
; MACROS:
p;

8;
; EQUATED SYMBOLS:
 ;
d	$EQULST	NET$C_,GLOBAL,,,<-
		<MAXINT,16>,-		; MAX LTH OF AN INTERRUPT MSG
,>
;
; ARGUMENT LIST OFFSETS FOR QIO 
X;
P1	= 0				; ARG #1 ETC.
 P2	= 4				;
P3	= 8				;
P4	= 12				;
LP5	= 16				;
P6	= 20				;

x;****** TEMPORARY UNTIL STARLET.OLB UPDATED
;
@SS$_MSGTOOBIG=^X29C
;*****
 
l 	.PSECT	WIONONPAGED
 ;
4!; OWN STORAGE:
!;
!
`"
"	.SBTTL	DRIVER DISPATCH TABLE
(#
#NET$DDT::				; REFERENCE LABEL
#	.LONG	0			; START I/O OPERATION
T$	.LONG	0			; UNSOLICITED INTERRUPT
$	.LONG	FUNCTABLE		; FUNCTION DECISION TABLE ADDRESS
%	.LONG	0			; CANCEL I/O ENTRY POINT
%	.LONG	0			; ADDRESS OF REGISTER DUMP ROUTINE
%	.LONG	0			; DIAGNOSTIC AND ERROR BUFFER SIZES
H&	.PAGE
&	.SBTTL	FUNCTION DECISION TABLE
' 
t'FUNCTABLE:				;FUNCTION DECISION TABLE
'	FUNCTAB	,-			;LEGAL FUNCTIONS
<(		<READVBLK,-		;READ VIRTUAL BLOCK
(		 WRITEVBLK,-		;WRITE VIRTUAL BLOCK
)		 ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
h)		 ACPCONTROL,-		;ACP CONTROL FUNCTION
)		 DEACCESS>		;DEACCESS FILE
0*	FUNCTAB	,-			;BUFFERED I/O FUNCTIONS
*		<ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
*		READVBLK,-		; READ VIRTUAL
\+		WRITEVBLK,-		; WRITE VIRTUAL
+		 ACPCONTROL,-		;ACP CONTROL FUNCTION
$,		 DEACCESS>		;DEACCESS FILE
,	FUNCTAB	RCV_QIO,<READLBLK>	; READ FUNCTION *** - WAS CONVERTED TO LOGICAL
,	FUNCTAB	XMT_QIO,<WRITELBLK>	; WRITE FUNCTION *** - WAS CONVERTED TO LOGICAL
P-	FUNCTAB	ACP$ACCESS,<ACCESS,CREATE> ; ACCESS AND CREATE FILE OR DIRECTORY
-	FUNCTAB	ACP$DEACCESS,<DEACCESS>	;DEACCESS FILE
.	FUNCTAB	ACP$MODIFY,<ACPCONTROL>	; ACP CONTROL FUNCTIONS
|.	.PAGE
.	.SBTTL	QIO PROCESSING INITIALIZATION
D/;++
/; FUNCTIONAL DESCRIPTION:
0;
p0; QIO_INIT - PICK UP BUFFER DESCRIPTION AND VERIFY ACCESS
0;
81; CALLING SEQUENCE:
1;
 2;	BSB	QIO_INIT
d2;
2; INPUT PARAMETERS:
,3;
3;	REGISTERS FROM QIO ENTRY
3;
X4; IMPLICIT INPUTS:
4;
 5;	NONE
5;
5; OUTPUT PARAMETERS:
L6;
6;	R0 - BUFFER ADDRESS
7;	R1 - BUFFER LENGTH
x7;
7; IMPLICIT OUTPUTS:
@8;
8;	NONE
9;
l9; COMPLETION CODES:
9;
4:;	SS$_ABORT - LOGICAL LINK MARKED FOR BREAK (DEACCESS PENDING)
:;	SS$_FILNOTACC - NO LOGICAL LINK
:;
`;; SIDE EFFECTS:
;;
(<;	NONE
<;
<;--
T=
=QIO_INIT:
>	MOVZWL	#SS$_FILNOTACC,R0	; ASSUME NOT ACCESSED
>	TSTL	CCB$L_WIND(R6)		; CHECK THE WINDOW ADDRESS
>	BGEQ	ABORT_IO		; IF GEQ NO GOOD
H?	MOVZWL	S^#SS$_ABORT,R0		; ASSUME LINK MARKED FOR BREAK
?	BBS	#UCB$V_NT_BREAK,UCB$W_DEVSTS(R5),ABORT_IO ; IF BS CAN'T DO I/O
@	MOVL	P1(AP),R0		; GET USER BUFFER ADDRESS
t@	MOVZWL	P2(AP),R1		; GET BUFFER COUNT
@	MOVQ	R0,IRP$L_MEDIA(R3)	; SAVE BUFFER ADDR AND COUNT
<A	RSB				; DONE
A	.PAGE
B	.SBTTL	READ VIRTUAL BLOCK PROCESSING
hB;++
B; FUNCTIONAL DESCRIPTION:
0C;
C; RCV_QIO - ROUTINE TO PROCESS RECEIVE REQUESTS (READVBLK) BY USER.
C;
\D; INPUT PARAMETERS:
D;
$E;	R3 = I/O PACKET ADDRESS
E;	R4 = PCB ADDRESS
E;	R5 = UCB ADDRESS
PF;	R6 = CCB ADDRESS
F;	R7 = FUNCTION CODE
G;	AP = ADDRESS OF THE FIRST OPERATION SPECIFIC QIO PARAMETER
|G;
G; OUTPUT PARAMETERS:
DH;
H;	NONE
I;
pI; COMPLETION CODES:
I;
8J;	TBS
J;
 K; SIDE EFFECTS:
dK;
K;	LINK SERVICES MESSAGE SENT
,L;
L;--
L
XM
MRCV_QIO:
 N	BSBB	QIO_INIT		; INIT PROCESSING
N;*****
N; PERFORM QUOTA CHECK
LO;*****
O	BSBW	EXE$READCHK		; CHECK THE BUFFER
P	BEQL	ABORT_IO		; IF EQL ERROR
xP	BRB	GO_TO_ACP		; QUEUE FUNCTION FOR ACP
P	.PAGE
@Q	.SBTTL	PROCESS TRANSMIT QIO REQUEST
Q;++
R; FUNCTIONAL DESCRIPTION:
lR;
R; XMT_QIO - SERVICE USER TRANSMIT QIO'S.
4S;	INTERRUPT MESSAGES ARE CHECKED FOR MAX OF 16 BYTES.
S;	OTHER MESSAGES ARE SEGMENTED FOR TRANSMISSION.
S;
`T; INPUT PARAMETERS:
T;
(U;	R3 = I/O PACKET ADDRESS
U;	R4 = PCB ADDRESS
U;	R5 = UCB ADDRESS
TV;	R6 = CCB ADDRESS
V;	R7 = FUNCTION CODE
W;	AP = ADDRESS OF THE FIRST OPERATION SPECIFIC QIO PARAMETER
W;
W; OUTPUT PARAMETERS:
HX;
X;	NONE
Y;
tY; COMPLETION CODES:
Y;
<Z;	TBS
Z;
[; SIDE EFFECTS:
h[;
[;	MESSAGE MAY BE TRANSMITTED TO PARTNER.  DATA MOVED TO BUFIO BLOCK.
0\;
\;--
\
\]	.ENABL	LSB
]
$^XMT_QIO:
^	BSBB	QIO_INIT		; INIT PROCESSING
^;*****
P_; PERFORM QUOTA CHECK
_;*****
`	BSBW	EXE$WRITECHK		; CHECK THE BUFFER
|`	BEQL	ABORT_IO		; IF EQL ERROR
`	MOVL	R0,R11			; SET UP USER VA FOR SEGMENTATION
Da	MOVW	R1,IRP$W_BOFF(R3)	; BYTE QUOTA CHARGED
a	CLRL	IRP$L_SVAPTE(R3)	; INIT PTR TO XMT BFR CHAIN
b	BBC	#IO$V_INTERRUPT,IRP$W_FUNC(R3),20$ ; IF BC NOT INTERRUPT
pb;
b; PROCESS A USER INTERRUPT MESSAGE
8c;
c	MOVZWL	#SS$_MSGTOOBIG,R0	; ASSUME USER'S MSG IS TOO BIG
 d	CMPW	#NET$C_MAXINT,R1	; CHECK MAX LTH OF AN INTMSG
dd	BGEQU	10$			; IF GEQU OK
dABORT_IO:
,e	CLRL	R1			; CLEAR 2ND I/O STATUS LONGWORD
e	BRW	EXE$ABORTIO		; KILL IT RIGHT HERE
e 
Xf10$:
f	MOVL	R1,R8			; NO. OF BYTES IN MSG
 g	MOVL	UCB$L_NT_INTSSB(R5),R7	; GET THE SSB ADDRESS
g	BSBB	SETUP_SEGMENT		; SETUP A DATA SEGMENT
g	MOVB	#NET$M_INTMSG!NET$M_INTLS,CXB$C_NSPSTART(R6) ; INDICATE INTERRUPT MSG
Lh	BRB	GO_TO_ACP		; QUEUE FUNCTION FOR ACP
h
i
xi;
i; PROCESS A USER DATA MESSAGE - I SEGMENT IT FOR HIM
@j;
j20$:
k	MOVL	UCB$L_NT_DATSSB(R5),R7	; GET SSB ADDRESS FOR DATA SUBCHANNEL
lk	MOVZWL	UCB$W_DEVBUFSIZ(R5),R8	; GET THE MAX SIZE OF A SEGMENT
k	MOVZBL	#NET$M_BOM,R9		; MARK FIRST SEG AS BOM
4l;
l; DETERMINE THE NUMBER OF SEGMENTS AND THE SIZE OF THE LAST ONE
l;
`m	CLRL	R2			; RESET HIGH ORDER DIVIDEND
m	EDIV	R8,R1,R10,-(SP)		; DO THE DIVISION - LTH OF FINAL SEG TO STACK
(n	BEQL	40$			; IF EQL ONLY ONE SEGMENT
n
n;
To; MAIN SEGMENTATION LOOP
o;
p30$:
p	BSBB	SETUP_SEGMENT		; SET UP DATA SEGMENT
p	BISB	R9,CXB$C_NSPSTART(R6)	; SET THE SUBTYP (BOM OR EOM) BIT
Hq	CLRL	R9			; RESET FOR SUBSEQUENT SEGMENTS
q	SOBGTR	R10,30$			; LOOP
r;
tr; PROCESS FINAL SEGMENT OF MESSAGE
r;
<s40$:
s	BISB	#NET$M_EOM,R9		; SET EOM BIT
t	MOVL	(SP)+,R8		; SET LTH OF FINAL SEGMENT
ht	BEQL	50$			; IF EQL NOTHING THERE
t	BSBB	SETUP_SEGMENT		; SET UP DATA SEGMENT
0u50$:
u	BISB	R9,CXB$C_NSPSTART(R6)	; SET THE EOM BIT
uGO_TO_ACP:
\v	BISW	#<IRP$M_CHAINED!IRP$M_COMPLX>,IRP$W_STS(R3) ; MARK AS COMPLEX CHAINED BFR
v	MOVL	UCB$L_VCB(R5),R0	; GET THE VCB ADDRESS
$w	INCW	VCB$W_TRANS(R0)		; BUMP THE TRANSACTION COUNT
w	SETIPL	#IPL$_SYNCH
w	BRW	EXE$QIOACPPKT		; QUEUE THE PACKET FOR THE ACP
Px
x	.DSABL	LSB
y	.PAGE
|y;
y; SETUP_SEGMENT - ALLOCATE A DATA SEGMENT AND MOVE IN THE DATA
Dz;
z; INPUTS:
{;		R3 - IRP ADDRESS
p{;		R5 - UCB ADDRESS
{;		R7 - SSB ADDRESS (SETUP_SEGMENT)
8|;		R8 - NO. OF BYTES TO MOVE
|;		R11 - CURRENT ADDRESS OF USER DATA
 };
d}; OUTPUTS:	R6 - BASE OF BUFFERED I/O BLOCK ALLOCATED AND FILLED IN
};		R3,R4,R5 PRESERVED ACROSS CALL
,~;
~
~SETUP_SEGMENT:
X	PUSHR	#^M<R3,R4,R5>		; SAVE REGS
	MOVL	R8,R1			; GET NO. OF BYTES TO MOVE
 ;
; ALLOCATE A CHAINED COMPLEX BUFFER
;
L	ADDL	#<NET$C_NSPOVH+CXB$C_LENGTH>,R1 ; ACCOUNT FOR OVERHEAD
	BSBW	EXE$ALLOCBUF		; ALLOCATE A BUFFER
;*****
x; CHECK FOR ALLOCATION FAILURE
܂;*****
@	MOVL	R2,R6			; COPY THE BASE ADDRESS
	MOVAL	UCB$B_TYPE(R6),R3	; SET PTR FOR FILLING IN
	MOVB	#DYN$C_CXB,(R3)+	; SET THE BLOCK TYPE
l	MOVB	#CXB$C_DDCDAT,(R3)+	; SET BLOCK TYPE TO "DATA OUT"
Є	CLRQ	(R3)+			; RESET MSG LTH, OFFSET, AND BFR LINK
4	MOVL	R7,(R3)+		; GET THE SSB ADDRESS
	CLRW	(R3)+			; LEAVE ROOM FOR ACKNUM, MAYBE

`	ASSUME	NET$C_MSGFLG EQ 0
Ć	ASSUME	NET$C_DATAM EQ 0
(
	CLRB	(R3)+			; MSGID BYTE
	MOVL	UCB$W_DSTADDR(R5),(R3)+	; HIS LINK ADDRESS AND MINE
T;
; PUT IN THE PROPER SEGMENT NUMBER
;
	INCW	SSB$W_XMTSEGNUM(R7)	; BUMP SEGMENT NO.
	BICW3	#^C<4095>,SSB$W_XMTSEGNUM(R7),(R3)+ ; STUFF SEGNUM MOD 4096
H;
; MOVE IN THE DATA
;
t	MOVC3	R8,(R11),(R3)		; DO IT
؋	MOVL	R1,R11			; UPDATE BUFFER POINTER
<	BSBB	NET$SET_LENGTH		; COMPUTE THE LENGTH OF THE DATA
	POPR	#^M<R3,R4,R5>		; RESTORE REGS
;
h; LINK BUFFER INTO CHAIN
̍;
0	MOVAB	IRP$L_SVAPTE-CXB$L_LINK(R3),R0 ; SEED THE CHAINING
20$:
	MOVL	R0,R2			; COPY ADDRESS
\	MOVL	CXB$L_LINK(R2),R0	; GET THE LINK
	BNEQ	20$			; IF NEQ NOT AT END
$	MOVL	R6,CXB$L_LINK(R2)	; LINK IN THE SEGMENT
	RSB				; DONE
.PAGE
P	.SBTTL	SET MSG LTH IN CXB
;++
; FUNCTIONAL DESCRIPTION:
|;
; NET$SET_LENGTH - THIS ROUTINE COMPUTES THE LTH OF A MSG TO BE SENT
D;
; CALLING SEQUENCE:
;
p;	BSB	NET$SET_LENGTH
Ԕ;
8; INPUT PARAMETERS:
;
 ;	R3 - END OF MSG BFR+1
d;	R6 - BEGINNING OF BUFIO BLOCK
Ȗ;
,; IMPLICIT INPUTS:
;
;	NONE
X;
; OUTPUT PARAMETERS:
 ;
;	NONE
;
L; IMPLICIT OUTPUTS:
;
;	NONE
x;
ܛ; COMPLETION CODES:
@;
;	NONE
;
l; SIDE EFFECTS:
Н;
4;	NONE
;--

`NET$SET_LENGTH::
ğ	MOVAL	CXB$C_NSPSTART(R6),-(SP)	; GET POINTER TO DATA
(	SUBL3	(SP)+,R3,CXB$W_LENGTH(R6) ; COMPUTE LTH OF MSG - WORD AFTER LENGTH NOT USED
	MOVW	#CXB$C_NSPSTART,CXB$W_OFFSET(R6) ; INIT OFFSET TO MSG
	RSB
T
	.END
