Document revision date: 19 July 1999 | |
Previous | Contents | Index |
The VAX C program LAT.C shown in Example 5-1 initiates and maintains an outbound LAT session from the local node. It demonstrates the following LAT $QIO functions:
Example 5-1 LAT.C Terminal Driver Programming Example |
---|
#module LAT_FORWARD_CONNECT "X1.0-001" /* **++ ** ** MODULE DESCRIPTION: ** ** In initiating and maintaining an outbound LAT session from the local ** node, this program demonstrates the following LAT $QIO functions: ** ** o Cloning the LAT template device (LTA0:) ** o IO$M_LT_SETMODE ** o IO$M_LT_CONNECT (on forward port) ** o IO$M_LT_SENSEMODE ** **-- */ /* ** ** INCLUDE FILES ** */ #include <descrip> /* VMS Descriptor Definitions */ #include <iodef> /* I/O Function Codes Definitions */ #include <latdef> /* LAT Definitions */ #include <ssdef> /* System Service Return Status */ /* Code Definitions */ #include <ttdef> /* Terminal Characteristics */ #include <tt2def> /* Terminal Extended */ /* Characteristics */ /* ** ** MACRO DEFINITIONS ** */ /* ** Service name which the session will be to. */ #define SERVICE_NAME "LAT_SERVICE" #define SERVICE_NAME_LENGTH 11 /* ** For the sake of clarity, the sizes of the buffers used for reading from ** and writing to the LTA and TT devices are set to the values below. In ** order to gain maximum throughput from this program, the following SYSGEN ** parameters can be set: ** ** o TTY_ALTYPAHD - 1500 ** o TTY_TYPAHDSZ - 80 ** ** To get the best performance from this program without touching these ** SYSGEN parameters on your system, modify the program to set the size of ** the buffers to the following: ** ** o LTA_BUFFER_SIZE = MIN(TTY_ALTYPAHD, 1500) ** o TT_BUFFER_SIZE = MIN(TTY_TYPAHDSZ, 132) */ #define LTA_MAXBUF 1500 #define TT_MAXBUF 80 /* ** Size of the LAT SENSEmode itemlist. */ #define MAX_SENSE_ITEMLIST_SIZE 1500 /* ** Character user can press to terminate the LAT connection (CTRL+\). */ #define CONNECTION_TERMINATOR 0x1C /* ** ** FUNCTION PROTOTYPES ** */ unsigned long SetDeviceChars(void); void ConnectAST(void); void LTAreadChannelAST(void); void TTreadChannelAST(void); void LTAhangupHandler(void); void EndSession(void); void ExitHandler(void); /* ** ** GLOBAL DATA ** */ char *LTAbuffer, /* LTA device I/O buffer */ *TTbuffer, /* TT device I/O buffer */ /* ** Text for LAT reject codes. Note that some LAT ** implementations will return a 0 reject code to ** indicate a normal disconnect. */ *LATrejectTable[] = { "Unknown", "User requested disconnect", "System shutdown in progress", "Invalid slot received", "Invalid service class received", "Insufficient resources at server", "Port or service in use", "No such service", "Service is disabled", "Service is not offeredon the requested port", "Port name is unknown", "Invalid service password", "Remote entry is not in queue", "Immediate access rejected", "Access denied", "Corrupted request", "Requested function is not supported", "Session cannot be started", "Queue entry deleted by server", "Illegal request parameters" }; unsigned short LTAchannel, /* LTA device I/O channel */ TTchannel, /* TT device I/O channel */ LTA_QIOiosb[4], /* IOSB for LTA device functions */ TT_QIOiosb[4]; /* IOSB for TT device functions */ unsigned long ReadTerminatorMask[2] = { 0, 0 }, /* $QIO read terminator mask */ SavedTTdeviceChar[3], /* Saved TT device characteristics */ DeviceCharBuffSize = sizeof(SavedTTdeviceChar); /* Size of device characteristics buffer*/ ExitConditionValue, /* Exit condition value of program */ LATrejectTableSize =/* Number of elements in LAT reject tbl */ sizeof(LATrejectTable) / sizeof(LATrejectTable[0]); /* ** Itemlist for setting LAT port with the target service name. */ struct { unsigned short item_code; char item_byte_count; char item_value[ SERVICE_NAME_LENGTH ]; } PortSetmodeItemlist = { LAT$_ITM_TARGET_SERVICE_NAME, SERVICE_NAME_LENGTH, SERVICE_NAME }; /* ** Exit handler block. */ struct { unsigned long flink; void (*exit_handler)(); unsigned long arg_count; unsigned long *exit_status; } ExitHandlerBlock = { 0, ExitHandler, 1, &ExitConditionValue }; /* ** Devices which channels are assigned to. */ $DESCRIPTOR(LTAtemplateDSC, "LTA0:"); $DESCRIPTOR(TTchannelDSC, "SYS$COMMAND"); main() { /* ** Local Variables: */ unsigned long status, portSetmodeItemlistSize = sizeof(PortSetmodeItemlist); /* ** BEGIN: ** ** Declare an exit handler. */ if (!((status = sys$dclexh(&ExitHandlerBlock)) & 1)) lib$signal(status); /* ** Assign a channel to LTA0: to get a forward LAT port and assign a ** channel to the terminal. */ if (!((status = sys$assign(<AtemplateDSC, <Achannel, 0, 0)) & 1)) lib$signal(status); if (!((status = sys$assign(&TTchannelDSC, &TTchannel, 0, 0)) & 1)) lib$signal(status); /* ** Allocate memory for the channel data buffers. */ LTAbuffer = malloc(LTA_MAXBUF); TTbuffer = malloc(TT_MAXBUF); /* ** Set device characteristics for the two channels. */ if (!((status = SetDeviceChars()) & 1)) lib$signal(status); /* ** Do SETmode $QIO to set the port entity with the target service name ** specified in the item list. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_TTY_PORT|IO$M_LT_SETMODE, <A_QIOiosb, 0, 0, &PortSetmodeItemlist, portSetmodeItemlistSize, LAT$C_ENT_PORT|(LAT$C_ENTS_OLD << 0x10), 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Enable a CTRL+Y AST on the LAT channel. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_SETMODE|IO$M_CTRLYAST, <A_QIOiosb, 0, 0, LTAhangupHandler, 0, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Post the first read (with AST) on the LTA device to ensure that the ** first burst of data from the target service is not lost. It is very ** important that the first read is queued before doing the connect ** $QIO to ensure no data lossage. */ if (!((status = sys$qio( 0, LTAchannel, IO$_READVBLK|IO$M_NOECHO, <A_QIOiosb, LTAreadChannelAST, 0, LTAbuffer, 1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); /* ** Do the LAT connect $QIO and hibernate until program exit. The ** ConnectAST will execute when the connection completes and post the ** initial read on the TT channel. */ if (!((status = sys$qio( 0, LTAchannel, IO$_TTY_PORT|IO$M_LT_CONNECT, <A_QIOiosb, ConnectAST, 0, 0, 0, 0, 0, 0, 0)) & 1)) lib$signal(status); sys$hiber(); } /* END - main() */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine sets device characteristics of the LTA and TT devices. ** The HOSTSYNC, NOBRDCST, EIGHTBIT and PASTHRU characteristics are set ** on the LTA device. The ESCAPE and TTSYNC characteristics are cleared. ** ** The TTSYNC, HOSTSYNC, EIGHTBIT, and PASTHRU characteristics are set ** on the TT device. The ESCAPE characteristic is cleared. The TT ** characterisitcs are also saved for restoration at program exit. ** **-- */ unsigned long SetDeviceChars(void) { /* ** Local Variables: */ unsigned long status, deviceChar[3]; /* ** BEGIN: ** ** Mask and set the characteristics of the LTA device. Sense the ** current characteristics, and mask in and set the new ones. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_SENSEMODE, <A_QIOiosb, 0, 0, &deviceChar, DeviceCharBuffSize, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); deviceChar[1] = (deviceChar[1] | (TT$M_HOSTSYNC | TT$M_NOBRDCST | TT$M_EIGHTBIT)) & ~TT$M_ESCAPE & ~TT$M_TTSYNC; deviceChar[2] |= TT2$M_PASTHRU; if (!((status = sys$qiow( 0, LTAchannel, IO$_SETMODE, <A_QIOiosb, 0, 0, &deviceChar, DeviceCharBuffSize, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Repeat the procedure for TT device characteristics. However, save ** the current characteristics for restoration at program exit. */ if (!((status = sys$qiow( 0, TTchannel, IO$_SENSEMODE, &TT_QIOiosb, 0, 0, &SavedTTdeviceChar, DeviceCharBuffSize, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(TT_QIOiosb[0] & 1)) lib$signal(TT_QIOiosb[0]); deviceChar[0] = SavedTTdeviceChar[0]; deviceChar[1] = (SavedTTdeviceChar[1] | (TT$M_TTSYNC | TT$M_HOSTSYNC | TT$M_EIGHTBIT)) & ~TT$M_ESCAPE; deviceChar[2] = SavedTTdeviceChar[2] | TT2$M_PASTHRU; if (!((status = sys$qiow( 0, TTchannel, IO$_SETMODE, &TT_QIOiosb, 0, 0, &deviceChar, DeviceCharBuffSize, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(TT_QIOiosb[0] & 1)) lib$signal(TT_QIOiosb[0]); return(status); } /* END - SetDeviceChars */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is an AST which executes when the connect $QIO completes. ** First the IOSB is checked. If the connection timed out or was aborted, ** simply end the session. Any other abnormal status causes the program ** to exit. ** ** Otherwise the connection completed successfully and a read on the TT ** channel is posted. ** **-- */ void ConnectAST() { /* ** Local Variables: */ unsigned long status; /* ** BEGIN: ** ** If the status in the IOSB indicates that the connection timed out ** or aborted, call the session end routine. Any other abnormal ** status causes program exit. */ if ((LTA_QIOiosb[0] == SS$_TIMEOUT) || (LTA_QIOiosb[0] == SS$_ABORT)) EndSession(); if (!(LTA_QIOiosb[0] & 1)) sys$exit(LTA_QIOiosb[0]); /* ** The connection completed successfully! Post a read (with AST) on ** the TT device and return. */ if (!((status = sys$qio( 0, TTchannel, IO$_READVBLK|IO$M_NOECHO, &TT_QIOiosb, TTreadChannelAST, 0, TTbuffer, 1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); return; } /* END - ConnectAST */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is an AST which executes when the first character read on ** the LTA channel completes. It does a "flush" read of the channel to ** drain any data out of the ALTYPAHD buffer and writes the data to the ** TT channel. It then posts another read on the channel. ** **-- */ void LTAreadChannelAST(void) { /* ** Local Variables: */ unsigned long status; /* ** BEGIN: ** ** If the status in the IOSB indicates channel hangup, simply end the ** session. Signal any other abnormal status. */ if (LTA_QIOiosb[0] == SS$_HANGUP) EndSession(); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Do a "flush" read of the LTA device. This is done by doing a timed ** read with a 0 timeout. There may or may not be any data to drain. ** This method is more efficient than using single character reads. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO, <A_QIOiosb, 0, 0, LTAbuffer+1, LTA_MAXBUF-1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1) && (LTA_QIOiosb[0] != SS$_TIMEOUT)) lib$signal(LTA_QIOiosb[0]); /* ** The second word of the IOSB contains the number of characters ** read. Write the characters plus 1 for the initial read to the ** TT device. */ if (!((status = sys$qiow( 0, TTchannel, IO$_WRITEVBLK, &TT_QIOiosb, 0, 0, LTAbuffer, LTA_QIOiosb[1]+1, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(TT_QIOiosb[0] & 1)) lib$signal(TT_QIOiosb[0]); /* ** Post another read on the LTA device. */ if (!((status = sys$qio( 0, LTAchannel, IO$_READVBLK|IO$M_NOECHO, <A_QIOiosb, LTAreadChannelAST, 0, LTAbuffer, 1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); return; } /* END - LTAreadChannelAST */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is an AST which executes when the first character read on ** the TT channel completes. It does a "flush" read of the channel to ** drain any data out of the TYPAHD buffer and writes the data to the ** LTA channel. It then posts another read on the channel. ** **-- */ void TTreadChannelAST(void) { /* ** Local Variables: */ unsigned long status; /* ** BEGIN: ** ** If the user pressed the connection terminator character, do a LAT ** disconnect $QIO and exit. */ if (*TTbuffer == CONNECTION_TERMINATOR) { if (!((status = sys$qiow( 0, LTAchannel, IO$_TTY_PORT|IO$M_LT_DISCON, <A_QIOiosb, 0, 0, 0, 0, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); return; } /* ** Do a "flush" read of the TT device. This is done by doing a timed ** read with a 0 timeout. There may or may not be any data to drain. */ if (!((status = sys$qiow( 0, TTchannel, IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO, &TT_QIOiosb, 0, 0, TTbuffer+1, TT_MAXBUF-1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); if (!(TT_QIOiosb[0] & 1) && (TT_QIOiosb[0] != SS$_TIMEOUT)) lib$signal(TT_QIOiosb[0]); /* ** The second word of the IOSB contains the number of characters ** read. Write the characters plus 1 for the initial read to the ** TT device. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_WRITEVBLK, <A_QIOiosb, 0, 0, TTbuffer, TT_QIOiosb[1]+1, 0, 0, 0, 0)) & 1)) lib$signal(status); /* ** If the status in the IOSB indicates channel hangup, simply end ** the session. Signal any other abnormal status. */ if (LTA_QIOiosb[0] == SS$_HANGUP) EndSession(); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Post another read on the LTA device. */ if (!((status = sys$qio( 0, TTchannel, IO$_READVBLK|IO$M_NOECHO, &TT_QIOiosb, TTreadChannelAST, 0, TTbuffer, 1, 0, &ReadTerminatorMask, 0, 0)) & 1)) lib$signal(status); return; } /* END - TTreadChannelAST */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is the CTRL+Y AST for the LTA channel. It executes when ** a hangup on the LTA channel is recognized (connection timed out or ** aborted). It will call the session end routine if it hasn't already ** been called by ConnectAST. ** ** NOTE: CTRL+Y ASTs for application ports will NOT execute when the ** connection is disconnected. ** **-- */ void LTAhangupHandler(void) { /* ** BEGIN: ** ** Call the session end routine and return. */ EndSession(); return; } /* END - LTAhanghupHandler */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is executed at session end. It will do a $QIO SENSEmode ** and search the resulting itemlist to find the reason for the LAT ** disconnect. The reason for the disconnect is displayed on the ** terminal and the image exits. ** **-- */ void EndSession(void) { /* ** Local Variables: */ struct ITEM_ENTRY *itemlistEntry; unsigned long status; char *senseItemlist = malloc(MAX_SENSE_ITEMLIST_SIZE), *itemlistEntryPointer; /* ** BEGIN: ** ** Do the SENSEmode on the port. */ if (!((status = sys$qiow( 0, LTAchannel, IO$_TTY_PORT|IO$M_LT_SENSEMODE, <A_QIOiosb, 0, 0, senseItemlist, MAX_SENSE_ITEMLIST_SIZE, LAT$C_ENT_PORT|(LAT$M_SENSE_FULL << 0x10), 0, 0, 0)) & 1)) lib$signal(status); if (!(LTA_QIOiosb[0] & 1)) lib$signal(LTA_QIOiosb[0]); /* ** Set up two pointers used to traverse the itemlist. */ itemlistEntry = (struct ITEM_ENTRY *) senseItemlist; itemlistEntryPointer = senseItemlist; /* ** Search the itemlist for the LAT$_ITM_DISCONNECT_REASON code to find ** out why the connection terminated. */ while (itemlistEntry->LAT$R_ITM_CODE.LAT$W_ITEMCODE != LAT$_ITM_DISCONNECT_REASON) { /* ** If the current itemcode being checked has a string value, ** advance the pointer to the next itemcode by skipping ** BCNT bytes plus 3 bytes for the BCNT byte itself and the ** 2 byte itemcode. */ if (itemlistEntry-> LAT$R_ITM_CODE.LAT$R_ITM_BITS.LAT$V_STRING) itemlistEntryPointer += itemlistEntry->LAT$R_ITEM_VALUE. LAT$R_ITEM_COUNTED_STRING.LAT$B_ITEM_BCNT + 3; /* ** If the current itemcode being checked has a scalar value, ** advance the pointer to the next itemcode by skipping 6 ** bytes for the itemcode and the 4 byte scalar. */ else itemlistEntryPointer += 6; itemlistEntry = (struct ITEM_ENTRY *) itemlistEntryPointer; } /* ** If the disconnect reason is a LAT reject code, print out the ** text corresponding to the code and set the exit condition value ** to SS$_NORMAL. */ if (itemlistEntry->LAT$R_ITEM_VALUE.LAT$L_ITEM_SCALAR_VALUE <= LATrejectTableSize) { printf("\nSession disconnected. Reason: %s\n\n\n", LATrejectTable[ itemlistEntry->LAT$R_ITEM_VALUE. LAT$L_ITEM_SCALAR_VALUE ]); ExitConditionValue = SS$_NORMAL; } /* ** The scalar value is a LAT facility message code. Set the exit ** condition value to be the scalar. Upon image exit, the ** corresponding LAT facility message will be displayed. */ else ExitConditionValue = itemlistEntry->LAT$R_ITEM_VALUE.LAT$L_ITEM_SCALAR_VALUE; sys$exit(ExitConditionValue); } /* END - EndSession */ /* **++ ** ** FUNCTIONAL DESCRIPTION: ** ** This is the program exit handler which is executed upon image exit. ** It will cancel all pending I/O on the two channels and restore the ** TT channel characteristics. ** **-- */ void ExitHandler(void) { /* ** Local Variables: */ unsigned long status; /* ** BEGIN: ** ** Cancel I/O on the channels, reset terminal characteristics and ** return. */ if (!((status = sys$cancel(LTAchannel)) & 1)) lib$signal(status); if (!((status = sys$cancel(TTchannel)) & 1)) lib$signal(status); if (!((status = sys$qiow( 0, TTchannel, IO$_SETMODE, &TT_QIOiosb, 0, 0, &SavedTTdeviceChar, DeviceCharBuffSize, 0, 0, 0, 0)) & 1)) lib$signal(status); if (!(TT_QIOiosb[0] & 1)) lib$signal(TT_QIOiosb[0]); return; } /* END - ExitHandler */ |
The VAX MACRO program FULL_DUPLEX_TERMINAL.MAR (Example 5-2) shows several I/O operations using the full-duplex capabilities of the terminal. This program shows some important concepts about terminal driver programming: assigning an I/O channel, performing full-duplex I/O operations, enabling Ctrl/C AST requests, and itemlist read operations. The program is designed to run with a terminal set to full-duplex mode.
The initialization code queues a read request to the terminal and enables Ctrl/C AST requests. The main loop then prints out a random message every three seconds. When you enter a message on the terminal, the read AST routine prints an acknowledgment message and queues another read request. If you press Ctrl/C, the associated AST routine cancels the I/O operation on the assigned channel and exits to the command interpreter.
Example 5-2 FULL_DUPLEX_TERMINAL.MAR Terminal Driver Programming Example |
---|
.TITLE FULL_DUPLEX TERMINAL PROGRAMMING EXAMPLE .IDENT /05/ ; ******************************************************************** ; ; TERMINAL PROGRAM ; ; ******************************************************************** .SBTTL DECLARATIONS .DISABLE GLOBAL ; ; Declare the external symbols and MACRO libraries. ; .EXTERNAL LIB$GET_EF .LIBRARY 'SYS$LIBRARY:LIB.MLB' .LIBRARY 'SYS$LIBRARY:STARLET.MLB' ; ; Define symbols ; $IODEF ; Define I/O function codes $QIODEF ; Define QIO definition codes $SSDEF ; Define the system service status codes $TRMDEF ; Define itemlist read codes $TTDEF ; Terminal characteristic definitions ; ; Define macros ; .SHOW .MACRO ITEM LEN=0,CODE,VALUE .WORD LEN .WORD TRM$_'CODE' .LONG VALUE .LONG 0 .ENDM ITEM .NOSHOW ; ; Declare exit handler control block ; EXIT_HANDLER_BLOCK: .LONG 0 ; System uses this for pointer .LONG EXIT_HANDLER ; Address of exit handler .LONG 1 ; Argument count for handler .LONG STATUS ; Destination of status code STATUS: .BLKL 1 ; Status code from $EXIT ; ; Allocate terminal descriptor and channel number storage ; TT_DESC: .ASCID /SYS$INPUT/ ; Logical name of terminal TT_CHAN: .BLKW 1 ; TT channel number storage ; ; Define acknowledgment message. This is done right above input buffer ; so that we can concatenate the two together when the acknowledgment ; message is issued. ; ACK_MSG: .ASCII <CR><LF> /Following input acknowledged: / ACK_MSGLEN=.-ACK_MSG ; Calculate length of message ; ; Allocate input buffer ; IN_BUFLEN = 20 ; Set length of buffer IN_BUF: .BLKB IN_BUFLEN ; Allocate character buffer IN_IOSB: .BLKQ 1 ; Input I/O status block ; ; Define out-of-band ast character mask ; CNTRLA_MASK: .LONG 0 .LONG ^B0010 ; Control A mask ; ; Define old terminal characteristics buffer ; OLDCHAR_BUF_LEN = 12 OLDCHAR_BUF: .BLKB OLDCHAR_BUF_LEN ; ; Define new terminal characteristics buffer ; NEWCHAR_BUF_LEN = 12 NEWCHAR_BUF: .BLKB NEWCHAR_BUF_LEN ; ; Define carriage control symbols ; CR=^X0D ; Carriage return LF=^X0A ; Line feed ; ; Define output messages ; ; Output messages are accessed by indexing into a table of ; longwords with each message described by a message address and ; message length ; ARRAY: ; Table of message addresses and ; lengths .LONG 10$ ; First message address .LONG 15$ ; First message length .LONG 20$ .LONG 25$ .LONG 30$ .LONG 35$ .LONG 40$ .LONG 45$ ; ; Define messages ; 10$: .ASCII <CR><LF>/RED ALERT! RED ALERT!/ 15$=.-10$ ; 20$: .ASCII <CR><LF>/ALL SYSTEMS GO/ 25$=.-20$ ; 30$: .ASCII <CR><LF>/WARNING..INTRUDER ALARM/ 35$=.-30$ ; 40$: .ASCII <CR><LF>/** SYSTEM OVERLOAD **/ 45$=.-40$ ; ; Static QIO packet for message output using QIO$_G form ; WRITE_QIO: $QIO EFN=SYNC_EFN, - ; QIO packet FUNC=IO$_WRITEVBLK!IO$M_BREAKTHRU!IO$M_REFRESH, - IOSB=SYNC_IOSB ; ; Declare the required I/O status blocks. ; SYNC_IOSB:: .BLKQ 1 ; I/O status block for synchronous terminal processing. ; ; Declare the required event flags. ; ASYNC_EFN:: .BLKL 1 ; Event flag for asynchronous terminal processing. SYNC_EFN == WRITE_QIO + 4 ; Event flag for sync terminal processing. TIMER_EFN:: .BLKL 1 ; Event flag for timer processing. ; ; Timer storage ; WAITIME: .LONG -10*1000*1000*3,-1 ; 3 second delta time TIME: .BLKQ 1 ; Current storage time used for ; random number .PAGE .SBTTL START - MAIN ROUTINE .ENABLE LOCAL_BLOCK ;++ ; ; Functional description: ; ; ******************************************************************** ; ; Start program ; ; ******************************************************************** ; ; The following code performs initialization functions. ; It is assumed that the terminal is already in ; FULL-DUPLEX mode. ; ; NOTE: When doing QIO_S calls, parameters P1 and P3-P6 should be ; passed by value, while P2 should be passed by reference. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ;-- .ENTRY START ^M < > ; Get the required event flags. PUSHAL ASYNC_EFN CALLS # 1, G^ LIB$GET_EF ; Get EFN for async terminal operations. BLBC R0, 10$ ; Error - branch. PUSHAL SYNC_EFN CALLS # 1, G^ LIB$GET_EF ; Get EFN for sync terminal operations. BLBC R0, 10$ ; Error - branch. PUSHAL TIMER_EFN CALLS # 1, G^ LIB$GET_EF ; Get EFN for timer operations. BLBC R0, 10$ ; Error - branch. ; Initialize the terminal characteristics. $ASSIGN_S DEVNAM=TT_DESC,-; Assign terminal channel using CHAN=TT_CHAN ; logical name and channel number BLBC R0, 10$ ; Error - branch. BSBW CHANGE_CHARACTERISTICS ; Change the characteristics of ; terminal BSBW ENABLE_CTRLCAST ; Allow Ctrl/C traps BSBW ENABLE_OUTBANDAST ; Enable Ctrl/A out-of-band AST BSBW ENABLE_READ ; Queue read MOVZWL TT_CHAN, WRITE_QIO+8 ; Insert channel into BRB LOOP ; static QIO packet 10$: BRW ERROR ; ; This loop outputs a message based on a random number and then ; delays for 3 seconds ; LOOP: $GETTIM_S TIMADR=TIME ; Get random time BLBC R0, 10$ ; Error - branch. EXTZV #6, #2, TIME, R0 ; Load random bits into switch MOVQ ARRAY[R0], - ; Load message address WRITE_QIO+QIO$_P1 ; and size into QIO ; packet ; ; Issue QIO write using packet defined in data area ; $QIOW_G WRITE_QIO BLBC R0, 10$ ; QIO error - branch. MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. BLBC R0, 10$ ; Terminal driver error - branch. ; ; Delay for 3 seconds before issuing next message ; $SETIMR_S EFN=TIMER_EFN,- ; Timer service DAYTIM=WAITIME ; will set event flag ; in 3 seconds BLBC R0, 10$ ; Error - branch. $WAITFR_S EFN=TIMER_EFN ; Wait for event flag BLBS R0, LOOP ; No error if set BRB 10$ ; Error - branch. .DISABLE LOCAL_BLOCK .PAGE .SBTTL CHANGE_CHARACTERISTICS - CHANGE CHARACTERISTICS OF TERMINAL ;++ ; ; Functional description: ; ; Routine to change the characteristics of the terminal. ; ; Input parameters: ; None ; ; Output parameters: ; R0 - status from $QIO call. ; R1 - R5 destroyed ; ;-- ; CHANGE_CHARACTERISTICS: $QIOW_S EFN=SYNC_EFN, - ; Get current terminal characteristics CHAN=TT_CHAN, - FUNC=#IO$_SENSEMODE, - IOSB=SYNC_IOSB, - P1=OLDCHAR_BUF, - P2=#OLDCHAR_BUF_LEN BLBC R0, 10$ ; Error if clear MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. BLBC R0, 10$ ; Error - branch $DCLEXH_S EXIT_HANDLER_BLOCK ; Declare exit handler to reset ; characteristics BLBC R0, 10$ ; Error - branch. MOVC3 #OLDCHAR_BUF_LEN, - ; Move old characteristics into OLDCHAR_BUF, - ; new characteristics buffer NEWCHAR_BUF BISL2 #TT$M_NOBRDCST, - ; Set nobroadcast bit NEWCHAR_BUF+4 ; ... $QIOW_S EFN=SYNC_EFN, - ; Set current terminal characteristics CHAN=TT_CHAN, - FUNC=#IO$_SETMODE, - IOSB=SYNC_IOSB, - P1=NEWCHAR_BUF, - P2=#NEWCHAR_BUF_LEN BLBC R0, 10$ ; QIO error - branch. MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. BLBC R0, 10$ ; Terminal driver error - branch. RSB 10$: BRW ERROR .PAGE .SBTTL ENABLE_CTRLCAST - ENABLE Ctrl/C AST ;++ ; ; Functional description: ; ; Routine to allow Ctrl/C recognition. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ;-- ; ENABLE_CTRLCAST: $QIOW_S EFN=SYNC_EFN, - CHAN=TT_CHAN, - FUNC=#IO$_SETMODE!IO$M_CTRLCAST, - IOSB=SYNC_IOSB, - P1=CTRLCAST, - ; AST routine address P3=#3 ; User mode BLBC R0, 10$ ; Error - branch. MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. BLBC R0, 10$ ; Terminal driver error - branch. RSB 10$: BRW ERROR .PAGE .SBTTL ENABLE_OUTBANDAST - ENABLE Ctrl/A AST ;++ ; ; Functional description: ; ; Routine to allow CNTRL/A recognition. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ENABLE_OUTBANDAST: $QIOW_S EFN=SYNC_EFN, - CHAN=TT_CHAN, - FUNC=#IO$_SETMODE!IO$M_OUTBAND, - IOSB=SYNC_IOSB, - P1=CTRLAAST, - ; AST routine address P2=#CNTRLA_MASK, - ; Character mask P3=#3 ; User mode BLBC R0, 10$ ; QIO error - branch. MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. BLBC R0, 10$ ; Terminal driver error - branch. RSB 10$: BRW ERROR .PAGE .SBTTL ENABLE_READ - QUEUE A READ TO THE TERMINAL. ;++ ; ; Functional description: ; ; Routine to queue a read operation to the terminal. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ; Define item list for itemlist read ; ITEM_LST: ITEM 0, MODIFIERS, - ; Convert lowercase to TRM$M_TM_CVTLOW!TRM$M_TM_NOEDIT ; upper and inhibit line ITEM 6, TERM,MASK_ADDR ; editing ; Set up terminator mask ITEM_LEN = . - ITEM_LST MASK_ADDR: .LONG 1@^XD ; Terminator mask is ; <CR> .WORD 1@4 ; and "$" ENABLE_READ: $QIO_S EFN=ASYNC_EFN, - ; Must not be QIOW form or read will block CHAN=TT_CHAN, - ; process FUNC=#IO$_READVBLK!IO$M_EXTEND, - IOSB=IN_IOSB, - ASTADR=READAST, - ; AST routine to execute P1=IN_BUF, - ; on P2=#IN_BUFLEN, - P5=#ITEM_LST, - ; Itemlist read address P6=#ITEM_LEN ; Itemlist read size BLBC R0, 10$ ; QIO error - branch. ; The queued read operation will not affect write operations due ; to the fact that breakthru has been set for the write operations. RSB 10$: BRW ERROR .PAGE .SBTTL READAST - AST ROUTINE FOR READ COMPLETION .ENABLE LOCAL_BLOCK ;++ ; ; Functional description: ; ; AST routine to execute on read completion. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ;-- ; 10$: MOVZWL IN_IOSB, R0 ; Get the terminal driver status 20$: BRW ERROR ; Exit with error status. .ENTRY READAST ^M < R2, R3, R4, R5 > ; Procedure entry mask BLBC IN_IOSB, 10$ ; Terminal driver error - branch MOVZWL IN_IOSB+2, R0 ; Get number of characters read into R0 ADDL2 #ACK_MSGLEN, R0 ; Add size of fixed acknowledge message $QIO_S EFN=ASYNC_EFN, - ; Issue acknowledge message CHAN=TT_CHAN, - ; Note, ACK must be asynchronous (QIO) FUNC=#IO$_WRITEVBLK, - ; and the terminal driver write status P1=ACK_MSG, - ; is ignored (no IOSB and AST routine). P2=R0 ; Specify IOSB and AST routine if output ; must be displayed on the terminal. BLBC R0, 20$ ; QIO error - branch ; ; Process read message ; ; . ; . ; . ;(user-provided code to decode command inserted here) ; . ; . ; . BSBW ENABLE_READ ; Queue next read RET ; Return to mainline loop .DISABLE LOCAL_BLOCK .PAGE .SBTTL CTRLAAST - AST ROUTINE FOR Ctrl/A .SBTTL CTRLCAST - AST ROUTINE FOR Ctrl/C .SBTTL ERROR - EXIT ROUTINE ;++ ; ; Functional description: ; ; AST routine to execute when Ctrl/C or Ctrl/A is entered. ; ; Input parameters: ; None ; ; Output parameters: ; None ; CTRLCAST:: CTRLAAST:: .WORD ^M < > ; Procedure entry mask MOVL #SS$_NORMAL, R0 ; Put success in R0 ERROR:: $EXIT_S R0 ; Exit RSB .PAGE .SBTTL EXIT_HANDLER - EXIT HANDLER ROUTINE ;++ ; ; Functional description: ; ; Exit handler routine to execute when image exits. It cancels ; any outstanding I/O on this channel and resets the terminal ; characteristics to their original state. ; ; Input parameters: ; None ; ; Output parameters: ; None ; ;-- ; .ENTRY EXIT_HANDLER ^M< > $CANCEL_S CHAN=TT_CHAN ; Flush any I/O on queue $QIOW_S EFN=SYNC_EFN, - ; Reset terminal characteristics CHAN=TT_CHAN, - FUNC=#IO$_SETMODE, - IOSB=SYNC_IOSB, - P1=OLDCHAR_BUF, - P2=#OLDCHAR_BUF_LEN BLBC R0, 10$ ; QIO error - branch. MOVZWL SYNC_IOSB, R0 ; Get the terminal driver status. 10$: RET .END START |
Previous | Next | Contents | Index |
privacy and legal statement | ||
6136PRO_024.HTML |