Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93L-BB_1990 - 10,7/mon/ethuuo.mac
There are 8 other files named ethuuo.mac in the archive. Click here to see a list.
	TITLE	ETHUUO - ETHERNET USER INTERFACE	V26
	SUBTTL	WILLIAM C. DAVENPORT/WXD	17-APR-90

	SEARCH	F,S,ETHPRM,MACSYM
	$RELOC
	$HIGH

;THIS MODULE IMPLEMENTS THE ETHNT. UUO INTERFACE TO ETHERNET

;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 1985,1986,1988,1990.
;ALL RIGHTS RESERVED.

.CPYRT<1985,1990>


	XP	VETHUU,26	;ETHUUO VERSION NUMBER

ETHUUO::!ENTRY	ETHUUO		;LOAD IF LIBRARY SEARCH


;LOCAL DEFINITIONS

NU.WAI==000000,,400000		;ETHERNET FUNCTION COMPLETION WAIT
	SUBTTL	TABLE OF CONTENTS


;               TABLE OF CONTENTS FOR ETHUUO
;
;
;                        SECTION                                   PAGE
;    1. TABLE OF CONTENTS.........................................   2
;    2. DATA STRUCTURES
;         2.1   QUEUE HEADER BLOCK................................   3
;         2.2   MONITOR BUFFER DESCRIPTOR BLOCK...................   4
;         2.3   ETHERNET JOB BLOCK................................   5
;         2.4   USER PORTAL BLOCK.................................   6
;    3. ETHNT. UUO SUPPORT
;         3.1   RESET UUO.........................................   7
;         3.2   PSI INTERRUPTS....................................   8
;         3.3   ETHNT. UUO DISPATCH...............................   9
;         3.4   ETHNT. UUO DISPATCH TABLES........................  12
;    4. ETHNT. UUO FUNCTIONS
;         4.1   OPEN USER PORTAL..................................  15
;         4.2   CLOSE USER PORTAL.................................  16
;         4.3   QUEUE RECEIVE DATAGRAM BUFFER.....................  17
;         4.4   READ RECEIVE DATAGRAM QUEUE.......................  18
;         4.5   QUEUE TRANSMIT DATAGRAM BUFFER....................  20
;         4.6   READ TRANSMIT DATAGRAM QUEUE......................  21
;         4.7   ENABLE/DISABLE MULTI-CAST ADDRESS.................  22
;         4.8   READ CHANNEL LIST.................................  23
;         4.9   READ CHANNEL INFORMATION..........................  24
;         4.10  READ CHANNEL COUNTERS.............................  25
;         4.11  SET CHANNEL ADDRESS...............................  26
;         4.12  READ PORTAL LIST..................................  27
;         4.13  READ PORTAL INFORMATION...........................  28
;         4.14  READ PORTAL COUNTERS..............................  29
;         4.15  READ KONTROLLER LIST..............................  30
;         4.16  READ KONTROLLER INFORMATION.......................  31
;         4.17  READ KONTROLLER COUNTERS..........................  32
;    5. ETHNT. UUO FUNCTION SUPPORT
;         5.1   READ ETHERNET LIST................................  33
;         5.2   READ ETHERNET INFORMATION.........................  34
;         5.3   READ ETHERNET COUNTERS............................  35
;         5.4   READ ETHERNET DATA................................  36
;         5.5   ETHSER INTERFACE..................................  37
;         5.6   ETHSER ERROR CODE CONVERSION......................  38
;    6. ETHNT. UUO COMPLETION INTERRUPT
;         6.1   INTERRUPT DISPATCH................................  39
;         6.2   DISPATCH TABLE....................................  40
;         6.3   RECEIVE DATAGRAM..................................  42
;         6.4   TRANSMIT DATAGRAM.................................  43
;         6.5   READ ETHERNET DATA................................  44
;    7. ETHNT. UUO SUPPORT
;         7.1   ETHERNET JOB BLOCK MANIPULATION...................  45
;         7.2   USER PORTAL BLOCK MANIPULATION....................  47
;         7.3   MONITOR BUFFER MANIPULATION.......................  50
;         7.4   INFORMATION PORTAL MANIPULATION...................  55
;         7.5   FUNCTION COMPLETION EVENT WAIT....................  57
;         7.6   PORTAL STATUS UPDATE..............................  59
;         7.7   QUEUE MANIPULATION................................  60
;    8. PRIVILEGE CHECKING........................................  65
;    9. BYTE POINTERS.............................................  66
;   10. DEFAULT VALUE STORAGE.....................................  67
;   11. THE END...................................................  68
	SUBTTL	DATA STRUCTURES  --  QUEUE HEADER BLOCK


;A QUEUE HEADER BLOCK IS USED TO MAINTAIN TRANSMIT AND RECEIVE
;DATAGRAM QUEUES.

	$PHASE	0		;THESE ARE OFFSETS

.QHFLI:! BLOCK	1		;ADDRESS OF FIRST QUEUE ENTRY

.QHBLI:! BLOCK	1		;ADDRESS OF LAST QUEUE ENTRY

.QHCNT:! BLOCK	1		;COUNT OF ENTRIES IN QUEUE

.QHLEN:!			;LENGTH OF QUEUE HEADER BLOCK

	$DEPHASE


;A QUEUE ENTRY BLOCK IS THE FIRST PART OF ANY QUEUE ENTRY

	$PHASE	0		;THESE ARE OFFSETS

.QEFLI:! BLOCK	1		;ADDRESS OF NEXT QUEUE ENTRY

.QELEN:!			;LENGTH OF QUEUE ENTRY BLOCK

	$DEPHASE
	SUBTTL	DATA STRUCTURES  --  MONITOR BUFFER DESCRIPTOR BLOCK


;SINCE ETHERNET ACCESS HAS NO GUARANTEED RESPONSE TIME, DATA IS NOT
;DIRECTLY RECEIVED INTO OR TRANSMITTED FROM USER BUFFERS.  INSTEAD,
;A MONITOR BUFFER IS ALLOCATED AND USED FOR RECEIPT AND TRANSMISSION
;OF DATAGRAMS.  USER DATA IS COPIED TO/FROM THE MONITOR BUFFER AT
;UUO LEVEL.  THE MONITOR BUFFER DESCRIPTOR BLOCK IS USED TO REMEMBER
;INFORMATION ABOUT THE USER'S BUFFER AND THE MONITOR'S BUFFER.

	$PHASE	0		;THESE ARE OFFSETS

.MBQEB:! BLOCK	.QELEN		;QUEUE ENTRY BLOCK

.MBUBD:! BLOCK	.UBLEN		;SAVED USER BUFFER DESCRIPTOR

.MBDBS:! BLOCK	1		;DATAGRAM BUFFER SIZE (IN WORDS)
.MBUBA:! BLOCK	1		;USER DATAGRAM BUFFER ADDRESS
.MBMBA:! BLOCK	1		;MONITOR DATAGRAM BUFFER ADDRESS
.MBMSD:! BLOCK	MD.LEN		;MONITOR BUFFER MSD

.MBLEN:!			;LENGTH OF USER BUFFER DESCRIPTOR BLOCK

	$DEPHASE
	SUBTTL	DATA STRUCTURES  --  ETHERNET JOB BLOCK


;EACH USER OF THE ETHERNET HAS AN ETHERNET JOB BLOCK CONTAINING JOB
;WIDE PARAMETERS, QUOTAS, AND A POINTER TO A TABLE OF USER PORTAL
;BLOCKS.  THE ETHERNET JOB BLOCK IS POINTED TO BY .PDEJB.

	$PHASE	0		;THESE ARE OFFSETS

EJBJCH:! BLOCK	1		;JCH OF JOB BLOCK OWNER

EJBUPQ:! BLOCK	1		;USER PORTAL QUOTA

EJBBQT:! BLOCK	1		;DATAGRAM BUFFER QUOTAS
	 EJQXBQ==777777,,000000		;TRANSMIT BUFFER QUOTA
	 EJQRBQ==000000,,777777		;RECEIVE BUFFER QUOTA

EJBINF:! BLOCK	1		;ADDRESS OF INFORMATION PORTAL BLOCK

EJBUPC:! BLOCK	1		;COUNT OF USER PORTAL TABLE ENTRIES
EJBUPT:! BLOCK	1		;ADDRESS OF USER PORTAL TABLE

EJBPSQ:! BLOCK	.QHLEN		;USER PORTAL PSI PENDING QUEUE

EJBUNB:! BLOCK	UN.LEN		;UN BLOCK FOR UUO LEVEL

EJBLEN:!			;LENGTH OF ETHERNET JOB BLOCK

	$DEPHASE
	SUBTTL	DATA STRUCTURES  --  USER PORTAL BLOCK


;EACH PORTAL THAT A USER PROCESS HAS OPENED HAS A USER PORTAL BLOCK.
;THIS BLOCK KEEPS TRACK OF USER RECEIVE AND TRANSMIT DATAGRAMS, AND
;MAINTAINS INFORMATION NEEDED TO INTERFACE TO ETHSER.

	$PHASE	0		;THESE ARE OFFSETS

UPBNAM:! BLOCK	1		;PORTAL DEVICE NAME (SAME PLACE AS DEVNAM)

UPBEJB:! BLOCK	1		;ADDRESS OF ETHERNET JOB BLOCK

UPBFWC:! BLOCK	1		;ETHERNET FUNCTION WAIT CODE

UPBPIW:! BLOCK	1		;PROTOCOL IDENTIFICATION WORD
				; (SAME FORMAT AT .ETPIW WORD)

UPBPSW:! BLOCK	1		;PORTAL STATUS WORD
				; (SAME FORMAT AT .ETPSW WORD)
UPBPPS:! BLOCK	1		;PREVIOUS PORTAL STATUS WORD

UPBCSW:! BLOCK	1		;CHANNEL STATUS WORD
				; (SAME FORMAT AT .ETCSW WORD)

UPBXBC:! BLOCK	1		;TRANSMIT DATAGRAM BUFFER COUNT
UPBRBC:! BLOCK	1		;RECEIVE DATAGRAM BUFFER COUNT

UPBBQT:! BLOCK	1		;DATAGRAM BUFFER QUOTAS
	 UPQXBQ==777777,,000000		;TRANSMIT BUFFER QUOTA
	 UPQRBQ==000000,,777777		;RECEIVE BUFFER QUOTA

UPBPSQ:! BLOCK	.QELEN		;PSI PENDING QUEUE LINKAGE

UPBXQH:! BLOCK	.QHLEN		;TRANSMIT DONE QUEUE HEADER
UPBRQH:! BLOCK	.QHLEN		;RECEIVE DONE QUEUE HEADER

UPBLEN:!			;LENGTH OF USER PROTOCOL BLOCK

	$DEPHASE
	SUBTTL	ETHNT. UUO SUPPORT  --  RESET UUO


;ROUTINE CALLED UPON A RESET UUO
;LINKAGE:
;	PUSHJ	P,ENTRST
;RETURNS:
;	CPOPJ ALWAYS

ENTRST::PUSHJ	P,FNDPDS##	;SET UP JOB'S PDB
	SKIPN	.PDEJB##(W)	;JOB HAVE AN ETHERNET JOB BLOCK?
	POPJ	P,		;NO, RETURN NOW
	SE1ENT			;RUN IN SECTION 1
	PUSHJ	P,SAVE2##	;SAVE P1-P2
	PUSHJ	P,SAVJW##	;SAVE J AND W
	MOVE	J,.PDEJB##(W)	;GET ADDRESS OF ETHERNET JOB BLOCK
	XMOVEI	U,EJBUNB(J)	;GET ADDRESS OF UN BLOCK
	MOVE	P1,EJBUPQ(J)	;GET USER PORTAL QUOTA
	MOVE	P2,EJBUPT(J)	;AND ADDRESS OF USER PORTAL TABLE
ENTRS1:	JUMPE	P1,ENTRS3	;EXIT LOOP AT END OF TABLE
	SKIPN	F,(P2)		;GET ADDRESS OF NEXT USER PORTAL BLOCK
	JRST	ENTRS2		;NONE, CONTINUE WITH NEXT TABLE ENTRY
	PUSHJ	P,ENTCLS	;CLOSE THIS PORTAL
	  JFCL			;ERROR, NOT MUCH CAN DO ABOUT IT
ENTRS2:	XMOVEI	P2,1(P2)	;INCREMENT USER PORTAL TABLE ADDRESS
	SOJA	P1,ENTRS1	;LOOP BACK FOR ENTIRE TABLE
ENTRS3:	PJRST	KILEJB		;RELEASE ETHERNET JOB BLOCK AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  PSI INTERRUPTS


;ROUTINE CALLED UPON ETHERNET PSI INTERRUPT TO RETURN PORTAL STATUS WORD
;LINKAGE:
;	J/ JOB NUMBER
;	PUSHJ	P,ENTPSI
;RETURNS:
;	CPOPJ ALWAYS WITH:
;	T2/ PORTAL STATUS WORD

ENTPSI::SE1ENT			;RUN IN SECTION 1
	PUSHJ	P,SAVJW##	;SAVE J AND W
	PUSHJ	P,FNDPDB##	;GET ADDRESS OF JOB'S PDB
	  JRST	ENTPS2		;NONE, RETURN ZERO
	SKIPN	J,.PDEJB##(W)	;GET ADDRESS OF ETHERNET JOB BLOCK
	JRST	ENTPS2		;NONE, RETURN ZERO
	XMOVEI	T1,EJBPSQ(J)	;GET ADDRESS OF PSI QUEUE HEADER
	PUSHJ	P,REMQUE	;REMOVE USER PORTAL BLOCK FROM PSI QUEUE
	  JRST	ENTPS2		;NONE, RETURN ZERO
	XMOVEI	F,-UPBPSQ(T2)	;...
	XMOVEI	T1,EJBPSQ(J)	;GET ADDRESS OF PSI QUEUE HEADER
	PUSHJ	P,CHKQUE	;IS QUEUE EMPTY?
	  JRST	ENTPS1		;YES, DON'T SIGNAL ANOTHER PSI
	PUSH	P,J		;SAVE J
	MOVE	J,EJBJCH(J)	;GET JCH OF JOB BLOCK OWNER
	SIGNAL	C$ETH		;SIGNAL ETHERNET EVENT
	  JFCL			;...
	POP	P,J		;RESTORE J
ENTPS1:	SKIPA	T2,UPBPSW(F)	;GET PORTAL STATUS WORD
ENTPS2:	SETZ	T2,		;GET STATUS WORD OF ZERO
	POPJ	P,		;RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  ETHNT. UUO DISPATCH


;UUO FOR USER ACCESS TO ETHERNET
;LINKAGE:
;	XMOVEI	AC,ADDR
;	ETHNT.	AC,
;	  ERROR RETURN, CODE IN AC
;	NORMAL RETURN
;
;ADDR:	LENGTH,,FUNCTION CODE
;	ARGUMENTS

	ERCODX	ETEPRV,ETPRV%	;INSUFFICIENT PRIVILEGES
	ERCODX	ETEADC,ETADC%	;ADDRESS CHECK
	ERCODX	ETEIAL,ETIAL%	;ILLEGAL ARGUMENT LIST LENGTH
	ERCODX	ETEILF,ETILF%	;ILLEGAL FUNCTION
	ERCODX	ETEUEE,ETUEE%	;UNEXPECTED ETHERNET ERROR
	ERCODX	ETERES,ETRES%	;INSUFFICIENT RESOURCES
	ERCODX	ETEIPI,ETIPI%	;INVALID PORTAL ID
	ERCODX	ETEICI,ETICI%	;INVALID CHANNEL ID
	ERCODX	ETEIPT,ETIPT%	;INVALID PROTOCOL TYPE
	ERCODX	ETEPIU,ETPIU%	;PROTOCOL TYPE IN USE
	ERCODX	ETEPRA,ETPRA%	;PROMISCUOUS RECEIVER ACTIVE
	ERCODX	ETEBAC,ETBAC%	;BUFFER ADDRESS CHECK
	ERCODX	ETEIBS,ETIBS%	;ILLEGAL BUFFER SIZE
	ERCODX	ETEIBP,ETIBP%	;ILLEGAL BYTE POINTER
	ERCODX	ETEIEA,ETIEA%	;ILLEGAL ETHERNET ADDRESS
	ERCODX	ETEPQE,ETPQE%	;PORTAL QUOTA EXCEEDED
	ERCODX	ETEBQE,ETBQE%	;BUFFER QUOTA EXCEEDED

UETHNT::PUSHJ	P,SAVE4##	;SAVE P1-P4
	PUSHJ	P,SSPCS##	;SAVE CURRENT PCS
	PUSHJ	P,SXPCS##	;SET UP PCS FOR USER ARGUMENT
	  PJRST	ETEADC		;ADDRESS CHECK
	MOVE	M,T1		;SET UP FOR GETEWD
	EXCTUX	<MOVE	T1,.ETFCN(M)> ;GET FUNCTION CODE WORD
	  ERJMP	ETEADC		;HANDLE POSSIBLE ADDRESS CHECK
	MOVE	P4,T1		;SAVE FUNCTION CODE WORD
	HRRE	P2,P4		;ISOLATE ARGUMENT BLOCK LENGTH
	JUMPLE	P2,ETEIAL	;VALIDITY CHECK ARGUMENT BLOCK LENGTH
	LDB	P3,[POINTR (P4,ET.FFN)] ;GET FUNCTION CODE
	SKIPLE	P3		;RANGE CHECK FUNCTION CODE
	CAILE	P3,ENTMAX	;...
	  PJRST	ETEILF		;ILLEGAL FUNCTION CODE

				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

	LDB	T1,[POINTR (ENTDSF(P3),DF.ABL)] ;GET MINIMUM BLOCK LENGTH
	CAMLE	T1,P2		;USER'S ARGUMENT BLOCK LARGE ENOUGH?
	  PJRST	ETEIAL		;NO, ILLEGAL ARGUMENT LIST LENGTH
	MOVE	T1,M		;GET ARGUMENT BLOCK ADDRESS
	MOVE	T2,P2		;AND USER SPECIFIED LENGTH
	PUSHJ	P,ARNGE##	;ADDRESS CHECK THE ARGUMENT BLOCK
	 PJRST	ETEADC		;ADDRESS CHECK
	  JFCL			;ADDRESS ILLEGAL FOR I/O
	SKIPE	J,.PDEJB##(W)	;JOB ALREADY HAVE AN ETHERNET JOB BLOCK?
	JRST	ETHNT1		;YES, CONTINUE
	PUSHJ	P,CREEJB	;CREATE AN ETHERNET JOB BLOCK
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
ETHNT1:	XMOVEI	U,EJBUNB(J)	;GET ADDRESS OF UN BLOCK
	MOVE	F,EJBINF(J)	;GET ADDRESS OF INFORMATION USER PORTAL
	MOVX	T1,DF.PID	;NEED TO SPECIFY A USER PORTAL ID?
	TDNN	T1,ENTDSF(P3)	;...
	JRST	ETHNT2		;NO, CONTINUE
	EXCTUX	<MOVE	T1,.ETPSW(M)> ;GET PORTAL STATUS WORD
	ANDX	T1,ET.PID	;MASK TO PORTAL ID
	PUSHJ	P,FNDUPB	;FIND USER PORTAL BLOCK
	  PJRST	ETEIPI		;ERROR, INVALID PORTAL ID
ETHNT2:	MOVX	T1,DF.AUB	;NEED TO ADDRESS CHECK USER BUFFER?
	TDNN	T1,ENTDSF(P3)	;...
	JRST	ETHNT3		;NO, JUST DISPATCH
	EXCTUX	<DMOVE	P1,.ETBFL(M)> ;GET SIZE AND ADDRESS OF USER BUFFER
	DMOVE	T1,P1		;GET SIZE AND ADDRESS OF USER BUFFER
	EXCH	T1,T2		;SET UP TO ADDRESS CHECK USER BUFFER
	PUSHJ	P,ARNGE##	;ADDRESS CHECK USER BUFFER
	 PJRST	ETEBAC		;BUFFER ADDRESS CHECK
	  PJRST	ETEBAC		;ADDRESS ILLEGAL FOR I/O

				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

ETHNT3:	MOVE	T1,ENTDSP(P3)	;GET ADDRESS OF FUNCTION SPECIFIC ROUTINE
	PUSHJ	P,(T1)		;DISPATCH TO FUNCTION SPECIFIC ROUTINE
	  POPJ	P,		;ERROR, RETURN, ERROR CODE ALREADY STORED
	MOVX	T1,DF.UPS	;NEED TO RETURN UPDATED PORTAL STATUS?
	TDNN	T1,ENTDSF(P3)	;...
	PJRST	CPOPJ1##	;NO, RETURN
	PUSHJ	P,UPDPSW	;UPDATE CURRENT PORTAL STATUS
	MOVE	T1,UPBPSW(F)	;GET UPDATED PORTAL STATUS
	EXCTXU	<MOVEM	T1,.ETPSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  ETHNT. UUO DISPATCH TABLES


;ETHNT. UUO DISPATCH TABLE

DEFINE	FNC,<

	XALL				;;LIST GENERATED TABLE

DISP	0,		0,	0, ETEILF	;;(0) ILLEGAL, PLACE HOLDER
DISP	DF.UPS,		.ETOPN,	4, ENTOPN	;;(1) OPEN PORTAL
DISP	DF.PID,		.ETCLS,	2, ENTCLS	;;(2) CLOSE PORTAL
DISP	DF.PID!DF.UPS,	.ETQRB,	3, ENTQRB	;;(3) QUEUE RECEIVE DATAGRAM BUFFER
DISP	DF.PID!DF.UPS,	.ETRRQ,	3, ENTRRQ	;;(4) READ RECEIVE QUEUE
DISP	DF.PID!DF.UPS,	.ETQXB,	3, ENTQXB	;;(5) QUEUE TRANSMIT DATAGRAM BUFFER
DISP	DF.PID!DF.UPS,	.ETRXQ,	3, ENTRXQ	;;(6) READ TRANSMIT QUEUE
DISP	DF.PID!DF.UPS,	.ETEMA,	4, ENTEMA	;;(7) ENABLE MULTI-CAST ADDRESS
DISP	DF.PID!DF.UPS,	.ETDMA,	4, ENTDMA	;;(10) DISABLE MULTI-CAST ADDRESS

DISP	DF.AUB,		.ETRCL,	4, ENTRCL	;;(11) READ CHANNEL LIST
DISP	DF.AUB,		.ETRCI,	4, ENTRCI	;;(12) READ CHANNEL INFORMATION
DISP	DF.AUB,		.ETRCC,	4, ENTRCC	;;(13) READ CHANNEL COUNTERS
DISP	0,		.ETSCA,	4, ENTSCA	;;(14) SET CHANNEL ADDRESS

DISP	DF.AUB,		.ETRPL,	4, ENTRPL	;;(15) READ PORTAL LIST
DISP	DF.AUB,		.ETRPI,	4, ENTRPI	;;(16) READ PORTAL INFORMATION
DISP	DF.AUB,		.ETRPC,	4, ENTRPC	;;(17) READ PORTAL COUNTERS

DISP	DF.AUB,		.ETRKL,	4, ENTRKL	;;(20) READ KONTROLLER LIST
DISP	DF.AUB,		.ETRKI,	4, ENTRKI	;;(21) READ KONTROLLER INFORMATION
DISP	DF.AUB,		.ETRKC,	4, ENTRKC	;;(22) READ KONTROLLER COUNTERS

	SALL				;;TURN LISTING BACK OFF

>; END DEFINE FNC
;GENERATE FUNCTION FLAGS TABLE

DF.PID==400000,,000000		;PORTAL ID REQUIRED
DF.AUB==200000,,000000		;ADDRESS CHECK USER BUFFER
DF.UPS==100000,,000000		;UPDATE USER PORTAL STATUS WORD
DF.ABL==000000,,000777		;MINIMUM ARGUMENT BLOCK LENGTH

DEFINE	DISP(FLAG,CODE,ABLN,ADDR),<
	EXP	FLAG!ABLN	;(CODE) ADDR
>; END DEFINE DISP

ENTDSF:	FNC			;GENERATE FUNCTION FLAGS TABLE
;GENERATE FUNCTION DISPATCH TABLE

DEFINE	DISP(FLAG,CODE,ABLN,ADDR),<
IF1,<IFN <CODE-<.-ENTDSP>>,<PRINTX ?Table ENTDSP entry CODE is out of order>>
	IFIW	ADDR		;(CODE) ADDR
>; END DEFINE DISP

ENTDSP:	FNC			;GENERATE FUNCTION DISPATCH TABLE
ENTMAX==.-ENTDSP-1		;MAXIMUM ETHNT. UUO FUNCTION CODE
	SUBTTL	ETHNT. UUO FUNCTIONS  --  OPEN USER PORTAL


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION OPEN USER PORTAL
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTOPN
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTOPN:	PUSHJ	P,ENTPRV	;JOB HAVE SUFFICIENT PRIVILEGES?
	  PJRST	ETEPRV		;NO, GIVE ERROR RETURN
	PUSHJ	P,CREUPB	;CREATE A NEW USER PORTAL BLOCK
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	EXCTUX	<MOVE	T1,.ETCIW(M)> ;GET CHANNEL IDENTIFICATION WORD
	ANDX	T1,ET.CID	;MASK TO CHANNEL ID
	DPB	T1,UPPCID	;STORE IN USER PORTAL BLOCK
	EXCTUX	<MOVE	T1,.ETPIW(M)> ;GET PROTOCOL IDENTIFICATION WORD
	MOVEM	T1,UPBPIW(F)	;STORE IN USER PORTAL BLOCK
	LDB	T1,UPPCID	;GET CHANNEL ID
	STOR	T1,UNCHN,(U)	;STORE IN UN BLOCK
	LDB	T1,UPPPTY	;GET PROTOCOL TYPE
	STOR	T1,UNPRO,(U)	;STORE IN UN BLOCK
	LDB	T1,UPPPAD	;GET PADDING FLAG
	STOR	T1,UNPAD,(U)	;STORE IN UN BLOCK
	MOVE	T1,EJBJCH(J)	;GET JCH OF PORTAL OWNER
	STOR	T1,UNJCH,(U)	;SAVE IN UN BLOCK
	STOR	F,UNUID,(U)	;SAVE CALLBACK ID IN UN BLOCK
	XMOVEI	T1,ENCINT	;GET CALLBACK ADDRESS
	STOR	T1,UNCBA,(U)	;SAVE IN UN BLOCK
	MOVEI	T1,NU.OPN	;GET ETHERNET OPEN PORTAL FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO OPEN PORTAL
	  JRST	ENEOPN		;ERROR, GO FREE UP PORTAL AND RETURN
	LOAD	T1,UNPID,(U)	;GET PORTAL ID ASSIGNED BY ETHSER
	DPB	T1,UPPPID	;SAVE IN PORTAL STATUS WORD
	PJRST	CPOPJ1##	;AND RETURN

;HERE ON AN ERROR RETURN FROM OPEN PORTAL FUNCTION

ENEOPN:	PUSH	P,T1		;SAVE ETHSER ERROR CODE
	PUSHJ	P,KILUPB	;DELETE THIS USER PORTAL BLOCK
	POP	P,T1		;RESTORE ETHSER ERROR CODE
	PJRST	ETEETH		;CONVERT ERROR CODE AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  CLOSE USER PORTAL


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION CLOSE USER PORTAL
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTCLS
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTCLS:	MOVEI	T1,NU.CLO!NU.WAI ;GET ETHERNET CLOSE PORTAL FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO CLOSE PORTAL
	  JFCL			;...
ENTCL1:	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE QUEUE HEADER
	PUSHJ	P,REMQUE	;DEQUEUE NEXT MONTITOR BUFFER DESCRIPTOR
	  JRST	ENTCL2		;NONE LEFT, GO EMPTY TRANSMIT QUEUE
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	JRST	ENTCL1		;LOOP BACK FOR ENTIRE RECEIVE QUEUE
ENTCL2:	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT QUEUE HEADER
	PUSHJ	P,REMQUE	;DEQUEUE NEXT MONTITOR BUFFER DESCRIPTOR
	  JRST	ENTCL3		;NONE LEFT, GO RELEASE USER PORTAL BLOCK
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	JRST	ENTCL2		;LOOP BACK FOR ENTIRE TRANSMIT QUEUE
ENTCL3:	PUSHJ	P,KILUPB	;DELETE USER PORTAL BLOCK
	PJRST	CPOPJ1##	;AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  QUEUE RECEIVE DATAGRAM BUFFER


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION QUEUE RECEIVE DATAGRAM BUFFER
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTQRB
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTQRB:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	EXCTUX	<SKIPA	P2,.ETUBL(M)> ;GET FIRST USER BUFFER DESCRIPTOR
ENTQR1:	EXCTUX	<MOVE	P2,.UBNXT(P2)> ;GET NEXT USER BUFFER DESCRIPTOR
	EXCTXU	<MOVEM	P2,.ETUBL(M)> ;SAVE CURRENT USER BUFFER DESCRIPTOR
	PJUMPE	P2,CPOPJ1##	;RETURN SUCCESS AT END OF LIST
	LDB	T1,UPPRBQ	;GET RECEIVE DATAGRAM BUFFER QUOTA
	CAMG	T1,UPBRBC(F)	;PORTAL WITHIN ITS QUOTA?
	PJRST	ETEBQE		;NO, BUFFER QUOTA EXCEEDED
	MOVE	T1,P2		;GET ADDRESS OF USER BUFFER DESCRIPTOR
	PUSHJ	P,GETMBD	;GET A MONITOR BUFFER AND DESCRIPTOR
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	MOVE	P1,T2		;SAVE ADDRESS IN P1
;$	SETZ	T1,		;CLEAR BYTE COUNT FOR MSD STYLE BUFFER
;$	STOR	T1,UNBSZ,(U)	;...
;$	XMOVEI	T1,.MBMSD(P1)	;GET ADDRESS OF MONITOR BUFFER'S MSD
;$	STOR	T1,UNBFA,(U)	;SAVE IN UN BLOCK
	MOVE	T1,.MBUBD+.UBBSZ(P1) ;$ GET USER DATAGRAM BYTE COUNT
	STOR	T1,UNBSZ,(U)	;$ ...
	MOVE	T1,MD.AUX+.MBMSD(P1) ;$ GET TWO WORD BYTE POINTER TO BUFFER
	MOVE	T2,MD.ALA+.MBMSD(P1) ;$ ...
	DMOVEM	T1,UN.BFA(U)	;$ SAVE IN UN BLOCK
	STOR	P1,UNRID,(U)	;SAVE MONITOR BUFFER DESCRIPTOR IN UN BLOCK
	MOVEI	T1,NU.RCV	;ETHERNET QUEUE RECEIVE DATAGRAM FUNCTION
	PUSHJ	P,CALETH	;CALL ETHSER TO QUEUE RECEIVE BUFFER
	  JRST	ENEQRB		;ERROR, ERROR CODE IN T1
	AOS	UPBRBC(F)	;INCREMENT RECEIVE DATAGRAM BUFFER COUNT
	JRST	ENTQR1		;LOOP BACK TO PROCESS ENTIRE BUFFER LIST

;HERE ON AN ERROR RETURN FROM QUEUE RECEIVE DATAGRAM FUNCTION

ENEQRB:	PUSH	P,T1		;SAVE ETHSER ERROR CODE
	MOVE	T2,P1		;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	POP	P,T1		;RESTORE ETHSER ERROR CODE
	PJRST	ETEETH		;CONVERT ERROR CODE AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ RECEIVE DATAGRAM QUEUE


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ RECEIVE DATAGRAM QUEUE
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRRQ
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRRQ:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	EXCTUX	<SKIPA	P2,.ETUBL(M)> ;GET FIRST USER BUFFER DESCRIPTOR
ENTRR1:	EXCTUX	<MOVE	P2,.UBNXT(P2)> ;GET NEXT USER BUFFER DESCRIPTOR
	EXCTXU	<MOVEM	P2,.ETUBL(M)> ;SAVE CURRENT USER BUFFER DESCRIPTOR
	PJUMPE	P2,CPOPJ1##	;RETURN SUCCESS AT END OF LIST
	MOVE	T1,P2		;GET ADDRESS OF USER BUFFER DESCRIPTOR
	MOVEI	T2,.UBLEN	;AND LENGTH OF DESCRIPTOR
	PUSHJ	P,ARNGE##	;ADDRESS CHECK USER BUFFER DESCRIPTOR
	 PJRST	ETEBAC		;BUFFER ADDRESS CHECK
	  JFCL			;ADDRESS ILLEGAL FOR I/O
	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE QUEUE
	PUSHJ	P,CHKQUE	;CHECK RECEIVE DATAGRAM QUEUE
	  PJRST	CPOPJ1##	;EMPTY, RETURN
	MOVE	P1,T2		;SAVE ADDRESS OF FIRST ENTRY IN P1
	MOVEI	T1,.UBLEN-1	;GET LENGTH OF SAVED USER BUFFER DESCRIPTOR
	XMOVEI	T2,.MBUBD+1(P1)	;GET ADDRESS OF SAVED USER BUFFER DESCRIPTOR
	MOVE	T3,P2		;AND ADDRESS OF CURRENT USER BUFFER DESCIPTOR
	AOJ	T3,		;...
	XBLTXU	<T1>		;COPY SAVED DESCRIPTOR TO USER DESCRIPTOR
	MOVE	T1,.MBUBA(P1)	;GET USER DATAGRAM BUFFER ADDRESS
	MOVE	T2,.MBDBS(P1)	;GET LENGTH OF DATAGRAM BUFFER
	PUSHJ	P,ARNGE##	;ADDRESS CHECK USER DATAGRAM BUFFER
	 PJRST	ENERRQ		;BUFFER ADDRESS CHECK
	  PJRST	ENERRQ		;BUFFER ADDRESS CHECK
	MOVE	T1,.MBDBS(P1)	;GET SIZE OF BUFFER IN WORDS
	MOVE	T2,.MBMBA(P1)	;GET MONITOR BUFFER ADDRESS
	MOVE	T3,.MBUBA(P1)	;GET ADDRESS OF USER DATAGRAM BUFFER
	XBLTXU	<T1>		;COPY MONITOR BUFFER INTO USER DATAGRAM
	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE QUEUE
	PUSHJ	P,REMQUE	;REMOVE ENTRY FROM QUEUE
	  JFCL			;CAN'T HAPPEN
	SOS	UPBRBC(F)	;DECREMENT RECEIVE DATAGRAM BUFFER COUNT
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	JRST	ENTRR1		;LOOP BACK TO PROCESS ENTIRE BUFFER LIST

				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

;HERE ON A BUFFER ADDRESS CHECK

ENERRQ:	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE QUEUE
	PUSHJ	P,REMQUE	;REMOVE ENTRY FROM QUEUE
	  JFCL			;CAN'T HAPPEN
	SOS	UPBRBC(F)	;DECREMENT RECEIVE DATAGRAM BUFFER COUNT
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	PJRST	ETEBAC		;RETURN BUFFER ADDRESS CHECK ERROR
	SUBTTL	ETHNT. UUO FUNCTIONS  --  QUEUE TRANSMIT DATAGRAM BUFFER


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION QUEUE TRANSMIT DATAGRAM BUFFER
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTQXB
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTQXB:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	EXCTUX	<SKIPA	P2,.ETUBL(M)> ;GET FIRST USER BUFFER DESCRIPTOR
ENTQX1:	EXCTUX	<MOVE	P2,.UBNXT(P2)> ;GET NEXT USER BUFFER DESCRIPTOR
	EXCTXU	<MOVEM	P2,.ETUBL(M)> ;SAVE CURRENT USER BUFFER DESCRIPTOR
	PJUMPE	P2,CPOPJ1##	;RETURN SUCCESS AT END OF LIST
	LDB	T1,UPPXBQ	;GET TRANSMIT DATAGRAM BUFFER QUOTA
	CAMG	T1,UPBXBC(F)	;PORTAL WITHIN ITS QUOTA?
	PJRST	ETEBQE		;NO, BUFFER QUOTA EXCEEDED
	MOVE	T1,P2		;GET ADDRESS OF USER BUFFER DESCRIPTOR
	PUSHJ	P,GETMBD	;GET A MONITOR BUFFER AND DESCRIPTOR
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	MOVE	P1,T2		;SAVE ADDRESS IN P1
	MOVE	T1,.MBDBS(P1)	;GET SIZE OF BUFFER IN WORDS
	MOVE	T2,.MBUBA(P1)	;GET ADDRESS OF USER DATAGRAM BUFFER
	MOVE	T3,.MBMBA(P1)	;GET MONITOR BUFFER ADDRESS
	XBLTUX	<T1>		;COPY USER DATAGRAM INTO MONITOR BUFFER
	SETZ	T1,		;CLEAR BYTE COUNT FOR MSD STYLE BUFFER
	STOR	T1,UNBSZ,(U)	;...
	XMOVEI	T1,.MBMSD(P1)	;GET ADDRESS OF MONITOR BUFFER'S MSD
	STOR	T1,UNBFA,(U)	;SAVE IN UN BLOCK
	DMOVE	T1,.MBUBD+.UBDEA(P1) ;GET DESTINATION ETHERNET ADDRESS
	DMOVEM	T1,UN.DAD(U)	;SAVE IN UN BLOCK
	STOR	P1,UNRID,(U)	;SAVE MONITOR BUFFER DESCRIPTOR IN UN BLOCK
	MOVEI	T1,NU.XMT	;ETHERNET QUEUE TRANSMIT DATAGRAM FUNCTION
	PUSHJ	P,CALETH	;CALL ETHSER TO QUEUE RECEIVE BUFFER
	  JRST	ENEQXB		;ERROR, ERROR CODE IN T1
	AOS	UPBXBC(F)	;INCREMENT TRANSMIT DATAGRAM BUFFER COUNT
	JRST	ENTQX1		;LOOP BACK TO PROCESS ENTIRE BUFFER LIST

;HERE ON AN ERROR RETURN FROM QUEUE TRANSMIT DATAGRAM FUNCTION

ENEQXB:	PUSH	P,T1		;SAVE ETHSER ERROR CODE
	MOVE	T2,P1		;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER DESCRIPTOR
	POP	P,T1		;RESTORE ETHSER ERROR CODE
	PJRST	ETEETH		;CONVERT ERROR CODE AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ TRANSMIT DATAGRAM QUEUE


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ TRANSMIT DATAGRAM QUEUE
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRXQ
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRXQ:	PUSHJ	P,SAVE2##	;SAVE P1-P2
	EXCTUX	<SKIPA	P2,.ETUBL(M)> ;GET FIRST USER BUFFER DESCRIPTOR
ENTRX1:	EXCTUX	<MOVE	P2,.UBNXT(P2)> ;GET NEXT USER BUFFER DESCRIPTOR
	EXCTXU	<MOVEM	P2,.ETUBL(M)> ;SAVE CURRENT USER BUFFER DESCRIPTOR
	PJUMPE	P2,CPOPJ1##	;RETURN SUCCESS AT END OF LIST
	MOVE	T1,P2		;GET ADDRESS OF USER BUFFER DESCRIPTOR
	MOVEI	T2,.UBLEN	;AND LENGTH OF DESCRIPTOR
	PUSHJ	P,ARNGE##	;ADDRESS CHECK USER BUFFER DESCRIPTOR
	 PJRST	ETEBAC		;BUFFER ADDRESS CHECK
	  JFCL			;ADDRESS ILLEGAL FOR I/O
	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT QUEUE
	PUSHJ	P,CHKQUE	;CHECK TRANSMIT DATAGRAM QUEUE
	  PJRST	CPOPJ1##	;EMPTY, RETURN
	MOVE	P1,T2		;SAVE ADDRESS OF FIRST ENTRY IN P1
	MOVEI	T1,.UBLEN-1	;GET LENGTH OF SAVED USER BUFFER DESCRIPTOR
	XMOVEI	T2,.MBUBD+1(P1)	;GET ADDRESS OF SAVED USER BUFFER DESCRIPTOR
	MOVE	T3,P2		;AND ADDRESS OF CURRENT USER BUFFER DESCIPTOR
	AOJ	T3,		;...
	XBLTXU	<T1>		;COPY SAVED DESCRIPTOR TO USER DESCRIPTOR
	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT QUEUE
	PUSHJ	P,REMQUE	;REMOVE ENTRY FROM QUEUE
	  JFCL			;CAN'T HAPPEN
	SOS	UPBXBC(F)	;DECREMENT TRANSMIT DATAGRAM BUFFER COUNT
	PUSHJ	P,GIVMBD	;FREE UP MONITOR BUFFER AND DESCRIPTOR
	JRST	ENTRX1		;LOOP BACK TO PROCESS ENTIRE BUFFER LIST
	SUBTTL	ETHNT. UUO FUNCTIONS  --  ENABLE/DISABLE MULTI-CAST ADDRESS


;ROUTINE CALLED TO PROCESS ETHNT. MULTI-CAST ADDRESS FUNCTIONS
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTEMA/ENTDMA
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTEMA:	SKIPA	T1,[NU.EMA]	;GET ENABLE MULTI-CAST FUNCTION CODE
ENTDMA:	MOVEI	T1,NU.DMA	;GET DISABLE MULTI-CAST FUNCTION CODE
	EXCTUX	<DMOVE	T2,.ETMCA(M)> ;GET MULTI-CAST ADDRESS
	DMOVEM	T2,UN.DAD(U)	;STORE INTO UN BLOCK
	PUSHJ	P,CALETH	;CALL ETHSER
	  PJRST	ETEETH		;GO CONVERT ERROR CODE AND RETURN
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ CHANNEL LIST


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ CHANNEL LIST
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRCL
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRCL:	MOVEI	T1,NU.RCL	;ETHERNET READ CHANNEL LIST FUNCTION
	PJRST	ENTRXL		;READ LIST INTO USER BUFFER AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ CHANNEL INFORMATION


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ CHANNEL INFORMATION
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRCI
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRCI:	EXCTUX	<MOVE	T1,.ETCSW(M)> ;GET CHANNEL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RCI	;ETHERNET READ CHANNEL INFORMATION FUNCTION
	PUSHJ	P,ENTRXI	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED CHANNEL STATUS WORD
	EXCTXU	<MOVEM	T1,.ETCSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ CHANNEL COUNTERS


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ CHANNEL COUNTERS
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRCC
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRCC:	EXCTUX	<MOVE	T1,.ETCSW(M)> ;GET CHANNEL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RCC!NU.WAI ;ETHERNET READ CHANNEL COUNTERS FUNCTION
	PUSHJ	P,ENTRXC	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED CHANNEL STATUS WORD
	EXCTXU	<MOVEM	T1,.ETCSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  SET CHANNEL ADDRESS


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION SET CHANNEL ADDRESS
;LINKAGE:
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTSCA
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTSCA:	EXCTUX	<MOVE	T1,.ETCSW(M)> ;GET CHANNEL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	EXCTUX	<DMOVE	T2,.ETEAD(M)> ;GET ETHERNET ADDRESS
	DMOVEM	T2,UN.DAD(U)	;STORE INTO UN BLOCK
	MOVEI	T1,NU.SCA!NU.WAI ;GET SET CHANNEL ADDRESS FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO SET CHANNEL ADDRESS AND RETURN
	  PJRST	ETEETH		;ERROR, CONVERT ERROR CODE AND RETURN
	LOAD	T1,UNSID,(U)	;GET UPDATED CHANNEL STATUS WORD
	EXCTXU	<MOVEM	T1,.ETCSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ PORTAL LIST


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ PORTAL LIST
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRPL
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRPL:	EXCTUX	<MOVE	T1,.ETCSW(M)> ;GET CHANNEL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RPL	;ETHERNET READ PORTAL LIST FUNCTION
	PJRST	ENTRXL		;READ LIST INTO USER BUFFER AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ PORTAL INFORMATION


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ PORTAL INFORMATION
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRPI
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRPI:	EXCTUX	<MOVE	T1,.ETPSW(M)> ;GET PORTAL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RPI	;ETHERNET READ PORTAL INFORMATION FUNCTION
	PUSHJ	P,ENTRXI	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED PORTAL STATUS WORD
	EXCTXU	<MOVEM	T1,.ETPSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ PORTAL COUNTERS


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ PORTAL COUNTERS
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRPC
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRPC:	EXCTUX	<MOVE	T1,.ETPSW(M)> ;GET PORTAL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RPC!NU.WAI ;ETHERNET READ PORTAL COUNTERS FUNCTION
	PUSHJ	P,ENTRXC	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED PORTAL STATUS WORD
	EXCTXU	<MOVEM	T1,.ETPSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ KONTROLLER LIST


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ KONTROLLER LIST
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRKL
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRKL:	EXCTUX	<MOVE	T1,.ETCSW(M)> ;GET CHANNEL STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RKL	;ETHERNET READ KONTROLLER LIST FUNCTION
	PJRST	ENTRXL		;READ LIST INTO USER BUFFER AND RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ KONTROLLER INFORMATION


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ KONTROLLER INFORMATION
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRKI
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRKI:	EXCTUX	<MOVE	T1,.ETKSW(M)> ;GET KONTROLLER STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RKI	;ETHERNET READ KONTROLLER INFORMATION FUNCTION
	PUSHJ	P,ENTRXI	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED KONTROLLER STATUS WORD
	EXCTXU	<MOVEM	T1,.ETKSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTIONS  --  READ KONTROLLER COUNTERS


;ROUTINE CALLED TO PROCESS ETHNT. FUNCTION READ KONTROLLER COUNTERS
;LINKAGE:
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRKC
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

ENTRKC:	EXCTUX	<MOVE	T1,.ETKSW(M)> ;GET KONTROLLER STATUS WORD
	STOR	T1,UNSID,(U)	;STORE IN UN BLOCK
	MOVEI	T1,NU.RKC!NU.WAI ;ETHERNET READ KONTROLLER COUNTERS FUNCTION
	PUSHJ	P,ENTRXC	;READ DATA INTO USER BUFFER
	  POPJ	P,		;ERROR, ERROR CODE ALREADY STORED
	LOAD	T1,UNSID,(U)	;GET UPDATED KONTROLLER STATUS WORD
	EXCTXU	<MOVEM	T1,.ETKSW(M)> ;STORE IN USER ARGUMENT BLOCK
	PJRST	CPOPJ1##	;RETURN
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  READ ETHERNET LIST


;ROUTINE CALLED TO READ ETHERNET LIST INTO USER BUFFER
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRXL
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	USER AC/ SIZE OF RETURNED DATA

ENTRXL:	PJRST	ENTRXD		;READ ETHERNET LIST
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  READ ETHERNET INFORMATION


;ROUTINE CALLED TO READ ETHERNET INFORMATION INTO USER BUFFER
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRXI
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	USER AC/ SIZE OF RETURNED DATA

ENTRXI:	PJRST	ENTRXD		;READ ETHERNET INFORMATION
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  READ ETHERNET COUNTERS


;ROUTINE CALLED TO READ ETHERNET COUNTERS INTO USER BUFFER
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRXC
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	USER AC/ SIZE OF RETURNED DATA

ENTRXC:	TXNN	P4,ET.FZC	;IS THIS A READ/ZERO COUNTERS FUNCTION
	TDZA	T2,T2		;NO, CLEAR ZERO COUNTERS FLAG AND SKIP
	MOVEI	T2,1		;YES, SET ZERO COUNTERS FLAGS
	STOR	T2,UNZRO,(U)	;SET/CLEAR ZERO COUNTERS FLAG IN UN BLOCK
	PJUMPE	T2,ENTRXD	;CONTINUE IF JUST READ COUNTERS
	PUSH	P,T1		;SAVE ETHERNET FUNCTION CODE
	PUSHJ	P,ENTPRV	;JOB HAVE SUFFICIENT PRIVILEGES?
	  JRST	[POP	P,(P)	;NO, CLEAR STACK
		 PJRST	ETEPRV]	;AND GIVE ERROR RETURN
	POP	P,T1		;RESTORE ETHERNET FUNCTION CODE
	PJRST	ENTRXD		;AND CONTINUE
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  READ ETHERNET DATA


;ROUTINE CALLED TO READ ETHERNET DATA INTO USER BUFFER
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	P1/ SIZE OF USER BUFFER
;	P2/ ADDRESS OF USER BUFFER
;	P4/ FUNCTION CODE WORD
;	U/ ADDRESS OF UN BLOCK
;	M/ ADDRESS OF ARGUMENT BLOCK
;	PUSHJ	P,ENTRXD
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	USER AC/ SIZE OF RETURNED DATA

ENTRXD:	PUSH	P,T1		;SAVE ETHERNET FUNCTION CODE
	MOVE	T2,P1		;GET SIZE OF USER BUFFER
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED MONITOR CORE FOR BUFFER
	  JRST	[POP	P,(P)	;ERROR, CLEAR STACK
		 PJRST	ETERES]	;AND RETURN INSUFFICIENT RESOURCES ERROR
	STOR	P1,UNBSZ,(U)	;STORE BUFFER SIZE IN UN BLOCK
	STOR	T1,UNBFA,(U)	;AND BUFFER ADDRESS IN UN BLOCK
	STOR	U,UNRID,(U)	;STORE ADDRESS OF UN BLOCK AS REQUEST ID
	POP	P,T1		;GET BACK ETHERNET FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO READ ETHERNET LIST
	  JRST	ENERXD		;ERROR, GO FREE UP BUFFER AND RETURN
	MOVE	T1,P1		;GET SIZE OF USER BUFFER
	LOAD	T2,UNBFA,(U)	;GET ADDRESS OF MONITOR BUFFER
	MOVE	T3,P2		;AND ADDRESS OF USER BUFFER
	XBLTXU	<T1>		;COPY MONITOR BUFFER INTO USER BUFFER
	LOAD	T1,UNBSZ,(U)	;GET COUNT OF ENTRIES STORED
	PUSHJ	P,STOTAC##	;STORE IN USER AC
	MOVE	T1,P1		;GET SIZE OF MONITOR BUFFER
	LOAD	T2,UNBFA,(U)	;AND ADDRESS OF MONITOR BUFFER
	PUSHJ	P,GIVEWS##	;RELEASE MONITOR BUFFER
	PJRST	CPOPJ1##	;AND RETURN

;HERE ON AN ERROR RETURN FROM READ ETHERNET DATA FUNCTION

ENERXD:	PUSH	P,T1		;SAVE ETHSER ERROR CODE
	MOVE	T1,P1		;GET SIZE OF MONITOR BUUFER
	LOAD	T2,UNBFA,(U)	;AND ADDRESS OF MONITOR BUFFER
	PUSHJ	P,GIVEWS##	;RELEASE MONITOR BUFFER
	POP	P,T1		;RESTORE ETHSER ERROR CODE
	PJRST	ETEETH		;CONVERT ERROR CODE AND RETURN
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  ETHSER INTERFACE


;ROUTINE CALLED TO INTERFACE TO ETHSER
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,CALETH
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	T1/ ERROR CODE (UNXXX%)
;	CPOPJ1 ON SUCCESS

CALETH:	LDB	T2,UPPPID	;GET PORTAL ID
	STOR	T2,UNPID,(U)	;STORE IN UN BLOCK
	MOVE	T2,U		;GET ADDRESS OF UN BLOCK
	TXZN	T1,NU.WAI	;WAIT FOR FUNCTION COMPLETION?
	PJRST	ETHSER##	;NO, DISPATCH TO ETHSER AND RETURN
	MOVEM	T1,UPBFWC(F)	;SAVE ETHERNET FUNCTION WAIT CODE
	PUSHJ	P,ETHSER##	;CALL ETHSER FOR FUNCTION
	  POPJ	P,		;ERROR, ERROR CODE IN T1
	AOS	(P)		;PRESET FOR SKIP RETURN
	PJRST	ENTSLP		;WAIT FOR FUNCTION COMPLETION AND RETURN
	SUBTTL	ETHNT. UUO FUNCTION SUPPORT  --  ETHSER ERROR CODE CONVERSION


;ROUTINE CALLED TO CONVERT ETHSER ERROR CODE INTO ETHNT. ERROR CODE
;LINKAGE:
;	T1/ ETHSER ERROR CODE (UNXXX%)
;	PUSHJ	P,ETEETH
;RETURNS:
;	CPOPJ ALWAYS WITH:
;	USER AC/ ERROR CODE (ETXXX%)

ETEETH:	MOVEI	T3,ETETLN	;GET LENGTH OF ERROR TABLE
	XMOVEI	T4,ETETAB	;AND ADDRESS OF ERROR TABLE
ETEET1:	HLRZ	T2,(T4)		;GET NEXT ETHSER ERROR CODE FROM TABLE
	CAMN	T1,T2		;MATCH TARGET ERROR CODE?
	JRST	ETEET2		;YES, EXIT LOOP
	XMOVEI	T4,1(T4)	;INCREMENT ERROR TABLE ADDRESS
	SOJG	T3,ETEET1	;LOOP BACK TO CHECK COMPLETE TABLE
	STOPCD	ETEUEE,DEBUG,ENTUEE ;++UNEXPECTED ETHSER ERROR CODE
ETEET2:	HRRZ	T1,(T4)		;PICK UP CORRECT ETHNT. ERROR CODE
	PJRST	STOTAC##	;STORE ERROR CODE IN USER AC AND RETURN


;TABLE OF ETHSER TO ETHNT ERROR CODE CORRESPONDENCE

ETETAB:	UNRES%,,ETRES%		;NO RESOUCES
	UNNSC%,,ETICI%		;NO SUCH CHANNEL
	UNIVP%,,ETIPT%		;ILLEGAL PROTOCOL TYPE
	UNPIU%,,ETPIU%		;PROTOCOL TYPE IN USE
	UNPRA%,,ETPRA%		;PROMISCUOUS RECEIVER ACTIVE
	UNNSP%,,ETIPI%		;NO SUCH PORTAL
	UNIBS%,,ETIBS%		;ILLEGAL BUFFER SIZE
	UNIBP%,,ETIBP%		;ILLEGAL BYTE POINTER
	UNNRE%,,ETRES%		;NO ROOM FOR ENTRY
	UNIMA%,,ETIEA%		;ILLEGAL MULTICAST ADDRESS
	UNICA%,,ETIEA%		;ILLEGAL CHANNEL ADDRESS
	UNPWS%,,ETPWS%		;PROTOCOL IN WRONG STATE
	UNNSK%,,ETIKI%		;NO SUCH KONTROLLER
ETETLN==.-ETETAB		;LENGTH OF ERROR CODE TABLE
	SUBTTL	ETHNT. UUO COMPLETION INTERRUPT  --  INTERRUPT DISPATCH


;ROUTINE CALLED BY ETHERNET SUPPORT ON COMPLETION OF A FUNCTION
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	T2/ ADDRESS OF UN BLOCK
;	T3/ FUNCTION SPECIFIC DATA
;	PUSHJ	P,ENCINT
;RETURNS:
;	CPOPJ ALWAYS

ENCINT::PUSHJ	P,SAVJW##	;SAVE J AND W
	PUSH	P,F		;AND F
	PUSH	P,U		;AND U
	MOVE	U,T2		;SAVE UN BLOCK ADDRESS IN U
	LOAD	F,UNUID,(U)	;GET ADDRESS OF USER PORTAL BLOCK
	MOVE	J,UPBEJB(F)	;GET ADDRESS OF ETHERNET JOB BLOCK
	PUSH	P,T1		;SAVE ETHERNET FUNCTION CODE
	PUSHJ	P,ENTWAK	;WAKE UP ANY WAITING JOB
	POP	P,T1		;RESTORE ETHERNET FUNCTION CODE
	MOVE	T1,ENCDSP(T1)	;GET ADDRESS OF FUNCTION SPECIFIC ROUTINE
	PUSHJ	P,(T1)		;DISPATCH
	POP	P,U		;AND U
	POP	P,F		;AND F
	POPJ	P,		;AND RETURN
	SUBTTL	ETHNT. UUO COMPLETION INTERRUPT  --  DISPATCH TABLE


;FUNCTION SPECIFIC COMPLETION ROUTINE DISPATCH TABLE

DEFINE	FNC,<

XALL				;;LIST GENERATED TABLE

DISP	0,CPOPJ##		;;PLACE HOLDER
DISP	NU.OPN,	CPOPJ##		;;OPEN PORTAL
DISP	NU.CLO,	CPOPJ##		;;CLOSE PORTAL
DISP	NU.RCV,	ENCRDG		;;RECEIVE DATAGRAM
DISP	NU.XMT,	ENCXDG		;;TRANSMIT DATAGRAM
DISP	NU.EMA,	CPOPJ##		;;ENABLE MULTI-CAST
DISP	NU.DMA,	CPOPJ##		;;DISABLE MULTI-CAST

DISP	NU.RCL,	ENCRXD		;;READ CHANNEL LIST
DISP	NU.RCI,	ENCRXD		;;READ CHANNEL INFORMATION
DISP	NU.RCC,	ENCRXD		;;READ CHANNEL COUNTERS
DISP	NU.SCA,	CPOPJ##		;;SET CHANNEL ADDRESS

DISP	NU.RPL,	ENCRXD		;;READ PORTAL LIST
DISP	NU.RPI,	ENCRXD		;;READ PORTAL INFORMATION
DISP	NU.RPC,	ENCRXD		;;READ PORTAL COUNTERS

DISP	NU.RKL,	ENCRXD		;;READ KONTROLLER LIST
DISP	NU.RKI,	ENCRXD		;;READ KONTROLLER INFORMATION
DISP	NU.RKC,	ENCRXD		;;READ KONTROLLER COUNTERS

SALL				;;TURN LISTING BACK OFF

>; END DEFINE FNC
;GENERATE FUNCTION DISPATCH TABLE

DEFINE	DISP(CODE,ADDR),<
IF1,<IFN <CODE-<.-ENCDSP>>,<PRINTX ?Table ENCDSP entry CODE is out of order>>
	IFIW	ADDR		;CODE
>; END DEFINE DISP

ENCDSP:	FNC			;GENERATE FUNCTION DISPATCH TABLE
IF1,<IFN <NU.MAX-<.-ENCDSP-1>>,<PRINTX ?Table ENCDSP is missing entries>>
	SUBTTL	ETHNT. UUO COMPLETION INTERRUPT  --  RECEIVE DATAGRAM


;ROUTINE CALLED BY ETHSER ON COMPLETION OF RECEIVE DATAGRAM FUNCTION
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,ENCRDG
;RETURNS:
;	CPOPJ ALWAYS

ENCRDG:	PUSHJ	P,SAVE1##	;SAVE P1
	LOAD	P1,UNRID,(U)	;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	SETZ	T1,		;GET DEFAULT DATAGRAM STATUS
	SKIPE	T3		;ANY ERRORS?
	TXO	T1,UB.ERR	;YES, SET ERROR FLAG
	MOVEM	T1,.MBUBD+.UBSTS(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	LOAD	T1,UNBSZ,(U)	;GET SIZE OF RECEIVED DATAGRAM
	MOVEM	T1,.MBUBD+.UBBSZ(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	LOAD	T1,UNPRO,(U)	;GET PROTOCOL TYPE
	MOVEM	T1,.MBUBD+.UBPTY(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	DMOVE	T1,UN.SAD(U)	;GET SOURCE ETHERNET ADDRESS
	DMOVEM	T1,.MBUBD+.UBSEA(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	DMOVE	T1,UN.DAD(U)	;GET DESTINATION ETHERNET ADDRESS
	DMOVEM	T1,.MBUBD+.UBDEA(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	MOVE	T1,MD.AUX+.MBMSD(P1) ;$ GET ORIGINAL BYTE POINTER
	MOVE	T2,MD.ALA+.MBMSD(P1) ;$ ...
ENCRD1:	CAMLE	T2,UN.BFA+1(U)	;$ GONE TOO FAR?
	JRST	ENCRD2		;$ YES, EXIT LOOP AND GIVE UP
	CAMN	T2,UN.BFA+1(U)	;$ GONE FAR ENOUGH?
	CAME	T1,UN.BFA(U)	;$ ...
	SKIPA			;$ NO, CONTINUE UPDATING BYTE POINTERS
	JRST	ENCRD2		;$ YES, EXIT LOOP
	IBP	T1		;$ UPDATE MONITOR BUFFER BYTE POINTER
	IBP	.MBUBD+.UBBFA(P1) ;$ AND USER BUFFER BYTE POINTER
	JRST	ENCRD1		;$ LOOP BACK UNTIL ALIGNED THE SAME
ENCRD2:	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE DATAGRAM QUEUE
	MOVE	T2,P1		;AND ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,PUTQUE	;ADD MONITOR BUFFER DESCRIPTOR TO QUEUE
	PJRST	UPDPSW		;UPDATE PORTAL STATUS AND RETURN
	SUBTTL	ETHNT. UUO COMPLETION INTERRUPT  --  TRANSMIT DATAGRAM


;ROUTINE CALLED BY ETHSER ON COMPLETION OF TRANSMIT DATAGRAM FUNCTION
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,ENCXDG
;RETURNS:
;	CPOPJ ALWAYS

ENCXDG:	PUSHJ	P,SAVE1##	;SAVE P1
	LOAD	P1,UNRID,(U)	;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	SETZ	T1,		;GET DEFAULT DATAGRAM STATUS
	SKIPE	T3		;ANY ERRORS?
	TXO	T1,UB.ERR	;YES, SET ERROR FLAG
	MOVEM	T1,.MBUBD+.UBSTS(P1) ;SAVE IN USER BUFFER DESCRIPTOR BLOCK
	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT DATAGRAM QUEUE
	MOVE	T2,P1		;AND ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,PUTQUE	;ADD MONITOR BUFFER DESCRIPTOR TO QUEUE
	PJRST	UPDPSW		;UPDATE PORTAL STATUS AND RETURN
	SUBTTL	ETHNT. UUO COMPLETION INTERRUPT  --  READ ETHERNET DATA


;ROUTINE CALLED BY ETHSER ON COMPLETION OF READ ETHERNET DATA FUNCTIONS
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,ENCRXD
;RETURNS:
;	CPOPJ ALWAYS

ENCRXD:	LOAD	T2,UNRID,(U)	;GET ADDRESS OF ORIGINAL UN BLOCK
	PJUMPE	T2,ENCRCI	;PROCESS DIFFERENTLY IF UNSOLICITED CALLBACK
	LOAD	T1,UNBSZ,(U)	;GET UPDATED BUFFER SIZE
	STOR	T1,UNBSZ,(T2)	;STORE IN ORIGINAL UN BLOCK
	POPJ	P,		;AND RETURN


;HERE ON UNSOLICITED READ CHANNEL INFORMATION CALLBACK

ENCRCI:	LOAD	T1,UNRUN,(U)	;GET PORTAL RUN FLAG
	DPB	T1,[POINTR (UPBPSW(F),ET.PON)] ;STORE PORTAL ONLINE STATUS
	PJRST	UPDPSW		;UPDATE PORTAL STATUS AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  ETHERNET JOB BLOCK MANIPULATION


;ROUTINE CALLED TO CREATE AN ETHERNET JOB BLOCK
;LINKAGE:
;	W/ ADDRESS OF JOB'S PDB
;	PUSHJ	P,CREEJB
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	F/ ADDRESS OF INFORMATION PORTAL BLOCK

CREEJB:	MOVEI	T2,EJBLEN	;GET LENGTH OF ETHERNET JOB BLOCK
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED CORE FOR JOB BLOCK
	  PJRST	ETERES		;ERROR, INSUFFICIENT RESOURCES
	MOVE	J,T1		;SAVE ADDRESS OF JOB BLOCK IN J
	MOVE	T1,.CPJCH##	;GET JCH OF JOB BLOCK OWNER
	MOVEM	T1,EJBJCH(J)	;STORE IN ETHERNET JOB BLOCK
	MOVEM	J,.PDEJB##(W)	;SET UP POINTER TO JOB'S EJB
	XMOVEI	T1,EJBPSQ(J)	;GET ADDRESS OF PSI QUEUE HEADER
	PUSHJ	P,INIQUE	;INITIALIZE QUEUE
	MOVEI	T2,UPBLEN	;GET LENGTH OF USER PORTAL BLOCK
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED CORE FOR INFORMATION PORTAL
	  JRST	CREEJ1		;ERROR, INSUFFICIENT RESOURCES
	MOVEM	T1,EJBINF(J)	;SAVE ADDRESS OF INFORMATION PORTAL BLOCK
	MOVEM	J,UPBEJB(T1)	;SAVE ADDRESS OF ETHERNET JOB BLOCK
	XMOVEI	U,EJBUNB(J)	;GET ADDRESS OF UN BLOCK
	PUSHJ	P,OPNINF	;OPEN THE INFORMATION PORTAL
	  PJRST	KILEJB		;ERROR, ERROR CODE ALREADY STORED
	MOVE	T1,ENTUPQ	;GET DEFAULT USER PORTAL QUOTA
	MOVEM	T1,EJBUPQ(J)	;SET UP IN ETHERNET JOB BLOCK
	MOVE	T1,ENTBQT	;GET DEFAULT BUFFER QUOTAS
	MOVEM	T1,EJBBQT(J)	;SET UP IN ETHERNET JOB BLOCK
	MOVE	T2,EJBUPQ(J)	;GET USER PORTAL QUOTA
	JUMPE	T2,CPOPJ1##	;ALL DONE IF ZERO PORTAL QUOTA
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED CORE FOR PORTAL TABLE
	  JRST	CREEJ1		;ERROR, INSUFFICIENT RESOURCES
	MOVEM	T1,EJBUPT(J)	;SAVE ADDRESS OF USER PORTAL TABLE
	PJRST	CPOPJ1##	;AND RETURN

;HERE ON RESOURCE ERROR ALLOCATING INFORMATION PORTAL OR USER PORTAL TABLE

CREEJ1:	PUSHJ	P,KILEJB	;RELEASE ETHERNET JOB BLOCK
	PJRST	ETERES		;AND RETURN INSUFFICIENT RESOURCES ERROR
;ROUTINE CALLED TO RELEASE AN ETHERNET JOB BLOCK
;LINKAGE:
;	W/ ADDRESS OF JOB'S PDB
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,KILEJB
;RETURNS:
;	CPOPJ ALWAYS

KILEJB:	SKIPN	J,.PDEJB##(W)	;GET POINTER TO JOB'S EJB
	POPJ	P,		;NONE, RETURN
	SETZM	.PDEJB##(W)	;ZERO POINTER TO ETHERNET JOB BLOCK
	SKIPE	EJBUPC(J)	;MAKE SURE USER PORTAL COUNT ZERO
	STOPCD	.+1,DEBUG,ENTPCN ;++USER PORTAL COUNT NON-ZERO
	PUSHJ	P,CLSINF	;CLOSE THE INFORMATION PORTAL
	MOVEI	T1,UPBLEN	;GET LENGTH OF USER PORTAL BLOCK
	SKIPE	T2,EJBINF(J)	;AND ADDRESS OF INFORMATION PORTAL BLOCK
	PUSHJ	P,GIVEWS##	;RELEASE INFORMATION PORTAL BLOCK
	MOVE	T2,EJBUPT(J)	;GET ADDRESS OF USER PORTAL TABLE
	SKIPE	T1,EJBUPQ(J)	;AND USER PORTAL QUOTA
	PUSHJ	P,GIVEWS##	;RELEASE USER PORTAL TABLE
	MOVEI	T1,EJBLEN	;GET LENGTH OF ETHERNET JOB BLOCK
	MOVE	T2,J		;AND ADDRESS OF JOB BLOCK
	PJRST	GIVEWS##	;RELEASE ETHERNET JOB BLOCK AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  USER PORTAL BLOCK MANIPULATION


;ROUTINE CALLED TO FIND A USER PORTAL BLOCK
;LINKAGE:
;	T1/ PORTAL ID
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,FNDUPB
;RETURNS:
;	CPOPJ ON ERROR
;	CPOPJ1 ON SUCCESS WITH:
;	F/ ADDRESS OF USER PORTAL BLOCK

FNDUPB:	MOVE	T3,EJBUPQ(J)	;GET USER PORTAL QUOTA
	MOVE	T4,EJBUPT(J)	;AND ADDRESS OF USER PORTAL TABLE
FNDUP1:	PJUMPE	T3,CPOPJ##	;RETURN AT END OF USER PORTAL TABLE
	SKIPN	F,(T4)		;GET ADDRESS OF NEXT USER PORTAL BLOCK
	JRST	FNDUP2		;NONE, CONTINUE SEARCHING TABLE
	LDB	T2,UPPPID	;GET PORTAL ID
	CAMN	T1,T2		;A MATCH?
	PJRST	CPOPJ1##	;YES, RETURN
FNDUP2:	XMOVEI	T4,1(T4)	;INCREMENT USER PORTAL TABLE ADDRESS
	SOJA	T3,FNDUP1	;LOOP BACK FOR ENTIRE TABLE
;ROUTINE CALLED TO CREATE A USER PORTAL BLOCK
;LINKAGE:
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,CREUPB
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	F/ ADDRESS OF USER PORTAL BLOCK

CREUPB:	MOVE	T1,EJBUPC(J)	;GET CURRENT USER PORTAL COUNT
	CAML	T1,EJBUPQ(J)	;BELOW PORTAL QUOTA?
	PJRST	ETEPQE		;NO, PORTAL QUOTA EXCEEDED
	MOVEI	T2,UPBLEN	;GET LENGTH OF PORTAL BLOCK
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED CORE FOR PORTAL BLOCK
	  PJRST	ETERES		;ERROR, INSUFFICIENT RESOURCES
	MOVE	F,T1		;SAVE ADDRESS OF PORTAL BLOCK
	MOVEM	J,UPBEJB(F)	;SAVE ADDRESS OF ETHERNET JOB BLOCK
	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE DATAGRAM QUEUE
	PUSHJ	P,INIQUE	;INITIALIZE QUEUE HEADER
	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT DATAGRAM QUEUE
	PUSHJ	P,INIQUE	;INITIALIZE QUEUE HEADER
	MOVE	T1,EJBBQT(J)	;GET JOB WIDE PORTAL BUFFER QUOTAS
	MOVEM	T1,UPBBQT(F)	;SAVE IN PORTAL BLOCK
	MOVE	T3,EJBUPQ(J)	;GET USER PORTAL QUOTA
	MOVE	T4,EJBUPT(J)	;AND ADDRESS OF USER PORTAL TABLE
CREUP1:	SKIPN	(T4)		;FOUND AN EMPTY SLOT IN USER PORTAL TABLE
	JRST	CREUP2		;YES, EXIT LOOP
	XMOVEI	T4,1(T4)	;INCREMENT USER PORTAL TABLE ADDRESS
	SOJG	T3,CREUP1	;LOOP BACK FOR ENTIRE TABLE
	STOPCD	.+1,DEBUG,ENTPTF ;++USER PORTAL TABLE FULL
	MOVEI	T1,UPBLEN	;GET LENGTH OF USER PORTAL BLOCK
	MOVE	T2,F		;AND ADDDRESS OF USER PORTAL BLOCK
	PUSHJ	P,GIVEWS##	;RELEASE PORTAL BLOCK MEMORY
	PJRST	ETEPQE		;AND RETURN PORTAL QUOTA EXCEEDED ERROR
CREUP2:	AOS	EJBUPC(J)	;INCREMENT USER PORTAL COUNT
	MOVEM	F,(T4)		;SAVE USER PORTAL IN USER PORTAL TABLE
	PJRST	CPOPJ1##	;RETURN
;ROUTINE CALLED TO RELEASE A USER PORTAL BLOCK
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,KILUPB
;RETURNS:
;	CPOPJ ALWAYS

KILUPB:	MOVE	T3,EJBUPQ(J)	;GET USER PORTAL QUOTA
	MOVE	T4,EJBUPT(J)	;AND ADDRESS OF USER PORTAL TABLE
KILUP1:	CAMN	F,(T4)		;FOUND USER PORTAL BEING DELETED?
	JRST	KILUP2		;YES, EXIT LOOP
	XMOVEI	T4,1(T4)	;INCREMENT USER PORTAL TABLE ADDRESS
	SOJG	T3,KILUP1	;LOOP BACK FOR ENTIRE TABLE
	STOPCD	KILUP3,DEBUG,ENTMPB ;++MISSING USER PORTAL BLOCK
KILUP2:	SETZM	(T4)		;CLEAR USER PORTAL TABLE ENTRY
	SOS	EJBUPC(J)	;DECREMENT USER PORTAL COUNT
KILUP3:	XMOVEI	T1,EJBPSQ(J)	;GET ADDRESS OF PSI PENDING QUEUE
	XMOVEI	T2,UPBPSQ(F)	;AND ADDRESS OF PSI QUEUE LINKAGE
	PUSHJ	P,DELQUE	;DELETE PORTAL FROM PSI PENDING QUEUE
	MOVEI	T1,UPBLEN	;GET LENGTH OF PORTAL BLOCK
	MOVE	T2,F		;AND ADDRESS
	PJRST	GIVEWS##	;RELEASE MEMORY AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  MONITOR BUFFER MANIPULATION


;ROUTINE CALLED TO CREATE A MONITOR BUFFER AND DESCRIPTOR
;LINKAGE:
;	T1/ ADDRESS OF USER BUFFER DESCRIPTOR
;	PUSHJ	P,GETMBD
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS WITH:
;	T2/ ADDRESS OF MONITOR BUFFER DESCRIPTOR

GETMBD:	PUSHJ	P,SAVE4##	;SAVE P1-P4
	MOVE	P2,T1		;SAVE ADDRESS OF USER BUFFER DESCRIPTOR
	MOVEI	T2,.UBLEN	;GET LENGTH OF USER BUFFER DESCRIPTOR
	PUSHJ	P,ARNGE##	;ADDRESS CHECK USER BUFFER DESCRIPTOR
	 PJRST	ETEBAC		;BUFFER ADDRESS CHECK
	  JFCL			;ADDRESS ILLEGAL FOR I/O
	PUSH	P,M		;SAVE M FOR A BIT
	EXCTUX	<DMOVE	T1,.UBBFA(P2)>	;GET USER BYTE POINTER
	EXCTUX	<MOVE	T3,.UBBSZ(P2)>	;AND USER BYTE COUNT
	MOVE	M,P2		;USE .UBSTS WORD FOR SCRATCH LOCATION
	ADDI	M,.UBSTS	;...
	PUSHJ	P,QRNGE##	;ADDRESS CHECK USER DATAGRAM BUFFER
	 JRST	GETMB1		;BUFFER ADDRESS CHECK
	  JRST	GETMB1		;ADDRESS ILLEGAL FOR I/O
	POP	P,M		;RESTORE M
	PUSHJ	P,GTWGBP##	;GENERATE TWO WORD GLOBAL USER BYTE POINTER
	DMOVE	P3,T1		;SAVE RESOLVED USER BYTE POINTER
	MOVEI	T2,.MBLEN	;GET SIZE OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,GETEWZ##	;ALLOCATE ZEROED CORE FOR DESCRIPTOR
	  PJRST	ETERES		;ERROR, INSUFFICIENT RESOURCES
	MOVE	P1,T1		;SAVE ADDRESS OF MONITOR BUFFER DESCRIPTOR
	MOVEI	T1,.UBLEN-1	;GET LENGTH OF SAVED USER BUFFER DESCRIPTOR
	MOVE	T2,P2		;GET ADDRESS OF CURRENT USER BUFFER DESCRIPTOR
	ADDI	T2,.UBNXT+1	;COPY ALL BUT POINTER TO NEXT BUFFER DESCRIPTOR
	XMOVEI	T3,.MBUBD+.UBNXT+1(P1) ;GET ADDRESS OF SAVED BUFFER DESCRIPTOR
	XBLTUX	<T1>		;COPY USER DESCRIPTOR TO SAVED DESCRIPTOR

				;CONTINUED ON NEXT PAGE
				;CONTINUED FROM PREVIOUS PAGE

	MOVEM	P3,MD.AUX+.MBMSD(P1) ;SET UP P&S PORTION OF MSD
	MOVEM	P4,.MBUBA(P1)	;SAVE USER BUFFER ADDRESS
	LDB	T2,[POINT 6,P3,5] ;GET POSITION FIELD FROM BYTE POINTER
	IDIVI	T2,^D8		;COMPUTE BYTE OFFSET
	SUBI	T2,4		;...
	MOVMS	T2		;...
	TRZN	T2,4		;WORD ALIGNED ON SECOND WORD?
	TDZA	T1,T1		;NO, GET A ZERO
	MOVEI	T1,1		;YES, GET A ONE
	MOVNM	T1,MD.ALA+.MBMSD(P1) ;PRESET MONITOR BUFFER BYTE POINTER
	ADDM	T1,.MBUBA(P1)	;ADJUST USER BUFFER ADDRESS
	ADD	T2,.MBUBD+.UBBSZ(P1) ;ADD USER BYTE COUNT TO BYTE OFFSET
	ADDI	T2,3		;CONVERT TO WORD COUNT
	ASH	T2,-2		;...
	MOVEM	T2,.MBDBS(P1)	;SAVE AS DATAGRAM BUFFER SIZE
	PUSHJ	P,GETMBF	;ALLOCATE MONITOR BUFFER
	  JRST	GETMB2		;ERROR, INSUFFICIENT RESOURCES
	MOVEM	T1,.MBMBA(P1)	;SAVE ADDRESS OF MONITOR BUFFER
	ADDM	T1,MD.ALA+.MBMSD(P1) ;SET UP MONITOR BUFFER BYTE POINTER
	MOVE	T1,.MBUBD+.UBBSZ(P1) ;GET USER DATAGRAM BYTE COUNT
	MOVEM	T1,MD.BYT+.MBMSD(P1) ;SAVE IN MONITOR BUFFER MSD
	MOVE	T2,P1		;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PJRST	CPOPJ1##	;AND RETURN


;HERE ON USER BUFFER ADDRESS CHECK

GETMB1:	POP	P,M		;RESTORE M
	PJRST	ETEBAC		;GIVE BUFFER ADDRESS CHECK ERROR


;HERE ON RESOURCE ERROR ALLOCATING MONITOR BUFFER

GETMB2:	MOVE	T2,P1		;GET ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PUSHJ	P,GIVMBD	;RELEASE MONITOR BUFFER AND DESCRIPTOR
	PJRST	ETERES		;GIVE INSUFFICIENT RESOURCES ERROR
;ROUTINE CALLED TO RELEASE A MONITOR BUFFER AND DESCRIPTOR
;LINKAGE:
;	T2/ ADDRESS OF MONITOR BUFFER DESCRIPTOR
;	PUSHJ	P,GIVMBD
;RETURNS:
;	CPOPJ ALWAYS

GIVMBD:	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,T2		;SAVE ADDRESS OF MONITOR BUFFER DESCRIPTOR
	MOVE	T1,.MBDBS(P1)	;GET DATAGRAM BUFFER SIZE
	SKIPE	T2,.MBMBA(P1)	;AND ADDRESS OF MONITOR BUFFER
	PUSHJ	P,GIVMBF	;RELEASE MONITOR BUFFER
	MOVEI	T1,.MBLEN	;GET LENGTH OF MONITOR BUFFER DESCRIPTOR
	MOVE	T2,P1		;AND ADDRESS OF MONITOR BUFFER DESCRIPTOR
	PJRST	GIVEWS##	;RELEASE MONITOR BUFFER DESCRIPTOR AND RETURN
;ROUTINE CALLED TO ALLOCATE A MONITOR BUFFER
;LINKAGE:
;	T2/ SIZE OF MONITOR BUFFER
;	PUSHJ	P,GETMBF
;RETURNS:
;	CPOPJ ON RESOURCE ERROR
;	CPOPJ1 ON SUCCESS WITH:
;	T1/ ADDRESS OF MONITOR BUFFER

GETMBF:	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;GET OUR JOB NUMBER
	PUSHJ	P,GFWNZS##	;ALLOCATE MONITOR BUFFER
	  PJRST	JPOPJ##		;ERROR, RESTORE J AND RETURN
	PJRST	JPOPJ1##	;RESTORE J AND RETURN
;ROUTINE CALLED TO DEALLOCATE A MONITOR BUFFER
;LINKAGE:
;	T1/ SIZE OF MONITOR BUFFER
;	T2/ ADDRESS OF MONITOR BUFFER
;	PUSHJ	P,GIVMBF
;RETURNS:
;	CPOPJ ALWAYS

GIVMBF:	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;GET OUR JOB NUMBER
	PUSHJ	P,GVFWDS##	;DEALLOCATE MONITOR BUFFER
	PJRST	JPOPJ##		;RESTORE J AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  INFORMATION PORTAL MANIPULATION


;ROUTINE CALLED TO OPEN AN INFORMATION PORTAL
;LINKAGE:
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,OPNINF
;RETURNS:
;	CPOPJ ON ERROR WITH:
;	USER AC/ ERROR CODE (ETXXX%)
;	CPOPJ1 ON SUCCESS

OPNINF:	MOVE	F,EJBINF(J)	;GET ADDRESS OF INFORMATION USER PORTAL
	SETZ	T1,		;USE ETHERNET CHANNEL ZERO
	STOR	T1,UNCHN,(U)	;STORE IN UN BLOCK
	MOVX	T1,PT%INF	;GET INFORMATION PSEUDO-PROTOCOL TYPE
	STOR	T1,UNPRO,(U)	;STORE IN UN BLOCK
	MOVE	T1,EJBJCH(J)	;GET JCH OF PORTAL OWNER
	STOR	T1,UNJCH,(U)	;SAVE IN UN BLOCK
	STOR	F,UNUID,(U)	;SAVE CALLBACK ID IN UN BLOCK
	XMOVEI	T1,ENCINT	;GET CALLBACK ADDRESS
	STOR	T1,UNCBA,(U)	;SAVE IN UN BLOCK
	MOVEI	T1,NU.OPN	;GET ETHERNET OPEN PORTAL FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO OPEN PORTAL
	  PJRST	ETEETH		;ERROR, GO CONVERT ERROR CODE AND RETURN
	LOAD	T1,UNPID,(U)	;GET PORTAL ID ASSIGNED BY ETHSER
	DPB	T1,UPPPID	;SAVE IN PORTAL STATUS WORD
	PJRST	CPOPJ1##	;AND RETURN
;ROUTINE CALLED TO CLOSE AN INFORMATION PORTAL
;LINKAGE:
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	U/ ADDRESS OF UN BLOCK
;	PUSHJ	P,CLSINF
;RETURNS:
;	CPOPJ ALWAYS

CLSINF:	MOVE	F,EJBINF(J)	;GET ADDRESS OF INFORMATION PORTAL
	MOVEI	T1,NU.CLO	;GET ETHERNET CLOSE PORTAL FUNCTION CODE
	PUSHJ	P,CALETH	;CALL ETHSER TO CLOSE PORTAL
	  JFCL			;ERROR, CAN'T DO MUCH
	POPJ	P,		;RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  FUNCTION COMPLETION EVENT WAIT


;ROUTINE CALLED TO WAIT FOR FUNCTION COMPLETION
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,ENTSLP
;RETURNS:
;	CPOPJ ALWAYS UPON FUNCTION COMPLETION

ENTSLP:	MOVEI	T1,EV.ETH	;GET ETHERNET EVENT WAIT CODE
	PUSH	P,J		;SAVE J
	MOVE	J,EJBJCH(J)	;GET JCH OF PORTAL OWNER
	ANDI	J,JOBMSK##	;MASK TO JUST JOB NUMBER
	PUSHJ	P,FSLEEP##	;WAIT FOR FUNCTION COMPLETION
	POP	P,J		;RESTORE J
	SKIPE	UPBFWC(F)	;FUNCTION COMPLETED?
	JRST	ENTSLP		;NO, WAIT TILL FUNCTION COMPLETES
	POPJ	P,		;RETURN
;ROUTINE CALLED TO SIGNAL FUNCTION COMPLETION
;LINKAGE:
;	T1/ ETHERNET FUNCTION CODE (NU.XXX)
;	F/ ADDRESS OF USER PORTAL BLOCK
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,ENTWAK
;RETURNS:
;	CPOPJ ALWAYS

ENTWAK:	CAME	T1,UPBFWC(F)	;FUNCTION WE'RE WAITING FOR?
	POPJ	P,		;NO, RETURN
	SETZM	UPBFWC(F)	;YES, INDICATE FUNCTION HAS COMPLETED
	MOVE	T1,EJBJCH(J)	;GET JCH OF PORTAL OWNER
	PUSHJ	P,CTXEWK##	;WAKE UP CONTEXT
	  JFCL			;SHOULD SKIP
	POPJ	P,		;RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  PORTAL STATUS UPDATE


;ROUTINE CALLED TO UPDATE PORTAL STATUS
;LINKAGE:
;	F/ ADDRESS OF USER PORTAL BLOCK
;	J/ ADDRESS OF ETHERNET JOB BLOCK
;	PUSHJ	P,UPDPSW
;RETURNS:
;	CPOPJ ALWAYS

UPDPSW:	ETHLOK			;INTERLOCK AGAINST RACES
	PUSH	P,S		;SAVE S
	MOVE	S,UPBPSW(F)	;GET CURRENT PORTAL STATUS
	TXO	S,ET.PRB!ET.PXB	;SET DATAGRAM BUFFER AVAILABLE FLAGS
	XMOVEI	T1,UPBRQH(F)	;GET ADDRESS OF RECEIVE QUEUE HEADER
	PUSHJ	P,CHKQUE	;IS QUEUE EMPTY?
	  TXZ	S,ET.PRB	;YES, CLEAR RECEIVE DATAGRAM AVAILABLE FLAG
	XMOVEI	T1,UPBXQH(F)	;GET ADDRESS OF TRANSMIT QUEUE HEADER
	PUSHJ	P,CHKQUE	;IS QUEUE EMPTY?
	  TXZ	S,ET.PXB	;YES, CLEAR TRANSMIT DATAGRAM AVAILABLE FLAG
	MOVEM	S,UPBPSW(F)	;STORE UPDATED PORTAL STATUS
	EXCH	S,UPBPPS(F)	;GET AND UPDATE PREVIOUS PORTAL STATUS
	XOR	S,UPBPPS(F)	;MASK TO CHECK DIFFERENCES
	TXNE	S,ET.PST	;PORTAL STATUS CHANGED?
	SKIPE	UPBPSQ(F)	;YES, USER PORTAL ALREADY ON PSI QUEUE?
	JRST	STOPS1		;NO CHANGE OR ALREADY ON PSI QUEUE
	XMOVEI	T1,EJBPSQ(J)	;GET ADDRESS OF PSI QUEUE HEADER
	XMOVEI	T2,UPBPSQ(F)	;AND ADDRESS OF QUEUE LINKAGE
	PUSHJ	P,PUTQUE	;ADD PORTAL TO PSI QUEUE
	PUSH	P,J		;SAVE J
	MOVE	J,EJBJCH(J)	;GET JCH OF PORTAL OWNER
	SIGNAL	C$ETH		;SIGNAL ETHERNET EVENT
	  JFCL			;...
	POP	P,J		;RESTORE J
STOPS1:
	ETHULK			;RELEASE INTERLOCK
	POP	P,S		;RESTORE S
	POPJ	P,		;AND RETURN
	SUBTTL	ETHNT. UUO SUPPORT  --  QUEUE MANIPULATION


;ROUTINE CALLED TO INITIALIZE A QUEUE
;LINKAGE:
;	T1/ ADDRESS OF QUEUE HEADER
;	PUSHJ	P,INIQUE
;RETURNS:
;	CPOPJ ALWAYS

INIQUE:	MOVEM	T1,.QHFLI(T1)	;POINT QUEUE AT ITSELF
	MOVEM	T1,.QHBLI(T1)	;...
	SETZM	.QHCNT(T1)	;ZERO QUEUE ENTRY COUNT
	POPJ	P,		;AND RETURN
;ROUTINE CALLED TO CHECK FOR EMPTY QUEUE
;LINKAGE:
;	T1/ ADDRESS OF QUEUE HEADER
;	PUSHJ	P,CHKQUE
;RETURNS:
;	CPOPJ ON EMPTY QUEUE
;	CPOPJ1 ON NON-EMPTY QUEUE WITH:
;	T2/ ADDRESS OF FIRST QUEUE ENTRY

CHKQUE:	MOVE	T2,.QHFLI(T1)	;GET ADDRESS OF FIRST QUEUE ENTRY
	CAME	T1,T2		;IS QUEUE EMPTY?
	AOS	(P)		;NO, PRESET SKIP RETURN
	POPJ	P,		;RETURN
;ROUTINE CALLED TO DELETE AN ENTRY FROM A QUEUE
;LINKAGE:
;	T1/ ADDRESS OF QUEUE HEADER
;	T2/ ADDRESS OF QUEUE ENTRY
;	PUSHJ	P,DELQUE
;RETURNS:
;	CPOPJ ALWAYS

DELQUE:	ETHLOK			;INTERLOCK QUEUE ACCESS
	XMOVEI	T4,.QHFLI-.QEFLI(T1) ;PRESET ADDRESS OF "PREVIOUS" ENTRY
DELQU1:	MOVE	T3,T4		;SAVE ADDRESS OF PREVIOUS QUEUE ENTRY
	MOVE	T4,.QEFLI(T4)	;GET ADDRESS OF NEXT QUEUE ENTRY
	CAMN	T4,.QHFLI(T1)	;AT END OF QUEUE?
	PJRST	UNLETH##	;YES, RETURN
	CAME	T4,T2		;FOUND SUBJECT QUEUE ENTRY?
	JRST	DELQU1		;NO, LOOP BACK FOR ENTIRE QUEUE
	MOVE	T4,.QEFLI(T4)	;GET ADDRESS OF NEXT QUEUE ENTRY
	MOVEM	T4,.QEFLI(T3)	;UNLINK SUBJECT QUEUE ENTRY
	SETZM	.QEFLI(T2)	;CLEAR LINK WORD
	PJRST	UNLETH##	;RELEASE INTERLOCK AND RETURN
;ROUTINE CALLED TO REMOVE AN ENTRY FROM A QUEUE
;LINKAGE:
;	T1/ ADDRESS OF QUEUE HEADER
;	PUSHJ	P,REMQUE
;RETURNS:
;	CPOPJ IF QUEUE EMPTY
;	CPOPJ1 IF SUCCESS WITH:
;	T2/ ADDRESS OF QUEUE ENTRY

REMQUE:	ETHLOK			;INTERLOCK QUEUE ACCESS
	CAMN	T1,.QHFLI(T1)	;QUEUE EMPTY?
	PJRST	UNLETH##	;YES, RELEASE INTERLOCK AND RETURN
	MOVE	T2,.QHFLI(T1)	;GET ADDRESS OF FIRST QUEUE ENTRY
	MOVE	T3,.QEFLI(T2)	;GET ADDRESS OF NEXT QUEUE ENTRY
	MOVEM	T3,.QHFLI(T1)	;STORE AS NEW FIRST ENTRY IN QUEUE
	CAMN	T1,.QHFLI(T1)	;QUEUE NOW EMPTY?
	MOVEM	T1,.QHBLI(T1)	;YES, RESET POINTER TO LAST ENTRY
	SOS	.QHCNT(T1)	;DECREMENT COUNT OF ENTRIES IN QUEUE
	ETHULK			;RELEASE INTERLOCK
	SETZM	.QEFLI(T2)	;CLEAR ENTRY'S FORWARD QUEUE LINK
	PJRST	CPOPJ1##	;AND RETURN
;ROUTINE CALLED TO ADD AN ENTRY TO A QUEUE
;LINKAGE:
;	T1/ ADDRESS OF QUEUE HEADER
;	T2/ ADDRESS OF QUEUE ENTRY
;	PUSHJ	P,PUTQUE
;RETURNS:
;	CPOPJ ALWAYS

PUTQUE:	ETHLOK			;INTERLOCK QUEUE ACCESS
	MOVE	T3,.QHBLI(T1)	;GET ADDRESS OF LAST ENTRY ON QUEUE
	MOVEM	T2,.QEFLI(T3)	;POINT IT AT NEW ENTRY
	MOVEM	T2,.QHBLI(T1)	;MAKE NEW ENTRY THE LAST ENTRY ON QUEUE
	MOVEM	T1,.QEFLI(T2)	;...
	AOS	.QHCNT(T1)	;INCREMENT COUNT OF ENTRIES IN QUEUE
	PJRST	UNLETH##	;RELEASE INTERLOCK AND RETURN
	SUBTTL	PRIVILEGE CHECKING


;ROUTINE CALLED TO CHECK IF A JOB HAS ETHERNET PRIVILEGES
;(TRANSLATES TO POKE PRIVILEGES)
;LINKAGE:
;	PUSHJ	P,ENTPRV
;RETURNS:
;	CPOPJ IF UNPRIVILEGED
;	CPOPJ1 IF PRIVILEGED

ENTPRV:	PUSH	P,J		;SAVE J
	MOVE	J,.CPJOB##	;PRVBIT WANTS JOB NUMBER IN J
	MOVSI	T1,JP.POK	;GET THE BIT
	PUSHJ	P,PRVBIT##	;SEE IF PRIVILEGED
	  JRST	JPOPJ1##	;YES, RESTORE J AND SKIP RETURN
	JRST	JPOPJ##		;NO, RESTORE J AND NON-SKIP RETURN
	SUBTTL	BYTE POINTERS


;BYTE POINTERS FOR USER PORTAL BLOCK

UPPCID:	POINTR	(UPBCSW(F),ET.CID)	;ETHERNET CHANNEL ID
UPPPAD:	POINTR	(UPBPIW(F),ET.PAD)	;PADDING FLAG
UPPPTY:	POINTR	(UPBPIW(F),ET.PTY)	;PROTOCOL TYPE CODE
UPPPID:	POINTR	(UPBPSW(F),ET.PID)	;PORTAL ID

UPPXBQ:	POINTR	(UPBBQT(F),UPQXBQ)	;TRANSMIT BUFFER QUOTA
UPPRBQ:	POINTR	(UPBBQT(F),UPQRBQ)	;RECEIVE BUFFER QUOTA
	SUBTTL	DEFAULT VALUE STORAGE


;ETHERNET JOB BLOCK DEFAULTS

ENTUPQ:	EXP	%ETUPQ##	;USER PORTAL QUOTA
ENTBQT:	EXP	%ETBQT##	;DATAGRAM BUFFER QUOTAS
	SUBTTL	THE END


ENTLIT:!XLIST			;LITERALS
	LIT
	LIST

ENTEND:!END