Google
 

Trailing-Edge - PDP-10 Archives - BB-P363B-SM_1985 - mcb/cex/cexbuf.m11
There are no other files named cexbuf.m11 in the archive.
	.TITLE	CEXBUF - Comm/Exec Buffer Management
	.IDENT	/003180/
	.ENABL	LC

;
;                    COPYRIGHT (c) 1980, 1981, 1982
;                    DIGITAL EQUIPMENT CORPORATION
;                        Maynard, Massachusetts
;
;     This software is furnished under a license and may  be  used
;     and copied only in accordance with the terms of such license
;     and with the inclusion of the above copyright notice.   This
;     software  or any other copies thereof may not be provided or
;     otherwise made available to any other person.  No  title  to
;     and ownership of the software is hereby transferred.
;
;     The information  in  this  software  is  subject  to  change
;     without  notice  and should not be construed as a commitment
;     by DIGITAL EQUIPMENT CORPORATION.
;
;     DIGITAL assumes no responsibility for the use or reliability
;     of  its  software  on  equipment  which  is  not supplied by
;     DIGITAL.
;

;++
; FACILITY: MCB Communications Executive
;
; FUNCTIONAL ABSTRACT:
;
;	This module contains the routines which manage the MCB
;	Comm/Exec buffer pools. These include CCBs, SDBs, LDBs,
;	and RDBs.
;
; ENVIRONMENT: RSX kernel mode with EIS
;
; AUTHOR: Alan D. Peckham, CREATION DATE: 21-FEB-80
;
; MODIFIED BY:
;
;	Alan D. Peckham, 2-Jul-80: VERSION 3.0
; 01	- Change CRSH$ references to CRSH$S.
; 02	- Globalize references to I/O page.
; 03	- Moved global data to seperate module.
;	  Eliminated local data (module can now be made read-only).
; 04	- Must map buffer in $SDBRT before clearing link word.
; 05	- Add support for "CCB allocated" flag.
;	- Support SDB header, owner checking, and "SDB allocated" flag.
; 06	- Catch RDB being returned as CCB and vice-versa.
;	  Update CRSH$S context.
; 08	- Eliminate CE$CBL and CE$RBL checks.
; 09	- Detect out-of-range CCB, RDB, and SDB addresses.
;	Alan D. Peckham, 11-Dec-80: VERSION 3.1
; 10	- Add $DSRGT and $DSRRT routines for DSR checking.
; 11	- Add DSR checking crashes.
; 12	- Add CCB recovery support.
;	Alan D. Peckham, 30-Jan-80: VERSION 3.2
; 13	- Support new C.SRC and C.DST in BUFDS.
;	  Use .CRPDB where current process descriptor block is useful.
;	  Alter process descriptor scan in BUFDS to use
;	  process descriptor vector.
; 14	- Combine CCB/RDB service routines
; 15	- Correct flag handling bug in CCBRQ.
; 16	- Correct crash stack context in $CBBRT, $CORRT, and $DSRRT.
; 17	- Add $BLKGT which allocated 32 word blocks of mapped core.
; 18	- Correct $CORRT to adjust R0 when D$$BUG is turned off.
;	  Remove D$$BUG conditionals from CF.USE and CF.ACT maintenance.
;--
	.SBTTL	DECLARATIONS

;
; INCLUDE FILES:
;

	.MCALL	CRSH$S

;
; MACROS:
;

	.MACRO	CORCK$ adr,?l1
	.IF	NE,D$$BUG
	PUSH$S	adr		; Range check
	SUB	#140000,(SP)	; virtual address
	CMP	#20000,(SP)+
	BHI	l1
	CRSH$S	BFR		; Invalid address for buffer.
l1:
	.ENDC
	.ENDM	CORCK$

	.MACRO	DSRCK$ adr,?l1,?l2
	.IF	NE,D$$BUG
	CMP	#$POOL,adr
	BHI	l1
	CMP	$EXSIZ,adr
	BHI	l2
l1:	CRSH$S	DSR		; DSR address invalid
l2:
	.ENDC
	.ENDM	DSRCK$

;
; EQUATED SYMBOLS:
;
;	None
;
; OWN STORAGE:
;

	.GLOBL	.CCBTB		; Address of CCB pool table
	.GLOBL	.RDBTB		; Address of RDB pool table

	.GLOBL	.CORTA
	.GLOBL	.CORNM
;
; VALIDATION DECLARATIONS:
;
	.SBTTL	$BLKGT - Get Block of Core
;++
; FUNCTIONAL DESCRIPTION:
;
;	Allocate a core block from the pool.
;
;	NOTE: At present, only one block is assumed to be in the pool.
;
; CALLING SEQUENCE:
;
;	CALL	$BLKGT
;
; INPUT PARAMETERS:
;
;	R1 = number of 32. word blocks to allocate.
;
; IMPLICIT INPUTS:
;
;	.BLKTB = Address of free core.
;
; OUTPUT PARAMETERS:
;
;	KISAR6 = mapped to allocated block.
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$BLKGT::PLVL$			; Crash if not process level.
	MAP$	.BLKTB		; If there is a pool,
	BEQ	80$		; then
	SUB	R1,@#140002	; allocate our block
	BMI	70$		; if enough room.
	BEQ	20$
	ADD	@#140002,@#KISAR6 ; Map to allocated block.
	RETURN
20$:	CLR	.BLKTB		; Pool is exhausted.
	RETURN
70$:	ADD	R1,@#140002	; (not enough room)
80$:	SEC
	RETURN
	.SBTTL	$CCBCN - Cancel request for CCB
;++
; FUNCTIONAL DESCRIPTION:
;
;	Disable the CCB request flag for the current data base.
;
; CALLING SEQUENCE:
;
;	CALL	$CCBCN
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	.CCBTB = Address of CCB pool.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Routine CCBCN is called.
;--

	.PSECT	$CODE$,I,RO
$CCBCN::PLVL$			; Crash if not process level.
	JSR	R2,CCBCN
	.CCBTB
	.SBTTL	$CCBGT - Allocate a CCB from the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Allocate a CCB for the current process.
;
; CALLING SEQUENCE:
;
;	CALL	$CCBGT
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	.CCBTB = Address of CCB pool.
;
; OUTPUT PARAMETERS:
;
;	If success:
;	    R4 = address of CCB containing:
;		C.LNK	<zero>
;		C.CHN	<zero>
;		C.STK	<zero>
;		C.OWN	<calling process' PIX>
;	If failure:
;	    R4 = undefined.
;
; IMPLICIT OUTPUTS:
;
;	None
;
; CONDITION CODES:
;
;	C-bit set = Allocation failed.
;	C-bit clear = CCB allocated.
;
; SIDE EFFECTS:
;
;	Routine CCBGT is called.
;--

	.PSECT	$CODE$,I,RO
$CCBGT::PLVL$			; Crash if not process level.
	JSR	R2,CCBGT	; Get a CCB
	.WORD	.CCBTB		; from the CCB pool.
	.SBTTL	$CCBRQ - Request the next freed CCB
;++
; FUNCTIONAL DESCRIPTION:
;
;	Enable the CCB request flag for the current process.
;
; CALLING SEQUENCE:
;
;	CALL	$CCBRQ
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Routine CCBRQ is called.
;--

	.PSECT	$CODE$,I,RO
$CCBRQ::PLVL$			; Crash if not process level.
	JSR	R2,CCBRQ
	.CCBTB
	.SBTTL	$CCBRT - Return a CCB to the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Return a CCB to the free CCB pool.
;
; CALLING SEQUENCE:
;
;	CALL	$CCBRT
;
; INPUT PARAMETERS:
;
;	R4 = CCB to return to pool.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	.CCBTB = Address of CCB pool.
;
; CONDITION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Routine CCBRT is called.
;	Register R4 is not preserved.
;--

	.PSECT	$CODE$,I,RO
$CCBRT::PLVL$			; Crash if not process level.
	CCBCK$			; Verify CCB address.

	.IF	NE,D$$BUG
	BIT	#CF.RDB,C.FLG(R4) ; If an RDB
	BNE	100$		; then don't allow this to happen.
	.IFTF

	JSR	R2,CCBRT	; Return this
	.WORD	.CCBTB		; the CCB pool.

	.IFT
100$:	CRSH$S	CBB		; RDB being returned as CCB
	.ENDC
	.SBTTL	$CBBGT - Allocate CCB/COR from the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Allocate a CCB and COR for the current process.
;
;	If a CCB can be allocated (by calling $CCBGT), then
;	an attempt to obtain the required buffer is made (by calling
;	$CORGT).  If a buffer is not available, then the CCB is
;	returned,  otherwise the buffer bias/address is set in
;	the buffer descriptor of the CCB.
;
; CALLING SEQUENCE:
;
;	CALL	$CBBGT
;
; INPUT PARAMETERS:
;
;	R1 = length of required buffer.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	If success:
;	    R4 = address of CCB containing:
;		C.LNK	<zero>
;		C.CHN	<zero>
;		C.STK	<zero>
;		C.OWN	<calling process' PIX>
;		C.BUF	<descriptor of allocated buffer>
;	If failure:
;	    R4 = undefined.
;
; IMPLICIT OUTPUTS:
;
;	If success:
;	    KISAR6 = mapped to allocated buffer.
;	If failure:
;	    KISAR6 = undefined.
;
; CONDITION CODES:
;
;	C-bit set = Allocation of either CCB or buffer failed.
;	C-bit clear = Allocation succeeded.
;
; SIDE EFFECTS:
;
;	Routines $CCBGT and $CORGT are called.
;--

	.PSECT	$CODE$,I,RO
$CBBGT::PLVL$			; Crash if not process level.
	CALL	$CCBGT		; If we can get a CCB
	BCS	80$		; then
	PUSH$S	R0		; save register used by $CORGT.
	CALL	$CORGT		; Try for a buffer
	BCC	10$		; and if no-go
	CALL	$CCBRT		; then return the CCB
	SEC			; and return
	BR	20$		; in shame.
10$:	SMAP$	C.BUF+0(R4)	; Set the buffer mapping bias
	MOV	R0,C.BUF+2(R4)	; and the virtual address.
20$:	POP$S	R0		; Restore user registers
80$:	RETURN			; and return.
	.SBTTL	$CBBRT - Return a CCB/buffer to the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Return a CCB and attached buffer to their related
;	pools.
;
;	Simple!  Return the buffer (by calling $CORRT),  and
;	return the CCB (by calling $CCBRT).
;
; CALLING SEQUENCE:
;
;	CALL	$CBBRT
;
; INPUT PARAMETERS:
;
;	R4 = Address of CCB containing:
;	    C.BUF	<descriptor of buffer to return>
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Routines $CCBRT and $CORRT are called.
;
;	Registers R4 and KISAR6 are not preserved.
;--

	.PSECT	$CODE$,I,RO
$CBBRT::PLVL$			; Crash if not process level.
	CCBCK$			; Verify CCB address.
	CORCK$	C.BUF+2(R4)

	.IF	NE,D$$BUG
	BIT	#CF.ACT,C.FLG(R4) ; If not allocated
	BEQ	92$		; then this is not his.
	BIT	#CF.RDB,C.FLG(R4) ; If an RDB
	BNE	93$		; then don't allow this to happen.
	CMPB	.CRPIX,C.OWN(R4) ; If returning process not owner
	BNE	90$		; then quit while we're ahead.
	.IFTF

	PUSH$S	R0		; Save user's register so that we may
	MAP$	C.BUF+0(R4)	; get the buffer bias
	MOV	C.BUF+2(R4),R0	; and virtual address

	.IFT
	CMP	.CRPDB,-(R0)	; If returning process not owner
	BNE	94$		; then quit while we're ahead.
	TST	-(R0)		; If not allocated
	BEQ	95$		; then this is not his.
	CMP	R1,(R0)		; If length incorrect
	BNE	91$		; then complain.
	CMP	(R0)+,(R0)+	; Reset CORe address.
	.IFTF

	CALL	$CORRT		; to return it.
	POP$S	R0		; Restore user register
	JMP	$CCBRT		; and release the CCB.

	.IFT
93$:	CRSH$S	CBB		; RDB being returned as CCB
95$:	POP$S	R0		; Restore user register
92$:	CRSH$S	FRE		; Free buffer being returned
91$:	POP$S	R0		; Restore user register
	CRSH$S	LEN		; Buffer length is invalid
94$:	POP$S	R0		; Restore user register
90$:	CRSH$S	OWN		; Buffer not being returned by owner
	.ENDC
	.SBTTL	$CORGT - Allocate a COR buffer from the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Allocate a COR block from one of the pre-allocated pools.
;
; CALLING SEQUENCE:
;
;	CALL	$CORGT
;
; INPUT PARAMETERS:
;
;	R1 = length of block to allocate.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	If success:
;	    R0 = virtual address of buffer.
;	If failure:
;	    R0 = undefined.
;
; IMPLICIT OUTPUTS:
;
;	If success:
;	    KISAR6 = mapped to buffer.
;	If failure:
;	    KISAR6 = undefined.
;
; COMPLETION CODES:
;
;	C-bit set = Allocation failed.
;	C-bit clear = Buffer allocated.
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$CORGT::PLVL$			; Crash if not process level.
	PUSH$S	R2
	MOV	.CORTA,R2
	BNE	20$
	BR	60$
10$:	ADD	#P.BLEN-2,R2
20$:	CMP	(R2)+,R1
	BLO	10$
	DEC	(R2)+
	BMI	50$
	MAP$	(R2)+
	MOV	(R2),R0
	MOV	(R0)+,-(R2)
	MOV	(R0)+,2(R2)
	BNE	30$
	MOV	R2,6(R2)
30$:	MOV	R1,(R0)+
	MOV	.CRPDB,(R0)+
	CLC
40$:	POP$S	R2
	RETURN
50$:	INC	-(R2)
	INC	P.BALF-2(R2)
60$:	SEC
	BR	40$
	.SBTTL	$CORRT - Return a COR block to the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Return a COR block to the free pool.
;
; CALLING SEQUENCE:
;
;	CALL	$CORRT
;
; INPUT PARAMETERS:
;
;	R0 = buffer virtual address.
;
; IMPLICIT INPUTS:
;
;	KISAR6 = buffer bias.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Registers R2 and KISAR6 are not preserved.
;--

	.PSECT	$CODE$,I,RO
$CORRT::PLVL$			; Crash if not process level.
	CORCK$	R0

	.IF	NE,D$$BUG
	CMP	.CRPDB,-(R0)	; If returning process not owner
	BNE	90$		; then quit while we're ahead.
	TST	-(R0)		; If not allocated
	BEQ	91$		; then this is not his.
	CMP	R1,(R0)		; If length incorrect
	BNE	93$		; then complain.
	CLR	(R0)		; 
	.IFF
	CMP	-(R0),-(R0)
	.IFTF

	PUSH$S	R2
	MOV	.CORTA,R2
	BR	20$
10$:	ADD	#P.BLEN-2,R2
20$:	CMP	(R2)+,R1
	BLO	10$
	INC	(R2)+
	CLR	-(R0)
	CLR	-(R0)
	PUSH$S	R0
	SMAP$S
	MAP$	4(R2)
	MOV	6(R2),R0
	MOV	(SP),(R0)+
	POP$S	4(R2)
	MOV	(SP),(R0)
	POP$S	6(R2)
	POP$S	R2
	RETURN

	.IFT
90$:	TST	(R0)+		; Reset user register
	CRSH$S	OWN		; Buffer not being returned by owner.
91$:	CMP	(R0)+,(R0)+	; Reset user register
	CRSH$S	FRE		; Free buffer being returned.
93$:	CMP	(R0)+,(R0)+	; Reset user register
	CRSH$S	LEN		; Buffer length is invalid.
	.ENDC
	.SBTTL	$DSRGT - Allocate Memory from the RSX DSR
;++
; FUNCTIONAL DESCRIPTION:
;
;	Get DSR memory for requesting process.
;
; CALLING SEQUENCE:
;
;	CALL	$DSRGT
;
; INPUT PARAMETERS:
;
;	R1 = Size of memory to get in bytes.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	If success:
;	    R0 = address of allocated memory.
;	If failure:
;	    R0 is undefined.
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	C-bit set = Allocation failed.
;	C-bit clear = DSR allocated.
;
; SIDE EFFECTS:
;
;	Routine $ALOCB is called.
;--

	.PSECT	$CODE$,I,RO
$DSRGT::SAV2$S

	.IF	NE,D$$BUG
	PUSH$S	R1
	ADD	#4,R1
	.IFTF

	CALL	$ALOCB		; Just go to it for now.

	.IFT
	POP$S	(R0)+
	MOV	.CRPDB,(R0)+
	.ENDC

	RETURN
	.SBTTL	$DSRRT - Return Memory to the RSX DSR
;++
; FUNCTIONAL DESCRIPTION:
;
;	Return DSR memory from process.
;
; CALLING SEQUENCE:
;
;	CALL	$DSRRT
;
; INPUT PARAMETERS:
;
;	R0 = address of memory to be returned.
;	R1 = Size of memory to return in bytes.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	Routine $DEACB is called.
;--

	.PSECT	$CODE$,I,RO
$DSRRT::DSRCK$	R0

	.IF	NE,D$$BUG
	CMP	.CRPDB,-(R0)
	BNE	101$
	CMP	R1,-(R0)
	BNE	100$
	CLR	(R0)
	.IFTF

	SAV3$S

	.IFT
	ADD	#4,R1
	.IFTF

	CALL	$DEACB		; Just go to it for now.
	RETURN

	.IFT
100$:	CMP	(R0)+,(R0)+
	CRSH$S	LEN		; DSR length incorrect.
101$:	TST	(R0)+
	CRSH$S	OWN		; DSR being returned by foreigner
	.ENDC
	.SBTTL	$RDBCN - Cancel request for RDB
;++
; FUNCTIONAL DESCRIPTION:
;
;	Disable the RDB request flag for the current data base.
;
; CALLING SEQUENCE:
;
;	CALL	$RDBCN
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	.CRPIX = data base index.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$RDBCN::PLVL$			; Crash if not process level.
	JSR	R2,CCBCN
	.RDBTB
	.SBTTL	$RDBGT - Allocate a RDB from the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	Allocate a RDB for the current process.
;
;	If a RDB is available,  it  is  allocated,  and  the
;	count of RDBs in the pool is decremented.  Otherwise
;	the RDB allocation failure count is incremented.
;
; CALLING SEQUENCE:
;
;	CALL	$RDBGT
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	.RDB*H = Free RDB list header.
;	.CRPIX = process index of the current process.
;
; OUTPUT PARAMETERS:
;
;	If success:
;	    R4 = address of CCB containing:
;		C.LNK	<zero>
;		C.CHN	<zero>
;		C.STK	<zero>
;		C.OWN	<calling process' PIX>
;		C.BUF	<descriptor of RDB>
;	If failure:
;	    R4 = undefined.
;
; IMPLICIT OUTPUTS:
;
;	If success:
;	    .RDBCT = count of RDBs in pool.
;	If failure:
;	    .RDBAF = number of RDB allocation failures.
;
; COMPLETION CODES:
;
;	C-bit set = Allocation failed.
;	C-bit clear = RDB allocated.
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$RDBGT::PLVL$			; Crash if not process level.
	JSR	R2,CCBGT	; Get a RDB
	.WORD	.RDBTB		; from the RDB pool.
	.SBTTL	$RDBRQ - Request the next freed RDB
;++
; FUNCTIONAL DESCRIPTION:
;
;	Enable the RDB request flag for the current data base.
;
; CALLING SEQUENCE:
;
;	CALL	$RDBRQ
;
; INPUT PARAMETERS:
;
;	None
;
; IMPLICIT INPUTS:
;
;	.CRPIX = data base index.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$RDBRQ::PLVL$			; Crash if not process level.
	JSR	R2,CCBRQ
	.RDBTB
	.SBTTL	$RDBRT - Return a RDB to the free pool
;++
; FUNCTIONAL DESCRIPTION:
;
;	The RDB is returned to the free pool.
;
;	If the returner of the RDB is not the owner,  a  RBO
;	crash is generated.  If there is more than  one  RDB
;	linked together, a RBL crash is generated. Otherwise
;	count of RDBs in the pool is incremented and the RDB
;	is linked into the pool.
;
; CALLING SEQUENCE:
;
;	CALL	$RDBRT
;
; INPUT PARAMETERS:
;
;	R4 = RDB to return to the pool.
;
; IMPLICIT INPUTS:
;
;	.CRPIX = process index of the current process.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	.RDB*H = Free RDB list header.
;	.RDBCT = count of RDBs in pool.
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
$RDBRT::PLVL$			; Crash if not process level.
	CCBCK$			; Verify CCB address.

	.IF	NE,D$$BUG
	PUSH$S	C.BUF+2(R4)	; Range check
	SUB	#140000,(SP)	; virtual address
	CMP	#20000,(SP)+
	BLOS	101$
	BIT	#CF.RDB,C.FLG(R4) ; If an CCB
	BEQ	100$		; then don't allow this to happen.
	PUSH$S	C.BUF+0(R4)	; and bias.
	SUB	.RDBCM+0,(SP)
	CMP	.RDBCM+2,(SP)+
	BLOS	101$
	.IFTF

	JSR	R2,CCBRT	; Return this
	.WORD	.RDBTB		; the RDB pool.

	.IFT
100$:	CRSH$S	RBB		; CCB being returned as RDB
101$:	CRSH$S	RBR		; Invalid bias/address for RDB
	.ENDC
	.SBTTL	CCBCN - Cancel request for a CCB/buffer
;++
; FUNCTIONAL DESCRIPTION:
;
;	This is a common routine to cancel a request for a CCB, RDB or SDB.
;
; CALLING SEQUENCE:
;
;	JSR	R2,CCBCN
;	.WORD	address_of_ccb_pool_block
;
; INPUT PARAMETERS:
;
;	(SP) = return address.
;
; IMPLICIT INPUTS:
;
;	.CRPDB = current process descriptor block.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
CCBCN:	MOV	(R2),R2		; Get CCB pool block
	PUSH$S	R1
	MOV	.CRPDB,R1	; and current process descriptor.
	BIT	P.CFLG(R2),Z.FLG(R1) ; If flag is up
	BEQ	80$		; then
	BIC	P.CFLG(R2),Z.FLG(R1) ; clear the buffer request flag,
	DEC	P.CREQ(R2)	; another request cancelled,
80$:	POP$S	<R1,R2>		; and restore the registers.
	RETURN
	.SBTTL	CCBGT - Get a CCB/buffer
;++
; FUNCTIONAL DESCRIPTION:
;
;	This is a common routine to dispatch a CCB to the next needy process.
;
; CALLING SEQUENCE:
;
;	JSR	R2,CCBGT
;	.WORD	address_of_ccb_pool_block
;
; INPUT PARAMETERS:
;
;	(SP) = return address.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
CCBGT:	MOV	(R2),R2
	ADD	#P.CQUE,R2

	.IF	NE,C$$QUE
	MOV	(R2),R4		; If there is a CCB available
	BEQ	80$		; then
	MOV	(R4),(R2)	; un-link it from the list
	BNE	10$		; and if now empty
	MOV	R2,2(R2)	; then reset queue header.
10$:	DEC	4(R2)		; This CCB is no longer free.
	.IFF
	MOV	(R2),R4		; If there is a CCB available
	BEQ	80$		; then
	MOV	(R4),(R2)	; un-link it from the stack.
	DEC	(R2)		; This CCB is no longer free.
	.ENDC

	BIS	#CF.ACT!CF.USE,C.FLG(R4) ; Indicate allocated.
	MOVB	.CRPIX,C.OWN(R4) ; Set owner.
	CLR	C.STK(R4)	; Clear stack pointer
	CLR	C.CHN(R4)	; buffer chain pointer
	CLR	(R4)		; and link word (C-bit clear).
90$:	POP$S	R2
	RETURN

80$:	INC	-(R2)		; Account for failure
	BNE	82$		; and if overflow
	DEC	(R2)		; then back it up.
82$:	SEC			; Indicate error.
	BR	90$
	.SBTTL	CCBRQ - Request the next freed CCB/buffer
;++
; FUNCTIONAL DESCRIPTION:
;
;	This is a common routine to enable a request for a CCB, RDB or SDB.
;
; CALLING SEQUENCE:
;
;	JSR	R2,CCBRQ
;	.WORD	address_of_ccb_pool_block
;
; INPUT PARAMETERS:
;
;	(SP) = return address.
;
; IMPLICIT INPUTS:
;
;	.CRPDB = current process descriptor block.
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
CCBRQ:	MOV	(R2),R2		; Get CCB pool block

	.IF	NE,D$$BUG
	TST	P.CCNT(R2)	; and if there is a buffer available
	BNE	100$		; then he is mistaken.
	.IFTF

	PUSH$S	R1
	MOV	.CRPDB,R1	; Get current process descriptor
	BIT	P.CFLG(R2),Z.FLG(R1) ; and if flag not already up
	BNE	80$		; then
	BIS	P.CFLG(R2),Z.FLG(R1) ; set the buffer request flag,
	INC	P.CREQ(R2)	; count another request,
80$:	POP$S	<R1,R2>		; and restore the registers.
	RETURN

	.IFT
100$:	CRSH$S	IBR		; CCB request with pool non-empty
	.ENDC
	.SBTTL	CCBRT - Return CCB/buffer to Pool or Needy Process
;++
; FUNCTIONAL DESCRIPTION:
;
;	This is a common routine to dispatch a CCB to the next needy process.
;
; CALLING SEQUENCE:
;
;	JSR	R2,CCBRT
;	.WORD	address_of_ccb_pool_block
;
; INPUT PARAMETERS:
;
;	(SP) = return address.
;
; IMPLICIT INPUTS:
;
;	None
;
; OUTPUT PARAMETERS:
;
;	None
;
; IMPLICIT OUTPUTS:
;
;	None
;
; COMPLETION CODES:
;
;	None
;
; SIDE EFFECTS:
;
;	None
;--

	.PSECT	$CODE$,I,RO
CCBRT:	MOV	(R2),R2
	ADD	#P.CREQ,R2

	.IF	NE,D$$BUG
	BIT	#CF.ACT,C.FLG(R4) ; If not allocated
	BEQ	100$		; then this is not his.
	CMPB	.CRPIX,C.OWN(R4) ; If returning process not owner
	BNE	101$		; then quit while we're ahead.
	.IFTF

	TST	(R2)		; If CCB requested
	BNE	20$		; then dispatch to hungry process.
	BIC	#CF.ACT,C.FLG(R4) ; This is now ours.
	INC	-(R2)		; This CCB now free.

	.IF	NE,C$$QUE
	CLR	(R4)		; Clear the link,
	MOV	R4,@-(R2)	; set this CCB to last in queue
	MOV	R4,(R2)		; and new end of queue.
	.IFF
	MOV	-(R2),(R4)	; Link top of stack to this CCB
	MOV	R4,(R2)		; and set new top of stack.
	.ENDC

	POP$S	R2
	RETURN
20$:	PUSH$S	<R1,R0>		; Get room for
	DEC	(R2)+
	MOV	(R2)+,R0	; process descriptor vector pointer.
22$:	CMP	.PDBVE,R0	; If last process descriptor
	BHI	24$		; then
	MOV	#.PDBVB,R0	; reset to start of vector.
24$:	MOV	(R0)+,R1	; Go on to next
	BEQ	22$		; (if there is one)
	BIT	(R2),Z.FLG(R1)	; and if request flag is up
	BEQ	22$		; then
	MOV	R0,-2(R2)	; service this data base.
	BIC	(R2)+,Z.FLG(R1) ; Request is satisfied.
	CLR	(R4)		; Clear link word,
	CLR	C.STK(R4)	; stack pointer,
	CLR	C.CHN(R4)	; and buffer chain pointer.
	MOVB	Z.PIX(R1),C.OWN(R4) ; Destination is owner.
	MOVB	(R2)+,C.FNC(R4) ; Set up dispatch codes.
	MOVB	(R2)+,C.MOD(R4)
	CLR	C.SRC(R4)	; We are source,
	MOV	R1,C.DST(R4)	; destination is this process.
	POP$S	<R0,R1,R2>
	JMP	$CCBQL		; Queue to lower process.

	.IFT
100$:	POP$S	R2
	CRSH$S	FRE		; Free CCB being returned
101$:	POP$S	R2
	CRSH$S	OWN		; CCB not being returned by owner
	.ENDC

	.END