Trailing-Edge
-
PDP-10 Archives
-
bb-jr93h-bb
-
7,6/ap021/dteser.x21
There are 3 other files named dteser.x21 in the archive. Click here to see a list.
TITLE DTESER - DTE20 INTERFACE ROUTINES V471
SUBTTL E.SOCCI/EVS/EJW/JBS/DRL/EGF/VJB/SSG 25-OCTOBER-88
SEARCH F,S,NETPRM,DTEPRM,D36PAR,MACSYM
T10SYM ;TO DEFEAT MACSYM
$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 VDTESR,471
;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==71
; THIS WAY, ASSEMBLING THIS MODULE WITH WRONG VERSION OF DTEPRM FOR SOME REASON
; (LIKE FORGETTING TO ASSEMBLE IT) WILL CAUSE ASSEMBLY TO TERMINATE
; THIS SCHEME DOES NOT CAUSE EXTRA EDITING, SINCE ONLY FILES
; WHICH NEED THE CHANGES NEED PRMMIN TO BE UPDATED. MODULES
; THAT DO NOT NEED A NEW VERSION OF DTEPRM NEED NOT DEMAND IT.
IFL VDTPRM-PRMMIN,<PRINTX ?PLEASE USE LATEST VERSION OF DTEPRM
PASS2
END>
SALL ;CLEAN MACRO EXPANSIONS
ENTRY DTESER
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 THE QUEUED PROTCOL VERSION 1 AND
; QPRV2.MEM FOR THE CHANGES IN VERSION 2.
;
;DTESER NOW DEALS WITH BOTH VERSIONS OF THE DTE'S PROTOCOL.
; THE PROTYP FIELD (AS DEFINED IN QPRV2.MEM) CONTAINS THE PROTOCOL
; TYPE IN USE (THIS FIELD IS CALLED EC.PRT IN THE DTEPRM COMM AREA
; DEFINITIONS). THE VALUE OF THIS FIELD IS 0 FOR THE OLD PROTOCOL
; AND 1 FOR THE NEW MCB (QPR V2) ONE.
;
;THE FOLLOWING COMMENTS DEAL WITH QPR V1.
;
;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)
;This module searches D36PAR for symbols, but does not use the LOAD
;and STOR functions they expect. Thus we make the following checks to
;assure that the MOVEs in this module will be OK.
;The assignment under IFE FTDECNET is to allow the module to compile
;without searching D36PAR, which is under IFN FTDECNET. Note that the
;code does not run this way that we should feature test out all the
;DECnet code. That would require more testing, though. The value
;400000 is intended to cause an IME if the DECnet code is exercised at
;the wrong time.
DEFINE CHKWRD(prefix,symbol),<
IFN prefix'symbol+1,<PRINTX ?prefix'symbol MUST BE A FULL-WORD FOR DTESER>
IFE FTDECNET,<prefix'.'symbol==400000>
>
CHKWRD (MD,NXT)
CHKWRD (MD,BYT)
CHKWRD (MD,AUX)
CHKWRD (MD,ALA)
SUBTTL DTE20 INITIALIZATION ROUTINES
;ROUTINE TO INITIALIZE ALL DTES ON A CPU
; CALL WITH CPU NUMBER IN T1
DTEINI::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 DOESN'T EXIST
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
MOVE T2,.CPTTD## ;GET M'N'TTDN
STOR. T2,ED.ATN,(F) ;STORE NUMBER OF TERMINALS IN ETD
AOJA P1,DTEIN1 ;LOOP ON
DTEIN2: SKIPN P2 ;HAS A MASTER BEEN LOCATED AT ALL?
STOPCD .,STOP,DTEMDM, ;++NO MASTER DTE
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
MOVX 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,.CPEPT## ;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,(XPCW) ;THE RIGHT INSTRUCTION TO CATCH A DOUBLE WORD PC
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
ANDI T3,377 ;JUST CHAR AND PARITY
MOVEI T1,DT.MTO(T3) ;STORE IN DTECMD
PUSHJ P,SPCMD ;DO THE COMMAND
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO GET DATE/TIME FROM -20F
;CALL WITH:
; PUSHJ P,SPCGDT
; NOT CAPABLE OR FAILED OR NOT VALID
; SUCCEEDED, LOCxxx UPDATED
SPCGDT::MOVE T1,.CPSPF## ;GET OUR SECONDARY PROTOCOL FLAGS
TRNE T1,DF.GDT ;DOES THIS -20F SUPPORT DT.GDT?
POPJ P, ;NO, ERROR RETURN
PUSHJ P,GTEPT ;GET EPT OFFSET FOR CFE
SETOM .EPDTM##(T4) ;ASSUME FAILURE
MOVE T1,[.EPDTM##*1B19+DT.GDT] ;COMMAND FOR -20F
PUSHJ P,SPCMD ;BEG, GROVEL, AND WHINE
SKIPLE T1,.EPDTM##(T4) ;DID WE GET A VALID RESULT?
TDNN T1,[177777B19] ;YES, IS THE VALIDITY FLAG SET?
POPJ P, ;NO, WE FAILED
ANDI T1,177777 ;GET YEAR
MOVEM T1,LOCYER## ;STORE IT
LDB T1,[POINT 8,.EPDTM##+1(T4),11] ;MONTH
AOJ T1, ;MAKE JAN = 1
MOVEM T1,LOCMON## ;STORE IT
LDB T1,[POINT 8,.EPDTM##+1(T4),19] ;DAY
AOJ T1, ;MAKE THE FIRST = 1
MOVEM T1,LOCDAY## ;STORE DAY
; LDB T1,[POINT 8,.EPDTM##+1(T4),27] ;DAY OF WEEK 0 = MONDAY
; LDB T1,[POINT 8,.EPDTM##+1(T4),35] ;DST FLAG
LDB T1,[POINT 16,.EPDTM##+2(T4),19] ;SECONDS SINCE MIDNIGHT /2
LSH T1,1 ;SECONDS
IDIVI T1,^D60 ;MAKE SECONDS INTO THIS MINUTE
MOVEM T2,LOCSEC## ;STORE SECOND
IDIVI T1,^D60 ;EXTRACT HOUR AND MINUTE
MOVEM T1,LOCHOR## ;HOUR
MOVEM T2,LOCMIN## ;MINUTE
JRST CPOPJ1## ;DONE
;ROUTINE TO RETURN SECONDARY PROTOCOL FLAGS IN .CPSPF.
;PRESERVES ALL ACS
SPCGSF: PUSHJ P,SAVT## ;SAVE SOME ACS
SETZ T3, ;GET AN (EVEN PARITY) NULL
PUSHJ P,SPCTYO ;TYPE IT SO WE CAN GET THE DONE FLAG
MOVE T4,.CPEPT## ;GET ADDRESS OF EPT FOR THIS CPU
SKIPN T1,DTEMTD(T4) ;GET THE DONE FLAG (CONTAINS ^-NEW FEATURES)
JRST .-1 ;WAIT FOR IT
SETZM DTEMTD(T4) ;GOT THE FEATURES MASK, CLEAR DONE
MOVEM T1,.CPSPF## ;SAVE FLAGS FOR LATER USE
POPJ P, ;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
PUSH P,T1 ;SAVE COMMAND
CAIN T1,DT.ESP ;ENTERING SECONDARY PROTOCOL IS OK IF
; NOT IN SECONDARY PROTOCOL
JRST SPCMD1 ;SO DON'T CHECK
MOVSI T1,(ED.SPC) ;IS SECONDARY PROTOCOL RUNNING ON THIS DTE?
TDNN T1,ETDSTS(F) ;?
JRST TPOPJ## ;NO
SPCMD1: SETZM DTEFLG(T4) ;CLEAR DONE FLAG
CONI PI,T1 ;PI STATUS
CONO PI,PI.OFF ;NO, TURN OFF SO WE GET TO PUT COMMAND
; IN AND RING DOORBELL, ENSURING THAT 11
; WILL SEE SO A HIGHER LEVEL CAN CHECK DTEFLG
EXCH T1,(P) ;SAVE PI STATE, RESTORE COMMAND
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,PI.ON ;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 & SGET DTE CTL ADDR, EPT ADDR
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
HRRZ U,.CPCTN## ;POINT U TO CTY
SKIPN DINITF## ;SYSTEM INITIALIZING?
SKIPN LINTAB##(U) ;HAVE AN LDB ADDRESS?
POPJ P, ;ONCE TYPEIN/OUT HANDLED DIFFERENTLY
SKIPN T1,DTEMTI(T4) ;CHECK FOR INPUT READY
JRST SPCODI ;NO INPUT--CHECK FOR OUTPUT DONE
MOVE T3,DTEF11(T4) ;WAS INPUT READY, GET CHAR IN T3
SETZM DTEMTI(T4) ;CLEAR INTERLOCK SO CAN GET ANOTHER CHARACTER
ANDI T3,CK.CHR ;KEEP ONLY CHARACTER
PUSHJ P,RECINT## ;AND CALL SCNSER
PUSHJ P,GTEPD ;SETUP F AND T4 AGAIN
SETZ T1, ;CLEAR T1 AGAIN TO CHECK FOR OUTPUT DONE
HRRZ U,.CPCTN## ;POINT U TO CTY
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 TPOPJ## ;NO
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
JRST CPOPJ1## ;AND GIVE OUTPUT DONE RETURN
SUBTTL CAL11. UUO
; CAL11. UUO DISPATCH FOR RSX-20F AND MCB DTES
;
; CALLING SEQUENCE IS:
; MOVE AC,[XWD LENGTH,BLOCK]
; CAL11. AC,
; ERROR RETURN
; OK RETURN
;
; BLOCK: EXP FUNCTION CODE
; ARGUMENT (1) ...
;
;
; ENTER FROM COMDEV WITH P1 CONTAINING CPU#,,DTE# AND DTE BASE IN W
;
; COMDEV DOES THE DISPATCH BASED ON THE FOLLOWING TABLE. THE HIGH
; ORDER BIT, IF SET, INDICATES THAT THE USER MUST HAVE THE "POKE" PRIV.
C1120F:
C11MCB: XWD 400000,ECOD2## ;(0) DEPOSIT TO -11
XWD 400000,ECOD2## ;(1) EXAMINE THE -11
XWD 400000,ECOD2## ;(2) ERROR (IN DC76: QUE11)
XWD 0,NAME11 ;(3) RETURN NAME OF PGM IN 11
XWD 0,DOWN11 ;(4) IS PORT UP OR DOWN?
XWD 400000,ECOD2## ;(5) SEND MESSAGE
XWD 400000,ECOD2## ;(6) RECEIVE MESSAGE
XWD 0,TYPE11 ;(7) NODE & TYPE
MC1120==.-C1120F ;LENGTH OF 20F VECTOR
MC11MC==.-C11MCB ;LENGTH OF MCB VECTOR
;COME HERE TO RETURN THE NAME OF THE PDP-11 PROGRAM.
NAME11: MOVE F,P1 ;COPY CPU#,,DTE#
PUSHJ P,GETETD ;FIND THE ETD
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,ETDSTS(F) ;GET STATUS WORD
TLNN T1,(ED.DTX) ;DOES THIS FE REALLY EXIST?
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,DLXNMT##(W) ;PICK UP NAME
PJRST STOTC1## ;SKIP RETURN, GIVING NAME
;COME HERE TO TELL THE STATUS OF THE PDP-11 PROGRAM.
DOWN11: MOVE F,P1 ;COPY CPU#,,DTE#
PUSHJ P,GETETD ;FIND THE ETD
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,ETDSTS(F) ;GET STATUS WORD
TLNN T1,(ED.DTX) ;DOES THIS FE REALLY EXIST?
JRST ECOD20## ;ILLEGAL PORT NUMBER
TLNE T1,(ED.PPC) ;PRIMARY PROTOCOL DOWN
TLNE T1,(ED.RLD) ; OR THE RELOAD BIT SET?
TDZA T1,T1 ;SAY THE -11 IS DOWN
MOVEI T1,1 ;INDICATE UP
PJRST STOTC1## ;SKIP RETURN
;HERE TO REPORT NODE & TYPE
TYPE11: MOVE F,P1 ;COPY CPU#,,DTE#
PUSHJ P,GETETD ;FIND THE ETD
JRST ECOD20## ;ILLEGAL PORT NUMBER
MOVE T1,ETDSTS(F) ;GET STATUS WORD
TLNN T1,(ED.DTX) ;DOES THIS FE REALLY EXIST?
JRST ECOD20## ;ILLEGAL PORT NUMBER
HRRZ T1,DLXTYP##(W) ;GET TYPE OF FRONT END
CAIN T1,.C1CFE ;RSX-20F?
PJRST STOTC1## ;NO NODE NUMBER, SO JUST RETURN
SE1ENT ;DECNET STUFF IN NON-ZERO SECTION
SKIPE T2,ETDLBK(F) ;GET ADDRESS OF DLL BLOCK
LOAD T2,DLUID,(T2) ;GET ADDRESS OF ROUTER CONTROL BLOCK
JUMPE T2,TYP11A ;AVOID IME
LOAD T1,RCAJQ,(T2) ;GET ADJACENCY BLOCK ADDRESS
JUMPE T1,TYP11A ;JUMP IF NO ADJACENCY (NO NODE NUMBER)
LOAD T2,AJNAN,(T1) ;NOW GET THE NODE NUMBER
LOAD T1,AJNAA,(T1) ;AND NODE AREA
LSH T1,^D10 ;POSITION IT
IOR T1,T2 ;COMBINE IN T1
TYP11A: HRL T1,DLXTYP##(W) ;GET TYPE AGAIN
MOVSS T1 ;MAKE IT NODE,,TYPE
PJRST STOTC1## ;AND RETURN
; ROUTINE TO SET THE CAL11. UUO DISPATCH VECTOR POINTER
; MOVE F, ETD
; MOVE T1, CAL11. DISPATCH ADDRESS
; CALL: PUSHJ P,C11VEC
; RETURN ;ALWAYS
;
C11VEC: PUSH P,W ;SAVE W
MOVE W,ETDDLX(F) ;POINT TO THE BASE TABLE
MOVEM T1,DLXCAL##(W) ;SET ADDRESS
JRST WPOPJ## ;RESTORE W AND RETURN
SUBTTL DTE FEK (GENERIC)
DFKDSP::CAIE T1,FF.SEC ;SEE IF ONCE-A-SECOND CALL
POPJ P, ;NO--IGNORE WHAT WE DON'T CARE ABOUT
POPJ P, ;**** TEMP **** CHECK FOR DN60S HERE
;HERE TO SETUP FEK INFORMATION FOR A DTE
;CALL WITH ETD IN F AND LINE-USER IN T2
;RETURN CPOPJ WITH A VALID LINE-USER IN T2 ('NOBODY' OR UNCHANGED)
DFKSET::SKIPL T2 ;IN RANGE?
CAILE T2,DD.MAX ;BOTH WAYS?
DFKSE0: SETZ T2, ;NO, USE 'NOBODY'
CAIE T2,DD.NOB ;IF NOBODY
CAIN T2,DD.PRO ;OR PROGRAM
JRST DFKSE1 ;IT'S ALWAYS OK
MOVSI T1,(ED.DTM) ;IS THIS THE MASTER DTE?
TDNE T1,ETDSTS(F) ;CHECK
SETZ T2, ;YES, USE 'NOBODY' AFTER ALL
DFKSE1: MOVE T1,ETDDLX(F) ;POINT TO DS'N'M'BS
MOVE T3,DLXFEK##(T1) ;AND TO THE FEK
MOVSI T4,^-7 ;MASK FOR NON-CPU BITS IN LH
ANDCAM T4,FEKUNI(T3) ;CLEAN UP AFTER PREVIOUS USERS
MOVEM T2,ETDUSR(F) ;STORE NEW VALUE FOR THE CALLER
CAIN T2,DD.PRO ;IF PROGRAM MODE,
HRLM J,ETDUSR(F) ;REMEMBER WHICH USER
JRST @.+1(T2) ;SETUP THE FEK DATA
IFIW DFKUSR ;RSX20F
IFIW D8SUSR## ;ANF10
IFIW DFKMCB ;DECNET
IFIW DFKPRO ;PROGRAM
IFIW D6SUSR## ;IBM
REPEAT DD.MAX-DD.IBM,<IFIW DFKUSR> ;UNKNOWN ENTRIES?
DFKNAM::SIXBIT |NOBODY|
SIXBIT |ANF10|
SIXBIT |DECNET|
SIXBIT |MAINT|
SIXBIT |DN60|
IFN DD.MAX-<.-DFKNAM>+1,<PRINTX ? DFKNAM IS WRONG>
DFKUSR::TDZA T2,T2 ;INDEX SHOULD BE RESET TO 'NOBODY'
DFKMCB: SKIPA T4,[.C1MCB] ;TYPE OF FE
DFKPRO: MOVEI T4,.C1CFE ;TYPE OF FE
MOVEM T4,DLXTYP##(T1) ;SET ITS TYPE
MOVE T4,ETDSTS(F) ;GET THE STATUS
TLNE T4,(ED.DTM) ;IF THE REAL CFE,
SKIPA T4,['RSX20F'] ;SAY SO (NOT 'NOBODY')
MOVE T4,DFKNAM(T2) ;NO--GET TYPE NAME TO USE
MOVEM T4,DLXNMT##(T1) ;SET NAME
MOVE T4,[PUSHJ P,DFKDSP] ;GENERIC INSTRUCTION
MOVEM T4,FEKDSP(T3) ;SET UP ITS DISPATCH INFO
MOVE T4,[MC11MC,,C11MCB] ;GET MCB CAL11. INFO
IFN <C11MCB-C1120F>!<MC11MC-MC1120>,<
CAIE T2,DD.DEC ;IF A DECNET FE,
MOVE T4,[MC1120,,C1120F] ;ELSE USE RSX20F CAL11. INFO
> ;END CHECK FOR DIFFERING CAL11. VECTORS
MOVEM T4,DLXCAL##(T1) ;SET IT THAT WAY
SKIPN T2 ;IF DFKUSR ENTRY,
SETZM ETDUSR(F) ;MAKE SURE ETD INFO IS RIGHT
CAIE T2,DD.DEC ;UNLESS DECNET,
POPJ P, ;NOW WE'RE DONE MESSING UP THE FEK
;Now that we know we are setting the user to DECNET, lets let DECnet
;know so that when the protocol comes up, ROUTER will be ready.
DFKSLD: MOVX T3,LILXC!FLD(LD.DTE,LIDEV) ;BUILD A LINE ID FOR THIS DTE
LOAD. T1,ED.CPN,(F) ;GET THE CPU#
STOR T1,LIKON,+T3 ;SAVE AS KONTROLLER NUMBER
LOAD. T1,ED.DTN,(F) ;GET THE DTE#
STOR T1,LIUNI,+T3 ;SAVE AS THE UNIT NUMBER
MOVEI T1,DI.ICB ;OPEN THIS CIRCUIT
PUSHJ P,CALUSR ;CALL THE DRIVER
PJRST DFKSE0 ;FAILURE--RESET TO 'NOBODY'
MOVEI T2,DD.DEC ;SUCCESS, RESTORE LINE USER
POPJ P, ;RETURN WITH TYPE ACTUALLY SET IN T2
SUBTTL DTE. UUO
;CALL TO DTE. UUO IS:
; MOVE AC,<FUNCTION,,ADDR>
; DTE. AC,
; <ERROR RETURN>
; <OK RETURN>
UDTE:: PUSHJ P,SAVE2##
HRR M,T1 ;ADDRESS OF PARAMETER BLOCK
HLRE P1,T1 ;GET FUNCTION CODE
MOVSI T1,JP.POK ;DISALLOW UNLESS PRIVILEGED
PUSHJ P,PRVBIT## ;IS HE?
SKIPA ;IS
JRST DTUNPE ;ERROR, NO PRIVILEGES
CAML P1,[EXP DTUCDS-DTUDSP] ;SKIP IF SMALLER THAN SMALLEST LEGAL
CAILE P1,MXDTFN ;OUT OF RANGE?
JRST DTUFNE ;YES, FUNCTION NUMBER ERROR
MOVE T1,DTUDSP(P1) ;GET FUNCTION AND FLAGS
TXNN T1,DF.OWN ;DO I HAVE TO BE OWNER??
JRST DTE.1 ;NOPE, DON'T BOTHER CHECKING USER
PUSHJ P,DTUGTF ;YES, SET UP F FROM CPU,,DTE IN ARG BLK
MOVE T1,DTUDSP(P1) ;RESTORE FUNCTION AND FLAGS
HRRZ T2,ETDUSR(F) ;GET THE LINE'S USER
CAIE T2,DD.PRO ;IS IT PROGRAM MODE?
JRST DTE.1 ;NO, ANYBODY MAY USE IT
HLRZ T2,ETDUSR(F) ;YES, GET THE JOB NUMBER
CAME J,T2 ;IS IT THE SAME AS OUR CURRENT JOB
JRST DTUWRU ;ERROR: WRONG USER FOR FUNCTION
DTE.1: TXNE T1,DF.GTF ;SHOULD WE CALL DTUGTF??
PUSHJ P,DTUGTF ;YES, SET UP F FROM CPU,,DTE IN ARG BLK
PUSHJ P,@DTUDSP(P1) ;DISPATCH BY FUNCTION
SOS (P) ;UUO FAIL RETURN
SETZ F, ;CLEAR F FOR UUOXIT
JRST CPOPJ1## ; AND RETURN
;DISPATCH TABLE FOR DTE. UUO
DEFINE FUNCT(ADDR,FLAGS),<
..TEMP==0
IRP <FLAGS>,<..TEMP==..TEMP!DF.'FLAGS>
EXP ..TEMP+ADDR
>
;THESE ARE THE FLAGS USED BY THE DTE. PROCESSORS
DF.GTF==1B0 ;CALL DTUGTF BEFORE CALLING PROCESSOR
DF.OWN==1B1 ;MUST BE OWNER OF THE LINE
DTUCDS: ;MIN LEGAL FUNCTION
DTUDSP: FUNCT DTUCLR,<GTF,OWN> ;(0)CLEAR A DTE
FUNCT DTUSTR,<GTF,OWN> ;(1)START A DTE
FUNCT DTUSTB,<GTF,OWN> ;(2)SET TO-10 BYTE POINTER
FUNCT DTUSEB,<GTF,OWN> ;(3)SET TO-11 POINTER
FUNCT DTUGRW,<GTF> ;(4)GET ROM WORD
FUNCT DTUGMN,<GTF> ;(5)GET MASTER DTE NUMBER
FUNCT DTUPRB,<GTF,OWN> ;(6)PRESS RELOAD BUTTON
FUNCT DTUGST,<GTF> ;(7)GET STATUS
FUNCT DTUSRJ ;(10)SET RELOAD JOB
FUNCT FEDGET## ;(11)GET FRONT END DEVICE
FUNCT FEDUIN## ;(12)FED INPUT
FUNCT FEDUOU## ;(13)FED OUTPUT
FUNCT FEDUGS## ;(14)GET FED STATUS
FUNCT FEDUSS## ;(15)SET FED STATUS
FUNCT FEDGIV## ;(16)RELEASE FED
FUNCT DTURLC,<GTF> ;(17)RELEASE KLE CHUNKS
FUNCT DTURTM,<GTF> ;(20)RESET KL ERROR TIMER
FUNCT DTUTTD,<GTF> ;(21)CONVERT TO TTY NUMBERS
FUNCT DTUSLU,<GTF,OWN> ;(22)SET LINE'S USER
FUNCT DTURLU,<GTF> ;(23)READ LINES USER
FUNCT DTULDS,<GTF,OWN> ;(24)LOAD SECONDARY BOOTSTRAP
FUNCT DTUDMP,<GTF,OWN> ;(25)DUMP
FUNCT DTUKLP,<GTF> ;(26)REPLACE KLINIK PARAMS
FUNCT DTUKPR,<GTF> ;(27)READ KLINIK PARAMS
MXDTFN==.-DTUDSP-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 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
ERCODE DTUIUN,DTEIU% ;(23)ILLEGAL USER NAME
ERCODE DTUWRU,DTEWU% ;(24)WRONG USER FOR FUNCTION
ERCODE DTUNEV,DTEEV% ;(25)NO EVM AVAILABLE FOR FUNCTION
ERCODE DTUIBP,DTEIP% ;(26)ILLEGAL BYTE POINTER
;DTE. FUNCTION (#0) TO CLEAR A DTE
; ADDR/CPU#,,DTE#
; CAUSES DTE TO LEAVE PRIMARY PROTOCOL. ALSO CLEARS ED.RLD.
;
; NOTE THAT THIS FUNCTION CAN BE DONE BY ANY PRIVILEGED PROGRAM
; EVEN IF HE IS NOT THE OWNER OF THE LINE. ONCE THE DTE HAS BEEN
; HALTED (CLEARED), THE PROGRAM MAY SET THE USER OF THE LINE TO
; WHATEVER HE WANTS.
DTUCLR: PUSHJ P,DTECLR ;GO CLEAR OUT THE DTE
PUSHJ P,DFKSE0 ;SET LINE'S USER TO NOBODY AND TELL THE FEK
JRST CPOPJ1## ;GIVE SKIP RETURN
;DTE. FUNCTION (#1) TO START PROTOCOL ON A DTE
; ADDR/CPU#,,DTE#
DTUSTR: MOVE T1,ETDSTS(F) ;GET DTE STATUS
TLNE T1,(ED.PPC) ;ALREADY RUNNING PRIMARY PROTOCOL?
JRST DTUARP ;YES, GIVE AN ERROR RETURN
HRRZ T2,ETDUSR(F) ;GET THE USER OF THE DTE
CAIN T2,DD.DEC ;IS IT DECNET?
JRST DTUSTM ;YES, GO INITIALIZE Q.P. V2
TLNN T1,(ED.DTM) ;IF NOT MASTER,
CAIE T2,DD.NOB ;AND UNKNOWN USER,
TRNA ;(NO)
JRST DTUSTM ;THEN ACT LIKE IT'S AN MCB
TLNE T1,(ED.DTM) ;IF MASTER,
PUSHJ P,[PUSHJ P,ENTSPC ;GO INTO SECONDARY PROTOCOL FIRST
PUSHJ P,CLRDSN## ;FORGET DISK DRIVE SERIAL NUMBERS
PJRST TTDRLD##] ;AND RESTART -20F LINES
MOVEI T1,.M20F ;SPECIFY 20F TYPE PROTOCOL (MEANS ANF, TOO)
LOAD. T2,ED.211,(F) ;POINT TO TO-11 SECTION
STOR. T1,EC.PRT,(T2) ;STORE THE PROTOCOL TYPE
LOAD. T2,ED.210,(F) ;POINT TO TO-10 SECTION
STOR. T1,EC.PRT,(T2) ;STORE PROTOCOL TYPE HERE, ALSO
PUSHJ P,STXPPC ;START UP PRIMARY PROTOCOL
JRST DTUSTE ;SOMETHING WENT WRONG, WE CAN'T START IT
MOVE T1,ETDSTS(F) ;DTE STATUS
TLNE T1,(ED.DTM) ;ARE WE TALKING TO MASTER?
PUSHJ P,KPSSND ;SEND KLINIK PARAMETERS
JFCL ;NOT SERIOUS (OLD VERSION OF 20F)
JRST CPOPJ1## ;SIGNAL SUCCESSFUL START
;HERE TO INITIALIZE QUEUED PROTOCOL VERSION 2. USED WITH THE MCB.
DTUSTM: PUSHJ P,DTECLR ;CLEAR THE STATE
MOVEI T1,.MMCB ;USE MCB PROTOCOL TYPE
LOAD. T2,ED.211,(F) ;GET POINTER TO 11 REGION
STOR. T1,EC.PRT,(T2) ;STORE THE PROTOCOL TYPE
LOAD. T2,ED.210,(F) ;GET POINTER TO 10 REGION
STOR. T1,EC.PRT,(T2) ;STORE IT HERE, TOO
PUSHJ P,STXPPC ;START UP THE PROTOCOL
TRNA ;COULDN'T INITIALIZE
JRST CPOPJ1## ;RETURN SUCCESS
PUSHJ P,DTECLR ;WE COULDN'T INITIALIZE, SO LEAVE THE
; DTE IN A DEAD STATE
PJRST DTUSTE ;SOMETHING WENT WRONG, WE CAN'T START IT
;DTE. FUNCTION (#2) TO SET TO-10 BYTE POINTER IN EPT
; ADDR/CPU#,,DTE#
; ADDR+1/<BYTE POINTER>
DTUSTB: 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,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: 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: 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#
DTUPRB: TLNE T1,(ED.PPC) ;RUNNING PRIMARY PROTOCOL?
JRST DTUARP ;ALREADY RUNNING PROTOCOL
PUSHJ P,PRSRLD ;PRESS RELOAD BUTTON
JRST DTUDEE ;NO ELEVEN DOORBELL BACK
JRST CPOPJ1## ;WE MADE IT.
;DTE FUNCTION #7, GET STATUS WORD.
DTUGST: 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: 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: MOVEI T1,.KLETM+1 ;RESET TIMER
MOVEM T1,.CPETM## ;FIRST, THEN
SKIPN .CPEAD## ;MAKE SURE THE CORE IS REALLY THERE
JRST DTUTME ;SORRY, IT'S NOT AVAILABLE
JRST CPOPJ1## ;OK, RETURN
;FUNCTION #21, RETURN -20F LINE #'S FOR CPU,,DTE
DTUTTD: PJRST TTDDLN## ;FINISH UUO IN TTDINT
;DTE. FUNCTION (#22) TO SET LINES USER
; ADDR/ CPU#,,DTE#
; ADDR+1/ 'NAME' OF USER
DTUSLU: MOVSI T2,(ED.PPC!ED.SPC) ;BITS THAT MEAN WE'RE NOT HALTED
; NOTE THAT WE DID NOT INCLUDE ED.MAI
; BECAUSE WE GO FROM MAINT MODE TO
; PPC WHEN WE SET LINE USER TO DECNET
TDNE T2,ETDSTS(F) ;ARE WE DOING ANYTHING?
PJRST DTUARP ;CANNOT SET - LINE IS RUNNING SOMETHING
PUSHJ P,GETWD1## ;GET THE NAME TO SET
SETZ T2, ;START WITH ZERO
DTUSL1: PUSHJ P,KONUSN## ;IDENTIFY USER NAME
JRST DTUIUN ;ILLEGAL USER NAME
PUSH P,T2 ;SAVE INTENDED USER
PUSHJ P,DFKSET ;SET-UP THE FEK INFO
POP P,T2 ;RESTORE INTENDED LINE USER
HRRZ T1,ETDUSR(F) ;SEE WHAT GOT SET
CAIE T1,(T2) ;WAS IT THE SAME?
JRST DTUIUN ;GIVE ERROR IF DRIVER NOT LOADED
CAIE T2,DD.DEC ;SKIP RESET IF DECNET
PUSHJ P,DTECLR ;OTHERWISE JUST CLEAN THINGS UP
PJRST CPOPJ1## ; AND RETURN
;DTE FUNCTION (#23) TO READ LINE'S USER
; ADDR/ CPU#,,DTE#
; ADDR+1/ 'NAME' OF USER
; ADDR+2/ JOB NUMBER IF USER IS 'PROGRA'
DTURLU: HRRZ T1,ETDUSR(F) ;GET THE USER OF THE LINE FROM ETD BLOCK
MOVE T1,DTNAME##(T1) ; FROM THAT GET THE SIXBIT NAME
PUSHJ P,PUTWD1## ;GIVE THE USER NAME
HLRZ T1,ETDUSR(F) ;GET THE JOB NUMBER (ZERO IF NOT DD.PRO)
AOS (P) ;GIVE GOOD RETURN
PJRST PUTWD1## ;GIVE USER THE JOB NUMBER AND RETURN
;DTE FUNCTION (#24) TO LOAD SECONDARY BOOTSTRAP
; ADDR/ CPU#,,DTE#
; ADDR+1/ BP TO SECONDARY LOADER
; ADDR+2/ LENGTH OF LOADER IN BYTES
DTULDS: PUSHJ P,DTECLR ;CLEAR DTE
MOVE J,.CPJOB## ;ANF CAN CLOBBER J
PUSHJ P,PRSRLD ;PRESS RELOAD BUTTON
JRST DTUDEE ;ROM RELOAD FAILURE
MOVEI T1,PI0ENB+PILDEN ;ENABLE TRANSFERING (PI 0)
XCT ETDCNO(F) ;DO THE CONO
PUSHJ P,GETWD1## ;GET NEXT WORD (BYTE POINTER)
MOVE P1,T1 ;PRESERVE IT
LDB T1,[POINT 6,T1,11] ;GET BYTE SIZE
CAIE T1,^D16 ;MAKE SURE BYTESIZE IS .LE. 16 BITS, OR ELSE WE
JRST DTUIBP ; MIGHT CLOBBER THE E-BUS
PUSHJ P,GETWD1## ;GET COUNT
MOVE P2,T1 ;PRESEVE THIS ALSO
DMOVE T1,P1 ;SET UP FOR CALL
PUSHJ P,DTUEBP ;MAP EVM FROM THIS BP AND COUNT
JRST DTUNEV ;NO EVM LEFT, GIVE ERROR
MOVEM T3,@ETDEBP(F) ;STORE TO-11 BYTE POINTER
PUSHJ P,WAIT11 ;WAIT FOR TO11DB
JRST DTUDDE ;TIMED OUT, GIVE ERROR
MOVEI T1,TO11DB ;RING THE 11 DOORBELL TO
XCT ETDCNO(F) ; START THE LOAD
JRST CPOPJ1## ;RETURN NICELY
;DTE FUNCTION (#25) TO GET A DUMP FROM A PRE-LOADED DUMPER
; ADDR/ CPU#,,DTE#
; ADDR+1/ BP TO DUMP AREA
; ADDR+2/ NUMBER OF BYTES TO DUMP
DTUDMP: PUSHJ P,GETWD1## ;GET THE BP TO DUMP AREA
MOVE P1,T1 ;SAVE DUMP AREA POINTER
LDB T1,[POINT 6,T1,11] ;GET BYTE SIZE
CAIL T1,^D16 ;CHECK FOR A REASONABLE BYTE POINTER, ANYTHING
CAILE T1,^D36 ; LESS THAN 16 BITS JUST DOESN'T CUT IT, 'CAUSE
JRST DTUIBP ; WE ONLY DO BOOT TRANSFERS IN WORD MODE
PUSHJ P,GETWD1## ;GET COUNT OF BYTES TO BE DUMPED
MOVE P2,T1 ;PRESERVE COUNT
DMOVE T1,P1 ;SET UP FOR EVM CALL
PUSHJ P,DTUEBP ;MAP THE USERS DUMP BUFFER
JRST DTUNEV ;NO EVM LEFT, GIVE ERROR
MOVEI T1,PI0ENB+PILDEN ;ENABLE TRANSFERING (PI 0)
XCT ETDCNO(F) ;DO THE CONO
MOVE T2,P2 ;GET THE BYTE COUNT
MOVE T1,T3 ;MOVE FOR DNDDMP
PUSHJ P,DNDDMP ;DO DUMP
JRST DTUDDE ;DUMP TIMED OUT
JRST CPOPJ1## ;GIVE GOOD RETURN
;DTE. FUNCTION (#26) TO CHANGE KLINIK PARAMS ON A DTE
; ADDR/CPU#,,DTE#
; +1/BC,,ADDR OF STRING
; STRING: BYTE(16)LEN,OPEN SSM(8)OPEN MM,YY,0,DD(16)CLOSE SSM(8)CLOSE MM,YY,
; 0,DD,CONSOLE MODE,KL MODE,A,P,S,S,D,W
; WHERE: KL MODE = 0 DISABLED, = 1 REMOTE CTY, = -1 USER MODE
; CONSOLE MODE = 1 OPERATOR, 3 PROGRAMMER, 7 MAINTENANCE.
; LEN = # OF BYTES TO FOLLOW (MUST MATCH -20F)
; SSM IS SECONDS SINCE MIDNIGHT/2
; AND EACH PAIR OF BYTES IN THE PASSWORD ARE REVERSED ("PASSWD" ABOVE)
DTUKLP: MOVE T1,ETDSTS(F) ;GET DTE STATUS
TLNN T1,(ED.PPC) ;PRIMARY PROTOCOL FUNNING?
JRST DTUARP ;NO
TLNN T1,(ED.DTM) ;IF NOT MASTER,
JRST DTUDCE ;INVALID CPU/DTE
LOAD. T2,ED.211,(F) ;POINT TO TO-11 SECTION
LOAD. T1,EC.PRT,(T2) ;LOAD THE PROTOCOL TYPE
CAIE T1,.M20F ;20F?
JRST DTUDCE ;NO, BAD
PUSHJ P,GETWD1## ;GET NEXT ARG
HLRZ T2,T1 ;GET BYTE COUNT
CAIE T2,KPSLEN ;MATCH WHAT WE EXPECT?
JRST DTUBCE ;NO, RETURN ERROR (ILLEGAL BYTE COUNT)
HRRZS T1 ;ISOLATE ADDRESS ONLY
MOVEI T2,<<KPSLEN+3>/4>-1(T1) ;SET T2 := LAST WORD IN MESSAGE
MOVE P1,T1 ;SAVE THIS
PUSHJ P,TRNGE## ;MAKE SURE ALL THE DATA IS IN CORE.
HRR M,P1 ;GET ADDRESS OF FIRST WORD
PUSHJ P,GETWDU## ;READ IT FROM USER
LDB T1,[POINT 16,T1,15] ;GET LENGTH OF BLOCK
CAIE T1,KPSLEN-2 ;BETTER BE DATA AREA - LEN(COUNT)
JRST DTUDCE ;SOMEONE WANTED TO TRASH -20F!
MOVEI T2,<<22+^D<36/8-1>>/4>+<SIZE(.KEHDL,36)> ;SIZE OF LOG ENTRY
;+SIZE OF KLE HEADER IN -10 WDS
PUSHJ P,MESCOR ;ALLOCATE SOME CORE TO LOG THE EVENT
JRST DTUNFC ;NO FREE CORE, ABORT
PUSH P,P1 ;SAVE ADDRESS OF FIRST USER WORD
LOAD. P1,ED.DTN,(F) ;GET DTE #
LOAD. T2,ED.CPN,(F) ;GET CPU #
HRL P1,T2 ;CPU#,,DTE#
MOVSI P2,.EMKLI ;DEVICE IS KLINIK EVENT
MOVEI P3,22 ;UNIT 0,,BYTE COUNT
PUSHJ P,LOGSET ;SET UP LOG HEADER
POP P,T1 ;GET USER ADDRESS BACK
HRLZS T1 ;GET SOURCE (USER ADDRESS)
HRRI T1,.CPKPB## ;GET DESTINATION (EXEC ADDRESS)
EXCTUX <BLT T1,.CPKPB##-1+<<KPSLEN+3>/4>> ;COPY TO CDB
MOVE T4,P4 ;COPY BP TO DATA AREA
MOVEI T1,EM.ELR ;ERROR LOG REQUEST
IDPB T1,T4 ;STORE IN MESSAGE
MOVEI T1,1 ;SET KLINIK CODE
LDB T2,[POINT 8,.CPKPB##+3,32] ;NEW KLINIK MODE
SKIPE T2 ;ENABLED (SOME FLAVOR)?
TROA T1,1*400 ;YES, EVENT IS "SET"
MOVEI T1,377 ;NO, EVENT IS "CLEAR"
IDPB T1,T4 ;STORE THIS TOO
MOVEI T3,7 ;NUMBER OF 16-BIT WORDS TO LOG
MOVE T2,[POINT 16,.CPKPB##,31-16] ;DON'T LOG COUNT OR PASSWD
CPYWND: ILDB T1,T2 ;COPY A WORD OF WINDOW/MODE
IDPB T1,T4 ;INTO LOG BUFFER
SOJG T3,CPYWND ;TILL ALL MOVED
MOVEI T2,-<SIZE(.KEHDL,36)>(P4) ;POINT BACK TO START OF KLE CHUNK
PUSHJ P,DVSLOG ;AND LOG THE EVENT (WILL EVENTUALLY FREE CORE)
PUSHJ P,KPSSND ;SEND KLINIK PARAMETERS
JFCL ;NOT SERIOUS (OLD VERSION OF 20F)
JRST CPOPJ1## ;SIGNAL SUCCESSFUL START
;DTE. FUNCTION (#27) TO READ KLINIK PARAMS ON A DTE
; ADDR/CPU#,,DTE#
; +1/BC,,ADDR OF STRING
; STRING: BYTE(16)LEN,OPEN SSM(8)OPEN MM,YY,0,DD(16)CLOSE SSM(8)CLOSE MM,YY,
; 0,DD,CONSOLE MODE,KL MODE
; WHERE: KL MODE = 0 DISABLED, = 1 REMOTE CTY, = -1 USER MODE
; CONSOLE MODE = 1 OPERATOR, 3 PROGRAMMER, 7 MAINTENANCE.
; LEN = # OF BYTES TO FOLLOW (MUST MATCH -20F)
; SSM IS SECONDS SINCE MIDNIGHT/2
DTUKPR: MOVE T1,ETDSTS(F) ;GET DTE STATUS
TLNN T1,(ED.DTM) ;IF NOT MASTER,
JRST DTUDCE ;INVALID CPU/DTE
LOAD. T2,ED.211,(F) ;POINT TO TO-11 SECTION
LOAD. T1,EC.PRT,(T2) ;LOAD THE PROTOCOL TYPE
CAIE T1,.M20F ;20F?
JRST DTUDCE ;NO, BAD
PUSHJ P,GETWD1## ;GET NEXT ARG
HLRZ T2,T1 ;GET BYTE COUNT
CAIE T2,KPSLEN-6 ;MATCH WHAT WE EXPECT?
JRST DTUBCE ;NO, RETURN ERROR (ILLEGAL BYTE COUNT)
HRRZS P1,T1 ;ISOLATE BUFFER ADDRESS AND SAVE
MOVEI T2,<<KPSLEN-6+3>/4>-1(T1) ;SET T2 := LAST WORD IN MESSAGE
HRL P1,T2 ;SAVE LAST,,FIRST
PUSHJ P,TRNGE## ;MAKE SURE ALL THE DATA IS IN CORE.
IFE FTXMON,<
HLRZ T1,P1 ;RETRIEVE LAST WORD (USER)
HRLI P1,.CPKPB## ;WHERE THE DATA COMES FROM
EXCTXU <BLT P1,(T1)> ;COPY TO USER
>
IFN FTXMON,<
HLRZ T1,P1 ;RETRIEVE LAST WORD (USER)
SUBI T1,(P1) ;COUNT-1
MOVEI T1,1(T1) ;FIX TO REAL COUNT
XSFM T2 ;GET PCS
ANDI T2,(SECMSK) ;ISOLATE SECTION
MOVS T3,T2 ;GET IN PROPER HALFWORD
HRRI T3,(P1) ;FORM COMPLETE USER ADDRESS
XMOVEI T2,.CPKPB## ;WHERE THE DATA COMES FROM
XBLTXU T1, ;COPY TO THE USER
>
JRST CPOPJ1## ;OK
;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#
TRC T1,-1 ;ASKING FOR MASTER DTE?
TRCN T1,-1
IFN FTMP,<
PUSHJ P,CPLCK## ;YES, LOCKED ON THIS CPU?
CAIA
>
HRL T1,.CPCPN## ;YES, SUPPLY CPU NUMBER
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
IFN FTMP,<
HLRZ T1,W ;CPU NUMBER
PUSHJ P,ONCPUS## ;MAKE SURE WE'RE ON THE RIGHT CPU
JRST DTUGT1
>
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
;DTUEBP RETURN A BYTE POINTER TO EVM
; CALLED WITH:
; T1/ BYTE POINTER TO USER ADDRESS SPACE
; T2/ BYTE COUNT
; ON BEFORE RETURNING, PLACES ADDR OF ROUTINE TO GIVE BACK EVM ON STACK
; AND SAVES EVA AND # OF PAGES TO RETURN. T3 CONTAINS POINTER TO EVM
; ON SKIP RETURN. NON-SKIP RETURN GIVEN WHEN OUT OF EVM. ALL POINTERS
; GIVEN AND RETURNED ARE ILDB/IDPB POINTERS.
; USES T1-T4
DTUEBP: PUSHJ P,CHKBPT## ;RANGE CHECK IT
JRST UADERR## ;ADDRESS CHECK
MOVSI T3,NSHF!NSWP ;LOCK JOB IN CORE
IORM T3,JBTSTS##(J) ;SET STATUS WORD FOR JOB
IBP T1 ;MAKE BYTE POINTER POINT TO FIRST REAL ADDRESS
PUSH P,T1 ;SAVE BYTE POINTER FOR LATER
LDB T4,[POINT 6,T1,11] ;GET BYTE SIZE FROM BYTE POINTER
MOVEI T3,^D36 ;GET BITS/WORD
IDIV T3,T4 ;T3=BYTES/WORD
IDIV T2,T3 ;T2=WORDS OF EVM REQUIRED
HRRZ T3,T1 ;GET FIRST USER ADDRESS FOR GTEVBF
MOVE T1,T2 ;SET UP BUFFER SIZE FOR GTEVBF
PUSH P,F ;SAVE ETD POINTER FOR LATER
SETZ F, ;MAKE SURE UUOCON KNOWS WE DON'T HAVE DDB HERE
PUSHJ P,GTEVBF## ;DO THE MAPPING
JRST DTUEB1 ; GIVE THE ERROR RETURN (NO EVM LEFT)
POP P,F ;RESTORE ETD POINTER
POP P,T2 ;GET COPY OF INCREMENTED BYTE POINTER
HLL T3,T2 ;RESTORE P AND S FIELDS FROM INC'D USER BP
EXCH T1,0(P) ;T1=ADDR OF CALLER, 0(P)=AMOUNT OF EVM WE GOT
PUSH P,T3 ;SAVE ADDRESS OF EVM
SETO T2, ;GET OFFSET FOR ABJBP
ADJBP T2,T3 ;DECREMENT BYTE POINTER BY ONE
MOVE T3,T2 ;PUT BP TO MAPPED EVM BACK WHERE IT BELONGS
PUSHJ P,1(T1) ;CALL THE CALLER WITH SKIP RETURN
CAIA ;NON SKIP RETURN
AOS -2(P) ;INDICATE SKIP RETURN
POP P,T2 ;GET BACK EVA
POP P,T1 ;AND THE NUMBER OF PAGES
ANDI T1,777 ;GET USEFULL PART
PUSH P,F ;SAVE F FOR LATER USE
SETZ F, ;KEEP GIVEVM FROM LOOKING AT NON-EXISTANT DDB
PUSHJ P,GIVEVM## ;GIVE IT BACK
MOVSI T1,NSWP!NSHF ;NO SWAP, NO SHUFFLE
ANDCAM T1,JBTSTS##(J) ;CLEAR THEM (UNLOCK)
JRST FPOPJ## ;RETURN TO SENDER.
DTUEB1: POP P,F ;RESTORE ETD POINTER
POP P,T1 ;AND T1
POPJ P, ;AND RETURN NO SKIP
SUBTTL DTEDDB - PROTOTYPE DDB FOR THE DTE DEVICE
DEFINE X(NAME<%1>,SIZE<1>),<NAME==:<%1==%1+SIZE>-SIZE>
%1==DEVLLD ;INITIALIZE THE OFFSET
X DEVETD ;XWD ETD ADDRESS, INPUT MSG QUEUE
X DEVOBC ;COUNT OF OUTPUT BUFFERS OUTSTANDING
X DTEDBL,0 ;LENGTH OF DTE DDB
;LAY OUT THE PROTOTYPE DDB
DEFINE X(OFFSET,EXPR),<
RELOC DTEDDB+OFFSET
EXPR
>
$LOW ;HAS TO BE DIDDLED WITH
DTEDDB::X DEVCHR,<XWD <6*HUNGST>+DVC2IO,<DTEMMS+3>/4+1> ; BUFFER SIZE
X DEVSER,<XWD 0,DTEUDS> ;DISPATCH THROUGH THIS
X DEVMOD,<XWD DVIN!DVOUT,1_BYTMOD>
X DEVSTA,<XWD DEPLEN!<.TYDTE*.TYEST>,DEPEVM> ;VARIABLE BUFFERS, NO EVM
X DEVCPU,<EXP 707B8> ;SET DEYPCL SO IT WILL RUN ON ANY CPU
X DTEDBL ;RESERVE SUFFICIENT ROOM
$HIGH ;PURE AGAIN
PURGE X
SUBTTL DTEUUO - DTE DEVICE'S ENTRY TO DTESER
;DISPATCH TABLE
POPJ P, ;(-5) DEVICE OFF LINE
JRST ECOD2## ;(-4) DEVOP. UUO
JRST REGSIZ## ;(-3) LENGTH CAN BE GOTTEN FROM DDB
POPJ P, ;(-2) ONCE INITIALIZATION
JRST DTEHNG ;(-1) HUNG DEVICE
DTEUDS: JRST DTEREL ;(0) RELEASE
JRST OUT## ;(1) CLOSE OUTPUT
JRST DTEOUT ;(2) OUTPUT
JRST DTEIN ;(3) INPUT
;TSTDTE - CALLED FROM DDBSRC IN UUOCON TO CHECK FOR THE DTE PHYSICAL DEVICE
; CALL:
; T1/ DEVICE NAME
; RETURN:
; CPOPJ ;ON ERROR (NOT DTE, ETC.)
; CPOPJ1 ;F CONTAINING DDB ADDRESS ON SUCCESS
TSTDTE::HLRZ T2,T1 ;GET THE RH OF THE NAME
CAIE T2,'DTE' ;IS IT 'DTE'?
POPJ P, ;NO, GIVE BAD RETURN
HRLZ T2,.USMUO ;UUO OP CODE
IOR T2,.USMUE ;EA-CALC
TDZ T2,[777,,UPHNLY] ;ONLY CALLI
CAMN T2,[FILOP.] ;FILOP?
JRST TSTDT1 ;YES, ALLOW THAT
HLRZS T2 ;OR OPEN
CAIE T2,(OPEN)
JRST TSTER1 ;NO, ONLY FILOP/OPEN MAY CREATE DDB
TSTDT1: PUSHJ P,SAVT## ;SAVE THE T'S
PUSHJ P,SAVE1## ; AND A PEA
MOVE P1,T1 ;PRESERVE THE DEVICE NAME
MOVSI T1,JP.POK ;MAKE SURE THIS GUY IS REALLY
PUSHJ P,PRVBIT## ; A GOOD PERSON TO LET DO THIS
CAIA ;SEEMS OK
JRST TSTER1 ;DON'T LET HIM
;CHECK FOR REAL DTE
TRNE P1,575454 ;IS RH A GOOD NUMBER? (MUST BE 'DTE0NN')
POPJ P, ;ERROR
LDB F,[POINT 3,P1,29] ;GET CPU NUMBER
MOVSS F ;PUT IT IN THE LEFT HALF
LDB T1,[POINT 3,P1,35] ;GET DTE NUMBER
HRR F,T1 ;CPU#,,DTE#
PUSHJ P,GETETD ;GET ETD BLOCK ADDRESS IN F
JRST TSTER1 ;CLEAR F AND RETURN
MOVE T1,ETDSTS(F) ;GET FLAGS INTO T1
TXNE T1,ED.DTX ;DOES THIS DTE EXIST??
TXNE T1,ED.DTM ;LETS ALSO MAKE SURE THAT
JRST TSTER1 ; THIS ISN'T THE MASTER DTE
TXNE T1,ED.PPC ;IS PROTOCOL UP??
JRST TSTER1 ; YES, CAN'T DO THIS
PUSHJ P,GETCPU ;AVOID ALL KINDS OF RACES
JRST TSTER1 ; CPU IS DOWN
SKIPE ETDDDB(F) ;DID SOMEONE OWN A DDB ALREADY?
JRST TSTER1 ;YES, CAN'T OPEN IT AGAIN
; NOW WE CAN BUILD THE DDB
MOVEI T2,DTEDBL ;GET THE LENGTH OF THE DDB
PUSHJ P,GETWDS## ;ALLOCATE THAT MANY WORDS
JRST TSTER1 ;OOPS
MOVSI T2,DTEDDB ;GET PROTOTYPE DDB
HRR T2,T1 ;COPY THE ADDRESS OF THE NEW ONE
BLT T2,DTEDBL-1(T1) ;INITIALIZE THE NEW ONE
MOVEM P1,DEVNAM(T1) ;STORE THE NAME IN THE DDB
HRLM F,DEVETD(T1) ;MAKE DDB POINT TO ETD BLOCK
MOVEM T1,ETDDDB(F) ;MAKE ETD POINT BACK TO DDB
MOVEI T2,DD.PRO ;WE ARE NOW
MOVEM T2,ETDUSR(F) ; IN PROGRAM MODE
HRLM J,ETDUSR(F) ;REMEMBER JOB NUMBER OF OWNER
LOAD. T2,ED.CPN,(F) ;GET CPU# OF THIS DTE
LSH T2,^D33 ;GET CPU # IN 0-2
IFN FTMP,<
ADDI T2,PPCPI+INTL0## ;GET ADDR OF INTERLOCK WORD
>
MOVEM T2,DEVCPU(T1) ;STUFF IT
DDBSRL ;LOCK THE DDB CHAIN WHILE WE PLAY
HLLZ T2,DEVSER+DTEDDB ;GET ADDR OF CHAIN FOLLOWING PROTOTYPE
HLLM T2,DEVSER(T1) ;INSTALL IT IN THE NEW DDB
HRLM T1,DEVSER+DTEDDB ;MAKE PROTOTYPE POINT TO NEW DB
DDBSRU ;WE CAN NOW UNLOCK THE CHAIN
; SET UP TO DO I/O TO THE DTE DEVICE
MOVX T1,ED.TID ;GET TO-10 IDLE INDICATOR
STOR. T1,ED.2TS,(F) ;STUFF IT
IFN ED.TID-ED.EID, MOVX T1,ED.EID ;GET TO-11 IDLE INDICATOR
STOR. T1,ED.2ES,(F) ;MAKE THAT IDLE TOO
MOVX T1,ED.BFR+ED.MAI ;GET BUFFER READY BIT
ANDCAM T1,ETDSTS(F) ;RESET IT
SKIPE ETDIBK(F) ;IS A BUFFER ALLOCATED ALREADY?
STOPCD TSTERR,DEBUG,DTEIBA ;++ INPUT BUFFER ALREADY ALLOCATED
MOVEI T2,<DTEMMS+3>/4 ;GET NUMBER OF WORDS NEEDED FOR BUFFER
PUSHJ P,GETWDS## ;GET IT FROM THE MONITOR
JRST TSTERR ; NO MEMORY, GIVE UP
STOR. T1,ED.IBK,(F) ;STORE IT
SKIPE ETDOBK(F) ;IS A BUFFER ALLOCATED ALREADY?
STOPCD TSTERR,DEBUG,DTEOBA ;++ OUTPUT BUFFER ALREADY ALLOCATED
MOVEI T2,<DTEMMS+3>/4 ;GET NUMBER OF WORDS NEEDED FOR BUFFER
PUSHJ P,GETWDS## ;GET IT FROM THE MONITOR
JRST TSTERR ; NO MEMORY, GIVE UP
STOR. T1,ED.OBK,(F) ;STORE IT
MOVX T1,ED.MAI ;GET MAINTENANCE MODE BIT
IORM T1,ETDSTS(F) ;LET INTERRUPT LEVEL KNOW WHATS GOING ON
MOVX T1,PILDEN+PI0ENB+PPCPI ;GET BITS TO ENABLE THE DTE
XCT ETDCNO(F) ;TURN ON INTERRUPTS
MOVEI T2,DD.PRO ;PROGRAM MODE
PUSHJ P,DFKSET ;TELL THE FEK
LOAD. F,ED.DDB,(F) ;MAKE F POINT TO DDB
JRST CPOPJ1## ;GOOD RETURN
TSTERR: PUSHJ P,FREIOB ;RELEASE THE I/O BUFFERS
TSTER1: SETZ F, ;CLEAR F
POPJ P, ;GIVE BAD RETURN
FREIOB: LOAD. T2,ED.IBK,(F) ;ADDRESS OF INPUT BUFFER
JUMPE T2,FREIO1 ;NO SUCH ANIMAL, TRY TO DEALLOCATE OUT BUFF
MOVEI T1,<DTEMMS+3>/4 ;GET SIZE OF INPUT BUFFER
PUSHJ P,GIVWDS## ;DEALLOCATE THE MEMORY
SETZ T2, ;CLEAR ADDRESS
STOR. T2,ED.IBK,(F) ;SAVE IT
FREIO1: LOAD. T2,ED.OBK,(F) ;ADDRESS OF INPUT BUFFER
JUMPE T2,CPOPJ## ;NO SUCH ANIMAL, JUST RETURN
MOVEI T1,<DTEMMS+3>/4 ;GET SIZE OF INPUT BUFFER
PUSHJ P,GIVWDS## ;DEALLOCATE THE MEMORY
SETZ T2, ;CLEAR ADDRESS
STOR. T2,ED.OBK,(F) ;SAVE IT
POPJ P,
;DTEREL - PROCESS THE "RELEASE" FUNCTION FOR OF THE DTE
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ALWAYS
DTEREL: PUSHJ P,DTECKO ;CHECK TO MAKE SURE WE'RE OWNER
POPJ P,
HLRZ F,DEVETD(F) ;MAKE F POINT TO ETD
PUSHJ P,FREIOB ;AND RELEASE THE I/O BUFFERS
PUSHJ P,DFKSE0 ;SET LINE-USER 'NOBODY' AND TELL THE FEK
LOAD. F,ED.DDB,(F) ;TURN IT BACK TO A DDB POINTER
POPJ P, ;AND RETURN
;ZAPDTE - DESTROY A DTE DDB
; CALLED BY RELEA9 IN UUOCON
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ALWAYS
ZAPDTE::MOVEI T1,DTEDDB ;MAKE T1 POINT TO PROTOTYPE DDB
HLRZ T2,DEVSER+DTEDDB ;T2 POINTS TO FIRST DDB WE WANT TO LOOK AT
DDBSRL ;LOCK THE DDB CHAIN
ZAPDT2: CAIN T2,(F) ;IS THIS THE ONE?
JRST ZAPDT1 ;YES, GO REMOVE IT
MOVE T1,T2 ;FOLLOW THE CHAIN
HLRZ T2,DEVSER(T1) ;GET NEXT DDB
JUMPN T2,ZAPDT2 ;JUMP BACK IF THERE IS MORE TO LOOK AT
STOPCD ZAPDT1,DEBUG,DTEDWA, ;++DDB WENT AWAY?
ZAPDT1: HLLZ T2,DEVSER(F) ;GET THE NEXT DDB
HLLM T2,DEVSER(T1) ;MAKE PREVIOUS DDB POINT TO NEXT DDB
HLRZ T1,DEVETD(F) ;GET ETD ADDRESS IN T1
MOVX T2,ED.MAI ;CLEAR MAINTENANCE MODE BIT SO THAT INTERRUPT
ANDCAM T2,ETDSTS(T1) ; LEVEL DOESN'T USE ETDDDB...
SETZM ETDDDB(T1) ;CLEAR PTR TO DDB
DDBSRU ;UNLOCK THE CHAIN
HRRZ T2,F ;GET THE ADDR OF THE DDB
MOVEI T1,DTEDBL ; AND LENGTH
PJRST GIVWDS## ;GIVE BACK STORAGE AND RETURN
;DTEIN - CALLED TO PROCESS THE IN UUO FOR THE DTE DEVICE
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ALWAYS
T5==T4+1 ;(W) EXTRA T FOR EXTEND INSTRUCTIONS
T6==T5+1 ;(M) AND ANOTHER
IFN W-T5,<
IF1,<PRINTX ?DTESER assumes that ACs W and T5 are the same
PRINTX ? because it knows that W is OK to trash>
>
IFN M-T6,<
IF1,<PRINTX ?DTESER assumes that ACs M and T6 are the same
PRINTX ? because it knows that M is OK to trash>
>
DTEIN: HLRZ T2,DEVETD(F) ;GET ETD ADDRESS
MOVEI T1,PILDEN+PI0ENB+PPCPI
XCT ETDCNO(T2) ;ENABLE INTERRUPTS
PUSHJ P,SAVE2## ;SAVE THREE PEAS
PUSHJ P,DTECKM ;CHECK TO SEE IF IN CORRECT MODE
SKIPA ;SKIP OVER INITIAL WAIT
DIWAIT: PUSHJ P,DIOWAI ; WAIT FOR -11 TO KICK US
PUSHJ P,DTEONL ;MAKE SURE DTE IS ON-LINE
POPJ P, ;RETURN - ERROR BITS HAVE BEEN SET
HLRZ P2,DEVETD(F) ;GET ETD BLOCK ADDRESS
MOVX T2,ED.BFR ;GET BUFFER READY BIT
TDNN T2,ETDSTS(P2) ;IS THE BUFFER AVAILABLE???
JRST DIWAIT ; NO, WAIT FOR IT
HRRZ P1,DEVIAD(F) ;GET ADDRESS OF USERS INPUT BUFFER
;SET UP TO COPY DATA
LOAD. T4,ED.IBK,(P2) ;GET ADDR OF MONITORS INPUT BUFFER
HRLI T4,(POINT 8,) ;MAKE IT A BYTE POINTER
; TLNN S,IOBEG ;SKIP THIS IF WE ARE IN ROM DUMP MODE
PUSHJ P,GX2BYT ; GET FIRST TWO BYTES AS MSG LENGTH INTO T1
; TLNE S,IOBEG ;ARE WE IN ROM DUMP MODE?
; MOVEI T1,DTEMMS ; YES, TRANSFER THE WHOLE BUFFER
EXCTXU <HRRM T1,1(P1)> ;STORE BYTE COUNT FOR USER
MOVE T2,T4 ;SET UP SOURCE BYTE POINTER
EXCTUX <HLRZ T4,(P1)> ;GET THE LENGTH OF THE INPUT BUFFER
SUBI T4,1 ;MAKE IT THE ACTUAL LENGTH IN WORDS
LSH T4,2 ; AND CONVERT THAT TO BYTES
CAMGE T4,T1 ;MAKE SURE THAT THE DATA WILL FIT
JRST D.BKTL ; IF NOT, THEN GIVE THE ERROR "BLOCK TO LARGE"
MOVSI T5,(POINT 8,) ;MAKE A BYTE POINTER TO THE
HRRI T5,2(P1) ;USER'S INPUT BUFFER
PXCT 1,[EXTEND T1,[EXP MOVSLJ,0]] ;AND COPY THE DATA
STOPCD CPOPJ##,JOB,DTEMDS, ;++ MOVSLJ DIDN'T SKIP
;NOW RESET THE MONITOR'S INPUT BUFFER, AND ADVANCE THE USERS BUFFER
MOVX T1,ED.BFR ;GET BUFFER READY BIT
ANDCAM T1,ETDSTS(P2) ;CLEAR IT, 'CAUSE WE JUST READ THE BUFFER
PUSHJ P,ADVBFF## ;ADVANCE THE USER'S INPUT BUFFER
POPJ P, ;IF WE'RE SUPPOSED TO STOP, RETURN TO UUOCON
POPJ P, ;YES, RETURN IMMEDIATELY, CAUSE MAINT MODE
; WONT SAY ANYMORE TILL USER GIVES IT SOMETHING
;The following code, and all code controlled by IOBEG implements a new style
;of primary bootstrap for the DTE (in lieu of the .DTELS and .DTEDM DTE.
;functions.) This operates as follows: 1) If IOBEG is set, and an IN uuo is
;done,one bufferful of 16 bit words is read over the DTE and given to the user.
;The user has the option of doing as many IN uuos as is necessary in order
;to dump the front end. 2) If IOBEG is set, and an OUT uuo is done, IOBEG
;gets cleared, and a bufferful of 16 bit words is copied from the user to
;location 0 of the front end, and then started. This implies that the OUT
;uuo may only be done once in this mode. It also implies that the code
;you load had better be able to speak the IN/OUT 8 bit protocol defined
;by DTEIN/DTEOUT (ie: the first two (swapped) bytes of each message is the
;count of the number of bytes that follow).
;
;Also note that this code is commented out, until I get a chance to implement
;it in NML (or DTELDR for that matter).
repeat 0,<
;FSTIO USES BM873 BOOT ROM TO DUMP THE FRONT END. THIS IS CALLED ONLY WHEN NO
;OUT UUO'S HAVE BEEN PERFORMED.
FSTIO: HRRZ P1,DEVIAD(F) ;GET ADDRESS OF USERS INPUT BUFFER
EXCTUX <HLRZ T1,(P1)> ;GET THE LENGTH OF THE INPUT BUFFER
SUBI T1,1 ;MAKE IT THE ACTUAL LENGTH IN WORDS
LSH T1,1 ; AND CONVERT THAT TO 16 BIT BYTES
CAILE T1,DTEMMS/2 ;IS BUFFER BIG ENOUGH?
JRST D.BKTL ; NO, BLOCK TOO LARGE ERROR
MOVNS T1 ;NEGATE IT
ANDI T1,TO10BC ;MASK IT DOWN
HLRZ T2,DEVETD(F) ;GET ETD ADDR
MOVX T3,ED.TDB ;INDICATE WE ARE WAITING FOR DIRECT XFER
STOR. T3,ED.2TS,(T2) ; TO COMPLETE
LOAD. T3,ED.IBK,(T2) ;GET INPUT BUFFER ADDRESS
HRLI T3,(POINT 16,) ;MAKE IT A BYTE POINTER
MOVEM T3,@ETDTBP(T2) ;PUT IT IN THE EPT
XCT ETDDTO(T2) ;START THE XFER
POPJ P, ;AND RETURN
>; End of repeat 0
;MAIDBL RESPONDS TO DOORBELL INTERRUPTS FOR MAINTENANCE MODE
MAIDBL: MOVEI T1,CL11PT ;CLEAR THE DOORBELL
XCT ETDCNO(F) ;DO THE CONO
MOVX T1,ED.BFR ;GET BUFFER READY BIT
TDNE T1,ETDSTS(F) ;HAS UUO LEVEL READ THE BUFFER YET?
JRST MAIDER ; NO, SOMEBODY SCREWED UP...
LOAD. T1,ED.2TS,(F) ;GET TO-10 STATUS
CAIE T1,ED.TID ;ARE WE IDLE?
JRST MAIDER ; NO, MOP SCREWED UP...
;GET READY TO COPY THE MESSAGE LENGTH INTO THE BUFFER
LOAD. T1,ED.IBK,(F) ;GET ADDRESS OF INPUT BUFFER
HRLI T1,(POINT 8,) ;MAKE IT A BP
MOVEM T1,@ETDTBP(F) ;SAVE IT IN THE DTE CONTROL BLOCK
MOVX T1,ED.TIB ;INDICATE NEW STATE
STOR. T1,ED.2TS,(F) ;IN THE ETD BLOCK
MOVEI T1,-2&TO10BC ;START TRANSFER OF MESSAGE LENGTH (2 BYTES)
XCT ETDDTO(F) ;START THE XFER
POPJ P, ;AND RETURN
;HERE ON TO-10 XFER DONE WHILE IN MAINTENANCE MODE
MAIIDN: MOVX T1,CLTO10 ;CLEAR TO-10 XFER DONE
XCT ETDCNO(F) ;TELL THE HARDWARE ABOUT IT
LOAD. T1,ED.2TS,(F) ;GET TO-10 STATE
CAIN T1,ED.TIB ;WERE WE WAITING FOR THE BYTE COUNT?
JRST MAIINP ; YES, GO START REAL XFER
CAIN T1,ED.TDB ;WERE WE WAITING FOR FINAL XFER TO COMPLETE?
JRST MAIITC ; YES, GO DO INPUT COMPLETE STUFF
JRST MAIDER ;NO TO EITHER...
;HERE WHEN WE HAVE THE BYTE COUNT FOR THE MOP MESSAGE. START THE REAL XFER
MAIINP: LOAD. T4,ED.IBK,(F) ;GET ADDRESS OF INPUT BUFFER
HRLI T4,(POINT 8,) ;MAKE IT A BYTE POINTER
PUSHJ P,GX2BYT ;GET THE SIZE OF THE MESSAGE INTO T1
JUMPE T1,MAIDER ;ZERO LENGTH MESSAGE IS NO GOOD
CAILE T1,DTEMMS ;IS THE MESSAGE TOO BIG?
JRST MAIDER ; YES, DIE GRACEFULLY
MOVNS T1 ;NEGATE THE LENGTH
ANDI T1,TO10BC ;REDUCE IT TO 12 BITS
TXO T1,TO10IB ;INTERRUPT 11 AFTER THIS XFER
XCT ETDDTO(F) ;START THE TRANSFER
MOVEI T1,ED.TDB ;INDICATE THAT WE ARE
STOR. T1,ED.2TS,(F) ; WAITING FOR BULK OF MESSAGE TO ARRIVE
POPJ P, ;AND RETURN
;HERE WHEN ALL OF MESSAGE HAS ARRIVED. LET UUO LEVEL KNOW
MAIITC: MOVX T1,ED.TID ;INDICATE THAT THE TO-10 SIDE OF
STOR. T1,ED.2TS,(F) ; THE DTE IS NOW IDLE
MOVX T1,ED.BFR ;GET THE BUFFER IS READY BIT
IORM T1,ETDSTS(F) ;LET UUO LEVEL KNOW THAT BUFFER IS VALID
;HERE TO SIGNAL I/O DONE
MAIIOD: MOVEI T1,PSIIOD## ;SIGNAL I/O DONE
LOAD. F,ED.DDB,(F) ;MAKE F POINT TO DDB
;HERE TO SIGNAL UUO LEVEL THAT SOMETHING HAS HAPPENED
;CALL WITH F CONTAINING DDB POINTER
MAISGL: PUSHJ P,(T1) ;SIGNAL I/O DONE OR ERROR
MOVE T1,DEVAIO(F) ;GET NON-BLOCKING I/O BITS
TRNE T1,DEPAIO ;NON-BLOCKING I/O???
POPJ P, ; YES, WE CAN QUIT NOW
LDB T1,PJOBN## ;GET THE JOB NUMBER
PJRST EWAKE## ;GO WAKE UP THE JOB
;HERE WHEN WE GET TO-11 XFER DONE
MAIOTC: MOVX T1,CLTO11 ;CLEAR TO-11 DONE
XCT ETDCNO(F) ;. . .
LOAD. T1,ED.2ES,(F) ;GET THE TO-11 STATE
CAIE T1,ED.EDB ;WAITING FOR TO-11 DONE?
POPJ P, ; NO, JUST RETURN
MOVX T1,ED.EID ;NEW STATE IS TO-11 IDLE
STOR. T1,ED.2ES,(F) ;LET UUO LEVEL KNOW THAT BUFFER IS AVAILABLE
JRST MAIIOD ;WAKE UP THE JOB
;DTEOUT - ROUTINE TO PROCESS THE OUTPUT UUO FOR THE DTE DEVICE
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ALWAYS
DTEOUT: PUSHJ P,SAVE2## ;P1/ DEVOAD P2/ DATA BUFFER ADDRESS
TLO S,IO ;INDICATE THAT WE ARE DOING OUTPUT
IORM S,DEVIOS(F) ;IN THE DDB ALSO
PUSHJ P,DTECKM ;CHECK FOR CORRECT MODE
SKIPA ;SKIP OVER INITIAL WAIT
DOWAIT: PUSHJ P,DIOWAI ; WAIT FOR -11 TO GRONK US
DOLOOP: PUSHJ P,DTEONL ;MAKE SURE THAT WE ARE ONLINE
POPJ P, ;IF NOT, RETURN (ERROR BITS ARE SET)
HRRZ P1,DEVOAD(F) ;GET USERS BUFFER ADDRESS
HLRZ P2,DEVETD(F) ;GET ETD ADDRESS
LOAD. T1,ED.2ES,(P2) ;GET TO-11 STATE
CAIE T1,ED.EID ;IS IT IDLE?
JRST DOWAIT ; NO, GO WAIT FOR XFER TO COMPLETE
;HERE TO COPY DATA FROM USER TO TO-11 MONITOR BUFFER
EXCTUX <HRRZ T1,1(P1)> ;GET THE NUMBER OF USER BYTES
JUMPE T1,ADVBFE## ;QUIT NOW IF BUFFER EMPTY
CAILE T1,DTEMMS ;MAKE SURE THAT THE NUMBER IS REALISTIC
JRST D.BKTL ;AND TELL THE USER "BLOCK TO LARGE"
MOVSI T2,(POINT 8,) ;START A BYTE POINTER
HRRI T2,2(P1) ;COMPLETE THE SOURCE BP
MOVE T4,T1 ;DEST BYTE COUNT CAN BE SAME AS SOURCE
LOAD. T5,ED.OBK,(P2) ;GET OUTPUT BUFFER ADDRESS
HRLI T5,(POINT 8,) ;MAKE IT A BP
MOVEM T5,@ETDEBP(P2) ;SAVE IT IN THE DTE CONTROL BLOCK (TO-11 PTR)
IDPB T1,T5 ;INSTALL LOW ORDER PART OF MESSAGE LENGTH
LDB T3,[POINT 8,T1,27] ;GET HIGH ORDER PART OF MESSAGE LENGTH
IDPB T3,T5 ;INSTALL THAT TOO
XCT 2,[EXTEND T1,[EXP MOVSLJ,0]] ;COPY THE DATA INTO THE MONITOR
PUSHJ P,DTEMDS ;++ MOVSLJ DIDN'T SKIP
MOVX T1,ED.EDB ;NEW STATE IS WAITING FOR TO-11 XFER
STOR. T1,ED.2ES,(P2) ;INSTALL IT
MOVEI T1,TO11DB ;GO RING THE PDP-11'S
XCT ETDCNO(P2) ; DOORBELL
PUSHJ P,ADVBFE## ;ADVANCE THE USER'S OUTPUT BUFFER
POPJ P, ;IF NO MORE OUTPUT, RETURN TO UUOCON
JRST DOLOOP ;OTHERWISE TRY TO SEND MORE
PURGE T5 ;WE'RE DONE WITH THE EXTEND INSTRUCTIONS
SUBTTL DTEHNG Hung device code for the DTE device
;DTEHNG WILL SET AN ERROR BIT IN DEVIOS, SO THAT DIMOPW WILL KNOW WHEN TO
; GIVE UP.
; CALL:
; F/ DDB ADDRESS
; S/ DEVIOS
; RETURN:
; CPOPJ1 ALWAYS
DTEHNG: PUSHJ P,D.DERR ;SET THE IODERR BIT IN DEVIOS
JRST CPOPJ1 ;AND ALWAYS SKIP RETURN
;WAIT FOR -11 TO GRONK US. IF DOING NON-BLOCKING I/O, JUST RETURN
DIOWAI:
repeat 0,<
TLNE S,IOBEG ;ARE WE IN ROM-DUMP MODE?
PUSHJ P,FSTIO ; YES, GO START UP TRANSFER
>
MOVE T1,DEVAIO(F) ;GET NON-BLOCKING I/O BITS
TRNE T1,DEPAIO ;DOING NON-BLOCKING I/O?
JRST TPOPJ## ; YES, POPJ PAST CALLER AND GET OUT OF HERE
MOVEI T1,EV.DTE ;OTHERWISE, GO INTO
PJRST ESLEEP## ; EVENT WAIT
;DTECKO - CHECK OWNERSHIP OF THE ETD BLOCK
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ETD IS NOT IN PROGRAM MODE
; CPOPJ1 ;ETD IS IN PROGRAM MODE
DTECKO: HLRZ T1,DEVETD(F) ;GET THE ETD BLOCK POINTER
HRRZ T1,ETDUSR(T1) ;GET THE USER CODE
CAIN T1,DD.PRO ;IS IT A PROGRAM?
AOS (P) ;YES, SKIP RETURN
POPJ P, ;NO, BAD RETURN
;DTEONL - CHECK TO SEE IF THE DTE IS "ONLINE"
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;NOT OWNED OR OFFLINE (WITH ERROR BITS SET)
; CPOPJ1 ;DTE SEEMS TO BE READY FOR I/O
DTEONL: PUSHJ P,DTECKO ;FIRST SEE IF WE OWN THE LINE
JRST D.IMPM ; IF NOT, MUST BE IMPROPER MODE
MOVE S,DEVIOS(F) ;GET THE DEVICE STATUS
TRNE S,IOSSRM!IOSMRN ;IF EITHER ERROR IS LIT
JRST D.DERR ; RETURN TO USER WITH ERROR
TRNE S,IODERR!IODTER!IOIMPM!IOBKTL ;IF ANY ERROR LEFT
POPJ P, ; USER MUST CLEAR FIRST
HLRZ T2,DEVETD(F) ;GET THE POINTER TO ETD BLOCK
TRNE S,IOSMAI ;ARE WE TRYING MAINT MODE
JRST DTEON1 ; YES, TRY SEE IF WE'RE IN THE MODE
MOVSI T1,(ED.PPC) ;SEE IF PRIMARY PROTOCOL IS WORKING
TDNN T1,ETDSTS(T2) ;ARE WE?
JRST D.DERR ;NO, DEVICE ERROR
JRST CPOPJ1## ;GIVE GOOD RETURN
DTEON1: MOVSI T1,(ED.MAI) ;CHECK FOR MAINT MODE
TDNN T1,ETDSTS(T2) ;ARE WE?
JRST D.DERR ;NO, DEVICE ERROR
JRST CPOPJ1## ;GOOD
;DTECKM - CHECK/SET THE MAINT/NORMAL MODE OF THE LINE
; CALL:
; F/ DDB ADDRESS
; RETURN:
; CPOPJ ;ALWAYS
DTECKM: PUSHJ P,DTECKO ;MAKE SURE WE OWN THE LINE
POPJ P, ;WE DON'T, LOSE
HLRZ T2,DEVETD(F) ;GET ADDRESS OF ETD BLOCK
MOVE T1,ETDSTS(T2) ;GET THE ETD STATUS WORD
MOVE S,DEVIOS(F) ;GET THE DEVICE STATUS WORD
TRNN S,IOSMAI ;SEE IF WE ARE TRYING FOR MAINT MODE
JRST DTECK1 ;NOPE, GO SEE ABOUT PRMARY PROTOCOL
TLNE T1,(ED.MAI) ;CHECK THE MODE OUT
POPJ P, ;WE'RE OK
HLRZ T2,DEVETD(F) ;GET THE ETD BLOCK ADDR IN T2
MOVSI T1,(ED.MAI) ;GET THE MAINTAINACE BIT
IORM T1,ETDSTS(T2) ;IDENTIFY OURSELVES AS DOING MAINT
POPJ P, ; RETURN READY TO TALK MOP
DTECK1: TLNE T1,(ED.PPC) ;ARE WE IN PRIMARY PROTCOL?
POPJ P, ;YUP, THATS OK
;FOR RIGHT NOW THERE SHOULD BE NO
;WAY TO GET INTO THIS MODE, SO WE
;WILL JUST RETURN A DEVICE ERROR
D.IMPM: MOVEI S,IOIMPM ;SET IMPROPER MODE
JRST D.SET ;SET DEVIOS CORRECTLY
D.DERR: MOVEI S,IODERR ;GET THE DEVICE ERROR BIT
JRST D.SET ;SET IN DEVIOS
D.BKTL: MOVEI S,IOBKTL ;GET THE BLOCK TOO LARGE BIT
D.SET: IORB S,DEVIOS(F) ;SET THE APPROPRIATE BIT
POPJ P, ; AND RETURN
SUBTTL DTEMAI INTERRUPT LEVEL CODE FOR MOP MODE XFERS
DTEMAI: LOAD. P1,ED.DDB,(F) ;GET POINTER TO DDB
XCT ETDCNI(F) ;GET CONI BITS INTO T1
TXNE T1,DEAD11!TO10ER!TO11ER ;-11 DIE, OR ANY XFER ERRORS?
JRST MAIDER ; YES, SAY SO
TXNE T1,TO10DN ;TO-10 XFER COMPLETE?
JRST MAIIDN ; YES, GO DO BUFFER CLEANUP
TXNE T1,TO10DB ;ANYBODY HOME?
JRST MAIDBL ; YES, GO START XFERS
TXNE T1,TO11DN ;TO-11 XFER DONE?
JRST MAIOTC ; YES, GO SIGNAL OUTPUT DONE
; PJRST DTICLR ;FREE INTERRUPTS, NO BITS...
MAIDER: MOVEI T1,PSIDWN## ;SIGNAL DEVICE OFF LINE
LOAD. F,ED.DDB,(F) ;GET BACK DDB POINTER
PUSHJ P,MAISGL ;WAKE UP THE JOB
PUSHJ P,D.DERR ;SET IO.DER FOR UUO LEVEL
HLRZ F,DEVETD(F) ;MAKE F POINT TO DTE AGAIN
PJRST DTICLR ;CLEAR THE DTE...
SUBTTL DTEDSP - ENTRY VECTOR TO DTESER
;DTEDSP IS THE OUTSIDE WORLD'S ENTRY TO DTES IN Q'ED PROTOCOL V2.
; CALL:
; T1/ FUNCTION CODE
; T2/ CPU,,DTE (FOR FUNCTIONS DD.OPN AND DD.CET)
; T2/ ETD BLOCK ADDRESS (FOR ALL OTHER FUNCTIONS)
; T3/ FUNCTION SPECIFIC DATA
; RETURN:
; CPOPJ ;ON FAILURE
; CPOPJ1 ;ON SUCCESS
;NOTE THAT THE FAIL RETURN IS ONLY GIVEN WHEN WE ARE CALLED FROM A
;DRIVER THAT DOES NOT CURRENTLY "OWN" THE LINE.
DTEDSP::PUSHJ P,SAVE4## ;SAVE ALL PEAS
CAIL T1,0 ;FIRST RANGE CHECK THE
CAILE T1,DD.MAX ; FUNCTION CODE
STOPCD(CPOPJ##,DEBUG,DTEIKF) ;++ILLEGAL KONTROLLER FUNCTION
PUSH P,F ;SAVE F FOR A FEW
MOVE F,T2 ;SET UP F FOR GETETD AND FRIENDS
PUSH P,U ;SAVE U
PUSH P,J
PUSHJ P,@DTEDST(T1) ;AND DISPATCH ON THE FUNCTION CODE
TRNA ;IF NO SKIP, DON'T INCREMENT RETURN PC
AOS -3(P) ;SKIPPED, INCREMENT THE PC
POP P,J
POP P,U
POP P,F ;RESTORE F
POPJ P, ; AND RETURN
DTEDST: IFIW DDFOPN ;0 = OPEN CIRCUIT (INITIALIZE PROTOCOL)
IFIW DDFCLS ;1 = CLOSE CIRCUIT (HALT PROTOCOL)
IFIW DDFQUE ;2 = QUEUE OUTPUT BUFFER
IFIW DDFPRB ;3 = POST RECEIVE BUFFER
IFIW DDFCET ;4 = CHECK EXISTANCE
IFN <.-DTEDST-DD.MAX-1>,<PRINTX ?Table DTEDST is incorrect>
;DDFOPN PERFORMS THE INITIALIZATION ON THE DTE
; CALL:
; T3/ DNADLL CALLBACK ID
; F/ CPU,,DTE
; RETURN:
; CPOPJ ON ERROR
; CPOPJ1 ON SUCCESS WITH T1/ ETD ADDRESS
DDFOPN: PUSH P,T3 ;SAVE CALLBACK ID FOR A BIT
PUSH P,T4 ;SAVE RECEIVE BUFFER ADDRESS
S0PSHJ GETETD ;GET ETD BLOCK
PJRST TTPOPJ## ;NONE, RETURN
POP P,T4 ;RESTORE RECEIVE BUFFER ADDRESS
POP P,T3 ;AND CALLBACK ID
MOVEM T3,ETDLBK(F) ;SAVE CALLBACK ID FOR LATER USE
HRRZ T1,ETDUSR(F) ;GET LINE'S USER
CAIE T1,DD.DEC ;IS IT DECNET?
POPJ P, ;NO, RETURN NOW
MOVEM T4,ETDMBP(F) ;SAVE RECEIVE MESSAGE BLOCK POINTER
PUSHJ P,[PJSP T1,DTERLD] ;GO RELOAD (OR RESTART PROTOCOL)
MOVE T1,F ;GET ETD BLOCK ADDRESS
PJRST CPOPJ1## ;AND RETURN
;DDFCLS WILL RESET THE DTE
; CALL:
; F/ ETD BLOCK ADDRESS
; RETURN:
; CPOPJ1 ;ALWAYS
DDFCLS: SKIPN T1,F ;IF NEVER REALLY OPENED,
JRST CPOPJ1## ;SUCCEED VACUOUSLY (WITH NO BUFFER)
PUSHJ P,DTECLR ;RESET THE DTE
MOVE T1,ETDMBP(F) ;GET ANY ALLOCATED BUFFER
SETZM ETDMBP(F) ;CLEAR MEMORY
SETZM ETDLBK(F) ;...
PJRST CPOPJ1## ;AND RETURN
;DDFQUE QUEUE AN OUTPUT MESSAGE
; CALL:
; F/ ETD BLOCK ADDRESS
; T3/ MESSAGE BUFFER ADDRESS
; RETURN:
; CPOPJ ;ON ERROR
; CPOPJ1 ;ON SUCCESS
DDFQUE: JUMPE F,CPOPJ## ;FAIL IF NOT INITIALIZED
LOAD. T4,ED.CPN,(F) ;GET THE CPU NUMBER WE NEED TO BE ON
CAME T4,.CPCPN ;ARE WE ON IT?
STOPCD .,STOP,DTECOW ;++CALLED FOR OUTPUT ON WRONG CPU
;NO, GIVE A STOPCODE
;(BEING ON THE CORRECT CPU IS THE
; RESPONSIBILITY OF THE OWNER OF THE LINE)
SETZB P2,S ;ZERO SOME OF THESE FOR DTEQUE
SKIPN P3,T3 ;SET UP POINTER TO MESSAGE BLOCK
STOPCD DTERLD,DEBUG,DTEBMB ;++ BAD MESSAGE BLOCK POINTER
PJRST DTEQMC ;QUEUE IT OUT (PROPAGATE SUCCESS/FAILURE)
;DDFPRB POST RECEIVE BUFFER
; CALL:
; F/ ETD BLOCK ADDRESS
; T3/ MESSAGE BUFFER ADDRESS
; RETURN:
; CPOPJ ;ON ERROR
; CPOPJ1 ;ON SUCCESS
DDFPRB: JUMPE F,CPOPJ## ;FAIL IF NOT INITIALIZED
SKIPE ETDMBP(F) ;ALREADY HAVE A RECEIVE BUFFER ALLOCATED?
POPJ P, ;ALREADY HAVE A BUFFER, REFUSE THIS ONE
MOVEM T3,ETDMBP(F) ;SAVE RECEIVE MESSAGE BLOCK POINTER
PJRST CPOPJ1## ;AND RETURN
;DDFCET - CHECK DTE EXISTANCE
; CALL:
; F/ CPU,,DTE
;RETURN:
; CPOPJ IF DTE DOESN'T EXIST
; CPOPJ1 IF DTE EXISTS WITH T1/ ETD ADDRESS
DDFCET: S0PSHJ GETETD ;GET ADDRESS OF ETD BLOCK
POPJ P, ;NONE, ERROR RETURN
MOVE T1,ETDSTS(F) ;GET STATUS BITS
TXNE T1,ED.DTX ;IF IT DOES NOT EXIST,
TXNE T1,ED.DTM ;OR IS THE MASTER,
POPJ P, ;TELL DNADLL IT'S NOT THERE
MOVE T1,F ;IT'S OK FOR DECNET TO USE (LATER),
JRST CPOPJ1## ;RETURN SUCCESS WITH ETD ADDRESS IN T1
;DNDDMP - RECEIVE MESSAGE FROM 11
; CALLED WITH:
; T1/ BYTE POINTER TO WHERE IT GOES
; T2/ COUNT OF BYTES TO TRANSFER
; (TO10IB IS SET IN T2 TO INTERRUPT 11 AFTER XFER)
; RETURNS WITH MESSAGE AS PER T1
; USES T1,T2
T10TIM==^D2 ;2000 MS SOUNDS REASONABLE
DNDDMP: PUSHJ P,SAVE1## ;SAVE A PEA
MOVE P1,T2 ;SAVE THE COUNT AND FLAG
PUSHJ P,RESPTR ;RESOLVE THE INDEXED BYTE POINTER
MOVEM T1,@ETDTBP(F) ;STORE TO-10 BYTE POINTER
MOVEI T1,CLTO10 ;SET INTO PROPER STATE
XCT ETDCNO(F) ;DO CONO DTEN,(T1)
MOVE T1,P1 ;GET COPY OF BYTE COUNT
TRZ T1,TO10IB ;ZAP BIT IF ON
MOVNS T1 ;GET NEGATIVE COUNT
ANDI T1,TO10BC ;ONLY WANT THESE BITS
TRNE P1,TO10IB ;DID USER SET IT?
TRO T1,TO10IB ;YES, HE MUST HAVE WANTED IT
XCT ETDDTO(F) ;DATAO DTEN,T1
MOVEI P1,T10TIM ;TIME TO WAIT FOR TO-10
IMUL P1,TICSEC## ;CONVERT TO TICKS
ADD P1,SYSUPT## ;FIGURE OUT FUTURE TIME
DNDDM1: MOVEI T1,TO10DN!TO10ER ;CHECK FOR THESE
XCT ETDCSZ(F) ;CHECK IF DONE
JRST DNDDM2 ;GO IT
CAMG P1,SYSUPT## ;DONE YET?
POPJ P, ;SIGNAL ERROR
PUSHJ P,SCDCHK## ;SEE ABOUT OTHERS
JRST DNDDM1 ;LOOP
DNDDM2: MOVEI T1,TO10ER ;CHECK FOR ERROR
XCT ETDCSZ(F) ;LOOK
POPJ P, ;YES, GIVE BAD RETURN
JRST CPOPJ1## ;RETURN
;WAIT11 ROUTINE TO WAIT FOR ELEVEN TRANSFER
; CALL:
; F/ ETD BLOCK ADDRESS
; RETURN:
; CPOPJ ;WHEN TIMED OUT OR ERROR OCCURS
; CPOPJ1 ;ON SUCCESS
; USES T1
LDSTIM==^D2 ;LENGTH OF TIME TO WAIT FOR XFER
WAIT11: PUSHJ P,SAVE1## ;SAVE A PEA
MOVEI T1,CLTO11+TO11DB ;CLEAR TO-11 DONE, RING TO-11 DB
XCT ETDCNO(F) ;DO IT
MOVEI P1,LDSTIM ;TIME TO WAIT FOR LOAD (SECS)
IMUL P1,TICSEC## ;GET IT IN TICS
ADD P1,SYSUPT## ;TIME IN THE FUTURE
WAIT12: MOVEI T1,TO11DN!TO11ER ;LOOK FOR SOMETHING BACK
XCT ETDCSZ(F) ;CHECK FOR RETURN
JRST WAIT13 ;GOT IT, CHECK OUT REASON
CAMG P1,SYSUPT## ;OVER OUR ALOTTED TIME
POPJ P, ;TO ELEVEN TIMED OUT
PUSHJ P,SCDCHK## ;SEE ABOUT ANYBODY ELSE
JRST WAIT12 ;DO IT AGAIN
WAIT13: MOVEI T1,TO11ER ;CHECK IF IT WAS AN ERROR
XCT ETDCSO(F) ;WAS IT
AOS (P) ;MAKE IT A GOOD RETURN
POPJ P, ;BACK TO WHOEVER
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
; ; T1 = 0 IF NO FREE CORE
; ; T1 = -1 IF RELOAD BIT OR PRIMARY NOT UP
; ; T2 = EDTSTS(F)
; <OK RETURN>
;
;
; WHEN CALLED FOR A TRANSFER IN THE MCB PROTOCOL, THE TRANSFER MODE IS
; DETERMINED FROM THE BYTE SIZE IN THE BYTE POINTER STORED IN P4. ENTER
; THROUGH DTEQUF WHEN F ALREADY POINTS TO A GOOD ETD BLOCK.
;
; 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
SETO T1, ;ASSUME PROPER PROTOCOL NOT UP
LOAD. T2,ED.USR,(F) ;GET THE USER OF THIS LINE
CAIE T2,DD.ANF ;IS IT ANF?
CAIN T2,DD.NOB ; OR NOBODY (-20F)?
JRST DTEQU1 ;YES TO EITHER
CAIE T2,DD.IBM ;OR THE DN60?
JRST FUPOPJ ;NO--GIVE ERROR RETURN
DTEQU1:
IFN FTMP,<
LOAD. T1,ED.CPN,(F) ;GET CPU NUMBER
CAME T1,.CPCPN## ;CALLED ON CORRECT CPU
STOPCD .,STOP,DTEWCN,DTEPDI, ;++WRONG CPU NUMBER
>
DTEQUF: MOVE T2,ETDSTS(F) ;GET STATUS WORD
SETO T1, ;ASSUME RELOAD BIT UP OR PRIMARY DOWN
TLNE T2,(ED.PPC) ;IS PRIMARY PROTOCOL DOWN OR
TLNE T2,(ED.RLD) ;IS THE RELOAD BIT SET?
PJRST FUPOPJ## ;YES, GIVE ERROR RETURN
PUSHJ P,GT2EFT ;GET TO-11 FUNCTION TYPE
STOPCD .,STOP,DTEEFI,DTEPDI, ;++ILLEGAL FUNCTION CODE
PUSHJ P,@DTQTYP(T1) ;DISPATCH TO PROPER ROUTINE
; WHICH WILL CREATE PROPER HEADER
; FOR FUNCTION
TDZA T1,T1 ;RETURN 0 BECAUSE OUT OF FREE CORE
AOS -2(P) ;GIVE GOOD RETURN
PJRST FUPOPJ## ;GIVE NO FREE CORE RETURN
DTQTYP: DTINDR
DT16BT
DTLINE
DTLNGD
DTLNDT
DTD60D
;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
POPJ P, ;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
JUMPE T3,DTEQU4 ;IF NO DATA, SKIP THIS
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
POPJ P, ;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
POPJ P, ;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
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
POPJ P, ;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
POPJ P, ;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
;HERE IF DN60 DIRECT OR DN60 DIRECT AND INDIRECT DATA (.EMD6D)
; CALL: PUSHJ P,DTLDST ;(RH) OF S MUST POINT TO A
; ; BLOCK WHICH CONTAINS AS THE
; ; (RH) OF THE FIRST WORD THE NUMBER
; ; OF 8-BIT DIRECT BYTES THAT ARE
; ; IN THE BLOCK.
DTD60D: MOVE T3,S ;GET HERE CAUSE CAN'T INDEX THRU S
HRRZ T2,(T3) ;GET COUNT OF 8-BIT BYTES IN THE BLOCK
PUSHJ P,DTMHED ;GO SETUP THE QUEUE HEADER AND
; THE MESSAGE HEADER.
POPJ P, ;WE ARE OUT OF FREE CORE
HRLI T4,(POINT 8,) ;MAKE IT A 8-BIT BYTE POINTER
MOVE T3,S ;GET HERE CAUSE CAN'T INDEX THRU S
MOVE T1,[POINT 8,1(T3)] ;POINT TO THE DATA
HRRZ T2,(T3) ;GET COUNT OF BYTES
STOR. P3,EQ.CNT,(U) ;INDIRECT MESSAGES NEED COUNT REMEMBERED
STOR. P4,EQ.PTR,(U) ;POINTER TO INDIRECT DATA
DTLDS1: PUSH P,T3 ;SAVE T3
ILDB T3,T1 ;GET A BYTE OF DIRECT DATA
IDPB T3,T4 ;PUT IN THE MESSAGE HEADER
POP P,T3 ;RESTORE T3
SOJG T2,DTLDS1 ;ALL BYTES XFER'ED TO MSG HEADER?
; PJRST DTEQU4 ;GO SEND THE MESSAGE
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,PI.OFF ;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
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: CONO PI,PI.ON ;GIVE GOOD RETURN
JRST CPOPJ1##
;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,PI.OFF ;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,PI.ON ;OK TO MESS WITH QUEUE AGAIN
JRST DTESND ;GO SEND THIS MESSAGE
DTENX1: MOVEI T1,ED.EID ;MAKE TO-11 DTE SIDE IDLE
STOR. T1,ED.2ES,(F) ;PLACE IN TO-11 DTE STATE VAR
CONO PI,PI.ON ;OUT OF CRITICAL REGION
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
MOVEM T4,@ETDEBP(F) ;PUT INTO TO-11 POINTER EPT LOCATION
LOAD. T2,EM.CNT,(T4) ;GET MESSAGE BYTE COUNT
LOAD. T4,ED.211,(F) ;POINT TO TO-11 SECTION
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 . . .
STOPCD .,STOP,DTEDNE,DTEPDI, ;++COUNT NOT EVEN
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 TPOPJ##] ;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
;HERE WHEN MESSAGE IS TO BE SENT IN MCB (QPR V2) PROTOCOL.
; P3 POINTS TO THE MESSAGE BLOCK
T6==T4+2 ;T6 HOLDS INDEX FOR AUX BYTE POINTER
DTEQMC: SE1ENT ;MAKE THIS CODE RUN IN SECTION ONE
MOVE T2,ETDSTS(F) ;GET STATUS WORD
TLNN T2,(ED.RLD) ;RELOAD REQUESTED???
TLNN T2,(ED.PPC) ;IS PRIMARY PROTOCOL DOWN
POPJ P, ; YES, GIVE THE ERROR RETURN
LOAD. T2,ED.211,(F) ;GET POINTER TO TO-11 AREA
LOAD. T2,EC.PRT,(T2) ;GET PROTOCOL TYPE
CAIE T2,.MMCB ;RUNNING MCB PROTOCOL?
POPJ P, ; CAN'T QUEUE IT, GIVE ERROR RETURN
DTEOFF ;TURN OFF INTERRUPTS WHILE QUEUING
LOAD. T1,ED.2ES,(F) ;GET THE TO-11 STATUS OF DTE
CAIE T1,ED.EID ;ARE WE BUSY?
JRST DTEQM3 ; YES, JUST QUEUE UP THIS ONE
PUSHJ P,DTESMM ;SEND THE MESSAGE BLOCK
DTEON ;TURN DTESER BACK ON
JRST CPOPJ1## ;AND GIVE SUCCESSFUL RETURN
DTEQM3: SETZM MB.NXT(P3) ;ZAPP NEXT MB POINTER IN CURRENT MB
LOAD. T1,ED.LST,(F) ;GET ADDRESS OF LAST QUEUED MB
MOVEM P3,MB.NXT(T1) ;MAKE US BE NEXT FOR THE PREVIOUS ENTRY
STOR. P3,ED.LST,(F) ;MAKE US BE THE NEW LAST
DTEON ;TURN INTERRUPTS BACK ON
PJRST CPOPJ1## ;RETURN SUCCESS
;HERE TO INITIATE A SEND FOR QUEUED PROTOCOL VERSION 2.
;THIS ROUTINE WILL ALSO DECLARE THE DTE AS BEING BUSY
DTESMM: STOR. P3,ED.CUR,(F) ;STORE CUR PTR TO MESSAGE BLOCK FOR TO-11
; DONE PROCESSING
MOVE T1,P3 ;SET UP T1 TO POINT TO MESSAGE BLOCK
SNCALL (DNLENG##,MS.HGH) ;GET THE TOTAL LENGTH OF MESSAGE
LOAD. T4,ED.211,(F) ;POINT TO TO-11 SECTION
STOR. T1,EC.PSZ,(T4) ;STORE THE TOTAL COUNT IN PSIZE AND CSIZE
STOR. T1,EC.CSZ,(T4) ; SINCE WE DON'T BREAK UP XFERS
MOVEI T1,.TMBYT ;MAKE SURE THAT BYTE MODE TRANSFERS ARE DONE
STOR. T1,EC.TMD,(T4) ; BY SETTING IT IN TO-11 SECTION
LOAD. U,ED.OBK,(F) ;GET ADDRESS TO STUFF DATA IN
PUSHJ P,DTEQCM ;COPY DATA FROM POSSILBY EXTENDED SECTION
;DTEQCM RETURNS BYTE PTR TO DATA IN U
MOVEM U,@ETDEBP(F) ;STORE THE BYTE POINTER IN EPT
LOAD. T4,ED.211,(F) ;POINT TO THE TO-11 SECTION
LOAD. T1,EC.QCT,(T4) ;GET QCOUNT
AOJ T1, ;INCREMENT, LET IT OVERFLOW
STOR. T1,EC.QCT,(T4) ;TRUNCATE AND PUT IT BACK
MOVEI T1,ED.EDB ;MAKE NEW STATE BE BUSY
STOR. T1,ED.2ES,(F) ;STORE IT
MOVEI T1,TO11DB ;SET UP TO RING 11 DOORBELL
XCT ETDCNO(F) ;RING
POPJ P, ;RETURN TO SENDER
;HERE WITH A TO11 DONE FOR MCB
; T4 IS SET UP WITH CURRENT MESSAGE BLOCK POINTER
DTEEDM: LOAD. T1,ED.2ES,(F) ;GET TO-11 STATE
JRST @.+1(T1) ;ED.2ES HAD BETTER BE 2 BITS WIDE
CPOPJ ; ED.EID - FREE TO-11 DONE, JUST IGNORE
DTEED2 ; ED.EDB - WAITING FOR DIRECT XFER
.+2 ; ED.EIB - WE DON'T USE THIS STATE
.+1 ; NOBODY USES THIS STATE!
STOPCD DTERLD,DEBUG,DTEI1S ;++ILLEGAL TO-11 DONE STATE FOR QP2
DTEED2: MOVEI T1,ED.EID ;SET STATE TO IDLE, 'CAUSE WE REALLY ARE IDLE!
STOR. T1,ED.2ES,(F) ; IF DTESMM IS CALLED, IT WILL FIX STATE TO
; REFLECT NON-IDLENESS
SE1ENT ;RUN IN SECTION ONE
SETZ T1, ;GET A ZERO
STOR. T1,ED.CUR,(F) ;CLEAR CURRENT MB ENTRY
;HERE TO SEE IF THERE IS ANYTHING ON THE OUTPUT QUEUE TO TRANSFER. WHEN
;THERE IS NOTHING LEFT, WE DECLARE THE DTE IDLE.
LOAD. T1,ED.QUE,(F) ;GET NEXT QUEUE ENTRY
JUMPE T1,DTENM1 ;JUMP IF NO MORE TO DO
MOVE T2,MB.NXT(T1) ;GET THE NEXT ENTRY ON QUEUE
STOR. T2,ED.QUE,(F) ;MAKE HIM FIRST
MOVEI T3,ETDQUE-MB.NXT(F) ;IN CASE QUEUE IS EMPTY
SKIPN T2 ;AND IF QUEUE IS NOW EMPTY
STOR. T3,ED.LST,(F) ; MAKE TAIL POINT TO BEGINNING
PUSH P,T4 ;SAVE PTR TO FINISHED MB
PUSH P,P3 ;SAVE P3 FOR USE WITH SMM
MOVE P3,T1 ;SET UP MESSAGE BLOCK POINTER
PUSHJ P,DTESMM ;INITIATE TRANSFER OF MESSAGE BLOCK
POP P,P3 ;RESTORE P3
POP P,T4 ;RESTORE PTR TO FINISHED MB
;HERE WHEN WE JUST HAVE TO RETURN THE COMPLETED MESSAGE
DTENM1: MOVEI T1,DI.ODN ;GET "OUTPUT DONE" KONTROLLER FUNCT
MOVE T3,T4 ;GET MB POINTER INTO CORRECT AC
PJRST CALUSR ;CALL DTE USER AND RETURN
;The following returns are only used for the non-gather read version of
;DTESER. Eventually, when FTSEG is turned on (when the MCB supports
;it), this copying will be done by the DTE hardware. A side effect of
;this copy is that we do not have to play with the page table to map
;extended section message blocks into section zero for DTE transfer.
;
;Here to copy the extended message block into somewhere in section zero.
;
;DTEQCM is used only for DECNET transfers.
;
;Call: P3/ Full-word pointer to message block in extended section
; U/ 0,,pointer to DTE buffer in section 0/1
;Return:
; U/ Byte pointer to beginning of data in DTE buffer
T5==T4+1 ;(W) NEED T5 & T6 FOR EXTEND INSTRs
T6==T5+1 ;(M) BYTE PTR (MD.AUX) USES THIS INDEX
DTEQCM: PUSHJ P,SAVE1## ;SAVE P1
PUSH P,T5 ;WE NEED SIX
PUSH P,T6 ; TEMP ACS FOR MOVSLJ
SETZ T4, ;WE'LL COLLECT BYTE COUNT HERE
SKIPN T5,MB.FMS(P3) ;GET PTR TO FIRST MSD
STOPCD .,STOP,DTENOD, ;++NO DATA
DTQCM0: SKIPN T3,MD.NXT(T5) ;REMEMBER ADDR OF LAST MSD IN T5
JRST DTQCM1 ;DON'T INCLUDE LAST MSD IN CHAIN
ADD T4,MD.BYT(T5) ;COUNT THIS MSD'S DATA
MOVE T5,T3 ;MOVE TO NEXT MSD
JRST DTQCM0 ;THERE IS A NEXT MSD, GO COUNT IT
DTQCM1: MOVE T6,MD.AUX(T5) ;INDEXED 8-BIT BYTE PTR TO BEG OF SOURCE
TLNN T6,700000 ;IS IT 0410T6,,xxx?
ADD T6,[400000,,1] ;YES, IT REALLY POINTS TO NEXT WORD
HRRZ T2,T6 ;ISOLATE OFFSET FROM RH OF BYTE PTR
ADD T2,MD.ALA(T5) ; WHICH WAS INDEXED BY T6=MD.ALA
MOVEI T1,3(T4) ;GET BYTES BEFORE THIS MSD, ROUNDED UP
ASH T1,-2 ;CALCULATE WORDS FOR ALL BUT LAST MSD
XMOVEI T3,(U) ;CALC SECTION 1 DEST PTR FOR XBLT
ADD T3,T1 ;OFFSET TO ALLOW FOR HDRS LATER
HRR T6,T3 ;SAVE LOCAL BYTE PTR TO BEG OF DEST
MOVE T1,MD.BYT(T5) ;GET COUNT OF BYTES IN MSD WE'RE COPYING
ADDI T1,3+3 ;ROUND UP TO ALLOW FOR MISALIGNED BYTES
ASH T1,-2 ;CALC # OF WORDS TO COPY
EXTEND T1,[XBLT] ;COPY FROM LAST MSD TO (U) IN SEC 1
TLZ T6,17 ;GET RID OF INDEX FIELD IN LOCAL BYTE PTR
MOVN T5,T4 ;NEGATE COUNT OF BYTES BEFORE BLT'D DATA
ADJBP T5,T6 ;LOCAL BYTE PTR TO START OF MSG
MOVE U,T5 ;RETURN LOCAL BYTE PTR TO CALLER
TLO T5,P1 ;MOVSLJ NEEDS GLOBAL BPT IN T5
MOVSI P1,1 ;MAKE P1 INDEX BPT IN T5 TO SECTION 1
MOVE T3,MB.FMS(P3) ;PICK UP PTR TO FIRST MSD
DTQCM2: SKIPN MD.NXT(T3) ;IS THIS THE LAST MSD?
JRST DTQCM3 ;YES, ALREADY BLT'D, DON'T MOVSLJ IT
MOVE T1,MD.BYT(T3) ;LENGTH OF DATA IN THIS MSD
MOVE T2,MD.AUX(T3) ;BYTE PTR TO BEG OF DATA
MOVE T6,MD.ALA(T3) ;BYTE PTR IN T2 IS INDEXED BY T6
MOVE T4,T1 ;COPY SOURCE LENGTH TO DEST LENGTH
EXTEND T1,[MOVSLJ] ;COPY SECTION 3 DATA TO SECTION 1(0)
STOPCD .,STOP,DTECDF, ;++ COPY DATA FAILED
SKIPN T3,MD.NXT(T3) ;GET PTR TO NEXT MSD IN CHAIN
STOPCD .,STOP,DTENFP, ;++ NO FORWARD POINTER IN MSD
JRST DTQCM2 ;GO COPY NEXT IF ITS NOT LAST
DTQCM3: POP P,T6 ;RESTORE
POP P,T5 ; ACS, AND
POPJ P, ; RETURN TO SENDER
;DTE2CM WILL COPY A MESSAGE FROM A SECTION ZERO, NON-SEGMENTED MESSAGE
;INTO A POSSIBLY EXTENDED SECTION MESSAGE BLOCK.
;CALLED WITH T1 POINTING TO SOURCE BLOCK AND T2 POINTING TO THE
;MESSAGE BLOCK.
DTE2CM: PUSHJ P,SAVE2## ;SAVE SOME PEAS
DMOVE P1,T1 ;SAVE THE ARGUMENTS
XMOVEI T2,UD.MSD(P2) ;POINT TO THE USER DATA MSD
MOVE T3,MD.BYT(T2) ;GET LENGTH OF THE WHOLE MESSAGE
ADDI T3,3 ;CONVERT TO
LSH T3,-2 ; WORDS (ROUNDING UP)
MOVE T2,MD.ALA(T2) ;SET UP PTR TO POSSIBLY EXTENDED DEST BLK
MOVE T1,P1 ;SET UP PTR TO SOURCE FOR DNCPYW
SNCALL (DNCPYW##,MS.HGH) ;COPY THE WORDS
POPJ P, ;AND RETURN
SUBTTL DTE20 INTERRUPT SERVICE
;HERE WITH ETD (DTE CONTROL BLOCK) ADDRESS IN F
DTEINT::MOVE T1,ETDSTS(F) ;GET FLAGS INTO T1
TXNE T1,ED.PPC ;IS PRIMARY PROTOCOL RUNNING??
JRST DTEINN ; YES, GO HANDLE NORMAL INTERRUPT
TXNE T1,ED.SPC ;SECONDARY PROTOCOL??
PJRST SPCINT ; YES, DO SECONDARY PROTOCOL INTERRUPT
TXNE T1,ED.MAI ;ARE WE IN MAINTENANCE MODE?
JRST DTEMAI ; YES, GO DO SPECIAL STUFF
TXNN T1,ED.IPU ;DO WE WANT TO INDICATE PROTOCOL UP?
JRST DTICLR ; NO, JUST CLEAR DTE AND DISMISS
PUSHJ P,PPUINT ;YES, GIVE THE PROTOCOL UP INTERRUPT
; TO THE USER OF THE LINE AND PROCESS NORMALLY
DTEINN: XCT ETDCNI(F) ;CONI DTEN,T1
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
TRNE T1,DEAD11 ;11 POWER FAIL?
JRST PWRF11 ;YES
TRNE T1,TO11ER!TO10ER;IF EITHER A TO 10 OR A TO 11 ERROR
PJSP T1,DTERLD ; THEN RELOAD IT
TRNE T1,TO10DN ;TO-10 DONE? MUST CHECK BEFORE TO10DB
JRST DTE2XD ; SO WE FINISH MESSAGE BEFORE STARTING NEXT
TRNE T1,TO10DB ;TO-10 DOORBELL?
JRST DTERNG
TRNE T1,TO11DN ;TO-11 DONE?
JRST DTE2ED ;YES
;HERE WHEN WE CAN'T DETERMINE CAUSE OF INTERRUPT
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
SUBTTL QUEUED PROTOCOL VERSION 1 DRIVERS - RECEIVER
;HERE ON TO-10 DOORBELL, ETD ADDRESS IN F, STATUS IN T4
;BOTH QP1 & QP2 COME HERE INITIALLY, QP2 BRANCHES OFF IN A MOMENT
DTERNG: MOVEI T1,CL11PT ;CLEAR DOORBELL
XCT ETDCNO(F) ;CONO DTEN,(T1)
TLNE T4,(EC.LOD) ;11 WANTS TO BE RELOADED?
PJSP T1,DTERLD ;RELOAD THE DTE
LOAD. T3,ED.210,(F) ;GET 11'S TO-10 ADDRESS
LOAD. T1,EC.PRT,(T3) ;GET PROTOCOL TYPE
CAIN T1,.MMCB ;ARE WE RUNNING QP2???
JRST DTERNM ; YES, GO DO THINGS DIFFERENTLY
TRNE T4,EC.IND ;IS THIS AN INDIRECT (OLD STYLE) MSG
JRST DTEIND ;YES, BETTER GO PROCESS 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
STOPCD .,STOP,DTETNI,DTEPDI, ;++DTE NOT IDLE
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
STOPCD .,STOP,DTENFC,DTEPDI, ;++NO FREE CORE
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
STOPCD .,STOP,DTEPTL,DTEPDI, ;++PACKET TOO 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
PJSP T1,DTERLD ;-11 IS CONFUSED
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.IBK,(F) ;GET COUNT SENT IN DIRECT PART OF THIS MESSAGE
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)
LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE
LOAD. T2,ED.210,(F) ;GET PTR TO TO10 AREA
LOAD. T2,EC.PRT,(T2) ;GET THE CURRENT PROTOCOL
CAIN T2,.MMCB ;ARE WE RUNNING 20F?
JRST DTE2XM ; DONE INTERRUPT FOR QP2
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
PJSP T1,DTERLD ;-11 IS CONFUSED
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
HRL P1,.CPCPN## ;CPU 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
JRST DTERLD]
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
; HERE ON DIRECT PART OF INDIRECT 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
;HERE WHEN RECEIVE DONE INTERRUPT WHILE WAITING FOR INDIRECT PART OF INDIRECT
;MESSAGE
DTEXDI: LOAD. T1,ED.2TS,(F) ;GET TO-10 DTE STATE
CAIE T1,ED.TIB ;WERE WE EXPECTING TO-10 DONE FOR INDIRECT?
STOPCD .,STOP,DTENIS,DTEPDI, ;++DTE 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
STOPCD .,STOP,DTEIPA,DTEPDI, ;++NO POST ADDRESS
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER IN P1
HRL P1,.CPCPN## ;CPU NUMBER TO THE LEFT HALF
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.IBK,(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.IBK,(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.IBK,(F) ;SAVE FOR NEXT TIME
SKIPGE T2 ;DRIVER EATING TOO MUCH?
STOPCD .,STOP,DTEARD,DTEPDI, ;++RUNAWAY DRIVER
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.IBK,(F) ;GET NUMBER OF BYTES LEFT IN PACKET
SKIPE T1 ;SKIP IF DRIVER HAS TAKEN ENOUGH
STOPCD .,STOP,DTEDNH,DTEPDI, ;++DRIVER NOT HUNGRY
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
SUBTTL QUEUED PROTOCOL VERSION 2 DRIVERS - RECEIVER
;HERE TO HANDLE DOORBELL FOR QP2
; **** NOTE WELL **** !PROTOCOL VIOLATION!
;
; IN THE FOLLOWING CODE, THE CPQCNT FIELD IS USED EXCLUSIVLY WHEN DEALING WITH
; A TO-10 TRANSFER. THIS MEANS THAT WE INSPECT CPQCNT (EC.CPQ) FROM THE TO-10
; AREA, AND (AFTER VERIFICATION) COPY IT INTO CPQCNT IN THE TO-11 AREA. NOTE
; THAT THESE BYTES ARE BEING HANDLED IDENTICALLY TO THE QP1 DOORBELL PROCEDURE.
DTERNM: TXNE T4,EC.INI ;DOES HE WANT TO INITIALIZE PROTOCOL???
PJSP T1,DTERLD ; YES, LET UUO LEVEL TAKE CARE OF THAT
LOAD. T3,ED.211,(F) ;GET ADDRESS OF TO-11 AREA
LOAD. T1,EC.CPQ,-ETCSTS+T4 ;GET HIS QCOUNT
LOAD. T2,EC.CPQ,(T3) ;AND MY COPY OF HIS QCOUNT (CPQCNT)
CAMN T1,T2 ;ARE THEY DIFFERENT???
POPJ P, ; NO, FREE DOORBELL, IGNORE
AOJ T2, ;INCREMENT MY COPY (CPQCNT)
ANDI T2,377 ;REDUCE IT TO 8 BITS (FOR WRAPAROUND)
CAME T1,T2 ;DID WE DIFFER BY EXACTLY ONE??
PJSP T1,DTERLD ; NOPE, I BET HE WENT CRAZY
MOVEI T1,EC.RCV ;YES. GET TO-11 RECEIVE BIT
IORM T1,ETCSTS(T3) ;LET -11 KNOW THAT I RECEIVED HIS DOORBELL
STOR. T2,EC.CPQ,(T3) ;SAVE THE LATEST COPY OF HIS QCOUNT
LOAD. T4,ED.210,(F) ;GET TO-10 ADDRESS
LOAD. T1,EC.TMD,(T4) ;GET TRANSFER MODE FROM TO-10 BLOCK
SKIPE T1 ;IS IT BYTE MODE? (ONLY ONE WE SUPPORT)
STOPCD .+1,DEBUG,DTEITM ;++ILLEGAL TO-10 TRANSFER MODE IN QP2
LOAD. T1,ED.2TS,(F) ;GET TO-10 TRANSFER STATE
JRST @.+1(T1) ;THIS TABLE ASSUMES ED.2TS IS A 2 BIT FIELD
EXP DTERN1 ;ED.TID WE ARE IDLE, GET BUFFERS FOR A NEW XFER
EXP DTEBST ;ED.TDB, WAITING FOR XFER TO COMPLETE -- BAD
EXP DTERN2 ;ED.TWD, WAITING FOR NEXT PART OF SCATTER READ
EXP DTEBST ;ED.TIB, WAITING FOR SCATTER READ XFER TO COMPLETE
DTEBST: STOPCD DTERLD,DEBUG,DTEITS ;++ILLEGAL TO-10 TRANSFER STATE
;HERE WHEN WE ARE STARTING A NEW XFER (ED.2TS = ED.TID)
DTERN1: SE1ENT ;RUN THIS IN SECTION ONE
LOAD. T3,EC.PSZ,(T4) ;GET THE WHOLE MESSAGE SIZE
STOR. T3,ED.RMN,(F) ;SAVE THIS STARTING COUNT
SKIPN T1,ETDMBP(F) ;GET THE MESSAGE BLOCK POINTER
POPJ P, ;NONE, PROBABLY BEING TURNED OFF
XMOVEI T2,UD.MSD(T1) ;LOAD POINTER TO USER DATA MSD
MOVEM T2,MB.FMS(T1) ;STORE POINTER TO FIRST MSD IN MSG
MOVEM T3,MD.BYT(T2) ;STORE XFER SIZE AS MSG BYTE COUNT
LOAD. T1,ED.IBK,(F) ;POINT TO BLOCK USED FOR INPUT
HRLI T1,(POINT 8,) ;FINISH UP THE BYTE POINTER
MOVEM T1,@ETDTBP(F) ;PUT IT IN TABLE
; HERE FOR EACH SEGMENT OF A SCATTER WRITE (INBOUND) TRANSFER
DTERN2: LOAD. T1,EC.PSZ,(T4) ;GET MESSAGE SIZE
LOAD. T2,EC.CSZ,(T4) ;GET SIZE OF THIS TRANSFER, WHICH COULD BE
; DIFFERENT FROM MESSAGE SIZE IF SENDER IS
; DOING A SCATTER WRITE
CAMLE T2,T1 ;REASONABLE TRANSFER?
STOPCD DTERLD,DEBUG,DTEBTC ;++BAD TRANSFER COUNT(S)
MOVEI T3,ED.TDB ;ASSUME WAITING FOR LAST XFER
CAME T2,T1 ;CSIZE AND PSIZE EQUAL???
MOVEI T3,ED.TIB ; NO, TELL DONE INTERRUPT NOT TO CALL KONTROLLER
STOR. T3,ED.2TS,(F) ;STORE THE NEW TO-10 STATUS
MOVN T1,T2 ;GET THE NEGATIVE OF CSIZE
ANDI T1,TO10BC ;MASK OUT ALL BUT 12 BITS
TRO T1,TO10IB ;ALWAYS INTERRUPT 11
XCT ETDDTO(F) ;START THE TRANSFER
POPJ P, ;AND RETURN
;HERE WITH TO-10 DONE FOR QP2
DTE2XM: LOAD. T3,ED.211,(F) ;GET PTR TO MY -11 AREA
MOVEI T1,EC.RCV ;GET THE "RECEIVED DOORBELL" BIT
ANDCAM T1,ETCSTS(T3) ;TURN IT OFF, SO -11 KNOWS I GOT DONE INTERRUPT
LOAD. T1,ED.2TS,(F) ;GET TO-10 STATE
JRST @.+1(T1) ;THIS TABLE ASSUMES ED.2TS IS A 2 BIT FIELD
EXP DTEBS2 ;ED.TID, WE ARE IDLE (AND WE JUST GOT A DONE INT!?!?)
EXP DTE2X4 ;ED.TDB, WAITING FOR XFER TO COMPLETE
EXP DTEBS2 ;ED.TWD, WAITING FOR NEXT PART OF SCATTER READ
EXP DTE2X5 ;ED.TIB, WAITING FOR SCATTER READ XFER TO COMPLETE
DTEBS2: PJSP T1,DTERLD ;ILLEGAL, RELOAD THE DTE
; STOPCD DTERLD,DEBUG,DTEIDS ;++ILLEGAL TO-10 DONE STATE
; HERE WHEN WE ARE COMPLETELY DONE WITH A TO-10 TRANSFER. TELL THE KNOTROLLER
DTE2X4: SE1ENT ;RUN THIS IN SECTION ONE
SKIPN T2,ETDMBP(F) ;GET MESSAGE BLOCK POINTER
JRST DTE2X6 ;NONE, DRIVER MUST BE SHUTTING US DOWN
LOAD. T1,ED.IBK,(F) ;POINT TO THE INPUT BLOCK
PUSHJ P,DTE2CM ;DO THE COPY
MOVEI T1,DI.INC ;INPUT COMPLETE IS TYPE
MOVE T3,ETDMBP(F) ;GET THE POINTER TO MESSAGE BLOCK
SETZM ETDMBP(F) ;CLEAR PREVIOUS MESSAGE ADDRESS
PUSHJ P,CALUSR ;CALL DTE USER MODULE
DTE2X6: MOVEI T1,ED.TID ;NOW SAY THAT
STOR. T1,ED.2TS,(F) ; DTE IS IDLE
POPJ P, ;RETURN
;HERE WHEN WE JUST RECEIVED PART OF A SCATTER TO-10 XFER. JUST WAIT FOR NEXT
;DOORBELL
DTE2X5: MOVEI T1,ED.TWD ;WE ARE WAITING FOR DOORBELL FOR NEXT CHUNK
STOR. T1,ED.2TS,(F) ; DTE IS IDLE
POPJ P, ;RETURN
SUBTTL DTE20 INTERRUPT SERVICE
;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 AS 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 . . .
CLKDSP==EATDSP
DL1DSP==EATDSP
DH1DSP==EATDSP
KLIDSP==EATDSP
KLEDSP==EATDSP
KLCDSP==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) ;GET KLINIK STATUS
@KLEDSP(T1) ;GET 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)
>
@D6SDDS##(T1) ;DN60 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: DTEFNC ;(??) GENERATE DUMMY TABLE ENTRIES
DTEFNC (2TI,TAKCTN) ;(02) TAKE CTY-DLS CORRESPONDENCE
DTEFNC (HDS,TAKDVS) ;(07) TAKE DEVICE STATUS
DTEFNC (RDT,TAKRDT) ;(11) REQUEST FOR DATE/TIME
DTEFNC (RBI,TAKROM) ;(24) TAKE 11 ROM WORD
DTEFNC (AKA,TAKAAL) ;(25) ACK ALL
DTEFNC (KPS,KLCKPS) ;(33) TAKE KLINIK PARAMETERS
DTEFNC (DSN,TAKRPN) ;(40) TAKE DRIVE SERIAL NUMBERS
IF2, IFN .-ALLDSP-<MAXFNC+1>,PRINTX ? ALLDSP table is not the same length as FNCTAB
;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?
CAIN T1,TD60D ;DN60 DATA?
JRST GTXXF1 ;YES, DON'T CARE
HRLI T3,(CAIE T1,) ;YES, SETUP FOR INDIRECT
XCT T3 ;SKIP IF DIRECT/INDIRECT MODE IS SET CORRECTLY
POPJ P, ;NO, ITS NOT
GTXXF1: 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
STOPCD .,STOP,DTEPCI,DTEPDI, ;++FUNCTION CODE ILLEGAL
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
TD60D==5 ;DN60 DATA
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+<TLNDT>B32+<TLNDT>B35 ;(5)REQUEST FOR DEVICE STATUS
0 ;(6)UNUSED
LGLAL+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+<TLINE>B32 ;(13)FLUSH TTY LINE OUTPUT
LGL2E+<TINDR>B32 ;(14)SEND ALL
LGL2E+LGL2X+<TLINE>B32+<TLNGD>B35 ;(15)DATASET CONNECTED
LGL2E+LGL2X+<TLINE>B32+<TLNGD>B35 ;(16)DATASET HUNG UP
LGL2E+LGL2X+<TLNGD>B32+<TLNGD>B35 ;(17)DEVICE ACKNOWLEDGE
LGL2E+<TLINE>B32 ;(20)XON
LGL2E+<TLINE>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
LGL2E+LGL2X+<TD60D>B32+<TD60D>B35 ;(32)DN60 DATA
LGLAL+LGL16+LGL2E+LGL2X+<TINDR>B32+<TINDR>B35 ;(33)KLINIK PARAMETERS
LGL2E+<TLNDT>B32 ;(34)ENABLE/DISABLE AUTO-XOFF
LGL2E+<TLNGD>B32 ;(35)BREAKTHROUGH CHAR DATA
LGL2E+<T16BT>B32 ;(36)DEBUGGING MODE ON
LGL2E+<T16BT>B32 ;(37)DEBUGGING MODE OFF
LGLAL+LGL16+LGL2X+<TINDR>B35 ;(40)HERE ARE DRIVE SERIAL NUMBERS
LGL2E+<TLINE>B32 ;(41)ENABLE EIGHT BIT TTY
LGL2E+<TLINE>B32 ;(42)DISABLE EIGHT BIT TTY
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
TKD60D ;DN60 DATA
;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.IBK,(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
;HERE FOR DN60 TYPE DATA
;
TKD60D: MOVE P4,T4 ; AND THE POINTER
TRNN P2,EM.IND ;INDIRECT?
POPJ P, ;DIRECT, SO RETURN NOW
STOR. P2,ED.XFN,(F) ;STORE THE FUNCTION
MOVEI T1,4 ;NUMBER OF BYTES TO PASS OVER
ADJBP T1,T4 ;POINTER TO THE COUNT
MOVE T4,T1 ;POINTER HERE FOR GX2BYT
PUSHJ P,GX2BYT ;GET COUNT FROM THE DIRECT PORTION
STOR. T1,ED.IBK,(F) ;REMEMBER FOR INDIRECT PART
MOVE P3,T1 ;RETURN INDIRECT COUNT TO DRIVER
; IN P3
POPJ P, ;
;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.
IFIW CPOPJ## ;(-1) LOST TO-10 INDIRECT MESSAGE
EATDSP::DTEFNC ;(??) GENERATE DUMMY TABLE ENTRIES
EATMSG::PUSHJ P,GT2XFT ;GET THE TO-10 FUNCTION TYPE
STOPCD .,STOP,DTEFNG,DTEPDI ;++ILLEGAL FUNCTION CODE
PJRST @EATTAB(T1) ;DISPATCH
EATTAB: EATIND ;INDIRECT
CPOPJ## ;16 BIT
CPOPJ## ;LINE NUMBER
CPOPJ## ;LONG DIRECT
CPOPJ## ;LINE-DATA
EATIND ;DN60 DATA - COULD BE INDIRECT
;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. T2,ED.211,(F) ;GET PTR TO COMM REGION
LOAD. T3,EC.PRT,(T2) ;GET PROTOCOL TYPE
CAIN T3,.MMCB ;IS IT MCB?
JRST DTEEDM ;PROCESS FOR MCB
LOAD. T1,ED.2ES,(F) ;GET TO-11 DTE STATE
CAIN T1,ED.EDB ;WERE WE WAITING FOR TO-11 DONE
JRST DTEEDD ;YES, SEE IF WE HAVE TO SEND INDIRECT DATA
CAIE T1,ED.EIB ;WAS TO-11 INDIRECT GOING?
PJSP T1,DTERLD ;SOMEONE FIDDLING WITH SWITCHES OR DTELDR
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#
HRL P1,.CPCPN## ;INSERT CPU NUMBER
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
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)
PUSH P,F ;SAVE ETD ADDRESS
PUSHJ P,(T3) ;CALL DRIVER'S POST ROUTINE
POP P,F ;RESTORE ETD ADDRESS
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,
;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
HRLM T1,.CPCTN## ;AND IN CDB
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 ;SAVE ETD ADDRESS
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 ;RESTORE ETD ADDRESS
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: .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::MOVEI T1,.C0CDB## ;GET ADDRESS OF FIRST CDB
MOVSI T2,F20SDT## ;GET BIT TO TELL TTDINT TO SET DATE/TIME
COMSD1: IORM T2,.CP20F##-.CPCDB##(T1) ;SET BIT FOR THIS CPU
HLRZ T1,.CPCDB##-.CPCDB##(T1) ;STEP TO NEXT CDB
JUMPN T1,COMSD1 ;LOOP FOR ALL CPU'S
POPJ P, ;RETURN
;HERE FROM TTDINT WHEN THE DATE/TIME IS ACTUALLY TO BE
; SET. COMSDT DOESN'T DO THE WORK DIRECTLY BECAUSE
; WE WANT TO TELL THE -11 ON EACH CPU IN THE SYSTEM
; OF THE CHANGE
DTEDTM::PUSHJ P,SAVE4## ;SAVE P1-P4 NOW
PUSHJ P,SVEPTD ;GET MASTER ETD ADDRESS
LOAD. P1,ED.DTN,(F) ;GET DTE NUMBER IN P1
HRL P1,.CPCPN## ; AND CPU # OF THIS CPU
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
MOVSI 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
S0PSHJ 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
;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
HRL P1,.CPCPN## ;ON THIS CPU
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
S0JRST DTEQUE ;SEND MESSAGE
KPSPTR: POINT 16,.CPKPB## ;POINTER TO SAVE AREA
SUBTTL -- DRIVE SERIAL NUMBER RECEIPT
;HERE ON DIRECT PART OF THE DRIVE SERIAL MESSAGE
TAKRPN: MOVSI S,DSNRCV ;POST DRIVE SERIAL SAVE ADDRESS
MOVEI P3,^D<8*2> ;LENGTH OF DRIVE SERIAL MESSAGE
MOVE P4,DSNPTR ;POINTER TO SAVE AREA
POPJ P, ; AND RETURN
;HERE ON RECEIPT OF THE INDIRECT PORTION OF THE DRIVE SERIAL MESSAGE
DSNRCV: MOVEI P3,0 ;INDICATE ALL EXPECTED DATA RECEIVED
PJRST NEWDSN## ;TELL FILSER NEW SERIAL NUMBERS ARRIVED
;ROUTINE TO RETURN UNIT NUMBER OF BOOT DEVICE ON SPECIFIED CPU.
;CALL:
; T1/ CPU NUMBER
;RETURN:
; <ERROR>
; <SUCCESS>, T1/ UNIT NUMBER PLUS 1B0 IF BOOTED FROM DISK
DTEGBU::PUSH P,F ;DTESER STEPS ON F
HRLO F,T1 ;PUT IN FORM DTESER UNDERSTANDS
PUSHJ P,GETETD ;GET ADDRESS OF DTE CONTROL BLOCK
JRST FPOPJ## ;ERROR
LOAD. T1,ED.211,(F) ;GET TO-11 SECTION FOR THIS DTE/11
LOAD. T2,EC.RLD,(T1) ;GET RELOAD WORD FOR THIS 11
LDB T1,[POINT 3,T2,27] ;GET BOOT UNIT
TRNE T2,1B28 ;BOOTED FROM DISK?
TLO T1,(1B0) ;YES, SET BIT
JRST FPOPJ1## ;SKIP RETURN
DSNPTR::POINT 16,.CPDSN## ;POINT TO DRIVE SERIAL NUMBER FOR THIS CPU
SUBTTL KL ERROR STATUS COLLECTING
;HERE ON RECEIPT OF STATUS MESSAGE
TAKDVS: 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
LOGSET: 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)
ADDI P4,SIZE(.KEHDL,36) ;POINT TO FIRST WORD WITH DATA
HRLI P4,(POINT 16,) ;MAKE BYTE POINTER
MOVSI S,DVSDON ;ADDRESS TO GO WHEN XFER IS DONE
POPJ P, ;RETURN AND START XFER
;HERE WHEN STATUS MESSAGE IS IN, GIVE TO DRIVER AND THEN LOG IT IF APPROPRIATE
DVSDON: PUSH P,P4 ;SAVE POINTER TO STATUS MESSAGE
MOVE T2,P4 ;COPY BYTE POINTER
ILDB T2,T2 ;GET GENERAL STATUS BYTE
PUSH P,F ;SAVE ETD ADDRESS
TRNN T2,EM.CFG ;IS THIS REALLY CONFIGURATION INFO
PUSHJ P,DSDSP ;NO, REAL STATUS, HAND DATA TO DRIVER
POP P,F ;RESTORE ETD ADDRESS
POP P,T2 ;RESTORE POINTER
SETZ P3, ;WE ARE DONE WITH ALL THE DATA
MOVEI T2,-<SIZE(.KEHDL,36)>(T2) ;POINT BACK TO CHUNK PROPER
LOAD. T1,KE.1WD,(T2) ;GET GENERAL STATUS BYTE
TRNN T1,EM.ELR ;ERROR LOGGING REQUEST
JRST DVSGIV ;NO, RETURN CHUNK TO FREE CORE
DVSLOG: CONO PI,PI.OFF ;NO RACES PLEASE
HLRZ T1,.CPEAD## ;POINTER TO LAST CHUNK IN THE CHAIN
JUMPE T1,DVSDN1 ;THIS IS THE FIRST ONE
STOR. T2,KE.LNK,(T1) ;PUT THE NEW ONE AT THE END
JRST DVSDN2 ;FIX UP
DVSDN1: HRRM T2,.CPEAD## ;THIS IS THE FIRST
DVSDN2: HRLM T2,.CPEAD## ;NEW CHUNK IS ALWAYS THE LAST
CONO PI,PI.ON ;ALLOW RACES
MOVEI T2,.KLETM+1 ;RESET SELF-DESTRUCT TIMER FOR CHUNKS
MOVEM T2,.CPETM## ;TO ALLOW DAEMON A CHANCE TO GET THE INFO
JUMPN T1,CPOPJ## ;DON'T MAKE DUPLICATES
MOVEI T1,.ERKLE ;CODE FOR DAEMON
HRL T1,.CPEAD## ;POINT TO FIRST CHUNK
PJRST DAEEIM## ;KICK DAEMON
;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,.CPEAD## ;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
PUSHJ P,DVSGIV ;RETURN THE CHUNK
JRST KLERE1 ;GO FOR MORE TO DEALLOCATE
KLERE2: SETZM .CPEAD## ;CLEAR LAST,,FIRST ADDRESSES
POPJ P, ;RETURN
;SUBROUTINE TO ACTUALLY DEALLOCATE THE CORE, CALLED FROM ABOVE AND TAKDVS
DVSGIV: 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
PJRST GIVMES ;CALL WITH ADDR IN T2, COUNT IN T1
SUBTTL PROTOCOL CONTROL
;ROUTINE TO ENTER SECONDARY PROTOCOL FOR THE FIRST TIME
; USES T ACS.
ENTSPC::PUSHJ P,SVEPTD ;SAVE F,T4 AND SETUP DTE & EPT ADDRESSES
CONI PI,T2 ;GET CURRENT PI STATE
PUSH P,T2 ;SAVE FOR LATER
CONO PI,PI.OFF ;TURN OFF IN CASE STUFF RUNNING
MOVSI T2,(ED.PPC) ;GET READY TO CLEAR PRIMARY PROTOCOL BIT
ANDCAM T2,ETDSTS(F) ;CLEAR BIT. NOW INTERRUPTS WILL GO
; THRU SECONDARY INTERRUPT ROUTINE
LOAD. T2,ED.211,(F)
MOVSI T1,(EC.PWF) ;CLEAR POWER FAIL BIT
ANDCAM T1,ETCSTS(T2) ; SO 11 WILL BELIEVE WE ARE OK
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,[POP P,T2 ;GO KILL -11
TRNE T2,PI.PIA ;BUT FIRST, RESTORE PI
CONO PI,PI.ON ;BACK ON
PJRST DTERLD] ;AND TELL DTELDR
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
POP P,T2 ;GET PREVIOS PI STATE
TRNE T2,PI.PIA ;WERE THEY ON BEFORE
CONO PI,PI.ON ;TURN ON PI SYSTEM AND
PUSHJ P,SPCGSF ;GET SECONDARY PROTOCOL FLAGS INTO .CPSPF
POPJ P, ;RETURN
REPEAT 0,<
;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)
MOVE T1,.CPCPN## ;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
> ;END OF REPEAT 0
;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
PUSHJ P,SSEC0## ;USE SECTION 0 CAUSE OF INDIRECTION IN DTEFEK
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)
SKIPN T2,@DTEFEK##(T1) ;SEE IF A FEK THERE
POPJ P, ;NO GET OUT NOW
MOVEI T1,FF.DWN ;GET THE "FEK DIED" FUNCTION CODE
XCT FEKDSP(T2) ; AND TELL SOMEONE THEY LOST AN 11
POPJ P, ;RETURN
;STAPPC ROUTINE TO START PRIMARY PROTOCOL ON ALL DTE'S.
; DTEINI MUST BE CALLED FIRST.
; THIS ROUTINE FIRST STARTS PRIMARY PROTOCOL ON DTE'S 3-0, THEN REQUESTS
; DATE AND TIME FROM THE MASTER.
;RETURNS NON-SKIP ALWAYS
STAPPC::MOVSI T1,(ST%NPP) ;SEE IF ONCE PREVENTED THIS (/NOPPC)
TDNE T1,CNFST2## ;...
POPJ P, ;YES, KEEPA YOUR HANDS OFFA DEM DTES
PUSHJ P,SVEPTD ;SAVE F, T4 ETC.
MOVEI F,3 ;GET NUMBER OF LAST (POSSIBLE) DTE
HRL F,.CPCPN## ;GET CPU NUMBER IN LEFT HALF.
STAPP1: PUSH P,F ;SAVE "XWD CPU,DTE"
PUSHJ P,GETETD ;FIND DTE BLOCK
JRST STAPP2 ;NON-EXISTANT
MOVE P1,(P) ;DTE NUMBER
MOVX T1,ED.SAL ;THIS CALL IS FROM START ALL
IORM T1,ETDSTS(F) ;TELL STXPPC
PUSHJ P,DTECLR ;CLEAR OUT ANY OLD QUEUES
HLRZ T1,(P) ;GET CPU #
CAME F,DTEMAS##(T1) ;DON'T DO CFE YET
PUSHJ P,STXPPC ;START PRIMARY PROTOCOL
JFCL ; WE DON'T CARE IF WE CAN'T
STAPP2: MOVX T1,ED.SAL ;START-ALL FLAG
ANDCAM T1,ETDSTS(F) ;MAKE SURE IT'S CLEAR FOR OTHER CALLERS
POP P,F ;GET "XWD CPU,DTE" BACK
TRNE F,-1 ;IF WE HAVEN'T GOTTEN DOWN TO "ZERO"
SOJA F,STAPP1 ; DECREMENT TO THE NEXT ONE AND START THAT.
;NOW REQUEST DATE AND TIME FROM THE MASTER.
PUSHJ P,GTEPD ;GET F := ETD ADDRESS OF THE MASTER
PUSHJ P,DFKSE0 ;SET LINE-USER TYPE FOR RSX20F
MOVX T1,ED.SAL ;FROM START-ALL FLAG
IORM T1,ETDSTS(F) ;LIGHT IT FOR THIS CALL
PUSHJ P,STXPPC ;START PRIMARY ON MASTER NOW
JFCL ;SHOULD NEVER FAIL
MOVX T1,ED.SAL ;START-ALL FLAG
ANDCAM T1,ETDSTS(F) ;LEAVE IT CLEAR FOR DTELDR
POPJ P, ;ALL DONE. ALL DTE'S STARTED, MASTER TICKLED.
;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
STXPPC: PUSHJ P,SAVE4## ;SAVE P1-P4 FOR CALL TO DTEQUE
STXPP0: PUSHJ P,GTEPT ;GET EPT, F ALREADY SET UP
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
MOVE T1,ETDSTS(F) ;GET SOME BITS
MOVE T2,ETDUSR(F) ;AND THE LINE USER
TLNE T1,(ED.DTM) ;IF NOT THE MASTER,
JRST STXPP4 ;MASTER--JUST USE WHAT'S BEEN SET
CAIE T2,DD.NOB ;AND WE DON'T KNOW THE USER,
CAIN T2,DD.DEC ;OR IT'S AN MCB
TRNA ;THEN MAKE SURE OF QP2
JRST STXPP4 ;(NO--JUST USE WHAT'S BEEN SET)
LOAD. T3,ED.210,(F) ;YES--GET 11'S TO-10 ADDRESS
LOAD. T2,ED.211,(F) ;AND OUR TO-11 ADDRESS
MOVEI T1,.MMCB ;AND THE MCB PROTOCOL TYPE
STOR. T1,EC.PRT,(T2) ;SET IN TO-11 SECTION
STOR. T1,EC.PRT,(T3) ;AND IN TO-10 SECTION
STXPP4: LOAD. T3,ED.210,(F) ;GET 11'S TO-10 SECTION ADDRESS
LOAD. T2,EC.PRT,(T3) ;GET PROTOCOL TYPE
SETZ T1, ;AT LEAST CLEAR THE QUEUE COUNTS
CAIE T2,.MMCB ;IS IT MCB TYPE?
MOVSI T1,(EC.VEX!EC.QIU) ;NO, VALID EXAMINE, Q PROTOCOL IN USE
MOVEM T1,ETCSTS(T3) ;INITIALIZE STATUS WORD
;(ZEROES QUEUE COUNTS TOO)
LOAD. T3,ED.211,(F) ;GET TO-11 SECTION ADDRESS
MOVEM T1,ETCSTS(T3) ;DO SAME FOR TO-11 SECTION STATUS
CAIE T2,.MMCB ;ARE WE RUNNING MCB PROTOCOL?
JRST STXPP1 ;NO, SKIP THIS STUFF
MOVEI T1,CLRDTE ;RESET DTE
XCT ETDCNO(F) ;DO IT
SETZM DTEEPW(T4) ;CLEAR VALID EXAMINE
SETZM DTETBP(T4) ; AND BYTE POINTERS IN CASE
SETZM DTEEBP(T4) ; . . .
MOVEI T1,TO11DB ;RING 11'S DOORBELL TO TELL HIM
XCT ETDCNO(F) ;RING
STXPP1: PUSH P,T4 ;SAVE T4
LOAD. T3,ED.10A,(F) ;POINT TO 10'S COMM AREA
LOAD. T4,ED.11A,(F) ;POINT TO 11'S COMM AREA
SETZ T1, ;INITIALIZE VERSION TYPES
CAIE T2,.M20F ;OLD STYLE?
MOVEI T1,.CVMCB ;NO, USE MCB COMM REGION VERSION
STOR. T1,EC.CVR,(T3) ;STORE IT IN COMM REGION VERSION FIELD
STOR. T1,EC.CVR,(T4) ;DO IT FOR TO-11 ALSO
CAIE T2,.M20F ;OLD STYLE?
MOVEI T1,.PVMCB ;NO, USE MCB'S PROTCOL VERSION
STOR. T1,EC.PVR,(T3) ;STORE IN TO-10 FIELD
STOR. T1,EC.PVR,(T4) ;STORE IN TO-11 FIELD
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
POP P,T4 ;GET BACK EPT POINTER
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
CAIN T2,ETOSIZ ;DOES THIS ALLOW THE -11 TO TALK TO US?
ADDI T2,ET2SIZ ;NO--FIX IT
ASH T2,3 ;CONVERT SIZE OF OWNERS SECTION TO WORDS
MOVEM T2,DTEDPW(T4) ;THAT'S THE DEPOSIT PROTECTION
;***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 THINK 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
STOPCD .,STOP,DTEQEF,DTEPDI, ;++QUEUE ENTRY FULL
LOAD. T1,ED.QUE,(F) ;DON'T LET CORE DISAPPEAR
SKIPE T1
STOPCD .,STOP,DTETQP,DTEPDI, ;++FOUND QUEUE POINT
MOVSI T1,(ED.DTM) ;IS THIS THE MASTER?
TDNN T1,ETDSTS(F) ;?
JRST STXPP2 ;NO, JUST RING DOORBELL
MOVE T1,[MC1120,,C1120F] ;POINT TO CAL11. UUO VECTOR
PUSHJ P,C11VEC ;SET UP BASE TABLE
PUSHJ P,SPCGSF ;GET FLAGS INTO .CPSPF
MOVEI T1,DT.LSP!DT.RST;LEAVE SECONDARY PROTOCOL, RESET COMM REGION
PUSHJ P,SPCMD ;DO IT
MOVSI T1,(ED.SPC!ED.PPP) ;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
S0PSHJ DTEQUE ;SEND THE MESSAGE
POPJ P, ;NO GOOD, GIVE ERROR RETURN
PUSHJ P,DTESDT ;SEND DATE/TIME TO -11
SETZB P3,S ;CLEAR JUNK
MOVE P2,[XWD .EMCLK,.EMRDT] ;REQUEST DATE AND TIME
MOVX T1,ED.SAL ;START-ALL FLAG
TDNE T1,ETDSTS(F) ;ONLY SEND THIS IF SET
S0PSHJ DTEQUE ;SEND THIS MESSAGE (S, P1 & P4 STILL SETUP)
JFCL ;SHOULDN'T FAIL
MOVE P2,DEBUGF## ;GET DEBUG BIT
LSH P2,-^D35 ;RIGHT-JUSTIFIED
DPB P2,[POINT 1,ETDSTS(F),^L<ED.DBG>] ;SAVE FE DEBUG MODE
MOVN P2,P2 ;STUPID FUNCTIONS WERE ASSIGNED BACKWARDS
MOVEI P2,.EMDBF(P2) ;GET FUNCTION TO PERFORM
S0PSHJ DTEQUE ;SET/CLEAR FE DEBUG MODE AS PER DEBUGF
POPJ P, ;SIGH....
JRST CPOPJ1## ;AND GIVE SKIP RETURN
STXPP2: LOAD. T3,ED.211,(F) ;POINT TO 11 REGION
LOAD. T2,EC.PRT,(T3) ;GET PROTOCOL TYPE
CAIN T2,.MMCB ;IS IT THE MCB PROTOCOL?
JRST STXQP2 ;START IT UP
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
HLRZ T1,P1 ;ISOLATE CPU #
SKIPN T2,@DTEFEK##(T1) ;SEE IF A FEK FOR THIS DTE
RETSKP ;IF NO FEK, GET OUT NOW
MOVEI T1,FF.UP ;GET THE "11 UP" FUNCTION CODE
XCT FEKDSP(T2) ;TELL SOMEONE HIS 11 IS THERE
RETSKP ;GIVE GOOD RETURN
STXPP3: LOAD. T2,ED.11A,(F) ;GET 11'S AREA HEADER ADDRESS
LOAD. T1,EC.CVR,(T2) ;GET COMM. REGION VERSION
JUMPN T1,DTECLR ;FAIL IF -11 DIDN'T CLEAR IT
LOAD. T2,EC.PVR,(T2) ;OK--GET LINE-USER TYPE INDEX
PUSHJ P,DFKSET ;SETUP FOR OUR PREFERRED STYLE
JUMPE T2,DTECLR ;FAIL IF WE DIDN'T REALLY SET A TYPE
MOVEI T1,.M20F ;PROTOCOL TYPE FOR NON-MCB
LOAD. T2,ED.211,(F) ;GET TO-11 ADDRESS
STOR. T1,EC.PRT,(T2) ;MAKE SURE WE KNOW IT'S NOT AN MCB
MOVEI T1,CLRDTE+PILDEN+0 ;BITS TO SILENCE A DTE
XCT ETDCNO(F) ;QUIET THE -11 BEFORE WE TRY AGAIN
JRST STXPP0 ;AND THEN TRY IT AGAIN
;STXQP2 -- ROUTINE TO START QUEUED PROTOCOL V. 2 ON A DTE
MCINI1==^D5 ;WAIT THIS LONG ON FIRST PASS
MCINI2==^D3 ;NOT AS LONG FOR SECOND
STXQP2: MOVE T1,[MC11MC,,C11MCB] ;POINT TO CAL11. UUO VECTOR
PUSHJ P,C11VEC ;SET UP BASE TABLE
MOVEI T1,<ETOSIZ+ET2SIZ>*10 ;GET SIZE OF DEPOSIT WINDOW
MOVEM T1,DTEDPW(T4) ; AND STORE IT IN EPT
LOAD. T2,ED.11A,(F) ;GET POINTER TO 11 OWNING SECTION
LOAD. T3,ED.10A,(F) ; AND 10'S
MOVEI T1,2 ;MCB IS ALWAYS SIZE TWO (MAGIC)
STOR. T1,EC.OSZ,(T2) ;STORE IT
STOR. T1,EC.OSZ,(T3)
LOAD. T3,ED.211,(F) ;PTR TO TO11 REGION
LOAD. T4,ED.210,(F) ;PTR TO TO10 REGION
SETZM ETCQSZ(T3) ;ZERO THESE TWO DYNAMIC WORDS
SETZM ETCQSZ(T4)
MOVSI T1,(EC.INI!EC.VEX) ;SET INI AND VEX (VALID EXAMINE)
MOVEM T1,ETCSTS(T3) ;LIGHT THEM
MOVEI T1,PILDEN+PI0ENB+TO11DB ;ENABLE DTE AND RING 11'S DOORBELL
XCT ETDCNO(F) ;DO IT
MOVEI P2,MCINI1 ;TIME TO WAIT
PUSHJ P,WAITDB ;WAIT FOR IT
POPJ P, ;ERROR - INITIALIZATION FAILURE
MOVE T2,ETCSTS(T4) ;GET THE STATUS WORD
TLNN T2,(EC.INI) ;DID HE SET THE INI BIT?
POPJ P, ;GIVE FAILURE RETURN
MOVEI T1,CL11PT ;CLEAR TO-10DB
XCT ETDCNO(F) ;DO IT
LOAD. T1,EC.PRT,(T4) ;GET DESIRED PROTOCOL TYPE
CAIN T1,.M20F ;IS IT BACK TO RSX20F (ANF/DN60)?
JRST STXPP3 ;YES--GO FIX IT UP
PUSH P,T3 ;SAVE A REGISTER
PUSH P,T4 ;OR TWO
MOVEI T2,DD.DEC ;LINE-USER OF DECNET
CAME T2,ETDUSR(F) ;IF WE DIDN'T KNOW BEFORE,
PUSHJ P,DFKSET ;WE DO NOW
POP P,T4 ;RESTORE TO-10 POINTER
POP P,T3 ;AND TO-11 POINTER
JUMPE T2,DTECLR ;FAIL IF CAN'T SET LINE-USER OF 'DECNET'
MOVX T1,ED.SAL ;START-ALL BIT
TDNE T1,ETDSTS(F) ;WAS IT?
PJRST DTECLR ;YES--WAIT FOR NML TO START AN MCB
MOVSI T1,(EC.INI) ;THIS IS THE INI BIT
ANDCAM T1,ETCSTS(T3) ;CLEAR IT
MOVEI T1,TO11DB ;TO-11 DOORBELL
XCT ETDCNO(F) ;RING IT
MOVEI P2,MCINI2 ;LENGTH OF TIME TO WAIT
PUSHJ P,WAITDB ;WAIT FOR IT
POPJ P, ;ERROR - INITIALIZATION FAILURE
MOVE T2,ETCSTS(T4) ;GET THE STATUS WORD
TLNE T2,(EC.INI) ;WAS THIS LIT?
POPJ P, ;GIVE FAILURE RETURN
MOVSI T1,(ED.MAI!ED.PPP) ;WE ARE OUT OF MAINT MODE
ANDCAM T1,ETDSTS(F) ;SHOW THIS
MOVSI T1,(ED.IPU) ;ALSO INDICATE THAT WHEN WE GET THE
IORM T1,ETDSTS(F) ; INTERRUPT FOR THIS DTE, WE HAVE TO
; GIVE LINE'S USER A PROTOCOL UP
MOVEI T1,ETDQUE-MB.NXT(F) ;GET PSEUDO MB ADDRESS SO THAT NEXT STOR.
STOR. T1,ED.LST,(F) ; TO ED.LST WILL SET UP ED.QUE
;If we are not doing gather reads, we will get a piece of free core to
; use for doing the transfer in section zero. When the message block is
; ready to be transfered, it is copied into this block from a possibly
; extended section.
LOAD. T1,ED.OBK,(F) ;GET PTR TO OUTPUT BLOCK
JUMPN T1,STXQP3 ;JUMP IF WE ALREADY HAVE ONE
MOVEI T2,UBLSIZ ;WE NEED BLOCKS THIS BIG
ADDI T2,SIZE(.EQLEN,36) ;LITTLE ROOM FOR THE HEADER
PUSH P,T2 ;SAVE THIS SIZE
PUSHJ P,MESCOR ;GET A PIECE OF BIG
JRST TPOPJ## ;FIX STACK AND RETURN
STOR. T1,ED.OBK,(F) ;STORE THE POINTER TO IT
POP P,T2 ;RESTORE THE SIZE
STOR. T2,EQ.SIZ,(T1) ;SAVE IT
STXQP3:
LOAD. T1,ED.IBK,(F) ;GET PTR TO INPUT BLOCK
JUMPN T1,STXQP4 ;JUMP IF WE ALREADY HAVE ONE
MOVEI T2,UBLSIZ ;MAXIMUM SIZE BLOCK FOR INPUT
ADDI T2,SIZE(.EQLEN,36) ;LITTLE ROOM FOR THE HEADER
PUSH P,T2 ;SAVE THIS SIZE
PUSHJ P,MESCOR ;GET A PIECE OF BIG
JRST TPOPJ## ;FIX STACK AND RETURN
STOR. T1,ED.IBK,(F) ;STORE THE POINTER TO IT
POP P,T2 ;RESTORE THE SIZE
STOR. T2,EQ.SIZ,(T1) ;SAVE IT
STXQP4:
;Here we start the DTE and set ourselves up for interrupts.
;All setup code must be done before this.
MOVEI T1,PI0ENB+PILDEN+PPCPI ;SET PI STATE
XCT ETDCNO(F) ;DO CONO DTEX,(T1)
JRST CPOPJ1## ;GIVE GOOD RETURN
;PPUINT IS CALLED FROM DTEINT ON THE FIRST DTE INTERRUPT AFTER STXQP2
;HAS FINISHED SETTING UP FOR PRIMARY PROTOCOL. IT WILL CALL THE USER OF
;THE LINE TO INDICATE THAT THE PROTOCOL IS UP.
PPUINT: MOVSI T1,(ED.IPU) ;TURN OFF "GIVE PROTOCOL UP INTERRUPT"
ANDCAM T1,ETDSTS(F)
MOVSI T1,(ED.PPC) ;WE CAN NOW SAY WE ARE IN PRIMARY PROTOCOL
IORM T1,ETDSTS(F) ;TURN IT ON
MOVSI T1,(ED.LLS) ;GET LINE STATE REPORTED FLAG
TDNE T1,ETDSTS(F) ;WAS LAST LINE STATE REPORTED AS UP?
POPJ P, ;YES, RETURN
IORM T1,ETDSTS(F) ;MARK LAST STATE REPORTED AS UP
MOVEI T1,DI.LSC ;SIGNAL A PROTOCOL UP RIGHT AWAY
MOVEI T3,LS.ON ;NEW LINE STATE OF ON
PJRST CALUSR ;CALL DTE USER AND 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)
MOVSI T4,F20LPP## ;LOST PROTOCOL
IORM T4,.CP20F## ;LIGHT FOR TTDINT
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: PUSHJ P,ENTSPC ;ENTER SECONDARY PROTOCOL JUST IN CASE
POP P,T4
POP P,F ;RESTORE F, T4
JRST (T3) ;AND RETURN TO CALLER'S PC IMMEDIATELY
;ROUTINE TO CAUSE THE MASTER -11 TO RELOAD THE -10
;THIS IS INTENDED TO BE CALLED PRIOR TO EXECUTING A HALT INSTRUCTION
;OR WHEN THE BOOTSTRAP IS NOT AVAILABLE FOR RELOADING THE MONITOR.
;CALL: PUSHJ P,LOAD10
;
; *** RETURNS IN PRIMARY PROTOCOL ***
LOAD10::PUSHJ P,SVEPTD ;SAVE F, T4, AND SETUP DTE & EPT ADDRESSES
SKIPE DTEEPW(T4) ;ALREADY IN PRIMARY PORTOCOL?
SKIPN T1,ETDKAR(F) ;GET SAVED EXAMINE PROTECTION WORD
JRST LOAD1A ;ALREADY IN PP OR NO SAVED EPW
MOVEM T1,DTEEPW(T4) ;TURN ON VALID EXAMINE
MOVEI T1,DT.LSP ;BIT TO LEAVE SECONDAY PROTOCOL (ENTER PRIMARY)
SETZM DTEFLG(T4) ;CLEAR DONE FLAG
MOVEM T1,DTECMD(T4) ;STUFF COMMAND WHERE -20F WILL FIND IT
MOVEI T1,TO11DB ;DOORBELL
XCT ETDCNO(F) ;TELL -20F TO ENTER PRIMARY PROTOCOL
LOAD1A: MOVX T1,EC.LOD ;GET THE LOAD BIT
IORM T1,ETCSTS(F) ;SET FOR THE -11 TO READ
MOVEI T1,TO11DB ;DOORBELL
XCT ETDCNO(F) ;REQUEST A DUMP/LOAD SEQUENCE
POPJ P, ;RETURN
;LOOP OVER EACH DTE AND CALL A SUBROUTINE
;CALL: MOVE T1, SUBROUTINE ADDRESS
; PUSHJ P,DTEAPP
DTEAPP::PUSHJ P,SSEC0## ;RUN IN SECTION ZERO
PUSHJ P,SAVE1## ;SAVE P1
PUSH P,F ;SAVE F
PUSH P,T1 ;SAVE SUBROUTINE ADDRESS
MOVSI P1,-4 ;AOBJN POINTER
DTEAP1: HRLZ F,.CPCPN## ;CPU NUMBER
HRR F,P1 ;DTE NUMBER
PUSHJ P,GETETD ;FIND ETD BLOCK
SKIPA ;NOT THERE
PUSHJ P,@(P) ;CALL SUBROUTINE
JFCL ;IGNORE ERRORS
AOBJN P1,DTEAP1 ;LOOP FOR ALL DTES
POP P,(P) ;PHASE STACK
POP P,F ;RESTORE F
POPJ P, ;RETURN
;ROUTINE TO INITIATE A PROTOCOL PAUSE
;CALL WITH THE PI SYSTEM OFF TO PREVENT SOME NASTY RACES
;
;NOTE THAT THE -11 WILL KEEP A TIMER RUNNING ON US, AND WILL CAUSE A
;RELOAD 30 SECONDS AFTER WE ENTER PROTOCOL PAUSE.
DTESPP::SKIPE DINITF## ;SYSTEM STARTUP?
POPJ P, ;THIS IS A NOOP
MOVEI T1,SETPP ;ROUTINE TO EXECUTE
PJRST DTEAPP ;SET PROTOCOL PAUSE
SETPP: MOVSI T1,(ED.PPC) ;ONLY DO THIS IF ACTUALLY IN PRIMARY PROTOCOL
TDNN T1,ETDSTS(F)
POPJ P, ;NOT IN PRIMARY PROTOCOL, THIS IS A NO-OP
LOAD. T4,ED.DTN,(F) ;GET DTE NUMBER
ASH T4,3 ;TIMES 8
ADD T4,.CPEPT## ;INDEX INTO THE EPT
SETZM DTECMD(T4) ;ENSURE THAT -20F DOESN'T SEE "ENTER SECONDARY"
MOVE T1,DTEEPW(T4) ;COPY OLD PROTOCOL STATUS
LOAD. T2,ED.DTN,(F) ;GET DTE # OF THIS FRONT END
MOVEM T1,.CPEPW##(T2) ;SAVE FOR LATER
SETZM DTEEPW(T4) ;INITIATE A PROTOCOL PAUSE
MOVEI T1,TO11DB ;SET DOORBELL TO GET -11'S ATTN
SKIPE .CPEPW##(T2) ; ... UNLESS IT'S IGNORING US ALREADY
XCT ETDCNO(F) ;TELL IT TO IGNORE US FOR A WHILE
MOVX T1,ED.PPP ;PROTOCOL-PAUSE STATUS BIT
IORM T1,ETDSTS(F) ;REMEMBER FOR LATER
POPJ P, ;RETURN PREVIOUS STATE
;ROUTINE TO TERMINATE PROTOCOL PAUSE
DTERPP::SKIPE DINITF## ;SYSTEM STARTUP?
POPJ P, ;THIS IS A NOOP
MOVEI T1,CLRPP ;ROUTINE TO EXECUTE
PJRST DTEAPP ;CLEAR PROTOCOL PAUSE
CLRPP: MOVX T1,ED.PPP ;PROTOCOL-PAUSE STATUS BIT
TDNN T1,ETDSTS(F) ;DID WE SET IT?
POPJ P, ;NO--NO NEED TO CLEAR IT
ANDCAM T1,ETDSTS(F) ;YES--CLEAR IT OUT
LOAD. T4,ED.DTN,(F) ;GET DTE NUMBER
ASH T4,3 ;TIMES 8
ADD T4,.CPEPT## ;INDEX INTO THE EPT
LOAD. T2,ED.DTN,(F) ;GET DTE # OF THIS FRONT END
MOVE T1,.CPEPW##(T2) ;GET OLD EPW
MOVEM T1,DTEEPW(T4) ;RESTORE PRIMARY PROTOCOL
MOVEI T1,TO11DB ;TELL -11 WE'RE BACK
SKIPE DTEEPW(T4) ; ... UNLESS WE'RE NOT (SNH)
XCT ETDCNO(F) ;RING THE 'OLE BELL
POPJ P, ;DONE
;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
;ROUTINE TO CHECK TO SEE IF THE MASTER IS OK.
; CALL IS:
; PUSHJ P,SKPMRN
; <NOT - AT LEAST MARKED AS NEEDING RELOADING>
; <IS>
SKPMRN::PUSHJ P,SVEPTD ;SAVE F,T4; GET MASTER CTL BLOCK ADDRESS
MOVSI T4,(ED.RLD) ;GET NEEDS RELOADING BIT
TDNN T4,ETDSTS(F) ;DOES IT?
AOS (P) ;NO, GIVE SKIP RETURN
POPJ P, ;RETURN
SUBTTL ONCE PER SECOND ACTIVITIES
DTESEC::PUSH P,F ;SAVE FOR DTE CONTROL BLOCK
HRLZ T4,.CPCPN## ;START WITH FIRST DTE ON THIS CPU
DTESC1: MOVE F,T4 ;GET NEXT DTE # '' CPU #
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
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?
STOPCD .,STOP,DTEBAA,DTEPDI, ;++BUFFER ALREADY THERE
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 CPU REMOVAL CODE FOR DTESER
; THIS ROUTINE WILL CLEAR OUT ALL THE DTES ON A GIVEN CPU. IT CAN BE CALLED ON
; ANY CPU FOR ANY CPU. ITS MAIN PURPOSE IS TO RELEASE ALL CHUNKS OF CORE
; WHICH HAVE BEEN ALLOCATED TO THOSE DTES. THIS INCLUDES QUEUED UP OUTPUT
; BUFFERS, SECTION ZERO TRANSFER BUFFERS, AND ANYTHING ELSE THAT TAKES UP
; LOTS OF SPACE.
;
; CALL: MOVx T1,CPU#
; PUSHJ P,KILDTE##
KILDTE::
PUSHJ P,SAVE1## ;SAVE A P
PUSH P,F ;SAVE F
HRLZ P1,T1 ;SAVE CPU,,DTE#
KILDT1: TRNE P1,777774 ;DID WE OVERFLOW?
PJRST FPOPJ## ; YES, RETURN NOW
MOVE F,P1 ;GET CPU,,DTE INTO F
PUSHJ P,GETETD ;GET ADDRESS OF ETD
AOJA P1,KILDT1 ; NON-EXISTANT
LOAD. T2,ED.211,(F) ;GET THE TO-11 SECTION
LOAD. T2,EC.PRT,(T2) ;GET THE PROTOCOL TYPE
CAIN T2,.MMCB ;TALKING DECNET?
PUSHJ P,DTECLK ;KILL THE DTE
AOJA P1,KILDT1 ;NEXT DTE PLEASE
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::PUSHJ P,SSEC0## ;MAY BE CALLED BY DECnet IN NON-ZERO SECTION
LOAD. T1,ED.CPN,(F) ;GET THE CPU NUMBER OF THIS DTE
CAME T1,.CPCPN## ;ARE WE ON THE CORRECT CPU?
STOPCD CPOPJ,DEBUG,DTEDWC ;++DTECLR CALLED ON WRONG CPU
MOVSI T1,(ED.PPC) ;IF RUNNING PRIMARY PROTOCOL,
TDNE T1,ETDSTS(F) ;
PUSHJ P,LEVPPC ;LEAVE PRIMARY PROTOCOL ON THIS DTE/11
PUSHJ P,GTEPT ;MAKE SURE OF EPT ADDRESS
LOAD. T1,ED.DTN,(F) ;DTE NUMBER FOR THIS FE
ASH T1,3 ;8-WORD BLOCKS
ADD T4,T1 ;ADDRESS OF THIS DTE'S VARIABLES
SETZM DTEEPW(T4) ;MAKE SURE HE KNOW'S HE'S DEAD
MOVEI T1,CLRDTE+PILDEN+0 ;CLEAR THIS DTE AND ZERO PI ASSIGNMENT
XCT ETDCNO(F)
DTECLK:
; HERE TO CLEAR DTE FROM ANY CPU. AFTER THIS POINT, THERE SHOULD BE NO I/O
; INSTRUCTIONS OR ANY REFERENCES TO PER-CPU DATA BASES (SUCH AS .CPxxx).
MOVEI T1,0 ;CLEAR CAL11. VECTOR
MOVSI T2,(ED.DTM) ;GET MASTER DTE BIT
TDNE T2,ETDSTS(F) ;IS THE THE MASTER DTE?
PUSHJ P,C11VEC ;YES--ZAP CAL11. VECTOR
LOAD. T2,ED.211,(F) ;POINT TO THE TO-11 SECTION
LOAD. T2,EC.PRT,(T2) ;GET THE PROTOCOL TYPE
MOVSI T1,(ED.RLD) ;CLEAR RELOAD BIT
ANDCAB T1,ETDSTS(F) ;SINCE THIS 11 IS NOW QUIET.
CAIN T2,.MMCB ;RUNNING THE MCB?
PJRST DTECLM ;YUP, CLEAN OUT THE MESS
TLNE T1,(ED.DTM) ;IF THE MASTER
PUSHJ P,[PUSHJ P,CLRDSN## ;FORGET DISK DRIVE SERIAL NUMBERS
PJRST TTDRLD##] ;RESTART -20F LINES
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 TO DO CLEARING PROCESSING FOR QUEUED PROTOCOL VERSION 2 (MCB).
DTECLM: MOVEI T1,0 ;CLEAR CAL11.
PUSHJ P,C11VEC ; VECTOR ADDRESS
MOVX T1,ED.EID ;GET TO-11 IDLE STATE INDICATOR
STOR. T1,ED.2ES,(F) ;MAKE TO-11 SIDE IDLE
MOVX T1,ED.TID ;GET TO-10 IDLE STATE INDICATOR
STOR. T1,ED.2TS,(F) ;MAKE TO-10 SIDE IDLE
SE1ENT ;QPV2 CODE RUNS IN SECTION ONE
MOVEI T1,.M20F ;RESET PROTOCOL TYPE TO 20F (ALSO ANF)
LOAD. T2,ED.211,(F) ;GET POINTER TO TO-11 SECTION
STOR. T1,EC.PRT,(T2) ;SET 11'S PROTOCOL TYPE
LOAD. T2,ED.210,(F) ;GET POINTER TO TO-10 SECTION
STOR. T1,EC.PRT,(T2) ;SET 10'S PROTOCOL TYPE
MOVSI T1,(ED.LLS) ;GET LINE STATE REPORTED FLAG
TDNN T1,ETDSTS(F) ;WAS LAST LINE STATE REPORTED AS DOWN?
JRST DTECM4 ;YES, DON'T REPORT AGAIN
ANDCAM T1,ETDSTS(F) ;MARK LAST STATE REPORTED AS DOWN
MOVEI T1,DI.LSC ;SIGNAL A PROTOCOL DOWN RIGHT AWAY
MOVEI T3,LS.OFF ;NEW LINE STATE OF OFF
PUSHJ P,CALUSR ;CALL DTE USER
DTECM4: SETZ T2, ;GET A ZERO
EXCH T2,ETDIBK(F) ;GET INPUT BUFFER ADDRESS
JUMPE T2,DTECM2 ;IF NO INPUT BUFFER, SKIP THIS
MOVX T1,UBLSIZ+SIZE(.EQLEN,36) ;GET INPUT BUFFER SIZE
PUSHJ P,GIVWDS## ;GIVE BACK THE MEMORY
DTECM2: SETZ T2, ;GET A ZERO
EXCH T2,ETDOBK(F) ;GET OUTPUT BUFFER ADDRESS
JUMPE T2,DTECM3 ;IF NO OUTPUT BUFFER, SKIP THIS
MOVX T1,UBLSIZ+SIZE(.EQLEN,36) ;GET OUTPUT BUFFER SIZE
PUSHJ P,GIVWDS## ;GIVE BACK THE MEMORY
DTECM3: LOAD. T3,ED.CUR,(F) ;GET THE CURRENT MESSAGE POINTER
SKIPE T3 ;IS ONE THERE?
PUSHJ P,DTECMR ;NO, GIVE THE OUTPUT INCOMPLETE
SETZ T3,
STOR. T3,ED.CUR,(F) ;ZERO OUT THE ENTRY
DTECM1: LOAD. T3,ED.QUE,(F) ;GET NEXT QUEUE ENTRY
JUMPE T3,CPOPJ## ;WE'RE ALL DONE NOW IF NONE LEFT
MOVE T1,MB.NXT(T3) ;GET POINTER TO NEXT MESSAGE
STOR. T1,ED.QUE,(F) ;STORE IT AS NEW FIRST ITEM
PUSHJ P,DTECMR ;GIVE THE MESSAGE BACK TO DRIVER (RTR)
JRST DTECM1 ;CLEAN OUT THE NEXT ONE
;HERE TO PRETEND OUTPUT DONE TO DRIVER (DNADLL) WHICH WILL DISCARD
;THE MESSAGE IN THE CORRECT MANNER. CALLED WITH T3 POINTING TO THE
;MESSAGE.
DTECMR: MOVEI T1,DI.ODN ;GET "OUTPUT DONE" KONTROLLER FUNCT
SKIPN T3 ;HAVE A MESSAGE BLOCK?
STOPCD .,STOP,DTENOM, ;++ NO MESSAGE BLOCK
PJRST CALUSR ;CALL DTE DRIVER AND RETURN
;HERE TO INFORM THE 11 ON A POWER FAILURE
DTEPWF::PUSHJ P,GTEPD
LOAD. T2,ED.211,(F)
MOVSI T1,(EC.PWF)
IORM T1,ETCSTS(T2)
MOVEI T1,TO11DB
XCT ETDCNO(F)
POPJ P,
;HERE WHEN POWER IS RESTORED
DTEPFC::PUSHJ P,GTEPD
SETZM DTEEPW(T4)
PUSHJ P,ENTSPC
PUSHJ P,STAPPC
POPJ P,
;PRSRLD - PRESS 11 RELOAD BUTTON
; SKIP RETURN ON SUCCESS, OTHERWISE INDICATES WE NEVER SAW 11 DOORBELL
BOFTIM==^D200 ;WAIT 200 MS, THEN TURN RELOAD BUTTON OFF
DBCTIM==^D2 ;WAIT 2 SECS FOR DOORBELL TO CLEAR
MAGICN==^O1365 ;ROM HELLO BYTE COUNT
PRSRLD: PUSHJ P,SAVE3## ;SAVE SOME ACS FOR USE
MOVEI T1,SR11B ;SET 11 RELOAD BUTTON
XCT ETDCNO(F) ;DO IT
PRSRL2: RDTIME P1 ;GET TIME BASE TIME
PRSRL3: 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 PRSRL3 ;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,SYSUPT## ;GET TIME TO WAIT FOR, LEAVE DOORBELL
; BIT IN T1
PRSRL4: MOVEI T1,TO11DB ;SETUP IN CASE SLEEP CALLED
XCT ETDCSO(F) ;DOORBELL CLEAR?
JRST PRSRL5 ;YES, WHAT WE WANTED
CAMG P1,SYSUPT## ;TIME TO QUIT?
POPJ P, ;ELEVEN MUST HAVE TIMED OUT
MOVEI T1,1 ;WAIT FOR 1 SEC
PUSHJ P,SLEEPF## ;GO SLEEP FOR 1 SEC
JRST PRSRL4 ;WAIT STILL
PRSRL5: MOVEI T1,CLRDTE ;CLEAR ALL BITS
XCT ETDCNO(F)
JRST CPOPJ1## ;GIVE GOOD RETURN
;WAITDB -- ROUTINE TO WAIT FOR TO-10 DOORBELL, CALL WITH P2 CONTAINING THE
; WAIT TIME IN SECONDS. OBVIOUSLY P2 MUST BE SAVED FROM DESTRUCTION.
WAITDB: IMUL P2,TICSEC## ;CONVERT TO TICS
ADD P2,SYSUPT## ;TIME IN FUTURE
WAITD1: MOVEI T1,TO10DB ;WAIT FOR TO-10 DOORBELL
XCT ETDCSZ(F) ;CONSZ DTEN,(T1)
JRST CPOPJ1## ;GOT IT
CAMG P2,SYSUPT## ;TIMED OUT YET?
POPJ P, ;YUP, GIVE BAD NEWS
PUSHJ P,UUOLVL## ;CAN WE CALL SCDCHK?
JRST WAITD1 ;NO--JUST LOOP AT STARTUP TIME
PUSHJ P,SCDCHK## ;CHECK OTHER GUYS
JRST WAITD1 ;CHECK AGAIN
;CALUSR -- ROUTINE TO CALL DECnet
;CALL WITH F POINTING TO ETD BLOCK
CALUSR: PUSHJ P,SAVR## ;DECnet USES R AS A TRASH AC
LOAD. T2,ED.USR,(F) ;GET THE LINE'S USER
CAIE T2,DD.DEC ;IS IT DECnet ???
STOPCD CPOPJ##,DEBUG,DTEIUD ;++ILLEGAL USER FOR DTE
MOVE T2,ETDLBK(F) ;GET LINE BLOCK ADDRESS
PJRST DTIPPI## ;PASS IT OFF TO DNADLL
;RESPTR - RESOLVE A POSSIBLY EXTENDED INDEXED BYTE POINTER FOR USE
; WITH TO-11 AND TO-10 BYTE POINTERS.
;
;IF THE INDEX TURNS OUT TO BE AN EXTENDED POINTER, IT MUST BE MAPPED INTO
;SECTION ZERO SO IT CAN BE SENT ACROSS THE DTE.
;
;CALLED WITH T1 CONTAINING THE UNRESOLVED BYTE POINTER, RETURNS WITH
; T1 CONTAINING THE RESOLVED POINTER.
RESPTR: LDB T2,[POINT 4,T1,17] ;GET THE INDEX FIELD OF THE BYTE POINTER
JUMPE T2,CPOPJ ;UNINDEXED, JUST RETURN
CAIE T2,T6 ;ARE WE INDEXING BY T6 (THE DECNET INDEX)
STOPCD .,STOP,DTEIDX, ;++ BAD INDEX IN BYTE POINTER
TLZ T1,37 ;MASK OUT THE INDEX AND INDIRECT BITS
MOVE T3,(T2) ;DO THE INDIRECTION NOW
TLNE T3,-1 ;EXTENDED SECTION?
PUSHJ P,RESPT1 ;YES, DO THE MAPPING AND RETURN
ADDI T1,(T3) ;ADD THE OFFSET TO THE BYTE POINTER
POPJ P, ; AND RETURN
;HERE WE HAVE TO MAP THE NON-ZERO SECTION MESSAGE BLOCK.
RESPT1:
; SE1ENT ;GO INTO SECTION ONE FOR A WHILE
;*** FILL IN THIS SPACE ***
POPJ P, ;RETURN WITH T1 CONTAINING BYTE POINTER
;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.
DTERLD::MOVEM T1,ETDLCP(F) ;SAVE LAST -11 CRASH PC
LOAD. T1,ED.CPN,(F) ;GET THE CPU NUMBER FOR THIS DTE
CAME T1,.CPCPN ;ARE WE RUNNING ON THE CORRECT CPU?
STOPCD CPOPJ,DEBUG,DTERWC ;++DTERLD CALLED ON WRONG CPU
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
MOVE T1,ETDUSR(F) ;GET THE USER OF THE LINE
CAIN T1,DD.DEC ;IF IT'S DECNET
JRST DECRLD ; GO TELL DECNET ABOUT IT
CONSZ PI,PI.PIA ;DON'T CALL WAKJOB IF PI'S ARE OFF
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)
DECRLD: SE1ENT ;DECNET WANTS TO BE IN SECTION 1
MOVSI T1,(ED.LLS) ;GET LINE STATE REPORTED FLAG
TDNN T1,ETDSTS(F) ;WAS LAST LINE STATE REPORTED AS DOWN?
POPJ P, ;YES, RETURN
ANDCAM T1,ETDSTS(F) ;MARK LAST STATE REPORTED AS DOWN
MOVEI T1,DI.LSC ;SIGNAL A PROTOCOL DOWN RIGHT AWAY
MOVEI T3,LS.OFF ;NEW LINE STATE OF OFF
PJRST CALUSR ;CALL DTE USER AND RETURN
SUBTTL MISCELLANEOUS UTILITY ROUTINES
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
STOPCD .,STOP,DTEBDN ;++BAD DEVICE NUMBER
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,M.CPU## ;IN RANGE?
POPJ P, ;NO, GIVE ERROR INDICATION
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
CAIL T3,4 ;IS DESIRED DTE NUMBER LESS THAN NUMBER OF DTES?
POPJ P, ;NO, GIVE ERROR RETURN
HLRZ T1,F ;RESTORE CPU NUMBER
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
JRST CPOPJ1## ;RETURN SUCCESS
;ROUTINE TO GET TWO EIGHT BIT BYTES FROM A MESSAGE, SWAP THEM, AND
; RETURN THEM AS A 16 BIT BYTE IN T1. USES T4 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
;HERE DURING STOPCD PROCESSING TO TYPE DTE THAT
; CAUSES THE STOPCODE. F CONTAINS ETD ADDRESS.
DTEPDI::PUSHJ P,INLMES##
ASCIZ /DTE /
LOAD. T1,ED.DTN,(F) ;GET DTE NUMBER
IFN FTMP,<
PUSHJ P,PRTDI8## ;OUTPUT DTE NUMBER
PUSHJ P,INLMES##
ASCIZ / on CPU /
LOAD. T1,ED.CPN,(F) ;GET CPU NUMBER
>
PJRST PRTDI8## ;OUTPUT AND RETURN
;GETCPU PLACES A JOB ON THE CORRECT CPU DEPENDING UPON F (POINTER TO THE
;ETD REGION). ONLY CALLED FROM UUO LEVEL!
IFE FTMP,<GETCPU==CPOPJ1##>
IFN FTMP,<
GETCPU:
PUSHJ P,SSEC0## ;MUST CALL THIS IN SECTION 0
LOAD. T1,ED.CPN,(F) ;GET THE CPU NUMBER FROM THE ETD BLOCK
PJRST ONCPUS## ;RUN ON THAT ONE, SKIPPING IF DOABLE
>;IFN FTMP
;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
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: MOVE T1,.CPCPN## ;GET CPU NUMBER OF CALLING CPU
MOVE F,DTEMAS##(T1) ;GET DTE CONTROL BLOCK OF MASTER DTE
GTEPT: MOVE T4,.CPEPT## ;NOW GET EPT ADDRESS OF CALLING CPU
POPJ P, ;DONE.
$LOW
DTRJOB::Z ;JOB TO WAKE ON 11 RELOAD
$LIT
DTEEND: END