From:	CSBVAX::MRGATE!@KL.SRI.Com,@wiscvm.wisc.edu,@YMIR.BITNET:KVC@ENGVAX.SCG.HAC.COM@SMTP 17-JUL-1987 15:16
To:	EVERHART
Subj:	CMU pseudo-terminal drivers (part 3 of 3)  [DCL archive format]

Received: from wiscvm.wisc.edu by KL.SRI.COM with TCP; Thu 16 Jul 87 17:29:17-PDT
Received: from YMIR.BITNET by wiscvm.wisc.edu ; Thu, 16 Jul 87 19:27:19 CDT
Received: from ENGVAX.SCG.HAC.COM by YMIR.BITNET; Thu, 16 Jul 87 17:15 PDT
Date: Thu, 16 Jul 87 16:51 PDT
From: Kevin Carosso <@YMIR.BITNET:KVC@ENGVAX.SCG.HAC.COM>
Subject: CMU pseudo-terminal drivers (part 3 of 3)  [DCL archive format]
To: info-vax@sri-kl.ARPA
X-VMS-To: INFO-VAX-SUBMIT

$ show default
$ check_sum = 1276286148
$ write sys$output "Creating TPDRIVER.MAR"
$ create TPDRIVER.MAR
$ DECK/DOLLARS="$*$*EOD*$*$"
        .TITLE  TPDRIVER - Pseudo terminal driver for Front End and ethernet
        .IDENT  'V04-007'

;
;++
; FACILITY:
;
;       VAX/VMS TERMINAL DRIVER
;
; ABSTRACT:
;
;       PSEUDO TERMINAL ROUTINES.
;
; AUTHOR:
;
;       19-NOV-1982     Dale Moore (dwm) at CMU
;               Redone for VMS V3.0
;
;       This program has been granted to the public domain by the author.
;
; MODIFICATIONS:
;       Version 'V03-001':
;               DWM     - Added .Page above each .sbttl
;                       - added modem transition routines in disco and init
;                       - removed $ACBDEF external def's
;                       - restored timeout to resume
;                       - added ioc$initiate call in xoff and xon routines.
;       Version V03-002 - Changed TP startio to clear TIM in UCB$W_STS
;       Version V03-003 - Changed TP$RESUME to not set timeout bit in sts
;
;       Version V03-004 (Thu Dec  9 12:43:17 1982) D. Kashtan
;                         Made into a TEMPLATE driver.
;                         (***WARNING*** -- LOOK AT COMMENTS FOR ROUTINE
;                          TP$SET_LINE.  THERE IS IMPORTANT INFORMATION
;                          ABOUT CHANGES TO VMS THAT WILL AFFECT THE TPDRIVER)
;       Version V03-005 - (14-Jun-1983 )Dale Moore
;                         Add R4 to masks on calls to ioc$initiate.
;                         TTY$STARTIO clobber R4.
;       Version V03-006 - Change TP$XON and TP$XOFF routines from
;                         unconditionally calling IOC$INITIATE.
;                         IOC$INITIATE will branch to PY$STARTIO,
;                         Which will call TTY$GETNEXTCHAR (UCB$L_TT_GETNEXT),
;                         Which will branch to EOLSEEN,
;                         which calls TTY$READONE,
;                         which calls the PORT_XOFF routine which is TP$XOFF.
;                         This cycle was eating up all of the kernel stack.
;       Version V03-007 - (12-Jul-1983) Mark London
;                         Set default of TP to TERM to allow REPLY/USERS.
;                         Make TP owned and not a TEMPLATE in order that
;                         SHO TERM TPA0 does not cause a crash (SHOW attempts
;                         an ASSIGN to the device.)
;       Verison V04-001 - ( 9-Nov-1984 ) L. Bellamy and D. Davis
;                         In order of appearance:
;
;                         Added Object Rights Block offset definitions.
;                         Add TEMPLATE bit to UCB$W_STS.
;                         Add ORB definitions in prologue.
;                         Modify to allow vector definitions using VEC macro.
;                         Use CLASS_CTRL_INIT and CLASS_UNIT_INIT to locate
;                          vector table.
;                         Update powerfail routines.
;                         Use new methodology for XON/XOFF flow control.
;                         Get rid of all the SET_LINE stack manipulation
;                         since the terminal driver does not do anything
;                         malicious as suggested.
;
;                         NOTE - Comments in subroutine preambles not altered
;                         to reflect changes in most places.
;
;       Version V04-003 (24-Jun-1985) Kevin Carosso, Hughes Aircraft Co., S&CG
;                       Cleaned this thing up quite a bit.
;                       - Got rid of MBX characteristic on the devices.  This
;                         was a holdover to before cloned devices really
;                         existed.
;                       - Leave the TP template device OFFLINE.  This is what
;                         other TEMPLATE devices do, to indicate that you
;                         really cannot do I/O to the template.  Also left
;                         it UNAVAILABLE, since the only way it is supposed to
;                         get used is by cloning in the PY device.
;                       - Got rid of all modem operations.  Improper use tended
;                         to crash the system and they are not necessary.  TP
;                         device is always NOMODEM.  HANGUP works as you want
;                         it to without the modem stuff.
;                       - Setup forced characteristics and default permanent
;                         characteristics.  Forced are: NOAUTOBAUD, and NODMA.
;                         Default is HANGUP.
;                       - Fixed up TP$DISCONNECT to properly send a message
;                         to PY device's associated mailbox only if we are
;                         actually doing a hangup.  It used to do it every
;                         time.  Changed the message to MSG$_TRMHANGUP.
;                       - Got rid of the BRDCST on/off stuff.  It doesn't seem
;                         to be necessary any more.  It also had a bug in it
;                         somewhere that caused the terminal to start off
;                         NOBRDCST when it shouldn't.
;                       - General house-cleaning.  Got rid of commented out
;                         lines from VMS V3 version.  Fixed up typos in
;                         comments.
;
;       Version V04-004 (10-Feb-1986) Kevin Carosso, Hughes Aircraft Co., S&CG
;                       Changed all references to PTDRIVER to TPDRIVER because
;                       DEC (bless their little hearts) invented the %*%#$%
;                       TU81 and use PTA0: now.
;
;       Version V04-005 (3-Sep-1986) Kevin Carosso, Hughes Aircraft Co., S&CG
;                       Fixed bug whereby the sequence ^S followed by ^Y
;                       would cause a system hang.  Apparently the class
;                       driver calls the port RESUME routine when doing
;                       an ABORT and again when canceling the ^S.  Calling
;                       RESUME twice like this is bad.  In general, the
;                       port RESUME routine should not restart the output.
;                       In this driver, the RESUME and STOP routines aren't
;                       needed, so I got rid of them completely.
;
;                       Now on ^Y the ^S state is not cleared.  You still
;                       need to type ^Q to get your output (including the
;                       *INTERRUPT* echo string.  I thought this was another
;                       bug, but it's how my DHU-11 based terminals act
;                       and makes sense, because only a ^Q should really
;                       cancel a ^S.
;
;                       Also removed the TEMPLATE bit from the TPA0: template
;                       device since it was allowing people to $ASSIGN channels
;                       and get unhappy (lonely) TP devices that could crash
;                       the system.  Now, the only way to clone TP devices
;                       is through the code in PYDRIVER, hence by assigning
;                       a channel to PYA0:.  You can still $ASSIGN to TPA0:,
;                       but since the device is offline that shouldn't hurt
;                       anything.  This fixed crashes caused by KERMIT and
;                       other things attempting to use TPA0:.  You now get
;                       an error "DEVOFFLINE".
;
;                       Fixed a bug that caused a system crash from SHOW
;                       DEVICE/FULL of TPA0:.  The ACL_QUEUE bit was set
;                       in the ORB but the ACL queue was invalid (was zeroed).
;                       I got rid of the bit, now all is well.
;
;       Version V04-006 (5-Dec-1986) Kevin Carosso, Hughes Aircraft Co., S&CG
;                       Fixed the infamous character munging bug.  The fix
;                       is really in PYDRIVER.
;
;       Version V04-007 (10-JUL-1987) Kevin Carosso, Hughes Aircraft Co., S&CG
;                       In TP$INITLINE make sure to tell the class driver
;                       never to time out.  This fix from Forest Kenney
;                       at DEC.
;
;                       Also, while we're in here, lets make the device
;                       acquire "NODE$" prefixes, since all the other
;                       terminal drivers do.
;--









        .PAGE
        .SBTTL  Declarations

        .LIBRARY        /SYS$LIBRARY:LIB.MLB/

;
; EXTERNAL DEFINITIONS:
;
..NOCROSS
        $CRBDEF                         ; DEFINE CRB
        $DCDEF                          ; DEVICE CLASSES AND TYPES
        $DDBDEF                         ; DEFINE DDB
        $DDTDEF                         ; DEFINE DDT
        $DEVDEF                         ; DEVICE CHARACTERISTICS
        $DYNDEF                         ; Dynamic structure definitions
        $IDBDEF                         ; DEFINE IDB OFFSETS
        $IODEF                          ; I/O Function Codes
        $IRPDEF                         ; IRP definitions
        $MSGDEF                         ; Message types
        $ORBDEF                         ; Define Object's Rights Block offsets
        $TTYDEF                         ; DEFINE TERMINAL DRIVER SYMBOLS
        $TTDEF                          ; DEFINE TERMINAL TYPES
        $TT2DEF                         ; Define Extended Characteristics
        $UCBDEF                         ; DEFINE UCB
        $VECDEF                         ; DEFINE VECTOR FOR CRB
        $TTYMACS                        ; DEFINE TERMINAL DRIVER MACROS
        $TTYDEFS                        ; DEFINE TERMINAL DRIVER SYMBOLS
..CROSS

;
; LOCAL DEFINITIONS
;
DT$_TP = ^XFF
;
; Definitions that follow the standard UCB fields for TP driver
;  This will all probably have to be the same as the standard term

        $DEFINI UCB                     ; Start of UCB definitions

        .=UCB$K_TT_LENGTH               ; Position at end of UCB

$DEF    UCB$L_TP_XUCB   .BLKL   1       ; UCB of corresponding
                                        ;  control/application unit
$DEF    UCB$K_TP_LEN                    ; Size of UCB

        $DEFEND UCB                     ; End of UCB definitions
;
; Definitions that follow the standard UCB fields in PY devices
;

        $DEFINI UCB                     ; Start of UCB definitions

        .=UCB$K_LENGTH          ; position at end of UCB

$DEF    UCB$L_PY_XUCB   .BLKL 1 ; UCB of terminal part of pseudo terminal

$DEF    UCB$K_PY_LEN            ; Size of UCB

        $DEFEND UCB             ; end of UCB definitions

;
; LOCAL STORAGE
;
        .PSECT  $$$105_PROLOGUE









        .PAGE
        .SBTTL  Standard Tables

;
; Driver prologue table:
;
TP$DPT::
        DPTAB   -                       ; DRIVER PROLOGUE TABLE
                END=TP_END,-            ; End and offset to INIT's vectors
                UCBSIZE=UCB$K_TP_LEN,-  ; SIZE OF UCB
                FLAGS=DPT$M_NOUNLOAD,-  ; Do not allow unload
                ADAPTER=NULL,-          ; ADAPTER TYPE
                NAME=TPDRIVER,-         ; NAME OF DRIVER
                VECTOR=PORT_VECTOR
        DPT_STORE INIT
        DPT_STORE UCB,UCB$W_UNIT_SEED,W,0       ; SET UNIT # SEED TO ZERO
        DPT_STORE UCB,UCB$B_FIPL,B,8    ; FORK IPL
        DPT_STORE UCB,UCB$L_DEVCHAR,L,<-; CHARACTERISTICS
                        DEV$M_REC!-     ;
                        DEV$M_IDV!-     ;
                        DEV$M_ODV!-     ;
                        DEV$M_TRM!-     ;
                        DEV$M_CCL>
        DPT_STORE UCB,UCB$L_DEVCHAR2,L, -               ; Device characteristics
                        <DEV$M_NNM>                     ; prefix with "NODE$"
        DPT_STORE UCB,UCB$B_DEVCLASS,B,DC$_TERM         ;
        DPT_STORE UCB,UCB$B_TT_DETYPE,B,TT$_UNKNOWN     ; TYPE
        DPT_STORE UCB,UCB$W_TT_DESIZE,@W,TTY$GW_DEFBUF  ; BUFFER SIZE
        DPT_STORE UCB,UCB$L_TT_DECHAR,@L,TTY$GL_DEFCHAR ; DEFAULT CHARACTERS
        DPT_STORE UCB,UCB$L_TT_DECHA1,@L,TTY$GL_DEFCHAR2; DEFAULT CHARACTERS
        DPT_STORE UCB,UCB$W_TT_DESPEE,@B,TTY$GB_DEFSPEED; DEFAULT SPEED
        DPT_STORE UCB,UCB$W_TT_DESPEE+1,@B,TTY$GB_RSPEED; DEFAULT SPEED
        DPT_STORE UCB,UCB$B_TT_DEPARI,@B,TTY$GB_PARITY  ; DEFAULT PARITY
        DPT_STORE UCB,UCB$B_TT_PARITY,@B,TTY$GB_PARITY  ; DEFAULT PARITY
        DPT_STORE UCB,UCB$B_DEVTYPE,B,TT$_UNKNOWN       ; TYPE
        DPT_STORE UCB,UCB$W_DEVBUFSIZ,@W,TTY$GW_DEFBUF  ; BUFFER SIZE
        DPT_STORE UCB,UCB$L_DEVDEPEND,@L,TTY$GL_DEFCHAR ; DEFAULT CHARACTERS
        DPT_STORE UCB,UCB$L_TT_DEVDP1,@L,TTY$GL_DEFCHAR2; Default Characters
        DPT_STORE UCB,UCB$W_TT_SPEED,@B,TTY$GB_DEFSPEED ; DEFAULT SPEED
        DPT_STORE UCB,UCB$W_TT_SPEED+1,@B,TTY$GB_RSPEED ; DEFAULT SPEED
        DPT_STORE UCB,UCB$B_DIPL,B,8                    ; DEV IPL (no device)
        DPT_STORE UCB,UCB$L_TT_WFLINK,L,0       ; Zero write queue.
        DPT_STORE UCB,UCB$L_TT_WBLINK,L,0       ; Zero write queue.
        DPT_STORE UCB,UCB$L_TT_RTIMOU,L,0       ; Zero read timed out disp.
;
; Added ORB definitions
;
        DPT_STORE ORB, ORB$B_FLAGS, B, <ORB$M_PROT_16>
        DPT_STORE ORB, ORB$W_PROT, @W, TTY$GW_PROT
        DPT_STORE ORB, ORB$L_OWNER, @L, TTY$GL_OWNUIC

        DPT_STORE DDB,DDB$L_DDT,D,TP$DDT

        DPT_STORE REINIT
        DPT_STORE CRB,CRB$L_INTD+VEC$L_INITIAL,D,TP$INITIAL; CONTROLLER INIT
        DPT_STORE CRB,CRB$L_INTD+VEC$L_UNITINIT,D,TP$INITLINE; UNIT INIT
        DPT_STORE END

        DDTAB   DEVNAM  = TP,-          ; Dummy TP port Driver Dispatch table
                START   = 0,-
                FUNCTB  = 0

        .PSECT $$$115_DRIVER,LONG

; The associated class driver uses this table to command the port driver.
; The address of the table is contained in the terminal UCB extension area.
; The offset definitions are defined by the ttydefs.

;
; TP specific dispatch table
;
PORT_VECTOR:
;
; Added port vector table using VEC macros
;
        $VECINI TP,TP$NULL
        $VEC    STARTIO,TP$STARTIO
        $VEC    DISCONNECT,TP$DISCONNECT
        $VEC    SET_LINE,TP$SET_LINE
        $VEC    XON,TP$XON
        $VEC    XOFF,TP$XOFF
        $VEC    ABORT,TP$ABORT
        $VECEND

TP$NULL:                                ; Null port routine
        RSB










        .PAGE
        .SBTTL  TP$INITIAL - Initialize pseudo terminal interface
;++
; TP$INITIAL - INITIALIZE INTERFACE
;
; FUNCTIONAL DESCRIPTION:
;
; This routine is entered at device CONNECT time and power recovery.
; All we do is connect ourselves up to the class driver.
;
; INPUTS:
;
;       R4 = ADDRESS OF THE UNIT CSR
;       R5 = IDB OF UNIT
;       R8 = ADDRESS OF THE UNIT CRB
;
; OUTPUTS:
;
;       R0, R1, R2, R3 are destroyed.
;
; IMPLICIT INPUTS:
;
;       IPL = IPL$_POWER
;
;--
TP$INITIAL::

        CLASS_CTRL_INIT TP$DPT,PORT_VECTOR
        MOVB    #DT$_TP,CRB$B_TT_TYPE(R8)
        RSB









        .PAGE
        .SBTTL  TP$INITLINE - RESET INDIVIDUAL LINE
;++
; TP$INITLINE - RESET pseudo terminal control state
;
; FUNCTIONAL DESCRIPTION:
;
; This routine performs a simple unit initialization.
;
;
; INPUTS:
;
;       R5 = UCB ADDRESS
;
; OUTPUTS:
;
;       R2,R5 ARE PRESERVED.
;--
TP$INITLINE::                           ; RESET SINGLE LINE
        MOVAL   TP$VEC,R0               ; Set TP port vector table
        CLASS_UNIT_INIT
        TSTL    UCB$W_UNIT(R5)          ; Skip initialization of TEMPLATE
        BEQL    40$                     ; Unit #0 = Template: Skip everything!

        BBS     #UCB$V_POWER,UCB$W_STS(R5),-    ; Skip if powerfail recovery
                20$
        movl    UCB$L_TT_LOGUCB(r5), r1         ; Look at logical term UCB
        beql    10$                             ; If none, then has no refs
        tstw    UCB$W_REFC(r1)                  ; See if TP has any references
        BNEQ    20$                             ; If so don't reinit ucb
10$:    bsb     set_forced_chars                ; Set required characteristics
        BISL    #TT2$M_HANGUP,-                 ; Set default characteristics
                UCB$L_TT_DECHA1(R5)
        MOVL    UCB$L_TT_CLASS(R5),R1           ; Address class vector table
        JSB     @CLASS_SETUP_UCB(R1)            ; Init ucb fields
        bisw    #TTY$M_PC_NOTIME, -
                UCB$W_TT_PRTCTL(r5)             ; Class driver not to time out

20$:    BBC     #UCB$V_POWER,UCB$W_STS(R5),40$  ; Powerfail handler
        MOVL    UCB$L_TT_CLASS(R5),R0
        JMP     @CLASS_POWERFAIL(R0)

40$:    RSB

;
; This little routine sets certain required characteristics.  It is called by
; the INITLINE code to set them at the outset and by the SETLINE code to reset
; them unconditionally if someone tries to set them.
;
set_forced_chars:
        bicl2   #<TT2$M_DMA ! TT2$M_AUTOBAUD>, -
                UCB$L_TT_DEVDP1(R5)
        bicl2   #<TT2$M_DMA ! TT2$M_AUTOBAUD>, -
                UCB$L_TT_DECHA1(R5)
        rsb










;++
; TP$SET_LINE - Used to Reset SPEED and UCB
;
; FUNCTIONAL DESCRIPTION:
;
;       Called whenever someone tries to set terminal modes/characteristics.
;       All we do is reset anything that we think should never be changed.
;
; INPUTS:
;
;       R5 = UCB ADDRESS of TP
;
; OUTPUTS:
;
;       none
;--
TP$SET_LINE::
        brb     set_forced_chars











        .Page
;++
; TP$DISCONNECT - SHUT OFF UNIT
;
; FUNCTIONAL DESCRIPTION:
;
; This routine is used when for some reason the unit must be disconnected.
; This can be at hangup or last deassign.  If the PY device has an associated
; mailbox, signal an MSG$_TRMHANGUP in it.
;
; Although we are disconnecting a virtual device, we don't do anything
; more than send a hangup message because we want to allow the device to
; be reusable.  It's really only if the control device (PY) goes away
; that we mark the TP offline and delete it's UCB.  That code's all in
; PYDRIVER.
;
; INPUTS:
;
;       R0 = (0 for hangup, 1 for nohangup)
;       R5 = UCB ADDRESS of TP
;
; OUTPUTS:
;
;       R3,R4 ARE USED.
;--
TP$DISCONNECT::
        blbs    r0, 99$                 ; If no hangup, skip all this.

        PUSHR   #^M<R0,R1,R2,R3,R4,R5>  ; Save the registers

        MOVL    UCB$L_TP_XUCB(R5),R5    ; Get PY UCB
        BEQL    10$                     ; If disconnected, ignore
        MOVL    UCB$L_AMB(R5),R3        ; Load Associated Mailbox of PY UCB
        BEQL    10$                     ; If EQL then no mailbox
        MOVZWL  #MSG$_TRMHANGUP,R4      ; Load Message Type
        JSB     G^EXE$SNDEVMSG          ; Send the message
10$:    POPR    #^M<R0,R1,R2,R3,R4,R5>  ; Restore everything
99$:    RSB











        .PAGE
        .SBTTL  TP START I/O ROUTINE
;++
; TP$STARTIO - START I/O OPERATION ON TP
;
; FUNCTIONAL DESCRIPTION:
;
;       This routine is entered from the device independent terminal startio
;       routine to enable output interrupts on an idle TP unit
;
; INPUTS:
;
;       R3 =    Character       AND     CC = Plus (N EQL 0)
;       R3 =    Address         AND     CC = Negative (N EQL 1)
;
;       R5 = UCB ADDRESS
;
; OUTPUTS:
;
;       R5 = UCB ADDRESS
;--
TP$STARTIO::                            ; START I/O ON UNIT
        BGEQ    20$                     ; Single character
        BISW    #TTY$M_TANK_BURST,-     ; Signal burst active
                UCB$W_TT_HOLD(R5)
10$:
;
; Here we must do something to notify our mate device that
; there is data to pick up
;
        PUSHR   #^M<R0,R2,R3,R4,R5>     ; Save TP UCB
        MOVL    UCB$L_TP_XUCB(R5),R5    ; Switch to PY UCB
        BEQL    17$                     ; PY is disconnected: skip
        DSBINT  UCB$B_FIPL(R5)
        BBC     #UCB$V_BSY,-            ; If the device isn't busy,
                UCB$W_STS(R5),15$       ; then dont do i/o
        MOVL    UCB$L_IRP(R5),R3        ; Get IRP address
        JSB     G^IOC$INITIATE          ; IOC$INITIATE needs IRP addr
15$:    ENBINT
16$:    POPR    #^M<R0,R2,R3,R4,R5>     ; Switch back to TP UCB
        RSB
;
; Come here if we have no PY control device to send stuff to.  Just
; suck all the data we can out of the class driver and throw it away.
;
17$:    POPR    #^M<R0,R2,R3,R4,R5>     ; Switch back to TP UCB
18$:    bicb    #UCB$M_INT, UCB$W_STS(r5)
        jsb     @UCB$L_TT_GETNXT(r5)
        tstb    UCB$B_TT_OUTYPE(r5)
        bneq    18$
        rsb

20$:
        MOVB    R3,UCB$W_TT_HOLD(R5)    ; Save output character
        BISW    #TTY$M_TANK_HOLD,-      ; Signal charater in tank
                UCB$W_TT_HOLD(R5)
        BRB     10$









        .PAGE
        .SBTTL  Port Routines Stop,Resume,XON,XOFF
;++
; TP$XOFF -     Send Xoff
; TP$XON -      Send Xon
; TP$ABORT -    Abort current output
;
; Functional Description:
;
;       These routines are used by the terminal class driver to
;       control output on the port
;
; Inputs:
;
;       R5 = UCB Address
;
; Outputs:
;
;       R5 = UCB Address
;--
        .ENABLE LSB
;
; Schedule xon/xoff to be sent
;
TP$XOFF:
TP$XON:
;
; Changed schedule bit mask
;
        BISW    #TTY$M_TANK_PREMPT,UCB$W_TT_HOLD(R5)    ; Schedule xon
        MOVB    R3,UCB$B_TT_PREMPT(R5)                  ; Save character
20$:
        RSB
        .DISABLE LSB
;
; Abort any port currently active
;
TP$ABORT:
5$:     BBCC    #TTY$V_TANK_BURST,UCB$W_TT_HOLD(R5),-   ; reset burst active
                10$
10$:    RSB

TP_END:                         ; End of driver

        .END
$*$*EOD*$*$
$ checksum TPDRIVER.MAR
$ if checksum$checksum .ne. check_sum then -
$   write sys$output "Checksum failed, file probably corrupted"
$ exit
