Trailing-Edge
-
PDP-10 Archives
-
bb-jr93d-bb
-
7,6/ap016/fedser.x16
There are 2 other files named fedser.x16 in the archive. Click here to see a list.
TITLE FEDSER - FRONT END DEVICE SERVICE ROUTINES V031
SUBTTL E. SOCCI/EVS/TL 10 SEP 85
SEARCH F,S,DTEPRM
;NOTE:
; IF ANY CHANGES ARE MADE TO DTEPRM THAT FEDSER MUST HAVE, UPDATE
; THE FOLLOWING SYMBOL TO THE VERSION OF DTEPRM THAT MUST BE USED
PRMMIN==63
; 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.
;
.CPYRT<1976,1986>
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
;
;DATE LOAD EDIT #
;____ ____ ______
;
;
XP VFEDSR,031
SALL ;CLEAN MACRO EXPANSIONS
ENTRY FEDSER
FEDSER::
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS -- ASSIGN FED
;FUNCTION TO GET FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT # OR -1 TO ASSIGN ANY FREE FED
;
FEDGET::PUSHJ P,GETFEB ;GET FRONT END DEVICE BLOCK IN F FROM USER AREA
CAIA ;FAILED, SEE WHY
JRST FEDASG ;SUCCEEDED, ASSIGN THIS FED
JUMPL T1,CPOPJ## ;RETURN DTUDCE IF CPU DOESN'T EXIST
MOVE F,T1 ;SAVE CPU#,,DTE#
PUSHJ P,GETWDU## ;FAILED, SEE WHAT USER SAID
CAME T1,[-1] ;REQUEST "ANY FREE FED"?
PJRST DTUNXF## ;NO, FED DOES NOT EXIST
PUSHJ P,GETETD## ;FETCH DTE CONTROL BLOCK
PJRST DTUNXF## ;?HUH
LOAD. F,ED.FED,(F) ;GET FIRST FEB ADDRESS ON THIS FE
FEDASW: JUMPE F,DTUNXF## ;RETURN ERROR IF FIND NONE
LOAD. T1,FE.JCH,(F) ;LOOK FOR FED OWNER
JUMPN T1,[LOAD. F,FE.LNK,(F) ;ALREADY OWNED, GET NEXT FEB
JRST FEDASW] ;AND CHECK IT OUT
LOAD. T1,FE.UNI,(F) ;GET FED NUMBER OF THIS UNIT
PUSHJ P,STOTAC## ;RETURN FED NUMBER TO USER
FEDASG: LOAD. T1,FE.JCH,(F) ;GET JOB OWNING THE FRONT END DEVICE
JUMPN T1,DTUFDB## ;SOMEONE ALREADY HAS IT
PUSHJ P,FEDCLR ;CLEAR OUT THE BITS IN FEDSTS FIRST
PUSHJ P,FEDGTC ;ALLOCATE INPUT AND OUTPUT BUFFERS
POPJ P, ;OOPS, COULDN'T DO IT
PUSHJ P,FEDSPT ;INITIALIZE POINTERS TO INPUT BUFFER
MOVE T1,.CPJCH## ;GET JCH OF NEW OWNER
STOR. T1,FE.JCH,(F) ;MARK FED IN USE AND AVAIL FOR INPUT
JRST CPOPJ1## ;RETURN
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS -- RELEASE FED
;FUNCTION TO RETURN A FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
;
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
SUBTTL RESET UUO SERVICE
;HERE FROM RESET. CHECK TO SEE IF THE JOB OWNS A FRONT END DEVICE,
; AND GIVE IT UP IF SO.
IFE FTMP,< ;SINGLE PROCESSORS DON'T HAVE TO SAVE SO MUCH
FEDRST::PUSHJ P,SAVE2## ;SAVE P1,P2
> ;IFE FTMP
IFN FTMP,< ;MULTI-CPU SYSTEMS DO TRIPLE LOOPS
FEDRST::PUSHJ P,SAVE3## ;SAVE P1,P2,P3
MOVEI P3,M.CPU## ;FOR EACH CPU
FEDRS4: > ;IFN FTMP
MOVEI P2,3 ;SCAN 4 FRONT ENDS
FEDRS0: MOVEI P1,.FEMXU ;AND 4 FRONT END DEVICES
FEDRS1: MOVE F,P2 ;GET CPU#,,DTE# IN F FOR GETETD
IFN FTMP,<
HRLI F,-1(P3) ;P3 IS 1 HIGHER THAN CPU NO.
> ;IFN FTMP
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.JCH,(F) ;GET JOB OWNING IT
CAMN T1,.CPJCH## ;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
IFN FTMP,<
SOJG P3,FEDRS4 ;LOOP FOR NEXT CPU
> ;IFN FTMP
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: MOVSI T1,(FE.MIP) ;IS A MESSAGE IN PROGRESS AT INTERRUPT LEVEL
SYSPIF ;CONSISTENCY (NOT NESC. ON OWNING CPU)
TDNN T1,FEDSTS(F) ;?? (SO PI.OFF IS NOT SUFFICIENT)
JRST FEDCLN ;NO, CLEAN OUT THE FED
SYSPIN ;WAIT
MOVEI T1,EV.FEI ;YES, WAIT FOR MESSAGE TO FINISH COMING IN
PUSHJ P,ESLEEP## ;SO WE DON'T RELEASE THE CORE IT WILL WRITE
JRST FEDCLR ;SEE IF SAFE YET
FEDCLN: SETZ T1, ;CLEAR OUT JOB NUMBER
STOR. T1,FE.JCH,(F) ;IN FED BLOCK
SYSPIN ;INTERRUPT CODE WON'T TOUCH NOW.
MOVE T1,[FE.CLR] ;BITS TO CLEAR IN STATUS
ANDCAM T1,FEDSTS(F) ;CLEAR THEM
PJRST FEDRLC ;RELEASE BUFFER CORE AND RETURN
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS -- FED DEVICE INPUT
;FUNCTION TO DO INPUT FROM FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
; ADDR+2/#16-BIT BYTES TO READ,,BUFFER ADDRESS
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 THIS FRONT END DEVICE
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
MOVE T2,P3 ;GET 16 BIT BYTE COUNT
ASH T2,-1 ;TURN INTO 36 BIT WORD COUNT
TLZ T1,-1 ;C(T1) NOW HAS FIRST ADDRESS
ADDI T2,(T1) ;C(T2) NOW HAS LAST ADDRESS
PUSHJ P,TRNGE## ;MAKE SURE ITS ALL IN CORE
MOVSI T1,(FE.EOF) ;CLEAR END OF FILE FLAG
ANDCAM T1,FEDSTS(F)
SETZ P1, ;CLEAR COUNT OF BYTES GIVEN TO USER
FEDUI1: PUSHJ P,FEDUIB ;GET NEXT INPUT BYTE
POPJ P, ;ERROR, RETURN IT
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 ;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.
;READ NEXT (16-BIT) BYTE FROM -11
;RETURNS BYTE IN T2, MUST PRESERVE T1, P1, P3, & M
;RETURN: CPOPJ IF ERROR (ERROR ALREADY SET)
; CPOPJ1 WITH DATA
FEDUIB: SKIPG FEDTCT(F) ;IF NO DATA AVAILABLE
JRST FEDUB2 ;GET SOME MORE
ILDB T2,FEDTPT(F) ;GET A BYTE
SOS FEDTCT(F) ;THERE IS ONE LESS BYTE AVAILABLE NOW
JRST CPOPJ1## ;DONE
FEDUB2: PUSH P,T1 ;SAVE POSSIBLE BYTE IN LH(T1)
SYSPIF ;MUST TURN OFF PI SO WE DON'T GET INPUT
; DATA FOR FED WHILE UPDATING PUT POINTER
SKIPG FEDTCT(F) ;OF COURSE, THE DTE COULD HAVE DELIVERED DATA
JRST FEDUB3 ;SINCE WE LOOKED. JUMP IF IT DID NOT.
SYSPIN ;IT DID, MUST CONSUME THAT DATA FIRST
POP P,T1 ;RESTORE POSSIBLE BYTE IN LH
JRST FEDUIB ;GO TAKE DATA THAT SNUCK IN
FEDUB3: MOVSI T1,(FE.MIP) ;IS A MESSAGE ON ITS WAY IN
TDNN T1,FEDSTS(F) ;(AT INTERRUPT LEVEL)?
PUSHJ P,FEDSPT ;NO, MAKE THE NEXT ONE START AT TOP OF BUFFER
SYSPIN ;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
PUSHJ P,FEDSAK ;SINCE WE EXPECT TO BLOCK, SEND AN ACK TO GET
PJRST TPOPJ## ;MORE DATA FROM THE -11. (RETURN IF ERROR)
PUSHJ P,FEDWTI ;WAIT FOR THE BUFFER
JRST FEDUB4 ;OOPS, FATAL ERROR.
POP P,T1 ;RESTORE POSSIBLE LH BYTE
JRST FEDUIB ;GO FETCH THE NEW DATA
FEDUB4: POP P,T1 ;GET JUNK OFF STACK
JRST DTUFER## ;GO GIVE FATAL ERROR
;ROUTINE TO SEND AN ACK TO -20F
;-20F DOESN'T REALLY CARE HOW MANY ACKS IT GETS. IT WILL BLOCK FOR AN
;ACK WHEN SENDING DEVICE DATA (BUT NOT FUNCTION REPLYS). MORE COMPLICATED
;SCHEMES COULD BE MORE EFFICIENT, BUT SUFFER SYNCHRONIZATION PROBLEMS.
;
;CALLED BY FEDUIB, MUST PRESERVE SAME ACS
FEDSAK: 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.CPN,(F) ;CPU #
HRL P1,T1 ;CPU#,,DTE# IN P1
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
JRST CPOPJ1## ;DONE
;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. (11-RELOAD, DATA OVERRUN)
FEDWTI: MOVSI T1,(FE.FER) ;HAS AN ERROR OCCURED?
TDNE T1,FEDSTS(F)
POPJ P, ;YES, GIVE THE ERROR RETURN.
SKIPLE FEDTCT(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 AT INTERRUPT LEVEL 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.JCH,(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
HRLM T2,FEDFBI(F) ;SAVE MESSAGE LENGTH FOR POST ROUTINE
MOVE P4,FEDPPT(F) ;GET POINTER TO STORE DATA WITH
ADJBP T2,P4 ;COMPUTE POINTER TO NEXT PLACE TO STORE DATA
MOVEM T2,FEDPPT(F) ;UPDATE FOR NEXT MESSAGE
MOVSI S,FEDTDD ;THE POST PLACE
MOVSI T1,(FE.MIP) ;MESSAGE WILL NOW COME IN
IORM T1,FEDSTS(F) ;SO MAKE SURE BUFFER POINTERS AREN'T RESET
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 AT INTERRUPT LEVEL WHEN WE CRASH THE -11 WHILE WAITING FOR INDIRECT DONE
;DTESER ACS ARE SETUP.
FEDLMG: PUSHJ P,FDIGET ;GET FED BLOCK FROM C(P2), C(P3)
MOVSI T1,(FE.FER) ;FLAG FATAL ERROR STATUS
IORM T1,FEDSTS(F) ;SO USER WAKES UP NOW
PJRST FEDTD1 ;CLEAR MESSAGE IN PROGRESS
;HERE AT INTERRUPT LEVEL WHEN DATA TRANSFER TO THE TO-10 BUFFER IS COMPLETE.
;DTESER ACS ARE SETUP.
FEDTDD: PUSHJ P,FDIGET ;GET FED BLOCK FROM C(P2), C(P3)
HLRZ T1,FEDFBI(F) ;FETCH LENGTH OF THIS MESSAGE
ADDM T1,FEDTCT(F) ;MAKE DATA AVAILABLE TO USER
FEDTD1: HRRES FEDFBI(F) ;RESTORE BYTES AVAIL FOR NEXT MESSAGE
MOVSI T1,(FE.MIP) ;MESSAGE IS NO LONGER IN PROGRESS
ANDCAM T1,FEDSTS(F) ;SO ALLOW BUFFER SWITCHING
;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.JCH,(F) ;GET JOB NUMBER OWNING THIS
JUMPE T1,CPOPJ## ;DO NOTHING IF THERE IS NONE
PUSHJ P,CTXEWK## ;THERE IS ONE, WAKE THE JOB UP IF IT'S WAITING
JFCL ;IT DOESN'T MATTER IF CTX IS NOW GONE
POPJ P, ;JOB IS AS AWAKE AS IT'LL GET
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS -- FED DEVICE OUTPUT
;FUNCTION TO DO OUTPUT TO FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
; ADDR+2/#16-BIT BYTES TO WRITE,,BUFFER ADDRESS
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
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
MOVE T2,P3 ;GET 16 BIT COUNT
ASH T2,-1 ;MAKE 36 BIT COUNT
TLZ T1,-1 ;FIRST ADDRESS
ADDI T2,(T1) ;MAKE IT LAST ADDRESS
PUSHJ P,TRNGE## ;MAKE SURE ALL PAGES ARE THERE
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?
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 IT'S SLEEPING
JUMPN P3,FEDACK ;LOOP IF MORE ACKS ARE IN THIS MESSAGE
POPJ P, ;ALL DONE
SUBTTL DTESER ACK ALL SERVICE
;HERE ON ACK ALL - IF SOMEONE IS USING A FRONT END DEVICE, GIVE HIM
; AN ERROR, AS THE FE HAS JUST RELOADED.
FEDAAL: LOAD. F,ED.FED,(F) ;GET FIRST FRONT END DEVICE ADDRESS
FEDAA1: JUMPE F,CPOPJ## ;DONE
LOAD. T1,FE.JCH,(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 DTE. UUO FRONT END DEVICE FUNCTIONS -- GET FED DEVICE STATUS
;FUNCTION TO GET STATUS FROM FRONT END DEVICE
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
; 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 AT INTERRUPT LEVEL TO TAKE STATUS OF A FRONT END DEVICE FROM THE -11
; (DTESER HAS ALREADY RECEIVED IT)
;DTESER ACS ARE SETUP.
FEDTKS: PUSHJ P,FDIGET ;GET FED BLOCK IN F
ILDB T1,P4 ;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
SUBTTL DTE. UUO FRONT END DEVICE FUNCTIONS -- SET FED DEVICE STATUS
;FUNCTION TO SET FRONT END DEVICE STATUS
; ADDR/CPU#,,DTE#
; ADDR+1/FED UNIT #
; ADDR+2/NEW STATUS (16 BITS)
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
SUBTTL DTE. UUO INTERFACE - READ USER ARGUMENT BLOCK
;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
; IN ANY CASE WITH CPU#,,DTE# IN T1 (OR -1 IF INVALID)
GETFEB: PUSH P,[-1] ;ASSUME CPU OR DTE IS INVALID
PUSHJ P,[PUSHJ P,DTUGTF## ;CHECK AND GET CPU#,,DTE# IN T1
JRST CPOPJ1##] ;SKIP FOR SUCCESS
JRST TPOPJ## ;RETURN BAD CPU/DTE ERROR
MOVEM T1,(P) ;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
SUBTTL FEB SEARCH ROUTINES
;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 END
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/DEALLOCATION
;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 [PUSHJ P,FEDRC1 ;NO FREE CORE, RELEASE INPUT 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,<.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
FEDRC1: 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
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:
; ASSUMES JOB IS CURRENT (.CPJCH)
; MOVE F,<FED BLOCK ADDRESS>
; JSP T4,FEJCHK
; <RETURN IF JOB OWNS FRONT END DEVICE>
FEJCHK: LOAD. T1,FE.JCH,(F)
CAME T1,.CPJCH## ;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
SETZM FEDTCT(F) ;NO DATA AVAILABLE TO USER
POPJ P, ;RETURN
SUBTTL DTESER FUNCTION DISPATCH TABLE FOR THIS DRIVER
FEDLMG ;(-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)
EATMSG## ;(27)
EATMSG## ;(30)
EATMSG## ;(31)
EATMSG## ;(32)
EATMSG## ;(33)
EATMSG## ;(34)
END