1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-02 01:30:40 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

4425 lines
160 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE DTESER - DTE20 INTERFACE ROUTINES V470
SUBTTL E.SOCCI/EVS/EJW/JBS/DRL/EGF/VJB/SSG 7-JUNE-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,470
;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+<TLINE>B32+<TLINE>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: 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