.TITLE BAUD - Autobaud Terminal Handler .IDENT /1.04/ ;++ ; Title: ; BAUD - Autobaud Terminal Handler ; ; Facility: ; System utility to implement automatic baud rate detection ; for terminal lines. ; ; Abstract: ; This program determines the speed of the incoming data on ; a DZ-11 line. This is useful when a dial-in line could come ; in at more than one speed. The speed cannot be determined until ; the line is answered. ; ; A user wishing to login must type one or more carriage returns ; until the "Username:" prompt is received. The speed detection ; is accomplished by having a one character read pending for every ; line that is to be autobauded. When a character is received, ; it is checked to see if it is a carriage return, or if it is a ; known pattern which represents a carriage return read at the wrong ; speed. If the character falls into either of these two cases, the ; DZ-11 speed is adjusted to the incoming speed, and a message is ; send to the Job Controller mailbox to initiate a login. If the ; character cannot be recognized, the DZ-11 speed is adjusted ; and another read is posted. This process is repeated until the ; incoming character is recognizable. ; ; The BAUD program is intended to run as a detached process. It must ; run with the [1,4] UIC in order to communicate with the Job ; Controller. Configuration information is passed to the detached ; process via a mailbox. The DCL command sequence: ; $COPY TT: BAUD_OPER_MBX ; baud commands..... ; ^Z ; can be used to send configuration commands. The commands can ; enable and disable autobauding on any line and select the ; legal baud rates recognized by BAUD. The configuration ; commands can also be placed (along with the RUN command to start BAUD) ; into a detached job submitted by SYSTARTUP.COM. ; ; The configuration commands recognized by BAUD are as follows: ; STOP Terminate BAUD freeing all terminals. ; AUTO TTcu: Enables autobauding on line TTcu: ; FREE TTcu: Disables autobauding on line TTcu: ; ADDR n Add new allowable baud rate ; DELR n Deletes allowable baud rate ; ; Command names must begin in the first character in the record ; and contain exactly 4 characters. If there is a command ; parameter, it must be separated from the command by exactly ; one blank. ; ; The main program of BAUD is normally in hibernation. It is ; periodically awakened to scan the range of lines known to be ; available for autobauding. Any lines which are found to ; be available for autobauding, but not owned by any process, are ; allocated and a read with timeout is made. This places the line ; into the "RELEASED" state. If a character is received on this read, ; the normal autobaud detection sequence is begun. If the read instead ; times out, a HANGUP $QIO function is issued to hangup the line. ; This hangup causes the DTR modem signal to be dropped. Dropping this ; signal usually causes the communications equipment to disconnect ; the incoming line instead of holding if forever. When the hangup ; is initiated, the line is placed into the "HANGUP_PENDING" state. ; This state is necessary because the hangup takes some period of ; time to occur, even after the I/O request finishes. The AST ; routine for this state is triggered by a timer request, and ; eventually issues a read and transitions the the "IDLE" state. ; ; The normal autobaud sequence takes place when a character is received ; in response to a read. The character is analyzed, and if it can ; be recognized, the DZ-11 speed is set to the incoming line speed, and ; the line is released for the user. The Job Controller is sent ; a message identical to that it normally receives from TTDRIVER, which ; makes it think there was an unsolicited typein on the newly freed ; terminal. Job Control then starts a login sequence for the user. ; ; When the character is not recognizable as a carriage return, the ; DZ-11 speed is adjusted and a read with timeout is issued. The ; line enters the "ADJUST_SPEED" state. If a character is ; received on this read, it is analyzed and processed as above. ; If the read times out, it is assumed that the user has given up, ; The line is returned to the IDLE state, via the HANGUP_PENDING ; state as described above. In the ADJUST_SPEED state, the ; timeout read also serves to prevent the line from becoming "lost" ; if the user radically alters his terminal speed during an ; autobaud sequence. This could cause a problem if BAUD is homing ; in on a low speed signal, and suddenly the user drastically raises ; the speed. The start bit is then too short to be detected by the ; DZ-11 and the line ceases to respond. ; ; The default selection of legal baud rates is intended to provide ; for one or two carriage return selection of the speeds 110, 150, 300, ; 600, 1200, and 2400 baud. If different speeds are desired, they ; can be added via the commands described above. If it is necessary ; to autobaud above 4800 baud, it will be necessary to alter the ; DEFAULT SPEED assembly parameter and reassemble the program. ; The assembly parameter LOG_ENABLE can be used to enable the printing ; of log messages tracing the operation of the program. Setting it to ; causes the logging code to be omitted. BAUD uses a structured- ; programming macro package which must be included at assembly. ; To build BAUD, use the following commands: ; ; $MACRO/LIST BAUD+SMAC/LIB ; $MESSAGE/LIST BAUDMSG ; $LINK BAUD+BAUDMSG ; ; Environment: ; Native Mode. Intended to run as detached process with ; following privileges and quotas: ; $RUN/PROCESS_NAME=AUTO_BAUD,- ; /UIC=[001,004],- ; /AST_LIMIT=n+2,- ; /FILE_LIMIT=n+2,- ; /IO_BUFFERED=n+2,- ; /PAGE_FILE=1000,- ; /QUEUE_LIMIT=n ; /PRIORITY=14,- ; /PRIVILEGES=PHY_IO ; Where n is the number of terminals to be autobauded. ; ; Author: ; Gary L. Grebus, Creation date: 17-Feb-1981 ; Battelle Columbus Labs ; ; Modified by: ; 1.00 - Gary L. Grebus, 27-Feb-1981 ; Initial version up for testing ; ; 1.01 - Gary L. Grebus, 7-Apr-1981 ; Fixed MESSAGE macro to supply correct argument count in vector ; ; 1.02 - Gary L. Grebus, 23-Apr-1981 ; Changed default listening rate to 1200 baud. Eliminated ; 150 baud as a default rate. This makes distinguishing ; 1200 and 2400 baud more reliable. ; ; 1.03 - Gary L. Grebus, 27-Apr-1981 ; Corrected bad GARP_TABLE entry for 1200 baud listening. ; Added 150 baud back as a default rate. This prevents ; more serious problems by causing 110 baud to take 2 cr's ; Problem is 300 baud cr sometimes appearing as a zero and ; falsing to 110 baud. ; ; 1.04 - Gary L. Grebus, 7-May-1981 ; Fixed access violation in DATA_RECEIVED. Bit position ; argument was being supplied as a byte instead of a ; longword. ;-- .PAGE .SBTTL Symbol definitions ; System symbols $IODEF ; IO function codes $TTDEF ; Terminal related symbols ; Equated symbols MAX_TERMS = 48 ; Maximum number of terminals allowed MBX_BUFFER_SZ = 12 ; Size of buffer for configuration ; mailbox LOG_ENABLE = 1 ; Flag - non-zero activates debugging ; log messages UNITS_PER_CTRL = 8 ; Number of units on a controller SCAN_SECS = 8 ; Interval between wakeups to scan ; for newly freed terminals and update ; the TST RELEASE_SECS = 30 ; Timeout after user logs out before ; we drop DTR and hang up on him. ADJ_SPEED_SECS = 10 ; Timeout after withc we assume we ; have lost control of line while ; adjusting speed. HANGUP_SECS = 2 ; Interval to wait following doing a ; QIO hangup to make sure it finishes. ; Should be twice system parameter ; TTYSCANDELTA DEFAULT_SPEED = TT$C_BAUD_1200 ; Default speed to read terminals at READ_FUNC = IO$_READPBLK ! IO$M_PURGE !- IO$M_NOECHO ! IO$M_CVTLOW !- IO$M_NOFILTR ; Function code and modifiers for ; terminal read ASCII_CR = ^X0D ; ASCII carriage return NR_DZ_BAUDS = 15 ; # of baud rates available on DZ-11 DEF_HIGHEST_BAUD = TT$C_BAUD_2400 ; Default highest baud rate to allow DEF_LOWEST_BAUD = TT$C_BAUD_110 ; Default lowest baud rate to allow ; These should match selections in ; OUR_RATES bit table. .PAGE .SBTTL Local macros ; Local macros .MACRO MESSAGE CODE,F1,F2,F3,F4,F5,F6,F7,F8 ;; Macro to build a message vector for the $PUTMSG system service. ;; Vector is for only one message and is built on the stack. ;; Message flags are left null. R0 is modified in additon to the ;; $PUTMSG call. .IF BLANK, ;; Code must be specified .ERROR ; Message code must be specified .MEXIT .ENDC .NARG ..MSG_NARGS ;; Get number of arguments ..LEN = 0 ; Length of vector built on stack .IRP F, .IF NB, ;; If parameter was supplied PUSHL 'F ; Push the parameter ..LEN = ..LEN + 1 ;; and count it .ENDC .ENDR .IF NE,<..LEN> ;; If there were FAO args PUSHL #..LEN ; Push FAO count ..LEN = ..LEN + 1 ;; and count it .ENDC PUSHL CODE ; Store message code PUSHL #..LEN+1 ; Store vector length MOVL SP,R0 ; Point to vector $PUTMSG_S MSGVEC=(R0) ; Issue the message ADDL2 #<4*<..LEN+2>>,SP ; Remove vector from stack .ENDM MESSAGE .MACRO LOG_MESSAGE CODE,F1,F2,F3,F4,F5,F6,F7,F8 ;; Macro to issue a log message. Message code is only generated if ;; logging is enabled. .IF NE,LOG_ENABLE MESSAGE CODE,,,,,,,, .ENDC .ENDM LOG_MESSAGE .MACRO IF_ERROR CODE,F1,F2,F3,F4,F5,F6,F7,F8,?L1 ;; Macro to stop on an error. Issues the specified local message ;; then does a LIB$STOP on the system error code in R0. BLBS R0,L1 ; Branch if no error PUSHR #^M ; Save the system code MESSAGE CODE,,,,,,,, POPR #^M ; Restore system code CALL LIB$STOP, R0 ; Stop on the system code L1: .ENDM IF_ERROR .MACRO DELTA SECONDS=0,HUNDREDTHS=0 ;; Macro to allow easy definition of short delta times. Time cannot ;; exceed about 7 minutes when defined in this manner. .IIF GT,, .WARN ; Delta time may be too big .LONG -1*<<10*1000000*SECONDS>+<100000*HUNDREDTHS>> .LONG -1 .ENDM DELTA .PAGE .SBTTL Read/write data .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Read/write data ; ; Terminal Status Table ; ; This structure is used to keep track of the status of all terminal (TTcu:) ; lines on the system. Table is in order TTA0:, TTA1:,...TTF6:, TTF7:,... ; Table contains an entry for each terminal found on the system. ; ; Table entry description $DEFINI TST $DEF TST_Q_IOSB .BLKQ 1 ; IOSB for terminal operations $DEF TST_R_CHRBUF .BLKL 1 ; Buffer for $GETCHN service. First $DEF TST_Q_DEVCHR .BLKQ 1 ; longword needed for $GETCHN. ; Remaining quadword used for $QIO ; SETCHAR $DEF TST_W_CHAN .BLKW 1 ; Channel number assigned to terminal $DEF TST_W_STS .BLKW 1 ; Status flags ; Valid status bits _VIELD TST,0,<- ,- ; Line should be autobauded ,- ; We own (have allocated) this line > $DEF TST_T_BUFFER .BLKB 4 ; Buffer for reading from terminal $DEF TST_T_NAME .BLKB 6 ; Terminal name $DEF TST_B_STATE .BLKB 1 ; Terminal state code ; Valid terminal state codes ; Zero = invalid TST_C_ST_IDLE = 1 ; Line is idle - read pending TST_C_ST_RELEASE = 2 ; Line is released - read/tmo pending TST_C_ST_ADJ = 3 ; Speed being adjusted - read/tmo ; pending TST_C_ST_BUSY = 4 ; Line is in use TST_C_ST_HNGUP = 5 ; Hangup pending $DEF TST_B_SPEED .BLKB 1 ; Code for current terminal speed $DEF TST_C_ENTSZ ; Size of an entry $DEFEND TST ; ; Reserve storage for the TST and associated variables ; TERM_STAT: .BLKB MAX_TERMS*TST_C_ENTSZ ; Terminal status table LOWEST_TERM_IDX: COUNT 0 ; TST index of lowest terminal ; to autobaud HIGHEST_TERM_IDX: COUNT 0 ; TST index of highest terminal ; to autobaud NR_TERMS: COUNT 0 ; Number of terminals currently ; on system ; ; Baud rate data ; ; Longword bit mask of default rates we will recognize. 134 and 150 ; should not be both set. 1800 and 2000 should not be both set. ; Bit number corresponds to the baud rate code. Note bit zero unused. OUR_RATES: .LONG - <<1@> ! - <1@> ! - <1@> ! - <1@> ! - <1@> ! - <1@>> ; Table for conversion between speed values and the speed codes ; returned for device characteristics. RATE_CODES: .WORD 50,TT$C_BAUD_50 .WORD 75,TT$C_BAUD_75 .WORD 110,TT$C_BAUD_110 .WORD 134,TT$C_BAUD_134 .WORD 150,TT$C_BAUD_150 .WORD 300,TT$C_BAUD_300 .WORD 600,TT$C_BAUD_600 .WORD 1200,TT$C_BAUD_1200 .WORD 1800,TT$C_BAUD_1800 .WORD 2000,TT$C_BAUD_2000 .WORD 2400,TT$C_BAUD_2400 .WORD 3600,TT$C_BAUD_3600 .WORD 4800,TT$C_BAUD_4800 .WORD 7200,TT$C_BAUD_7200 .WORD 9600,TT$C_BAUD_9600 HIGHEST_BAUD: .BLKL 1 ; Current highest allowed baud rate LOWEST_BAUD: .BLKL 1 ; Current lowest allowed baud rate ; ; Data structures for configuration mailbox ; MBX_BUFFER: STRING MBX_BUFFER_SZ MBX_CHAN: .BLKW 1 ; Mailbox channel number MBX_NAME: .ASCID /BAUD_OPER_MBX/ ; Logical name for configuration ; mailbox MBX_IOSB: .BLKQ 1 ; IOSB for mailbox ; ; Delta times for various delays ; SCAN_DELTA: DELTA SECONDS=SCAN_SECS ; Interval between scans to update TST HANG_DELTA: DELTA SECONDS=HANGUP_SECS ; Interval to wait following hangups. .PAGE .SBTTL BAUD - Main program .PSECT CODE RD,NOWRT,EXE,SHR,LONG .ENTRY BAUD,0 ; ; Main program for BAUD autobaud terminal handler. ; Following initialization, the program waits in a HIBER state until ; awoken by a periodic $SCHDWK. It then updates the Terminal Status ; Table by searching for lines which have become released and returns ; to the HIBER state. ; All other activities take place at AST level. ; CALL INITIALIZE ; Initialize, including requesting ; the $SCHDWK REPEAT $SETAST_S ENBFLG=#0 ; Disable AST's to lock TST IF_ERROR - CODE=#BAUD_SETAST ; Stop if an error CALL UPDATE_TST ; Update the TST $SETAST_S ENBFLG=#1 ; Enable AST's IF_ERROR - CODE=#BAUD_SETAST ; Stop if an error $HIBER_S ; Hibernate for next cycle IF_ERROR - CODE=#BAUD_HIBER ; Stop if an error UNTIL ; Loop forever .PAGE .SBTTL INITIALIZE - Initialize BAUD program. ;++ ; Functional Description: ; Initial setup routine for BAUD. Initializes TST, creates and reads ; configuration mailbox, and schedules periodic wakeup. ; ; Calling Sequence: ; CALLS #0,INITIALIZE ; ; Input Parameters: NONE ; ; Output Parameters: NONE ; ; Implicit Inputs: NONE ; ; Implicit Outputs: ; TERM_STAT - Terminal status table initialized ; LOWEST_TERM_IDX - " ; HIGHEST_TERM_IDX - " ; NR_TERMS - " ; MBX_CHAN - Configuration mailbox channel ; HIGHEST_BAUD - Limits on legal baud rates ; LOWEST_BAUD - " ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY INITIALIZE,^M<> ; Initialize the Terminal Status Table MOVZWL #MAX_TERMS+1,- LOWEST_TERM_IDX ; No lowest terminal yet. CLRL HIGHEST_TERM_IDX ; Ditto highest terminal MOVZWL #DEF_HIGHEST_BAUD,- HIGHEST_BAUD ; Init highest current baud rate ; to default MOVZWL #DEF_LOWEST_BAUD,- LOWEST_BAUD ; Ditto lowest rate CALL TST_INI, NR_TERMS ; Zero out TST. Returns number ; of terminals acutally found. ; Get mailbox for receiving configuration messages. $CREMBX_S - CHAN=MBX_CHAN,- MAXMSG=#MBX_BUFFER_SZ,- PROMSK=#^XF000,- LOGNAM=MBX_NAME ; Create the mailbox IF_ERROR - CODE=#BAUD_CREMBX ; Stop if an error ; Request periodic wakeup. $SCHDWK_S - DAYTIM=SCAN_DELTA,- REPTIM=SCAN_DELTA ; Wake up every SCAN_DELTA. IF_ERROR - CODE=#BAUD_SCHDWK ; Stop if an error ; Read with AST on the mailbox. $QIO_S CHAN=MBX_CHAN,- FUNC=#IO$_READVBLK,- IOSB=MBX_IOSB,- ASTADR=MBX_MSG_AST,- P1=MBX_BUFFER,- P2=#MBX_BUFFER_SZ ; Read from mailbox IF_ERROR - CODE=#BAUD_QIO ; Stop if an error ; Log that initialization is complete LOG_MESSAGE - CODE=#BAUD_INIDONE ; Initialization done RET .PAGE .SBTTL UPDATE_TST - Update Terminal Status Table ;++ ; Functional Description: ; This routine is called at each SCAN_DELTA interval to search ; for terminals which have become available in the last cycle. ; If a terminal has become available, we allocate it, reset ; its speed, and to a read with timeout. If the user attempts ; to reuse the line before the timeout (RELEASE_SECS) it ; appears to be a normal autobaud detect. However, if the ; user doesn't try to reuse the line, we will eventually time ; out and hangup on him. ; ; Calling Sequence: ; CALLS #0,UPDATE_TST ; ; Input Parameters: NONE ; ; Output Parameters: NONE ; ; Implicit Inputs: ; LOWEST_TERM_IDX - Limits of TST entries to scan ; HIGHEST_TERM_IDX - " ; TERM_STAT - Terminal status table ; ; Implicit Outputs: ; TERM_STAT - Terminal status table is updated ; ; Completion Status: NONE ; ; Side Effects: ; Terminals may be allocated and reads performed. ; ;-- .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Local storage DEV_DESC: .LONG 6 ; Skeleton descriptor for term name .LONG 0 GETCHN_DESC: .LONG <3*4> ; Skeleton descriptor for any $GETCHN .LONG 0 ; buffer .PSECT CODE NOWRT,EXE,SHR,LONG .ENTRY UPDATE_TST,^M ; Register usage ; R0-R1 Scratch ; R2 - Pointer to current TST entry ; R3 - Address of highest TST entry to scan. ; Setup scan loop start and limit MOVAL TERM_STAT,R0 ; Get table base address MULL3 #TST_C_ENTSZ,- LOWEST_TERM_IDX,R2 ; Offset to lowest entry ADDL R0,R2 ; Compute address of lowest entry MULL3 #TST_C_ENTSZ,- HIGHEST_TERM_IDX,R3 ; Offset to highest entry ADDL R0,R3 ; Compute address of highest entry ; Loop scanning table ENB_LONG ;; Enable long branches for SMAC WHILE DO IF AND - THEN ; Terminal is available for autobauding and we do not currently own it MOVAL TST_T_NAME(R2),- DEV_DESC+4 ; Build desc for device name $ALLOC_S - DEVNAM=DEV_DESC ; Try to get the terminal IF - THEN ; If not in use by someone else IF_ERROR - CODE=#BAUD_ALLOC ; and not some other error ; Terminal is not owned. It must have been released during this cycle ; by someone logging out. BISW #TST_M_OWNED,- TST_W_STS(R2) ; Mark terminal as owned by us ; Get a channel $ASSIGN_S - DEVNAM=DEV_DESC,- CHAN=TST_W_CHAN(R2) ; Get a channel on the terminal IF_ERROR - CODE=#BAUD_ASSIGN ; Stop if error LOG_MESSAGE - CODE=#BAUD_ASGCHN,- F1=#DEV_DESC ; Issue log message. We have channel. ; Get the device characteristics which are needed for later $QIO SETCHAR's ASSUME - TST_R_CHRBUF+4 EQ TST_Q_DEVCHR ; Make sure buffer parts ; are still declared contiguous MOVAL TST_R_CHRBUF(R2),- GETCHN_DESC+4 ; Plug buffer address into desc $GETCHN_S - CHAN=TST_W_CHAN(R2),- PRIBUF=GETCHN_DESC ; Get the characteristics IF_ERROR - CODE=#BAUD_GETCHN ; Stop if error ; Set the speed CALL SET_SPEED,- R2,- #DEFAULT_SPEED ; Set speed to default MOVB #DEFAULT_SPEED,- TST_B_SPEED(R2) ; Set speed field in TST ; Read with timeout on terminal. $QIO_S - CHAN=TST_W_CHAN(R2),- FUNC=#READ_FUNC!IO$M_TIMED,- IOSB=TST_Q_IOSB(R2),- ASTADR=RELEASE_AST,- ASTPRM=R2,- P1=TST_T_BUFFER(R2),- P2=#1,- P3=#RELEASE_SECS IF_ERROR - CODE=#BAUD_QIO ; Stop if error LOG_MESSAGE - CODE=#BAUD_RELREAD,- F1=#DEV_DESC ; Log message. We started a read. MOVB #TST_C_ST_RELEASE,- TST_B_STATE(R2) ; Set state to released ENDIF ENDIF ADDL #TST_C_ENTSZ,R2 ; Point to next TST entry ENDWHILE DSB_LONG ;; Disable long branches for SMAC RET .PAGE .SBTTL MBX_MSG_AST Configuration message AST routine ;++ ; Functional Description: ; This routine is called at AST level to receive a message sent ; to the configuration mailbox. The mailbox message is examined ; for data. If data is found, a routine is called to process it. ; A read is then performed on the mailbox. ; ; Calling Sequence: ; Called by VMS with CALLG and AST parameter block. ; ; Input Parameters: NONE relevant ; ; Output Parameters: NONE ; ; Implicit Inputs: ; MBX_IOSB - Mailbox I/O status ; MBX_BUFFER - Data from mailbox read ; MBX_CHAN - Mailbox channel number ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: ; Issues a read on the mailbox ; ;-- .ENTRY MBX_MSG_AST,^M<> MOVZWL MBX_IOSB,R0 ; Get IO status IF THEN ; Map end-of-file status MOVZWL #SS$_NORMAL,R0 ; To normal completion ENDIF IF_ERROR - CODE=#BAUD_MBXIO ; Stop if I/O error ; Log the message we received MOVZWL MBX_IOSB+2,R1 ; Get message length LOG_MESSAGE - CODE=#BAUD_CONFMSG,- F1=R1,- F2=#MBX_BUFFER ; Issue log message IF THEN ; If some data received CALL PROC_MBX_COMMAND ; Process the command ENDIF ; Issue a new read with AST for next configuration message $QIO_S CHAN=MBX_CHAN,- FUNC=#IO$_READVBLK,- IOSB=MBX_IOSB,- ASTADR=MBX_MSG_AST,- P1=MBX_BUFFER,- P2=#MBX_BUFFER_SZ ; Read from mailbox IF_ERROR - CODE=#BAUD_QIO ; Stop if an error RET .PAGE .SBTTL PROC_MBX_COMMAND - Process configuration command ;++ ; Functional Description: ; Routine to process commands received in the configuration mailbox. ; Legal commands are: ; STOP Terminate BAUD ; AUTO TTcu: Initiate auto baud on TTcu: ; FREE TTcu: Terminate auto baud on TTcu: ; ADDR n Add new allowable rate ; DELR n Delete allowable rate ; ; Command names must begin in first character in the record and contain ; exactly 4 characters. If there is a command parameter, it must be ; separated from the command by exactly one blank. ; ; Calling Sequence: ; CALLS #0,PROC_MBX_COMMAND ; ; Input Parameters: NONE ; ; Output Parameters: NONE ; ; Implicit Inputs: ; MBX_BUFFER - Mailbox buffer containing the command ; MBX_IOSB - Mailbox I/O status containing the command length ; ; Implicit Outputs: ; LOWEST_BAUD - Lowest legal baud rate ; HIGHEST_BAUD - Highest legal baud rate ; OUR_RATES - Bit mask of legal baud rates ; ; Completion Status: NONE ; ; Side Effects: ; Command processing may modify TST, cause reads on the terminal, ; or cause a $EXIT_S to be executed. ; ;-- .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Local data RATE_NUM: COUNT 0 ; Temporary storage .PSECT CODE NOWRT,EXE,SHR,LONG .ENTRY PROC_MBX_COMMAND,^M ; ; Register usage: ; R0-R2 - Scratch ; Check for "STOP" command IF THEN $EXIT_S CODE=#SS$_NORMAL ; Stop if we are told ENDIF ENB_LONG ;;Enable long branches for SMAC ; Check for a command with terminal name IF - OR THEN LOCC #^A/ /,MBX_IOSB+2,- MBX_BUFFER ; Look for blank separating name ; from terminal. Leaves R1 pointing ; to the blank. Leave length of ; remainder in R0. IF THEN ; If no blank found... LOG_MESSAGE - CODE=#BAUD_SYNERR ; Log syntax error ELSE INCL R1 ; Skip the blank DECL R0 BSBW NAME_TO_INDEX ; Convert terminal name to TST index IF OR THEN ; Negative index means bad terminal name format ; Index greater than number of terminals means non-existent terminal. LOG_MESSAGE - CODE=#BAUD_SYNERR ; Issue error message ELSE IF THEN ; Process AUTO command by putting autobaud status into TST entry CALL INS_TST_ENTRY, R2 ELSE ; Process FREE command by removing autobaud status from TST entry CALL DEL_TST_ENTRY, R2 ENDIF ENDIF ENDIF RET ENDIF IF OR - THEN ; Process commands for setting or clearing legal baud rates LOCC #^A/ /,MBX_IOSB+2,- MBX_BUFFER ; Locate separating blank ; Leaves R1 pointing to blank,- ; R0 with remaining string length IF THEN ; If no blank found... LOG_MESSAGE - CODE=#BAUD_SYNERR ; Log a syntax error ELSE INCL R1 ; Skip the blank DECL R0 CALL LIB$CVT_DTB,- R0, R1, RATE_NUM ; Convert string to binary ; Convert baud rate value to internal code CLRL R0 ; Clear loop count WHILE DO BREAK IF ; Branch out if first part ; of table entry matches the specified ; rate. ADDL #2,R0 ; Index to next entry ENDWHILE IF THEN ; Rate not found - syntax error LOG_MESSAGE - CODE=#BAUD_SYNERR ; Issue error message ELSE MOVZWL RATE_CODES+2[R0],- RATE_NUM ; Get code for the baud rate IF THEN ; Add new legal rate BBCS RATE_NUM,- OUR_RATES,10$ ; Set new bit 10$: ELSE ; Delete old rate BBSC RATE_NUM,- OUR_RATES,20$ ; Clear old bit 20$: ENDIF ; Update baud rate limits FFS #0,#TT$C_BAUD_9600,- OUR_RATES,LOWEST_BAUD ; Update low limit to lowest bit set ASHL #<32-TT$C_BAUD_9600>,- OUR_RATES,R0 ; Get bit table with highest possible ; bit in sign bit MOVL #TT$C_BAUD_9600,R1 ; Set counter to highest possible ; rate 30$: ASHL #1,R0,R0 ; Shift off next bit BVS 40$ ; Branch out if set bit shifted out DECL R1 ; Decrement highest possible rate BGTR 30$ ; Loop until set bit found or all bits ; checked 40$: MOVL R1,- HIGHEST_BAUD ; Update rate scan limit ENDIF ENDIF RET ENDIF DSB_LONG ;;Disable long branches for SMAC ; If no one has claimed this command, it must be unknown LOG_MESSAGE - CODE=#BAUD_UNKCMD ; Log unknown command RET .PAGE .SBTTL NAME_TO_INDEX Convert terminal name to TST index ;++ ; Functional Description: ; Subroutine used to convert the terminal name in the form ; TTcu: into a TST index. Validates beginning of argument ; name to make sure it looks something like a term name. ; ; Calling Sequence: ; BSBW NAME_TO_INDEX ; ; Input Parameters: ; R0 - Length of terminal name string ; R1 - Address of terminal name string ; ; Output Parameters: ; R2 - Set to TST index corresponding to terminal name ; ; Implicit Inputs: NONE ; ; Implicit Outputs: NONE ; ; Completion Status: ; R2 is set to -1 if the terminal name is invalid. ; ; Side Effects: NONE ; ;-- ; Register usage: ; R0 - Input parameter. Modified. ; R1 - Input parameter. Modified. ; R2 - Output parameter. Modified. NAME_TO_INDEX:: IF THEN ; If first char is a "_" INCL R1 ; Skip it DECL R0 ENDIF IF OR - THEN MNEGL #1,R2 ; Must be bad name ELSE ADDL #2,R1 ; Point to controller designator CLRL R0 ; Clear scratch register SUBB3 #^A/A/,(R1),R0 ; Get controller index MULL #UNITS_PER_CTRL,R0 ; Times units per controller INCL R1 ; Point to unit designator CLRL R2 ; Clear scratch register SUBB3 #^A/0/,(R1),R2 ; Get unit index IF OR - THEN MNEGL #1,R2 ; Bad digit in unit spot ELSE ADDL R0,R2 ; Add controller index to unit ; index and return value ENDIF ENDIF RSB .PAGE .SBTTL TST_INI - Initialize Terminal Status Table ;++ ; Functional Description: ; Routine to initialize the Terminal Status Table and determine ; the number of terminals actually on the system. Zeros each ; table entry and moves in the terminal name. ; ; Calling Sequence: ; PUSHAL number-of-terms-found ; CALLS #01,TST_INI ; ; Input Parameters: NONE ; ; Output Parameters: ; 4(AP) - Number of terminals found on system. ; ; Implicit Inputs: NONE ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: ; Terminal Status Table is initialized. ; ;-- .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Local data TERM_NAME_FORM: .ASCII /_TTcu:/ ; Form of a terminal name TERM_NAME_DESC: .LONG 6 ; Skeleton desc for terminal name .LONG 0 ; Register usage .PSECT CODE EXE,NOWRT,SHR,LONG .ENTRY TST_INI,^M ; R0 - R5 - Scratch ; R6 - Address of TST entry being initialized ; R7 - Terminal unit counter ; R8 - Terminal controller counter ; R9 - Index of TST entry being initialized CLRL R9 ; Start with zeroth entry CLRL R7 ; and unit 0 CLRL R8 ; on controller A MOVAL TERM_STAT,R6 ; Base address of TST ; Init the next TST entry INI_LOOP: MOVC5 #0,.,#0,- #TST_C_ENTSZ,(R6) ; Clear this TST entry MOVC3 #6,TERM_NAME_FORM,- TST_T_NAME(R6) ; Stuff in device name skeleton ADDB3 #^A/A/,R8,- TST_T_NAME+3(R6) ; Add controller name ADDB3 #^A/0/,R7,- TST_T_NAME+4(R6) ; and unit number ; Find out if this device exists MOVAL TST_T_NAME(R6),- TERM_NAME_DESC+4 ; Fill in skeleton descriptor $GETDEV_S - DEVNAM=TERM_NAME_DESC ; Try to get info on the device CMPL R0,#SS$_NOSUCHDEV ; Does device exist? BEQL LAST_FOUND ; Branch if not IF_ERROR - CODE=#BAUD_GETDEV ; Stop if other error ADDL #TST_C_ENTSZ,R6 ; Point to next TST entry INCL R7 ; Increment unit counter IF THEN INCL R8 ; Bump to next controller CLRL R7 ; Recycle to unit zero ENDIF AOBLSS #MAX_TERMS,R9,INI_LOOP ; Loop through all allowed terminals ; Last terminal in configuration located LAST_FOUND: MOVL R9,@4(AP) ; Return nr of terms found RET .PAGE .SBTTL INS_TST_ENTRY - Enable Autobaud for New Terminal ;++ ; Functional Description: ; Routine called to make a new terminal available for autobaud. ; If the terminal is not already owned by us (and therefor already ; setup), the TST entry is modified to make it appear that the ; terminal has just been released by a user process. The next ; UPDATE_TST cycle will then pick up the terminal (now marked as ; available for autobauding) and will cycle it from "busy" to ; to "released" to "idle". ; ; Calling Sequence: ; PUSHL #TST-index ; CALLS #1,INS_TST_ENTRY ; ; Input Parameters: ; 4(AP) - Index of TST entry for terminal to add ; ; Output Parameters: NONE ; ; Implicit Inputs: NONE ; ; Implicit Outputs: ; TERM_STAT - Terminal Status Table entry modified ; LOWEST_TERM_IDX - Lowest autobaud terminal. Updated. ; HIGHEST_TERM_IDX - Highest autobaud terminal. Updated. ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY INS_TST_ENTRY,^M ; Register usage: ; R0-R1 - Scratch ; R2 - Pointer to TST entry MULL3 #TST_C_ENTSZ,4(AP),R2 ; Get TST offset to entry to insert MOVAL TERM_STAT,R0 ; Get TST base address ADDL R0,R2 ; Compute entry address IF THEN ; If not already enabled for autobaud and IF THEN ; If we don't already own the terminal, grab it and start autobauding MOVB #TST_C_ST_BUSY,- TST_B_STATE(R2) ; Set state to BUSY BISW #TST_M_AUTO,- TST_W_STS(R2) ; Set autobaud enable bit IF THEN MOVL 4(AP),- LOWEST_TERM_IDX ; Reduce lower scan limit if needed ENDIF IF THEN MOVL 4(AP),- HIGHEST_TERM_IDX ; Raise higher scan limit if needed ENDIF MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_ADDED,- F1=#6,- F2=R1 ; Issue log message. New one added. ENDIF ELSE ; Note that autobaud was already enabled MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_AUTONOW,- F1=#6,- F2=R1 ; Issue log message - we already ; have this one. ENDIF RET .PAGE .SBTTL DEL_TST_ENTRY - Remove Terminal from Autobaud ;++ ; Functional Description: ; Routine used to remove a terminal for consideration for autobauding. ; If we don't own the terminal, its easy: just clear the bit. If we ; own it, we must also cancel any outstanding I/O, deassign the channel ; and deallocate the device. All AST routines must be prepared to ; field the $CANCEL on their I/O request. Note that since removing ; a terminal is probably in infrequent event, we don't bother to update ; the lowest and highest terminal index pointers. Scanning a few extra ; TST entries is not that slow. ; ; Calling Sequence: ; PUSHL #TST_index ; CALLS #1,DEL_TST_ENTRY ; ; Input Parameters: ; 4(AP) - TST index of terminal to process ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal to be removed. ; ; Implicit Outputs: ; TERM_STAT - TST entry is modified to un-autobaud this terminal ; ; Completion Status: NON ; ; Side Effects: ; $CANCEL can cause AST routines to be called. ; ;-- .ENTRY DEL_TST_ENTRY,^M ; Register usage: ; R0-R1 - Scratch ; R2 - Address of TST entry being manipulated MULL3 #TST_C_ENTSZ,4(AP),R2 ; Get TST offset to entry to delete MOVAL TERM_STAT,R0 ; Get TST base address ADDL R0,R2 ; Compute address of entry ENB_LONG ;;Enable long branches for SMAC IF THEN ; We own the terminal. Need to clean up outstanding reads and let it go. BICW #TST_M_OWNED,- TST_W_STS(R2) ; Clear "owned" bit so AST routines ; know to ignore any I/O completions. $CANCEL_S CHAN=TST_W_CHAN(R2) ; Cancel pending I/O ; Don't check for errors $DASSGN_S CHAN=TST_W_CHAN(R2) ; Deassign the channel IF_ERROR - CODE=#BAUD_DASSGN ; Stop if an error CLRW TST_W_CHAN(R2) ; Clear channel field in TST entry PUSHAL TST_T_NAME(R2) ; Build desc for term name. Address PUSHL #6 ; Length of name MOVL SP,R0 ; Get desc address $DALLOC_S DEVNAM=(R0) ; Deallocate the terminal ADDL #<2*4>,SP ; Remove desc from stack IF_ERROR - CODE=#BAUD_DALLOC ; Stop if error ENDIF DSB_LONG ;;Disable long branches for SMAC BICW #TST_M_AUTO,- TST_W_STS(R2) ; Clear autobaud enable bit MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_REMOVE,- F1=#6,- F2=R1 ; Issue log message RET .PAGE .SBTTL HANG_UP - Hang up a terminal line ;++ ; Functional Description: ; Routine to hang up a terminal line. Can only be called once a ; channel has been assigned on the terminal. ; ; Calling Sequence: ; This routine should be AST re-entrant since it may be called from ; at AST level. ; ; PUSHL TST_entry_address ; CALLS #1,HANG_UP ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal to hangup ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry of terminal to hangup. ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY HANG_UP,^M ; Register usage: ; R0 - R1 - Scratch ; R2 - Address of TST entry of terminal to hangup ; Hangup specified terminal MOVL 4(AP),R2 ; Get pointer to TST entry $QIOW_S - CHAN=TST_W_CHAN(R2),- FUNC=#IO$_SETCHAR!IO$M_HANGUP,- IOSB=TST_Q_IOSB(R2),- P1=TST_Q_DEVCHR(R2) ; Hang it up! IF_ERROR - CODE=#BAUD_QIO ; Stop if error MOVZWL TST_Q_IOSB(R2),R0 ; Get I/O status IF_ERROR - CODE=#BAUD_HANGERR ; Stop if I/O error ; Issue a log message MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_HANG,- F1=#6,- F2=R1 ; We hung it up RET .PAGE .SBTTL SET_SPEED - Set Terminal Speed ;++ ; Functional Description: ; Routine used to set the DZ-11 speed on a terminal line. ; Cannot be used until a channel has been assigned on the device. ; ; Calling Sequence: ; This routine should be AST reentrant since it may be called from ; AST level routines. ; ; PUSHL #speed_code ; PUSHL TST_entry_address ; CALLS #2,SET_SPEED ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal to set speed on. ; 8(AP) - Code for baud rate to be set ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal to be modified ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY SET_SPEED,^M ; Register usage ; R0-R1 - Scratch ; R2 - Address of TST entry MOVL 4(AP),R2 ; Get pointer to TST entry ; Set the characteristics including speed. $QIOW_S - CHAN=TST_W_CHAN(R2),- FUNC=#IO$_SETCHAR,- IOSB=TST_Q_IOSB(R2),- P1=TST_Q_DEVCHR(R2),- P3=8(AP) ; Set speed characteristic IF_ERROR - CODE=#BAUD_QIO ; Stop if error on QIO MOVZWL TST_Q_IOSB(R2),R0 ; Get I/O status IF_ERROR - CODE=#BAUD_SPEEDERR ; Stop if I/O error ; Issue log message MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_SPEED,- F1=#6,- F2=R1,- F3=8(AP) ; Say what terminal and speed RET .PAGE .SBTTL READ_AST - Terminal Read AST Routine ;++ ; Functional Description: ; This AST routine is the one called when a read completes on an ; autobaud terminal in the IDLE state. When we are called, a ; terminal received a character to initiate the autobaud sequence. ; This routine could also be called when the actual device times out, ; or when a $CANCEL is done on the line, such as when a FREE command ; is done. ; ; Calling Sequence: ; Called at AST level by VMS. ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal completing. (AST parameter) ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal whose read completed. ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY READ_AST,^M ; Register usage ; R0-R1 - Scratch ; R2 - Address of TST entry MOVL 4(AP),R2 ; Get pointer to TST entry ; Log the read completion MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_NRMCOM,- F1=#6,- F2=R1,- F3=TST_Q_IOSB(R2),- F4=TST_Q_IOSB+4(R2),- F5=TST_T_BUFFER(R2),- F6=TST_B_SPEED(R2) ; Log all the details ENB_LONG ;; Enable long branches for SMAC IF - OR - OR - OR THEN IF THEN ; If we get one of these statuses and the "owned" bit is clear, we are ; in the process of freeing the terminal from autobaud so we do nothing. ; If the bit is set, there must have been a real device timeout or carrier ; drop. In this case, everything is still setup correctly, so we just issue ; a new read. $QIO_S - CHAN=TST_W_CHAN(R2),- FUNC=#READ_FUNC,- IOSB=TST_Q_IOSB(R2),- ASTADR=READ_AST,- ASTPRM=R2,- P1=TST_T_BUFFER(R2),- P2=#1 ; Read again IF_ERROR - CODE=#BAUD_QIO ; Stop if an error MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_NRMREAD,- F1=#6,- F2=R1 ; Log the read ENDIF ELSE ; Must be a read completion with real data. Process it. CALL DATA_RECEIVED, R2 ; Process read completion ENDIF DSB_LONG ;;Disble long branches for SMAC RET .PAGE .SBTTL RELEASE_AST - Terminal AST Read Routine ;++ ; Functional Description: ; Routine called when the RELEASED state read (with timeout) completes. ; The RELEASED state is entered when a terminal is first enabled for ; autobaud, or when a user logs off the terminal, and it becomes free. ; There are three possible reasons for this AST routine to be entered: ; One, the user could have typed another carriage return before the ; line was hung up. This is treated as a normal read completion. ; We also could get here as a result of the timeout of the RELEASE ; state read. This occurs when the logged off user does not type ; anything following his logout. At this point, we hangup the line ; (to drop DTR), and enter the HANGUP_PENDING state. From HANGUP_ ; PENDING we will eventually return the line state to IDLE. The ; third possibility is that the terminal is being removed from ; autobauding and a $CANCEL was issued. In that case, we do nothing. ; ; Calling Sequence: ; Called at AST level by VMS. ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal whose read completed.(AST ; parameter) ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal being processed ; ; Implicit Outputs: ; TERM_STAT - TST entry may be updated ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY RELEASE_AST,^M ; Register usage: ; R0-R1 - Scratch. ; R2 - Address of TST entry for terminal whose read completed. MOVL 4(AP),R2 ; Get pointer to TST entry ENB_LONG ;;Enable long branches for SMAC ; Log the read completion MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_RELCOM,- F1=#6,- F2=R1,- F3=TST_Q_IOSB(R2),- F4=TST_Q_IOSB+4(R2),- F5=TST_T_BUFFER(R2),- F6=TST_B_SPEED(R2) ; Log the read with all details IF - OR - OR - OR THEN IF THEN ; If the "owned" bit is clear, we do nothing, since this can only happen ; during the removal of a terminal from autobauding. ; If the bit is set, we must process the termination. Either the user hung ; up, or the RELEASE state read timed out, or the physical device timed ; out. In any case, we hangup and wait for the hangup to complete. CALL HANG_UP, R2 ; Hangup the line MOVB #TST_C_ST_HNGUP,- TST_B_STATE(R2) ; Set state to HANGUP_PENDING $SETIMR_S - DAYTIM=HANG_DELTA,- ASTADR=HANG_AST,- REQIDT=R2 ; Issue timer request for enough ; time for hangup to complete. IF_ERROR - CODE=#BAUD_SETIMR ; Stop if error ENDIF ELSE ; The read completed with some data, so process it. CALL DATA_RECEIVED, R2 ENDIF DSB_LONG ;;Disable long branches for SMAC RET .PAGE .SBTTL ADJ_SPEED_AST - Terminal Read AST Routine ;++ ; Functional Description: ; Routine called when a read issued from the ADJUST_SPEED state ; completes. The ADJUST_SPEED state is entered after a character ; has been read, but before it is possible to determine the speed ; of the terminal. There are three reasons why this AST routine ; could be called. We could get called as a result of a normal ; read completing with the users next carriage return. We could ; also get called as a result of the ADJUST_SPEED read timing out. ; Either the user gave up (after we had modified the line speed ; at least once for him), or the user modified his terminal speed while ; we were trying to figure it out. If he raises his speed while ; we are adjusting the DZ-11 speed downward, we could start missing ; his input (the start bits are too short for the DZ-11 at a slow ; speed setting). In either case, we hangup the line and go into ; the HANGUP_PENDING state to wait for the hangup to complete. ; Eventually, that state returns to the IDLE state. ; The third possibility is that a $CANCEL was done while removing the ; terminal from autobauding. ; ; Calling Sequence: ; Called at AST level by VMS. ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal whose read completed (AST ; parameter) ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal ; ; Implicit Outputs: ; TERM_STAT - TST entry may be updated ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY ADJ_SPEED_AST,^M ; Register usage: ; R0-R1 - Scratch ; R2 - Address of TST entry for terminal being processed MOVL 4(AP),R2 ; Get pointer to TST entry ; Log the read completion MOVAL TST_T_NAME(R2),R1 ; Get pointer to terminal name LOG_MESSAGE - CODE=#BAUD_ADJCOM,- F1=#6,- F2=R1,- F3=TST_Q_IOSB(R2),- F4=TST_Q_IOSB+4(R2),- F5=TST_T_BUFFER(R2),- F6=TST_B_SPEED(R2) ; Log all the details ENB_LONG ;;Enable long branches for SMAC IF - OR - OR - OR THEN IF THEN ; If the owned bit is clear, we were called during the release of a ; terminal from autobauding. In that case, we do nothing. If the bit ; is set, either the read timed out while we were adjusting, or the ; physical device timed out or lost carrier. In either case, reset ; speed, hangup, and await hangup completion. CALL SET_SPEED,- R2,#DEFAULT_SPEED ; Set terminal speed to defaule MOVB #DEFAULT_SPEED,- TST_B_SPEED(R2) ; and update speed field of TST CALL HANG_UP, R2 ; Hangup the line MOVB #TST_C_ST_HNGUP,- TST_B_STATE(R2) ; Set state to HANGUP_PENDING $SETIMR_S - DAYTIM=HANG_DELTA,- ASTADR=HANG_AST,- REQIDT=R2 ; Issue timer request to wait for ; hangup to complete. IF_ERROR - CODE=#BAUD_SETIMR ; Stop if error ENDIF ELSE ; Another read completed with real data. Process it CALL DATA_RECEIVED, R2 ENDIF DSB_LONG ;;Disable long branches for SMAC RET .PAGE .SBTTL HANG_AST - Hangup Timer AST Routine ;++ ; Functional Description: ; This routine is called in response to a timer request used to ; wait for a line hangup to complete. The hangup function takes ; some interval to complete after the HANGUP I/O function completes. ; Since the line is safely hung up, we can now issue a normal, non- ; timed read and set the state to IDLE ; ; Calling Sequence: ; Called at AST level by VMS. ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal whose read completed (AST ; parameter) ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal ; ; Implicit Outputs: ; TERM_STAT - TST entry is updated ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .ENTRY HANG_AST,^M ; Register usage: ; R0-R1 - Scratch ; R2 - Address of TST entry for line being hung up MOVL 4(AP),R2 ; Get pointe to TST entry $QIO_S - CHAN=TST_W_CHAN(R2),- FUNC=#READ_FUNC,- IOSB=TST_Q_IOSB(R2),- ASTADR=READ_AST,- ASTPRM=R2,- P1=TST_T_BUFFER(R2),- P2=#1 ; Issue a normal read IF_ERROR - CODE=#BAUD_QIO ; Stop if error MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_NRMREAD,- F1=#6,- F2=R1 ; Log the read MOVB #TST_C_ST_IDLE,- TST_B_STATE(R2) ; Set state to IDLE RET .PAGE .SBTTL DATA_RECEIVED - Terminal Read Completed with DATA ;++ ; Functional Description: ; This routine is called by all of the terminal AST routines when ; a read completes with data. This routine attempts to determine ; the baud rate of the incoming signal based on the rate at which ; the read took place, and the garbage which was received. If the ; rate can be determined, the line is set to the correct speed, the ; line is freed, and a message is sent to the job controller to ; initiate a login. If the incoming rate cannot be determined, ; the DZ-11 speed is adjusted and another read is posted. This ; is the ADJUST_SPEED state, and the read is with timeout. That ; is so if the user goes away, or we manage to totally misadjust ; the DZ-11 speed, we will be able to recover. ; ; Calling Sequence: ; Called at AST level. ; PUSHL TST_entry_address ; CALLS #1,DATA_RECEIVED ; ; Input Parameters: ; 4(AP) - Address of TST entry for terminal that completed ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for terminal. ; ; Implicit Outputs: ; TERM_STAT - TST entry may be updated ; ; Completion Status: NONE ; ; Side Effects: ; Terminal may be freed from our control and a login started. ; ;-- .PSECT RODATA RD,NOWRT,NOEXE,SHR,LONG ; This table is used for mapping the received garbage character to a ; possible baud rate. Each row corresponds to a rate at which a ; read took place. Each column corresponds to the garbage that would ; be received if the line were at one of the 15 possible baud rates. GARP_TABLE: .BYTE 13,98,124,126,127,127,0,0,0,0,0,0,0,0,0 ; 50 baud .BYTE 114,13,98,114,114,127,127,0,0,0,0,0,0,0,0 ; 75 baud .BYTE 70,59,13,71,71,126,127,0,0,0,0,0,0,0,0 ; 110 baud .BYTE 12,118,25,13,13,126,127,127,0,0,0,0,0,0,0 ; 134 baud .BYTE 28,102,59,29,13,114,127,127,0,0,0,0,0,0,0 ; 150 baud .BYTE 96,120,28,78,102,13,114,127,0,0,0,0,0,0,0 ; 300 baud .BYTE 0,0,112,120,120,102,13,126,127,127,127,127 .BYTE 127,0,0 ; 600 baud .BYTE 0,0,0,0,0,120,102,13,98,114,126,127,127,0,127 ; 1200 baud .BYTE 0,0,0,0,0,96,28,114,13,5,70,114,127,0,127 ; 1800 baud .BYTE 0,0,0,0,0,64,60,114,29,13,5,114,126,0,127 ; 2000 baud .BYTE 0,0,0,0,0,0,120,102,59,25,13,98,114,0,127 ; 2400 baud .BYTE 0,0,0,0,0,0,96,28,102,118,59,13,71,0,127 ; 3600 baud .BYTE 0,0,0,0,0,0,0,120,12,78,102,59,13,0,114 ; 4800 baud .BYTE 0,0,0,0,0,0,0,96,120,56,28,102,123,13,71 ; 7200 baud .BYTE 0,0,0,0,0,0,0,0,112,112,120,12,102,0,13 ; 9600 baud .PSECT CODE EXE,NOWRT,SHR,LONG .ENTRY DATA_RECEIVED,^M ; Register usage: ; R0 - R1 - Scratch ; R2 - Pointer to TST entry ; R3 - The character read from the terminal ; R4 - If non-zero, the baud rate of the incoming signal ; R5 - Base address of the row of GARP_TABLE for the baud ; rate we read at. MOVL 4(AP),R2 ; Get pointer to TST entry LOG_MESSAGE - CODE=#BAUD_DATARX ; Log that we are processing ; received data ; Analyze the character we received CLRL R3 ; Clear out garbage BICB3 #^X80,TST_T_BUFFER(R2),- R3 ; Get significant part of char CLRL R4 ; Clear "character found" baud rate MOVZBL TST_B_SPEED(R2),R0 ; Get code for current speed ENB_LONG ;;Enable long branches for SMAC IF - AND THEN ; If we got a CR and it was at a legal ; baud rate MOVZBL - TST_B_SPEED(R2),R4 ; Set the baud rate to use ELSE ; Look for what we got in the translation table, and maybe we can tell ; what the incoming rate is. MOVZBL TST_B_SPEED(R2),R5 ; Get the speed we read at DECL R5 ; Less one MULL #NR_DZ_BAUDS,R5 ; Times nr of baud rates per row ; gives index to first value for ; our speed. MOVAL GARP_TABLE-1,R0 ; Translation table base addr less 1 ADDL R0,R5 ; Gives base address for our row -1 MOVL #1,R1 ; Init loop count (corresponds to ; speed code) WHILE THEN BREAK IF AND - ; Break if match found and it's at a ; legal speed. INCL R1 ; Increment loop counter ENDWHILE IF THEN ; We found a match in the table. Now look to see if it is unique. MOVL R1,R0 ; Save the location of the match INCL R1 ; and start one beyond there WHILE THEN ; Loop through remainder of table BREAK IF AND - ; Break if another match found at a ; legal speed INCL R1 ; Increment loop counter ENDWHILE IF THEN ; If we reached limit, no match MOVL R0,R4 ; The unique match was as found ; above. Use that as the line speed. ENDIF ENDIF ENDIF IF THEN ; If R4 contains a baud rate, we know what rate to use for the line IF THEN ; If not already at this baud rate, set it CALL SET_SPEED,R2,R4 ; Set to right speed MOVB R4,TST_B_SPEED(R2) ; and update TST ENDIF ; Give the terminal to the user $DASSGN_S - CHAN=TST_W_CHAN(R2) ; Deassign and deallocate terminal IF_ERROR - CODE=#BAUD_DASSGN ; Stop if an error PUSHAL TST_T_NAME(R2) ; Build desc for term name. Address PUSHL #6 ; and length MOVL SP,R1 ; Get descriptor address $DALLOC_S - DEVNAM=(R1) ; Deallocate the term IF_ERROR - CODE=#BAUD_DALLOC ; Stop if error BICW #TST_M_OWNED,- TST_W_STS(R2) ; Clear the "owned" bit CALL SND_JBC_MSG, R2 ; Yell at JOB_CONTROL MOVAL TST_T_NAME(R2),- R1 ; Get address of terminal name MOVZBL TST_B_SPEED(R2),- R3 ; Get speed as longword LOG_MESSAGE - CODE=#BAUD_TOUSER,- F1=#6,- F2=R1,- F3=R3 ; Log that we let the user have the ; line ELSE ; Can't make speed determination yet. Adjust DZ-11 speed and try another ; read. This moves into the ADJUST_SPEED state CLRL R1 ; R1 will hold new baud rate IF THEN ; If DZ too slow IF THEN ADDB3 LOWEST_BAUD,- #2,R1 ; If already at top limit, start down ELSE ADDB3 TST_B_SPEED(R2),#2,- R1 ; Else raise rate some more ENDIF ENDIF IF THEN ; If DZ too fast IF THEN SUBB3 #2,- HIGHEST_BAUD,R1 ; If at lower limit, try higher speed. ELSE SUBB3 #3,TST_B_SPEED(R2),- R1 ; Else lower baud rate some ENDIF ENDIF IF THEN ; If neither of these cases ADDB3 #1,- TST_B_SPEED(R2),R1 ; Try raising a little ENDIF ; Insure our selection is in range IF THEN MOVL HIGHEST_BAUD,R1 ; Limit upper to HIGHEST_BAUD ENDIF IF THEN MOVL LOWEST_BAUD,R1 ; Limit lower to LOWEST_BAUD ENDIF MOVB R1,TST_B_SPEED(R2) ; And update TST CALL SET_SPEED, R2, R1 ; Set the speed to our choice $QIO_S - CHAN=TST_W_CHAN(R2),- FUNC=#READ_FUNC!IO$M_TIMED,- IOSB=TST_Q_IOSB(R2),- ASTADR=ADJ_SPEED_AST,- ASTPRM=R2,- P1=TST_T_BUFFER(R2),- P2=#1,- P3=#ADJ_SPEED_SECS ; Issue timed read IF_ERROR - CODE=#BAUD_QIO ; Stop if error MOVAL TST_T_NAME(R2),R1 ; Get address of terminal name LOG_MESSAGE - CODE=#BAUD_ADJREAD,- F1=#6,- F2=R1 ; Log the read MOVB #TST_C_ST_ADJ,- TST_B_STATE(R2) ; Set state to adjust speed ENDIF DSB_LONG ;;Disable long branches for SMAC RET .PAGE .SBTTL SND_JBC_MSG - Send message to JOB_CONTROL ;++ ; Functional Description: ; Routine to send a message to the Job Controller process to simulate ; a terminal unsolicited interrupt. This is done following ; a baud rate determination so that the user's login will be initiated ; on the terminal. ; ; Calling Sequence: ; PUSHL TST_entry_address ; CALLS #1,SND_JBC_MSG ; ; Input Parameters: ; 4(AP) - Address of TST entry for the terminal ; ; Output Parameters: NONE ; ; Implicit Inputs: ; TERM_STAT - TST entry for the specified terminal ; ; Implicit Outputs: NONE ; ; Completion Status: NONE ; ; Side Effects: NONE ; ;-- .PSECT RWDATA RD,WRT,NOEXE,NOSHR,LONG ; Local storage JBC_MSG: .WORD 1 ; Job controller message type JBC_MSG_UNIT: .BLKW 1 ; Unit number field .BYTE 3 ; Length of device/controller name .WORD ^A/TT/ ; Device name/controller field JBC_MSG_CTRL: .BLKB 1 JBC_MSG_CHAN: .BLKW 1 ; Buffer to hold mailbox channel JBC_MBX_NAME: .ASCID /_MB1:/ ; Job control mailbox name .PSECT CODE NOWRT,EXE,SHR,LONG .ENTRY SND_JBC_MSG,^M ; Register usage ; R0-R1 - Scratch ; R2 - Address of TST entry for terminal ; Build message MOVL 4(AP),R2 ; Get pointer to TST entry MOVB TST_T_NAME+3(R2),- JBC_MSG_CTRL ; Put controller name into message SUBB3 #^A/0/,- TST_T_NAME+4(R2),- JBC_MSG_UNIT ; Convert unit name to binary and plug ; into message ; Get channel on mailbox and send message $ASSIGN_S - DEVNAM=JBC_MBX_NAME,- CHAN=JBC_MSG_CHAN ; Get channel IF_ERROR - CODE=#BAUD_ASSIGN ; Stop if error $QIO_S - CHAN=JBC_MSG_CHAN,- FUNC=#IO$_WRITEVBLK,- P1=JBC_MSG,- P2=#8 ; Send the message IF_ERROR - CODE=#BAUD_QIO ; Stop if error $DASSGN_S - CHAN=JBC_MSG_CHAN ; Deassign channel IF_ERROR - CODE=#BAUD_DASSGN ; Stop if error RET .END BAUD