Google
 

Trailing-Edge - PDP-10 Archives - tops20v41_monsrc - monitor-sources/fesrv.mac
There are 48 other files named fesrv.mac in the archive. Click here to see a list.
; UPD ID= 46, FARK:<4-1-WORKING-SOURCES.MONITOR>FESRV.MAC.2,   3-Apr-82 18:47:17 by ZIMA
;Edit 2607 - add ENDAV.s to ACVARs to use v5 MACSYM.
;<4-1-FIELD-IMAGE.MONITOR>FESRV.MAC.2, 25-Feb-82 20:21:05, EDIT BY DONAHUE
;UPDATE COPYRIGHT DATE
;<4.MONITOR>FESRV.MAC.4,  3-Jan-80 08:08:40, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<OSMAN.MON>FESRV.MAC.1, 10-Sep-79 15:28:23, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>FESRV.MAC.2,  4-Mar-79 16:40:07, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.MONITOR>FESRV.MAC.1,  8-Dec-78 17:26:37, EDIT BY MILLER
;USE HLDF TO REQUEST HOLD IN BALSET

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG
	TTITLE FESRV
   IFN KLFLG,<
	SEARCH PROKL>

;DEVICE CODE FOR FE DEVICES. THIS CODE CONTAINS THE DEVICE
;DEPENDENT ROUTINES FOR THE FE PSEUDO DEVICES. THE DEVICE NAMES
;ARE FEN: WHERE 0<=N<=3

;REGISTERS USED HEREIN

DEFAC (STS,P1)			;GTJFN,ETC BITS
DEFAC (JFN,P2)			;THE JFN FOR THE OPERATION
DEFAC (DEV,P4)

;STORAGE DEFINED IN STG FOR FE'S

EXTN<FELOCK,FEUDB0,FEUDB1,FEUDB5,FEUDB6,FEUDB7,FEUDB3,FEUDB4,FEN>

BLKSIZ==^D64			;SIZE OF A BUFFER

;DATA DEFINITIONS FOR UNIT DATA BLOCKS


DEFSTR (FEACT,FEUDB0,0,1)	;OUTPUT ACTIVE BIT
DEFSTR (FEDTE,FEUDB0,2,2)	;FIELD FOR WHICH DTE OWNS THIS DEVICE
DEFSTR (FEFRK,FEUDB0,35,18)	;FORK NUMBER OWNING DEVICE
DEFSTR (FEBLK,FEUDB0,3,1)	;UNIT IS BLOCKED
DEFSTR (FEEOF,FEUDB0,4,1)	;INPUT EOF DECLARED BY FE
DEFSTR (FEVDT,FEUDB0,5,1)	;FE ASSIGNMENT IS VALID
DEFSTR (FEFEM,FEUDB0,17,12)	;FE ALLOCATION
DEFSTR (FEICT,FEUDB1,11,12)	;CURRENT INPUT COUNT IN BYTES
;DEFSTR (FEICM,FEUDB1,23,12)	;UNUSED
DEFSTR (FEFEI,FEUDB1,35,12)	;BYTES NOW IN FE
DEFSTR (FEIBF,FEUDB3,17,18)	;BUFFER ADDRESS
DEFSTR (FEOCT,FEUDB3,35,12)	;OUTPUT COUNT
DEFSTR (FEBSZ,FEUDB3,23,6)	;BYTE SIZE OF OPENING
FEBPI==FEUDB4			;INPUT INPUT POINTER
DEFSTR (FEHNG,FEUDB5,0,1)	;HUNG BIT
DEFSTR (FEPRO,FEUDB5,11,11)	;COUNT OF INPUT SINCE LAST ACK
DEFSTR (FEIBC,FEUDB5,23,12)	;COUNT OF BYTES IN INTERRUPT BUFFER
DEFSTR (FEOE1,FEUDB5,35,12)	;BYTES REMAINING FOR OUTPUT LEVEL
FEBPO==FEUDB6			;OUTPUT OUTPUT POINTER
DEFSTR (FEIE1,FEUDB7,11,12)	;BYTES REMAINING FOR INPUT LEVEL
DEFSTR (FEOEB,FEUDB7,23,12)	;BYTES REMAINING FOR OUTPUT INT LEVEL
DEFSTR (FEIEB,FEUDB7,35,12)	;BYTES REMAINING FOR INPUT IN LEVEL
;DEVICE TRANSFER VECTOR

;FIRST THE PROTOCOL VECTOR

	RESCD

FEDTV::FEHSD			;STRING DATA
	FEDON			;ACK
	FESSTS			;STATUS
	FESLA			;SET LINE ALLOCATION
	0			;NO SYSERR
	FERLD			;RELOAD ACTION

	SWAPCD

FEDTB::	DTBBAD (GJFX32)		;SET DIRECTORY
	DTBBAD (DESX9)		;NAME LOOKUP
	DTBBAD (DESX9)		;EXTENSION LOOKUP
	DTBBAD (DESX9)		;VERSION LOOKUP
	DTBBAD (DESX9)		;PROTECTION INSERTION
	DTBBAD (DESX9)		;ACCOUNT INSERTION
	DTBBAD (DESX9)		;STATUS INSERTION
	DTBDSP (FEOPN) 		;OPEN
	DTBDSP (FEBIN)		;BIN
	DTBDSP (FEBOUT)		;BOUT
	DTBDSP (FECLZ)		;CLOSE
	DTBBAD (DESX9)		;RENAME
	DTBBAD (DESX9)		;DELD
	DTBBAD (DUMPX6)		;DUMPI
	DTBBAD (DUMPX6)		;DUMPO
	DTBBAD (DESX9)		;MOUNT
	DTBBAD (DESX9)		;DISMOUNT
	DTBBAD (DESX9)		;INIT DIRECTORY
	DTBDSP (FEMTO)		;MTOPR
	DTBBAD (DESX9)		;GETSTS
	DTBBAD (DESX9)		;SETSTS
	DTBSKP			;RECORD OUT
	DTBDSP (RFTADN)		; READ TAD
	DTBDSP (SFTADN)		; SET TAD
	DTBDSP (FESETI)		;SET JFN FOR INPUT
	DTBDSP (FESETO)		;SET JFN FOR OUTPUT
	DTBBAD (GJFX49)		;CHECK ATTRIBUTE

	DTBLEN==:.-FEDTB	;GLOBAL LENGTH OF DISPATCH TABLE
	SWAPCD

;FEINI IS CALLED AT SYSTEM STARTUP TO INITIALIZE THE FE DATA
;BASE.

FEINI::	MOVSI A,-FEN		;NUMBER OF FE'S IN CONFIGURATION
	SETOM FELOCK		;INIT LOCK TO AVAILABLE
FECLR:	SETZM FEUDB0(A)		;CLEAR UDB0
	SETZM FEUDB1(A)		;UDB1
	AOBJN A,FECLR		;DO ALL DEVICES
	RET			;AND DONE

;ROUTINE TO OPEN AN FE DEVICE. ACCEPTS:
;	DEV/ UNIT,,DTB ADDRESS
;	STS/ BITS AND BYTE SIZE

	SWAPCD			;IS SWAPPABLE
FEOPN:	ACVAR <W1>
	STKVAR <<BTARG,2>>	;ARGS FOR BOOT JSYS
	SKIPN PROFLG		;EVER GOING TO USE PRIMARY PROTOCOL ?
	RETBAD (OPNX18)		;NO, ISSUE ERROR
	MOVE A,CAPENB		;GET ENABLED CAPABILITIES
	TXNN A,SC%WHL!SC%OPR	;MUST BE WHEEL OR OPERATOR
	RETBAD (CAPX1)		;IF NOT, RETURN WITH ERROR
	LDB W1,PBYTSZ		;GET DEISRED BYTE SIZE OF OPEN
	CAIE W1,10		;8 BITS
	CAIN W1,20		;OR 16 BITS?
	JRST FEOPN2		;YES. ALLOW IT
	CAIE W1,7		;OR 7 BITS?
	RETBAD (SFBSX2)		;NO. CAN'T DO IT THEN
FEOPN2:	LOCK FELOCK,<CALL LCKTST> ;LOCK UP THE DATA BASE
	HLRZ D,DEV		;GET PROPER UNIT
	JN FEFRK,(D),[	UNLOCK FELOCK ;ALREADY ASSIGNED?
			RETBAD (OPNX9)] ;YES. GIVE ERROR
	TRNE STS,17		;NORMAL MODE?
	RETBAD (OPNX14,<UNLOCK FELOCK>) ;NO. BOMB HIM
	JUMPN D,FEOPN1		;IF NOT FE0, DON'T SET DTE ASSIGNMENT
	JN FEVDT,(D),FEOPN1	;IF ALREADY ASSIGNED ,SKIP THIS
	MOVEI A,.BTSTS		;READ DTE STATUS
	MOVEI B,BTARG		;WHERE ARG IS
	MOVEM D,.BTDTE(B)	;SET UP ARG
	BOOT			;READ PROTOCOL STATUS
	 ERJMP FEOPN1		;IF NON-EX DTE, GO ON
	MOVE B,.BTCOD(B)	;GET PROTOCOL STATE
	CAIE B,.VN20F		;DOING 20F PROTOCOL?
	JRST FEOPN1		;NO
	STOR D,FEDTE,(D)	;MAKE THIS ON THE DEFAULT FE
	SETONE FEVDT,(D)	;SAY ASSIGNMENT IS NOW VALID
	; ..
;FEOPN CONTINUED

;ASSIGN BUFFERS TO THIS FE

FEOPN1:	TQZE <RNDF>		;WANT APPEND?
	TQO <WRTF>		;YES. GIVE WRITE THEN
	MOVE A,[.RESP3,,BLKSIZ*2] ;GET BUFFER SPACE FOR THIS FE
	MOVE B,[RS%SE0!.RESNP]	;FROM THE NETWORK POOL
	CALL ASGRES		;GO GET THE FREE SPACE
	 JRST [	UNLOCK FELOCK	;FAILED. FREE THE LOCK
		RETBAD()]	;AND DON'T DO THE OPEN
	HLRZ D,DEV		;GET BACK UNIT NUMBER
	STOR A,FEIBF,(D)	;STORE BUFFER ADDRESS

;BUFFERS ARE ASSIGNED

	MOVEI A,^D36		;BITS PER WORD
	IDIV A,W1		;COMPUTE BYTES PER WORD
	IMULI A,BLKSIZ		;BYTES PER BUFFER
	STOR W1,FEBSZ,(D)	;REMEMBER BYTE SIZE OF OPENING
	CAIN W1,20		;WORD MODE?
	MOVEI A,BLKSIZ*4	;YES. INT BUFFER HAS THIS SIZE THEN
	STOR A,FEIBC,(D)	;STORE BYTES IN INTERRUPT BUFFER
	SETZRO <FEICT,FEOCT,FEACT,FEFEI,FEPRO>,(D) ;CLEAR COUNTS
	JN FEFEM,(D),FEOPN3	;HAVE AN ALLOCATION YET?
	STOR A,FEFEM,(D)	;NO. ASSUME A WHOLE BUFFER
FEOPN3:	CALL SETINB
	CALL SETINI
	CALL SETOPB
	CALL SETOBI		;GO INIT ALL BUFFER POINTERS
	MOVE A,FORKX		;OWNING FORK
	STOR A,FEFRK,(D)	;REMEMBER THIS
	OPSTR <SKIPE>,FEVDT,(D)	;HAVE VALID ASSIGNMENT?
	CALL SETALC		;YES, GO DECLARE LINE ALLOCATION
	UNLOCK FELOCK		;FREE THE LOCK
	TQO <SIZEF>		;CAN'T CHANGE FILE BYTE SIZE
	RETSKP			;AND DONE
;**;[2607] Add one line at FEOPN3: +11L	JGZ	3-APR-82
	ENDAV.			;[2607] END ACVAR
;ROUTINES TO INIT POINTERS AND COUNTS

;ROUTINE TO SET UP FILBYT FOR FILE
;ACCEPTS:	D/ FE UNIT NUMBER
;		JFN/ THE JFN FOR THE FILE

SETOPB:	LOAD A,FEIBC,(D)	;GET MAX COUNT
	STOR A,FEOE1,(D)	;SET THIS UP AS CURRENT
	CALL FRMINP		;GET POINTER
	ADDI A,BLKSIZ		;MOVE IT TO THE OUTPUT BUFFER
	MOVEM A,FILMS2(JFN)	;SAVE IT
	RET			;AND DONE

;SET UP POINTER AND COUNT FOR OUTPUT INTERRUPT LEVEL

	RESCD			;CALLED FROM INT LEVEL
SETOBI:	LOAD A,FEIBC,(D)	;GET MAX COUNT OF INT BUFFER
	STOR A,FEOEB,(D)	;SAVE IT
	CALL FRMINP		;GET POINTER
	TLZE A,2000		;WORD MODE?
	TLO A,1000		;YES. CHANGE TO BYTES
	ADDI A,BLKSIZ		;POINT TO OUTPUT BUFFER
	MOVEM A,FEBPO(D)		;SAVE IT
	RET			;AND DONE

;ROUTINE TO SET UP INPUT POINTER AND COUNT

	SWAPCD
SETINB:	LOAD A,FEIBC,(D)	;GET MAX COUNT
	STOR A,FEIE1,(D)	;SAVE IT
	CALL FRMINP		;GET POINTER
	MOVEM A,FILOFN(JFN)	;SAVE IT
	RET			;AND DONE

;ROUTINE TO SET UP INPUT INT POINTER AND COUNT

	RESCD			;CALLED FROM INT LEVEL
SETINI:	LOAD A,FEIBC,(D)	;GET MAX COUNT OF INT BUFFER
	STOR A,FEIEB,(D)	;SAVE IT
	CALL FRMINP		;GET POINTER
	TLZE A,2000		;WORD MODE?
	TLO A,1000		;YES. MAKE IT BYTE MODE
	MOVEM A,FEBPI(D)		;SAVE IT
	RET			;AND DONE

;ROUTINE TO FORM A BYTE POINTER

FRMINP:	LOAD A,FEIBF,(D)	;GET BUFFER ADDRESS
	LOAD B,FEBSZ,(D)	;GET BYTE SIZE OF OPENING
	IORI B,4400		;MAKE PROPER BYTE POINTER
	DPB B,[POINT 12,A,11]	;COMBINE HALVES
	RET			;DONE
;ROUTINE TO OUTPUT A BYTE TO AN FE. ACCEPTS:
;	A/THE BYTE
;	JFN/ THE JFN FOR THE OPERATION
;	DEV/ UNIT,,DTB

	SWAPCD			;IS SWAPPABLE
FEBOUT:	HLRZ D,DEV		;GET UNIT
	JE FEVDT,(D),[	TQO <ERRF>	;OF NO VAILD ASSIGNMENT,
			RET]		;THIS IS AN ERROR
	STKVAR <SAVCHR>
	MOVEM A,SAVCHR		;SAVE THE BYTE
	CALL FESETO		;AND GO SET UP OUTPUT
	SOSGE FILCNT(JFN)	;ROOM?
	JRST [	CALL STRTFE	;GO START UP THE DEVICE
		MOVSI A,0(D)
		HRRI A,FEFULL
		TQO <BLKF>	;NEED TO BLOCK
		RET]
	MOVE A,SAVCHR		;GET BACK BYTE
	IDPB A,FILBYT(JFN)	;STORE IT
	RET			;AND DONE
;SCHEDULER TEST ROUTINES

	RESCD

FEFULL:	JE FEVDT,(A),1(4)	;MAKE SURE STILL HAS AN ASSIGNMENT
	LOAD B,FEOCT,(A)	;GET CURRENT COUNT
	OPSTR <CAML B,>,FEIBC,(A) ;ROOM YET?
	JRST 0(4)		;NO.
	JRST 1(4)		;YES

FEDOBE::JE FEVDT,(A),1(4)	;MAKE SURE STILL HAS ASSIGNMENT
	OPSTR <SKIPE>,FEOCT,(A)	;IS OUTPUT BUFFER EMPTY?
	JRST 0(4)		;NO. CAN'T WAKE YET
	OPSTR <SKIPE>,FEFEI,(A)	;HAS FE ACKED ALL BYTES?
	JRST 0(4)		;NO. CAN'T WAKE YET
	JRST 1(4)		;YES. TIME TO AWAKEN

;ROUTINE CALLED FROM DETSRV AT SCHEDULER LEVEL TO SEE IF ANY
;FE'S NEED ATTENTION

FEPOLL:	MOVEI D,-FEN		;POLL ALL DEVICES
FEPOL2:	JE FEHNG,(D),FEPOL1	;IS ATTENTION BIT UP?
	SETZRO FEHNG,(D)	;YES. CLEAR IT
	CALL STRTF1		;AND GO START UP THE DEVICE
FEPOL1:	AOBJN D,FEPOL2		;DO ALL OF THEM
	RET			;AND DONE

;-11 RELOAD ACTION

FERLD:	MOVSI D,-FEN		;SCAN ALL FE'S
FERLD1:	JE FEVDT,(D),FERLD2	;DON'T LOOK AT INACTIVE FE'S
	LOAD B,FEDTE,(D)	;GET ITS ASSIGNMENT
	CAIE B,0(A)		;SAME AS RELOADING -11?
	JRST FERLD2		;NO. SKIP IT
	SETZRO FEVDT,(D)	;YES. CLEAR ASSIGNMENT AND GIVE
				; PROGRAM ERROR NEXT I/O ATTEMPT
FERLD2:	AOBJN D,FERLD1		;SCAN THEM ALL
	RET			;AND DONE
;DTE STARTUP AND INTERRUPT CODE

STRTFE:	JN FEACT,(D),R		;IS IT ACITVE YET?
	SETONE FEACT,(D)	;NO. START IT UP THEN
STRTF1:	NOSKD1
	CHNOFF DLSCHN		;AND THE DTE
	CALL FEINT1		;AND GO START A TRANSFER
	CHNON DLSCHN		;TURN ON THE DTE
	OKSKD1			;AND THE SCHEDULER
	RET			;AND DONE

;DTE POST ROUTINE

;	A/ UNIQUE CODE
;	B/ FE UNIT NUMBER

	RESCD			;MUST BE RESIDENT
FEINT:	CALL CHKFE
	 RET			;BAD DTE
	MOVE D,B		;MOVE DTE NUMBER
	LOAD C,FEOCT,(D)	;GET CURRENT COUNT
	SUBI C,0(A)		;ACCOUNT FOR BYTES JUST SENT
	STOR C,FEOCT,(D)	;AND UPDATE THE COUNT
	OPSTRM <ADDM A,>,FEFEI,(D) ;AND INCREMENT BYTES IN THE FE
	LOAD C,FEOEB,(D)	;GET BYTES IN PHYSICAL BUFFER
	SUBI C,0(A)		;ACCOUNT FOR THE ONES SENT
	JUMPLE C,[CALL SETOBI	;INIT NEW VALUES
		JRST FEINT1]	;AND PROCEED
	STOR C,FEOEB,(D)	;NEW COUNT
	ADJBP A,FEBPO(D)	;UPDATE THE BYTE POINTER
	MOVEM A,FEBPO(D)	;AND SAVE NEW VALUE
	; ..
;DTE POST AND STARTUP CODE (STRTFE) JOIN HERE

FEINT1:	JE FEOCT,(D),[SETZRO FEACT,(D)
		RET]		;ALL DONE IF NO MORE BYTES
	LOAD A,FEOCT,(D)	;GET CURRENT OUTPUT COUNT
	LOAD C,FEFEM,(D)	;GET MAX BYTES ALLOWED IN FE
	OPSTR <SUB C,>,FEFEI,(D) ;NUMBER REMAINING IN QUOTA
	JUMPLE C,[SETONE FEBLK,(D) ;IF NO MORE ROOM, SAY WE ARE BLOCKED
		RET]		;AND GIVE UP FOR NOW
	CAILE A,0(C)		;ROOM FOR ALL BYTES?
	MOVEI A,0(C)		;NO. TAKE SMALLER NUMBER THEN
	LOAD C,FEOEB,(D)	;GET ROOM LEFT IN PHYSICAL BUFFER
	CAILE A,0(C)		;DO WE NEED WRAP TO HANDLE ALL OF THEM?
	MOVEI A,0(C)		;YES. DO AS MANY AS POSSIBLE THEN
	LOAD B,FEBSZ,(D)	;GET BYTE SIZE OF OPENING
	CAIN B,20		;WORD MODE?
	JRST [	TRZN A,1	;YES. MUST BE EVEN COUNT THEN
		JRST .+1	;ALREADY IS
		JUMPN A,.+1	;WASN'T. IS IT NOW NON-ZERO?
		SETONE FEBLK,(D) ;NO. SAY WE ARE BLOCKED
		RET]		;AND GIVE UP
	MOVEI C,0(A)		;COUNT
	HRLI C,0(D)		;UNIT
	PUSH P,D		;SAVE UNIT NUMBER
	PUSH P,F		;SAVE FLAGS
	MOVEI F,0(A)		;SAVE COUNT AS UNIQUE CODE
	CAIE B,20		;WORD MODE?
	TXO C,DTBYTM		;NO. FORCE BYE-MODE TRANSFER
	LOAD A,FEDTE,(D)	;DTE NUMBER
	HRLI A,FEINT		;WHERE TO POST TO
	MOVE B,[.DFHSD,,.FEFE]
	MOVE D,FEBPO(D)		;BYTE POINTER
	CALL DTEQ		;GO SEND DATA
	 JRST [	POP P,F		;FAILED.
		POP P,D		;GET BACK UNIT NUMBER
		SETONE FEHNG,(D) ;TELL SCHEDULER TO TRY AGAIN
		RET]		;AND DONE
	POP P,F			;RESTORE F
	POP P,D			;AND UNIT NUMBER
	RET			;AND DONE
;MTOPR FUNCTIONS FOR THE FE DEVICES. 
;ACCEPTS:	2/FUNCTION
;		USER 3/DATUM

;VALID FUNCTIONS:
;	.MODTE	ASSIGN FE TO SPECIFIED DTE
;	.MOEOF	EOF ON OUTPUT SIDE OF FE

	SWAPCD			;ALL SWAPPABLE
FEMTO:	STKVAR <<BTARGM,2>>	;SPACE FOR BOOT ARGS
	TQNN <OPNF>		;ILLEGAL IF OPENED
	RETBAD (CLSX1)		;JFN NOT OPENED ERROR
	UMOVE C,C		;GET DATUM
	HRRZS C			;RIGHT HALF ONLY
	HLRZ D,DEV		;GET FE UNIT
	CAIN B,.MOEOF		;SETTING OUTPUT EOF?
	JRST CLZIT		;YES. GO DO IT
	CAIE B,.MODTE		;SETING DTE ASSIGNMENT?
	RETBAD (MTOX1)		;NO. UNKNOWN CODE
	JN FEVDT,(D),[		;NOW HAVE A VALID ASSIGNMEMT?
		OPSTR <CAME C,>,FEDTE,(D) ;YES.IS IT THE SAME ONE?
		JRST .+1	;NO. DO ASSIGNMENT
		RETSKP]		;YES. ALL DONE THEN
	MOVEI A,.BTSTS		;SET UP TO VERIFY THIS DTE
	MOVEI B,BTARGM		;ARG BLOCK
	MOVEM C,.BTDTE(B)	;INTO ARG BLOCK
	BOOT			;GET STATE
	 ERJMP [RETBAD (ASNDX3)] ;INVALID DTE
	MOVE B,.BTCOD(B)	;GET PROTOCOL
	CAIE B,.VN20F		;PROPER?
	RETBAD (ASNDX3)		;NO
	SETONE FEVDT,(D)	;REMEMBER IT HAS BEEN ASSIGNED
	STOR C,FEDTE,(D)	;SET ASSIGNMENT
	CALL SETALC		;GO SET DEVICE ALLOCATION
	RETSKP			;DONE SUCCESSFULLY
;GENERATE DEVICE EOF TO THE FE

CLZIT:	JE FEVDT,(D),[	RETBAD (ASNDX3)] ;IF NO VALID ASSIGNMENT
	CALL FEIUND		;UNDO INPUT TO GET AN ACK (FOR THE DN64)
	CALL FEOUND		;UNDO OUTPUT
	JE FEOCT,(D),CLZIT1	;ANY BYTES TO GO?
CLZIT2:	CALL STRTFE		;YES. MAKE THEM GO NOW
	MOVSI A,0(D)		;UNIT #
	HRRI A,FEDOBE		;TEST ROUTINE
	TQO <BLKF,HLDF>		;REQUEST BLOCK AND HOLD
	RET
CLZIT1:	CALL SETOPB		;INIT OUTPUT POINTERS
	CALL SETOBI		;""
	UMOVE C,C		;GET IT AGAIN
	SKIPE C			;SEND EOF
	RETSKP			;NO. JUST RETURN
	HLRZ D,DEV		;GET UNIT AGAIN
	LOAD A,FEDTE,(D)
	MOVE B,[.DFSTS,,.FEFE]	;SET DEVICE STATUS
	MOVSI C,0(D)		;UNIT
	HRRI C,2		;COUNT OF BYTES
	MOVE D,[POINT 8,[BYTE (16) .DVFEF]]
	CALL DTEQ		;DO IT
	 JFCL			;WILL GO
	RETSKP			;AND DONE

;ROUTINE TO DECLARE ALLOCATION OF THIS LINE
;	D/ UNIT NUMBER

SETALC:	LOAD A,FEDTE,(D)	;GET DTE ASSIGNMENT
	MOVE B,[.DFHLA,,.FEFE]	;FUNCTION,,DEVICE
	MOVSI C,0(D)		;UNIT
	LOAD D,FEIBC,(D)	;GET MAX BUFFER SIZE
	LSH D,-1		;HALVE IT
	CALL DTEQ		;DO IT
	 JFCL
	RET			;AND DONE
;ROUTINE TO SET EOF IN INPUT STREAM
;CALLED FROM DTESRV AT DTE PI LEVEL
;		B/UNIT
;		C/COUNT
;		D/BYTE POINTER

	RESCD
FESSTS::CAIGE C,2		;ENOUGH BYTES LEFT?
	RET			;NO ALL DONE
	CALL CHKFE
	 RET			;ABD UNIT
	ILDB A,D		;GET THE STATUS
	ILDB A,D		;GET LOW EIGHT BITS
	TXNN A,.DVFEF		;END OF FILE?
	JRST [	BUG(FEUSTS)
		JRST FESST1]
	SETONE FEEOF,(B)	;AND IS AT EOF
FESST1:	SUBI C,2		;TOOK 2 BYTES
	RET			;AND DONE

;ROUTINE TO COMPLETE LINE BUFFER EMPTY MESSAGE FROM DTE
;ACCEPTS:	B/UNIT

FEDON::	JUMPL B,DONALL		;IF NEG, HE WANTS TO ACK THEM ALL
	CALL CHKFE
	 RET			;BAD FE UNIT
	SETZRO FEFEI,(B)	;NO BYTES IN FE -11 NOW
	JN FEBLK,(B),[		;IS IT NOW BLOCKED?
		MOVE D,B	;YES
		SETZRO FEBLK,(D) ;CLEAR BLOCKED INDICATOR
		CALLRET FEINT1]	;AND GO START IT UP AGAIN
	RET			;AND DONE
;HERE TO ACK ALL UNITS

DONALL:	STKVAR <SAVEE>
	MOVSI C,-FEN		;TO DO THEM ALL
DONAL1:	MOVEM C,SAVEE
	MOVEI B,0(C)		;SET UP ARG
	LOAD C,FEDTE,(B)	;GET DTE ASSIGMENT
	CAMN C,MSTRDT		;IS THIS ON THE MASTER?
	CALL FEDON		;GO ACK IT
	MOVE C,SAVEE		;THE WORD
	AOBJN C,DONAL1		;GO DO IT
	RET			;AND DONE

;ROUTINE TO SET DEVICE ALLOCATION
;ACCEPTS:	A/DEVICE CODE
;		B/ALLOCATION
;		C/UNIT

FESLA::	CALL CHKFE
	 RET			;BAD UNIT
	LOAD D,FEIBC,(C)	;GET OUR MAX INT COUNT
	CAILE B,0(D)		;DOES IT FIT IN OUR BUFFER?
	MOVEI B,0(D)		;NO. USE OUR MAX SIZE THEN
	STOR B,FEFEM,(C)	;SET IT
	RET			;AND DONE

;ROUTINE TO CHECK AND VERIFY UNIT NUMBER
;WITH:		B/ UNIT NUMBER

CHKFE:	CAIL B,FEN		;VALID UNIT?
	RET			;NO
	JE FEVDT,(B),R		;MUST HAVE AN ASSIGNMENT
	RETSKP			;ALL IS WELL
;ROUTINE CALLED FROM DTE INTERRUPT LEVEL TO PASS STRING DATA TO
;AN FE DEVICE. ACCEPTS:
;	A/DTE#,,BYTE COUNT
;	B/UNIT #
;	C/DEVICE CODE
;	D/BYTE POINTER TO THE DATA

	RESCD			;MUST BE RESIDENT

FEHSD::	CALL CHKFE
	 RET			;BAD FE UNIT
	EXCH B,D		;GET UNIT IN D
	JE FEFRK,(D),R		;IF UNASSIGNED, FORGET IT
	PUSH P,A		;SAVE COUNT
	HLRZS A			;GET DTE
	LOAD C,FEDTE,(D)	;GET ASSIGNED DTE
	CAIE A,0(C)		;SAME?
	JRST [	BUG(FEBAD) ;NO
		JRST PA1]	;DONE
	LOAD C,FEIBC,(D)	;GET MAX ALLOCATION
	LOAD A,FEICT,(D)	;GET CURRENT COUNT
	SUBI C,0(A)		;GET CURRENT ROOM LEFT
	POP P,A
	MOVEI A,0(A)		;ISOLATE BYTE COUNT
	CAILE A,0(C)		;CAN PUT THEM IN?
	JRST [	BUG(FEBFOV,<<A,D>,<C,D>>) ;NO
		MOVE A,C	;ONLY DO THOSE THAT WILL FIT
		JRST .+1]
	OPSTRM <ADDM A,>,FEICT,(D) ;NEW COUNT OF BYTES IN FE
	OPSTRM <ADDM A,>,FEPRO,(D) ;INPUT RECEIVED SINCE LAST ACK
	ACVAR <W1,W2>		;GET SOME WORK REGISTERS
	LOAD W2,FEIEB,(D)	;GET INT COUNT
FEHS1:	ILDB W1,B		;GET NEXT BYTE
	IDPB W1,FEBPI(D)	;INTO THE BUFFER
	SOSG W2			;ONE LESS INT LEVEL BYTE
	CALL [	SAVET		;SAVE ALL TEMPS
		CALL SETINI	;GO INIT BUFFERS
		LOAD W2,FEIEB,(D) ;GET BACK THE COUNT
		RET]		;AND PROCEED
	SOJG A,FEHS1		;DO ALL BYTES
	STOR W2,FEIEB,(D)	;PUT BACK FINAL COUNT
	RET			;AND DONE
;**;[2607] Add one line at FEHS1: +9L	JGZ	3-APR-82
	ENDAV.			;[2607] END ACVAR

;ROUTINE TO DO SEQUENTIAL INPUT ON AN FE.
;ACCEPTS:	DEV/UNIT,,CODE
;		JFN/THE JFN FOR THE OPERATION

	SWAPCD			;IS SWAPABLE
FEBIN:	HLRZ D,DEV		;GET UNIT
	JE FEVDT,(D),[	TQO <ERRF>	;MAKE SURE ASSIGNMENT IS VALID
			RET]	;ITS NOT
	TQNE <EOFF>		;EOF ON DEVICE?
	RET			;YES. FORGET IT
FEBIN1:	CALL FESETI		;GO SET UP FOR INPUT
	SOSL FILCNT(JFN)	;HAVE A BYTE TO FETCH?
	JRST ABYTE		;YES. GO GET IT
	JN FEEOF,(D),[		;NO. HAVE AN EOF?
		TQO <EOFF>	;YES. SET EOF IN STATUS
		SETZRO FEEOF,(D) ;CLEAR LOCAL EOF
		SETZ A,		;RETURN A NULL
		RET]		;AND DONE
FEBIN2:	MOVSI A,0(D)		;NO. MUST WAIT THEN
	HRRI A,FEBWT
	TQO <BLKF,HLDF>		;REQUEST BLOCK AND HOLD
	RET			;AND RETURN

;HAVE SOME BYTES TO READ
ABYTE:	ILDB A,FILBYT(JFN)	;GET A BYTE
	RET			;AND DONE
;ROUTINES TO SET UP JFN FOR INPUT/OUTPUT.

FESETI:	TQOE <FILINP>		;NOW SET UP FOR INPUT?
	JRST [	SKIPLE FILCNT(JFN) ;YES. HAVE ANY INPUT?
		RET		;YES. ALL READY THEN
		CALL FEIUND	;NO. GO ACK AND RECOMPUTE COUNTS
		JRST FESETI]	;AND TRY AGAIN
	CALL FEOUND		;GO UNDO OUTPUT
	HLRZ D,DEV		;GET UNIT NUMBER
	LOAD B,FEICT,(D)	;GET COUNT OF BYTES
	LOAD C,FEIE1,(D)	;GET BYTES LEFT IN RING
	CAILE B,0(C)		;RING BIGGER THAN BUFFER?
	MOVEI B,0(C)		;NO. USE RING THEN
	MOVE C,FILOFN(JFN)	;GET CURRENT BYTE POINTER
FEXSET:	MOVEM C,FILBYT(JFN)	;STASH IT
	LOAD C,FEBSZ,(D)	;GET OPEN BYTE SIZE
	CAIN C,20		;WORD MODE?
	LSH B,-1		;YES. HALVE THE COUNT THEN
	MOVEM B,FILCNT(JFN)	;SET UP THE COUNT
	MOVEM B,FILMS1(JFN)	;SAVE INITIAL SIZE
	MOVEM B,FILLEN(JFN)	;FAKE THE LENGTH
	SETZM FILBYN(JFN)	;AND SAY WE ARE AT TOP OF FILE
	RET			;AND DONE

;ROUTINE TO UNDO INPUT

FEIUND:	HLRZ D,DEV		;GET UNIT NUMBER
	TQZN <FILINP>		;NOW DOING INPUT?
	RET			;NO. FALSE ALARM
	SKIPGE FILCNT(JFN)	;HAVE A GOOD COUNT?
	SETZM FILCNT(JFN)	;NO
	MOVE B,FILMS1(JFN)	;START OFF COUNT
	SUB B,FILCNT(JFN)	;COMPUTE USED BYTES
	JUMPE B,R		;IF NONE USED, ALL DONE
	LOAD C,FEBSZ,(D)	;GET BYTE SIZE
	CAIN C,20		;WORD MODE?
	LSH B,1			;YES. COMPUTE CORRECT COUNT
	NOSKED
	CHNOFF DLSCHN
	LOAD C,FEICT,(D)	;GET CURRENT IN COUNT
	SUBI C,0(B)		;NEW COUNT
	STOR C,FEICT,(D)	;STASH IT
	OPSTR <SUB C,>,FEPRO,(D) ;COMPUTE FEICT-FEPRO
	CHNON DLSCHN
	OKSKED
	SKIPGE C		;CAN WE SEND AN ACK NOW?
	CALL CLRALC		;YES. SO DO IT
	LOAD C,FEIE1,(D)	;GET RING COUNT
	SUBI C,0(B)		;NEW RING COUNT
	SETZM FILCNT(JFN)	;NO COUNT
	JUMPLE C,[CALLRET SETINB] ;IF ALL GONE, GET NEW COUNT
	STOR C,FEIE1,(D)	;UPDATE COUNT
	MOVE C,FILBYT(JFN)	;GET CURRENT BYTE POINTER
	MOVEM C,FILOFN(JFN)	;AND REMEMBER IT
	RET			;AND DONE
;ROUTINES TO SET UP AND MANAGE OUTPUT BUFFERS

;ENTRY TO SET UP FOR OUTPUT

FESETO:	TQOE <FILOUP>		;NOW DOING OUTPUT?
	JRST [	SKIPLE FILCNT(JFN) ;YES. ANY COUNT?
		RET		;YES ALL DONE
		CALL FEOUND	;NO. RECOMPUTE COUNTS
		JRST FESETO]	;AND PROCEED
	CALL FEIUND		;UNDO INPUT
	HLRZ D,DEV		;GET UNIT NUMBER
	LOAD B,FEIBC,(D)	;GET MAX COUNT OF OUTPUT BUFFER
	OPSTR <SUB B,>,FEOCT,(D) ;GET ROOM LEFT
	LOAD C,FEOE1,(D)	;GET ROOM LEFT IN RING
	CAILE B,0(C)
	MOVEI B,0(C)		;USE MINIMUM OF NUMBERS
	MOVE C,FILMS2(JFN)	;GET BYTE POINTER
	JRST FEXSET		;AND GO DO COMMON JFN SET UP

;ROUTINE TO UNDO OUTPUT

FEOUND:	TQZN <FILOUP>		;NOW DOING OUTPUT?
	RET			;NO. FALSE ALARM
	HLRZ D,DEV		;GET UNIT NUMBER
	SKIPGE FILCNT(JFN)	;HAVE A GOOD COUNT
	SETZM FILCNT(JFN)	;NO. MAKE IT GOOD
	MOVE B,FILMS1(JFN)	;GET STARTING COUNT
	SUB B,FILCNT(JFN)	;GET ENDING COUNT
	LOAD C,FEBSZ,(D)	;GET PREVAILING BYTE SIZE
	CAIN C,20		;WORD MODE?
	LSH B,1			;YES. COMPUTE BYTES
	NOSKED			;PREVENT INTERRUPTION
	CHNOFF DLSCHN
	OPSTRM <ADDM B,>,FEOCT,(D) ;NEW OUTPTU COUNT
	CHNON DLSCHN
	OKSKED
	LOAD C,FEOE1,(D)	;GET RING COUNT
	SUBI C,0(B)		;COMPUTE BYTES LEFT IN THE RING
	SETZM FILCNT(JFN)	;CLEAR COUNT
	JUMPLE C,[CALLRET SETOPB] ;SET UP NEW RING QUANTITIES
	STOR C,FEOE1,(D)	;NEW COUNT
	MOVE C,FILBYT(JFN)	;GET FINAL BYTE POINTER
	MOVEM C,FILMS2(JFN)	;AND REMEMBER IT
	RET			;AND DONE

;ROUTINE TO SEND -11 LINE ALLOCATION EMPTY MESSAGE
;ACCEPTS	D/UNIT
;PRESEVES ALL REGS

CLRALC:	SAVET			;SAVE REGISTERS
	SETZRO FEPRO,(D)	;CLEAR COUNT OF BYTES SINCE ACK
	LOAD A,FEDTE,(D)	;GET DTE
	MOVE B,[.DFLBE,,.FEFE]	;LINE BUFFER EMPTY
	SETZ C,
	CALL DTEQ		;SEND IT
	 JFCL
	RET			;RETURN WITH BYTE

;SCHEDULER WAIT TEST FOR INPUT

	RESCD
FEBWT::	JE FEVDT,(A),1(4)	;IF NOT VALID ASSIGNMENT, WAKE UP
	JN FEEOF,(A),1(4)	;IF EOF UP, HAVE DATA
	JE FEICT,(A),0(4)	;IF NOT AND NO DATA, REBLOCK
	JRST 1(4)		;MUST HAVE DATA

;ROUTINE TO CLOSE AN FE DEVICE.

	SWAPCD
FECLZ:	HLRZ D,DEV		;GET UNIT
	TXNE A,CZ%ABT		;WANT ABORT?
	JRST FECLZ1		;YES. GO IT NOW THEN
	JE FEVDT,(D),[	RETBAD (ASNDX3)] ;NO. MUST HAVE AN ASSIGNMENT THEN
	CALL FEOUND		;UNDO OUTPUT
	JE FEOCT,(D),FECLZ1	;ANY BYTES TO GO?
	CALLRET CLZIT2		;GO START FE AND BLOCK
FECLZ1:	LOCK FELOCK,<CALL LCKTST>
	SETZRO FEVDT,(D)	;NO DTEASSIGNED
	SETZRO <FEFRK,FEBLK,FEEOF>,(D) ;CLEAR FIELDS
	CALL CLRALC		;CLEAR FE'S BUFFERS
	LOAD A,FEIBF,(D)	;GET BUFFER ADDRESS
	CALL RELRES		;AND RELEASE IT
	UNLOCK FELOCK
	SETZM FILMS1(JFN)
	SETZM FILMS2(JFN)	;CLEAN UP JFN BLOCK
	RETSKP			;AND DONE
	TNXEND			;END OF CODE
	END			;END OF ASSEMBLY