Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_1_19910112 - 7/ap23-tcpip/ipfree.mac
There are 9 other files named ipfree.mac in the archive. Click here to see a list.
; Edit= 9114 to IPFREE.MAC on 18-Jul-89 by GSCOTT
;Fix various internet free space problems with a "new" IPFREE from Stu
;Grossman.
; Edit= 8897 to IPFREE.MAC on 12-Aug-88 by RASPUZZI
;Update BUG. documentation.
; UPD ID= 8530, RIP:<7.MONITOR>IPFREE.MAC.5,   9-Feb-88 16:15:33 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8418, RIP:<7.MONITOR>IPFREE.MAC.4,   4-Feb-88 12:17:39 by GSCOTT
;TCO 7.1210 - Set IPGCOL normally not dumpable.
; UPD ID= 112, RIP:<7.MONITOR>IPFREE.MAC.3,  15-Sep-87 18:53:53 by GSCOTT
;TCO 7.1057 - Change code at GETBB3 to not be so paranoid about block sizes.
; *** Edit 7478 to IPFREE.MAC by PRATT on 12-May-87, for SPR #21612
; Fix up occaisional lost IP freespace bug in GETBB0. Change T1 to BLK. 
; UPD ID= 2087, SNARK:<6.1.MONITOR>IPFREE.MAC.7,   3-Jun-85 14:45:42 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1572, SNARK:<6.1.MONITOR>IPFREE.MAC.6,  26-Feb-85 17:17:55 by PAETZOLD
;Document BUGxxx's
; UPD ID= 1419, SNARK:<6.1.MONITOR>IPFREE.MAC.5,  29-Jan-85 11:37:43 by PAETZOLD
;TCO 6.1.1160 - Define USIZE Correctly
; UPD ID= 1035, SNARK:<6.1.MONITOR>IPFREE.MAC.4,  12-Nov-84 15:24:34 by PAETZOLD
;TCO 6.1041 - Move ARPANET to XCDSEC
; UPD ID= 310, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.11,  17-Oct-84 10:25:53 by PAETZOLD
;Make 1822 buffer sizes and initialization key off INTBSZ and MAXWPM.
; UPD ID= 297, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.10,  30-Sep-84 23:41:39 by PAETZOLD
;NI buffers are INTXPW size and not MAXWPM.
; UPD ID= 285, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.9,  24-Sep-84 13:54:22 by PURRETTA
;Update copyright notice.
; UPD ID= 276, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.8,   7-Sep-84 22:54:50 by PAETZOLD
;Clean up a little.  Remove repeat zeroes.
; UPD ID= 256, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.7,  26-Aug-84 17:45:45 by PAETZOLD
;NI buffers are now from IP free space.  Remove RETNIB hack from RETBLK.
; UPD ID= 227, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.6,   6-Aug-84 19:12:32 by PAETZOLD
;Rewrite DNGWDS and DNFWDS to use ASGRES and friends.
; UPD ID= 147, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.5,  30-May-84 14:24:21 by PAETZOLD
;NIPLKB and NIPULK are here now.  
;Make DNGWDS and DNFWDS lock and unlock the space.
; UPD ID= 97, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.4,  12-May-84 11:17:29 by PAETZOLD
;Forgot about DNFWDS
; UPD ID= 95, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.3,  12-May-84 10:51:42 by PAETZOLD
;CLRBLK now in this module.  Add NISRV needed routines.
; UPD ID= 26, SNARK:<TCPIP.5.4.MONITOR>IPFREE.MAC.2,   5-Apr-84 20:52:04 by PAETZOLD
;MAXWPM is no longer 400.
; UPD ID= 4004, SNARK:<6.MONITOR>IPFREE.MAC.4,  28-Mar-84 20:56:45 by PAETZOLD
;More TCO 6.1733 - Move 1822 buffer stuff to here.
; UPD ID= 3825, SNARK:<6.MONITOR>IPFREE.MAC.3,  29-Feb-84 18:14:55 by PAETZOLD
;More TCO 6.1733 - ANBSEC and MNTSEC removal.  Bug fixes.  Cleanup.
;<TCPIP.5.3.MONITOR>IPFREE.MAC.4,  6-Dec-83 23:51:37, Edit by PAETZOLD
;<TCPIP.5.1.MONITOR>IPFREE.MAC.7,  5-Jul-83 08:25:34, Edit by PAETZOLD
;TCP changes for 5.1

;	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.


	SEARCH	ANAUNV,PROLOG
	TTITLE	(IPFREE,IPFREE,< - Internet Free Space Handler>)
	Subttl	Table of Contents

;		     Table of Contents for IPFREE
;
;				  Section		      Page
;
;
;    1. IP Free Space Block Definitions  . . . . . . . . . . .   3
;    2. IP Free Space Debugging code and storage . . . . . . .   5
;    3. Internet Free Space Initialization and Misc Routines .   7
;    4. Internet Free Space Return Code  . . . . . . . . . . .   8
;    5. Internet Free Space List Handling Code . . . . . . . .  11
;    6. Internet Free Space Variable Block Assignment Routines  13
;    7. Internet Free Space Assignment Routines  . . . . . . .  16
;    8. Internet Free Space Misc Routines  . . . . . . . . . .  18
;    9. Internet Free Space Block Carver . . . . . . . . . . .  21
;   10. Internet Free Space Garbage Collector  . . . . . . . .  23
;   11. Internet Free Space Block Verification Routines  . . .  25
;   12. Internet Free Space Hash Table Routines  . . . . . . .  27
;   13. 1822 Buffer Handling . . . . . . . . . . . . . . . . .  28
;   14. Temporary Free Space Routines for NISRV and Friends  .  30
;   15. IPNIDV Buffer Handling . . . . . . . . . . . . . . . .  31
;   16. End of IPFREE  . . . . . . . . . . . . . . . . . . . .  32
	SUBTTL IP Free Space Block Definitions

; AC redefinitions:

IF1 <				;[9114] Only redefine during pass 1
BLK=P1				;[9114] Holds pointer to block in question
SIZ=Q3				;[9114] Holds size of block
LST=Q2				;[9114] Holds pointer to a list of blocks
>				;[9114] 

;[9114] Note: INTBLK(*) contains BSIZE & BLIST

;[9114] Definitions common to both used and free blocks

DEFSTR(BUSED,0,0,1)		;[9114] Block is in use if this is set
DEFSTR(BSIZE,0,17,17)		;[9114] Block size including header
DEFSTR(BCHEK,0,17,18)		;[9114] Check pattern at end of block
DEFSTR(BBACK,0,35,18)		;[9114] Pointer to start of block (BSIZE)
CHKPAT=='STU'			;[9114] Unique pattern for BCHEK

;[9114] Definitions for FREE block header structure:

DEFSTR(BLIST,1,35,36)		;[9114] List of other blocks
INTBLS==:2			;[9114] Words per INTBLK entry (see ANAUNV)
FBLKSZ==3			;[9114] Size of a FREE block header

;[9114] Definitions for USED block header structure:

DEFSTR(BHASH,0,35,18)		;[9114] Hash. Guards against user clobbering
DEFSTR(BDATA,1,35,36)		;[9114] Start of data area
UBLKSZ==2			;[9114] Size of a USED block header

;[9114] Block size quantitization -- all blocks except very short ones
;[9114] are forced to be a multiple of this size.

BSMALL==10			;[9114] Don't quantize this size or smaller
BSQUAN==10			;[9114] Must be a power of 2
;Variables and tables related to free storage (in STG.MAC) are:

;INTFSP		# words of available free storage
;BULKST		Extended address of first word of never-used free storage,
;		or  0 if all has been used.
;BULKND		Extended address of last word of never-used free storage,
;		or  0 if all has been used.
;INTBLK(NFIXED)	Table of currently unused storage, by size;  each
; INTBLS words	entry contains (SIZ & list), where list is an extended address.
;		HASHX(SIZ) provides the index.
;ODDBLK		List header of odd-size blocks (SIZ & list), sorted by
;		increasing extended address, or  0 if list is empty.
;FRELCK(LOCKSZ)	Lock for INTBLK and ODDBLK.
;MRGFLG		0 if no free blocks can be merged into larger blocks,
;		Non-zero if merging might be possible.
;INTSVR		Non-zero to scavange for more free storage. (write- only -gas)
;INTSVC		Count of scavanges done. (no -gas)
;INTSVT		Uptime after which INTFR6 BUGINF should be reported.

;[9114] Local storage for this module

RS INTGCT,1		;[9114] Uptime after which next GC will be attempted
	SUBTTL IP Free Space Debugging code and storage

;[9114] Define debugging macros we will use today.

	IF1 <IFN IPFDSW,<PRINTX Assembling IP Free Space Debugging>>

IFE IPFDSW,MNTMN==-1		;[9114] No monitoring if no IPDFSW
IFNDEF MNTMN,<MNTMN==0>		;[9114] Default if monitor is to monitor all
DEFINE MNTM0(code),<IFGE MNTMN-0,<code>> ;[9114] Minimal monitoring
DEFINE MNTM2(code),<IFGE MNTMN-2,<code>> ;[9114] Low monitoring
DEFINE MNTM5(code),<IFGE MNTMN-5,<code>> ;[9114] Medium monitoring
DEFINE MNTM9(code),<IFGE MNTMN-9,<code>> ;[9114] Maximal monitoring

IFN IPFDSW,<

;	Free space event ring buffer entries have the following format

	.IPRFX==0		; word 0/ 525252,,FORKX
	.IPRBK==1		; word 1/ Address of block
	.IPFLG==2		; word 2/ Flags from block
	.IPRTD==3		; word 3/ TODCLK value
	.IPRHP==4		; word 4/ HP time value
	.IPSTK==5		; word 4/ Stack Cells
	.IPSTS==5		; number of stack words to save
	IPFLEN==<.IPSTK+.IPSTS>-.IPRFX+1 ; Length of ring entry
	IPFRNN==^D50		; number of entries in ring buffer

RS IPFRNG,<IPFRNN*IPFLEN>	; FREE SPACE EVENT RING BUFFER
RS IPFADR,1			; CURRENT RING BUFFER ADDRESS
	XRESCD			; THIS CODE IS RESIDENT

IPFTRK:				; TRACK IP FREE SPACE EVENTS
	PUSH P,T1		; SAVE ACS
	PUSH P,T2
	PUSH P,T3
	PUSH P,T4
	SETO T3,		; ASSUME PI IS ON
	CONSO PI,PIPION		; IS PI ON?
	TDZA T3,T3		; NO SO TURN OFF FLAG
        PIOFF			; YES SO MAKE THE MACHINE MINE
	MOVE T1,IPFADR		; GET THE CURRENT RING POINTER
	ADDI T1,IPFRNG		; OFFSET BY BASE ADDRESS OF THE RING BUFFER
	HRRZ T2,FORKX		; GET OUR FORKX
	HRLI T2,525252		; GET THE MAGIC CODE
	MOVEM T2,.IPRFX(T1)	; SAVE THE FIRST WORD
	MOVE T2,-3(P)		; GET THE ADDRESS OF THE BLOCK
	MOVEM T2,.IPRBK(T1)	; SAVE IT
	SETSEC T2,INTSEC	; EXTENDED POINTER
	MOVE T2,1(T2)		; GET FLAGS FROM THE BLOCK
	MOVEM T2,.IPFLG(T1)	; AND SAVE THEM AWAY
	MOVE T2,TODCLK		; GET THE CURRENT TODLCK
	MOVEM T2,.IPRTD(T1)	; SAVE TODCLK VALUE ALSO
	PUSH P,T1		; SAVE T1
	JSP T4,MTIME		; GET THE HPTIM
	MOVE T2,T1		; GET THE TIME
	POP P,T1		; RESTORE T1
	MOVEM T2,.IPRHP(T1)	; SAVE THE HPTIME VALUE
				; NOW SAVE THE LAST .IPSTS STACK CELLS
	HRLI T2,-<.IPSTS+2>(P)	; GET THE ADDRESS OF THE FIRST STACK WORD
	HRRI T2,.IPSTK(T1)	; GET THE ADDRESS OF THE FIRST RING STACK WORD
	BLT T2,<.IPSTK+.IPSTS-1>(T1) ; SAVE THE STACK CELLS
				; NOW MOVE THE RING BUFFER ADDRESS
	MOVE T1,IPFADR		; GET THE RING ADDRESS AGAIN
	ADDI T1,IPFLEN		; BUMP THE RING POINTER
	CAIL T1,<IPFLEN*IPFRNN>	; SHOULD THE POINTER LOOP AROUND?
	SETZ T1,		; YES SO MAKE IT LOOP
	MOVEM T1,IPFADR		; SAVE THE NEW RING POINTER
	SKIPE T3		; SHOULD WE GO PION?
        PION			; YES SO GIVE BACK THE MACHINE
	JRST PA4		; POP ACS AND RETURN TO CALLER

	XSWAPCD			; THIS CODE IS SWAPPABLE

>				; end of IPFDSW
	SUBTTL Internet Free Space Initialization and Misc Routines

;FREINI	Initialize the Free Storage area
;	CALL FREINI
;Ret+1:	Always.

FREINI::SETZRO BLIST,+ODDBLK	;[9114] No odd size blocks returned yet
	MOVE T1,[INTBLK,,INTBLK+1] ; Set for a BLT
	SETZM INTBLK		; Clear 1st word of table
	BLT T1,INTBLK+<NFIXED*INTBLS>-1	;[9114] Clear rest

	MOVE T2,[INTSEC,,INTFRE] ; Pointer to the INT free area
  	MOVEM T2,BULKST		; Beginning of bulk storage
	ADDI T2,INTFSZ-1
	MOVEM T2,BULKND		; End of the bulk storage
	MOVEI T4,INTFSZ
	MOVEM T4,INTFSP		; Amount of free space available
	SETZM MRGFLG		; No block merging possible yet.
	SETZM INTSVC		; Count of scavenges done
	SETZM INTSVT		; TODCLK filter of excessive BUGINF's
	SETZM INTSVR		; Scavenge request flag
	IFN IPFDSW,<SETZM IPFADR> ; IF DEBUGING RESET THE RING POINTER
	MOVEI T1,FRELCK		; Free storage lock
	CALLRET CLRLCK		; Initialize it

;FREAVL	Returns amount of free storage available
;CALL FREAVL
;Ret+1:	Always, number of words in T1

FREAVL::MOVE T1,INTFSP
	RET
	SUBTTL Internet Free Space Return Code

;RETBLK	Return a block to free area
;T1/	(Extended) Pointer to the user portion of the block
;	CALL RETBLK
;Ret+1:	Always

RETBK2::SAVEAC <T2>		;[9114] Same as RETBLK but preserves T2
RETBLK::			;[9114]
MNTM5	AOS CELL(INFAA,1,,INF)	;[9114] RETBLK calls
	IFN IPFDSW,<CALL IPFTRK> ; IF DEBUGING TRACE THIS EVENT
	XMOVEI T3,-$BDATA(T1)	;[9114] Pointer to free header
	XMOVEI T2,RETBL1	; Get address of worker routine
	MOVEI T1,FRELCK		; Lock to set
	CALL LCKCAL		; Lock and call.
	RET			; AND RETURN TO CALLER

RETBL1:
	SAVEAC <BLK,SIZ,LST>
	MOVE BLK,T1		; Set block pointer
	LOAD SIZ,BSIZE,(BLK)	;[9114] and size (excluding header)
	CALL RETBK0		; Do the returning
	RET
;RETBK0	Workhorse for above.  Called with NOINT & FRELCK set.
;BLK/	(Extended) Pointer to the block to return
;SIZ/	Size of the block
;	CALL RETBK0
;Ret+1:	Always

RETBK0:	CALL CHKBLK		;[9114] (BLK,SIZ/) Make sure header not crashed
	TMNN BUSED,(BLK)	;[9114] Is this block supposedly in use?
	BUG.(HLT,INTFR3,IPFREE,SOFT,<Internet free space - Returning free block>,,<

Cause:	The internet free space facility is trying to return a free space block
	that appears to be free already.

>)				;[9114] Owie
	SETZRO <BUSED,BHASH>,(BLK) ;[9114] Mark free and invalidate hash code
	MOVE T1,BLK		;[9114] Get the block address
	ADDI T1,-1(SIZ)		;[9114] Point at last word of block
	SETZRO <BBACK,BCHEK>,(T1) ;[9114] Zap backup pointer and check code
	ADDM SIZ,INTFSP		;[9114] Update amount of free storage now avail
	SETZRO BLIST,(BLK)	;[9114] Block may become the end of a list
	SETOB T1,MRGFLG		;[9114] Say common size and merging possible
	CALLRET RETB		;[9114] (T1/) Return the block and return
;RETB	Return the block to some list. Called with NOINT & FRELCK set.
;BLK/	(Extended) Block	; with BSIZE setup
;T1/	UserCall Flag		; Non-zero says to create a slot in
;	CALL RETB
;Ret+1:	Always

RETB0:				; Indicate not being returned by user
	SETZ T1,		; Flag it
RETB:
	PUSH P,T1		; Save the flag
	LOAD SIZ,BSIZE,(BLK)	;[9114] Size
	CALL HASHX		; Get -1 or index to INTBLK
	POP P,T2		; Restore the flag
	JUMPL T1,RETB1		; Jump if there is no slot for this size
	JUMPE T2,RETB1		; Jump if not a user's block size
	MOVEI T2,INTBLK(T1)	; Pointer to the list head
	LOAD LST,BLIST,(T2)	;[9114] Pointer to the list itself
	STOR LST,BLIST,(BLK)	;[9114] Make block point to current tail
	STOR BLK,BLIST,(T2)	;[9114] Make head point to new front of list
	STOR SIZ,BSIZE,(T2)	;[9114] Be sure size is right in the table
	RET			;[9114]  and return

RETB1:	LOAD LST,BLIST,+ODDBLK	;[9114] The appropriate (extended) list
	CALL SPUT		; Put block on that list
	STOR LST,BLIST,+ODDBLK	;[9114] New list with block on it
	RET			;[9114] Return
	SUBTTL Internet Free Space List Handling Code

;SPUT	Put a block on an address ordered list
;BLK/	(Extended) Block pointer  with FSIZE & FNEXT
;LST/	(Extended) List pointer
;	CALL SPUT
;Ret+1:	Always.  New list containing Block in LST

CUR==T1				;[9114] Temp holding current
SUC==T2				;[9114] Temp holding successor

SPUT:	TRNE LST,-1		;[9114] Adding to null list?
	JRST SPUT1		;[9114] Jump if not adding to null list
	SETZRO BLIST,(BLK)	;[9114] Clear list pointer in block
	MOVE LST,BLK		;[9114] New list has only this block
	RET			;[9114] Return LST as new list

SPUT1:	CAML BLK,LST		;[9114] Adding to front of list?
	JRST SPUT2		;[9114] No. Search for right spot.

	STOR LST,BLIST,(BLK)	;[9114] Make BLK be first on the list
	MOVE SUC,LST		; Init so rest works
	MOVE LST,BLK		; Value to be returned
	MOVE CUR,BLK		; Current block on list
	JRST SPUT4

SPUT2:	SKIPA CUR,LST		; Start at beginning of list
SPUT3:	MOVE CUR,SUC		; Advance to next on list
	LOAD SUC,BLIST,(CUR)	;[9114] Get the successor to CUR
	CAML BLK,SUC		; BLK must be below SUC
	TRNN SUC,-1		; or SUC must be (section,,) 0
				; (CUR is end of list)
	CAMG BLK,CUR		; and BLK must be above CUR
	 JRST SPUT3		; Not right place for insert

	STOR SUC,BLIST,(BLK)	;[9114] Patch in BLK between CUR and SUC
	STOR BLK,BLIST,(CUR)	;[9114]
;[9114] Try to merge BLK and SUC together
;[9114] CUR may equal BLK,  SUC may equal (section,,0)

SPUT4:	LOAD T4,BSIZE,(BLK)	;[9114] Size of BLK
	ADD T4,BLK		;[9114] Address of word after BLK
	CAME T4,SUC		;[9114] Combine BLK and SUC ?
	JRST SPUT5		;[9114] No
	LOAD T3,BSIZE,(BLK)	;[9114] SUC is real block, not section,,0
	LOAD T4,BSIZE,(SUC)	;[9114] end pointer
	ADD T3,T4		;[9114] Size of combined block
	STOR T3,BSIZE,(BLK)	;[9114] Store that
	LOAD SUC,BLIST,(SUC)	;[9114] Successor of SUC is new SUC
	STOR SUC,BLIST,(BLK)	;[9114] and successor of combined BLK

;[9114] Try to merge CUR and BLK together
;[9114] CUR may equal BLK,  SUC may equal (section,,0)

SPUT5:	LOAD T3,BSIZE,(CUR)	;[9114] Length of CUR
	ADD T3,CUR		;[9114] Address following CUR
	CAME T3,BLK		;[9114] Combine CUR and BLK?
	RET			;[9114] Done
	LOAD T3,BSIZE,(CUR)	;[9114] Get the size of CUR
	LOAD T4,BSIZE,(BLK)	;[9114]  and of BLK
	ADD T3,T4		;[9114] Add then together
	STOR T3,BSIZE,(CUR)	;[9114] Set size of combined block
	LOAD T4,BLIST,(BLK)	;[9114] Successor of BLK
	STOR T4,BLIST,(CUR)	;[9114] Is successor of combined block
	RET			;[9114] Done

	PURGE CUR,SUC		;[9114] Remove temp symbols
	SUBTTL Internet Free Space Variable Block Assignment Routines

;GETBBK	Assign biggest block of free storage
;T1/	Minimum acceptable size
;T2/	Maximum usefull size
;	CALL GETBBK
;Ret+1:	Always.  T1 has 0 or or size,,pointer
;***** N.B.:  T1 does not have an extended address *****

;0 may be returned as a value meaning no space was available.
;The caller is expected to cope with this situation.

GETBBK::			;[9114]
MNTM5	AOS CELL(INFGK,0,,INF)	;[9114] GETBBK calls
MNTM5	CALL GETHST		;[9114] Histogram size
	DMOVEM T1,T3		; Place args for call via LCKCAL
	MOVEI T1,FRELCK		; The lock to set
	XMOVEI T2,[PUSH P,BLK	; Save ACs which will be
		PUSH P,SIZ	; Used as globals
		PUSH P,LST
		MOVE SIZ,T2	; Max size
		CALL GETBB0	; Do the work
		MOVE T1,BLK	; Value for caller
		POP P,LST
		POP P,SIZ
		POP P,BLK
		RET]
	CALL LCKCAL		; Call the function with the lock set
MNTM5	SKIPN T1		;[9114] Returning something?
MNTM5	AOS CELL(INFGK,1,,INF)	;[9114] Count GETBBK failures
	IFN IPFDSW,<CALL IPFTRK> ; IF DEBUGING TRACE THIS EVENT
	RET			; AND RETURN TO CALLER
;[9114]
;GETBB0	Workhorse for the above. Called with NOINT & FRELCK set.
;T1/	Min. size
;SIZ/	Max. size, excluding header
;FRELCK set
;	CALL GETBB0
;Ret+1:	Always.  BLK has 0 or size,,pointer

GETBB0:	ACVAR <MINSIZ>		;[9114] Place to save minimum size
	MOVEM T1,MINSIZ		;[9114] Save it
	CALL GETBK0		;[9114] (SIZ/BLK) Use normal GETBLK routine  
	JUMPN BLK,GETBBX	;[9114] Exit if we got the max. size block

;[9114] Note that the fail return from GETBK0 indicates that a garbage collect
;has happened and that all free blocks are now in INTBLK+(n*INTBLS).  Further,
;no block on ODDBLK is greater than or equal to the MAXSIZ.

	MOVEI SIZ,0		;[9114] Init max size seen
	LOAD T2,BLIST,<+ODDBLK>	;[9114] Init pointer to first block
	DO.			;[9114] Loop through the blocks
	  JUMPE T2,ENDLP.	;[9114] Jump if at end of list
	  LOAD T3,BSIZE,(T2)	;[9114] Get size of current block
	  CAMLE T3,SIZ		;[9114] Bigger than seen before?
	   MOVE SIZ,T3		;[9114] Yes.  Save max.
	  LOAD T2,BLIST,(T2)	;[9114] Point to next block
	  LOOP.			;[9114] Around for another trip please
	OD.			;[9114] End of loop

	CAIG SIZ,BSMALL		;[9114] If its a small block,
	JRST GETBB3		;[9114] Proceed, otherwise,
	SUBI SIZ,BSQUAN		;[9114] Round down to
	ANDCMI SIZ,BSQUAN-1	;[9114] Smaller quantization
	;...
	;...

GETBB3:	SUBI SIZ,UBLKSZ		;[9114] Reduce to useable portion
	CAMGE SIZ,MINSIZ	;[9114] Is the biggest block acceptable?
	JRST GETBB9		;[9114] No.  Tell caller.
	CALL GETBK0		;[9114] (SIZ/BLK) Get some space
	JUMPN BLK,GETBBX	;[9114] Return if all went well.
IFN IPFDSW,<
	BUG.(HLT,INTFR7,IPFREE,SOFT,<Internet free space - ODDBLK list fouled>,,<

Cause:	After searching for the largest available block of Internet free
	storage, the largest block can not be found.  The ODDBLK chain of
	available storage blocks has probably been fouled.  The dump should be
	examined.  By following the chain, see if the reported size is wrong,
	or whether the list has been fouled.

>)>				;[9114]
GETBB9:	SETZB BLK,SIZ		;[9114] Failure indication
GETBBX:	HRL BLK,SIZ		;[9114] Place size for caller
	RET			;[9114]  and return

	ENDAV.			;[9114] End of ACVAR at GETBB0
	SUBTTL Internet Free Space Assignment Routines

;GETBLK	Assign a block of free storage
;T1/	Size
;	CALL GETBLK
;Ret+1:	Always. 0 or Extended Pointer to block in T1

;0 may be returned as a value meaning no space was available.
;The caller is expected to cope with this situation.

GETBL2::SAVEAC <T2>
GETBLK::			;[9114]
MNTM5	AOS CELL(INFGB,0,,INF)	;[9114] GETBLK calls
MNTM5	CALL GETHST		;[9114] Histogram size
	MOVE T3,T1		;[9114] Place in right ac
	MOVEI T1,FRELCK		; Lock to set
	XMOVEI T2,GETBL0	; Address of the jacket routine
	CALL LCKCAL		; Call routine with lock set
MNTM5	SKIPN T1		;[9114] Returning something?
MNTM5	AOS CELL(INFGB,1,,INF)	;[9114] Count GETBLK failures
	IFN IPFDSW,<CALL IPFTRK> ; IF DEBUGING TRACE THIS EVENT
	RET			; AND RETURN TO CALLER

;[9114] Histogram calls, T1 has size, preserve T1 & T2

MNTM5<				;[9114] Only if needed
GETHST:	INHIST(INFHS,INF,T1,T3,T4) ;[9114] Histogram block sizes
	RET			;[9114] That's all
>				;[9114] End of MNTM5 code
GETBL0:	SAVEAC <BLK,SIZ,LST>	; Jacket routine
	MOVE SIZ,T1		; Get the requested size
	CALL GETBK0		; Do the work
	MOVE T1,BLK		; Return the address of the block
	RET

;GETBK0	Workhorse for above. Called with NOINT & FRELCK set.
;SIZ/	Size of block to be assigned
;	CALL GETBK0
;Ret+1:	Always.  0 or Extended Pointer to block in BLK. Must save SIZ.

GETBK0:	JUMPG SIZ,GETBK1	;[9114] Is there a size?
	BUG.(HLT,INTFR4,IPFREE,SOFT,<Internet free space - Block size requested too small>,,<

Cause:	The internet free space facility made an internal call for a zero or
	negative length block.   An examination of the dump should include
	a trace back on the stack to determine why the caller wants a 0 length
	block.

>)				;[9114]
	MOVEI SIZ,1		; Min size we ever hand out

GETBK1:	ADDI SIZ,UBLKSZ		;[9114] Add in overhead
	CAILE SIZ,INTFSZ	;[9114] Max size
	BUG.(HLT,INTFR5,IPFREE,SOFT,<Internet free space - Bad block size request>,,<

Cause:	The internet free space facility made an internal call for a block
	larger than the maximum supported size.  Examination of the dump 
	should include a trace back on the stack to find the caller.  There
	is probably a mathmatical error in that routine when it calculates 
	how much freespace to obtain.

>)
	CAIG SIZ,BSMALL		; Don't quantize Q heads etc.
	JRST GETBK2
	ADDI SIZ,BSQUAN-1	; Round up
	ANDCMI SIZ,BSQUAN-1	; To nearest bigger multiple
GETBK2:	CALL GETB		; Get it from somewhere
	JUMPE BLK,RTN		;[9114] Couldn't get the block
	MOVN T2,SIZ		;[9114] Size of block we will hand out
	ADDM T2,INTFSP		; Decrease amt of free space available
	CALL HASH		; Get a random number
	STOR T1,BHASH,(BLK)	;[9114] Check this when block returned
	SETONE BUSED,(BLK)	;[9114] Make this block be in use
	STOR SIZ,BSIZE,(BLK)	;[9114] Set the block size
	MOVE T2,BLK		;[9114] Get the block address
	ADDI T2,-1(SIZ)		;[9114] Get the last word of the block
	MOVX T1,CHKPAT		;[9114] Get the check pattern
	STOR T1,BCHEK,(T2)	;[9114] Install in word after the user portion
	STOR BLK,BBACK,(T2)	;[9114] Save back pointer there also
	OPSTR <XMOVEI BLK,>,BDATA,(BLK)	;[9114] Value is user area of the block
	SUBI SIZ,UBLKSZ		;[9114] Fix SIZ to reflect actual useable area
	RET			;[9114] Return to caller
	SUBTTL Internet Free Space Misc Routines

;GETB	Get a block from somewhere.  Called with NOINT & FRELCK set.
;SIZ/	Size, excluding header
;	CALL GETB
;Ret+1:	Always.   0 or (Extended) Pointer to block in BLK

GETB:	SETZ T1,		; Don't create a slot
	CALL HASHX		; Get index to INTBLK table
	JUMPL T1,GETB2		; Not in table.
	MOVEI T3,INTBLK(T1)	; Address of list head
	LOAD T4,BLIST,(T3)	;[9114] Pointer to list of blocks of this size
	JUMPE T4,GETB2		; None.  Try something else.
;[9114]	SETSEC T4,INTSEC	; Make extended address
	LOAD T2,BLIST,(T4)	;[9114] Successor of 1st block on list
	STOR T2,BLIST,(T3)	;[9114] Is now first thing on list
	SKIPA BLK,T4		; This block is the result
GETB2:  CALL GCARVE		; Look elsewhere for a block
	RET
;GCARVE	Carve a block of the required size from an odd block.
;SIZ/	Size, excluding header
;	CALL GCARVE
;Ret+1:	Always.   0 or (Extended) Pointer to block in BLK.

PRV==T1				;[9114] Temp for this routine

GCARVE:				;[9114]
MNTM5	AOS CELL(INFAA,2,,INF)	;[9114] GCARVE calls
	XMOVEI PRV,ODDBLK	; Address of pointer to odd block list
	LOAD BLK,BLIST,(PRV)	;[9114] Pointer to first odd block
	JUMPLE BLK,GCARV4	;[9114] None.  Try something else

	DO.			;[9114] Look through blocks
	  LOAD T2,BSIZE,(BLK)	;[9114] Get size of this odd block
	  CAME T2,SIZ		;[9114] Same as required?
	  IFSKP.		;[9114] Yes.
	    LOAD T3,BLIST,(BLK)	;[9114] Pointer to block after this one
	    STOR T3,BLIST,(PRV)	;[9114] Is new successor to one before this
	    RET			;[9114] Return with that one
	  ENDIF.		;[9114] Not same as required
	  CAIGE T2,FBLKSZ(SIZ)	;[9114] Min we can carve successfully
	  IFSKP.		;[9114] Big enough
	    LOAD T3,BLIST,(BLK)	;[9114] Successor of this one
	    STOR T3,BLIST,(PRV)	;[9114] Snip it out
	    CALLRET CSPLIT	;[9114] Split into required plus extra
	  ENDIF.		;[9114] Not carving

	  MOVE PRV,BLK		;[9114] Save previous
	  LOAD BLK,BLIST,(PRV)	;[9114] Move to next odd block
	  JUMPG BLK,TOP.	;[9114] And look at it
	OD.			;[9114] End of search

GCARV4:	CALLRET BULKCV		;[9114] Above failed.  Try bulk storage

	PURGE PRV		;[9114] Zap temp symbol
;CSPLIT		Split an odd block into required size plus extra.
;BLK/	(Extended) BLK
;SIZ/	Required size
;	CALL CSPLIT
;Ret+1:	Always.  Extended pointer to block of requird size in BLK

CSPLIT:				;[9114]
MNTM5	AOS CELL(INFAA,3,,INF)	;[9114] CSPLIT calls
	LOAD T3,BSIZE,(BLK)	;[9114] Get size of block to be split
	MOVE T1,BLK		;[9114] Get whole block
	ADD T1,SIZ		;[9114] Start of fragment
	STOR SIZ,BSIZE,(BLK)	;[9114] Store size of block to be returned
	SUB T3,SIZ		;[9114] Size of fragment
	STOR T3,BSIZE,(T1)	;[9114] Store size of fragment
	PUSH P,BLK
	PUSH P,SIZ
	MOVE BLK,T1
	CALL RETB0		; Return the fragment to free area
	POP P,SIZ
	POP P,BLK
	RET
	SUBTTL Internet Free Space Block Carver

;BULKCV	Carve block out of bulk storage.  Called with NOINT & FRELCK set.
;SIZ/	Size required
;	CALL BULKCV
;Ret+1:	Always.  BLK has 0 or extended pointer to block

BULKCV:				;[9114]
MNTM5	AOS CELL(INFBC,0,,INF)	;[9114] BULKCV calls
	PUSH P,SIZ		;[9114] Save SIZ
	MOVE T2,BULKND		;[9114] Current end of free storage
	IFN. T2			;[9114] Have something left
	  SUB T2,BULKST		;[9114] Compute current length
	  ANDN. T2		;[9114] Not enough
	    ADDI T2,1		;[9114] Total Length
	    CAME T2,SIZ		;[9114] Exactly what we need?	(-1)
	    IFSKP.		;[9114] Yes
	      SETZB BLK,BULKND  ;[9114] Cancel bulk area
	      EXCH BLK,BULKST	;[9114] Get beginning of block to return
	      JRST BULKCX	;[9114]  and return
	    ENDIF.		;[9114] Not exactly what we need

	    MOVE BLK,BULKST	;[9114] Start of what's left
	    CAIGE T2,FBLKSZ+1+1(SIZ) ;[9114] Big enough to carve? (-1)
	    IFSKP.		;[9114] Yes
	      ADDM SIZ,BULKST	;[9114] Remove from bulk area
	      JRST BULKCX	;[9114]  and return
	    ENDIF.		;[9114] Not big enough for carving

	    CAIGE T2,FBLKSZ	;[9114] Big enough to return?
	    ANSKP.		;[9114] No so forget it
	      STOR T2,BSIZE,(BLK) ;[9114] Convert what is left into a block
	      CALL RETB0	;[9114] Return the piece
	      SETZM BULKST	;[9114] Cancel bulk 
	      SETZM BULKND	;[9114]  storage
	ENDIF.			;[9114] No bulk to carve

	SKIPN MRGFLG		;[9114] Merging return blocks possible?
	IFSKP.			;[9114] Yes
	  CALL GC		;[9114] (/) Garbage collect (Save SIZ)
	  MOVE SIZ,0(P)		;[9114] Restore SIZ
	  CALL GETB		;[9114] Assign the block
	  JRST BULKCX		;[9114] Return
	ENDIF.			;[9114] Not possible to merge blocks
	MOVE T1,TODCLK		;[9114] Load the uptime
	CAMG T1,INTSVT		;Is it OK to mumble a bit more?
	IFSKP.			;[9114] Yes
	  MOVE T2,0(P)		;[9114] Get the size desired
	  BUG.(INF,INTFR6,IPFREE,SOFT,<Internet free space - Free storage exhausted>,,<

Cause:	Internet free space is totally exhausted.  This could be caused
	by someone not returning freespace or an insufficient amount of
	Internet freespace available.

Action:	If this problem can be reproduced, change this BUGINF to a BUGHLT
	and submit an SPR along with an unrun monitor, the dump, and any
	other information on reproduction of the problem.

>)				;[9114]
	  ADDI T1,^D60000	;[9114] 1 minute interval
	  MOVEM T1,INTSVT	;[9114] Set the next deadline time
	ENDIF.
	SETOM INTSVR		; And request everybody to do it
	MOVEI BLK,0		; None available.  Let caller handle it.
MNTM5	AOS CELL(INFBC,1,,INF)	;[9114] Count BULKCV failures
BULKCX:	POP P,SIZ		; Restore SIZ
	RET
	SUBTTL Internet Free Space Garbage Collector

;GC	Garbage Collector. Called with NOINT & FRELCK set.
;[9114]	Only operates each 30 seconds, last GC time is kept in INTGCT.

GC:	MOVE T1,TODCLK		;[9114] Load current uptime
	CAML T1,INTGCT		;[9114] Have we done a GC recently?
	IFSKP.			;[9114] Yes, in the last 30 seconds
	  SETZM MRGFLG		;[9114] Don't do merge 
	  RET			;[9114] Just return
	ENDIF.			;[9114] So it is time to do GC now
	ADDI T1,^D30000		;[9114] Get time of 30 seconds from now
	MOVEM T1,INTGCT		;[9114] Save as the next time to do GC

MNTM5	AOS CELL(INFAA,4,,INF)	;[9114] Count the GC calls
	BUG.(INF,IPGCOL,IPFREE,SOFT,<Internet free space - Reclaiming internet free space>,,<

Cause:	The internet free space facility is performing a garbage collection to
	make some space available.

>,,<DB%NND>)			;[7.1210] 
	;...
	;...

;[9114] We are going to GC.  Use SIZ for local since SPUT doesn't touch it.

	ACVAR <ILST>		;[9114] We need just one AC
	MOVEI LST,0		;[9114] Load zero
	EXCH LST,ODDBLK+$BLIST	;[9114] Get and clear odd block list
	MOVSI SIZ,-NFIXED      	;[9114] AOBJN pointer to INTBLK table
	DO.			;[9114] Loop through the blocks
	  MOVEI T1,INTBLK(SIZ)	;[9114] Pointer to current list header
	  LOAD ILST,BLIST,(T1)	;[9114] Pointer to first block on list

;[9114] Merge blocks from ILST into LST

	  IFN. ILST		;[9114] Don't copy nul list
	    DO.			;[9114] Loop through
	      TRNN ILST,-1	;[9114] End of ILST reached?
	      IFSKP.		;[9114] No
	        MOVE BLK,ILST	;[9114] First block on list
	        LOAD ILST,BLIST,(BLK) ;[9114] Get successor for next time
	        CALL SPUT	;[9114] (BLK,LST/LST) Return it
	        LOOP.		;[9114] Loop for all of them
	      ENDIF.		;[9114] End of check for end of ILST
	    OD.			;[9114] End of loop to free blocks
	  ENDIF.		;[9114] End of ILST to LST merge code

	  SETZRO BSIZE,+INTBLK(SIZ) ;[9114] Nullify the list
	  SETZRO BLIST,+INTBLK(SIZ) ;[9114] Nullify the list
	  ADDI SIZ,INTBLS-1	;[9114] Get to next one
	  AOBJN SIZ,TOP.	;[9114] Loop for all blocks
	OD.			;[9114] End of check through all blocks

;[9114] Return all free blocks to the proper place -- INTBLK or ODDBLK

	MOVE ILST,LST		;[9114] List of all free memory
	DO.			;[9114] Looping through it
	  TRNN ILST,-1		;[9114] End of list?
	  IFSKP.		;[9114] No
	    MOVE BLK,ILST	;[9114] Load the block
	    LOAD ILST,BLIST,(BLK) ;[9114] Successor is what to do next time
	    CALL RETB0		;[9114] (T1,BLK/) Return first block on list
	    LOOP.		;[9114] Loop for all of them
	  ENDIF.		;[9114] End of list check code
	ENDDO.			;[9114] End of returning all free blocks

	SETZM MRGFLG		;[9114] No merge possible now.
	RET			;[9114] The GC is now done

	ENDAV.			;[9114] End of ACVAR at GC
	SUBTTL Internet Free Space Block Verification Routines

;CHKBLK	See that the hash mark is still ok, etc.
;BLK/	(Extended) Pointer to block
;SIZ/	Size of the block, excluding UBLKSZ header
;	CALL CHKBLK
;Ret+1:	Always.

CHKBLK:	CAML BLK,[INTSEC,,INTFRE] ;[9114] Range check pointer
	CAMLE BLK,[<INTSEC,,INTFRE>+<INTFSZ-1>]	;[9114] to see if reasonable
	BUG.(HLT,INTFR2,IPFREE,SOFT,<Internet free space - Invalid block pointer>,,<

Cause:	An attempt has been made to return a block to Internet free storage
	with a pointer not between INTFRE and INTFRZ.

>)				;[9114] BLK bad
	CAIL SIZ,UBLKSZ+1	;[9114] Min size block ever handed out
	CAILE SIZ,INTFSZ	;[9114] Max size block ever handed out
	BUG.(HLT,INTFR0,IPFREE,SOFT,<Internet free space - Block size clobbered>,,<

Cause:	An attempt has been made to return a block to Internet free storage but
	the block has an illegal size.

>)				;[9114] SIZ bad
	CALL HASH		;(BLK,SIZ/T1) Get the hash code
	LOAD T2,BHASH,(BLK)	;[9114] Get the mark we left there
	CAME T1,T2		; Is it still there?
	BUG.(HLT,INTFR1,IPFREE,SOFT,<Internet free space - Block hash clobbered>,,<

Cause:	An attempt has been made to return a block to Internet free storage but
	the block's hash code appears to have changed indicating that the block
	has been smashed.

>)				;[9114] BHASH bad
	MOVE T1,BLK		;[9114] Get the block address
	ADDI T1,-1(SIZ)		;[9114] Point to last word of block
	LOAD T2,BCHEK,(T1)	;[9114] Get the check value
	CAXE T2,CHKPAT		;[9114] Is it the expected pattern?
	BUG.(HLT,INTFR8,IPFREE,SOFT,<Internet free space - Smashed free block pattern>,,<

Cause:	An attempt has been made to return a block to Internet free storage but
	the check pattern in the block appears to have changed indicating that
	the block has been smashed.

>)				;[9114] BCHEK bad
	LOAD T1,BBACK,(T1)	;[9114] Get the backup pointer
	CAIE T1,(BLK)		;[9114] Does it point to start of the block?
	BUG.(HLT,INTFR9,IPFREE,SOFT,<Internet free space - Bad backup pointer>,,<

Cause:	An attempt has been made to return a block to Internet free storage but
	the block's back pointer does not point to the start of the block,
	indicating that the block has been smashed.

>)				;[9114] BBACK bad
	RET
;HASH	Return a random number based on location and size.
;BLK/	(Extended) Block location
;SIZ/	Block size
;	CALL HASH
;Ret+1:	Always.  Hash value in T1

;This number is stored in the block header (BHASH) while the block is
;in the hands of the user. When he returns the block, a check is made
;to see that it has not been clobbered.

HASH:	MOVEI T1,25252(BLK)	; Flush section number and garble a bit
	IMULI T1,1234(SIZ)	; Mulitply by garbled length
	TSC T1,T1
	HRRZS T1
	RET

;CLRBLK Clear a block to be sure unstuffed fields are 0.
;T1/	(Extended) pointer to block
;T2/	Size of block
;	CALL CLRBLK
;Ret+1:	Always.

CLRBLK::			;[9114]
MNTM5	AOS CELL(INFAA,5,,INF)	;[9114] CLRBLK calls
	EXCH T1,T2		; Size to T1, Source to T2
	SUBI T1,1		; Number of transfers is 1 less
	XMOVEI T3,1(T2)		; Destination
	SETZM 0(T2)		; Clear a word.
	CALL XBLTA		; Clear the rest
	RET
	SUBTTL Internet Free Space Hash Table Routines

;HASHX	Given a block size, HASHX returns the index to INTBLK
;SIZ/	Size
;T1/	CreateFlag	; Non-0 to create slot if not there already
;	CALL HASHX
;Ret+1:	Always.  -1 or Index in T1. Saves SIZ.


I==T1				;[9114] Temps for this routine
L==T2				;[9114] L must be I+1
Q==T3				;[9114]
T==T4				;[9114]

HASHX:	ACVAR <FLAG>		;[9114] Place to store create flag
	MOVEM T1,FLAG		;[9114] Save create flag
	MOVSI T,-NFIXED		;[9114] Set to scan the table
	DO.			;[9114] Loop through all entries
	  MOVE I,SIZ		;[9114] Load size
	  ADDI I,0(T)		;[9114] Add probe count
	  IDIVI I,NFIXED	;[9114] Rem is the hash function
	  MOVE I,I+1		;[9114] (to I and L)
	  IMULI I,INTBLS	;[9114] Words per entry	
	  MOVEI L,INTBLK(I)	;[9114] Pointer to head of list
	  LOAD Q,BSIZE,(L)	;[9114] Get size of blocks on this one
	  IFE. Q		;[9114] If slot free
	    JUMPE FLAG,HASHXM	;[9114] Return -1 if not supposed to create it
	    STOR SIZ,BSIZE,(L)	;[9114] Create the list
	    EXIT.		;[9114] Get out of DO.
	  ENDIF.		;[9114] Slot not free
	  CAMN Q,SIZ		;[9114] Size we are looking for?
	  EXIT.			;[9114] Yes use it
	  AOBJN T,TOP.		;[9114] Probe again
HASHXM:	  SETO T1,		;[9114] Fail
	OD.			;[9114] End of loop
	RET			;[9114] Return to caller

	ENDAV.			;[9114] End of ACVAR at HASH
	PURGE I,L,Q,T		;[9114] Remove temp AC names for HASH
	SUBTTL 1822 Buffer Handling

NETINI::			; Initialize 1822 buffer area in INTSEC
	MOVEI T1,BF18SZ		; Get the number of buffers possible
	MOVEI T2,BF1822		; Get the initial buffer addess
	MOVE T3,MAXWPM		; Get the number of words per buffer
	ADDI T3,(T2)		; Get the initial link word
	SETSEC T2,INTSEC	; Buffer is in INTSEC
	MOVEM T2,BF18BO		; Save the initial head pointer
NETIN2:				; Loop for initializing buffers
	STOR T3,NBQUE,(T2)	; Store the forward link
	ADD T2,MAXWPM		; Get the address of the next buffer
	ADD T3,MAXWPM		; Get the new link word
	SOJG T1,NETIN2		; Initialize all the buffers
	SUB T2,MAXWPM		; Fix up Buffer address
	SETZRO NBQUE,(T2)	; This buffer is the last
	MOVEM T2,BF18BI		; Save the tail pointer word
	RET			; And return to caller

;Get an 1822 Buffer. Here via LCKCAL with FRELCK set

GET18B::			; Get an 1822 buffer. 
	SKIPN T1,BF18BO		; Buffer Available?
	 RET			; nope.
	SETSEC T1,INTSEC	; Buffer is in INTSEC
	LOAD T2,NBQUE,(T1)	; get the buffer's link word
	MOVEM T2,BF18BO		; set the new head word
	SKIPN T2		; was the link zero?
	 SETZM BF18BI		; yes so zero the tail pointer
	SETZRO NBQUE,(T1)	; clear forward link
	RET			; and return

;Return an 1822 buffer.  Here via LCKCAL with FRELCK set.

RET18B::			; Return an 1822 Buffer
	CAML T1,[INTSEC,,BF1822] ; Does this buffer look ok?
	CAML T1,[INTSEC,,BF1822+<BF18SZ*INTBSZ>] ; ?
	BUG.(HLT,IMPBAD,IPFREE,SOFT,<Internet free space - Attempt to return a buffer not in range>,,<

Cause:	The Internet 1822 buffer facility has been called to return a buffer
	which is not an 1822 buffer.  From looking at the dump, find the caller
	of this routine and figure out what kind of packet the caller is
	really dealing with.

>)				;[9114]
	MOVN T2,[INTSEC,,BF1822] ; Get the begining of the buffer space
	ADD T2,T1		; Get the offset of this buffer
	IDIV T2,MAXWPM		; Get the number of this buffer
	SKIPE T3		; Any remainder?
	BUG.(HLT,IMPVBD,IPFREE,SOFT,<Internet free space - Attempt to return a buffer with the address smashed>,,<

Cause:	The internet 1822 buffer facility has been called to return a buffer
	which has a bad address.

>)
	SETZRO NBQUE,(T1)	; No forward link on this buffer
	MOVE T2,BF18BI		; Get the old tail pointer
	SETSEC T2,INTSEC	; In INTSEC
	MOVEM T1,BF18BI		; We are the new tail
	STOR T1,NBQUE,(T2)	; Fix up the old tails queue
	SKIPN BF18BO		; Any buffers on the head?
	 MOVEM T1,BF18BO	; no so this is now the head
	RET			; and return 
	SUBTTL Temporary Free Space Routines for NISRV and Friends

REPEAT 0,<

	XRESCD			; THIS CODE IS RESIDENT

DNGWDS::			;Get free space for NISRV. 
	HRLI T1,.RESP2		;high priority
	MOVEI T2,.RESNP		;get the space from decnet
	CALL ASGRES		;get the space
	 RET			;non skip return means no space available
	HRLI T1,MSEC1		;in section one
	RETSKP			;and return to caller

DNFWDS::			;Release free space for NISRV.
	HRRZS T1		;zero the left half
	CALL RELRES		;release the space
	RET			;and return

DNGWDZ::			;Get zeroed free space for NISRV.
	STKVAR <DNGSZ>		;get some space
	MOVEM T1,DNGSZ		;save the size
	CALL DNGWDS		;get the space
	 RET			;failed to get the space
	MOVE T2,DNGSZ		;get the size
	MOVEM T1,DNGSZ		;save the address
	CALL CLRBLK		;zero the block
	MOVE T1,DNGSZ		;get the address back
	RETSKP			;success return
	ENDSV.

;RELJFR - Release JSB Free Space
;T2/ Location of Block to Be Returned
;	CALL RELJFR
; Returns +1: Always

RELJFR::MOVEI T1,JSBFRE		;Get address of JSB Free Space Header
	CALLRET RELFRE		;  and call routine to release the space

>				;end of Repeat 0
	SUBTTL IPNIDV Buffer Handling

	XSWAPCD			; THIS CODE IS SWAPPABLE

GETNIB::			; Get an NI Buffer
	MOVE T1,INTXPW		; input buffer size
	CALL GETBLK		; get a block of free space
	RET			; and return to caller

RETNIB::			; Return an NI buffer
	CALL RETBLK		; return a block of internet free space
	RET			; and return it to caller


;NIPLKB - LOCK BUFFER
;
; Called whenever we need a buffer locked.
;
; T1/ Address of buffer to lock
; T2/ Length of buffer
;
; Returns + 1 always, T1 and T2 preserved 

	XRESCD			; THIS CODE IS RESIDENT

NIPLKB::SAVEAC <T1,T2>
	CALL INTLKW		;LOCK THE FIRST ADDRESS
	ADD T1,T2		;COMPUTE LAST ADDRESS
	CALL INTLKW		;LOCK DOWN THE LAST ADDRESS
	RET

;NIPULK - UNLOCK BUFFER
;
; Called whenever we need a buffer unlocked.
;
; T1/ Address of buffer to unlock
; T2/ Length of buffer
;
; Returns + 1 always, T1 and T2 preserved 

	XRESCD			; THIS CODE IS RESIDENT

NIPULK::SAVEAC <T1,T2>
	CALL INTULW		;UNLOCK THE FIRST ADDRESS
	ADD T1,T2		;COMPUTE LAST ADDRESS
	CALL INTULW		;UNLOCK DOWN THE LAST ADDRESS
	RET
	SUBTTL End of IPFREE
	TNXEND
	END