Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
dteser.mac
There are 13 other files named dteser.mac in the archive. Click here to see a list.
TITLE DTESER - DTE20 INTERFACE ROUTINES V5241
SUBTTL E.SOCCI/EVS/EJW 22 AUG 78
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==015
; 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 VDTESR,5241
SALL ;CLEAN MACRO EXPANSIONS
ENTRY DTESER
DTESER::
DEFINE DEAD10<PUSHJ P,DEDTEN> ;ONE DEAD10 FOR ALL DTESER, PUSHJ
; TO IT SO WE KNOW WHICH FLAVOR
; THEORY IS THAT UNLESS DUMP IS LOOKED
; AT, ANY FURTHER DETAIL IS UNNEEDED;
; THUS, I DON'T HAVE TO THINK UP
; 20 OR SO NAMES FOR ALL THE DEAD10S IN
; DTESER
PPCPI==SCNCHN##
SPCPI==SCNCHN## ;***TEMPORARY
;DTESER IS THE ONE AND ONLY MODULE IN THE MONITOR WHICH DEALS
; WITH DTE20S DIRECTLY. DTESER CONTAINS ROUTINES TO DRIVE BOTH
; PRIMARY (AS IT EXISTS IN THE RSX20 FRONT END) AND SECONDARY
; (AS IT EXISTS IN BOTH RSX20 AND KLDCP) PROTOCOLS. SEE
; KLCOM.MEM FOR A DEFINITION OF THESE PROTOCOLS.
;
;DTESER CONTAINS THE TO-11 QUEUE MECHANISM FOR THE PRIMARY PROTOCOL,
; THE DTE20 INTERRUPT SERVICE AND PROTOCOL MESSAGE HANDLER, AND
; PROTOCOL DEVICE SERVICE ROUTINES DEALING WITH OPERATION OF THE
; FRONT END (DATE/TIME, INITIAL MESSAGES, ETC). THE CODE THAT
; DRIVES THE VARIOUS FRONT END DEVICES (NETWORK TTYS, LOCAL TTYS,
; FRONT END DEVICE, CTY) RESIDES MOSTLY IN INDIVIDUAL DEVICE DRIVER
; MODULES SEPARATE FROM DTESER.
;
;THESE DEVICE DRIVERS MUST OBEY THE FOLLOWING CONVENTIONS.
;
;TO-10 MESSAGE RECEIPT
;
;DTESER CALLS THE DRIVER WITH THE FOLLOWING ACS SET UP:
; P1/10 CPU#,,DTE # (0-3)
; P2/DEVICE,,FUNCTION
; P3/LINE,,DATA OR COUNT (ALWAYS 8 BIT BYTES)
; P4/BYTE POINTER
; F/DTE CONTROL BLOCK ADDRESS (ETD)
;
; P3 AND P4 CONTAIN COUNT AND POINTER FOR LONG DIRECT AND INDIRECT
; TYPE MESSAGES. ACS P1-P4 AND S ARE USED THROUGHOUT DTESER
; TO PASS THE ABOVE INFORMATION BETWEEN DTESER AND THE DRIVERS.
; THE USE OF THE FIELDS WITHING THESE ACS IS ALSO CONSISTENT.
; SEE THE COMMENT AT DTEQUE FOR A DESCRIPTION OF THE CONVENTION
; FOR THE CONTENTS OF P1-P4 AND S.
;
;THE DRIVER MAY USE ACS P3,P4 AND F BUT MUST PRESERVE P1 AND P2.
; IF THE DRIVER WISHES TO RESTORE THE CONTENTS OF F,
; MOVE F,P1
; PUSHJ P,GTETDS##
; WILL RESET F
;
;IF THE RECEIVED FUNCTION IS INDIRECT, THE DRIVER IS REQUIRED TO
; RETURN TO DTESER WITH AN 8 BIT BYTE COUNT AND BYTE POINTER IN P3 AND P4,
; RESPECTIVELY. A NON-ZERO POST ADDRESS MUST BE SPECIFIED IN LH(S).
; THE DRIVER DOES NOT GET THE 16 BIT MODE BIT SET IN THE FUNCTION
; CODE ON INDIRECT MESSAGES, SINCE IT IS NOT KNOWN AT THAT POINT
; WHICH MODE THE 11 WILL SEND THE DATA. THE DRIVER IS
; THEREFORE RESPONSIBLE FOR KNOWING, BASED ON THE FUNCTION CODE
; AND/OR THE DEVICE, WHICH MODE THE DATA WILL BE COMING IN.
; IN GENERAL, BYTE STRINGS COME IN BYTE MODE AND WORD STRINGS
; COME IN WORD MODE.
;
;INDIRECT MESSAGES CAN BE RECEIVED PIECEMEAL BY THE DRIVERS.
; WHEN A FRAGMENT OF AN INDIRECT DATA PACKET IS RECEIVED BY DTESER,
; THE DRIVER'S POST ROUTINE IS CALLED. P3 CONTAINS THE NUMBER OF
; 8 BIT BYTES OF INDIRECT DATA AVAILABLE TO THE DRIVER
; AT THIS POINT, AND P4 CONTAINS THE ADDRESS OF THE LAST INDIRECT BYTE POINTER.
; EITHER THE DRIVER RETURNS
; C(P3)=0, WHICH INDICATES THAT THE DRIVER WANTS NO MORE DATA,
; OR THE DRIVER HAS SET UP LH(S) TO BE THE NEW POST ADDRESS,
; P3 THE NEW 8 BIT BYTE COUNT, AND P4 THE NEW BYTE POINTER.
; DTESER KEEPS TRACK OF HOW MANY BYTES ARE IN THE ENTIRE
; INDIRECT PACKET, AND ENSURES THAT THE DRIVER TAKES EXACTLY
; ALL OF THEM.
;TO-11
;
;THE DRIVER SETS UP S, P1-P4 WITH THE STANDARD INFORMATION.
; THE DRIVER MUST SAVE P1-P4 BEFORE USING THEM FOR THIS PURPOSE.
; LH(S) GETS THE POST ADDRESS, TO WHICH CONTROL IS PASSED
; UPON COMPLETION OF THE ENTIRE MESSAGE (AFTER DIRECT, OR ALL OF
; INDIRECT), AND RH(S) CAN BE USED BY THE DRIVER FOR STORED INFORMATION.
; IF THE DRIVER NEEDS TO REMEMBER MORE THAN 18 BITS WORTH OF INFORMATION,
; IT IS RECOMMENDED THAT A CHUNK OF CORE BE ALLOCATED AND THE ADDRESS
; OF THE CORE CAN BE REMEMBERED IN S.
; AT POST TIME, DTESER PUTS THE CPU AND DTE NUMBER IN P1,
; THE DEVICE CODE AND FUNCTION CODE IN P2, THE LINE NUMBER
; IN LH(P3) (THIS NUMBER SHOULD BE IGNORED
; FOR FUNCTIONS NOT CONTAINING A UNIQUE LINE NUMBER),
; AND IF THE TO-11 FUNCTION WAS INDIRECT, THE INDIRECT
; 8 BIT BYTE COUNT IN RH(P3), AND THE BYTE POINTER
; IN C(P4).
;
;ALL DRIVERS SHOULD BE PREPARED TO LOSE ACKS BECAUSE OF TEMPORARILY
; LEAVING PRIMARY PROTOCOL, AND TO RECOVER FROM THE LOST ACKS
; BY PROCESSING THE ACK ALL MESSAGE CORRECTLY. EACH DRIVER WILL
; GET A SIMULATED ACK ALL MESSAGE FOR EACH DEVICE IN TABLE ACKTAB,
; AND IS RESPONSIBLE FOR SCANNING ALL UNITS ON THE PROTOCOL DEVICE
; TO ACKNOWLEDGE ANY THAT ARE WAITING FOR ACKS. IT IS ALSO A GOOD
; IDEA TO CODE THE DRIVERS SUCH THAT A FREE ACK CAUSES NO DAMAGE.
;THE PURPOSE OF USING ACS P1-P4 IN A CONSISTENT MANNER WAS TO
; TRY TO KEEP ALL KNOWLEDGE OF PROTOCOL FORMATS IN DTESER. HOWEVER,
; THE DRIVERS MUST STILL KNOW THE EXACT FORMAT OF LONG DIRECT AND
; INDIRECT MESSAGES FOR BOTH TO-10 AND TO-11 DIRECTIONS, SINCE
; THEY PROVIDE/ARE PROVIDED WITH BYTE POINTERS TO PROTOCOL SPECIFIC
; DATA. THE ALTERNATIVE TO THIS IS TO HAVE DTESER CALL/BE CALLED
; BY THE DRIVERS FOR ALL DATA IN INDIRECT AND LONG DIRECT MESSAGES.
; THIS WOULD MAKE DTESER SLOWER AND PREVENT THE DRIVERS FROM TAKING
; ADVANTAGE OF THE INDIRECT CAPABILITY (FILLING USER BUFFERS, FOR EXAMPLE)
SUBTTL DTE20 INITIALIZATION ROUTINES
XLIST ;DON'T PRINT LITERALS
LIT
LIST
$LOW ;USED IN SYSINI
;ROUTINE TO INITIALIZE ALL DTES ON A CPU
; CALL WITH CPU NUMBER IN T1
DTEINI::SETZM KLEEOF ;CLEAR EOF FLAG FOR KL ERROR PROCESSOR
SETZM KLNSTF
PUSH P,P1 ;SAVE P1 AND P2
PUSH P,P2 ;FOR USE AS FLAGS
HRLZ P1,T1 ;GET 10 NUMBER IN LH(P1), START WITH DTE
; NUMBER EQUAL TO ZERO IN RH(P1)
SETZ P2, ;CLEAR MASTER 11 SEEN FLAG
DTEIN1: MOVE F,P1 ;SETUP F WITH 10#,,DTE#
PUSHJ P,GETETD ;GET DTE CONTROL BLOCK ADDRESS IN F
JRST DTEIN2 ;RETURN, NO MORE BLOCKS LEFT.
PUSHJ P,DTEINA ;INITIALIZE ONE DTE
MOVSI T1,(ED.DTX) ;IF THIS DTE EXISTS
TDNE T1,ETDSTS(F) ;THEN IT CANT BE MASTER
SKIPE P2 ;SEEN A MASTER YET?
AOJA P1,DTEIN1 ;YES, LOOP ON
;NOTE THAT RM BIT IS OFF FOR NON-EXISTANT DTES
XCT ETDCNI(F) ;CONI DTEN,T1
TRNE T1,RM ;RESTRICTED?
AOJA P1,DTEIN1 ;YES.
SETOM P2 ;NO, FLAG THAT THIS IS MASTER
MOVSI T1,(ED.DTM)
IORM T1,ETDSTS(F) ;FLAG THAT THIS IS MASTER IN ETD BLOCK
LOAD. T1,ED.CPN,(F) ;GET CPU NUMBER OF THIS DTE
MOVEM F,DTEMAS##(T1) ;REMEMBER MASTER DTE FOR THIS CPU
AOJA P1,DTEIN1 ;LOOP ON
DTEIN2: SKIPN P2 ;HAS A MASTER BEEN LOCATED AT ALL?
DEAD10 ;NO, BOO BOO
POP P,P2 ;YES, RESTORE P2 AND
POP P,P1 ;P1 AND
POPJ P, ;RETURN
;HERE TO INITIALIZE A DTE, DTE CONTROL BLOCK ADDRESS IN F
DTEINA: MOVEI T1,CLRDTE+PILDEN+SPCPI
;CLEAR DTE, TRY SETTING PI ASSIGNMENT
XCT ETDCNO(F) ;CONO DTEN,(T1)
XCT ETDCNI(F) ;CONI DTEN,T1
MOVE T2,T1 ;GET COPY OF CONI WORD
ANDI T2,7 ;JUST PI ASSIGNMENT
CAIE T2,SPCPI ;DID WE SET PI?
POPJ P, ;NO, DTE IS NON-EXISTANT
MOVEI T1,CLRDTE+PILDEN+0;RESET PI ASSIGNMENT TO ZERO
XCT ETDCNO(F) ;DO IT
MOVE T2,[ED.CST] ;GET STATUS CLEARING BITS
ANDCAM T2,ETDSTS(F) ;CLEAR OUT BITS TO BE CLEARED
MOVSI T2,(ED.DTX) ;YES. MARK AS EXISTANT
IORM T2,ETDSTS(F) ;DTE EXISTS. CLEAR OUT REST OF WORD
LOAD. T4,ED.DTN,(F) ;GET DTE NUMBER
ASH T4,3 ;*^D8
MOVE T3,ETDCDB(F) ;CDB ADDRESS IN T3
MOVE T3,.CPTOS##(T3) ;GET EPT ADDRESS
ADDI T4,DTEHBG(T3) ;GET TO BEGINNING OF EPT REGION FOR THIS DTE
MOVEI T1,1(T4) ;MAKE BLT POINTER
HRL T1,T4
SETZM (T4) ;CLEAR FIRST WORD
BLT T1,DTEHBE-DTEHBG(T4);CLEAR HARDWARE LOCS
MOVSI T1,(JSR) ;THE RIGHT INSTRUCTION
HRRI T1,ETDINT(F) ;GET INTERRUPT ADDRESS
MOVEM T1,DTEDII-DTEHBG(T4);SETUP INTERRUPT JSR
POPJ P, ;RETURN
SUBTTL SECONDARY PROTOCOL ROUTINES
SPCTRY==50000 ;NUMBER OF TIMES TO CHECK COMMAND COMPLETE
;ROUTINE TO TYPE 1 CHAR ON CTY (DATAO TTY,CHAR)
;CALL WITH:
; T3= CHARACTER TO TYPE
; PUSHJ P,SPCTYO
; RETURN HERE
;CALLERS RESPONSIBILITY TO WAIT FOR OUTPUT DONE.
;
SPCTYO::PUSH P,T1 ;SAVE T1
PUSHJ P,PEVEN8## ;GET GOOD PARITY, RID OF JUNK
MOVEI T1,DT.MTO(T3) ;STORE IN DTECMD
PUSHJ P,SPCMD ;DO THE COMMAND
T1POPJ: POP P,T1 ;RESTORE T1
POPJ P, ;AND RETURN
;ROUTINE TO SEND COMMAND OVER SECONDARY PROTOCOL
; CALL WITH COMMAND IN T1. RESPECTS ALL ACS BUT T1.
; SAVES/RESTORES STATE OF PI.PIA IN CASE OF ERRORS THAT TRAP THRU
; THE PAGE FAULT MECHANISM
SPCMD:: PUSHJ P,SVEPTD ;SAVE F,T4 AND GET DTE CTL
; ADDRESS, EPT ADDRESS OF THIS CPU
CAIN T1,DT.ESP ;ENTERING SECONDARY PROTOCOL IS OK IF
; NOT IN SECONDARY PROTOCOL
JRST SPCMD1 ;SO DON'T CHECK
PUSH P,T1 ;SAVE COMMAND
MOVSI T1,(ED.SPC) ;IS SECONDARY PROTOCOL RUNNING ON THIS DTE?
TDNN T1,ETDSTS(F) ;?
JRST T1POPJ ;DON'T USE TPOPJ IN CASE HISEG NOT SETUP
POP P,T1 ;RESTORE THE COMMAND
SPCMD1: SETZM DTEFLG(T4) ;CLEAR DONE FLAG
ADJSP P,1 ;RESERVE A PLACE ON THE STACK FOR THE
CONI PI,(P) ;PI STATUS
CONO PI,PIOFF## ;TURN OFF SO WE GET TO PUT COMMAND
; IN AND RING DOORBELL, ENSURING THAT 11
; WILL SEE SO A HIGHER LEVEL CAN CHECK DTEFLG
MOVEM T1,DTECMD(T4) ;PUT COMMAND IN THE RIGHT WORD
MOVEI T1,TO11DB ;RING DOORBELL
XCT ETDCNO(F)
POP P,T1 ;RESTORE FORMER PI STATUS
TRNE T1,PI.PIA ;WAS PI SYSTEM ON?
CONO PI,PION## ;YES, THEN TURN IT ON
MOVE T1,DTECMD(T4) ;GET COMMAND IN PROGRESS
ANDI T1,17B27 ;JUST COMMAND, NOT DATA
CAIN T1,DT.MTO ;OUTPUT?
POPJ P, ;YES, OUTPUT COMMAND DOESNT SET DTEFLG
MOVEI T1,SPCTRY ;TRY THIS MANY TIMES
SKIPN DTEFLG(T4) ;COMMAND DONE YET?
SOJG T1,.-1 ;NO, WAIT FOR A WHILE
SKIPG T1 ;OK?
PJSP T1,DTERLD ;NO, SECONDARY PROTOCOL DEAD
SETZM DTECMD(T4) ;INDICATE SECONDARY PROTOCOL FREE NOW
POPJ P, ;RETURN
SPCINT::PUSHJ P,SVEPTD ;SAVE F,T4 AND SETUP DTE CTL ADDRESS, EPT ADDRESS
MOVEI T1,CLRDTE ;CLEAR DOORBELL
XCT ETDCNO(F) ;UNDING
MOVSI T1,(ED.DTM) ;IS THIS THE MASTER DTE?
TDNN T1,ETDSTS(F) ;?
POPJ P, ;NO DISMISS INTERRUPT
MOVEI U,TCONLN## ;SETUP LINE # FOR CTY
SETZ T1, ;GET READY TO TEST AND CLEAR FLAG
EXCH T1,DTEMTI(T4) ;CLEAR OUT DTEMTI AND GET ITS OLD VALUE IN T1
JUMPE T1,SPCODI ;JUMP IF NOT INPUT READY
MOVE T3,DTEF11(T4) ;WAS INPUT READY, GET CHAR IN T3
PUSHJ P,RECINT## ;AND CALL SCNSER
PUSHJ P,GTEPD ;SETUP F AND T4 AGAIN
SETZ T1, ;CLEAR T1 AGAIN TO CHECK FOR OUTPUT DONE
MOVEI U,TCONLN## ;SETUP CTY LINE NUMBER AGAIN
SPCODI: EXCH T1,DTEMTD(T4) ;TEST AND CLEAR DTEMTD (T1 WAS ALREADY 0
; IF THERE WAS NO INPUT READY)
PJUMPN T1,XMTINT## ;IF DTEMTD NON-ZERO, WE HAVE OUTPUT DONE
POPJ P, ;OTHERWISE DISMISS INTERRUPT
;ROUTINE USED TO WAIT UNTIL INPUT IS PRESENT ON THE CTY WHEN
; THE CTY IS BEING RUN UNDER SECONDARY PROTOCOL.
; SKIP RETURN IF INPUT READY, CHARACTER RETURNED IN T3.
; NON-SKIP IF INPUT NOT AVAILABLE.
SPCGTI::PUSHJ P,SVEPTD ;SETUP F AND T4 WITH DTE AND EPT ADDRESSES
MOVSI T3,(ED.SPC) ;IS SECONDARY PROTOCOL RUNNING ON THIS DTE?
TDNE T3,ETDSTS(F) ;IF NOT, INPUT IS NEVER READY.
SKIPN DTEMTI(T4) ;INPUT READY?
POPJ P, ;NO, RETURN
MOVE T3,DTEF11(T4) ;YES, GET CHAR THEN
SETZM DTEMTI(T4) ;TELL 11 THAT IT CAN GIVE ANOTHER CHAR
PJRST CPOPJ1## ;GIVE SKIP RETURN WITH CHAR IN T3
;ROUTINE TO WAIT FOR SECONDARY PROTOCOL OUTPUT TO COMPLETE.
; USED IN ONCE ONLY OR WHENEVER INTERRUPT SYSTEM CANNOT BE RELIED
; UPON TO FLAG OUTPUT DONE.
SPCWTO::PUSHJ P,SVEPTD ;SAVE F,T4 AND SETUP DTE, EPT ADDRESSES
PUSH P,T1 ;SAVE T1
MOVSI T1,(ED.SPC) ;IS SECONDARY PROTOCOL RUNNING?
TDNN T1,ETDSTS(F) ;?
JRST [POP P,T1 ;DO THIS BY HAND IN CASE SYSINI NOT THERE
POPJ P,] ;OUTPUT NEVER COMPLETE
POP P,T1 ;RESTORE T1
SKIPN DTEMTD(T4) ;OUTPUT DONE YET?
POPJ P, ;NO, NON-SKIP RETURN
SETZM DTEMTD(T4) ;YES, CLEAR FLAG FOR NEXT TIME
PJRST CPOPJ1## ;AND GIVE OUTPUT DONE RETURN
XLIST ;DON'T PRINT LITERALS
LIT
LIST
$HIGH ;BACK IN HISEG AGAIN
SUBTTL DTE. UUO
;CALL TO DTE. UUO IS:
; MOVE AC,<FUNCTION,,ADDR>
; DTE. AC,
; <ERROR RETURN>
; <OK RETURN>
DTE.:: PUSHJ P,SAVE2##
HRR M,T1 ;ADDRESS OF PARAMETER BLOCK
HLRZ P1,T1 ;GET FUNCTION CODE
IFN FTPRV,<
MOVSI T1,JP.POK ;DISALLOW UNLESS PRIVILEGED
PUSHJ P,PRVBIT## ;IS HE?
>
IFE FTPRV,<
PUSHJ P,PRVJ## ;CHECK FOR [1,2] OR JACCT
>
JRST .+2 ;IS
JRST DTUNPE ;ERROR, NO PRIVILEGES
CAILE P1,MXDTFN ;OUT OF RANGE?
JRST DTUFNE ;YES, FUNCTION NUMBER ERROR
ROT P1,-1 ;/2, EVEN/ODD IN SIGN BIT
MOVE T1,DTUDSP(P1) ;GET ENTRY
SKIPL P1 ;SKIP IF ODD
MOVSS T1 ;EVEN, USE LH
PJRST (T1) ;DISPATCH
;DISPATCH TABLE FOR DTE. UUO
DTUDSP: XWD DTUCLR,DTUSTR ;(0,1)CLEAR A DTE, START A DTE
XWD DTUSTB,DTUSEB ;(2,3)SET TO-10 BYTE POINTER, SET TO-11 POINTER
XWD DTUGRW,DTUGMN ;(4,5)GET ROM WORD, GET MASTER DTE NUMBER
XWD DTUPRB,DTUGST ;(6,7)PRESS RELOAD BUTTON, GET STATUS
XWD DTUSRJ,FEDGET## ;(10,11)SET RELOAD JOB, GET FRONT END DEVICE
XWD FEDUIN##,FEDUOU## ;(12,13)FED INPUT, FED OUTPUT
XWD FEDUGS##,FEDUSS## ;(14,15)GET FED STATUS, SET FED STATUS
XWD FEDGIV##,DTURLC ;(16,17)RELEASE FED, RELEASE KLE CHUNKS
XWD DTURTM,DTUKLN ;(20,21)RESET KL ERROR TIMER, GET KLINIK LINE
MXDTFN==<.-DTUDSP>*2-1 ;MAXIMUM LEGAL FUNCTION
;ERROR CODES
INTERN DTUBCE,DTUDOF,DTUFDB,DTUNXF,DTUFER,DTUNFC ;FRONT END DEVICE ERROR CODES
INTERN DTUCSM
ERCODE DTUNPE,DTENP% ;(1)NO PRIVILEGES
ERCODE DTUFNE,DTEUF% ;(2)FUNCTION NUMBER ERROR
ERCODE DTUDCE,DTEDC% ;(3)CPU OR DTE NUMBER ERROR
ERCODE DTUARP,DTEAP% ;(4)ALREADY RUNNING PRIMARY PROTOCOL
ERCODE DTUPTE,DTEPT% ;(5)POWER FAIL DIDNT COME UP
ERCODE DTUDEE,DTEDE% ;(6)DOORBELL DIDNT CLEAR
ERCODE DTUTEE,DTTTE% ;(7)TO-10 ERROR DURING BOOT SEQ.
ERCODE DTUDDE,DTEDD% ;(10)NO REPONSE FROM 11 AFTER BOOT SEQ.
ERCODE DTUILJ,DTEIJ% ;(11)ILLEGAL JOB NUMBER
ERCODE DTUBCE,DTEIB% ;(12)ILLEGAL BYTE COUNT
ERCODE DTUDOF,DTENI% ;(13)FRONT END DEVICE NOT INITED
ERCODE DTUFDB,DTEFB% ;(14)FRONT END DEVICE IN USE BY ANOTHER JOB
ERCODE DTUNXF,DTENF% ;(15)NON-EXISTANT FRONT END DEVICE
ERCODE DTUFER,DTEFE% ;(16)FATAL ERROR ON FRONT END DEVICE
ERCODE DTUSTE,DTESE% ;(17)ERROR STARTING PRIMARY PROTOCOL
ERCODE DTUNFC,DTENC% ;(20)NO FREE CORE FOR FED BUFFERS
ERCODE DTUTME,DTETE% ;(21)KL ERROR DATA TIMER EXPIRED
ERCODE DTUCSM,DTECM% ;(22)FEDSER WAS TOLD IT COULDN'T SEND A MESSAGE TO THE -11
;DTE. FUNCTION (#0) TO CLEAR A DTE
; ADDR/CPU#,,DTE#
; CAUSES DTE TO LEAVE PRIMARY PROTOCOL. ALSO CLEARS ED.RLD.
DTUCLR: PUSHJ P,DTUGTF ;GET CORRECT DTE CONTROL BLOCK IN F
AOS (P) ;GIVE SKIP RETURN
PJRST DTECLR ;GO CLEAR OUT THE DTE
;DTE. FUNCTION (#1) TO START PROTOCOL ON A DTE
; ADDR/CPU#,,DTE#
DTUSTR: PUSHJ P,DTUGTF ;GET DTE CONTROL BLOCK ADDR IN F
MOVE T1,ETDSTS(F) ;GET DTE STATUS
TLNE T1,(ED.PPC) ;ALREADY RUNNING PRIMARY PROTOCOL?
JRST DTUARP ;YES, GIVE AN ERROR RETURN
TLNE T1,(ED.DTM) ;IF MASTER,
PUSHJ P,ENTSPC ;GO INTO SECONDARY PROTOCOL FIRST
PUSHJ P,STXPPC ;START UP PRIMARY PROTOCOL
JRST DTUSTE ;SOMETHING WENT WRONG, WE CAN'T START IT
MOVE T1,ETDSTS(F) ;GET DTE STATUS
TLNE T1,(ED.DTM) ;IF MASTER,
PUSHJ P,KPSSND ;SEND KLINIK PARAMETERS
JFCL ;NOT SERIOUS (OLD VERSION OF 20F)
JRST CPOPJ1## ;SIGNAL SUCCESSFUL START
;DTE. FUNCTION (#2) TO SET TO-10 BYTE POINTER IN EPT
; ADDR/CPU#,,DTE#
; ADDR+1/<BYTE POINTER>
DTUSTB: PUSHJ P,DTUGTF ;GET CORRECT DTE CONTROL BLOCK IN F
PUSHJ P,DTUSXB ;GET EPT OFFSET IN T4 FOR PROPER DTE
POPJ P, ;ERROR.
MOVEM T1,DTETBP(T4) ;STORE IN EPT PLACE
JRST CPOPJ1## ;UUO GETS SUCCESS RETURN
;DTE. FUNCTION (#3) TO SET TO-11 BYTE POINTER IN EPT
; ADDR/CPU#,,DTE#
; ADDR+1/<BYTE POINTER>
DTUSEB: PUSHJ P,DTUGTF ;GET CORRECT DTE CONTROL BLOCK IN F
PUSHJ P,DTUSXB ;GET EPT OFFSET
POPJ P, ;ERROR
MOVEM T1,DTEEBP(T4) ;STORE
JRST CPOPJ1## ;UUO GETS SUCCESS RETURN
DTUSXB: MOVSI T2,(ED.PPC) ;RUNNING SOMETHING?
TDNE T2,ETDSTS(F) ;?
PJRST DTUARP ;YES, CANNOT SET ANY POINTERS
PUSHJ P,GETWD1## ;GET BYTE POINTER IN T1
PUSHJ P,GTEPT ;GET EPT ADDR FOR DTE'S CPU
LOAD. T2,ED.DTN,(F) ;GET DTE NUMBER
ASH T2,3 ;*8
ADD T4,T2 ;GET OFFSET FROM FIRST DTE
JRST CPOPJ1## ;GIVE GOOD RETURN
;DTE. FUNCTION (#4) TO GET 11 RELOAD ROM WORD
; ADDR/CPU#,,DTE#
DTUGRW: PUSHJ P,DTUGTF ;GET DTE CONTROL BLOCK ADDR IN F
LOAD. T1,ED.211,(F) ;GET TO-11 SECTION FOR THIS DTE/11
LOAD. T1,EC.RLD,(T1) ;GET RELOAD WORD FOR THIS 11
PJRST STOTC1## ;PUT IN UUO AC AND GIVE GOOD RETURN
;DTE. FUNCTION (#5) TO GET NUMBER OF MASTER DTE ON A CPU
; ADDR/CPU#,,DTE#
DTUGMN: PUSHJ P,DTUGTF ;GET DTE CONTROL BLOCK ADDR IN F
HLRZS T1 ;GET JUST CPU NUMBER IN T1
MOVE F,DTEMAS(T1) ;GET MASTER DTE CONTROL BLOCK ADDRESS
LOAD. T1,ED.DTN,(F) ;GET DTE NUMBER OF MASTER
PJRST STOTC1## ;STORE AND RETURN
;DTE FUNCTION (#6) TO PUSH 11 RELOAD BUTTON
; ADDR/CPU#,,DTE#
BOFTIM==^D200 ;WAIT 200 MS, THEN TURN RELOAD BUTTON OFF
DBCTIM==^D2 ;WAIT 2 SECS FOR DOORBELL TO CLEAR
DONTIM==^D1 ;WAIT 1 MORE SEC BEFORE CLEARING TO-10 DONE AND TO-10 ERROR
MAGICN==^O1365 ;ROM HELLO BYTE COUNT
DTUPRB: PUSHJ P,DTUGTF ;GET DTE CONTROL BLOCK FROM USER ARG
MOVE T1,ETDSTS(F) ;GET STATUS
TLNE T1,(ED.PPC) ;RUNNING PRIMARY PROTOCOL?
JRST DTUARP ;YES, ERROR
PUSHJ P,SAVE3## ;SAVE SOME ACS FOR USE
MOVEI T1,SR11B ;SET 11 RELOAD BUTTON
XCT ETDCNO(F) ;
DTUPR2: RDTIME P1 ;GET TIME BASE TIME
DTUPR3: RDTIME T1 ;GET TIME NOW
DSUB T1,P1 ;GET TIME DIFFERENCE
ASHC T1,<TB.LTP-^D35>;ACCOUNT FOR UNUSED BITS
CAIGE T2,BOFTIM*^D1000;WAITED THE TIME?
JRST DTUPR3 ;NO, WAIT SOME MORE
MOVEI T1,CR11B ;YES, GET YOUR FINGER OFF THE BUTTON
XCT ETDCNO(F) ;NOW.
;HERE TO SAY HELLO TO THE ROM
SETZM @ETDTBP(F) ;MAKE SURE SETTING BYTE COUNT XFERS NOTHING
MOVEI T1,MAGICN ;GET MAGIC HELLO NUMBER
XCT ETDDTO(F) ;HELLO, ROM
MOVEI T1,TO11DB ;RING THE DOORBELL
XCT ETDCNO(F)
MOVEI P1,DBCTIM ;GET MS TO WAIT FOR DOORBELL FOR
IMUL P1,TICSEC## ;TICS
ADD P1,UPTIME## ;GET TIME TO WAIT FOR, LEAVE DOORBELL
; BIT IN T1
DTUPR4: MOVEI T1,TO11DB ;SETUP IN CASE SLEEP CALLED
XCT ETDCSO(F) ;DOORBELL CLEAR?
JRST DTUPR5 ;YES, WHAT WE WANTED
CAMG P1,UPTIME## ;TIME TO QUIT?
JRST DTUDEE ;YES, NO ELEVEN DOORBELL
MOVEI T1,1 ;WAIT FOR 1 SEC
PUSHJ P,DTESLP ;GO SLEEP FOR 1 SEC
JRST DTUPR4 ;WAIT STILL
DTUPR5: MOVEI T1,CLRDTE ;CLEAR ALL BITS
XCT ETDCNO(F)
JRST CPOPJ1## ;WE MADE IT.
;HERE TO SLEEP FOR N SECS.
DTESLP: PUSH P,F ;SAVE ETD ADDRESS
SETZ F, ;SO THAT RTEVM WON'T GET UPSET
PUSHJ P,SLEEP## ;GO SLEEP
JRST FPOPJ## ;RESTORE F AND RETURN
;DTE FUNCTION #7, GET STATUS WORD.
DTUGST: PUSHJ P,DTUGTF ;GET ETD BLOCK
MOVE T1,ETDSTS(F) ;GET STATUS WORD
JRST STOTC1## ;AND RETURN WITH IT.
;DTE FUNCTION #10, SET RELOAD JOB
DTUSRJ: PUSHJ P,GETWDU## ;GET JOB NUMBER
CAMN T1,[-1] ;SELF?
MOVE T1,J ;YES
PUSHJ P,LGLPRC## ;IS IT LEGAL?
JRST DTUILJ ;NO, ILLEGAL JOB NUMBER
MOVEM T1,DTRJOB ;SET JOB NUMBER
JRST CPOPJ1## ;AND GIVE GOOD RETURN.
;FUNCTION #17, RELEASE KLE CHUNKS
; USED BY DAEMON AFTER IT HAS WRITTEN THE KL ERROR DATA INTO ERROR.SYS
DTURLC: PUSHJ P,GETWDU## ;GET USER ARG (CPU#,,0)
HLRZS T1 ;JUST CPU #
JUMPN T1,DTUDCE ;BAD CPU IF NON-ZERO
AOS (P) ;GIVE GOOD RETURN
PJRST KLEREL ;GO GIVE BLOCKS BACK AND RETURN
;HERE WHEN DAEMON CALLS TO RESET THE TIMER FOR THE KL ERROR DATA
; CORE. GIVES ERROR RETURN IF THE CORE IS NO LONGER AVAILABLE.
DTURTM: PUSHJ P,GETWDU## ;GET CPU#,,<DONT CARE>
HLRZS T1 ;JUST CPU NUMBER
JUMPN T1,DTUDCE ;BAD NON-ZERO CPU SPEC
MOVEI T1,.KLETM+1 ;RESET TIMER
MOVEM T1,KLETIM ;FIRST, THEN
SKIPN KLEADR ;MAKE SURE THE CORE IS REALLY THERE
JRST [SETZM KLETIM
JRST DTUTME] ;SORRY, IT'S NOT AVAILABLE
JRST CPOPJ1## ;OK, RETURN
;FUNCTION #21, GET DTE LINE NUMBER
DTUKLN: PUSHJ P,DTUGTF ;GET ETD BLOCK
PJRST TTDDLN## ;GO GET LINE NUMBER
;HERE FOR THOSE FUNCTIONS THAT HAVE CPU#,,DTE# AS FIRST WORD OF BLOCK
; CALL IS:
; PUSHJ P,DTUGTF
; <ONLY RETURN>
; RETURNS WITH DTE CONTROL BLOCK ADDRESS IN F SET UP FROM USER C(M),
; C(T1) = CPU#,,DTE# FOR USE BY FUNCTION SUBROUTINES.
; POPS CALLER'S PC OFF STACK AND POPJS IF DTE OR CPU NUMBER IS BAD.
; (BETTER NOT PUSH SOMETHING ON STACK AND THEN CALL DTUGTF.)
; THIS ROUTINE IS MEANT TO BE USED ONLY BY THE DTE UUO FUNCTION SUBROUTINES.
DTUGTF::PUSHJ P,GETWDU## ;GET CPU#,,DTE#
TLNE T1,-1 ;NON-ZERO CPU SPECIFIED?
JRST DTUGT1 ;YES, BAD CPU NUMBER (TEMPORARY TILL SMP)
MOVE W,T1 ;SAVE CPU#,,DTE# FOR LATER
MOVE F,T1 ;GET ARG IN F WHERE IT BELONGS
PUSHJ P,GETETD ;GET DTE CONTROL BLOCK ADDRESS IF ALL IS OK
JRST DTUGT1 ;GO GIVE ERROR
MOVSI T1,(ED.DTX) ;SEE IF THIS DTE REALLY EXISTS
TDNN T1,ETDSTS(F) ;DOES IT?
JRST DTUGT1 ;NO, GIVE ERROR
LOAD. T1,ED.DTN,(F) ;GET REAL DTE NUMBER IN CASE -1 WAS GIVEN
HLL T1,W ;PUT CPU NUMBER IN LH(T1)
POPJ P, ;EXIT
DTUGT1: POP P,(P) ;POP CALLER'S PC OFF STACK
JRST DTUDCE ;AND RETURN TO UPPER LEVEL, ABORT FUNCTION
SUBTTL DTE20 TO-11 QUEUE ROUTINES
;ROUTINE TO PLACE AN ENTRY INTO A DTE'S TO-11 QUEUE.
; CALL:
; MOVE S,[XWD POST ADDRESS,DEVICE DRIVER DATA]
; MOVE P1,[XWD 10 CPU#,DTE #]
; MOVE P2,[XWD DEVICE,FUNCTION] (FUNCTION+EM.16B IF INDIRECT WORD MODE)
; MOVE P3,[XWD LINE,DATA] ;SOME FUNCTIONS DON'T USE DATA,
; INDIRECT FUNCTIONS AND LONG DIRECT,
; DATA IS COUNT
;IF P4 HAS BYTE POINTER
; MOVE P4,[BYTE POINTER TO DATA] ;IF LONG DIRECT OR INDIRECT
; PUSHJ P,DTEQUE ;
; <ERROR RETURN> ;COULD NOT SEND THE MESSAGE
; <OK RETURN>
;
; USES T1-T4
DTEQUE::PUSH P,U ;SAVE U FOR HEADER ADDRESS
PUSH P,F ;SAVE F
MOVE F,P1 ;PUT 10#,DTE# IN F FOR GTETDS
PUSHJ P,GTETDS ;SETUP F WITH DTE CONTROL BLOCK ADDRESS
MOVE T1,ETDSTS(F) ;GET STATUS WORD
TLNE T1,(ED.PPC) ;IS PRIMARY PROTOCOL DOWN OR
TLNE T1,(ED.RLD) ;IS THE RELOAD BIT SET?
PJRST FUPOPJ## ;YES, GIVE ERROR RETURN
PUSHJ P,GT2EFT ;GET TO-11 FUNCTION TYPE
DEAD10 ;NOT LEGAL FUNCTION
JRST @DTQTYP(T1) ;DISPATCH TO PROPER ROUTINE
; WHICH WILL CREATE PROPER HEADER
; FOR FUNCTION
DTQTYP: DTINDR
DT16BT
DTLINE
DTLNGD
DTLNDT
;FUNCTION DEPENDENT ROUTINES
;HERE IF DRIVER HAS RH(P3) 16 BIT BYTES TO BE COPIED INTO A MESSAGE
DTLNGD: HRRZ T2,P3 ;GET COUNT
PUSHJ P,DTMHED ;GET HEADER, SET UP COMMON STUFF
PJRST FUPOPJ## ;OUT OF CORE . . .
HRLI T4,(POINT 8,) ;EACH DATUM IS AN 8 BIT BYTE
MOVE T2,P4 ;GET COPY OF POINTER
HRRZ T3,P3 ;AND COUNT
DTLNG1: ILDB T1,T2 ;GET DATA
IDPB T1,T4 ;STORE IN MESSAGE
SOJG T3,DTLNG1 ;LOOP FOR ALL BYTES
JRST DTEQU4 ;DO QUEUE HEADER
;HERE IF THIS IS AN INDIRECT MESSAGE
DTINDR: MOVEI T2,2 ;SIZE OF DATA NOT INCLUDING HEADER
PUSHJ P,DTMHED ;DO COMMON STUFF
PJRST FUPOPJ## ;OUT OF CORE . . .
HRLI T4,(POINT 8,) ;MAKE T4 AN 8 BIT POINTER
HLRZ T1,P3 ;P3 HAS LINE,,COUNT
IDPB T1,T4 ;STORE LINE
STOR. T1,EQ.ELN,(U) ;ALSO PUT IN HEADER FOR POST TIME
IDPB P3,T4 ;COUNT
STOR. P3,EQ.CNT,(U) ;INDIRECT MESSAGES NEED TO HAVE
; COUNT AND POINTER REMEMBERED
STOR. P4,EQ.PTR,(U) ;NOW POINTER
MOVSI T1,(EQ.16B) ;IS DATA TO BE SENT IN 16 BIT MODE?
TRNE P2,EM.16B ;THATS INDICATED BY EM.16B IN FUNCTION ARG
IORM T1,ETQSTS(U) ;YES, SET THE BIT
JRST DTEQU4 ;GO FINISH QUEUE HEADER
;HERE FOR THOSE FUNCTIONS WHICH HAVE 16 BIT DATA
DT16BT: MOVEI T2,2 ;SIZE OF DATA NOT INCLUDING HEADER
PUSHJ P,DTMHED ;RETURN POINTER IN T4
PJRST FUPOPJ## ;OUT OF CORE . . .
IDPB P3,T4 ;STORE 16 BIT DATA IN MESSAGE
MOVE T1,P3 ;NOW GET WHAT MAY BE A LINE NUMBER
ANDI T1,377 ;JUST 8 BITS
STOR. T1,EQ.ELN,(U) ;IN CASE THIS IS A LINE NUMBER, POST
; ROUTINE MAY LIKE TO SEE IT.
JRST DTEQU4 ;FINISH UP
;HERE FOR THOSE FUNCTIONS WHICH HAVE LINE NUMBER ONLY (XON,XOFF,ETC)
DTLINE: MOVEI T2,2 ;SIZE OF DATA NOT INCLUDING HEADER
PUSHJ P,DTMHED ;GET 16 BIT BYTE POINTER IN T4
; AND HEADER ADDRESS IN U
PJRST FUPOPJ## ;OUT OF CORE . . .
HLRZ T1,P3 ;GET LINE NUMBER PROVIDED
HRLI T4,(POINT 8,) ;GET 8 BIT BYTE POINTER
IBP T4 ;SKIP OVER FIRST 8 BIT BYTE
IDPB T1,T4 ;LINE NUMBER IS SECOND 8 BIT BYTE
STOR. T1,EQ.ELN,(U) ;REMEMBER FOR POST TIME
JRST DTEQU4 ;GO FINISH UP
;HERE FOR THOSE FUNCTIONS WHICH HAVE LINE NUMBER AND DATA
DTLNDT: MOVEI T2,2 ;SIZE OF DATA NOT INCLUDING HEADER
PUSHJ P,DTMHED ;POINTER IN T4
PJRST FUPOPJ## ;OUT OF CORE . . .
HRLI T4,(POINT 8,) ;8 BIT POINTER INSTEAD
HLRZ T1,P3 ;GET LINE NUMBER
IDPB T1,T4 ;PUT IN MESSAGE
STOR. T1,EQ.ELN,(U) ;AND IN HEADER FOR POST REPORT OF LINE
IDPB P3,T4 ;AND DATA
JRST DTEQU4 ;GO FINISH UP
DTEQU4: MOVE T4,U ;GET QUEUE HEADER ADDRESS IN T4 FOR DTESND
HLRZ T1,S ;GET POST ADDRESS
STOR. T1,EQ.PST,(U) ;POST ADDRESS (OR ZERO IF NONE)
STOR. S,EQ.DRD,(U) ;AND STORE DRIVER'S DATA
CONO PI,PIOFF## ;TURN OFF PI AND TRY TO GET DTE
LOAD. T1,ED.2ES,(F) ;GET TO-11 STATE
CAIN T1,ED.EID ;IDLE?
JRST [MOVEI T1,ED.EDB ;YES, MAKE IT BUSY FOR US
STOR. T1,ED.2ES,(F) ;PUT IT IN STATE CODE FOR TO-11
CONO PI,PION## ;TURN PI BACK ON
PUSHJ P, DTESND
JRST DTEQU7] ;AND GO SEND THE MESSAGE, BYPASS QUEUE
;PI STILL OFF TO INTERLOCK THE QUEUE
LOAD. T3,ED.LST,(F) ;GET OLD TAIL OF QUEUE
JUMPE T3,DTEQU5 ;Q IS EMPTY, MAKE THIS BOTH FIRST AND LAST
STOR. T4,EQ.LNK,(T3) ;REPLACE 0 WITH NEW POINTER TO NEXT ENTRY IN Q
JRST DTEQU6 ;REMEMBER NEW GUY AS LAST
DTEQU5: STOR. T4,ED.QUE,(F) ;QUEUE WAS EMPTY, SO THIS IS
; FIRST AND LAST ENTRY
DTEQU6: STOR. T4,ED.LST,(F) ;NEW LAST ENTRY
DTEQU7: POP P,F ;RESTORE F
POP P,U ;RESTORE U
AOS (P) ;GIVE GOOD RETURN
PJRST ONPOPJ##
;HERE AFTER ALL TO-11 DONE(OR ERROR) PROCESSING IS DONE, ETD
; ETD ADDRESS IS IN F, DTE STILL MARKED AS BUSY.
DTENXT: CONO PI,PIOFF## ;IN CASE SOMEONE TRIES TO ADD OR
; DELETE AN ENTRY TO QUEUE
LOAD. T4,ED.QUE,(F) ;GET NEXT QUEUE ENTRY
JUMPE T4,DTENX1 ;NONE, FREE UP DTE
MOVEI T1,ED.EDB ;TO-11 STATE IS BUSY WITH DIRECT
STOR. T1,ED.2ES,(F) ; MESSAGE
LOAD. T1,EQ.LNK,(T4) ;GET NEXT ENTRY AND MAKE IT
STOR. T1,ED.QUE,(F) ;THE NEW HEAD OF THE QUEUE
SKIPN T1 ;IF QUEUE IS NOW EMPTY,
STOR. T1,ED.LST,(F) ;THERE IS NO TAIL
CONO PI,PION## ;OK TO MESS WITH QUEUE AGAIN
JRST DTESND ;GO SEND THIS MESSAGE
DTENX1: CONO PI,PION## ;OUT OF CRITICAL REGION
MOVEI T1,ED.EID ;MAKE TO-11 DTE SIDE IDLE
STOR. T1,ED.2ES,(F) ;PLACE IN TO-11 DTE STATE VAR
POPJ P, ;DISMISS INTERRUPT
;HERE WITH DTE CONTROL BLOCK ADDRESS IN F, QUEUE ENTRY HEADER IN T4
; DTE ALREADY PUT INTO TO-11 DIRECT BUSY STATE BY CALLER
DTESND: STOR. T4,ED.CUR,(F) ;REMEMBER THIS QUEUE ENTRY FOR POST
; PROCESSING
ADD T4,[POINT 8,SIZE(.EQLEN,36)];MAKE INTO BYTE POINTER FOR DTE
LOAD. T2,EM.CNT,(T4) ;GET MESSAGE BYTE COUNT
MOVEM T4,@ETDEBP(F) ;PUT INTO TO-11 POINTER EPT LOCATION
LOAD. T4,ED.211,(F) ;GET TO-11 SECTION OF TO-10 AREA
STOR. T2,EC.QSZ,(T4) ;SET QSIZE UP
MOVSI T2,(EC.16B) ;SEND IN 8 BIT MODE
ANDCAM T2,ETCSTS(T4)
LOAD. T3,EC.11C,(T4) ;GET TO11IC
ADDI T3,1 ;INCREMENT, LET IT OVERFLOW
STOR. T3,EC.11C,(T4) ;TRUNCATE, PUT IT BACK
MOVEI T1,TO11DB ;RING 11 DOORBELL
XCT ETDCNO(F) ;DONG
POPJ P, ;RETURN
;EACH FUNCTION DEPENDENT ROUTINE CALLS DTMHED WITH THE LENGTH OF
; DATA WITHOUT BASIC HEADER IN 8 BIT BYTES IN T2.
; RETURNS 16 BIT BYTE POINTER TO "FIRST WORD" IN MESSAGE (AFTER
; MESSAGE HEADER), AND QUEUE HEADER ADDRESS IN U
; SKIP RETURN IF ALL IS OK, NON-SKIP RETURN IF WE RAN OUT OF CORE
DTMHED: TRNE T2,1B35 ;COUNT MUST BE EVEN . . .
DEAD10 ;IS NOT, SOME CALLER MADE AN ERROR
ADDI T2,.EMHBL ;ADD ON NUMBER OF 8 BIT BYTES FOR BASIC HEADER
PUSH P,T2 ;SAVE BYTE COUNT FOR MESSAGE COUNT
ADDI T2,^D3 ;ROUND UP TO NEAREST WORD
ASH T2,-^D2 ;/^D4 = WORDS NEEDED
ADDI T2,SIZE(.EQLEN,36);INCLUDE SIZE OF QUEUE HEADER
PUSH P,T2 ;SAVE FOR GIVING CORE BACK
PUSHJ P,MESCOR ;GET C(T2) WORDS OF CONTIGUOUS CORE
JRST [POP P,T1
JRST T1POPJ] ;GIVE THE ERROR RETURN
MOVE U,T1 ;SAVE ADDRESS OF QUEUE HEADER
POP P,T2 ;RESTORE WORD COUNT
STOR. T2,EQ.SIZ,(U) ;PUT INTO QUEUE HEADER FOR DEALLOCATION
MOVEI T4,SIZE(.EQLEN,36)(U);SKIP QUEUE HEADER FOR NOW
HRLI T4,(POINT 16,) ;MAKE INTO BYTE POINTER
POP P,T2 ;RESTORE PROVIDED BYTE COUNT
IDPB T2,T4 ;SAVE MESSAGE BYTE COUNT
IDPB P2,T4 ;STORE FUNCTION CODE
HLRZ T1,P2 ;GET DEVICE CODE
IDPB T1,T4 ;STORE MESSAGE PROTOCOL DEVICE CODE
SETZ T1, ;ZERO THE
IDPB T1,T4 ;SPARE
MOVEI T4,SIZE(.EMHBL,36)+SIZE(.EQLEN,36)(U)
;T4 POINTS TO FIRST WORD
HRLI T4,(POINT 16,) ;ASSUME 16 BIT POINTER NEEDED -
; IF 8 BIT POINTER IS NEEDED, JUST
; HRLI T4,(POINT 8,)
JRST CPOPJ1## ;SUCCESS RETURN
SUBTTL DTE20 INTERRUPT SERVICE
;HERE WITH ETD (DTE CONTROL BLOCK) ADDRESS IN F
DTEINT::MOVSI T1,(ED.SPC) ;CHECK TO SEE IF SECONDARY PROTOCOL
TDNE T1,ETDSTS(F) ;IS RUNNING
PJRST SPCINT ;YES, DO SECONDARY PROTOCOL INTERRUPT
MOVSI T1,(ED.PPC) ;NOT SECONDARY, SEE IF PRIMARY IS RUNNING
TDNN T1,ETDSTS(F) ;IS IT?
JRST DTICLR ;NO, JUST CLEAR DTE AND DISMISS
LOAD. T4,ED.210,(F) ;YES, GET TO-10 SECTION OF 11'S AREA
MOVE T4,ETCSTS(T4) ;GET STATUS WORD FROM TO-10 SECTION
XCT ETDCNI(F) ;CONI DTEN,T1
TRNE T1,DEAD11 ;11 POWER FAIL?
JRST PWRF11 ;YES
TRNE T1,TO11DN ;TO-11 DONE?
JRST DTE2ED ;YES
TRNE T1,TO10DN ;TO-10 DONE? MUST CHECK BEFORE TO10DB
JRST DTE2XD ; SO WE FINISH A MESSAGE BEFORE STARTING A NEW ONE
TRNE T1,TO10DB ;TO-10 DOORBELL?
JRST DTERNG
TRNE T1,TO11ER
JRST DTE2EE
TRNE T1,TO10ER
JRST DTE2XE
DTICLR: MOVEI T1,CLRDTE ;CLEAR OUT DTE
XCT ETDCNO(F) ;ZAP
POPJ P, ;FREE INTERRUPT, DISMISS
PWRF11: MOVEI T1,PILDEN+0 ;CLEAR PI ASSIGNMENT, SINCE A DEAD
; -11 ON A DTE KEEPS SETTING THE BIT
XCT ETDCNO(F) ;ZAP
JRST DTICLR ;GO CLEAR OUT DTE AND RETURN
;HERE ON TO-10 DOORBELL, ETD ADDRESS IN F, STATUS IN T4
DTERNG: MOVEI T1,CL11PT ;CLEAR DOORBELL
XCT ETDCNO(F) ;CONO DTEN,(T1)
TLNE T4,(EC.LOD) ;11 WANTS TO BE RELOADED?
PJSP T1,DTERLD ;YES, DO IT
TRNE T4,EC.IND ;IS THIS THE INDIRECT PORTION OF A MESSAGE?
JRST DTEIND ;YES, GO HANDLE IT
LOAD. T3,ED.211,(F) ;TO-11 SECTION OF 10'S AREA
LOAD. T2,EC.10C,(T3) ;GET LAST TO11IC COUNT
LOAD. T1,EC.10C,-ETCSTS+T4;GET THIS TO10IC COUNT FROM T4
CAMN T1,T2 ;CHANGED?
POPJ P, ;NO, FREE DOORBELL. IGNORE.
AOS T2 ;INCREMENT OLD COUNT
ANDI T2,377 ; (MAY WRAP AROUND)
CAME T1,T2 ;IS NEW COUNT 1 GREATER THAN OLD?
PJSP T1,DTERLD ;NO, SOMETHING'S WRONG
MOVEI T2,EC.2IT ;OK, SET TO-IT BIT BEFORE ACTUALLY
; INCREMENTING QUEUE COUNT SO THAT
; THE 11 CAN CHECK FOR LOST TO-10
; DONE INTERRUPTS
IORM T2,ETCSTS(T3) ;SET THE BIT
STOR. T1,EC.10C,(T3) ;REMEMBER VALUE OF THIS TO10IC IN
; TO-11 SECTION OF 10 COMM AREA
;NO, MUST BE A DIRECT PACKET . . .
;HERE IF TO-10 TRANSFER IS DIRECT (MAY BE DIRECT PART OF INDIRECT MESSAGE)
LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE CODE
CAIE T1,ED.TID ;BETTER BE IDLE
DEAD10 ;DTE IN WRONG STATE
MOVEI T1,ED.TDB ;MAKE TO-10 BUSY WITH DIRECT XFER
STOR. T1,ED.2TS,(F) ;PUT INTO DTE CONTROL BLOCK
LOAD. T4,ED.210,(F) ;GET ADDRESS OF TO-10 SECTION
LOAD. T2,EC.QSZ,(T4) ;GET QSIZE THAT 11 SET UP
MOVEM T2,ETDPKC(F) ;SAVE FOR CHECKING AT TO-10 DONE TIME
PUSHJ P,T10GTC ;ALLOCATE TO-10 BUFFER, RETURN ADDRESS IN T1
DEAD10 ;NO FREE CORE, LOSE
HRLI T1,(POINT 8,) ;MAKE INTO BYTE POINTER
MOVEM T1,@ETDTBP(F) ;PUT INTO EPT
LOAD. T3,ED.BSZ,(F) ;GET LENGTH OF THIS DTE'S BUFFER
IMULI T3,^D36/^D8 ;IN EIGHT BIT BYTES
MOVE T1,ETDPKC(F) ;GET WHAT QSIZE SAID AGAIN
CAMLE T1,T3 ;MAKE SURE QSIZE IS NOT GREATER
; THAN THE BUFFER LENGTH
DEAD10 ;PACKET TO LARGE
MOVNS T1 ;GET NEGATIVE BYTE COUNT
ANDI T1,TO10BC ;JUST THE COUNT BITS FOR DATAO
TRO T1,TO10IB ;TAKING THE WHOLE PACKET AT ONCE,
; SO INTERRUPT 11 WHEN XFER IS DONE
XCT ETDDTO(F) ;DATAO DTEN,T1
POPJ P, ;DONE
;HERE IF TO-10 PACKET IS THE INDIRECT PART OF AN INDIRECT MESSAGE
DTEIND: LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE
CAIE T1,ED.TWD ;WE SHOULD BE EXPECTING THIS DOORBELL
DEAD10 ;NO, DTE IS IN WRONG STATE
MOVEI T1,ED.TIB ;NOW WE'RE WAITING FOR TO-10 DONE
STOR. T1,ED.2TS,(F) ;FOR AN INDIRECT TRANSFER.
LOAD. T2,ED.211,(F) ;GET TO-11 SECTION ADDRESS
MOVEI T1,EC.2IT ;SET TO-10 XFER IN PROGRESS BIT FOR 11
IORM T1,ETCSTS(T2) ;POLLER.
LOAD. T4,ED.210,(F) ;TO-10 SECTION ADDRESS
LOAD. T2,EC.QSZ,(T4) ;NUMBER OF BYTES IN INDIRECT MESSAGE
LOAD. T1,ED.IBL,(F) ;GET COUNT SENT IN DIRECT PART OF THIS MESS^GE
CAME T1,T2 ;MAKE SURE IT MATCHES QSIZE
PJSP T1,DTERLD ;IT DOESNT
;IT DOES, LEAVE BYTES LEFT AT FULL COUNT
LOAD. T1,ED.ICT,(F) ;GET NUMBER OF BYTES DRIVER WANTS
PJRST DTEINX ;GO START FIRST INDIRECT FRAGMENT
;C(T1)=# 8 BIT BYTES WANTED,
; C(T2)=# BYTES LEFT (FULL COUNT NOW)
; FOR DTEINX
;HERE ON TO-10 DONE INTERRUPT
DTE2XD: MOVEI T1,CLTO10 ;GET READY TO CLEAR TO-10 DONE
XCT ETDCNO(F) ;CONO DTEN,(T1)
PUSHJ P,SAVE4## ;SAVE P1-P4 FOR ARG PASSING TO DRIVER
LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE
CAIN T1,ED.TDB ;EXPECTING TO-10 DONE FOR DIRECT XFER?
JRST DTE2X0 ;YES, GO PROCESS IT
CAIN T1,ED.TIB ;NO, MAYBE INDIRECT?
JRST DTEXDI ;YES, GO HANDLE THAT
DEAD10 ;DTE WAS IN WRONG STATE
DTE2X0: LOAD. T4,ED.211,(F) ;GET TO-11 SECTION
MOVEI T1,EC.2IT ;CLEAR TO-10 XFER IN PROGRESS BIT
ANDCAM T1,ETCSTS(T4) ;FOR THE 11 POLLER
LOAD. T4,ED.BUF,(F) ;ADDRESS OF THE TO-10 DATA
HRLI T4,(POINT 8,) ;MAKE INTO BYTE POINTER
STOR. T4,ED.MSP,(F) ;THIS IS POINTER FOR CURRENT MESSAGE
STOR. T4,ED.NMP,(F) ;THIS LOC CONTAINS POINTER FOR NEXT MESSAGE IN PACKET
;THIS IS LOOP FOR EACH MESSAGE. T4 HAS BYTE POINTER TO NEXT MESSAGE
DTE2X1: LOAD. P1,ED.DTN,(F) ;SET RH(P1) TO BE DTE NUMBER
PUSHJ P,GX2BYT ;BYTES IN HEADER COME SWAPPED, SO
; CALL GX2BYT FOR COUNT
TRNN T1,1B35 ;IS COUNT ODD
CAMLE T1,ETDPKC(F) ;OR IS 11 LIEING ABOUT SIZE OF THIS MESSAGE?
PJSP T1,DTERLD ;COUNT NOT EVEN OR BAD SIZE
; (INDIVIDUAL MESSAGE SIZE CANNOT
; EXCEED SIZE OF ENTIRE PACKET)
MOVN T2,T1 ;GET MINUS COUNT IN T2
ADDB T2,ETDPKC(F) ;PKC HAS COUNT LEFT
MOVE T2,T1 ;GET COUNT IN T2 AGAIN
ADJBP T2,ETDNMP(F) ;T4 HAS CURRENT MESSAGE POINTER,
; T2 GETS NEXT MESSAGE POINTER
STOR. T2,ED.NMP,(F) ;SAVE
SUBI T1,.EMHBL ;ACCOUNT FOR LENGTH OF HEADER UP TO
; BUT NOT INCLUDING FIRST WORD
SKIPGE T1 ;COUNT TOO SMALL??
PJSP T1,DTERLD ;YES
MOVE U,T1 ;FROM NOW ON, U HAS COUNT FOR CURRENT MESSAGE
PUSHJ P,GX2BYT ;16 BIT FUNCTION BYTE
HRRZ P2,T1 ;RH(P2) ALWAYS HAS FUNCTION CODE
PUSHJ P,GX2BYT ;16 BIT DEVICE CODE
HRL P2,T1 ;LH(P2) ALWAYS GETS DEVICE CODE
PUSHJ P,GX2BYT ;EAT UP SPARE. NOW WE'VE TAKEN .EMHBL BYTES
PUSH P,T4 ;SAVE BYTE POINTER
PUSHJ P,GT2XFT ;GET TO-10 FUNCTION TYPE IN T1
PJSP T1,[POP P,T4 ;ILLEGAL FUNCTION
PJRST DTERLD] ;FIX STACK AND RELOAD
POP P,T4 ;RESTORE BYTE POINTER
DTE2X2: PUSHJ P,@D2XTAB(T1) ;CALL FUNCTION DEPENDENT ROUTINE
; TO SETUP P3,P4
PUSH P,U ;SAVE U AROUND CALL TO FUNCTION ROUTINE
PUSH P,F ;SAVE ETD ADDRESS
PUSHJ P,DODSP ;DO A PJRST TO CORRECT DRIVER ROUTINE
POP P,F ;RESTORE ETD
POP P,U ;GET U BACK AGAIN
TRNE P2,EM.IND ;WAS THE MESSAGE JUST RECEIVED THE
; DIRECT PART OF AN INDIRECT MESSAGE?
JRST DTE2X3 ;YES, THIS IS DIRECT PART OF INDIRECT
SKIPG ETDPKC(F) ;ANYTHING LEFT?
JRST DTETID ;NO, MAKE DTE IDLE NOW
LOAD. T4,ED.NMP,(F) ;NO, GET OLD NEXT MESSAGE POINTER
JRST DTE2X1 ;GO DO NEXT MESSAGE
DTE2X3: HLRZ T1,S ;ITS EITHER THIS OR DONT USE STOR. IN NEXT INSTRUCTION
STOR. T1,ED.IPS,(F) ;SAVE INITIAL ADDRESS TO TRANSFER
; TO AFTER FIRST FRAGMENT OF INDIRECT
; MESSAGE COMES
MOVEI T1,ED.TWD ;WAITING FOR TO-10 DOORBELL TO SIGNAL START OF
STOR. T1,ED.2TS,(F) ;TO-10 INDIRECT PACKET XFER
STOR. P3,ED.ICT,(F) ;SAVE INITIAL BYTE COUNT (8 BIT BYTES)
MOVEM P4,@ETDTBP(F) ;PUT BYTE POINTER IN EPT NOW
STOR. P4,ED.MSP,(F) ;REMEMBER ORIGINAL POINTER TO PASS
; BACK TO DRIVER ON TO-10 DONE FOR
; INDIRECT PACKET
SKIPE ETDPKC(F) ;ANY MORE MESSAGES LEFT IN PACKET?
PJSP T1,DTERLD ;NO, 11 MUST HAVE LIED
POPJ P, ;RETURN, AWAITING DOORBELL
DTEXDI: LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE
CAIE T1,ED.TIB ;WERE WE EXPECTING TO-10 DONE FOR INDIRECT?
DEAD10 ;NO, DTE WAS IN WRONG STATE
;YES, LEAVE IN THAT STATE UNTIL ALL
; INDIRECT FRAGMENTS HAVE BEEN
; RECEIVED BY THE 10
LOAD. T2,ED.IPS,(F) ;GET TO-10 INDIRECT POST ADDRESS
SKIPN T2 ;BETTER BE ONE
DEAD10 ;NOT
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER IN P1
LOAD. P2,ED.XFN,(F) ;TO-10 FUNCTION
LOAD. T1,ED.XDV,(F) ;DEVICE THAT WAS SENT
HRL P2,T1 ;GOES IN LH(P2)
LOAD. P3,ED.IBL,(F) ;GET NUMBER OF BYTES NOW AVAILABLE TO
; DRIVER
LOAD. T1,ED.XLN,(F) ;TO-10 LINE
HRL P3,T1 ;LINE,,8 BIT BYTES LEFT IN P3
LOAD. P4,ED.MSP,(F) ;GET ORIGINAL POINTER FOR CORE DEALLOCATION
PUSH P,F ;SAVE ETD ADDRESS
PUSHJ P,(T2) ;CALL DRIVER TO SAY INDIRECT FRAGMENT DONE
POP P,F ;RESTORE ETD ADDRESS
TRNN P3,-1 ;IF DESIRED NEW COUNT = 0,
JRST DTEXD1 ; MAKE SURE DRIVER ISNT EXPECTING ANY MORE
HLRZ T1,S ;GET POST ADDRESS FROM STANDARD AC
STOR. T1,ED.IPS,(F) ;NEW TO-10 INDIRECT POST ADDRESS
LOAD. T2,ED.IBL,(F) ;GET NUMBER OF BYTES LEFT IN T2
HRRZ T1,P3 ;GET COUNT DRIVER WANTS IN T1
MOVEM P4,@ETDTBP(F) ;STORE NEW POINTER
STOR. P4,ED.MSP,(F) ;ALSO STORE IN ETD SO NEXT CALL TO DRIVER
; CAN PASS THIS POINTER BACK
;HERE AFTER INITIAL TO-10 DOORBELL SIGNALLING THE START OF INDIRECT
; FRAGMENT TRANSFER. T1 HAS CURRENT DESIRED COUNT, T2 HAS NUMBER
; OF BYTES LEFT IN PACKET BEFORE NEXT TRANSFER STARTS.
DTEINX: SUB T2,T1 ;GET NEW NUMBER OF BYTES LEFT IN PACKET IN T2
STOR. T2,ED.IBL,(F) ;SAVE FOR NEXT TIME
SKIPGE T2 ;DRIVER EATING TOO MUCH?
DEAD10 ;YES, ERROR
LOAD. T3,ED.210,(F) ;GET TO-10 SECTION ADDRESS
MOVE T3,ETCSTS(T3) ;GET TO-10 STATUS WORD FROM IT
TLNE T3,(EC.16B) ;IS THIS INDIRECT DATA 16 BITS?
ASH T1,-1 ;YES, TURN 8 BIT COUNT INTO 16 BIT COUNT
MOVNS T1 ;SETUP MINUS BYTE COUNT
ANDI T1,TO10BC ;JUST THESE BITS
SKIPG T2 ;TAKING IT ALL?
TRO T1,TO10IB ;YES, INTERRUPT 11 AFTER THIS XFER
XCT ETDDTO(F) ;DATAO DTEN,(T1)
POPJ P, ;TRANSFER IS GOING NOW.
;HERE IF DRIVER DOESNT WANT ANYMORE INDIRECT DATA
DTEXD1: LOAD. T1,ED.IBL,(F) ;GET NUMBER OF BYTES LEFT IN PACKET
SKIPE T1 ;SKIP IF DRIVER HAS TAKEN ENOUGH
DEAD10 ;DRIVER TOOK LESS INDIRECT DATA THAN
; THE 11 WAS TRYING TO SEND
LOAD. T2,ED.211,(F) ;GET TO-11 SECTION
MOVEI T1,EC.2IT ;CLEAR TO-10 XFER IN PROGRESS AFTER LAST FRAG
ANDCAM T1,ETCSTS(T2) ;FROM 1 TO ZERO
;HERE TO PUT TO-10 SIDE OF DTE IDLE
; RELEASE THE TO-10 BUFFER IF ITS THERE.
DTETID: MOVEI T1,ED.TID ;MARK TO-10 DTE AS IDLE
STOR. T1,ED.2TS,(F) ;ZAP
PJRST T10RLC ;RELEASE TO-10 BUFFER AND RETURN
;ROUTINES TO DO DISPATCH FOR INCOMING TO-10 FUNCTIONS
; PJRSTS TO APPROPRIATE PLACE IN DEVICE DRIVER
; CALL WITH C(P2) = DEVICE,,FUNCTION
; DEVICE CODE IS RANGE CHECKED, AND A SPECIAL "EAT" DISPATCH
; TABLE, DESIGNED TO GRACEFULLY THROW AWAY MESSAGES, IS USED
; FOR UNKNOWN DEVICES. THIS WAY, RSX20 CAN TALK ABOUT LINE
; PRINTERS AND WE WONT CARE.
; THIS IS A SEPARATE ROUTINE BECAUSE IT DOES SOME FOOLING AROUND
; LOOKING FOR SPECIAL DEVICES, AND CHECKING TO SEE IF THE FUNCTION
; IS LEGAL FOR ALL DEVICES, IN WHICH CASE A SEPARATE DISPATCH TABLE
; MUST BE USED.
; RETURN TO CALLER AFTER DISPATCH
DODSP: PUSHJ P,DSTDSP ;SETUP T1, T2 FOR DISPATCH
PUSHJ P,ISALL ;SKIP IF FN IS LEGAL FOR ALL DEVICES
PJRST @DEVTAB(T2) ;DISPATCH ACCORDING TO FUNCTION, DEVICE
PJRST @ALLDSP(T1) ;THIS IS SPECIAL FUNCTION. IGNORE DEVICE FIELD.
;HERE TO DISPATCH ON A NEGATIVE (DTESER INTERNAL) FUNCTION
; CODE
DNDSP: PUSH P,T1 ;SAVE THE CODE (18 BIT NEG)
PUSHJ P,DSTDSP ;SETUP T2 S IDX INTO DEVTAB
POP P,T1 ;RESTORE
PJRST @DEVTAB(T2) ;DISPATCH AND RETURN
;HERE TO DISPATCH FROM DEVTAB EVEN FOR GLOBAL FUNCTION CODES
DSDSP: PUSHJ P,DSTDSP ;SETUP T1,T2 FOR DISPATCH
PJRST @DEVTAB(T2) ;DISPATCH
;ENTER HERE WITH C(P2) = DEV,,FN
; EXIT WITH FUNCTION CODE IN T1, INDEX INTO DEVTAB IN T2.
; RETURN WITH C(T2) = 0 IF DEVICE IS UNKNOWN, CAUSING DISPATCH
; THROUGH DEVTAB TO USE EATDSP.
DSTDSP: HRRZ T1,P2 ;GET FUNCTION FROM P2
ANDI T1,FNCMSK ;JUST THE NUMBER
HLRZ T2,P2 ;GET DEVICE CODE
CAIG T2,MAXDEV ;OUT OF RANGE?
POPJ P, ;NO, RETURN
MOVEI T4,0 ;YES, SEE IF ITS ONE OF THE SPECIALS
MOVE T3,T2 ;SAVE ORIGINAL FUNCTION FOR CHECKING
DSTDS1: SKIPN T2,SPDVTB(T4) ;GET ENTRY IN TABLE
POPJ P, ;RETURN 0 (GUARANTEED TO BE EATDSP)
; IF END OF TABLE
CAME T2,T3 ;MATCH?
AOJA T4,DSTDS1 ;NO, KEEP LOOKING
MOVNI T2,1(T4) ;GET NEGATIVE INDEX INTO DEVTAB
POPJ P, ;RETURN WITH T1, T2 SETUP
;TEMPORARILY DEFINED TO BE IGNORED . . .
KLIDSP==ALLDSP
CLKDSP==EATDSP
DL1DSP==EATDSP
DH1DSP==EATDSP
;MASTER DISPATCH TABLES. FUNCTION CODE WILL BE IN T1.
; POSITIVE OFFSETS IN DEVTAB MUST AGREE WITH PROTOCOL DEVICE CODE
; DEFINITIONS (SEE DTEPRM).
; NEGATIVE OFFSETS TO DEVTAB MUST CORRESPOND TO POSITIVE ENTRIES
; IN SPDVTB, AND THEY INDICATE SPECIAL DEVICES.
@KLIDSP(T1) ;KLINIK
@KLEDSP(T1) ;GE FROM THE 11
@KLCDSP(T1) ;KL CPU (WHY RELOAD)
DEVTAB: @EATDSP(T1) ;GUARANTEED TO BE EATDSP
@CT0DSP##(T1) ;CTY
@DL1DSP(T1) ;DL11 #1
@DH1DSP(T1) ;DH11
@DLSDSP##(T1) ;DATA LINE SCANNER (DLS)
@DLPDSP##(T1) ;LPT
@FCRDSP##(T1) ;CDR
@CLKDSP(T1) ;CLOCK
@FEDDSP##(T1) ;FRONT END DEVICE
IFN FTNET,<
@NCLDSP##(T1) ;NCL DEVICE (DN87S)
>
IFE FTNET,<
@EATDSP(T1)
>
@EATDSP(T1) ;DAS60 DEVICE
MAXDEV==.-DEVTAB-1 ;MAXIMUM DEVICE NUMBER ALLOWED
IFN .EMMXD-MAXDEV,<PRINTX DEVTAB AND DTEPRM DO NOT AGREE>
;TABLE TO SEARCH FOR DEVICES OUT OF ORDER FROM ABOVE
; MUST BE IN REVERSE ORDER OF THE NEGATIVE ENTRIES IN DEVTAB
SPDVTB: .EMCPU ;KL10 CPU (WHY RELOAD)
.EMKLE ;KLERR
.EMKLI ;KLINIK
Z ;TABLE MUST END WITH A ZERO
;DISPATCH TABLE FOR FUNCTIONS THAT ARE LEGAL FOR ALL DEVICES
; NOTE NEGATIVE DISPATCH ENTRIES ARE NOT NEEDED, SINCE
; GENERIC FUNCTIONS DO NOT NEED THEM
ALLDSP: EATMSG ;(0)
EATMSG ;(1)
TAKCTN ;(2)TAKE CTY-DLS CORRESPONDENCE
EATMSG ;(3)
EATMSG ;(4)
EATMSG ;(5)
EATMSG ;(6)
KLNSTS ;(7)
EATMSG ;(10)
TAKRDT ;(11)REQUEST FOR DATE/TIME
EATMSG ;(12)
EATMSG ;(13)
EATMSG ;(14)
EATMSG ;(15)
EATMSG ;(16)
EATMSG ;(17)
EATMSG ;(20)
EATMSG ;(21)
EATMSG ;(22)
EATMSG ;(23)
TAKROM ;(24)TAKE 11 ROM WORD
TAKAAL ;(25)ACK ALL
EATMSG ;(26)
EATMSG ;(27)
EATMSG ;(30)
EATMSG ;(31)
EATMSG ;(32)
EATMSG ;(33)
;TEMPORARY DEFINITIONS
;ROUTINE TO RANGE CHECK A PROTOCOL FUNCTION CODE
; CALL WITH FUNCTION CODE, EM.IND ON IF APPLICABLE
; IN RH(P2) (USUAL PLACE)
; RETURN INTERNAL FUNCTION TYPE IN RH(T1), SOME BITS IN LH(T1)
; CALL AT GT2XFT TO FIND TO-10 FUNCTION TYPE
; CALL AT GT2EFT TO FIND TO-11 FUNCTION TYPE
; GIVES ERROR RETURN IF FUNCTION NOT LEGAL FOR SOME REASON
; GIVES SKIP RETURN IF OK, WITH FUNCTION TYPE IN RH(T1), BITS IN LH(T1)
FNCMSK==77777
GT2XFT: SKIPA T4,[LGL2X] ;CHECK LEGAL FOR TO-10 BIT
GT2EFT: MOVSI T4,(LGL2E) ;CHECK LEGAL FOR TO-11 BIT
GTXXFT: HRRZ T1,P2 ;GET FUNCTION CODE
ANDI T1,FNCMSK ;JUST THE CODE
CAILE T1,MAXFNC ;OUT OF RANGE?
POPJ P, ;YES, ERROR RETURN
MOVE T2,FNCTAB(T1) ;GET FUNCTION ENTRY FOR REST OF ROUTINE
TDNN T4,T2 ;LEGAL FOR SAID DIRECTION?
POPJ P, ;NO, GIVE ERROR RETURN
TRNE P2,EM.16B ;IS 16 BIT MODE ON?
; (NEVER IS FOR TO-10, 11 CANT SET IT)
TLNE T2,(LGL16) ;YES, IS IT LEGAL FOR THIS FN?
JRST .+2 ;YES.
POPJ P, ;NO, ERROR RETURN
LDB T1,[POINT 3,T2,35];GET TO-10 FUNCTION TYPE,
;ASSUMING TEN FUNCTION
TLNE T4,(LGL2E) ;REALLY CALLED FOR TO-11?
LDB T1,[POINT 3,T2,32];YES, GET TO-11
MOVE T3,[CAIN T1,TINDR]
;SETUP FOR DIRECT
TRNE P2,EM.IND ;IS THIS INDIRECT?
HRLI T3,(CAIE T1,) ;YES, SETUP FOR INDIRECT
XCT T3 ;SKIP IF DIRECT/INDIRECT MODE IS SET CORRECTLY
POPJ P, ;NO, ITS NOT
HLL T1,T2 ;GET FLAG BITS IN LH(T1)
;FUNCTION TYPE IS IN RH(T1)
JRST CPOPJ1## ;SUCCESS.
;ROUTINE TO CHECK TO SEE IF THE FUNCTION CODE IN RH(P2) IS
; LEGAL FOR ALL DEVICES (USE SPECIAL DISPATCH TABLE)
; CALL WITH FUNCTION CODE, EM.IND IN RH(P2) (USUAL PLACE)
; DEAD10 IF NOT A LEGAL FUNCTION (SHOULD HAVE BEEN CHECKED ALREADY)
; ERROR RETURN IF JUST ORDINARY FUNCTION
; SUCCESS RETURN IF FUNCTION IS LEGAL FOR ALL DEVICES
; SAVES ALL ACS
ISALL: PUSHJ P,SAVT## ;SAVE ALL T ACS
PUSHJ P,GT2XFT ;GET FUNCTION TYPE - INTERESTED IN LH BITS
DEAD10 ;FUNCTION NO GOOD AT ALL . . .
TLNE T1,(LGLAL) ;LEGAL FOR ALL DEVICES?
AOS (P) ;YES, GIVE SKIP RETURN
POPJ P, ;TO SKIP OR NOT TO SKIP
;TABLE INDICATING INTERNAL FUNCTION TYPE AND OTHER INFO
; TO-11 TYPE IN BITS 30-32, TO-10 TYPE IN BITS 33-35
LGL2X==1B0 ;LEGAL TO-10 FUNCTION
LGL2E==1B1 ;LEGAL TO-11 FUNCTION
LGLAL==1B2 ;LEGAL FOR ALL DEVICES (USE SPECIAL DISPATCH TABLE)
LGL16==1B3 ;LEGAL 16 BIT INDIRECT (COULD BE 8 BIT TOO)
;INTERNAL FUNCTION TYPES. THERE ARE TWO TABLES, DTQTAB AND D2XTAB, THAT
; DEPEND ON THE TYPES BEING DEFINED IN THE FOLLOWING ORDER.
TINDR==0 ;INDIRECT
T16BT==1 ;16 BITS OF DATA
TLINE==2 ;LINE NUMBER
TLNGD==3 ;LONG DIRECT (LINE, DATA, LINE, DATA . . .)
TLNDT==4 ;ONE LINE, ONE DATUM
FNCTAB: 0 ;(0)ILLEGAL FUNCTION
LGL2E+<T16BT>B32 ;(1)TO-11 INITIAL MESSAGE
LGLAL+LGL2X+<TLINE>B35 ;(2)TAKE CTY-DLS CORRESPONDENCE
LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(3)STRING DATA
LGL2E+LGL2X+<TLNGD>B32+<TLNGD>B35 ;(4)TAKE CHARACTER DATA
LGL2E+LGL2X+<TLINE>B32+<TLINE>B35 ;(5)REQUEST FOR DEVICE STATUS
0 ;(6)UNUSED
LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(7)HERE IS DEVICE STATUS
0 ;(10)UNUSED
LGLAL+LGL2E+LGL2X+<T16BT>B32+<T16BT>B35 ;(11)REQUEST DATE/TIME
LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(12)HERE IS DATE/TIME
LGL2E+<T16BT>B32 ;(13)FLUSH TTY LINE OUTPUT
LGL2E+<TINDR>B32 ;(14)SEND ALL
LGL2X+<TLNGD>B35 ;(15)DATASET CONNECTED
LGL2E+LGL2X+<TLNDT>B32+<TLNGD>B35 ;(16)DATASET HUNG UP
LGL2E+LGL2X+<TLNGD>B32+<TLNGD>B35 ;(17)DEVICE ACKNOWLEDGE
LGL2E+<T16BT>B32 ;(20)XON
LGL2E+<T16BT>B32 ;(21)XOFF
LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(22)HERE IS LINE SPEED
LGL2E+LGL2X+<TLNGD>B32+<TLNGD>B35 ;(23)HERE IS LINE ALLOCATIONS
LGLAL+LGL2X+<T16BT>B35 ;(24)HERE IS 11 ROM WORD
LGLAL+LGL2E+LGL2X+<T16BT>B32+<T16BT>B35 ;(25)ACK ALL
LGL2E+<TLNDT>B32 ;(26)DEVICE ON/OFF
LGL2E+<T16BT>B32 ;(27)ENABLE/DISABLE REMOTES (DATASETS)
LGL16+LGL2E+<TINDR>B32 ;(30)LOAD LP RAM
LGL16+LGL2E+<TINDR>B32 ;(31)LOAD LP VFU
0 ;(32) UNUSED
LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(33)KLINIK PARAMETERS
MAXFNC==.-FNCTAB-1 ;MAXIMUM FUNCTION CODE FOR RANGE CHECK
;TABLE FOR DISPATCH ON TO-10 MESSAGES ACCORDING TO INTERNAL FUNCTION TYPE
D2XTAB: TKINDR ;INDIRECT
TK16BT ;16 BIT DATUM
TKLINE ;JUST LINE NUMBER
TKLNGD ;LONG DIRECT
TKLNDT ;LINE-DATUM
;ROUTINES TO HANDLE THE VARIOUS TYPES OF FUNCTIONS
;HERE IF FUNCTION IS INDIRECT
TKINDR: HLRZ T1,P2 ;GET DEVICE
STOR. T1,ED.XDV,(F) ;STORE IN DTE BLOCK SO DRIVER CAN BE
; TOLD WHAT'S WHAT
STOR. P2,ED.XFN,(F) ;STOR.E FUNCTION TOO
ILDB P3,T4 ;GET COUNT FOR INDIRECT PART
STOR. P3,ED.IBL,(F) ;STORE IN ETD FOR COMPARE AGAINST QSIZE
; AT DOORBELL TIME
ILDB T1,T4 ;GET LINE NUMBER
STOR. T1,ED.XLN,(F) ;REMEMBER THIS FOR INDIRECT PART
HRL P3,T1 ;C(P3)=LINE,,COUNT
JRST TKEXT1
;HERE FOR FUNCTIONS WHICH HAVE 16 BITS OF DATA
TK16BT: PUSHJ P,GX2BYT ;GET 16 BIT BYTE (SWAP BYTES)
MOVE P3,T1 ;C(P3)=DATA
JRST TKEXT1
;HERE FOR FUNCTIONS CONTAINING JUST LINE NUMBER
TKLINE: ILDB T1,T4 ;GET LINE NUMBER
HRLZ P3,T1 ;C(P3)=LINE,,0
SUBI U,1
JRST TKEXT2
;HERE FOR LINE NUMBER,DATA FUNCTIONS
TKLNDT: ILDB P3,T4 ;GET DATA IN P3
ILDB T1,T4 ;GET LINE NUMBER
HRL P3,T1 ;LINE
TKEXT1: SUBI U,2 ;TOOK 2 8 BIT BYTES
TKEXT2: SETZ P4, ;NO BYTE POINTER
POPJ P, ;RETURN
;HERE FOR LONG DIRECT MESSAGES
TKLNGD: HRRZ P3,U ;THIS IS HOW LONG DATA IS
MOVE P4,T4 ;SETUP 8 BIT BYTE POINTER FOR DRIVER
POPJ P, ;RETURN, HAVEN'T TAKEN ANY BYTES
;EATING SERVICE
;THIS IS A "DEVICE DRIVER" FOR UNKNOWN DEVICES.
; USING THE EATDSP TABLE ENSURES THAT A MESSAGE FROM THE 11
; IS EATEN IN A WAY TO MAKE THE 11 HAPPY, BUT WILL BE IGNORED
; BY THE 10.
;THESE ROUTINES SHOULD BE USED BY DEVICE DRIVERS FOR THROWING AWAY
; UNKNOWN MESSAGES.
CPOPJ## ;(-1)LOST TO-10 INDIRECT MESSAGE
EATDSP::EATMSG ;(0)
EATMSG ;(1)
EATMSG ;(2)
EATMSG ;(3)
EATMSG ;(4)
EATMSG ;(5)
EATMSG ;(6)
EATMSG ;(7)
EATMSG ;(10)
EATMSG ;(11)
EATMSG ;(12)
EATMSG ;(13)
EATMSG ;(14)
EATMSG ;(15)
EATMSG ;(16)
EATMSG ;(17)
EATMSG ;(20)
EATMSG ;(21)
EATMSG ;(22)
EATMSG ;(23)
EATMSG ;(24)
EATMSG ;(25)
EATMSG ;(26)
EATMSG ;(27)
EATMSG ;(30)
EATMSG ;(31)
EATMSG::PUSHJ P,GT2XFT ;GET THE TO-10 FUNCTION TYPE
DEAD10 ;FN ALREADY PASS CHECK, MUST HAVE DROPPED
; THE BALL SOMEWHERE
PJRST @EATTAB(T1) ;DISPATCH
EATTAB: EATIND ;INDIRECT
CPOPJ## ;16 BIT
CPOPJ## ;LINE NUMBER
CPOPJ## ;LONG DIRECT
CPOPJ## ;LINE-DATA
;ROUTINE TO EAT AN INDIRECT MESSAGE. (ALL OTHERS CAN BE IGNORED)
EATIND::MOVSI S,CPOPJ## ;POST ADDRESS (P3 WILL BE ZERO AT POST TIME)
;LEAVE LINE,,COUNT IN P3
PJRST TKEXT2 ;ZERO BYTE POINTER SO DATA GOES NOWHERE
; LET DTESER XFER THE INDIRECT DATA
;HERE ON TO-11 DONE. ETD ADDRESS IN F
DTE2ED: MOVEI T1,CLTO11 ;CLEAR TO11 DONE
XCT ETDCNO(F) ;GONE.
LOAD. T4,ED.CUR,(F) ;GET RELEVANT QUEUE ENTRY
LOAD. T1,ED.2ES,(F) ;GET TO-11 DTE STATE
CAIN T1,ED.EDB ;WERE WE WAITING FOR TO-11 DIRECT
; OR INDIRECT DONE?
JRST DTEEDD ;YES, SEE IF WE HAVE TO SEND INDIRECT DATA
CAIN T1,ED.EIB ;WAS TO-11 INDIRECT GOING?
JRST DTEEDI ;YES, DON'T CHECK INDIRECT COUNT ANYMORE
PJSP T1,DTERLD ;SOMEONE FIDDLING
DTEEDI: MOVE T1,[EC.IND!EC.16B] ;CLEAR OUT SPECIAL INDIRECT BITS NOW
LOAD. T2,ED.211,(F) ;WHERE TO CLEAR THEM FROM
ANDCAM T1,ETCSTS(T2) ;ZAP EM
JRST DTEED1 ;CONTINUE ON
DTEEDD: LOAD. T1,EQ.CNT,(T4) ;GET INDIRECT COUNT, IF ANY
JUMPN T1,DTESID ;IF COUNT IS NON-ZERO, SEND INDIRECT DATA NOW
DTEED1: PUSH P,T4 ;SAVE CURRENT QUEUE ENTRY
SETZ T4, ;THERE IS NO MORE
STOR. T4,ED.CUR,(F) ;A CURRENT MESSAGE (UNTIL DTENXT)
PUSHJ P,DTENXT ;START UP DTE EARLY
POP P,T4 ;RESTORE FORMER CURRENT MESSAGE QUEUE HEADER
;HERE TO POST A TO-11 MESSAGE. CALLED BY PUSHJ FROM DTECLR TO
; FAKE UP A POST WHEN A DTE IS CLEARED SO DRIVERS DONT HANG UP.
; DRIVERS ARE BEING LIED TO ABOUT SUCCESSFUL COMPLETION OF MESSAGE.
; HOWEVER, SHOULD BE NO DIFFERENT THAN IF 11 GOT MESSAGE AND THEN DIED.
DTEPST: PUSHJ P,SAVE4## ;SAVE P1-P4 FOR ARG PASSING
LOAD. T3,EQ.PST,(T4) ;GET POST ADDRESS
JUMPE T3,DTEPS1 ;IF NO POST ADDRESS, SKIP SETUP
PUSH P,T4 ;SAVE QUEUE HEADER ADDRESS AGAIN
LOAD. P1,ED.DTN,(F) ;C(P1)=CPU#,,DTE#
ADDI T4,SIZE(.EQLEN,36) ;POINT TO THE TO-11 MESSAGE ITSELF
LOAD. P2,EM.FNC,(T4) ;GET FUNCTION IN RH P2
LOAD. T1,EM.DEV,(T4) ;DEVICE GOES IN LH OF
HRL P2,T1 ;P2
SUBI T4,SIZE(.EQLEN,36) ;POINT TO Q HEADER AGAIN
LOAD. T1,EQ.ELN,(T4) ;GET POSSIBLE TO-11 LINE NUMBER
HRLZ P3,T1 ;PUT INTO LH(P3) FOR DRIVER
LOAD. P4,EQ.PTR,(T4) ;PASS POINTER BACK TO DRIVER SO
; HE CAN DEALLOCATE CORE
LOAD. T1,EQ.CNT,(T4) ;GET INDIRECT COUNT HE GAVE
HRR P3,T1 ;RETURN IT FROM WHENCE IT CAME
MOVSI T1,(EQ.16B) ;WAS IT 16 BIT MODE?
TDNE T1,ETQSTS(T4) ;??
TRO P2,EM.16B ;YES, MAY AS WELL TELL HIM IN CASE IT WAS USEFUL
LOAD. S,EQ.DRD,(T4) ;DRIVER'S SPECIAL DATA (DDB OR SOMETHING)
PUSHJ P,(T3) ;CALL DRIVER'S POST ROUTINE
POP P,T2 ;RESTORE QUEUE ADDRESS INTO T2
JRST DTEPS2 ;AND GIVE CORE BACK
DTEPS1: MOVE T2,T4 ;GET ADDRESS IN T2 FOR GIVMES
DTEPS2: LOAD. T1,EQ.SIZ,(T2) ;GET TOTAL SIZE OF CORE BLOCK
PJRST GIVMES ;CALL GIVMES WITH ADDRESS IN T2,
; COUNT IN T1
;HERE IF TO-11 DONE FOR DIRECT PART OF INDIRECT MESSAGE
; WITH QUEUE HEADER ADDRESS IN T4
DTESID: LOAD. T3,ED.211,(F) ;GET TO-11 SECTION ADDRESS
LOAD. T1,EQ.PTR,(T4) ;GET INDIRECT POINTER DRIVER GAVE
MOVEM T1,@ETDEBP(F) ;PUT IN TO-11 POINTER WORD IN EPT
LOAD. T1,EQ.CNT,(T4) ;INDIRECT DATA COUNT
STOR. T1,EC.QSZ,(T3) ;SET UP QSIZE FOR INDIRECT PACKET
MOVEI T1,ED.EIB ;CHANGE STATE OF DTE TO EXPECTING TO-11
; DONE FOR INDIRECT SO THAT DRIVER GETS CALLED
STOR. T1,ED.2ES,(F) ; (SEE ABOVE CODE)
MOVE T2,ETCSTS(T3) ;GET STATUS WORD FROM TO-11 SECTION
TRO T2,EC.IND ;INDIRECT BIT, SO 11 KNOWS WHAT BELL IS FOR
MOVSI T1,(EQ.16B) ;IS THE INDIRECT DATA TO BE SENT IN
TDNE T1,ETQSTS(T4) ; WORD MODE?
TLO T2,(EC.16B) ;YES, SET THE BIT FOR COMM AREA
MOVEM T2,ETCSTS(T3) ;SET STATUS ALL AT ONCE
MOVEI T1,TO11DB ;RING 11 DOORBELL NOW
XCT ETDCNO(F) ;DONG
POPJ P, ;RETURN
SUBTTL GENERAL MESSAGE PROCESSOR
TAKCTN: HLRZ T1,P3 ;GET LINE # OF CTY
STOR. T1,ED.CTN,(F) ;STORE IN DTE CONTROL BLOCK
POPJ P, ;RETURN
;ACK ALL SERVICE
;THIS ROUTINE WILL DO INDIVIDUAL ACK ALL MESSAGES FOR ALL
; DEVICES IN ACKTAB
TAKAAL: MOVSI T4,-ACKTBL ;AOBJN POINTER TO ACKTAB
TAKAA1: HRL P2,ACKTAB(T4) ;GET DEVICE
PUSH P,T4 ;SAVE AOBJN POINTER
PUSH P,F ;SCNSER WIPES OUT F
PUSHJ P,DSDSP ;DO THE ACK FOR A SINGLE DEVICE
; (CALL SPECIAL ROUTINE THAT WILL DO DISPATCH
; THROUGH SPECIFIC DEVICE'S DISPATCH TABLE)
POP P,F
POP P,T4 ;GET POINTER BACK
AOBJN T4,TAKAA1 ;AND CONTINUE
POPJ P, ;DONE
;TABLE OF DEVICES THAT NEED ACK ALL. THESE DEVICES MUST
; BE NON-SPECIAL, SINCE TAKAAL DOES DISPATCH BY HAND AND DOES NOT
; DO SEARCH OF SPECIAL DEVICE TABLE.
ACKTAB: .EMCTY ;DO ACKS FOR CTY AND
.EMDLS ;DLS
.EMLPT ;LPT
.EMFED ;FRONT END DEVICE
ACKTBL==.-ACKTAB ;LENGTH
;TAKE 11 ROM WORD, FOR RELOADING
TAKROM: LOAD. T1,ED.211,(F) ;GET TO-11 SECTION ADDRESS
STOR. P3,EC.RLD,(T1) ;PUT INTO COMM REGION
POPJ P, ;RETURN
;DATE/TIME SERVICE
;HERE FROM COMCON TO SET DATE/TIME FOR ALL APPROPRIATE FRONT
; ENDS WHEN EITHER DATE OR DAYTIME SET COMMANDS ARE DONE.
; PRESENTLY ONLY THE MASTER -11 IS GIVEN THE DATE AND TIME.
COMSDT::PUSHJ P,SAVE4 ;SAVE P1-P4 NOW
PUSHJ P,SVEPTD ;GET MASTER ETD ADDRESS
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER IN P1
PJRST DTESD0 ;GO DO IT
;HERE TO PROCESS REQUEST FOR DATE/TIME, OR TO SEND DATE/TIME
; JUST FOR THE HECK OF IT. C(P1) = CPU#,,DTE#. P2-P4 SETUP BY THIS ROUTINE
; BEFORE CALL TO DTEQUE.
TAKRDT:
DTESDT: PUSHJ P,SAVE4## ;STILL USE DATA FROM P1-P4,
; BUT RESTORE AFTER WE'RE DONE
;HERE IF P1-P4 ALREADY SAVED
DTESD0: MOVEI T2,SIZE(.EMDTS,36) ;GET SIZE OF INDIRECT CORE, IN 36 BITS
PUSHJ P,MESCOR ;GET THE CORE
POPJ P, ;LOSE. DON'T CRASH THE TEN, THOUGH.
MOVE P4,T1 ;SAVE ADDRESS OF INDIRECT MESSAGE
MOVE T2,[POINT 16,(P4)] ;POINTER TO FILL MESSAGE
MOVEI T1,177777 ;FIRST BYTE SAYS VALID DATE/TIME
IDPB T1,T2 ;PUT IT IN THE INDIRECT MESSAGE
MOVE T1,LOCYER## ;NEXT BYTE IS THE YEAR
IDPB T1,T2
MOVE T2,[POINT 8,1(P4)] ;NEXT FEW ARE 8 BIT BYTES
MOVE T1,LOCMON## ;GET MONTH
SOS T1 ;RSX-20 EXPECTS JANUARY TO BE 0
IDPB T1,T2 ;STORE
MOVE T1,LOCDAY## ;AND DAY
SOS T1 ;RSX-20 EXPECTS 1ST OF THE MONTH TO BE ZEROTH
IDPB T1,T2 ;STORE THAT TOO
HLRZ T3,DATE## ;GET UNIVERSAL DATE
IDIVI T3,7 ;GET DAY OF WEEK IN T4
ADDI T4,2 ;RSX'S MONDAY = 0, WHILE WED. = 0 FOR UDT
CAIL T4,7 ;OVERFLOW?
SUBI T4,7 ;YES, DROP BACK 7
IDPB T4,T2 ;STORE DAY OF WEEK, MONDAY = 0
MOVE T2,[POINT 16,2(P4)] ;NEXT WORD. ONE 16 BIT BYTE IN HERE.
MOVE T3,TIME## ;GET TICS SINCE MIDNIGHT
IDIV T3,TICSEC## ;CONVERT TO SECONDS SINCE MIDNITE
ASH T3,-1 ;/2 SO IT WILL FIT
IDPB T3,T2 ;STORE THAT
;NOW MESSAGE PACKET IS COMPLETE, SEND IT
HRLI P4,(POINT 16,) ;16 BIT BYTE POINTER
MOVEI P3,.EMDTS ;SIZE OF MESSAGE, IN 8 BIT BYTES
MOVE P2,[.EMCLK,,EM.16B+EM.IND+.EMHDT] ;HERE IS DATE/TIME
MOVSI S,DTESD1 ;PLACE TO GO TO WHEN DONE
PUSHJ P,DTEQUE ;GO SEND IT
JFCL ;IGNORE AN ERROR
POPJ P, ;RETURN
;HERE WHEN DATE/TIME MESSAGE IS SENT, GIVE BACK CORE
DTESD1: MOVEI T1,SIZE(.EMDTS,36) ;WORDS TO GIVE BACK
HRRZ T2,P4 ;GET ADDRESS BACK FROM POINTER
PJRST GIVMES ;RETURN CORE.
SUBTTL -- KLINIK PARAMETER STATUS SAVING
KPSLEN==26 ;LENGTH OF PARAMETER SAVE MESSAGE
;HERE ON DIRECT PART OF THE KLINIK PARAMETER MESSAGE
KLCKPS: MOVSI S,KPSRCV ;POST KLINIK PARAMETER SAVE ADDRESS
MOVEI P3,KPSLEN ;LENGTH OF PARAMETER MESSAGE
MOVE P4,KPSPTR ;POINTER TO SAVE AREA
POPJ P, ; AND RETURN
;HERE ON RECEIPT OF THE INDIRECT PORTION OF THE PARAMETER MESSAGE
KPSRCV: MOVEI P3,0 ;INDICATE ALL EXPECTED DATA RECEIVED
POPJ P, ; AND RETURN
;HERE TO SEND THE PARAMETERS BACK TO THE -11
KPSSND: PUSHJ P,SAVE4## ;SAVE P1-P4
LOAD. P1,ED.DTN,(F) ;MASTER DTE NUMBER
MOVEI P2,EM.16B+EM.IND+.EMKPS
MOVEI P3,KPSLEN ;MESSAGE LENGTH IN 8-BIT BYTES
MOVE P4,KPSPTR ;POINTER TO THE DATA
MOVEI S,'FOO' ;DON'T CARE ABOUT POST
PJRST DTEQUE ;SEND MESSAGE
KPSPTR: POINT 16,KPSBUF ;POINTER TO SAVE AREA
$LOW
KPSBUF: BLOCK <KPSLEN+3>/4
$HIGH
SUBTTL KL ERROR STATUS COLLECTING
;KL ERROR INFORMATION IS SENT BY THE MASTER -11 AFTER IT
; RELOADS THE -10. THE DATA COMES AS EITHER ONE OR TWO RECORDS, BUT
; BOTH THESE RECORDS ARE TOO LARGE TO COME OVER AS A SINGLE
; INDIRECT PACKET. THIS CODE COLLECTS THE FRAGMENTS OF THE RECORDS
; IN FREE CORE AND CALLS DAEMON TO LOOK AT THEM WHEN THE LAST
; PACKET (THE ONE WITH EM.EOF SET) COMES OVER. DAEMON WILL ISSUE
; A DTE. UUO FUNCTION TO RELEASE ALL THE CORE AT ONCE WHEN IT IS
; FINISHED WRITING THE ENTRIES INTO ERROR.SYS. IF DAEMON DOES NOT
; RELEASE THE CORE IN A SPECIFIED AMOUNT OF TIME AFTER THE LAST
; STATUS MESSAGE COMES IN (SYMBOL
; .KETIM IN DTEPRM, IN MINUTES), THE MONITOR WILL RELEASE THE
; FREE CORE ITSELF, AND DAEMON WILL WRITE A NULL ENTRY INTO
; ERROR.SYS IF IT FINALLY GETS AROUND TO SERVICING THE ERROR LOG
; REQUEST. IF THE -11 QUITS BEFORE SENDING THE LAST MESSAGE,
; THE CORE WILL DISAPPEAR AFTER THE TIMEOUT INTERVAL ALSO.
; IF THE -11 COMES BACK UP AFTER A CRASH BEFORE SENDING THE
; FINAL MESSAGE, THE ACK ALL SERVICE CALL WILL RELEASE THE CORE
; IN THE HOPES THAT THE -11 WILL SEND THE STUFF OVER AGAIN.
;DISPATCH TABLE FOR KLE DEVICE
KLEREL ;(-1)TO-10 INDIRECT MESSAGE LOST
KLCDSP:
KLEDSP: EATMSG ;(0)
EATMSG ;(1)
EATMSG ;(2)
EATMSG ;(3)
EATMSG ;(4)
EATMSG ;(5)
EATMSG ;(6)
KLESTS ;(7)HERE IS DEVICE STATUS
EATMSG ;(10)
EATMSG ;(11)
EATMSG ;(12)
EATMSG ;(13)
EATMSG ;(14)
EATMSG ;(15)
EATMSG ;(16)
EATMSG ;(17)
EATMSG ;(20)
EATMSG ;(21)
EATMSG ;(22)
EATMSG ;(23)
EATMSG ;(24)
KLEAAL ;(25)ACK ALL
EATMSG ;(26)
EATMSG ;(27)
EATMSG ;(30)
EATMSG ;(31)
EATMSG ;(32)
KLCKPS ;(33) KLINIK PARAMETER STATUS MESSAGE
;LOCATIONS USED TO KEEP TRACK OF WHERE WE ARE:
$LOW
KLEEOF: 0 ;NON-ZERO IF ALL CHUNKS ARE IN. CLEARED BY KLEREL
KLETIM::0 ;SOSN DONE ON THIS LOCATION EVERY MINUTE TO
; MAKE SURE CHUNKS DON'T STAY ALLOCATED FOREVER
; IN THE CASE THAT DAEMON IS SICK, WRONG VERSION, ETC.
KLEADR: 0 ;LH = ADDRESS OF LAST CHUNK
KLNSTF: 0 ;KLINIK STATUS FLAG
; RH = ADDRESS OF FIRST CHUNK
$HIGH
;HERE ON RECEIPT OF STATUS MESSAGE
KLNSTS: SETOM KLNSTF ;KLINIK STATUS FLAG
KLESTS: MOVEI T1,.KLETM+1 ;RESET FREE CORE WATCH TIMER EVERY
MOVEM T1,KLETIM ;TIME A STATUS MESSAGE COMES IN SO
; THAT DAEMON WILL HAVE THAT MUCH
; TIME FROM LAST MESSAGE.
HRRZ T2,P3 ;GET COUNT OF 8 BIT BYTES
ADDI T2,^D36/^D8-1 ;ROUND UP TO A 36 BIT WORD'S WORTH
ASH T2,-2 ;TURN INTO 36 BIT WORDS
ADDI T2,SIZE(.KEHDL,36) ;ADD IN SIZE OF HEADER
PUSHJ P,MESCOR ;GET THE CORE
JRST EATMSG ;CAN'T, FORGET IT
MOVE P4,T1 ;GET ADDRESS IN P4, USE FOR POINTER LATER
HLRZ T1,P1 ;GET CPU NUMBER
STOR. T1,KE.CPU,(P4) ;REMEMBER IT
HRRZ T1,P1 ;GET DTE NUMBER
STOR. T1,KE.DTE,(P4) ;THAT TOO
HLRZ T1,P2 ;GET DEVICE CODE
STOR. T1,KE.DEV,(P4) ;STASH
HLRZ T1,P3 ;GET LINE NUMBER
STOR. T1,KE.LIN,(P4) ;STORE THAT TOO
HRRZ T1,P3 ;GET 8 BIT COUNT AGAIN
STOR. T1,KE.CNT,(P4) ;SAVE FOR DAEMON
SETZ T1, ;ZERO FIRST WORD SO DAEMON CAN SEE
STOR. T1,KE.1WD,(P4) ;IF TRANSFER EVER MADE IT (AT LEAST ONE BIT SHOULD
; BE ON IN THE GENERAL STATUS BYTE)
CONO PI,PIOFF## ;LINK UP THIS BLOCK ALONE
HLRZ T1,KLEADR ;GET POSSIBLE LAST ADDRESS
JUMPE T1,KLEST1 ;JUMP IF NEED TO MAKE NEW CHAIN
STOR. P4,KE.LNK,(T1) ;NO, LAST ENTRY POINTS TO THIS ONE
HRLM P4,KLEADR ;THIS IS NEW LINKING PLACE
JRST KLEST2 ;GO TURN PI BACK ON
KLEST1: HRRM P4,KLEADR ;SETUP NEW FIRST AND
HRLM P4,KLEADR ;LAST ADDRESS
KLEST2: CONO PI,PION## ;TURN PI BACK ON
ADDI P4,SIZE(.KEHDL,36) ;POINT TO FIRST WORD WITH DATA
HRLI P4,(POINT 16,) ;MAKE BYTE POINTER
MOVSI S,KLESDN ;ADDRESS TO GO WHEN XFER IS DONE
POPJ P, ;RETURN AND START XFER
;HERE WHEN DATA IS IN. CHECK GENERAL STATUS TO SEE IF EOF, IF SO
; CALL DAEMON
KLESDN: SUBI P4,SIZE(.KEHDL,36) ;SO REFERENCE TO KE.1WD WILL WORK
LOAD. T1,KE.1WD,(P4) ;GET STATUS BYTE
TRNN T1,EM.EOF ;TIME TO CALL DAEMON?
SKIPE KLNSTF ;KLINIK STATUS? TIME TO CALL
CAIA
POPJ P, ;NO, JUST LET THIS CHUNK LIE AROUND
AOS KLEEOF ;EOF HAS BEEN SEEN, CALL OFF THE ACK ALL
; ROUTINE
MOVEI T1,.ERKLE ;CODE FOR DAEMON
HRL T1,KLEADR ;ADDRESS TO LOOK AT FOR DATA
PJRST DAEEIM## ;BLAME IT ON JOB 0
;HERE ON ACK ALL. IF CORE EXISTS AND EOF HAS NOT BEEN SENT, RELEASE
; THE CORE SO THAT THE ERROR INFO DOESN'T REPEAT
KLEAAL: MOVEI T1,-1 ;SETUP TO CHECK FOR EXISTANCE OF ERROR DATA
TDNE T1,KLEADR ;IS THERE A CHAIN AND
SKIPE KLEEOF ;IS IT UNFINISHED?
POPJ P, ;NO
PJRST KLEREL ;YES, DO NOT LEAVE UNFINISHED CHAIN
;ROUTINE TO RELEASE THE KLERR CHUNKS. CALLED 5 MINUTES AFTER DAEMON IS
; CALLED, OR ON DTE. UUO FUNCTION THAT DAEMON DOES.
KLEREL::PUSHJ P,SAVE1## ;SAVE P1 TO REMEMBER NEXT CHUNK ADDRESS
HRRZ P1,KLEADR ;GET START OF LIST
KLERE1: JUMPE P1,KLERE2 ;JUMP IF NO MORE TO RELEASE
MOVE T2,P1 ;GET ADDRESS INTO T2 FOR GIVMES
LOAD. P1,KE.LNK,(T2) ;GET NEXT CHUNK TO DEALLOCATE
LOAD. T1,KE.CNT,(T2) ;GET SIZE OF KLE DATA IN THIS ONE
ADDI T1,^D36/^D8-1 ;ROUND UP
ASH T1,-2 ;MAKE IT 36 BIT WORDS
ADDI T1,SIZE(.KEHDL,36) ;DEALLOCATE HEADER TOO
PUSHJ P,GIVMES ;CALL WITH ADDR IN T2, COUNT IN T1
JRST KLERE1 ;GO FOR MORE TO DEALLOCATE
KLERE2: SETZM KLEADR ;CLEAR LAST,,FIRST ADDRESSES
SETZM KLNSTF ;CLEAR KLINIK STATUS FLAG
SETZM KLEEOF ;NO MORE END OF FILE
POPJ P, ;RETURN
SUBTTL PROTOCOL CONTROL
XLIST ;DON'T PRINT LITERALS
LIT
LIST
$LOW
;ROUTINE TO ENTER SECONDARY PROTOCOL FOR THE FIRST TIME
; USES T ACS.
ENTSPC::PUSHJ P,SVEPTD ;SAVE F,T4 AND SETUP DTE & EPT ADDRESSES
MOVSI T2,(ED.PPC) ;GET READY TO CLEAR PRIMARY PROTOCOL BIT
CONO PI,PIOFF## ;IN CASE STUFF IS RUNNING
ANDCAM T2,ETDSTS(F) ;CLEAR BIT. NOW INTERRUPTS WILL GO
; THRU SECONDARY INTERRUPT ROUTINE
MOVEI T1,PILDEN+SPCPI ;SETUP NEW PI ASSIGNMENT
XCT ETDCNO(F) ;DO IT
SKIPN DTEEPW(T4) ;WERE WE IN PRIMARY PROTOCOL?
JRST ENTSP1 ;NO, CAUSE NO EXTRA DOORBELLS
MOVEI T1,TO11DB ;WAIT FOR ALL DOORBELLS TO THE -11 TO CLEAR
MOVEI T2,SPCTRY ;TIME TO WAIT
XCT ETDCSZ(F) ;CLEAR YET?
SOJG T2,.-1 ;NO, TRY FOR A WHILE
SKIPG T2 ;DID WE MAKE IT?
PJSP T1,DTERLD ;NO, GO KILL -11
SETZM DTEEPW(T4) ;IN CASE PRIMARY PROTOCOL WAS RUNNING
MOVEI T1,TO11DB ;RING 11'S DOORBELL SO IT
XCT ETDCNO(F) ;CAN SEE WHATS HAPPENED
ENTSP1: MOVEI T1,DT.ESP ;ENTER SECONDARY PROTOCOL COMMAND
PUSHJ P,SPCMD ;DO THE COMMAND
MOVSI T1,(ED.SPC) ;SET SECONDARY PROTOCOL BIT
IORM T1,ETDSTS(F) ;IN DTE STATUS WORD
CONO PI,PION## ;TURN ON PI SYSTEM AND
POPJ P, ;RETURN. (DON'T USE ONPOPJ BECAUSE
; ITS NOT AROUND EARLY ENOUGH)
XLIST ;DON'T PRINT LITERALS
LIT
LIST
$HIGH
;ROUTINE TO START PRIMARY PROTOCOL ON ANY DTE. CALL WITH
; DTE NUMBER (0-3) IN T1.
STRPPC::PUSH P,F ;SAVE F AND
PUSH P,T4 ;T4
HRRZ F,T1 ;GET DTE NUMBER IN RH(F)
PUSHJ P,GTCPUN ;GET CPU NUMBER
HRL F,T1 ;IN LH OF F
PUSHJ P,GTETDS ;GET DTE CONTROL BLOCK IN F
AOS -2(P) ;ASSUME GOOD RETURN
PUSHJ P,STXPPC ;DO COMMON STUFF
SOS -2(P) ;NOT
POP P,T4 ;RESTORE T4
PJRST FPOPJ## ;F AND RETURN
;HERE TO STOP AN 11 FROM RUNNING PRIMARY PROTOCOL. LEAVES
; 11 WAITING TO ENTER A PROTOCOL (PRIMARY, SECONDARY).
; CALL WITH DTE CONTROL BLOCK ADDRESS IN F.
LEVPPC: PUSHJ P,SAVE1## ;WE'LL USE P1 BELOW TO PASS A PARAMETER
PUSHJ P,GTEPT ;HAVE ETD ALREADY, GET EPT
LOAD. T1,ED.DTN,(F) ;GET DTE NUMBER
LSH T1,3 ;*8
ADD T4,T1 ;PLUS EPT IS OFFSET FROM DTE0 VECTOR
MOVSI T1,(ED.PPC) ;CLEAR PRIMARY PROTOCOL BIT
ANDCAM T1,ETDSTS(F)
SETZM DTEEPW(T4) ;NOW STOP 11 FROM LOOKING AT VALID EXAMINE BIT
MOVEI T1,TO11DB ;MAKE 11 NOTICE BY RINGING DOORBELL
XCT ETDCNO(F) ;DONG
IFN FTNET,<
LOAD. P1,ED.DTN,(F) ;GET DTE # OF THIS FRONT END
LOAD. T1,ED.CPN,(F) ;GET CPU #
HRLI P1,(T1) ;P1 IS NOW STANDARD DATA (CPU,,DTE)
PUSHJ P,NCLDWN## ;TELL NCL IT MAY HAVE LOST A NODE
> ;IFN FTNET
POPJ P, ;RETURN
;STMPPC -- ROUTINE TO START PRIMARY PROTOCOL ON MASTER DTE
; FOR THE FIRST TIME.
; CALLED FAIRLY EARLY IN THE MONITOR INITIALIZATION SO THAT THE DATE AND TIME CAN
; BE OBTAINED FROM THE 11 INSTEAD OF FROM THE OPERATOR THROUGH THE
; ONCE ONLY DIALOG QUESTIONS. DTEINI MUST BE CALLED FIRST.
;
;STXPPC -- ROUTINE TO START PRIMARY PROTOCOL ON ANY DTE, ETD ADDRESS IN F
;
; NOTE: T4 IS SETUP TO BE OFFSET TO THE SPECIFIC DTE'S HARDWARE VECTOR
; MINUS ADDRESS OF FIRST VECTOR, SO DTE VECTOR IS ADDRESSED AS
; DTE???(T4), WHERE DTE??? IS THE LOCATION OF THE FIRST DTE'S VECTOR
; LOCATION
; SKIP RETURN IF SEEMED TO GET INTO PRIMARY PROTOCOL
; NON-SKIP IF NOT
STMPPC::PUSHJ P,SVEPTD ;SAVE F,T4 AND GET DTE,EPT ADDRESSES
PUSHJ P,STXPP1 ;CALL COMMON CODE
POPJ P, ;TOUGH LUCK, GIVE ERROR RETURN
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER
LOAD. T1,ED.CPN,(F) ;AND CPU NUMBER
HRL P1,T1 ;SETUP CPU#,,DTE# IN P1
MOVE P2,[.EMCLK,,.EMRDT] ;REQUEST TIME AND DATE
; SO THAT -11 WILL SEND US CPU AND KLERR INFORMATION
; AND LINE SPEEDS (LINE SPEEDS IGNORED)
SETZB P3,P4 ;CLEAR OUT UNUSED ACS
SETZ S, ;NO POST ADDRESS
PJRST DTEQUE ;GIVE ERROR RETURN IF DTEQUE GIVES ONE,
; OTHERWISE DTEQUE GIVES SKIP RETURN
STXPPC: PUSHJ P,GTEPT ;GET EPT, F ALREADY SET UP
STXPP1: PUSHJ P,SAVE4## ;SAVE P1-P4 FOR CALL TO DTEQUE
SETZ S, ;NO DRIVER DATA OR POST ADDRESS
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER IN RH(P1)
LOAD. T1,ED.CPN,(F) ;PUT CPU NUMBER IN LH(P1)
HRL P1,T1
MOVEI T1,PILDEN+PI0ENB+0 ;MAKE SURE THIS DTE DOESNT INTERRUPT
XCT ETDCNO(F)
LOAD. T1,ED.DTN,(F) ;GET DTE NUMBER
LSH T1,3 ;*8
ADD T4,T1 ;GET OFFSET TO THIS DTE'S HARDWARE VECTOR
SETZM ETDKAN(F) ;RESET KEEP-ALIVE HUNG COUNTER
; FOR THIS DTE
LOAD. T3,ED.210,(F) ;GET 11'S TO-10 SECTION ADDRESS
MOVSI T2,(EC.VEX!EC.QIU);VALID EXAMINE, Q PROTOCOL IN USE
MOVEM T2,ETCSTS(T3) ;INITIALIZE STATUS WORD
;(ZEROES QUEUE COUNTS TOO)
LOAD. T3,ED.211,(F) ;DO SAME FOR 10'S TO-11 AREA
MOVEM T2,ETCSTS(T3) ;..
LOAD. T2,ED.PNE,(F) ;11 PROTOCOL PROCESSOR NUMBER
MOVNI T3,1(T2) ;GET OFFSET RELATIVE TO BEGINNING
; OF COMM REGION
MOVEI T1,ETCRGN##(T3) ;GET ACTUAL ADDRESS THAT THIS 11
; WANTS TO BEGIN WINDOW AT
MOVEM T1,DTEERW(T4) ;THIS IS EXAMINE RELOCATION WORD
LOAD. T1,ED.11A,(F) ;GET ADDRESS OF THIS 11'S AREA
SETZM ETCKAC(T1) ;START WITH ZERO FOR ITS KEEP ALIVE
SETZM ETDKAR(F) ;AND 10'S REMEMBRANCE OF IT
MOVEM T1,DTEDRW(T4) ;DEPOSIT RELOCATION WORD
;HERE COMES THE TRICKY PART . . .
LOAD. T2,EC.OSZ,(T1) ;GET SIZE OF 11'S SECTION OF 11'S AREA
ASH T2,3 ;CONVERT SIZE OF OWNERS SECTION TO WORDS
MOVEM T2,DTEDPW(T4) ;THAT'S THE DEPOSIT RELOCATION
;***OFF BY ONE??***
;EXAMINE PROTECTION WORD IS LAST
LOAD. T2,ED.PNE,(F) ;GET PROTOCOL PROCESSOR NUMBER
; (ASSUME HEADER IS SET UP WITH ALL OF THEM, AND INCREASING
MOVEI T1,ETCSIZ##+1(T2);SIZE OF ENTIRE REGION
MOVEM T1,DTEEPW(T4) ;NOW 11 WILL THING Q PROTOCOL IS IN EFFECT
MOVEI T1,ED.EID ;MAKE TO-11 DTE STATE IDLE
STOR. T1,ED.2ES,(F)
PUSHJ P,DTETID ;MAKE TO-10 SIDE OF DTE IDLE
LOAD. T1,ED.CUR,(F) ;DON'T LET CORE DISAPPEAR
SKIPE T1
DEAD10 ;***TEMPORARY***
LOAD. T1,ED.QUE,(F) ;DON'T LET CORE DISAPPEAR
SKIPE T1
DEAD10 ;***TEMPORARY***
MOVSI T1,(ED.DTM) ;IS THIS THE MASTER?
TDNN T1,ETDSTS(F) ;?
JRST STXPP2 ;NO, JUST RING DOORBELL
MOVEI T1,DT.LSP!DT.RST;LEAVE SECONDARY PROTOCOL, RESET COMM REGION
PUSHJ P,SPCMD ;DO IT
MOVSI T1,(ED.SPC) ;TURN OFF SECONDARY PROTOCOL BIT IF IT WAS ON
ANDCAM T1,ETDSTS(F) ;TURN OFF JUST BEFORE ENABLING PI ASSIGNMENT
MOVSI T1,(ED.PPC) ;SET PRIMARY PROTOCOL BIT SO
; INTERRUPTS WILL GO TO RIGHT PLACE
IORM T1,ETDSTS(F) ;PUT INTO STATUS
MOVEI T1,PI0ENB+PILDEN+PPCPI ;SETUP PI STATUS PROPERLY
XCT ETDCNO(F) ;DO CONO DTEX,(T1)
MOVEI P2,.EM2EI ;TO-11 INITIAL MESSAGE FUNCTION
;DEVICE CODE DOESNT MATTER
LOAD. P3,ED.ATN,(F) ;GET NUMBER OF ASYNCHRONOUS TTY LINES ON THIS 11
MOVSI T1,(ST.CYC) ;GET 50HZ BIT
TDNE T1,STATES## ;IS IT 50HZ?
TRO P3,EM.50C ;YES, TELL 11
SETZ P4, ;NO POINTER
PUSHJ P,DTEQUE ;SEND THE MESSAGE
POPJ P, ;NO GOOD, GIVE ERROR RETURN
PUSHJ P,DTESDT ;SEND DATE/TIME TO -11
JRST CPOPJ1## ;AND GIVE SKIP RETURN
STXPP2: MOVSI T1,(ED.PPC) ;SET PRIMARY PROTOCOL FLAG
IORM T1,ETDSTS(F)
MOVEI T1,TO11DB+PI0ENB+PILDEN+PPCPI
;RING DOORBELL, ASSIGN PI STUFF
XCT ETDCNO(F) ;RING 11 DOORBELL FOR RESTRICTED 11
IFN FTNET,<
PUSHJ P,NCLUP## ;TELL NCL IT MAY HAVE GOTTEN A NEW NODE
>
JRST CPOPJ1## ;GIVE GOOD RETURN
;ROUTINE TO TEMPORARILY LEAVE PRIMARY PROTOCOL AND ENTER SECONDARY
; PROTOCOL ON THE MASTER 11 OF CALLING CPU. WORKS LIKE P AC SAVE
; ROUTINES, IN THAT PUSHJ TO SAVPPC WILL CAUSE SECONDARY PROTOCOL
; TO RUN, AND WHEN CALLING ROUTINE DOES A POPJ, PRIMARY PROTOCOL
; IS RESTORED. USED IN PARITY SCAN ROUTINES, DIE, AND ANYWHERE
; ELSE THAT NEEDS SECONDARY PROTOCOL TEMPORARILY.
; NOTE THAT THE MASTER DTE'S PI ASSIGNMENT IS CLEARED SO THAT
; THE INTERRUPT SYSTEM IS NOT USED. THEREFORE THE CALLER IS RESPONSIBLE
; TO WAIT FOR EVENTS THAT WOULD OTHERWISE GIVE INTERRUPTS (TRANSMIT DONE, ETC.)
; IF PI ASSIGNMENT WAS LEFT ON, INTERRUPT SERVICE MIGHT STEAL SECONDARY
; PROTOCOL DONE FLAG FROM ORIGINAL LEVEL.
;
; IF SECONDARY PROTOCOL IS ALREADY RUNNING, THIS ROUTINE IS A NO-OP.
; RESPECTS ALL ACS EXCEPT T1,T2,T3
SVPPC:: EXCH F,(P) ;SAVE OLD C(F) ON STACK GET CALLING PC
PUSH P,T4 ;SAVE T4
MOVE T3,F ;SAVE CALLING PC IN T3
PUSHJ P,GTEPD ;GET ETD ADDRESS IN F, EPT IN T4
LOAD. T2,ED.DTN,(F) ;COMPUTE OFFSET TO THE PROPER DTE
ASH T2,3 ;*8
ADD T4,T2 ;ADD TO EPT ADDRESS
MOVSI T2,(ED.PPC) ;IS THERE ANYTHING TO SAVE?
TDNN T2,ETDSTS(F) ;SKIP IF SO
JRST SVPP2 ;NOT, QUIT RIGHT NOW
PUSH P,DTEEPW(T4) ;SAVE EXAMINE PROTECTION WORD
PUSHJ P,ENTSPC ;ENTER SECONDARY PROTOCOL
MOVEI T1,PILDEN+0 ;CLEAR OUT PI ASSIGNMENT
XCT ETDCNO(F) ;CONO DTEN,(T1)
MOVE T4,-1(P) ;GET OLD CONTENTS OF T4
MOVE F,-2(P) ; AND OLD CONTENTS OF F
PUSHJ P,(T3) ;CALL THE CALLER
CAIA ;NON-SKIP RETURN
AOS -3(P) ;SKIP RETURN
PUSHJ P,GTEPD ;SETUP F AND T4 AGAIN. NO NEED TO SAVE
POP P,DTEEPW(T4) ;RESTORE OLD EXAMINE PROTECTION WORD
MOVEI T1,PILDEN+0 ;TURN OFF DTE FOR A WHILE
XCT ETDCNO(F) ;DO IT
MOVEI T1,DT.LSP ;ENTER PRIMARY PROTOCOL, NO RESET
PUSHJ P,SPCMD ;LEAVE
MOVSI T1,(ED.PPC) ;MARK PRIMARY PROTOCOL NOW
IORM T1,ETDSTS(F)
MOVSI T1,(ED.SPC) ;AND TURN OFF SECONDARY
ANDCAM T1,ETDSTS(F)
MOVEI T1,PILDEN+PI0ENB+PPCPI;PRIMARY PI ASSIGNMENT
XCT ETDCNO(F) ;DO IT
SVPP1: POP P,T4 ;T4
PJRST FPOPJ## ;RESTORE F
; AND RETURN WITH OLD PROTOCOL RUNNING
SVPP2: POP P,T4
POP P,F ;RESTORE F, T4
JRST (T3) ;AND RETURN TO CALLER'S PC IMMEDIATELY
;ROUTINE TO CHECK TO SEE IF MASTER IS RUNNING PRIMARY PROTOCOL
; CALL IS
; PUSHJ P,SKPMPP## ;SKIP IF MASTER RUNNING PRIMARY PROTOCOL
; <NOT>
; <IS>
SKPMPP::PUSHJ P,SVEPTD ;SAVE F,T4 & GET MASTER DTE'S CTL BLOCK ADDRESS
MOVSI T4,(ED.PPC) ;DON'T NEED EPT ADDRESS, USE SAVED T4
TDNE T4,ETDSTS(F) ;IS IT PRIMARY?
AOS (P) ;YES
POPJ P, ;RETURN THE RIGHT WAY
SUBTTL ONCE PER SECOND ACTIVITIES
DTESEC::MOVE T1,UPTIME## ;GET UPTIME (COUNT ON IT BEING INCREMENTED
; AT APR CLOCK LEVEL)
CAMGE T1,DTSTIM ;TIME TO TO ONCE A SECOND STUFF?
POPJ P, ;NO, RETURN DOING NOTHING
ADD T1,TICSEC## ;GET WHAT UPTIME SHOULD BE NEXT TIME
MOVEM T1,DTSTIM ;REMEMBER
;(THE ABOVE CODE IS MADE NECESSARY
; BY THE CASE WHERE MANY SECONDS ARE LOST
; DURING PARITY ERROR SWEEP. DTESEC
; WILL GET CALLED ONCE A TICK UNTIL
; ALL THE MISSED TICKS ARE COMPENSATED FOR)
PUSH P,F ;SAVE FOR DTE CONTROL BLOCK
MOVEI T4,0 ;START WITH FIRST DTE
DTESC1: MOVE F,T4 ;GET NEXT DTE # (CPU # ALWAYS ZERO)
;***SMP***
PUSHJ P,GETETD ;GET DTE CONTROL BLOCK ADDRESS
JRST FPOPJ## ;DONE
MOVE T1,ETDSTS(F) ;GET STATUS OF DTE
TLNN T1,(ED.PPC) ;RUNNING PRIMARY PROTOCOL?
AOJA T4,DTESC1 ;NO, DON'T BOTHER WITH THE REST
LOAD. T2,ED.10A,(F) ;GET ADDRESS OF 10'S COMM AREA
TLNE T1,(ED.DTM) ;IS THIS THE MASTER DTE?
AOS ETCKAC(T2) ;YES, INCREMENT THIS CPU'S KEEP ALIVE
; ONLY ONCE PER CALL TO THIS ROUTINE.
; NOTE THAT WE INCREMENT KEEP ALIVE
; EVEN IF -11 IS SICK IF ITS RUNNING
; PRIMARY PROTOCOL. THIS IS IN CASE
; THE -11 IS STILL WELL ENOUGH TO LOOK
TLNE T1,(ED.RLD) ;IS THIS -11 SICK?
AOJA T4,DTESC1 ;YES, DON'T OVERWRITE THE LAST CRASH PC
; WITH PC FROM HERE
LOAD. T2,ED.11A,(F) ;GET ADDRESS OF 11'S COMM AREA
MOVE T3,ETCKAC(T2) ;GET 11'S KEEP ALIVE COUNT
CAME T3,ETDKAR(F) ;DIFFERENT THAN OUR COPY?
JRST [SETZM ETDKAN(F) ;YES, RESET THE HUNG COUNTER
MOVEM T3,ETDKAR(F) ;REMEMBER NEW LAST VALUE
AOJA T4,DTESC1] ;AND GO TO NEXT DTE
AOS T1,ETDKAN(F) ;NO, GET HUNG COUNTER VALUE
CAIG T1,.EDKAE ;HAS IT PASSED MAXIMUM VALUE?
AOJA T4,DTESC1 ;NOT YET, GO TO NEXT DTE
PUSH P,T4 ;SAVE WHERE WE WERE
MOVEI T1,.+1 ;SET T1 UP TO BE PC
PUSHJ P,DTERLD ;RELOAD THIS DTE
POP P,T4 ;RESTORE DTE NUMBER
AOJA T4,DTESC1 ;LOOP
$LOW
DTSTIM: BLOCK 1 ;UPTIME AT NEXT SECOND FOR DTESEC
$HIGH
SUBTTL CORE ALLOCATION
;CALL MESCOR WITH NUMBER OF WORDS DESIRED IN T2
; IF CANT ALLOCATE CORE, RETURN CPOPJ WITH SIZE OF BIGGEST HOLE IN ??
; RETURN CPOPJ1 WITH ADDRESS OF CORE IN T1
; CORE IS CLEARED.
; SEE GETWDS IN CORE1
MESCOR: PUSH P,T2 ;SAVE ARG FOR BLT
PUSHJ P,GETWDS## ;GET SOME CORE
JRST TPOPJ## ;THROW AWAY SAVED ARG AND RETURN
POP P,T2 ;RESTORE NUMBER OF WORDS
HRL T3,T1 ;ADDRESS OF CORE IN LH(T3)
HRRI T3,1(T1) ;ADDRESS + 1 IN RH(T3)
MOVE T4,T1 ;COPY OF ADDRESS
ADDI T4,-1(T2) ;LAST ADDRESS TO CLEAR
SETZM (T1) ;CLEAR FIRST WORD
BLT T3,(T4) ;CLEAR THE REST
JRST CPOPJ1## ;RETURN CPOPJ1 WITH ADDRESS IN T1
;CALL GIVMES WITH ADDRESS OF CORE IN T2, SIZE IN T1
; ALWAYS RETURNS CPOPJ
GIVMES==GIVWDS## ;DITTO
;ROUTINE TO ALLOCATE TO-10 DTE BUFFER USING ED.BSZ, STORE ADDRESS
; OF BUFFER IN ED.BUF, RETURN THE ADDRESS IN T1.
; CALL WITH ETD ADDRESS IN F, NUMBER OF 8 WORD BYTES TO ALLOCATE IN T2.
; STOPCODE IF
; A TO-10 DTE BUFFER IS ALREADY ALLOCATED. SKIP RETURN
; IF SUCCESSFUL, NON-SKIP IF WE RAN OUT OF CORE.
T10GTC: MOVSI T1,(ED.TBA) ;GET TO-10 DTE BUFFER IS ALLOCATED BIT
TDNE T1,ETDBUF(F) ;IS IT THERE?
DEAD10 ;YES, SOMEONE GOOFED
IORM T1,ETDBUF(F) ;NO, ITS GOING TO BE
ADDI T2,^D36/^D8-1 ;ROUND UP TO NEXT WHOLE 36 BIT WORD
ASH T2,-2 ;/4 = NUMBER OF 36 BIT WORDS
STOR. T2,ED.BSZ,(F) ;REMEMBER TO-10 BUFFER SIZE
PUSHJ P,GETWDS## ;GET THAT MUCH
POPJ P, ;LOSE
STOR. T1,ED.BUF,(F) ;REMEMBER WHERE IT IS
JRST CPOPJ1## ;AND SUCCEED
;ROUTINE TO RELEASE TO-10 DTE BUFFER. CALL WITH ETD ADDRESS IN F.
; ALWAYS GIVES NON-SKIP RETURN. OK TO CALL IF TO-10 DTE BUFFER DOESNT
; EXIST.
T10RLC: MOVSI T1,(ED.TBA) ;GET TO-10 BUFFER ALLOCATED BIT
TDNN T1,ETDBUF(F) ;DOES IT EXIST?
POPJ P, ;NO, NO WORK TO DO
ANDCAM T1,ETDBUF(F) ;YES, SAY ITS GONE NOW
LOAD. T1,ED.BSZ,(F) ;GET SIZE TO DEALLOCATE
LOAD. T2,ED.BUF,(F) ;AND ADDRESS
PJRST GIVWDS## ;GOODBY.
SUBTTL 11 DUMP AND RELOAD CONTROL
;ROUTINE TO CLEAR OUT A DTE REGARDLESS OF WHAT ITS DOING
; CALL WITH DTE CONTROL BLOCK ADDRESS IN F
; GIVES PHONEY POSTS TO ALL DRIVERS WHICH HAD PENDING TO-11
; MESSAGES, WHICH SHOULD BE THE SAME AS THOSE MESSAGES ACTUALLY GETTING
; TO THE 11 JUST BEFORE IT DIES.
; ALL TO-11 MESSAGE CORE IS DEALLOCATED, DTE STATE IS CLEARED,
; 11 IS TAKEN OUT OF PRIMARY PROTOCOL IF IT IS THERE. PRESENCE OF
; TO-10 MESSAGES ARE IGNORED.
DTECLR: MOVSI T1,(ED.PPC) ;IF RUNNING PRIMARY PROTOCOL,
TDNE T1,ETDSTS(F) ;
PUSHJ P,LEVPPC ;LEAVE PRIMARY PROTOCOL ON THIS DTE/11
MOVEI T1,CLRDTE+PILDEN+0 ;CLEAR THIS DTE AND ZERO PI ASSIGNMENT
XCT ETDCNO(F)
MOVSI T1,(ED.RLD) ;CLEAR RELOAD BIT
ANDCAM T1,ETDSTS(F) ;SINCE THIS 11 IS NOW QUIET.
LOAD. T4,ED.CUR,(F) ;GET CURRENT TO-11 MESSAGE
SKIPE T4 ;SKIP IF NONE
PUSHJ P,DTEPST ;CALL DRIVER AND DEALLOCATE CORE
SETZ T4, ;CLEAR OUT CURRENT ENTRY
STOR. T4,ED.CUR,(F) ;CLEAR
DTECL1: LOAD. T4,ED.QUE,(F) ;GET NEXT QUEUE ENTRY
JUMPE T4,DTECL2 ;GO FINISH UP, ALL CORE DEALLOCATED
LOAD. T1,EQ.LNK,(T4) ;GET NEXT ITEM IN QUEUE
STOR. T1,ED.QUE,(F) ;MAKE THIS NEW FIRST ITEM
PUSHJ P,DTEPST ;GO CALL DRIVER, DEALLOCATE CORE FOR
; THIS MESSAGE
JRST DTECL1 ;LOOP FOR ALL MESSAGES IN QUEUE
DTECL2: STOR. T4,ED.LST,(F) ;CLEAR OUT PLACE TO PUT NEW QUEUE ENTRIES
LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATUS
CAIGE T1,ED.TWD ;NEED TO NOTIFY A DRIVER OF LOST
; TO-10 INDIRECT DATA?
JRST DTECL3 ;NO
PUSHJ P,SAVE4## ;YES, SAVE P1-P4 FOR CALL TO DRIVER
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER
LOAD. T1,ED.CPN,(F) ;AND CPU NUMBER
HRL P1,T1 ;IN P1
LOAD. P2,ED.XFN,(F) ;GET CURRENT TO-10 FUNCTION
LOAD. T1,ED.XDV,(F) ;AND DEVICE
HRL P2,T1 ;IN P2
LOAD. T1,ED.XLN,(F) ;GET LINE
HRLZ P3,T1 ;LINE,,0 LEFT
LOAD. P4,ED.MSP,(F) ;AND NOW THE IMPORTANT DATA, THE POINTER
; WITH WHICH THE DRIVER DEALLOCATED THE CORE
PUSH P,F ;SAVE F
MOVEI T1,.EMXML ;THE INTERNAL FUNCTION FOR THIS SITUATION
PUSHJ P,DNDSP ;DO NEGATIVE DISPATCH
POP P,F ;RESTORE F
DTECL3: PUSHJ P,DTETID ;MAKE TO-10 DTE SIDE IDLE
MOVEI T1,ED.EID ;MAKE TO-11 DTE SIDE IDLE
STOR. T1,ED.2ES,(F)
;COMM REGION WILL BE RESET THE NEXT
; TIME PRIMARY PROTOCOL IS ENTERED
POPJ P, ;RETURN
;HERE WHEN AN 11 IS DEAD TO INDICATE IT SHOULD BE RELOADED.
; CALL WITH DTE CONTROL BLOCK ADDRESS IN F
;INSTEAD OF BEING CALLED BY PJRST, DO PJSP T1, INSTEAD TO SAVE PC
;SOMEPLACE FOR DEBUGGING PURPOSES.
$LOW ;SYSINI USES SPCMD BEFORE HISEG SETUP
DTERLD::MOVEM T1,DTELCP ;SAVE LAST -11 CRASH PC
MOVEI T1,PILDEN+0 ;ZERO PI ASSIGNMENT SO SICK 11 WON'T
XCT ETDCNO(F) ; KILL US WITH ZILLIONS OF INTERRUPTS
MOVSI T1,(ED.RLD) ;SET RELOAD BIT
IORM T1,ETDSTS(F) ;SO PROGRAM THAT RELOADS CAN SEE
SKIPN T1,DTRJOB ;SKIP IF RELOAD JOB EXISTS
POPJ P, ;NO, RETURN
PJRST WAKJOB## ;WAKE IT UP, IT WILL SEE THE BIT
; (CAN'T GET HERE IF FROM SYSINI)
;HERE FROM COMMON DURING POWER FAILURE
DTEPWF::PUSHJ P,GTEPD ;FIND COMM REGION
LOAD. T2,ED.211,(F) ;FIND CFE'S AREA
MOVSI T1,(EC.PWF) ;"OUR POWER FAILED"
IORM T1,ETCSTS(T2) ;LIGHT IT BEFORE LIGHTS OUT
MOVEI T1,TO11DB
XCT ETDCNO(F) ;TELL -11
POPJ P,
$HIGH
SUBTTL MISCELLANEOUS UTILITY ROUTINES
$LOW
XLIST ;DON'T PRINT LITERALS
LIT
LIST
;ROUTINE TO SETUP DTE CONTROL BLOCK ADDRESS IN F,
; AND STOP IF CPU,,DTE SPEC IS NOT LEGAL.
; CALLED WITH LH(F) EQUAL TO CPU NUMBER (0-CPUN), RH(F) EQUAL TO DTE NUMBER
; (0-DTE'N10'N)
GTETDS::HRRE T1,F ;GET DTE NUMBER
AOSE T1 ;DO NOT ALLOW MASTER TO BE ASKED FOR BY -1
PUSHJ P,GETETD ;GET DTE CONTROL BLOCK ADDRESS
DEAD10 ;SORRY, BAD SPECIFICATION
POPJ P, ;OK, RETURN
;ROUTINE TO GET DTE CONTROL BLOCK ADDRESS IN F, SKIP IF SUCESSFUL.
; CALLED BY GTETDS, DTUGTF (UUO ROUTINE), DTESEC (FOR SCANNING
; THROUGH DTE CONTROL BLOCKS).
; CALL WITH CPU#,,DTE# IN F. IF MASTER DTE IS DESIRED, CALL WITH
; CPU#,,-1 IN F. GIVES NON-SKIP RETURN IF CPU OR DTE NUMBER IS BAD,
; OTHERWISE SKIP RETURN WITH DTE CONTROL BLOCK ADDRESS IN F.
GETETD::HLRZ T1,F ;GET CPU NUMBER
CAIL T1,CPUN## ;IN RANGE?
POPJ P, ;NO, GIVE ERROR INDICATION
PUSHJ P,GTCPUD ;GET CPU DATA BLOCK IN T2
HRRZ T3,F ;JUST DTE NUMBER
CAIN T3,-1 ;DOES CALLER WANT MASTER ETD?
JRST GTETD1 ;YES, PUT C(T2) IN F AND GIVE GOOD RETURN
CAML T3,.CPDTN##(T2) ;IS DESIRED DTE NUMBER LESS THAN NUMBER OF DTES?
POPJ P, ;NO, GIVE ERROR RETURN
SKIPA F,@ETDTAB##(T1) ;YES, ALL IS OK, FETCH PROPER ETD ADDRESS
GTETD1: MOVE F,DTEMAS(T1) ;GET MASTER DTE CONTROL BLOCK ADDR IN F
AOS (P) ;AND SUCCEED (CALLED BY SYSINI, NEED THE
; AOS HERE)
POPJ P, ;RETURN
XLIST ;DON'T PRINT LITERALS
LIT
LIST
$HIGH
;ROUTINE TO GET TWO EIGHT BIT BYTES FROM A MESSAGE, SWAP THEM, AND
; RETURN THEM AS A 16 BIT BYTE. USES ETDMSP(F) FOR BYTE POINTER.
; USES ACS T1,T2
GX2BYT: ILDB T1,T4 ;GET FIRST BYTE
ILDB T2,T4 ;GET SECOND BYTE
LSH T2,^D8 ;MAKE SECOND BYTE FIRST BYTE
IOR T1,T2 ;PUT INTO T1 AND
POPJ P, ;RETURN WITH 16 BIT BYTE
;ROUTINE TO SAVE F AND T4, AND SETUP F WITH DTE CONTROL BLOCK
; ADDRESS OF MASTER DTE ON CALLING CPU, T4 TO EPT ADDRESS OF
; CALLING CPU. SMASHES T1
$LOW
XLIST ;DON'T PRINT LITERALS
LIT
LIST
;USED DURING SYSINI
SVEPTD::EXCH F,(P) ;GET CALLING PC, SAVE F
PUSH P,T4 ;SAVE T4
PUSH P,F ;SAVE CALLING PC ON STACK
PUSH P,T1 ;SAVE T1 AROUND CALL
PUSHJ P,GTEPD ;SETUP DESIRED F AND T4
POP P,T1 ;RESTORE T1
ADJSP P,-1 ;ADJUST STACK POINTER BACK
PUSHJ P,@1(P) ;CALL CALLER
CAIA ;NON-SKIP
AOS -2(P) ;ADJUST FOR SKIP RETURN
POP P,T4 ;RESTORE T4
POP P,F ;AND F
POPJ P, ;AND GO BACK TO META-CALLER
;ROUTINE TO SETUP T4 AND F TO BE EPT ADDRESS AND DTE CONTROL BLOCK ADDRESS
; OF MASTER DTE ON CALLING CPU. SMASHES T1,F,T4
; ENTER AT GTEPT WITH DTE CONTROL BLOCK ADDRESS
; TO GET JUST EPT OFFSET OF DTE'S CPU.
GTEPD: PUSHJ P,GTCPUN ;GET CPU NUMBER OF CALLING CPU
MOVE F,DTEMAS##(T1) ;GET DTE CONTROL BLOCK OF MASTER DTE
GTEPT: MOVE T4,ETDCDB(F) ;GET CDB ADDRESS
MOVE T4,.CPTOS##(T4) ;NOW GET EPT ADDRESS OF CALLING CPU
POPJ P, ;DONE.
;ROUTINE TO RETURN CPU NUMBER OF CALLING CPU IN T1
GTCPUN: SETZ T1, ;ASSUME CPU0
SKPCPU(0) ;IS IT?
MOVEI T1,1 ;NO, ITS CPU1
;***SMP!***
POPJ P, ;EASILY DONE FOR NOW
;ROUTINE TO GET CPU DATA BLOCK FOR CPU WHOSE NUMBER IS IN T1
; RETURNS THE CPU NUMBER IN T1, CPU DATA BLOCK ADDRESS IN T2
GTCPUD: MOVEI T2,.C0CDB## ;ASSUME CPU0
SKIPE T1 ;IS IT? (***SMP***)
IFN FTMS,<
MOVEI T2,.C1CDB## ;YES, GET CPU1'S CDB
>;END IFN FTMS
IFE FTMS,<
DEAD10 ;ONLY ONE
>;END IFE FTMS
POPJ P, ;RETURN
$HIGH
XLIST ;DON'T PRINT LITERALS
LIT
LIST
DTE2EE:
DTE2XE:
STOPCD .,HALT,TXE, ;TO 10/11 ERROR
DEDTEN: STOPCD(.,STOP,D10) ;++DEAD 10
$LOW
DTELCP::0 ;LAST PC ON AN -11 RELOAD
DTRJOB: Z ;JOB TO WAKE ON 11 RELOAD
$LIT
DTEEND: END