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, 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, ; JSP T4,FEJCHK ; 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