Trailing-Edge
-
PDP-10 Archives
-
tops10_704_monitoranf_bb-x140c-sb
-
10,7/anf10/dndev.p11
There are 3 other files named dndev.p11 in the archive. Click here to see a list.
.SBTTL DNDEV - DEVICE IO ROUTINES 17-MAY-88
;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,1981,1982,1983,1984,1987,1988.
;ALL RIGHTS RESERVED.
VRDEV=076 ;FILE EDIT NUMBER
.SBTTL DEVICE DATA BLOCK DEFINITIONS
.IF NE DEVN
BLOCK DB ;DEF DB.??? OFFSETS
X STS,1 ;STATUS WORD
DS.CAC=000001 ;SEND CONNECT ACCEPT
DS.DSC=000002 ;SEND DISCONNECT CONFIRM
DS.QUE=000004 ;DEVICE HAS REQUEST TO RUN IN QUEUE
DS.OUT=000010 ;DEVICE DOES OUTPUT(E.G. LPT)
DS.ACT=000020 ;DEVICE ACTIVE
DS.DIE=000040 ;ABORT - OTHER NODE DISAPPEARED
DS.IST=000100 ;WE STOPPED INPUT WITH AN XOFF
.IF NE FT.TSK
DS.PAU=000200 ;TASK USING TTY FOR INPUT
DS.Q10=000400 ;TASK HAS QUEUED CHARS TO 10
.ENDC; .IF NE FT.TSK
DS.COR=001000 ;DEVICE WANTS TO RUN WHEN CORE IS FREE
DS.XCH=002000 ;NEED TO SEND CHARACTERISTICS
DS.EPL=004000 ;NEED TO SEND AN ECHO PIPELINE MARKER
DS.IQU=010000 ;INPUT QUEUED TO NCL - USED SO TTY'S DON'T HAVE
; TWO MESSAGES IN PIPE AT ONCE
DS.TTY=020000 ;DEVICE IS A TTY
DS.XDS=040000 ;NEED TO SEND DB.DCS TO OTHER GUY
DS.CON=100000 ;DEVICE IS CONNECTED
DS.CLR=^C<DS.TTY!DS.OUT!DS.QUE!DS.ACT> ;BITS CLRDDB WILL CLEAR
X LNK,1 ;LINK TO NEXT DEVICE DATA BLOCK
X HDW,1 ;HARDWARE ADR FOR DEVICE
X RPC,1 ;DEFAULT STARTING ADDRESS - CLRDDB MOVES THIS TO DB.OPC
X TPC,1 ;PC IF TIMER GOES OFF
X DVT,1 ;DEVICE ATTRIBUTES
XX DVU,1 ;DEVICE "UNIT" TYPE
XX DVV,1 ;DEVICE "CONTROLLER" TYPE
X WID,0 ;WIDTH
X RLN,1 ;RECORD LENGTH
XX ACR,1 ;AUTO CRLF POINT
XX UNI,1 ;UNIT NUMBER
XX OBJ,1 ;NCL OBJECT TYPE
XX ROT,1 ;NCL REMOTE OBJECT TYPE
XX MDR,1 ;FOR OUTPUT DEVICES MAX # OF DATA REQUESTS FOR DEVICE
XX CHK,1 ;MAX CHUNKS DEVICE CAN HAVE BEFORE SENDING DATA REQUEST
XX TYP,1 ; TYPE OF DEVICE (INDEX FOR JSR)
.IIF NE FT.RNN,XX RNN,1 ;ONLY NODE NUMBER WHICH MAY CONNECT TO DEVICE
.IIF NE FT.PFH,XX PFH,1 ;PREFERED HOST TO CONNECT TO
.IIF NE FTHOST,XX RCN,1 ;NODE TO RECONNECT TO
X OLA,1 ;OUR LINK ADDRESS FOR THIS DEVICE
.IIF NE FT.RDM!FT.RDP!FT.RDA,X RDT,1 ; REMOTE DATA TYPE
RDEMPT=1 ; FOR MULTIPOINT RDE TYPE
RDEPTP=2 ; FOR P-P RDE
RDEASC=4 ; FOR ASCII RDE
RDEBRK=100000 ; ASCII TYPE BREAK HAS BEEN SEEN
.IIF NE FT.TSK,X TSK,4 ;ADDRESS OF TASK FOR DEVICE
; 1ST WORD IS PRINTER GET TASK
; 2ND WORD IS KEYBOARD GET TASK
; 3RD WORD IS PRINTER PUT TASK
; 4TH WORD IS KEYBOARD PUT TASK
XX DFT,6 ;FORMS TYPE (ASCII)
X ZER,0 ;START CLEARING HERE ON A RESTART
X DCS,1 ;DEVICE CONTROL STATUS
X MML,1 ;MAXIMUM MESSAGE LENGTH FOR DEVICE
XX DCM,1 ;DATA CODE AND MODE
DCM.AS= B0 ; ASCII
DCM.EB= B1 ; EBCDIC
DCM.IM= B2 ; IMAGE
DCM.HO= B3 ; HOLLERITH (CDR ONLY)
DCM.DI= B4 ; DEC IMAGE (CDR ONLY)
DCM.XX= B5 ; RESERVED
DCM.CF= B6 ; COMPRESSED FORMAT
X RLA,1 ;REMOTE LINK ADDRESS FOR THIS DEVICE
X SCB,1 ;SCB ADDRESS FOR THIS DEVICE
X OBF,1 ;OUTPUT(FROM-TEN) BUFFER POINTER
X OLN,1 ;LENGTH OF CURRENT MSG
X OCN,1 ;COUNT FOR CURRENT SUBMESSAGE
X OAD,1 ;CURRENT BYTE POINTER
X OPC,1 ;ADDRESS TO RUN WHEN HAS REQUEST TO RUN IN QUEUE
XX ODR,1 ;COUNT OF OUTPUT(E.G. LPT) DATA REQUESTS
XX COL,1 ;COLUMN DEVICE IS ON
XX IDR,1 ;COUNT OF INPUT(E.G. CDR) DATA REQUESTS
XX CCN,1 ;COMPRESSED CHAR COUNT
X ,0 ;.EVEN
XX TIM,2 ;EIGHT BIT TIMER (COUNTED DOWN ONCE A CLOCK TICK
; IF POS, AND UP ONCE A SECOND IF NEG
; 2ND BYTE IS CODE FOR TYPE OF TIMER
X HLD,1 ;CHAR WE ARE HOLDING
X VFU,1 ;POINTER TO LPTVFU FOR LPT
X CHR,1 ;CHAR WE ARE UNCOMPRESSING
X IBF,1 ;POINTER TO INPUT(TO-TEN) BUFFERS
X ICC,1 ;INPUT CHARACTER COUNT
X ICN,3 ;INPUT MSG COUNT(1ST IS TOTAL, 2ND IS INCREMENTAL)
; 3RD IS ADDRESS OF COUNT
X IAD,1 ;INPUT CHAR ADDRESS
X SIZ,0 ;SIZE OF DEVICE BLOCK
X BIT,1 ;BIT FOR LINE
DB.DHB=DB.HDW ;ADDRESS OF DH11 DEVICE BLOCK
XX .LN,1 ;4 BIT LINE NUMBER
XX FIL,6 ;FILLER FOR 10,11,12,13,14,15
XX EPL,1 ;SERIAL NUMBER FOR ECHO PIPELINE MARKER
X LCB,1 ;LINE CONTROL BLOCK ADDRESS
.IF NE FTDN11
XX DNS,1 ;DN11 TABLE (DNTAB) DISPLACEMENT
; SIGN BIT IS DIAL IN PROGRESS
XX DNT,1 ;DN11 TIMER (SECONDS)
; TWO HIGH ORDER BITS ARE TIMER CODE
.ENDC;.IF NE FTDN11
X TTS,1 ;TTY STATUS
TT.APL=000002 ;TERMINAL IS IN APL MODE
TT.8BT=000010 ;TERMINAL IS IN 8-BIT MODE
TT.DFT=000020 ;FORMS TYPE IS PRESENT
X TZR,0 ;CLEAR FROM HERE ON RESTART
.IF NE FTDN11
X DNR,1 ;DN11 REQUEST WORD
.ENDC ; FTDN11
X STR,1 ;POINTER TO STRING TO TYPE
X TOC,1 ;COUNT OF OUTPUT CHARS IN CHUNK
X TOB,2 ;TTY OUTPUT POINTER - 1ST IS POINTER TO 1ST CHAR
; 2ND POINTER IS TO LAST CHAR
XX ASP,1 ;ASAP CHAR
XX BUF,1 ;PUT CHARS HERE FOR DH11 TO TYPE THEM
; EACH IS NUMBER OF TICKS TO WAIT AFTER TYPING
X FTM,1 ;FILL TIME ON CHAR
.IF NE FT.TSK
TQS=20 ;SIZE OF TTY QUEUES
X PCN,1 ;PRINTER COUNT (COUNT OF CHARS FROM NCL)
X PPT,1 ;PRINTER PUTTER
X PTK,1 ;PRINTER TAKER
X KPT,1 ;KEYBOARD PUTTER
X KTK,1 ;KEYBOARD TAKER
X KQU,TQS ;QUEUE FOR KEYBOARD
.ENDC;.IF NE FT.TSK
X TTC,1 ;CURRENT COPY OF DB.DCS (FOR ESCF HACKERIE)
X TSZ,0 ;SIZE OF TTY BLOCKS
;MACRO TO FINISH MESSAGE OFF AND SEND IT
.MACRO DVXMSG
MOVB R2,@(P)+ ;PUT CNT FIELD INTO CONNECT
ADD (P)+,R2 ;MAKE REAL COUNT
MOV (P)+,R0 ;GET MESSAGE POINTER
MOV R2,CN.LEN(R0) ;PUT COUNT INTO MSG
MOV J,-(P) ;BE SURE NCLIN1 IS HONEST
TRACE DV ;FOR THOSE WHO WATCH
JSR PC,NCLIN1 ;GIVE TO NCL TO GET RID OF
MOV (P)+,J
.ENDM DVXMSG
.SBTTL DEVICE ROUTINES
;HERE TO BEGIN A NCL MESSAGE(CONNECT, DISCONNECT, OR DATA REQUEST, ETC)
; CALL WITH J SETUP
; MOV DB.RLA,-(P) ;PUT DLA ON STACK
; MOV MSG TYPE,-(P) ;PUT MSG TYPE ON STACK
; JSR PC,DVXNCL
; ERROR RETURN
; ON RETURN @P WILL BE ADR OF COUNT
; AND 2(P) WILL BE COUNT
; AND 4(P) WILL BE ADR OF CHUNK
DVXNCL: CLR R1 ;WE ARE SENDING NUMBERED NCL MSG
MOV DB.SCB(J),SB ;DESTINATION NODE FOR MSG
MOV SB,DNA ;SAVE FOR NCLBMS
MOV #OURSCB,SNA ;SOURCE FOR THIS MESSAGE
JSR PC,NCLBMS ;TRY TO BEGIN NCL MSG
BNE 10$ ;BRANCH IF WE WON
BIS #DS.COR,@J ;FLAG WE RAN OUT OF CORE
MOV @P,R1 ;GET RETURN ADDRESS
ADD #6,P ;CLEAN OFF STACK
SEC ;SET CARRY CONDITION
JMP @R1 ;RETURN
10$: MOV 6(P),R0 ;GET DLA
MOV @P,6(P) ;AND REPOSITION CHUNK POINTER
MOV 2(P),@P ;AND REPOSITION RETURN ADDRESS
ADD #2,@P ;SKIP RETURN
JSR PC,PUTEXN ;PUT DLA INTO THE MESSAGE
MOV R3,2(P) ;PUT ADR OF COUNT FIELD INTO MESSAGE
JSR PC,PUTBYT ;PUT DUMMY COUNT INTO THE MESSAGE
MOV 4(P),R0 ;GET MESSAGE TYPE
MOV R2,4(P) ;PUT COUNT ONTO STACK
CLR R2 ;RESTART COUNT
JSR PC,PUTBYT ;AND PUT IT INTO MESSAGE
CLC ;CLEAR CARRY AND EXIT
RTS PC
;DVDNCL - SAME AS DVXNCL ONLY FOR LARGE MESSAGES
.IF NE FT.DDP!FTECHO ;ONLY USED BY DDP AND ECHO DEVICE SO FAR
DVDNCL: CLR R1 ;WE ARE SENDING NUMBERED NCL MSG
MOV DB.SCB(J),SB ;DESTINATION NODE FOR MSG
MOV SB,DNA ;SAVE FOR NCLBMS
MOV #OURSCB,SNA ;SOURCE FOR THIS MESSAGE
JSR PC,NCLBMS ;TRY TO BEGIN NCL MSG
BNE 10$ ;BRANCH IF WE WON
BIS #DS.COR,@J ;FLAG WE RAN OUT OF CORE
MOV @P,R1 ;GET RETURN ADDRESS
ADD #6,P ;CLEAN OFF STACK
SEC ;SET CARRY CONDITION
JMP @R1 ;RETURN
10$: MOV 6(P),R0 ;GET DLA
MOV @P,6(P) ;AND REPOSITION CHUNK POINTER
MOV 2(P),@P ;AND REPOSITION RETURN ADDRESS
ADD #2,@P ;SKIP RETURN
JSR PC,PUTEXN ;PUT DLA INTO THE MESSAGE
MOV R3,DB.ICN+0(J) ;SAVE ADDRESS OF LOW-ORDER COUNT BYTE
JSR PC,PUTBYT ;ALLOCATE DUMMY COUNT LOW-ORDER BYTE
MOV R3,DB.ICN+2(J) ;SAVE ADDRESS OF HIGH-ORDER COUNT BYTE
JSR PC,PUTBYT ;ALLOCATE DUMMY COUNT HIGH-ORDER BYTE
MOV 4(P),R0 ;GET MESSAGE TYPE
MOV R2,4(P) ;PUT COUNT ONTO STACK
CLR R2 ;RESTART COUNT
JSR PC,PUTBYT ;AND PUT IT INTO MESSAGE
CLC ;CLEAR CARRY AND EXIT
RTS PC
.ENDC ;.IF NE FT.DDP!FTECHO
;QUEDEV -- QUEUE UP A DEVICE SERVICE ROUTINE TO BE RUN
;QUEXDS -- SET THE NEED-TO-SEND-STATUS STATUS AND QUEUE UP THE DEVICE
QUEXDS: BIS #DS.XDS,@J ;SET NEED-TO-SEND-STATUS
QUEDEV: TRACE DV
QUEPUT DV 10$ ;PUT DEVICE BLOCK ADDRESS INTO THE QUEUE
RTS PC
;HERE TO CLEAN OUT A DEVICE BLOCK AFTER A DISCONNECT OR OTHER END DIED
CLNDDB: TRACE DV
.IF NE FT.RDM
BIT #RDEPTP!RDEMPT,DB.RDT(J); DDCMP RDE ?
BEQ 10$ ; NO, SPLIT
MOV J,-(P) ;MUST SET ALL STATIONS OFFLINE
MOV DB.HDW(J),J ;GET FIRST LINE BLOCK ADR
MOV J,-(P) ;SAVE IT
5$: BITB #MP.OFF,LB.MPS(J) ;IF NOT OFFLINE
BNE 7$
JSR PC,L.DOWN ;SET IT OFFLINE
7$: MOV LB.MPL(J),J ;GET NEXT BLOCK
CMP J,(P) ;IF ITS A NEW ONE LOOP
BNE 5$
TST (P)+ ;POP STACK
MOV (P)+,J ;RESTORE J
.ENDC ;.IF NE FT.RDM
10$: MOV DB.IBF(J),R0 ;GET INPUT(E.G. CDR)
BEQ 20$
CLR DB.IBF(J) ;NO LONGER HAVE A MESSAGE LIST
JSR PC,FRECNL ;FREE UP THE LINKED LIST
20$:
JSR PC,CLRDDB ;CLEAN OUT REST OF BLOCK
.IF NE FT.TSK
JSR PC,HSTWAK ;WAKE TASK ON DISCONNECT
.ENDC
RTS PC
;HERE TO CLEAR A DEVICE BLOCK
CLRDDB: BIC #DS.CLR,@J ;CLEAR MOST OF STATUS BITS
MOV J,R0 ;COPY DEVICE BLOCK ADR
ADD #DB.ZER,R0 ;POINT TO FIRST WORD TO ZERO
MOV #<DB.SIZ-DB.ZER>/2,R1 ;NUMBER OF WORDS TO CLEAR
.IF NE FT.RDM
BIT #RDEPTP!RDEMPT,DB.RDT(J) ; IF ASCII, TREAT LIKE TTY
BEQ 5$
SAVE <R0,R2>
MOV DB.HDW(J),R0 ;LOCATE LINE BLOCKS
MOVB LB..LN(R0),R2 ;FETCH DH11 LINE #
MOV LB.LCB(R0),R1 ;GET THE LINE SPEED
MOV LC.SPD(R1),R1
BIC #17,R1 ;AND SET THE RECEIVER TO ZERO BAUD
MOV @LB.DHB(R0),R0 ;LOCATE DH11 HDW
JSR PC,DHSPD ;AND SET IT
RESTORE <R2,R0>
MOV #<DB.PLE-DB.ZER>/2,R1 ;HAVE TO CLEAN MORE IN THIS CASE
5$:
.ENDC ;.IF NE FT.RDM
.IF NE FTHOST
MOV DB.DCS(J),R2
.ENDC;.IF NE FTHOST
10$: CLR (R0)+ ;CLEAR BLOCK
SOB R1,10$ ;LOOP TILL ALL CLEAR
MOV DB.RPC(J),DB.OPC(J) ;WHERE TO START SERVICE ROUTINE
.IF NE FTHOST
.IF NE <TTYN!FT.CTY>
BIT #DS.TTY,@J ;WAS THIS A TTY
BEQ 16$ ;IF NOT FORGET OLD STATUS
BIC #^CTS.RCN,R2 ;FORGET SOME STATUS
MOV R2,DB.DCS(J) ;RESTORE DATASET STATUS
MOV R2,DB.TTC(J) ;RESET OTHER COPY
.ENDC;.IF NE <TTYN!FT.CTY>
16$: MOVB DB.RCN(J),R0 ;GET NODE TO CONNECT TO
BEQ CLRD90
CLRB DB.RCN(J)
JSR PC,FNDSCB ;GET SCB FOR IT
BEQ CLRD90 ;BRANCH IF IMPOSSIBLE
SNDCON: MOV SB,DB.SCB(J) ;SAV SCB ADDRESS
BIS #DS.CAC!DS.CON!DS.XDS!DS.XCH,@J ;SO WE SEND CONNECT
CLR DB.RLA(J) ;CLEAR RLA SO WE DON'T SEND MSGS
; TILL A CONFIRM COMES IN.
JSR PC,QUEDEV ;WAKE DEVICE
.ENDC;.IF NE FTHOST
CLRD90: RTS PC
;HERE TO SEND A CONNECT CONFIRM MSG, OR A DISCONNECT CONFIRM MSG,
; OR BECAUSE OTHER GUY DIED
DVCCFM: BIT #DS.DIE,@J ;DID OTHER END DIE ?
BEQ 15$
JSR PC,CLNDDB ;IF SO JUST CLEAN HIM OUT
.IF NE <FT.CTY!TTYN>
BIT #DS.TTY,(J) ;IF ITS A TTY SEND A MSG
BEQ 10$
JSR PC,TYPHWA ;TELL USER THAT HOST WENT AWAY
.ENDC ;.IF NE <FT.CTY!TTYN>
10$: RTS PC
15$: BIT #DS.CAC!DS.DSC,@J ;DO WE NEED TO SEND CONFIRM ?
BEQ 10$
CLR -(P) ;DLA = 0 = NCL
MOV #NCLCON,-(P) ;TYPE IS CONNECT
BIT #DS.CAC,@J ;CHECK AGAIN
BNE 20$
INC @P ;MAKE THAT DISCONNECT
20$: JSR PC,DVXNCL ;BEGIN MESSAGE
BR 95$ ;MUST BE OUT OF CORE SO TRY LATER
MOV DB.RLA(J),R0 ;GET DESTINATION LINK NUMBER
JSR PC,PUTEXN ;PUT IT INTO MSG
MOV DB.OLA(J),R0 ;GET OUR LINK ADR
JSR PC,PUTEXN ;PUT IT INTO THE MSG
CLR R0 ;IN CASE DOING A DISCONNECT
BIT #DS.CAC,@J ;ARE WE DOING A CONNECT ?
BEQ 60$ ;IF NOT PUT IN DISCONNECT CODE
MOVB DB.ROT(J),R0 ;GET HIS OBJECT TYPE
JSR PC,PUTBYT ;PUT IT INTO THE MSG
.IF NE,FT.TDV
CMPB DB.OBJ(J),#OBJTSK
BNE 30$
JSR PC,DVCTNM
BR 31$
30$:
.ENDC;.IF NE,FT.TDV
CLR R0 ;HIS PROCESS NAME
JSR PC,PUTBYT
31$: MOVB DB.OBJ(J),R0 ;OUR OBJECT TYPE
JSR PC,PUTBYT ;INTO THE MSG
.IF NE,FT.TDV
CMPB DB.OBJ(J),#OBJTSK
BNE 40$
JSR PC,DVCTNM
BR 41$
40$:
.ENDC;.IF NE,FT.TDV
MOVB DB.UNI(J),R0 ;UNIT NUMBER = PROCESS NAME
JSR PC,PUTEXN ;INTO THE MSG
41$: MOV DB.MML(J),R0 ;MAXIMUM MESSAGE LENGTH
JSR PC,PUTEXN ;PUT INTO CONNECT
MOVB DB.DCM(J),R0 ;GET CODE AND MODE
JSR PC,PUTBYT ;PUT INTO MESSAGE
MOV DB.RLN(J),R0 ;GET RECORD SIZE
JSR PC,PUTEXN ;PUT INTO MESSAGE
MOV DB.DVT(J),R0 ;GET DEVICE ATTRIBUTES
JSR PC,PUTEXN ;PUT INTO MESSAGE
MOVB DB.DVU(J),R0 ;GET DEVICE "UNIT" TYPE
JSR PC,PUTEXN ;PUT INTO MESSAGE
MOVB DB.DVV(J),R0 ;GET DEVICE "CONTROLLER" TYPE
JSR PC,PUTEXN ;PUT INTO MESSAGE
JSR PC,DVXDFT ;SEND "FORMS" TYPE
BR 61$ ;SKIP DISCONNECT CODE
60$: JSR PC,PUTEXN ;PUT INTO MESSAGE
61$: DVXMSG ;SEND MESSAGE
BIT #DS.CAC,@J ;WAS THIS A CONNECT ?
BNE 70$
JSR PC,CLNDDB ;IF DISCONNECT CLEAN OUT DEVICE BLOCK
.IF NE <FT.CTY!TTYN>
BIT #DS.TTY,(J) ;IF IT'S A TTY, TYPE A MSG
BEQ 65$ ; IF NOT, DONT.
BIT #DS.CAC,(J) ;IS THIS A "SET HOST" DISCONNECT
BNE 65$ ; IF SO, DON'T TYPE MSG
JSR PC,TYPHSD ;SAY "HOST SENT DISCONNECT"
.ENDC
65$: RTS PC ;ALL DONE.
70$: BIC #DS.CAC,@J ;HAVE SENT CONNECT CONFIRM NOW
MOV @P,DB.OPC(J) ;DON'T RETURN AGAIN
.IF NE FT.RDM!FT.RDP
CMPB DB.OBJ(J),#OBJRDE ;IF RDE DEVICE,
BNE 90$
SAVE <R2>
MOV DB.HDW(J),R0 ;LOCATE LINE BLOCKS
MOVB LB..LN(R0),R2 ;FETCH DH11 LINE #
MOV LB.LCB(R0),R1 ;FETCH LINE SPEED
MOV LC.SPD(R1),R1
MOV @LB.DHB(R0),R0 ;LOCATE DH11 HDW
JSR PC,DHSPD ;AND SET SPEED
RESTORE <R2>
80$: CMPB DB.ODR(J),DB.MDR(J) ;IF WE NEED SOME MORE DATA REQUESTS,
BHIS 90$
JSR PC,DVXDRQ ;SEND A DATA REQUEST
BR 80$ ;CHECK REQUESTS AGAIN
.ENDC ;.IF NE FT.RDM!FT.RDP
90$: RTS PC
;HERE BECAUSE CAN'T CONNECT BECAUSE OUT OF CORE
95$: TWIDDLE
RTS PC
.IF NE,FT.TDV
;ROUTINE TO COPY A TSK NAME INTO THE CURRENT MESSAGE
DVCTNM: SAVE R5 ;SAVE R5 FOR LATER
MOV DB.RPC(R5),R5 ;POINT TO THE TSK NAME
SUB #2,R5 ;BACKUP TO THE BEGINING
MOV @R5,R5 ;POINT TO THE ASCIZ STRING
10$: MOVB (R5)+,R0 ;GET A CHARACTER OF THE NAME
BEQ 20$ ;IF A NUL WE ARE DONE
TSTB @R5 ;SEE IF NEXT CHARACTER IS A NUL
BEQ 11$ ;IF YES, DON'T SET EXTENSIBLE BIT
BIS #200,R0 ;IF NO, DO SET THE EXTENSIBLE BIT
11$: JSR PC,PUTBYT ;PUT THE CHARACTER IN MESSAGE
BR 10$ ;AND LOOP FOR MORE
20$: RESTORE R5 ;RESTORE R5 AND RETURN
RTS PC
.ENDC;.IF NE,FT.TDV
;HERE TO SEND A FORMS TYPE
DVXDFT: MOV #DB.DFT,R1 ;OFFSET TO FORMS TYPE
ADD J,R1 ;MAKE ABSOLUTE ADDRESS
MOV #6,-(P) ;PUT CHARACTER LIMIT ON THE STACK
10$: MOVB (R1)+,R0 ;GET NEXT CHARACTER
DEC (P) ;COUNT IT DOWN
BNE 11$ ;PASS UNCHANGED UNLESS END
BIC #200,R0 ;MAKE SURE IT ENDS
11$: JSR PC,PUTBYT ;PUT EXTENSIBLE ASCII BYTE
TSTB R0 ;CHECK FOR END
BMI 10$ ;LOOP OVER ALL SIGNIFICANT CHARACTERS
TST (P)+ ;TRIM THE STACK
RTS PC ;RETURN
;HERE TO SEND A DATA REQUEST
DVXDRQ: BIT #DS.DSC!DS.DIE,@J ;ARE WE STOPPING DEVICE ?
BNE 90$ ;IF SO DON'T SEND DATA REQUEST
TST DB.RLA(J) ;WAITING FOR CONNECT CONFIRM ?
BEQ 90$ ;IF SO DON'T SEND DRQ UNTIL CONFIRMED
CMP #ERSCNT*2,FRECNT ;GOTS LOTS OF ROOM STILL LEFT?
BLE 2$ ;YES
TWIDDLE ;NO - THAT'S INTERESTING
BIS #DS.COR,@J ;FLAG DEVICE WANTS CORE
BR 90$ ;AND WAIT UNTIL LESS CONGESTED
2$: MOVB DB.ODR(J),R0 ;GET COUNT OF DATA REQUESTS SENT
.IF EQ DGUTS
ASSERT PL
.IFF
BPL 03$
CLRB DB.ODR(J)
03$:
.ENDC ; .IF EQ DGUTS
CMPB DB.ODR(J),DB.MDR(J) ;HAVE WE SENT ENOUGH DATA-REQ'S
BPL 90$ ;IF SO, GOOD NIGHT
PIOFF ;DON'T LET ANY GET AWAY...
SAVE <R1,R2> ;SAVE REGS, PREPARE TO COUNT THE
;NUMBER OF CHUNKS THIS DEVICE HAS
CLR R0 ;R0 := TOTAL NUMBER OF CHUNKS
.IF NE FT.RDA
BIT #RDEASC,DB.RDT(J) ;IF THIS IS RDA THEN
BNE 5$ ; MUST COUNT UP DB.TOB CHUNKS ALSO
.ENDC ; FT.RDA
.IF NE TTYN+FT.CTY
BIT #DS.TTY,@J ;IF IT IS A TTY, THEN FALL
BEQ 20$ ; INTO STUFF TO COUNT OUTPUT BUFFER
5$: MOV DB.TOB(J),R1 ;GET A POINTER TO THE OUTPUT BUFFER
BEQ 20$ ;IF NONE, THEN COUNT QUEUED CHUNKS
DEC R1 ;NOW MAKE POINTER POINT TO
BIC #CNKSIZ-1,R1 ;THE START OF THE CHUNK
10$: INC R0 ;COUNT THAT CHUNK AND
MOV @R1,R1 ;FOLLOW THE CHAIN
BNE 10$ ;A ZERO WORD MARKS THE END
;WHEN DONE FALL THRU TO CODE TO
;COUNT QUEUED CHUNKS
.ENDC
20$: MOV DB.OBF(J),R2 ;GET POINTER TO LIST OF MESSAGES
BR 35$ ;JUMP INTO DOUBLE LOOP
30$: MOV CN.MLK(R2),R2 ;FOLLOW LINK TO NEXT MESSAGE
35$: BEQ 50$ ;IF NONE, THEN COUNTING IS DONE
INC R0 ;OTHERWISE COUNT THE CHUNK, AND
MOV @R2,R1 ;FOLLOW THE REST OF THE MESSAGE
40$: BEQ 30$ ;IF END OF MESSAGE, GO TO NEXT ONE
INC R0 ;ELSE COUNT THIS CHUNK AND
MOV @R1,R1 ;FOLLOW THE CHAIN FOR THE
BR 40$ ;MESSAGE
50$: RESTORE <R2,R1> ;DONE COUNTING THE MESSAGES
PION ;LET THE WORLD RUN AGAIN
CMPB R0,DB.CHK(J) ;TOO MANY CHUNKS IN USE?
BPL 90$ ;YES, DON'T ASK FOR MORE
MOVB DB.MDR(J),R1
MOVB DB.ODR(J),R0
SUB R0,R1 ; ASK FOR THE RIGHT AMOUNT OF DATA
MOV R1,-(P) ;SAVE COUNT WE ARE NOW SENDING
CLR -(P) ;DLA IS 0 = NCL
MOV #NCLDRQ,-(P) ;MESSAGE TYPE IS DATA REQUEST
JSR PC,DVXNCL ;BEGIN NCL MESSAGE
RTS PC ;CAN'T SEND IT NOW
MOV DB.RLA(J),R0 ;GET DLA
JSR PC,PUTEXN ;PUT INTO MESSAGE
MOV 6(P),R0 ;DATA REQUEST COUNT
JSR PC,PUTBYT ;PUT IT INTO THE MSG
DVXMSG ;SEND MESSAGE
ADD (P)+,DB.ODR(J) ;COUNT REQUESTS SENT
90$:
RTS PC
;HERE TO SEND DEVICE CONTROL STATUS
DVXDCS: BIT #DS.XDS,@J ;DO WE NEED TO SEND STATUS ?
BEQ 90$
TST DB.RLA(J) ;DO WE HAVE A REMOTE ADDRESS YET
BEQ 90$ ;DON'T SEND STATUS TILL CONNECT CONFIRM
BIT #DS.DIE,@J ;HAVE WE LOST CONTACT WITH HOST
BNE 90$ ;YES, DON'T SEND STATUS
.IF NE TTYN+FT.CTY
BIT #DS.TTY,@J ;TTY?
BEQ 10$ ; NO, SKIP IT
TST DB.LCB(J) ;CONNECTED??
BEQ 10$ ; NO, THIS LOSES TOO
BIT #LCB.TM,@DB.LCB(J) ;TIMER RUNNING
BNE 90$ ; YES, DONT SEND STATUS
.ENDC
10$: MOV DB.RLA(J),-(P) ;PUT DLA ON STACK
MOV #3,-(P) ;CODE FOR STATUS MESSAGE
JSR PC,DVXNCL ;BEGIN A MESSAGE
RTS PC ;NOT ENOUGH CORE NOW
BIC #DS.XDS,@J ;HAVE SENT STATUS NOW
CLR R0
JSR PC,PUTBYT ;PUT STC INTO MESSAGE
MOV DB.DCS(J),R0 ;GET DEVICE CONTROL STATUS
JSR PC,PUTEXN ;PUT IT INTO THE MESSAGE
MOV 4(P),R0 ;GET ADR OF CHUNK
BISB #NCFINT,CN.NCT(R0) ;SO DATA REQUESTS WORK
DVXMSG ;SEND MESSAGE TO 10
90$: RTS PC
;HERE TO GET NEXT OUTPUT BYTE FROM AN NCL MESSAGE
; CALL JSR PC,DVGBYT ;WITH J SETUP
; ; USES R1 AS SCRATCH
; NORMAL RETURN WITH DATA IN R0
; RETURN WITH MSG TYPE IN R0
; RETURN IF NO MORE DATA
; DB.OBF POINTS TO MESSAGES STRAIGHT FROM NCL
; DB.OLN IS LENGTH LEFT IN MESSAGE AFTER CURRENT SUBMESSAGE SEGMENT
; DB.OCN IS LENGTH OF CURRENT SUBMESSAGE
; DB.OAD POINTS TO CURRENT CHARACTER
DVGBUF: MOV DB.OBF(J),R0 ;GET ADR OF NEXT BUFFER FROM NCL
BNE 30$
ADD #4,@P
RTS PC
30$: MOV CN.MLK(R0),DB.OBF(J) ;DELINK THIS MESSAGE
;
;********* here is a convenient place for a sink macro call ******
;
MOV CN.CNT(R0),DB.OLN(J) ;SAVE LENGTH OF MESSAGE
MOV CN.ADR(R0),DB.OAD(J) ;SAVE ADR OF NEXT DATA BYTE
.IF EQ DGUTS
ASSERT NE
.IFF
BNE DVGBYT
DVGBFE: JSR PC,FRECKS ;CHUCK MSG AND REPORT ERROR
CTYMSG NCL
BR DVGBUF
.ENDC ; .IF EQ DGUTS
DVGBYT: MOV DB.OAD(J),R0 ;GET POINTER TO CURRENT MESSAGE IF ANY
BEQ DVGBUF ;GET NEXT BUFFER IF ANY
30$: DEC DB.OCN(J) ;COUNT BYTE OUT OF SUBMESSAGE
BPL 50$
DEC DB.OLN(J) ;COUNT PART OF COUNT OUT MESSAGE
BPL 40$ ;BRANCH IF THERE IS MORE
BIC #CNKSIZ-1,R0 ;MAKE CHUNK ADR FROM BYTE ADR
JSR PC,FRECKS ;AND RELEASE ALL CHUNKS
CLR DB.OAD(J) ;CLEAR BYTE POINTER
JSR PC,QUEDEV ;SO WE SEND MORE DATA REQUESTS
BR DVGBYT ;AND BACK TO CHECK FURTHER
40$: MOVB (R0)+,R1 ;GET PART OF COUNT
ADVCNK R0 FREE
42$: TSTB R1 ;WAS COUNT EXTENDED ?
BPL 48$
DEC DB.OLN(J) ;ADJUST TOTAL COUNT
BIC #^C177,R1 ;STRIP EXTENSIBLE BIT
MOV R1,-(P) ;AND SAVE LOW ORDER BITS
MOVB (R0)+,R1 ;GET HIGH ORDER BITS
ADVCNK R0 FREE
46$: SWAB R1 ;PUT HIGH ORDER BITS IN LH
.IF EQ DGUTS
ASSERT PL ;BETTER NOT BE EXTENSIBLE
.IFF
BPL 47$
TST (P)+ ;GET STACK BACK IN SYNC
BIC #CNKSIZ-1,R0 ;RETURN TO START OF CHUNK
BR DVGBFE ;AND CHUCK THE WHOLE THING
47$:
.ENDC ; .IF EQ DGUTS
ASR R1 ;POSITION HIGH ORDER BITS
ADD (P)+,R1 ;MAKE TOTAL COUNT
48$: SUB R1,DB.OLN(J) ;ADJUST HOW MUCH LEFT IN MESSAGE
ASSERT PL ;BETTER NOT BE NEGATIVE
DEC R1 ;COUNT NEXT BYTE WE TAKE OUT
MOV R1,DB.OCN(J) ;SAVE SUBMESSAGE LENGTH
ADD #2,@P ;SKIP RETURN
50$: MOVB (R0)+,R1 ;GET DATA
ADVCNK R0 FREE
56$: MOV R0,DB.OAD(J) ;SAVE BYTE ADDRESS
MOV R1,R0
RTS PC
;HERE TO GET A DATA BYTE FROM A MESSAGE
DVGDBY:
.IF NE DGUTS
TST DB.OAD(J) ;CHECK FOR DATA TO READ
BEQ 05$
TST DB.OCN(J)
BEQ 05$
.IFTF
JSR PC,DVGBYT ;GET NEXT BYTE
RTS PC
.IFF
TRAP
TRAP
.IFT
NOP
05$: CLR R0 ;HALUCINATE A NULL
CTYMSG NCL
RTS PC
.ENDC ;.IF NE DGUTS
;HERE TO GET AN EXTENSIBLE NUMBER FROM NCL HEADER
DVGEXF: JSR PC,DVGDBY ;GET 1ST BYTE
TSTB R0 ;SEE IF EXTENDED FLAG IS SET IN BYTE
BPL 92$ ;IF NOT WE ARE DONE
SAVE <R0>
JSR PC,DVGDBY ;GET 2ND BYTE
SWAB R0 ;NOW PATCH THESE 14 BITS TOGETHER
COM R0
ASR R0
BIC #177,R0
BIC R0,(P)
BPL 91$ ;IF BITS 14,15 ARE ZERO, WE'RE DONE
JSR PC,DVGDBY ;GET THE LAST TWO BITS
SAVE <R0>
BPL 90$ ;IF FLAG BIT IS OFF, WE'RE DONE
TWIDDLE ;COUNT TOOOO LOOOONG FIELD ERRORS
89$: JSR PC,DVGDBY ;ELSE EAT UP THE REST OF THIS GARBAGE
TSTB R0
BMI 89$
90$: RESTORE <R0> ;GET BITS 14,15
ASR R0
ROR R0
ROR R0
BIS #37777,R0
COM R0
BIC R0,(P)
91$: RESTORE <R0>
92$: RTS PC
;HERE TO PUT A BYTE INTO A SUBMESSAGE AS AN EXTENSIBLE FIELD
DVPEXA: BIC #^C377,R0 ;STRIP EXTRA BITS
;HERE TO PUT AN EXTENSIBLE FIELD INTO A SUBMESSAGE
DVPEXD: BIT #^C177,R0 ;IF MORE THAN 7 BITS
BEQ DVPDAT
MOV R0,-(P) ;SAVE VALUE
JSR PC,DVPEDT ;INSERT FIRST BYTE
MOV (P)+,R0 ;GET VALUE BACK
SWAB R0 ;MOVE BITS 7-15 TO 0-8
ASL R0
ADC R0
BIC #<^C777>,R0 ;STRIP EXTRA BITS
BR DVPEXD ;LOOP ON THE NEXT BYTE
;HERE TO BEGIN A SUBMESSAGE
; CALL MOV #TYPE,R0
; JSR PC,DVPBSM
;
;RETURN WITH CARRY CLEAR IF SUCCESS, CARRY SET IF FAILURE (E.G., NO FREE
;CHUNKS TO START A NEW MESSAGE).
;
;ONLY SUBMESSAGES UP TO 177 BYTES MAY BE SENT, FOR LARGER MESSAGES USE
;DVDBSM INSTEAD.
DVPBSM: MOV R0,-(P) ;SAVE TYPE CODE
TST DB.ICN(J) ;DANGLING PREVIOUS SUBMSG ?
BEQ 10$
JSR PC,DVPSBM ;FINISH PREVIOUS SUBMESSAGE
10$: MOV DB.IBF(J),R0 ;GET POINTER TO MSG
BNE 30$
MOV (P)+,R0 ;GET CODE
MOV DB.RLA(J),-(P) ;DESTINATION LINK ADDRESS
BEQ 40$ ;IF CONNECT NOT CONFIRMED, DON'T SEND
MOV R0,-(P) ;SAVE SUBMESSAGE TYPE
JSR PC,DVXNCL ;BEGIN MSG
BR 44$ ; ERROR TIME
MOV R3,DB.IAD(J) ;SAVE BYTE POINTER
MOV (P)+,DB.ICN(J) ;SAVE ADDRESS OF COUNT FIELD
MOV (P)+,R1 ;GET COUNT BACK
MOV (P)+,R0 ;GET BUFFER ADDRESS
MOV R1,CN.LEN(R0) ;PUT COUNT INTO THE MSG
MOV R0,DB.IBF(J) ;SAVE MSG POINTER
MOVB #001,@DB.ICN(J) ;INITIAL COUNT IS 1
CLC ;FLAG GOOD RETURN
RTS PC
;HERE WHEN ALREADY HAVE AN NCL MESSAGE, JUST START NEW SUBMESSAGE
30$: INC CN.LEN(R0) ;COUNT COUNT FIELD
MOV DB.IAD(J),DB.ICN(J) ;SAVE POINTER TO COUNT BYTE
CLR R0 ;VIRGIN COUNT
JSR PC,DVPBYT ;PUT COUNT INTO THE MSG
MOV (P)+,R0 ;GET TYPE CODE BACK
BR DVPDAT ;PUT CODE INTO THE MESSAGE
;HERE WHEN CAN'T START NEW [SUB]MESSAGE - NO CORE, NO RLA, ETC.
40$: TST (P)+ ;POP DUD RLA
44$: SEC ;ERROR RETURN
RTS PC
DVPEDT: BIS #200,R0 ;ADD EXTENSIBLE FLAG
;HERE TO PUT NEXT DATA BYTE IN AN NCL MESSAGE
; CALL JSR PC,DVPDAT ;WITH J SETUP AND CHAR IN R0
; ; USES R1 AS SCRATCH
; DB.IBF IS POINTER TO 1ST CHUNK IN MESSAGE
; DB.IAD IS INPUT CHAR POINTER
; DB.ICN IS POINTER TO CURRENT COUNT IN MESSAGE
DVPDAT: MOV DB.IAD(J),R3 ;GET POINTER TO CHUNK
BEQ 20$
10$: TST DB.ICN(J) ;IF NO PARTIAL MESSAGE, MAKE A NEW MSG.
BEQ 20$
15$: INCB @DB.ICN(J) ;INCREMENT THE BYTE COUNT.
BPL DVPBYT ;IF ITS NOT TOO LARGE, INSERT THE BYTE.
DECB @DB.ICN(J) ;DECREMENT THE COUNT, CAUSE THE CHARACTER
; DOESN'T FIT IN THE MESSAGE.
MOV R0,-(P)
JSR PC,DVPSBM ;FINISH OFF THE SUB MESSAGE.
MOV DB.IBF(J),R0 ;GET THE MESSAGE POINTER.
MOV J,CN.DDB(R0) ;PUT THE DDB ADDRESS IN THE HEADER.
CLR DB.ICC(J) ;CLEAR THE CHARACTER COUNT
JSR PC,NCLIN1 ;SEND THE MESSAGE.
CLR DB.IBF(J) ;MESSAGE IS GONE.
CLR DB.IAD(J) ;
BR 25$
20$: MOV R0,-(P) ;START A NEW DATA SUBMESSAGE.
25$: MOV #2,R0 ;SAVE DATA
JSR PC,DVPBSM ;BEGIN SUBMESSAGE
MOV (P)+,R0 ;GET CHAR BACK
BCC 15$ ;INSERT THE CHARACTER, IF THIS SUCCEEDED.
.IF EQ DGUTS
TRAP
.IFF
CTYMSG BME ;NCL MESSAGE GENERATION FAILURE.
SEC
RTS PC
.ENDC ; .IF EQ DGUTS
DVPBYT: MOV DB.IAD(J),R3 ;GET BYTE POINTER
.IF EQ DGUTS
ASSERT NE ;BETTER BE ONE
.IFF
BEQ DVPDAT ;IF NONE, TRY STARTING A NEW MSG
.ENDC ; .IF EQ DGUTS
MOVB R0,(R3)+ ;PUT CHARACTER INTO THE MESSAGE
ADVCNK R3 EXTEND ;ALLOCATE ANOTHER CHUNK IF REQUIRED
76$: MOV R3,DB.IAD(J) ;SAVE UPDATED BYTE POINTER
CLC ;SET SUCCESS
DVPEXT: RTS PC
;HERE TO PUT DEVICE CONTROL STATUS INTO AN NCL MESSAGE
; CALL JSR PC,DVPDCS ;WITH J SETUP (USES R0 AND R1)
DVPDCS: MOV DB.IAD(J),R3 ;GET POINTER TO CHUNK
BNE 30$
ASSERT EQ DB.IBF(J)
TST DB.RLA(J) ;SEE IF WE ARE CONNECTED (CONFIRMED)
BEQ DVPEXT ;DON'T SEND MSG TO A ZERO LAT
MOV DB.RLA(J),-(P) ;DESTINATION LINK ADDRESS
MOV #3,-(P) ;CODE FOR STATUS
JSR PC,DVXNCL ;BEGIN A MESSAGE
.IF EQ DGUTS
TRAP
.IFF
RTS PC
.ENDC ; .IF EQ DGUTS
;.IF NE TTYN
; BIT #DS.TTY,@J
; BEQ 20$
; MOV DB.DCS(J),R0 ;GET DEVICE STATUS
; BIC #TS.CAR,R0 ;CLEAR CARRIER FLAG
; MOV DB.LCB(J),R1 ;POINT TO DATA SET STATUS
; BIT #LCB.DS,LC.CAR(R1) ;IS IT DATA SET LINE?
; BEQ 38$ ; NO, GIVE UP
; MOVB LC.STA(R1),R1 ;GET STATE
; MOV CRBTAB(R1),R1 ;GET CARRIER BIT
; BIS R1,R0 ;SET IT IF WE HAVE IT
;38$: MOV R0,DB.DCS(J) ;SAVE UPDATED STATUS
;.ENDC;.IF NE TTYN
20$: MOV (P)+,DB.ICN(J) ;SAVE ADDRESS OF COUNT FIELD
MOVB #001,@DB.ICN(J) ;INITIAL COUNT IS ONE FOR TYPE
MOV (P)+,R1 ;GET COUNT BACK
MOV (P)+,R0 ;GET BUFFER ADDRESS
MOV R1,CN.LEN(R0) ;PUT COUNT INTO MESSAGE
MOV R0,DB.IBF(J) ;SAVE BUFFER ADDRESS
MOV R3,DB.IAD(J) ;SAVE POINTER TO CHAR
BR 40$
30$: MOV #3,R0 ;CODE FOR STATUS MESSAGE
JSR PC,DVPBSM ;BEGIN STATUS SUBMESSAGE
BCC 40$
RTS PC ;ERROR RETURN
40$: CLR R0 ;CODE FOR PLAIN STATUS
JSR PC,DVPDAT ;PUT CODE INTO MESSAGE
BCS DVPSBM ;IF ERROR, SEND GARBAGE, AND CORRECT IT LATER
MOV DB.DCS(J),R0 ;GET DEVICE CONTROL STATUS
JSR PC,DVPEXD ;PUT STATUS INTO THE MESSAGE
BIC #DS.XDS,@J ;HAVE SENT STATUS NOW
;CLOSE OUT STATUS SUBMESSAGE (FALL INTO CODE)
;HERE TO CLOSE OUT CURRENT SUBMESSAGE
DVPSBM: MOV DB.IBF(J),R0 ;GET ADDRESS OF MESSAGE
TST DB.ICN(J) ;SEE IF COUNT EXISTS
BEQ 90$ ; NO, EXIT
MOVB @DB.ICN(J),R1 ;GET COUNT FOR STATUS PORTION
ADD R1,CN.LEN(R0) ;PUT COUNT INTO MESSAGE
CLR DB.ICN(J) ;NO MORE POINTER TO COUNT
90$: RTS PC
;.IF NE TTYN
;;TABLE OF IF CARRIER IS ON OR OFF
;CRBTAB: .WORD 0 ;(00) VIRGIN
; .WORD TS.CAR ;(02) RING
; .WORD 0 ;(04) CARRIER DETECT (WAITING FOR)
; .WORD 0 ;(06) CARRIER DETECT SATISFIED
; .WORD 0 ;(08) AUTO BAUD DETECT
; .WORD TS.CAR ;(10) RUNNING UNCONNECTED
; .WORD TS.CAR ;(12) RUNNING CONNECTED, WAITING FOR -10
; .WORD TS.CAR ;(14) RUNNING, CONNECTED, CONFIRMED
; .WORD TS.CAR ;(16) LOST CARRIER (TEMP, 5. SECONDS)
; .WORD 0 ;(18) WANT TO HANG UP
; .WORD 0 ;(20) HANG UP
;.IF NE FTDN11
; .WORD TS.CAR ;(22) DIALING
; .WORD TS.CAR ;(24) DIALOUT SUCCEEDED
; .WORD 0 ;(26) DIALOUT FAILED
;.ENDC;.IF NE FTDN11
;.IIF NE .-CRBTAB-2-LCS.MX,.ERROR <.-CRBTAB>;CRBTAB STATE PHASE ERROR IN DNDEV
;.ENDC ;.IF NE TTYN
;HERE TO BEGIN A SUBMESSAGE
; CALL MOV #TYPE,R0
; JSR PC,DVDBSM
;
;RETURN WITH CARRY CLEAR IF SUCCESS, CARRY SET IF FAILURE (E.G., NO FREE
;CHUNKS TO START A NEW MESSAGE).
;
;DVDBSM SETS UP FOR LARGE (.GT. 177 BYTES) SUBMESSAGES, FOR KNOWN SHORT
;MESSAGES USE DVPBSM INSTEAD.
.IF NE FT.DDP!FTECHO ;ONLY USED BY DDP AND ECHO-TASK DEVICE(S) SO FAR
DVDBSM: MOV R0,-(P) ;SAVE TYPE CODE
TST DB.ICN(J) ;DANGLING PREVIOUS SUBMSG ?
BEQ 10$ ;NO, JUST START NEW ONE
JSR PC,DVDSBM ;FINISH PREVIOUS SUBMESSAGE
10$: MOV DB.IBF(J),R0 ;GET POINTER TO MSG
BNE 30$ ;AND JUST APPEND NEW SUBMESSAGE
MOV (P)+,R0 ;GET CODE
TST DB.RLA(J) ;SEE IF WE HAVE A REMOTE LINK #
BEQ 40$ ;IF CONNECT NOT CONFIRMED, DON'T SEND
MOV DB.RLA(J),-(P) ;DESTINATION LINK ADDRESS
MOV R0,-(P) ;SAVE SUBMESSAGE TYPE
JSR PC,DVDNCL ;BEGIN MSG
BR 40$ ; ERROR TIME
TST (P)+ ;TOSS DUMMY (A LA DVXNCL) WORD
MOV R3,DB.IAD(J) ;SAVE BYTE POINTER
MOV (P)+,R1 ;GET COUNT BACK
MOV (P)+,R0 ;GET BUFFER ADDRESS
MOV R1,CN.LEN(R0) ;PUT COUNT INTO THE MSG
MOV R0,DB.IBF(J) ;SAVE MSG POINTER
MOV #001,DB.ICN+4(J);INITIAL COUNT IS 1
CLC ;FLAG GOOD RETURN
RTS PC
;HERE TO APPEND TO ALREADY-EXTANT NCL MESSAGE
30$: ADD #2,CN.LEN(R0) ;ACCOUNT FOR 2-BYTE COUNT FIELD COMING UP
MOV DB.IAD(J),DB.ICN+0(J) ;SAVE LOW-ORDER COUNT BYTE ADDRESS
JSR PC,DVDBYT ;ALLOCATE COUNT (LOW ORDER) BYTE
MOV DB.IAD(J),DB.ICN+2(J) ;SAVE HIGH-ORDER COUNT BYTE ADDRESS
JSR PC,DVDBYT ;ALLOCATE COUNT (HIGH ORDER) BYTE
CLR DB.ICN+4(J) ;INITIALIZE NCL SUBMESSAGE COUNT
MOV (P)+,R0 ;GET TYPE CODE BACK
BR DVDDAT ;PUT CODE INTO THE MESSAGE
40$: SEC ;ERROR RETURN
RTS PC
;STILL IN IF NE FT.DDP!FTECHO
;HERE TO PUT NEXT DATA BYTE IN AN NCL MESSAGE
; CALL JSR PC,DVDDAT ;WITH J SETUP AND CHAR IN R0
; ; USES R3 AS SCRATCH
; DB.IBF IS POINTER TO 1ST CHUNK IN MESSAGE
; DB.IAD IS INPUT CHAR POINTER
; DB.ICN IS POINTER TO CURRENT COUNT (LOW ORDER) IN SUBMESSAGE
; DB.ICN+2 IS POINTER TO CURRENT COUNT (HIGH ORDER) IN SUBMESSAGE
; DB.ICN+4 IS CURRENT SUBMESSAGE BYTE COUNT
DVDDAT: TST DB.ICN(J) ;IF NO PARTIAL MESSAGE, MAKE A NEW MSG.
BEQ DVDDAX ;NO MESSAGE, START UP A NEW ONE
INC DB.ICN+4(J) ;INCREMENT THE BYTE COUNT.
DVDBYT: MOV DB.IAD(J),R3 ;GET BYTE POINTER
.IF EQ DGUTS
ASSERT NE ;BETTER BE ONE
.IFF
BEQ DVDDAT ;IF NONE, TRY STARTING A NEW MSG
.ENDC ; .IF EQ DGUTS
MOVB R0,(R3)+ ;PUT CHARACTER INTO THE MESSAGE
ADVCNK R3 EXTEND ;ALLOCATE ANOTHER CHUNK IF REQUIRED
76$: MOV R3,DB.IAD(J) ;SAVE UPDATED BYTE POINTER
CLC ;SET SUCCESS
RTS PC
DVDDAX: MOV R0,-(P) ;START A NEW DATA SUBMESSAGE.
MOV #2,R0 ;SAVE DATA
JSR PC,DVDBSM ;BEGIN SUBMESSAGE
MOV (P)+,R0 ;GET CHAR BACK
BCC DVDDAT ;INSERT THE CHARACTER, IF THIS SUCCEEDED.
.IF EQ DGUTS
TRAP
.IFF
CTYMSG BME ;NCL MESSAGE GENERATION FAILURE.
SEC
RTS PC
.ENDC ; .IF EQ DGUTS
;STILL IN IF NE FT.DDP!FTECHO
;HERE TO CLOSE OUT CURRENT SUBMESSAGE
DVDSBM: MOV DB.IBF(J),R0 ;GET ADDRESS OF MESSAGE
TST DB.ICN(J) ;ADDRESS OF SAVED SUBMESSAGE COUNT FIELD
BEQ 90$ ;EXIT IF NO SUBMESSAGE
MOV DB.ICN+4(J),R1 ;LENGTH OF THIS SUBMESSAGE
ADD R1,CN.LEN(R0) ;ADD INTO TOTAL NCL MESSAGE LENGTH
MOVB R1,@DB.ICN(J) ;SET LOW ORDER BYTE LENGTH
BISB #200,@DB.ICN(J) ;SET IT AS EXTENSIBLE
ASL R1 ;SHIFT TO HIGH-ORDER 7-BIT'S WORTH
SWAB R1 ;POSITION FOR BYTE OPERATION
MOVB R1,@DB.ICN+2(J) ;SET HIGH-ORDER BYTE LENGTH
CLR DB.ICN(J) ;NO MORE POINTER TO COUNT
90$: RTS PC
.ENDC ;.IF NE FT.DDP!FTECHO
;HERE TO RECEIVE A STATUS MESSAGE
; CALL JSR PC,DVRSTS ;WITH J SETUP AFTER GETTING TYPE = 3 = STATUS
DVRSTS: JSR PC,DVGDBY ;GET CODE IN STATUS MSG
MOV R0,-(P) ;SAVE CODE
JSR PC,DVGEXF ;GET BITS TO SET/CLEAR
ASSERT EQ DB.OCN(J)
MOV (P)+,R1 ;GET CODE AGAIN
MOV DB.DCS(J),-(P) ;SAVE CURRENT STATUS
;DO "STATUS" IF REQUESTED
TST R1 ;DOES HE WANT A "MOVEM" STATUS?
BNE 60$ ;NO
MOV R0,DB.DCS(J) ;YES, SET NEW STATUS
BR 90$ ;CHECK FOR CHANGES
;DO "SET" BITS IF REQUESTED
60$: CMP #1,R1 ;DOES HE WANT A SET BITS ?
BNE 70$
BIS R0,DB.DCS(J) ;SET BITS
BR 90$ ;AND NOW DONE
;DO "CLEAR" BITS IF REQUESTED
70$: CMP #2,R1 ;WANT TO CLEAR BITS ?
BNE 80$
BIC R0,DB.DCS(J) ;CLEAR THE BITS LIKE BEFORE
BR 90$ ;NOW DONE
;ILLEGAL STATUS FUNCTION
80$:
.IF EQ DGUTS
TRAP
.IFF
TST (P)+ ;GET STACK BACK INTO SYNC
CTYMSG NCL ;LOG BAD NCL MSG ERROR
RTS PC ;AND EXIT
.ENDC ;.IF EQ DGUTS
;CHECK FOR STATUS CHANGES
90$: TRACE DV
MOV DB.DCS(J),R0 ;COPY OF NEW STATUS
CMP (P)+,R0 ;DID DEVICE CONTROL STATUS CHANGE?
BEQ 95$ ;NO, ALL SET
BIS #DS.XDS,@J ;YES, SEND -10 OUR NEW STATUS
95$: RTS PC
.IF NE FTHOST
;HERE TO FIND A HOST (E.G., FOR A TTY)
;CALL JSR PC,FNDHST WITH J SETUP
; JSR PC,FNDPFH TO FIND THE GUY'S PREFERED HOST
; RETURN WITH ZBIT SET IF LOSE
FNDPFH:
.IF NE FT.RNN
MOVB DB.RNN(J),R0 ;GET THE RESTRICTED NODE NUMBER
BEQ 10$ ;IF NONE, TRY THE PREFERRED HOST
JSR PC,FNDSCB ;TRY TO FIND THE RESTRICTED HOST
BEQ 9$ ;IF IT'S NOT THERE, TOUGH LUCK
BIT #SBF.IC,@SB ;ARE WE IN CONTACT?
BEQ 9$ ;NO, GIVE UP
BIT #SF.MCR,@SB ;DOES HE HAVE AN MCR?
9$: RTS PC
10$:
.ENDC ;FT.RNN
.IF NE FT.PFH ;IF WE'RE TRYING FOR A PREFERED HOST
MOVB DB.PFH(J),R0 ; GET THE NUMBER OF THE HOST
BEQ FNDHST ;IF NONE, JUST TRY NORMAL FNDHST
JSR PC,FNDSCB ;SEE IF THE HOST EXISTS
BEQ FNDHST ; IF NOT, HUNT FOR SOME OTHER
BIT #SBF.IC,@SB ;IF WE ARE NOT IN CONTACT
BEQ FNDHST ; DON'T USE THIS GUY
BIT #SF.MCR,@SB ;IF HE DOESN'T SUPPORT TERMINALS,
BEQ FNDHST ; DON'T USE HIM EITHER
RTS PC ;RETURN WITH ZBIT CLEAR
.ENDC ;FT.PFH
FNDHST:
.IF NE FTDL10!FT.DTE
MOV TENSCB,SB ;GET OUR -10'S SCB
BEQ 10$ ;DON'T HAVE NEIGHBORING -10
BIT #SBF.IC,@SB ;PROTOCOL UP YET?
RTS PC ;RETURN WITH/OUT AN SCB
.ENDC ;.IF NE FTDL10!FT.DTE
10$: MOV HOSTES,SB ;GET SCB WE LAST CONNECTED TO
BNE 16$ ;AND USE NEXT SCB
12$: MOV #FIRSCB,SB ;IF HAVEN'T DONE BEFORE USE FIRST
14$: BIT #SBF.IC,@SB ;ARE WE IN CONTACT ?
BEQ 16$ ;DON'T USE UNKNOWN NODES
BIT #SF.MCR,@SB ;DOES IT HAVE MCR ?
BNE 17$ ;IF HAS MCR USE IT
16$: SB.ADV 14$ ;GET ADR OF NEXT SCB
TST HOSTES ;DID WE TRY EVERYONE ?
BEQ 90$ ;IF SO USERS LOSES
CLR HOSTES ;FLAG COMPLETE SCAN
BR 12$ ;TRY AGAIN FROM TOP
17$: MOV SB,HOSTESS ;REMEMBER WHO WE WENT TO LAST
90$: RTS PC
.ENDC ;.IF NE FTHOST
.ENDC ;.IF NE DEVN