1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-02-18 21:36:58 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_7/mon/fedser.mac
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

623 lines
22 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE FEDSER - FRONT END DEVICE SERVICE ROUTINES V035
SUBTTL E. SOCCI/EVS/TL 9-JUN-87
SEARCH F,S,DTEPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1976,1988>
XP VFEDSR,035
;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>
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
IFIW FEDLMG ;(-1) LOST TO-10 INDIRECT MESSAGE
FEDDSP::DTEFNC ;(??) GENERATE DUMMY TABLE ENTRIES
DTEFNC (STR,FEDTKD) ;(03) HERE IS STRING DATA
DTEFNC (HDS,FEDTKS) ;(07) HERE IS DEVICE STATUS
DTEFNC (ACK,FEDACK) ;(17) ACK
DTEFNC (AKA,FEDAAL) ;(25) ACK ALL
END