Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Q-SM - monitor-sources/nisrv.mac
There are 19 other files named nisrv.mac in the archive. Click here to see a list.
; UPD ID= 8565, RIP:<7.MONITOR>NISRV.MAC.2,  11-Feb-88 11:42:59 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 2134, SNARK:<6.1.MONITOR>NISRV.MAC.27,   5-Jun-85 10:05:40 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 2029, SNARK:<6.1.MONITOR>NISRV.MAC.26,  28-May-85 17:07:49 by GROSSMAN
;TCO 6.1.1414 - Make NU.RPI require a valid portal ID.  Also make it return
;the User ID.
; UPD ID= 1902, SNARK:<6.1.MONITOR>NISRV.MAC.25,   4-May-85 19:20:14 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1819, SNARK:<6.1.MONITOR>NISRV.MAC.24,  24-Apr-85 19:50:48 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1807, SNARK:<6.1.MONITOR>NISRV.MAC.23,  24-Apr-85 13:50:59 by GROSSMAN
;TCO 6.1.1342 - Add 'external' portal ID support (NU.CXI and friends).
; UPD ID= 1801, SNARK:<6.1.MONITOR>NISRV.MAC.22,  23-Apr-85 17:32:50 by GROSSMAN
;TCO 6.1.1337 - Move SETNIA to NIUSR.
; UPD ID= 1679, SNARK:<6.1.MONITOR>NISRV.MAC.21,  25-Mar-85 10:58:52 by GROSSMAN
;TCO 6.1.1285 - Fix NU.RPI.
; UPD ID= 1290, SNARK:<6.1.MONITOR>NISRV.MAC.20,   9-Jan-85 11:05:27 by GROSSMAN
;TCO 6.1.1122 - Move to section 6.
; UPD ID= 1274, SNARK:<6.1.MONITOR>NISRV.MAC.19,   5-Jan-85 16:01:10 by GROSSMAN
;TCO 6.1.1113 - Remove request for NITEST from here.
; UPD ID= 1266, SNARK:<6.1.MONITOR>NISRV.MAC.18,   4-Jan-85 09:05:26 by GROSSMAN
;TCO 6.1.1109 - Remove extra RESCDs.  Get rid of unused NF. functions and
;routines and their callbacks.  Totally re-do DLLDMA.
; UPD ID= 1186, SNARK:<6.1.MONITOR>NISRV.MAC.17,  11-Dec-84 14:52:50 by GROSSMAN
;TCO 6.1.1081 - Make errors during .NICLO clear PRCLO so that the close may be
;tried again.
; UPD ID= 1148, SNARK:<6.1.MONITOR>NISRV.MAC.16,   5-Dec-84 00:37:17 by GROSSMAN
;TCO 6.1.1072 - Remove useless calls to NIRES and NISTP.  Fix CLOCBK to return
;+1 always.
; UPD ID= 1134, SNARK:<6.1.MONITOR>NISRV.MAC.15,  28-Nov-84 13:45:39 by GROSSMAN
;TCO 6.1.1064 - Change all calls to DNGWDx to ASGRES.
; UPD ID= 1047, SNARK:<6.1.MONITOR>NISRV.MAC.14,  12-Nov-84 23:38:40 by GROSSMAN
;TCO 6.1.1046 - Don't use NIBARF anymore, just pass the error upwards.
; UPD ID= 758, SNARK:<6.1.MONITOR>NISRV.MAC.12,  27-Aug-84 11:58:50 by GROSSMAN
;Disable FTHIST.
; UPD ID= 756, SNARK:<6.1.MONITOR>NISRV.MAC.11,  26-Aug-84 23:34:28 by GROSSMAN
;Remove DCN feature test in lieu of finding a new home for SETNIA.
; UPD ID= 755, SNARK:<6.1.MONITOR>NISRV.MAC.10,  26-Aug-84 10:29:11 by GROSSMAN
;Put DECnet address generator under DCN feature test.
; UPD ID= 750, SNARK:<6.1.MONITOR>NISRV.MAC.9,  23-Aug-84 09:31:22 by GROSSMAN
;Implement DLLSCS (Set channel state).
;Remove junk code.
; UPD ID= 736, SNARK:<6.1.MONITOR>NISRV.MAC.8,  10-Aug-84 17:27:10 by GROSSMAN
;Make SETNIA smart enough to set the DECnet address on it's own.
; UPD ID= 714, SNARK:<6.1.MONITOR>NISRV.MAC.7,  27-Jul-84 00:13:08 by GROSSMAN
;Fix close of information portals.
; UPD ID= 556, SNARK:<6.1.MONITOR>NISRV.MAC.6,  24-May-84 14:03:06 by GROSSMAN
;Return channel status in NU.OPN.
;Add history buffer maintenance code.
; UPD ID= 520, SNARK:<6.1.MONITOR>NISRV.MAC.5,  14-May-84 09:45:09 by GROSSMAN
;Fix opening of information portals.
; UPD ID= 465, SNARK:<6.1.MONITOR>NISRV.MAC.4,  27-Apr-84 13:37:55 by GROSSMAN
;Implement NISRV.MEM.
; UPD ID= 367, SNARK:<6.1.MONITOR>NISRV.MAC.2,   2-Mar-84 02:27:01 by GROSSMAN
;Add PRFQA to portal block.  Used by PHYKNI to find the free queue header
;address efficiently.
;Put consistency checking into entry points
; UPD ID= 317, SNARK:<6.1.MONITOR>NISRV.MAC.1,   8-Feb-84 17:33:18 by GROSSMAN
;Create this module from NIDLL

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1988.
;	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 THAT IS NOT SUPPLIED BY DIGITAL.
	SUBTTL Stu Grossman
	SUBTTL Preamble

	; Searches

IFE TOPS-20 <
	SEARCH PROLOG		; Standard monitor defs

	; Define a Title

	TTITLE NISRV,,< - NI Data Link Layer>

	FTHINI==-1		; -1 means produce skyseg code

IFE FTHINI,<
	RESCD>			; NISRV/PHYKNI is mostly resident
IFN FTHINI,<
	XRESCD>			; Put us in the skyseg


>

IFE TOPS-10 <
	SEARCH	F,S		;SYSTEM PARAMETERS
	SEARCH	MACSYM
	SEARCH	D36PAR

	$RELOC
	$HIGH

	TITLE NISRV - NI Data Link Layer

	STDAC.			;GET STANDARD AC'S FROM MACSYM
	FTNITEST=0		;TEMPORARILY (SOON IN FGEN.HLP)
>
	SEARCH NIPAR

	; Special AC definitions

	DEFAC UN,Q1		; Points to UN block (user arg)
	DEFAC PR,Q2		; Points to portal (PR) block
	Subttl	Table of Contents

;		     Table of Contents for NISRV
;
;				  Section		      Page
;
;
;    1. Special Definitions For TOPS10/TOPS20 Compatibility  .   4
;    2. Function dispatch flags  . . . . . . . . . . . . . . .   5
;    3. Constant definitions
;        3.1    NISRV to PHYKNI interface  . . . . . . . . . .   6
;    4. Macro Definitions
;        4.1    ERROR - Report an NISRV error code . . . . . .   7
;        4.2    Interrupt control macros . . . . . . . . . . .   8
;        4.3    Portal Table Block . . . . . . . . . . . . . .   9
;    5. DLLUNI - User to NIDLL interface routine . . . . . . .  10
;    6. DLLOPN - Open an NISRV portal  . . . . . . . . . . . .  11
;    7. DLLCLO - Close a DLL port  . . . . . . . . . . . . . .  12
;    8. DLLEMA/DLLDMA - Enable/Disable a multicast address . .  13
;    9. DLLXMT - Send a DLL message  . . . . . . . . . . . . .  14
;   10. DLLRCV - DLL Specify Recieve Buffer  . . . . . . . . .  15
;   11. DLLPCB - Port Driver Call Back routine . . . . . . . .  16
;   12. DLLICB - Call Back from Port Driver was unknown  . . .  17
;   13. DLLPST - Post A Message as being transmitted . . . . .  18
;   14. DLLLSC - Line state Changed  . . . . . . . . . . . . .  19
;   15. DLLRPC - Read Portal Counters  . . . . . . . . . . . .  20
;   16. DLLRCI - Read Channel Information  . . . . . . . . . .  21
;   17. DLLSCA - Set Channel Address . . . . . . . . . . . . .  22
;   18. DLLRPL - Read Portal List  . . . . . . . . . . . . . .  23
;   19. DLLRCL - Read Channel List . . . . . . . . . . . . . .  24
;   20. DLLRPI - Read Portal Information . . . . . . . . . . .  25
;   21. Network management
;       21.1    Set Channel State  . . . . . . . . . . . . . .  26
;       21.2    Convert External Portal ID to Internal Portal   27
;       21.3    Read Channel Counters  . . . . . . . . . . . .  28
;   22. CALUSR - Calls the user up after setting up the UN blo  29
;   23. FNDEXI - Search for an external portal ID  . . . . . .  30
;   24. ALLPOR - Co-routine for looping through all portals  .  31
;   25. Miscellaneous routines . . . . . . . . . . . . . . . .  32
;   26. Static Storage . . . . . . . . . . . . . . . . . . . .  33
;   27. End of NISRV . . . . . . . . . . . . . . . . . . . . .  34
	SUBTTL Special Definitions For TOPS10/TOPS20 Compatibility

IFE TOPS-10 <
	EXTERNAL RTN		;COMMON SUBROUTINE RETURN (CPOPJ)
	EXTERNAL XBLTA		;EXTENDED BLT
	EXTERNAL PI.TFP		;TURN OFF SELECTED PI
	EXTERNAL PI.TNP		;TURN ON SELECTED PI

	KIEPT==.CPEPT##		;LOCATION OF EPT
	DLSCHN==NETCHN##	;PRIORITY INTERRUPT ASSIGNMENT FOR KLNI
	PIPIIP==LI.IPA##	;INTERRUPT IN PROGRESS CHANNELS

	OPDEF	RETBAD	[POPJ P,] ;ERROR RETURN
	OPDEF	EA.ENT	[PUSHJ P,SSEC1##] ;MAKE SURE WE ARE NON ZERO SECTION
	OPDEF	UNBRK	[JRST]

	DEFINE	SAVEPQ	<SAVEAC <P1,P2,P3>> ;ROOM TO WORK
	DEFINE	NOSKED	<>	;DON,T HAVE TO WORRY ABOUT THESE
	DEFINE	OKSKED	<>	;  IN TOPS10
	DEFINE	RESCD	<>	;  "
	DEFINE	TNXEND	<>	;  "

	DEFINE CHNOFF (CHN) <
	CONO	PI,PI.TFP+1B<28+CHN>>	;TURN OFF SELECTED PI

	DEFINE	CHNON (CHN) <
	CONO	PI,PI.TNP+1B<28+CHN>>	;TURN ON SELECTED PI

	KNIN=1			;NUMBER OF KLNI'S (TEMPORARILY)
				;  SOON TO BE M.KNI?

> ;END IFE TOPS-10
	SUBTTL Function dispatch flags

	FC.POR==1B2		;PORTAL ID IS REQUIRED
	SUBTTL Constant definitions -- NISRV to PHYKNI interface

	..VAL==-1		; Make values start at 0

	NF.ILL==.VAL.		;ILLEGAL FUNCTION CODE
	NF.XMT==.VAL.		;MSG XMITTED	XMIT MESSAGE
	NF.RCV==.VAL.		;MSG RCVIED	POST RECIEVE BUFFER
	NF.LSC==.VAL.		;LINE STATE HAS CHANGED
	NF.RDC==.VAL.		;READ CN COMP	READ COUNTERS (AND ZERO)
	NF.DPT==.VAL.		;		DISABLE PROTOCOL TYPE
	NF.EMA==.VAL.		;		ENABLE MULTICAST ADDRESS
	NF.DMA==.VAL.		;		DISABLE MULTICAST ADDRESS
	NF.ASP==.VAL.		;ASSIGN PROTOCOL
	NF.RCI==.VAL.		;READ CHANNEL INFO
	NF.CLO==.VAL.		;CLOSE PORTAL
	NF.SCA==.VAL.		;SET CHANNEL ADDRESS
	NF.RPC==.VAL.		;READ PORTAL COUNTERS
	NF.SCS==.VAL.		;SET CHANNEL STATE
	NF.RPI==.VAL.		;READ PORTAL INFORMATION
	NF.MAX==.VAL.		;MAXIMUM NF FUNCTION
	NF.MAX==NF.MAX-1	; Correct the maximum
	SUBTTL Macro Definitions -- ERROR - Report an NISRV error code

; Call:	ERROR UNxyz%

	DEFINE ERROR (SYM)<JRST <ERET(SYM)>>

	DEFINE ERET (SYM)<INTERR (\SYM)>

	DEFINE INTERR (SYM)<RET'SYM>

;Generate error returns

	X==1

	DEFINE XX (VAL)<RET'VAL: JSP T1,RETX>

RETBAS:
	REPEAT UNMAX%,<
	XX (\X)
	X==X+1
	>
RETX:	TLZ T1,-1		; Zero the left half
	SUBI T1,RETBAS		; Compute offset
	RET			; And return
	SUBTTL Macro Definitions -- Interrupt control macros

	OPDEF NIOFF [CALL .NIOFF]	; Disables KLNI interrupts
	OPDEF NION [CALL .NION]		; Enables KLNI interrupts

	FTHIST==0			; Disable history buffer stuff
	SUBTTL Macro Definitions -- Portal Table Block

; Data Structures
; Portal Table block

BEGSTR PR
	WORD	NXT		; Pointer to next block (must be first)

	FIELD	FLG,9		; Flags
	  BIT	CLO		;  Portal is closing
	  BIT	PAD		;  Pad flag

	FIELD	EXI,9		; External portal ID
	HWORD	BSZ		; Receive buffer size
	WORD	UID		; What user wants on callback
	HWORD	PMD		; Packing mode
	HWORD	PRO		; Protocol type (bytes swapped)
	WORD	CHN		; Ethernet channel block address

	WORD	MUL		; Bit vector of enabled multicasts
	WORD	POS		; Callback address
	WORD	CHK		; Check word (address of this block)
	WORD	FQA		; Free queue header address
	WORD	OXM		; Outstanding transmits
	WORD	ORC		; Outstanding receives

	WORD	TLZ		; Time at which counters were zeroed
	WORD	BYR		; Bytes received
	WORD	DGR		; Datagrams received
	WORD	BYS		; Bytes sent
	WORD	DGS		; Datagrams sent
	WORD	UBU		; User buffer unavailable
	ENDSTR
	SUBTTL DLLUNI - User to NIDLL interface routine

;
; Called:
;	MOVEI T1,<Function code>
;	MOVE T2,<Address of block>
;	CALL DLLUNI
;	 error return (in T1)
;	success return

IFN FTHINI,RESCD

DLLUNI::EA.ENT			; Make sure we are in section 1

IFN FTHINI,<
	JRST @[DLLUN1]		; Jump to the skyseg
	XRESCD			; Change PSECTs
DLLUN1:
>

IFN FTHIST,<
	CALL RECUNB		; Record UN block
>; End of IFN FTHIST

	SAVEAC <UN,PR>		; Save our permanent AC's
	SKIPLE T1		; Function too small?
	 CAXLE T1,NU.MAX	;  No, function too large?
	  ERROR UNIFC%		;   Yes to either... Illegal Function Code
	MOVE T1,USRDSP-1(T1)	; Get dispatch bits
	MOVE UN,T2		; Setup UN
	JUMPLE UN,ERET UNIUA%	; Jump if illegal UN block address
	TXNN T1,FC.POR		; Should we check for a valid portal ID?
	 JRST (T1)		;  No, dispatch
	LOAD PR,UNPID,(UN)	; Get his PID (Portal block address)
	JUMPLE PR,ERET UNNSP%	; Error if he gave a silly PID
	LOAD T2,PRCHK,(PR)	; Get check word
	CAME T2,PR		; Should be equal to PR block address
	 ERROR UNNSP%		;  Unrecognised portal ID
	JN PRCLO,(PR),ERET UNPWS% ; Error if we are closing
	JRST (T1)		; Dispatch to the correct function

USRDSP:
	TABBEG NU.OPN,NU.MAX,FOO
	 TABENT NU.OPN,<IFIW!DLLOPN>		; Open a portal
	 TABENT NU.CLO,<IFIW!FC.POR!DLLCLO>	; Close a portal
	 TABENT NU.RCV,<IFIW!FC.POR!DLLRCV>	; Specify recieve buffer
	 TABENT NU.XMT,<IFIW!FC.POR!DLLXMT>	; Send out a datagram
	 TABENT NU.EMA,<IFIW!FC.POR!DLLEMA>	; Enable Multicast
	 TABENT NU.DMA,<IFIW!FC.POR!DLLDMA>	; Disable Multicast
	 TABENT NU.RPC,<IFIW!FC.POR!DLLRPC>	; Read Portal Counters
	 TABENT NU.RCI,<IFIW!DLLRCI>		; Read Channel Info
	 TABENT NU.RPL,<IFIW!DLLRPL>		; Read Portal List
	 TABENT NU.RCL,<IFIW!DLLRCL>		; Read Channel List
	 TABENT NU.RPI,<IFIW!FC.POR!DLLRPI>	; Read Portal Info
	 TABENT NU.SCA,<IFIW!DLLSCA>		; Set Channel Address
	 TABENT NU.RCC,<IFIW!FC.POR!DLLRCC>	; Read Channel Counters
	 TABENT NU.SCS,<IFIW!DLLSCS>		; Set Channel State
	 TABENT NU.CXI,<IFIW!DLLCXI>		; Convrt xtrnal to int PID
	TABEND
	SUBTTL DLLOPN - Open an NISRV portal

; Check for unused protocol type, and existence of channel.

DLLOPN:
	MOVX T1,<.RESP2,,PR.LEN>; Get the number we need
	MOVX T2,.RESGP		;  from the general pool
	CALL ASGRES		; Allocate the PR block
	 ERROR UNRES%		;  Resource failure
	MOVE PR,T1		; PR <= block address

	STOR PR,UNPID,(UN)	; Make PR block address be the PID
	STOR PR,PRCHK,(PR)	; Set up the check word

	LOAD T1,UNUID,(UN)	; Get his user-ID
	STOR T1,PRUID,(PR)	; Save it for callbacks

	LOAD T1,UNPAD,(UN)	; Get the pad bit
	STOR T1,PRPAD,(PR)	; Stash it away

	LOAD T2,UNCBA,(UN)	; Get address of the posting routine
	STOR T2,PRPOS,(PR)	; Save it
	MOVX T1,UNICR%		; Illegal callback routine address
	 JUMPLE T2,OPNERR	;  Error if callback is .LE. 0

	LOAD T1,UNPRO,(UN)	; Get the desired protocol type
	STOR T1,PRPRO,(PR)	; Save the protocol type
	CAIN T1,-1		; Information portal?
	 JRST OPNINF		;  Yes, don't assign a protocol type

	MOVE T1,TODCLK		; Get current uptime (in MS)
	STOR T1,PRTLZ,(PR)	; Indicate time at which counters were zeroed

	MOVX T1,NF.ASP		; Assign protocol type
	CALL NIDSP		; Try to assign protocol type (UNPRO on UNCHN)
	 JRST OPNERR		;  Illegal protocol type, or already in use

; Read the channel status

	MOVX T1,NF.RCI		; Read channel info
	CALL NIDSP		; Get it from PHYKNI
	 TRN			;  ?!?

; Here to set up a portal block

OPNINF:	NIOFF			; No interrupts please
OPNIN1:	AOS T1,PORID		; Generate a new external portal ID
	CALL FNDEXI		; Is this one already assigned?
	 TRNA			;  Nope, all is fine
	  JRST OPNIN1		;   Yes, try again
	STOR T1,PREXI,(PR)	; Assign the external portal ID

	MOVE T1,PORBAS		; Get pointer to first block in chain
	STOR T1,PRNXT,(PR)	; Make our block point to first port block
	MOVEM PR,PORBAS		; Make our block be the new first
	NION			; Allow interrupts

	RETSKP			; Skip return to caller

; Here when we get an error during DLLOPN.  T1 contains error code

OPNERR:	SETZRO PRCHK,(PR)	; First, zapp the check word
	SETOM UNPID,(UN)	;  and return a really bad PID to ensure that
				;  caller dies horribly if he uses it.
	EXCH PR,T1		; Save error code, get PR block into T1
	CALL RELRES		; Release the memory
	MOVE T1,PR		; Get back the error code
	RET			; And non-skip return
	SUBTTL DLLCLO - Close a DLL port

; First disable the protocol type and return all receive buffers.  Then
; send a chaser packet through the hardware to flush all outstanding
; commands.

DLLCLO:	SETONE PRCLO,(PR)	; Indicate that portal is closing
	LOAD T1,PRPRO,(PR)	; Get protocol type
	CAIN T1,-1		; Information portal??
	 JRST CLOINF		;  Yes, no protocol type to disable

	MOVX T1,NF.DPT		; Disable protocol type
	CALL NIDSP		;  and return all receive buffers	
	 JRST CLOER1		;  Propagate the error
	SETONE PRPRO,(PR)	; In case of error, don't do this again

CLOINF:	MOVX T1,NF.CLO		; Chase out all his outstanding commands
	CALL NIDSP		; ...
	 JRST CLOER1		;  Propagate the error
	RETSKP			; Return success

CLOER1:	SETZRO PRCLO,(PR)	; Indicate that we aren't doing a close
	RET			; And give error return

CLOBUG:	BUG. (HLT,KNICFP,NISRV,SOFT,<Cannot find portal block during close.>,<<PR,PR>>,<

Cause:	NISRV was unable to find a portal block on the portal block list during
	a close portal callback.

Data:	PR - Portal block address
>)

; Here when chaser packet gets returned.  We can now deallocate his portal
; block and inform him of the death of his portal.

CLOCBK:	XMOVEI T1,PORBAS-PR.NXT	; Get address of address of 1st portal block
	PIOFF			; Absolutely, positively no interrupts
	TRNA			; Enter loop at the right point
CLOCB1:	 LOAD T1,PRNXT,(T1)	;  Get address of next portal block
	JUMPE T1,CLOBUG		; Bug if we reached the end
	OPSTR <CAME PR,>,PRNXT,(T1) ; Is our portal next?
	 JRST CLOCB1		;  No, try again
	LOAD T2,PRNXT,(PR)	; Get addr of portal block following us
	STOR T2,PRNXT,(T1)	; Splice us out of the chain
	PION			; Enable interrupts

	STOR PR,UNPID,(UN)	; Install PID in UN block
	LOAD T1,PRUID,(PR)	; Get user id
	STOR T1,UNUID,(UN)	; Put it where user can find it

	MOVX T1,NU.CLO		; Generate close
	CALL CALUSR		;  callback

	SETZRO PRCHK,(PR)	; Clear the check word
	MOVE T1,PR		; Get rid of this block
	CALLRET RELRES		; Free core up from port driver interface block
	SUBTTL DLLEMA/DLLDMA - Enable/Disable a multicast address

DLLEMA:	SKIPA T1,[NF.EMA]	; Get fcn code for enabling multicast addrs
DLLDMA:	 MOVX T1,NF.DMA		;  Get fcn code for disabling multicast addrs
	LOAD T2,PRPRO,(PR)	; Get protocol type
	CAXN T2,-1		; Information only portal?
	 ERROR UNNPE%		;  Yes, not allowed to do this

	CALL NIDSP		; Do the dispatch
	 RET			;  Pass the error back to the user
	RETSKP			; And give good return
	SUBTTL DLLXMT - Send a DLL message

;DLLXMT - Send an NI datagram
;
;	MOVEI T1,NU.TRN
;	XMOVEI T2,<ADDRESS OF BLOCK>
;	CALL DLLUNI
;	 error return
;	normal return
;
; Where:
;
;UNPID - This is the PORTAL-ID returned on the open call.
;
;UNBFA - This is the address of the buffer (for non MSD lists) and the 
;address of the MSD chain for MSD style lists.
;
;UNBSZ - For non MSD buffers, this is the buffer size.  It should be left 0 
;        for MSD style buffers.  This buffer length includes the CRC.
;        (ie:Data Length+CRC length<4>) and is specified in bytes.
;
;UNPRO - This is the protocol type for which this message is destined.
;
;
;UNDAD,UNDAD+1(ADDRESS) - This is the NI address for which the message is 
;                         bound.  It may be multicast, broadcast or any
;                         other allowable address.
;
;UNPSC - A flag to indicate that the CRC is included in this message.
;
;This routine is called to send an NI datagram out over the wire
;(to the port driver).  It accepts as it's arguments either an MSD style 
;pointer or a non-msd style pointer.  On the non-msd pointer you must give
;a buffer count along with the buffer address.  It will then queue the message
;out through the port.  Please be advised that no guarantee of deliver is made.
;

DLLXMT:	MOVX T1,NF.XMT		;SEND A MESSAGE
	CALLRET NIDSP		;SEND IT OFF
	SUBTTL DLLRCV - DLL Specify Recieve Buffer

DLLRCV:	MOVX T1,NF.RCV		; Function is post receive buffer
	CALLRET NIDSP		; Call the device driver

; Post Input Available

DLLIAV:	LOAD T1,PRUID,(PR)	; Get want the user wants us to call him with
	STOR T1,UNUID,(UN)	; Save it in the block
	STOR PR,UNPID,(UN)	; Save it for the user
	MOVX T1,NU.RCV		; Recieved message
	CALLRET CALUSR		; Call the user
	SUBTTL DLLPCB - Port Driver Call Back routine

; DLLCBK - Call back from Port Driver routine
;
; CALLED:
;	T1/ Function code
;	T3/ Error/success code for user
;
;	This routine is called by the port driver when he must
;notify the DLL of an event which will effect users.

DLLCBK:	SKIPLE T1		;Is it a legal function
	CAXLE T1,NF.MAX		;Is it a legal function
	 JRST DLLICB
	MOVE T1,DLLFNC-1(T1)	;Get the dispatch address and good bits
	TXNN T1,FC.POR		;Does this function require a portal?
	 JRST (T1)		; No, don't do the check
	LOAD T2,PRCHK,(PR)	;Get check word
	CAME T2,PR		;Everything Kosher?
	 BUG. (HLT,DLLBPA,NISRV,SOFT,<Illegal Portal supplied by PHYKNI>,<<UN,UN>,<PR,PR>>,<

Cause:	PHYKNI returned an illegal portal block address when it called back
	NISRV.

Data:	UN - UN block
	PR - Bad portal block address
>)
	JRST (T1)		;Call the completion routine

DLLFNC:
	TABBEG NF.XMT,NF.MAX,<IFIW DLLICB>
	 TABENT NF.XMT,<IFIW!FC.POR!DLLPST> ; Post message as transmitted
	 TABENT NF.RCV,<IFIW!FC.POR!DLLIAV> ; Post input available
	 TABENT NF.LSC,<IFIW!DLLLSC>	    ; Line state changed
	 TABENT NF.RDC,<IFIW!FC.POR!DLLRDC> ; Read counters completed
	 TABENT NF.CLO,<IFIW!FC.POR!CLOCBK> ; Close portal callback
	 TABENT NF.SCA,<IFIW!SCACBK>	    ; Set channel address callback
	 TABENT NF.RPC,<IFIW!RPCCBK>	    ; Read portal counters callback
	TABEND

repeat 0,<
	IFIW!FC.POR!DLLICB		;RETURN FOR WRITE STATION INFO COMPLETE
	IFIW!FC.POR!DLLICB		;RETURN FOR ENABLE PROTOCAL TYPE
	IFIW!FC.POR!DLLICB		;RETURN FOR DISABLE PROTOCAL TYPE
	IFIW!FC.POR!DLLICB		;RETURN FOR ENABLE MULTICAST ADDRESS
	IFIW!FC.POR!DLLICB		;RETURN FOR DISABLE MULTICAST ADDRESS
	IFIW!FC.POR!DLLICB		;RETURN FOR ENABLE PROMISCOUS MODE
	IFIW!FC.POR!DLLICB		;RETURN FOR DISABLE PROMISCOUS MODE
	IFIW!FC.POR!DLLICB		;RETURN FOR START PORT
	IFIW!FC.POR!DLLICB		;RETURN FOR RESET PORT
	IFIW!FC.POR!DLLICB		;RETURN FOR STOP PORT
>
	SUBTTL DLLICB - Call Back from Port Driver was unknown 

DLLICB:	 BUG. (HLT,NIDUNF,NISRV,SOFT,<Unknown Callback code from Port Driver.>,,<

Cause:	The port driver has called back with either a code in T1 that is 
	not understood or that is not expected to be called back on.

>,RTN)
	SUBTTL DLLPST - Post A Message as being transmitted

;DLLPST -  Call back for Output Done (NU.TRN)
;
;	MOVEI T1,NU.TRN
;	XMOVEI T2,<ADDRESS OF INFORMATION BLOCK>
;	CALL <CALLBACK ROUTINE FROM OPEN>
;	always return
;
; Where:
;
;UNPID - The portal ID on which the message was received.
;
;UNUID - This is the ID which the user asked us to specify on his posted 
;        messages.
;
;UNBFA - The message block pointer of the buffer just sent.
;
;UNBSZ - This is the size of the buffer as supplied by the user.
;
;UNSTA Status of the message:
;
;
;	Value			Event Type
;
;	  00			No error
;	  01			Internal Hardware error
;	  02			Transmit aborted
;	  03			Local unrecognized command
;	  04			Buffer length violation [1]
;	  05			Carrier lost
;	  06			Frame too short 	[2]
;	  07			Remote Failure to defer	[3]
;	  10			Frame too long
;	  11			Open Circuit
;	  12			Short Circuit
;	  13			** SPARE
;	  14			Carrier detect check failed
;	  15			Excessive collisions
;
;
;[1]	The length of the information transmitted and the length of the
;	BSD is inconsistent.
;
;[2]	This error occurs only when padding of the transmitted frame is
;	not specified and the length of the data is less than 46 bytes.
;
;[3]	This error is not detectable by the NIA module and thus will never
;	be set.  They are only included to conform to the Network Management
;	specification.
;
;
;This call back signifies that a message has been transmitted, but does not 
;mean that it was delivered to the user as no gaurantees are made on delivery
;at this level.
;

DLLPST:	LOAD T1,PRUID,(PR)	;GET THE USER ID
	STOR T1,UNUID,(UN)	;STOR IT FOR THE USER
	STOR PR,UNPID,(UN)	;SAVE IT FOR THE USER
	MOVX T1,NU.XMT		;MESSAGE TRANSMITTED
	CALLRET CALUSR		;CALL THE USER
	SUBTTL DLLLSC - Line state Changed 

; Call PHYKNI to read channel status and callback the portal owner to
; inform him.

DLLLSC:	SAVEAC P1		; Save a P
	LOAD P1,UNCHN,(UN)	; Save the channel # across calls to the user
	SKIPA PR,PORBAS		;GET THE BAS
DLLLS0:	 LOAD PR,PRNXT,(PR)	;GET THE NEXT ONE
	JUMPE PR,RTN		;Return when we have done all portals

	MOVX T1,NF.RCI		; Read channel info
	CALL NIDSP		; Get it from PHYKNI
	 BUG. (HLT,KNIERP,NISRV,SOFT,<Illegal error return from PHYKNI>,<<T1,ERROR>>,<

Cause:	NISRV got an error return from PHYKNI while processing a state
	change callback.  The error code (one of the UNxyz% errors) is in
	T1.
Data:	ERROR - Error returned from PHYKNI

>,RTN)
	LOAD T1,PRUID,(PR)	;GET THE USERS ID
	STOR T1,UNUID,(UN)	;SAVE IT
	STOR PR,UNPID,(UN)	;SAVE FOR THE USER
	STOR P1,UNCHN,(UN)	; Install the channel number
	MOVX T1,NU.RCI		;SAY LINE STATE CHANGE
	MOVE T2,UN		;GET THE ADDRESS OF THE BLOCK
	LOAD T3,PRPOS,(PR)	;GET THE POSTING ROUTINE
	CALL @T3		;CALL HIM THERE
	 NOP			;DON'T WORRY ABOUT HIS ERRORS
	JRST DLLLS0		;Go to next portal
	SUBTTL DLLRPC - Read Portal Counters

DLLRPC:	LOAD T1,UNSPI,(UN)	; Get source portal ID
	SKIPLE T1		; Less than or equal to 0 is bad
	OPSTR <CAME T1,>,PRCHK,(T1) ; Is it valid?
	 ERROR UNNSP%		;  Nope, No Such Portal

	LOADE T1,PRPRO,(T1)	; Get the source portal's protocol type
	CAMN T1,[-1]		; Information only portal?
	 ERROR UNNPE%		;  Yes, can't read counters for info portals
	MOVX T1,NF.RPC		; Read the User Buffer Unavailable counter
	CALLRET NIDSP

; Here for read portal counters callback

RPCCBK:	STOR PR,UNPID,(UN)	; Save portal ID for the user
	LOAD T1,PRUID,(PR)	; Get the user ID
	STOR T1,UNUID,(UN)	; Save that too
	MOVX T1,NU.RPC		; Indicate what we are returning
	CALL CALUSR		; And call back the user
	RET
	SUBTTL DLLRCI - Read Channel Information

DLLRCI:	MOVX T1,NF.RCI		; Read channel info
	CALLRET NIDSP		; Ask the hardware about it
	SUBTTL DLLSCA - Set Channel Address

DLLSCA:	MOVX T1,NF.SCA		; Set channel address
	CALLRET NIDSP		; Tell the hardware about it

; Here for set channel address callback.  Tell all portals that the address
; has changed.

SCACBK:	SAVEAC P1
	LOAD P1,UNCHN,(UN)	; Save channel # across calls to the user
	SKIPA PR,PORBAS		; Get address of first portal block
SCACB1:	 LOAD PR,PRNXT,(PR)	;  Get address of next portal block
	JUMPE PR,RTN		; Return when done

	LOAD T1,PRUID,(PR)	; Get the user's ID
	STOR T1,UNUID,(UN)	; Save it
	STOR PR,UNPID,(UN)	; Save the portal ID
	STOR P1,UNCHN,(UN)	; Save the channel #
	MOVX T1,NU.SCA		; Function is set channel address
	CALL CALUSR		; Tell the user about the address change
	JRST SCACB1		; And go on to the next user
	SUBTTL DLLRPL - Read Portal List

DLLRPL:	XMOVEI PR,PORBAS	; Get base address of portal list
	MOVE T2,[MOVE T1,PR]	; Get instruction for fetching data

; Common code for read portal list and read channel list
; PR contains address of base of list, T2 contains instruction to XCT
; to obtain data to be stored.

IFN PR.NXT-PS.NXT,PRINTX ? Value mismatch between PRNXT and PSNXT in REDLST

REDLST:	LOAD T4,UNBSZ,(UN)	; Get buffer size
	JUMPLE T4,ERET UNIBS%	; Any room?
	LOAD T3,UNBFA,(UN)	; Get buffer address
	JUMPLE T3,ERET UNIFB%	; Jump if illegally formatted buffer
	NIOFF			; No interrupts while walking chain

	SKIPA PR,(PR)		; Get first item in the list
DLLRP1:	 LOAD PR,PRNXT,(PR)	;  Get next portal block address
	JUMPE PR,DLLRP2		; Jump if we hit end of chain
	XCT T2			; Get data into T1
	SKIPLE T4		; Skip if user didn't allocate enough room
	 MOVEM T1,(T3)		;  Save the portal ID
	XMOVEI T3,1(T3)		; Increment dest address
	SOJA T4,DLLRP1		; Loop over the whole chain

DLLRP2:	NION			; Re-enable interrupts
	MOVE T1,T4		; Save -portal count
	OPSTR <SUB T4,>,UNBSZ,(UN) ; Compute -number of ID's returned
	OPSTR <MOVNM T4,>,UNBSZ,(UN) ; Make it positive & save it
	JUMPL T1,ERET UNIBS%	; Jump if we overflowed
	RETSKP
	SUBTTL DLLRCL - Read Channel List

DLLRCL:	XMOVEI PR,CHNBAS	; Get base of channel list
	MOVE T2,CHNFET		; Get instruction for fetching channel #
	JRST REDLST
	SUBTTL DLLRPI - Read Portal Information

DLLRPI:	SAVEAC P1
	LOADE T1,PRPRO,(PR)	; Get the protocol type
	MOVE P1,T1		; Keep it in a safe place
	SKIPL T1		; One of the funny ones?
	 CALL SWAB		;  No, normalize the bytes
	STOR T1,UNPRO,(UN)	; Setup the protocol type

	LOAD T1,PRUID,(PR)	; Get the user's ID
	STOR T1,UNUID,(UN)	; Return the user's ID

	LOAD T1,PRPAD,(PR)	; Get the pad bit
	STOR T1,UNPAD,(UN)	; Return that too

	SETZ T1,		; Get a zero
	STOR T1,UNPMS,(UN)	; Return PI mask

	LOAD T1,PROXM,(PR)	; Get outstanding transmit count
	STOR T1,UNOXM,(UN)	; Return outstanding transmit count

	LOAD T1,PRORC,(PR)	; Get outstanding receive count
	STOR T1,UNORC,(UN)	; Return outstanding receive count

	LOAD T1,PRPOS,(PR)	; Get the callback address
	STOR T1,UNCBA,(UN)	; Return callback address

	LOAD T1,PREXI,(PR)	; Get external portal ID
	STOR T1,UNEXI,(UN)	; Return external portal ID

	CAMN P1,[-1]		; Information portal?
	 RETSKP			;  Yes, there is no more to return

	MOVX T1,NF.RPI		; Get PHYKNI function code
	CALL NIDSP		; Get PHYKNI to fill out it's part
	 RET			;  Pass error upwards

	LOAD T1,PRBSZ,(PR)	; Get the buffer size
	STOR T1,UNBSZ,(UN)	; Return it
	RETSKP			; And return success
	SUBTTL Network management -- Set Channel State

DLLSCS:	MOVX T1,NF.SCS		; Set the channel's state
	CALLRET NIDSP		; Do this in PHYKNI
	SUBTTL Network management -- Convert External Portal ID to Internal Portal ID

DLLCXI:	LOAD T1,UNEXI,(UN)	; Get the external portal ID
	CALL FNDEXI		; Lookup the exteral ID
	 ERROR UNNSP%		;  No such portal
	STOR T2,UNPID,(UN)	; Install the real portal ID
	RETSKP			; And return success
	SUBTTL Network Management -- Read Channel Counters

DLLRCC:	MOVX T1,NF.RDC		; Read the counters
	CALLRET NIDSP		; Get them from the hardware

; Read Counters Complete

DLLRDC:	LOAD T1,PRUID,(PR)	; Get the user ID
	STOR T1,UNUID,(UN)	; Stor it for the user
	STOR PR,UNPID,(UN)	; Save the portal ID for the user
	MOVX T1,NU.RCC		; Read counters complete
	CALLRET CALUSR		; Call the user
	SUBTTL CALUSR - Calls the user up after setting up the UN block

;
; Called:
;	T1/ Function code
;	Q1/ Address of users block
;	Q2/ Address of ports block
;	Q3/ Address o call back routine
;	CALL CALUSR
;	 error return
;	normal return
;

CALUSR:	MOVE T2,UN		; Get UN block block addr where user expects it

IFN FTHIST,<
	CALL RECUNB		; Record UN block
>; End of IFN FTHIST

	OPSTR <CALL @>,PRPOS,(PR) ; Callback the user
	 TRN			;  Ignore errors
	RET			; Good
	SUBTTL	FNDEXI - Search for an external portal ID

; Search for the portal with the external portal ID in T1.
;
; Call:	MOVX T1,external_portal_ID
;	CALL FNDEXI
;	 <Return +1, failure>
;	<Return +2, T1/unchanged, T2/real portal ID>

FNDEXI:	XMOVEI T2,PORBAS	; Get the portal list base
	NIOFF
FNDEX1:	LOAD T2,PRNXT,(T2)	; Get the next portal block
	JUMPE T2,ONRET		; Jump if done
	OPSTR <CAME T1,>,PREXI,(T2) ; Does the external ID match
	 JRST FNDEX1		;  Loop over all the portals
	JRST ONRSKP		; Return success
	SUBTTL	ALLPOR - Co-routine for looping through all portals

; ALLPOR is a co-routine that will loop through all portals in existence.
; Skip and non-skip returns are treated the same.

ALLPOR:	SKIPA PR,PORBAS		; Get base of portal list
ALLPO1:	 LOAD PR,PRNXT,(PR)	;  Get next portal block	
	JUMPE PR,ALLPO2		; Jump when we reach end of list
	CALL @(P)		; Call back the caller
	 NOP			;  Ignore skip/non-skip
	JRST ALLPO1		; Loop for the rest

ALLPO2:	ADJSP P,-1		; Pop the caller off the stack
	RET			;  and return to his caller
	SUBTTL Miscellaneous routines

repeat 0,<
; Here on unexpected error returns from NIDSP

NIBARF:	MOVE T1,(P)		; Get caller's address
	BUG. (HLT,KNIBER,NISRV,SOFT,<Bad error return from PHYKNI>,<<T1,ERROR>,<T1,ROUTINE>>,<

Cause:	NISRV got an unexpected error return from PHYKNI.  The probable error
	code is in T1, and the address of the caller is on the stack.
>)
	RET
>; End of repeat 0
	SUBTTL Static Storage

RS (PORBAS,1)			; Head of portal list
RS (PORID,1)			; Next external portal ID to be assigned
	SUBTTL End of NISRV
;End of NISRV