Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
fedser.mac
There are 6 other files named fedser.mac in the archive. Click here to see a list.
TITLE FEDSER - FRONT END DEVICE SERVICE ROUTINES V20
SUBTTL E. SOCCI/EVS 01 FEB 77
SEARCH F,S,DTEPRM
;NOTE:
; IF ANY CHANGES ARE MADE TO DTEPRM THAT DTESER MUST HAVE, UPDATE
; THE FOLLOWING SYMBOL TO THE VERSION OF DTEPRM THAT MUST BE USED
PRMMIN==10
; THIS WAY, ASSEMBLING THIS MODULE WITH WRONG VERSION OF DTEPRM FOR SOME REASON
; (LIKE FORGETTING TO ASSEMBLE IT) WILL CAUSE ASSEMBLY TO TERMINATE
; THIS SCHEME DOES NOT CAUSE EXTRA EDITING, SINCE ONLY FILES
; WHICH NEED THE CHANGES NEED PRMMIN TO BE UPDATED. MODULES
; THAT DO NOT NEED A NEW VERSION OF DTEPRM NEED NOT DEMAND IT.
IFL VDTPRM-PRMMIN,<PRINTX ?PLEASE USE LATEST VERSION OF DTEPRM
PASS2
END>
$RELOC
$HIGH
;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 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VFEDSR,20
SALL ;CLEAN MACRO EXPANSIONS
ENTRY FEDSER
FEDSER::
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS
;FUNCTION TO GET FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
;
FEDGET::PUSHJ P,GETFEB ;GET FRONT END DEVICE BLOCK IN F FROM USER AREA
JRST DTUNXF## ;FRONT END DEVICE DOES NOT EXIST
CONO PI,PIOFF## ;DISALLOW INTERFERENCE
LOAD. T1,FE.JOB,(F) ;GET JOB OWNING THE FRONT END DEVICE
JUMPN T1,[CONO PI,PION## ;SOMEONE ALREADY HAS IT
JRST DTUFDB##] ;FRONT END DEVICE BUSY ERROR
PUSHJ P,FEDCLR ;CLEAR OUT THE BITS IN FEDSTS FIRST
STOR. J,FE.JOB,(F) ;STORE OUR JOB NUMBER
PUSHJ P,FEDGTC ;ALLOCATE INPUT AND OUTPUT BUFFERS
POPJ P, ;OOPS, COULDN'T DO IT
; WAIT FOR EVENTUAL RELEASE
JRST CPOPJ1## ;RETURN
;FUNCTION TO RETURN A FRONT END DEVICE
FEDGIV::PUSHJ P,GETFEB ;GET FRONT END DEVICE BLOCK IN F
JRST DTUNXF## ;DOESN'T EXIST
JSP T4,FEJCHK ;MAKE SURE WE OWN IT
PUSHJ P,FEDCLR ;CLEAR OUT THE FRONT END DEVICE
JRST CPOPJ1## ;AND RETURN
;HERE FROM RESET. CHECK TO SEE IF THE JOB OWNS A FRONT END DEVICE,
; AND GIVE IT UP IF SO.
FEDRST::PUSHJ P,SAVE2## ;SAVE P1,P2
MOVEI P2,3 ;SCAN 4 FRONT ENDS
FEDRS0: MOVEI P1,3 ;AND 4 FRONT END DEVICES
FEDRS1: MOVE F,P2 ;GET CPU#,,DTE# IN F FOR GETETD
PUSHJ P,GETETD## ;GET DTE CONTROL BLOCK ADDR FOR GETFE0
JRST FEDRS3 ;THIS FRONT END DOESN'T EXIST
MOVE T1,P1 ;GET UNIT NUMBER IN T1
PUSHJ P,GETFE0 ;GET THAT FRONT END BLOCK
JRST FEDRS2 ;DOESN'T EXIST
LOAD. T1,FE.JOB,(F) ;GET JOB OWNING IT
CAMN J,T1 ;SAME AS THIS JOB?
PUSHJ P,FEDCLR ;YES, RELEASE THIS FRONT END DEVICE
FEDRS2: SOJGE P1,FEDRS1 ;DO NEXT FRONT END DEVICE ON THIS FE
FEDRS3: SOJGE P2,FEDRS0 ;DO NEXT FRONT END
POPJ P, ;DONE
;ROUTINE TO DO ACTUAL RELEASE OF FRONT END DEVICE. CALLED FROM DTE.
; UUO, RESET UUO. CALL WITH FRONT END DEVICE BLOCK IN F.
FEDCLR: SETZ T1, ;CLEAR OUT JOB NUMBER
STOR. T1,FE.JOB,(F) ;IN FED BLOCK
MOVE T1,[FE.CLR] ;BITS TO CLEAR IN STATUS
ANDCAM T1,FEDSTS(F) ;CLEAR THEM
PJRST FEDRLC ;RELEASE BUFFER CORE AND RETURN
SUBTTL FRONT END DEVICE INPUT ROUTINES
FEDUIN::PUSHJ P,SAVE4##
PUSHJ P,GETFEB ;GET FRONT END BLOCK ADDRESS IN F
JRST DTUNXF## ;DOES NOT EXIST
JSP T4,FEJCHK ;MAKE SURE WE OWN THE FRONT END DEVICE IN QUESTION
PUSHJ P,GETWD1## ;GET BYTE COUNT,,ADDRESS
HRRI M,-1(T1) ;POINT TO WORD BEFORE THE ADDRESS
HLRZ P3,T1 ;GET COUNT IN P3
JUMPE P3,DTUBCE## ;IF ZERO, ERROR IN BYTE COUNT
IFN FTVM,<
MOVE T2,P3 ;GET 16 BIT BYTE COUNT
ASH T2,-1 ;TURN INTO 36 BIT WORD COUNT
ADDI T2,(T1) ;C(T2) NOW HAS LAST ADDRESS
PUSHJ P,TRNGE## ;MAKE SURE ITS ALL IN CORE
>;END IFN FTVM
MOVSI T1,(FE.EOF) ;CLEAR END OF FILE FLAG
ANDCAM T1,FEDSTS(F)
SETZ P1, ;CLEAR COUNT OF BYTES GIVEN TO USER
FEDUI1: MOVE T3,FEDPPT(F) ;GET PUT POINTER
CAMN T3,FEDTPT(F) ;SEE IF SAME AS TAKE
JRST FEDUI2 ;THEY ARE, NEED MORE DATA
ILDB T2,FEDTPT(F) ;GET A BYTE
TRNN P1,1 ;GOES IN LH?
JRST [HRLZ T1,T2 ;YES
JRST .+2]
HRR T1,T2 ;NO, PUT IN RH WITH THE OTHER BYTE
AOS P1 ;ONE MORE BYTE FOR USER
TRNN P1,1 ;BACK TO A LH BYTE?
PUSHJ P,PUTWD1## ;YES, GIVE 2 BYTES TO THE USER
CAMGE P1,P3 ;ITS NOT, HAVE WE GIVEN USER ALL HE ASKED FOR?
JRST FEDUI1 ;NO, KEEP GIVING
TRNE P1,1 ;YES, STILL KEEPING A LH BYTE IN T1?
PUSHJ P,PUTWD1## ;YES, STORE THE ODD BYTE
JRST CPOPJ1## ;RETURN TO USER WITH THE DATA IN HIS BUFFER.
FEDUI2: PUSH P,T1 ;SAVE POSSIBLE BYTE IN LH(T1)
CONO PI,PIOFF## ;MUST TURN OFF PI SO WE DON'T GET INPUT
; DATA FOR FED WHILE UPDATING PUT POINTER
PUSHJ P,FEDSPT ;SETUP THE POINTERS AND FREE COUNT
CONO PI,PION## ;TURN PI BACK ON.
; NOTE THAT FRONT END CAN NOW SEND DATA,
; BEFORE WE SEND ACK THUS WE SEND ACK
; WHEN LESS THAN WHOLE BUFFER IS AVAILABLE.
; TO GET AROUND THIS, BUFFER SIZE IS TWICE
; ALLOCATION
PUSH P,P1 ;SAVE COUNT OF BYTES GIVEN TO USER
PUSH P,P3 ;AND COUNT USER WANTS
LOAD. P1,FE.DTN,(F) ;GET DTE NUMBER OF THIS FE DEVICE
LOAD. T1,FE.UNI,(F) ;GET FRONT END UNIT NUMBER
LSH T1,^D35-^D15 ;POSITION LINE NUMBER IN 1ST 16 BIT BYTE
PUSH P,T1 ;SAVE IT SOMEWHERE
MOVEI P4,(P) ;GET ADDRESS OF DATA TO PUT INTO MSG IN P4
HRLI P4,(POINT 8,) ;MAKE INTO 8 BIT BYTE POINTER
MOVEI P3,2 ;2 8 BIT BYTES TO COPY FOR LONG DIRECT MSG
MOVE P2,[.EMFED,,.EMACK] ;ACK TO FRONT END DEVICE
MOVSI S,CPOPJ## ;POST ADDRESS,,DATA
PUSHJ P,DTEQUE## ;ASK FOR DATA
JRST [ADJSP P,-4 ;POP ALL THAT STUFF OFF STACK
JRST DTUCSM##] ;AND GIVE CAN'T SEND -11 MESSAGE ERROR
POP P,T1 ;TAKE TEMPORARY PART OF MSG OFF STACK
POP P,P3 ;AND USER'S SUPPLIED BYTE COUNT
POP P,P1 ;AND COUNT GIVEN TO USER SO FAR
PUSHJ P,FEDWTI ;WAIT FOR THE BUFFER
JRST FEDUI6 ;OOPS, FATAL ERROR.
POP P,T1 ;RESTORE POSSIBLE LH BYTE
JRST FEDUI1 ;REJOIN LOOP AS IF BUFFER WAS INFINITE
FEDUI6: POP P,T1 ;GET JUNK OFF STACK
JRST DTUFER## ;GO GIVE FATAL ERROR
;ROUTINE TO WAIT FOR FRONT END DEVICE INPUT BUFFER TO BECOME
; AVAILABLE. RETURNS CPOPJ1 IF IT IS, CPOPJ IF A FATAL ERROR
; HAS OCCURED IN THE FED.
FEDWTI: MOVSI T1,(FE.FER) ;HAS AN ERROR OCCURED?
TDNE T1,FEDSTS(F)
POPJ P, ;YES, GIVE THE ERROR RETURN.
MOVE T1,FEDTPT(F) ;GET TAKE POINTER
CAME T1,FEDPPT(F) ;NEED TO WAIT?
JRST CPOPJ1## ;NO, WE HAVE MORE DATA
MOVEI T1,EV.FEI ;FRONT END INPUT WAIT
PUSHJ P,ESLEEP## ;GO INTO EVENT WAIT, WAKE UP WHEN DATA IS READY
JRST FEDWTI ;MAKE SURE ALL IS OK
;HERE TO TAKE STRING DATA FOR A FRONT END DEVICE. P1-P4 SETUP BY
; DTESER TO BE THE STANDARD THINGS (SEE DTESER).
FEDTKD: PUSHJ P,FDIGET ;GET FED CONTROL BLOCK ADDRESS IN F
LOAD. T1,FE.JOB,(F) ;GET CONTROLLING JOB NUMBER
JUMPE T1,EATMSG## ;IF NONE, JUST EAT UP THE DATA
HRRZ T2,P3 ;GET 8 BIT BYTE COUNT IN T2
; IT HAD BETTER BE EVEN
TRNE T2,1 ;BYTE COUNT EVEN? (SHOULD BE 16 BIT BYTES)
JRST FEDTKE ;NO, GIVE ERROR
ASH T2,-1 ;CONVERT TO 16 BIT BYTE COUNT
CAMLE T2,FEDFBI(F) ;ENOUGH ROOM? (HAD BETTER BE OR ELSE
; FRONT END IS PROBABLY SENDING TOO MUCH)
JRST FEDTKE ;YES TO EITHER, GIVE FATAL ERROR TO UUO
MOVN T3,T2 ;GET COPY OF LENGTH OF MESSAGE
ADDM T3,FEDFBI(F) ;UPDATE COUNT OF FREE BYTES IN BUFFER
MOVSI S,FEDTDD ;THE POST PLACE
MOVE P4,FEDPPT(F) ;GET POINTER TO STORE DATA WITH
ADJBP T2,P4 ;PUT POINTER TO NEXT PLACE TO STORE DATA
MOVEM T2,FEDPPT(F)
POPJ P, ;RETURN TO DTESER, WHO WILL DO INDIRECT
; XFER.
;HERE IF THERE WAS A PROBLEM, GIVE UUO FATAL ERROR RETURN WHEN IT
; NEXT LOOKS.
FEDTKE: MOVSI T1,(FE.FER) ;YES TO EITHER, GIVE FATAL ERROR TO UUO
IORM T1,FEDSTS(F) ;SET BIT
PUSHJ P,FEDWKJ ;WAKE UP CORRECT JOB IF WAITING
PJRST EATMSG## ;EAT REMAINING DATA AND RETURN
;HERE WHEN DATA TRANSFER TO THE TO-10 BUFFER IS COMPLETE.
FEDTDD: PUSHJ P,FDIGET ;GET FED BLOCK FROM C(P2), C(P3)
;FALL INTO FEDWKJ
;HERE TO REMOVE A JOB FROM EVENT WAIT ASSOCIATED WITH A FRONT END DEVICE IF IT
; EXISTS. CALL WITH FRONT END DEVICE BLOCK ADDRESS IN F.
; ALWAYS RETURNS CPOPJ.
FEDWKJ: LOAD. T1,FE.JOB,(F) ;GET JOB NUMBER OWNING THIS
JUMPE T1,CPOPJ## ;DO NOTHING IF THERE IS NONE
PJRST EWAKE## ;THERE IS ONE, WAKE THE JOB UP IF ITS WAITING FOR SOMETHING
SUBTTL FRONT END DEVICE OUTPUT ROUTINES
;HERE FROM DTESER ON FRONT END DEVICE OUTPUT FUNCTION OF DTE. UUO
FEDUOU::PUSHJ P,SAVE4## ;WE WILL BE CALLING DTEQUE
PUSHJ P,GETFEB ;SETUP FED BLOCK ADDRESS IN F FROM USER ARGS
JRST DTUNXF## ;NON-GOOD
MOVE P1,T1 ;GETFEB RETURNS CPU#,,DTE# IN T1
; SO SAVE IN P1 FOR MAKING MESSAGE LATER
JSP T4,FEJCHK ;DOES THIS GUY HAVE THE RIGHT?
; IF NOT, GO AWAY AND GIVE HIM UUO ERROR RETURN
FEDUO1: PUSHJ P,GETWD1## ;GET BYTE COUNT,,ADDRESS
HLRZ P3,T1 ;GET 16 BIT BYTE COUNT IN P3
HRRI M,-1(T1) ;ADDRESS-1 IN RH(M) FOR GETWD1
JUMPE P3,DTUBCE## ;ZERO IS ERROR
IFN FTVM,<
MOVE T2,P3 ;GET 16 BIT COUNT
ASH T2,-1 ;MAKE 36 BIT COUNT
ADDI T2,(T1) ;MAKE IT LAST ADDRESS
PUSHJ P,TRNGE## ;MAKE SURE ALL PAGES ARE THERE
>;END IFN FTVM
FEDUO2: PUSHJ P,FEDWTO ;WAIT FOR OUTPUT BUFFER TO BE OURS
JRST DTUFER## ;SOMETHING HAPPENED . . .
MOVE P4,FEDOBF(F) ;ADDRESS TO PUT BYTES
HRLI P4,(POINT 16,) ;MAKE INTO A POINTER
MOVE P2,P3 ;GET COPY OF COUNT FOR LOOP
CAILE P2,.FEOSZ ;IS COUNT BIGGER THAN A BUFFER?
; (/2 BECAUSE BUFFER SIZE IS TWICE ALLOCATION)
MOVEI P2,.FEOSZ ;YES, JUST DO A BUFFER FULL NOW -
PUSH P,P2 ;SAVE COUNT OF DATA TO SEND OUT NOW
FEDUO3: PUSHJ P,GETWD1## ;GET 2 BYTES FROM USER
HLRZ T2,T1 ;GET FIRST BYTE
IDPB T2,P4 ;PUT INTO FED BUFFER
SOJLE P2,FEDU3A ;JUMP IF FINISHED
IDPB T1,P4 ;PUT SECOND ONE INTO FED OUTPUT BUFFER
SOJG P2,FEDUO3 ;LOOP UNTIL USER DATA EXHAUSTED
FEDU3A: EXCH P3,(P) ;SAVE TOTAL COUNT, GET COUNT FOR THIS OUTPUT
ASH P3,1 ;MAKE THIS # 8 BIT BYTES FOR DTESER
LOAD. T1,FE.UNI,(F) ;GET UNIT NUMBER OF THIS FRONT END DEVICE
HRL P3,T1 ;UNIT,,COUNT
MOVE P4,FEDOBF(F) ;GET ADDRESS OF BUFFER
HRLI P4,(POINT 16,) ;MAKE IT BYTE POINTER
MOVE P2,[.EMFED,,EM.16B+EM.IND+.EMSTR] ;DEVICE,,FN
;P1 WAS SETUP AT VERY BEGINNING
MOVSI S,CPOPJ## ;NO POST, WAIT FOR THE ACK THATS COMING
MOVSI T1,(FE.OAE) ;GIVE UP THE BUFFER, MAKING THE NEXT UUO BLOCK
IORM T1,FEDSTS(F) ;
PUSHJ P,DTEQUE## ;SEND THE DATA TO THE -11
JRST [POP P,P3 ;GET P3 BACK OFF STACK
JRST DTUCSM##] ;CAN'T SEND -11 MESSAGE
POP P,P3 ;RESTORE COUNT OF BYTES LEFT TO BE DONE
SUBI P3,.FEOSZ ;WE'VE JUST DONE LESS THAN OR EQUAL TO A
; WHOLE BUFFER - ANY BYTES LEFT TO DO?
JUMPG P3,FEDUO2 ;YES, GO DO THEM
JRST CPOPJ1## ;NO, RETURN TO USER RIGHT AWAY, LETTING HIM
; FILL ANOTHER BUFFER
;ROUTINE TO WAIT FOR OUTPUT BUFFER TO FREE UP
; SKIP RETURN WHEN OUTPUT BUFFER IS READY, NON-SKIP IF FATAL ERROR FLAG
; IS UP.
FEDWTO: MOVSI T1,(FE.FER) ;CHECK FOR FATAL ERROR
TDNE T1,FEDSTS(F) ;?
PJRST DTUFER## ;YEAH, GOODBYE.
MOVSI T1,(FE.OAE) ;CAN WE STUFF OUTPUT BUFFER WITH DATA?
TDNN T1,FEDSTS(F) ;?
JRST CPOPJ1## ;YES, GIVE SKIP RETURN
MOVEI T1,EV.FEO ;NO, GO INTO OUTPUT WAIT
PUSHJ P,ESLEEP## ;ZZZZ
JRST FEDWTO ;MAKE SURE EVERYTHING IS OK
;HERE WHEN THE 11 CAN ACCEPT MORE DATA FOR A FRONT END DEVICE
; (ACK)
FEDACK: ILDB T1,P4 ;GET LINE NUMBER
IBP P4 ;ADVANCE PAST BLANK BYTE
SUBI P3,2 ;REMEMBER WE'VE TAKEN 2 BYTES
PUSHJ P,FDIGT0 ;GET FED BLOCK ADDRESS IN F
MOVSI T1,(FE.OAE) ;MAKE OUTPUT BUFFER AVAILABLE TO UUO AGAIN
ANDCAM T1,FEDSTS(F)
PUSHJ P,FEDWKJ ;AND WAKE UP THE JOB IF ITS SLEEPING
JUMPN P3,FEDACK ;LOOP IF MORE ACKS ARE IN THIS MESSAGE
POPJ P, ;ALL DONE
;HERE ON ACK ALL - IF SOMEONE IS USING A FRONT END DEVICE, GIVE HIM
; AN ERROR
FEDAAL: LOAD. F,ED.FED,(F) ;GET FIRST FRONT END DEVICE ADDRESS
FEDAA1: JUMPE F,CPOPJ## ;DONE
LOAD. T1,FE.JOB,(F) ;GET JOB #, IF ANY
JUMPE T1,FEDAA2 ;NO JOB OWNS IT, GET NEXT FED ON THIS FE
MOVSI T1,(FE.FER) ;SOMEONE IS USING, GIVE HIM THE FINGER
IORM T1,FEDSTS(F) ;
PUSHJ P,FEDWKJ ;RUDE AWAKENING
FEDAA2: LOAD. F,FE.LNK,(F) ;GET NEXT ADDRESS
JRST FEDAA1 ;AND LOOP FOR ALL FRONT END DEVICES ON THIS DTE
SUBTTL FRONT END DEVICE STATUS HANDLING
;HERE ON DTE. UUO THAT OBTAINS STATUS
;ADDR/CPU#,,DTE#
;ADDR+1/FE DEVICE #
; USER GETS STATUS OF FRONT END DEVICE RETURNED IN HIS AC.
FEDUGS::PUSHJ P,GETFEB ;GET FED BLOCK FROM USER ARGS
JRST DTUNXF## ;SORRY
JSP T4,FEJCHK ;MAKE SURE HE OWNS THE FE DEVICE
MOVE T2,FEDSTS(F) ;GET STATUS WORD
SETZ T1, ;PREPARE RESULT
TLNE T2,(FE.EOF) ;EOF?
TRO T1,EM.EOF ;YES
TLNE T2,(FE.FER) ;FATAL ERROR?
TRO T1,EM.FER ;YES
JRST STOTC1## ;RETURN RESULT IN T1
;HERE FOR DTE. UUO FUNCTION TO SET FRONT END DEVICE STATUS
;ADDR/CPU#,,DTE#
;ADDR+1/FE DEVICE #
;ADDR+2/STATUS
FEDUSS::PUSHJ P,SAVE4## ;WE WILL BE CALLING DTEQUE
PUSHJ P,GETFEB ;GET FRONT END DEVICE BLOCK, AS USUAL
JRST DTUNXF##
JSP T4,FEJCHK ;MAKE SURE HE OWNS THE FE DEVICE
PUSHJ P,GETWD1## ;GET THE STATUS SETTING DESIRED
DPB T1,[POINT 16,FEDSOB(F),15] ;PUT INTO THE MESSAGE
MOVEI P4,FEDSOB(F) ;GET ADDRESS OF INDIRECT DATA
HRLI P4,(POINT 16,) ;MAKE INTO A BYTE POINTER
LOAD. T1,FE.UNI,(F) ;GET UNIT NUMBER OF FRONT END DEVICE
HRL P3,T1 ;SETUP UNIT # IN LH(P3)
HRRI P3,.FESMS*2 ;# 8 BIT BYTES IN THE INDIRECT MESSAGE
MOVE P2,[.EMFED,,EM.16B+EM.IND+.EMHDS] ;HERE IS DEVICE STATUS, 16 BIT STYLE
LOAD. P1,FE.DTN,(F) ;GET DTE #
LOAD. T1,FE.CPN,(F) ;CPU #
HRL P1,T1 ;CPU#,,DTE# IN P1
MOVSI S,CPOPJ## ;FORGET ABOUT POST
PUSHJ P,DTEQUE## ;SEND THE STATUS
JRST DTUCSM## ;CAN'T SEND -11 MESSAGE
JRST CPOPJ1## ;RETURN
;HERE TO TAKE STATUS OF A FRONT END DEVICE FROM THE -11
FEDTKS: PUSHJ P,FDIGET ;GET FED BLOCK IN F
MOVSI S,FEDTK1 ;CONTINUE FROM HERE WHEN DATA IS IN
HRRI P3,.FESMS*2 ;# 8 BIT BYTES WE WANT (THROW AWAY REST)
MOVEI P4,FEDSIB(F) ;ADDRESS TO TRANSFER STATUS TO
HRLI P4,(POINT 16,)
POPJ P, ;MAKE DTESER START UP THE FIRST FRAGMENT
;HERE WHEN FIRST PART OF STATUS IS IN. IGNORE THE REST OF THE DATA,
; UPDATE STATUS IN FED BLOCK.
FEDTK1: PUSHJ P,FDIGET ;SETUP FED BLOCK ADDR FROM C(P2), C(P3)
LDB T1,[POINT 16,FEDSIB(F),15] ;GET GOOD INFO
MOVSI T2,(FE.EOF) ;EOF BIT WILL BE SET OR CLEARED
TRNE T1,EM.EOF ;EOF BIT ON?
IORM T2,FEDSTS(F) ;YES, SET EOF IN THE BLOCK
MOVSI T2,(FE.FER) ;DO SAME FOR FATAL ERROR BIT
TRNE T1,EM.FER ;FATAL ERROR?
IORM T2,FEDSTS(F) ;YES, SET THE FATAL ERROR BIT IN STATUS
PJRST EATMSG## ;EAT UP REMAINING INDIRECT DATA
;ROUTINE TO GET FRONT END DEVICE BLOCK IN F FROM USER
; ARGUMENTS TO DTE. UUO
; USER ADDR+1/CPU#,,DTE#
; USER ADDR+2/FE DEVICE UNIT #
; SKIP RETURN IF OK, NON-SKIP IF SOMETHING WAS WRONG
; WITH CPU#,,DTE# IN T1
GETFEB: PUSHJ P,DTUGTF## ;CHECK AND GET CPU#,,DTE# IN T1
PUSH P,T1 ;SAVE CPU#,,DTE#
PUSHJ P,GETWD1## ;GET FE DEVICE UNIT #
CAILE T1,.FEMXU ;LEGAL UNIT NUMBER?
JRST TPOPJ## ;NO, ERROR RETURN
PUSHJ P,GETFE0 ;YES, GO GET THE BLOCK
JRST TPOPJ## ;DOESN'T EXIST
JRST TPOPJ1## ;RETURN WITH CPU#,,DTE# IN T1
;THIS ROUTINE IS FOR DRIVER INTERRUPT LEVEL TO GET THE FED ADDRESS IN F.
; CALL WITH CPU#,,DTE# IN P1, FED UNIT NUMBER IN LH(P3)
; ALWAYS RETURNS CPOPJ, IF FED DOESNT EXIST, STOPCD.
FDIGET: HLRZ T1,P3 ;GET FED UNIT
;ENTER HERE WITH UNIT # IN T1, CPU#,,DTE# IN P1
FDIGT0: MOVE F,P1 ;GET CPU#,,DTE# IN F
PUSH P,T1 ;SAVE FED UNIT NUMBER
PUSHJ P,GTETDS## ;GET DTE CONTROL BLOCK ADDR OR DIE
POP P,T1 ;RESTORE FED UNIT NUMBER
PUSHJ P,GETFE0 ;GET THE BLOCK OR
STOPCD .,STOP,NFB, ;++NO FRONT END DEVICE BLOCK
SALL
POPJ P, ;OK, RETURN
;HERE WITH FED UNIT NUMBER IN T1, DTE CONTROL BLOCK ADDR IN F
; RETURN CPOPJ1 WITH FED BLOCK ADDRESS IN F, OR CPOPJ IF ERROR.
GETFE0: LOAD. F,ED.FED,(F) ;GET FIRST FEB ADDRESS ON THIS FRONT EN
GETFE1: JUMPE F,CPOPJ## ;END OF CHAIN, GIVE ERROR RETURN
LOAD. T3,FE.UNI,(F) ;GET UNIT NUMBER OF THIS FE DEVICE
CAMN T1,T3 ;THIS THE ONE?
JRST CPOPJ1## ;YES, RETURN WITH FEB ADDRESS IN F
LOAD. F,FE.LNK,(F) ;NO, GET NEXT ADDRESS
JRST GETFE1 ;AND KEEP LOOKING
SUBTTL CORE ALLOCATION
;ROUTINE TO SETUP INPUT AND OUTPUT BUFFERS FOR FED. CALLED
; WHEN JOB GETS FED. CALL WITH C(F) = FED BLOCK. NON-SKIP
; WITH CORRECT ERROR CODE IN T1 IF NO CORE AVAILABLE, SKIP
; RETURN IF ALL OK.
FEDGTC: MOVEI T2,<.FEISZ+<^D36/^D16-1>>/<^D36/^D16>
;GET NUMBER OF WORDS IN FED BUFFER, ROUNDED UP
PUSHJ P,GETWDS## ;GET THAT MANY FOR INPUT BUFFER
PJRST DTUNFC## ;NO FREE CORE, GIVE ERROR RETURN
MOVEM T1,FEDIBF(F) ;OK, SAVE ADDRESS
MOVEI T2,<.FEOSZ+<^D36/^D16-1>>/<^D36/^D16>
;GET NUMBER OF WORDS IN FED BUFFER, ROUNDED UP
PUSHJ P,GETWDS## ;GET CORE FOR OUTPUT BUFFER NOW
PJRST DTUNFC## ;LOSE
MOVEM T1,FEDOBF(F) ;SAVE THAT TOO
JRST CPOPJ1## ;OK RETURN
;ROUTINE TO GIVE BACK FED BUFFER CORE. ALWAYS NON-SKIP RETURN.
; IGNORE IF NO BUFFERS TO GIVE BACK.
FEDRLC: MOVEI T1,<.FEISZ+<^D36/^D16-1>>/<^D36/^D16>
;GET NUMBER OF WORDS IN FED BUFFER, ROUNDED UP
SKIPE T2,FEDIBF(F) ;GET ADDRESS
PUSHJ P,GIVWDS## ;GIVE BACK THE INPUT BUFFER
SETZM FEDIBF(F) ;OK, NO MORE INPUT BUFFER
MOVEI T1,<.FEOSZ+<^D36/^D16-1>>/<^D36/^D16>
;GET NUMBER OF WORDS IN FED BUFFER, ROUNDED UP
SKIPE T2,FEDOBF(F) ;GET ADDRESS
PUSHJ P,GIVWDS## ;GET RID OF OUTPUT BUFFER
SETZM FEDOBF(F) ;SAY NO MORE BUFFER
POPJ P, ;RETURN
SUBTTL UTILITY ROUTINES
;ROUTINE TO CHECK TO SEE IF A JOB OWNS A FRONT END DEVICE, RETURN
; TO NEXT LEVEL IF NOT. CALL:
; MOVE J,<JOB>
; MOVE F,<FED BLOCK ADDRESS>
; JSP T4,FEJCHK
; <RETURN IF JOB OWNS FRONT END DEVICE>
FEJCHK: LOAD. T1,FE.JOB,(F)
CAME J,T1 ;DOES JOB OWN THIS FRONT END DEVICE?
JRST DTUDOF## ;NO, GIVE ERROR (AND POPJ BACK TO UPPER LEVEL)
JRST (T4) ;YES, RETURN TO CALLER
;ROUTINE TO SETUP PUT AND TAKE POINTERS, AND FREE BYTES IN
; FED INPUT BUFFER. CALLED AT FED INITIALIZATION TIME AFTER
; BUFFERS HAVE BEEN ALLOCATED, AND JUST BEFORE AN ACK IS SENT TO
; THE -11. CALL WITH FED BLOCK ADDRESS IN F
FEDSPT: MOVE T1,FEDIBF(F) ;SETUP INITIAL INPUT BUFFER POINTER
HRLI T1,(POINT 16,) ;MAKE IT A POINTER
MOVEM T1,FEDTPT(F) ;SETUP TAKE POINTER
MOVEM T1,FEDPPT(F) ;AND PUT POINTER
MOVEI T1,.FEISZ ;SETUP NUMBER OF BYTES IN BUFFER FREE
MOVEM T1,FEDFBI(F) ;FREE BYTES IN INPUT BUFFER
POPJ P, ;RETURN
SUBTTL INTERRUPT LEVEL ROUTINES
;PROTOCOL FUNCTION DISPATCH TABLE
CPOPJ## ;(-1)INTERNAL FUNCTION FOR TO-10 MESSAGE RUINED
FEDDSP::EATMSG## ;(0)
EATMSG## ;(1)
EATMSG## ;(2)
FEDTKD ;(3)HERE IS STRING DATA
EATMSG## ;(4)
EATMSG## ;(5)
EATMSG## ;(6)
FEDTKS ;(7)HERE IS DEVICE STATUS
EATMSG## ;(10)
EATMSG## ;(11)
EATMSG## ;(12)
EATMSG## ;(13)
EATMSG## ;(14)
EATMSG## ;(15)
EATMSG## ;(16)
FEDACK ;(17)ACK
EATMSG## ;(20)
EATMSG## ;(21)
EATMSG## ;(22)
EATMSG## ;(23)
EATMSG## ;(24)
FEDAAL ;(25)ACK ALL
EATMSG## ;(26)
END