KVC@BUSTER.NRC.COM (Kevin Carosso) (07/31/88)
+-+-+-+ Beginning of part 3 +-+-+-+ Xint`009`009xoff_ast(); Xint`009`009status; X Xstruct`009devchar`009changed_char; Xstruct`009iosb`009kbd_r_iosb; Xstruct`009iosb`009py_w_iosb; X X X/* Get information channel name and assign a channel to it */ X Xprintf("Enter device to output diagnostic information on: "); Xgets(devnam); X Xif (length=strlen(devnam)) X{ X dummy.dsc$a_pointer = &devnam[0]; X dummy.dsc$w_length = length; X status = SYS$ASSIGN(&dummy, &info_chan, 0, 0); X if (status & SS$_NORMAL) X { X info_flag = 1; X } X else X { X printf("Unable to assign infomation channel error number %9X", status); X } X} X X V/* Create a mailbox, get a channel to the PY device and the terminal exit any o Xf these steps fail */ X Xstatus = SYS$CREMBX(0, &mbx_chan, 0, 0, 0, 0, 0); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X Xstatus = SYS$ASSIGN(&py_devnam, &py_chan, 0, 0); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X Xstatus = SYS$ASSIGN(&kbd_devnam, &kbd_chan, 0, 0); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X X/* Get a bunch of efn that we will need exit if cannot get them */ Xstatus = LIB$GET_EF(&kbd_s_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xstatus = LIB$GET_EF(&kbd_r_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xstatus = LIB$GET_EF(&py_s_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xstatus = LIB$GET_EF(&py_w_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xstatus = LIB$GET_EF(&wait_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xstatus = LIB$GET_EF(&xoff_efn); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X X X/* Now read the terminal characteristics so we can alter them */ X Vstatus = SYS$QIOW(kbd_s_efn, kbd_chan, IO$_SENSEMODE, &kbd_r_iosb, 0, 0, &saved X_char, 12, 0, 0, 0, 0); X Xif (status & SS$_NORMAL) X{ X if (kbd_r_iosb.status & SS$_NORMAL) X { X changed_char = saved_char; V changed_char.basic_char = TT$M_NOECHO | changed_char.basic_char & ~(TT$M_HO XSTSYNC | TT$M_TTSYNC); X changed_char.extended_char = TT2$M_PASTHRU | changed_char.extended_char; X } X else X { X LIB$SIGNAL(kbd_r_iosb.status); X } X} Xelse X{ X LIB$SIGNAL(status); X} X X X/* Now establish the exit handler and change the terminal characteristics */ X Xstatus = SYS$DCLEXH (&exit_block_descrip); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X Vstatus = SYS$QIOW(kbd_s_efn, kbd_chan, IO$_SETMODE, &kbd_r_iosb, 0, 0, &changed X_char, 12, 0, 0, 0, 0); Xif (!(status & SS$_NORMAL)) LIB$SIGNAL(status); Xif (!(kbd_r_iosb.status & SS$_NORMAL)) LIB$SIGNAL(kbd_r_iosb.status); X X X/* All set up now so start read to mailbox, and PYDEVICE */ X Vstatus = SYS$QIO (0, mbx_chan, IO$_READVBLK, &mbx_iosb, &read_mbx_ast, 0, &mbx_ Xbuff[0], X`009`009 sizeof(mbx_buff), 0, 0, 0, 0); X Vstatus = SYS$QIO (0, py_chan, IO$_READVBLK, &py_r_iosb, &py_read_ast, 0, &py_r_ Xbuff[0], X`009`009 sizeof(py_r_buff), 0, 0, 0, 0); X X X/* Set up XON, XOFF, and set line ASTs */ X Vstatus = SYS$QIOW(py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, xon_ast, 0, X 0, 1, 0, 0); Vstatus = SYS$QIOW(py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, xoff_ast, 0 X, 0, 2, 0, 0); Vstatus = SYS$QIOW(py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, set_line_as Xt, 0, 0, 3, 0, 0); X X V/* Now the real magic begins we get a read going to the terminal in an infinite X loop */ X X Xprintf("\n\nTo exit use CTRL-@\n\n"); Xdummy.dsc$a_pointer = &kbd_r_buff[0]; X Xwhile (1) X{ X V status = SYS$QIOW (kbd_r_efn, kbd_chan, IO$_READVBLK, &kbd_r_iosb, 0, 0, &kbd X_r_buff[0], 1, X`009`009 0, &term_block, 0, 0); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X X /* Stall for 50 milli-seconds waiting for more data */ X X status = SYS$SETIMR (wait_efn, &bintim, 0, 0); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X status = SYS$WAITFR(wait_efn); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X X X /* Now pick up any more user data */ X V status = SYS$QIOW (kbd_r_efn, kbd_chan, IO$_READVBLK | IO$M_TIMED, &kbd_r_ios Xb, 0, 0, &kbd_r_buff[1], X`009`009 (sizeof(kbd_r_buff)-1), 0, &term_block, 0, 0); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X dummy.dsc$w_length = 1 + kbd_r_iosb.byte_cnt; X X X /* Go ahead and try and input a character */ X X X length = dummy.dsc$w_length; X do X { X status = SYS$QIOW(py_w_efn, py_chan, IO$_WRITEVBLK, &py_w_iosb, 0, 0, X`009`009 &kbd_r_buff[0], length, 0, 0, 0, 0); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X if ((py_w_iosb.status == SS$_DATAOVERUN) && (py_w_iosb.byte_cnt < length)) X { X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X status = SYS$WAITFR(xoff_efn); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X status = SYS$SETAST(0); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X status = SYS$CLREF(xoff_efn); X if (!(status & SS$_NORMAL)) LIB$SIGNAL(status); X status = SYS$SETAST(1); X length = length - py_w_iosb.byte_cnt; X } V else if ((py_w_iosb.status == SS$_NORMAL) || (py_w_iosb.status == SS$_DATAO XVERUN)) X { X break; X } X else X { X LIB$SIGNAL(py_w_iosb.status); X } X X } while (py_w_iosb.status != SS$_NORMAL); X X status = LIB$MATCHC(&null_char, &dummy); X if (status) LIB$SIGNAL(SS$_HANGUP); X} X X} X`012 X/* Simple exit handler routine to reset terminal characteristics */ X X Xexit_handler() X{ Xint`009`009status; X Xstruct`009iosb`009exit_iosb; X X Vstatus = SYS$QIOW(kbd_s_efn, kbd_chan, IO$_SETMODE, &exit_iosb, 0, 0, &saved_ch Xar, 12, X`009`009 0, 0, 0, 0); Xif (!(status & SS$_NORMAL)) printf("Error resetting terminal reason is %9X"); X X} X`012 X/* This routine will read the termination mailbox and report it to user */ Xread_mbx_ast() X{ Xint`009`009status; X X X/* Indicate if read mailbox & if successful */ Xif (mbx_iosb.status & SS$_NORMAL) X{ X printf("\n\nTermination mailbox message received form TW device!!\n\n"); X} Xelse X{ X printf("\n\nTermination maibox read with error %9X\n\n", mbx_iosb.status); X} X X X/* Reset read to termination mailbox */ X Vstatus = SYS$QIOW(0, mbx_chan, IO$_READVBLK, &mbx_iosb, &read_mbx_ast, 0, &mbx_ Xbuff[0], X`009`009 sizeof(mbx_buff), 0, 0, 0, 0); Vif (!(status & SS$_NORMAL)) printf("\n\nError setting up MBX read reason is %9X X\n\n"); X X} X X X`012 X/* This routine will write to the terminal data read from the PY device */ Xpy_read_ast() X{ Xint`009`009kbd_write_ast(); Xint`009`009status; X Xif (!(py_r_iosb.status & SS$_NORMAL)) X{ X printf("\n\nError reading from PY device program exiting!!!\n\n"); X LIB$SIGNAL(py_r_iosb.status); X} X Vstatus = SYS$QIO(0, kbd_chan, IO$_WRITEVBLK, &kbd_w_iosb, &kbd_write_ast, 0, &p Xy_r_buff[0], py_r_iosb.byte_cnt, 0, 0, 0, 0); X Xif (!(status & SS$_NORMAL)) X{ X printf("\n\nError writing PY data to terminal program exiting!!!\n\n"); X LIB$SIGNAL(status); X} X X} X X X`012 V/* This rouinte gets called when the write to the terminal finishes. It restart Xs the read on the PYDEVICE. */ Xkbd_write_ast() X{ Xint`009`009status; X Vstatus = SYS$QIO (0, py_chan, IO$_READVBLK, &py_r_iosb, &py_read_ast, 0, &py_r_ Xbuff[0], sizeof(py_r_buff), 0, 0, 0, 0); X Xif (!(status & SS$_NORMAL)) X{ X printf("\n\nError reading from PY program exiting!!!\n\n"); X LIB$SIGNAL(status); X} X X} X`012 V/* This routine will signal when an XOFF AST is delivered it resets AST and rep Xorts character that is delivered */ Xxoff_ast(param) Xint`009`009param; X{ Xchar`009`009buffer[40]; X Xshort int`009signal_char; X Xint`009`009len; Xint`009`009status; X X Vstatus = SYS$QIOW (py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, &xoff_ast, X 0, 0, 2, 0, 0); Xif (!(status & SS$_NORMAL)) X{ X printf("Error enabling XOFF ast on PYDEVICE"); X LIB$SIGNAL(status); X} Xif (!(py_s_iosb.status & SS$_NORMAL)) X{ X printf("Error enabling XOFF ast on PYDEVICE"); X LIB$SIGNAL(py_s_iosb.status); X} X Xif (info_flag) X{ X signal_char = (short int) (param >> 16); V len = sprintf(buffer, "\015\012Received XOFF character: %2X\015\012", signal X_char); V status = SYS$QIO(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0], X len, 0, 0, 0, 0); X} X X} X`012 V/* This routine will signal when an XON AST is delivered it resets AST and repo Xrts character that is delivered */ Xxon_ast(param) Xint`009`009param; X{ Xchar`009`009buffer[40]; X Xshort int`009signal_char; X Xint`009`009len; Xint`009`009status; X Xstatus = SYS$SETEF(xoff_efn); X Vstatus = SYS$QIOW (py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, &xon_ast, X0, 0, 1, 0, 0); Xif (!(status & SS$_NORMAL)) X{ X printf("Error enabling XON ast on PYDEVICE"); X LIB$SIGNAL(status); X} Xif (!(py_s_iosb.status & SS$_NORMAL)) X{ X printf("Error enabling XON ast on PYDEVICE"); X LIB$SIGNAL(py_s_iosb.status); X} X Xif (info_flag) X{ X signal_char = (short int) (param >> 16); V len = sprintf(buffer, "\015\012Received XON character: %2X\015\012", signal_ Xchar); V status = SYS$QIO(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0], X len, 0, 0, 0, 0); X} X X} X`012 X/* This routine will signal when an XON AST is delivered it resets AST */ Xset_line_ast() X{ Xchar`009`009buffer[80]; X Xint`009`009len; Xint`009`009status; X Xstruct`009devchar`009current_char; Xstruct`009devchar`009perm_char; X Vstatus = SYS$QIOW (py_s_efn, py_chan, IO$_SETMODE, &py_s_iosb, 0, 0, &set_line_ Xast, 0, 0, 3, 0, 0); Xif (!(status & SS$_NORMAL)) X{ X printf("Error enabling set line ast on PYDEVICE"); X LIB$SIGNAL(status); X} Xif (!(py_s_iosb.status & SS$_NORMAL)) X{ X printf("Error enabling set line ast on PYDEVICE"); X LIB$SIGNAL(py_s_iosb.status); X} X Xif (info_flag); X{ V status = SYS$QIOW(py_s_efn, py_chan, IO$_SENSEMODE, &py_s_iosb, 0, 0, ¤ Xt_char, 12, 0, 0, 0, 0); X if (!(status & SS$_NORMAL)) X { X printf("Error reading current characteristics on PYDEVICE"); X LIB$SIGNAL(status); X } X if (!(py_s_iosb.status & SS$_NORMAL)) X { X printf("Error reading current characteristics on PYDEVICE"); X LIB$SIGNAL(py_s_iosb.status); X } X X len = sprintf(buffer,"\015\012 Current device characteristics \015\012"); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X len = sprintf(buffer,"Device class: %8X\015\012",current_char.class); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X len = sprintf(buffer,"Devic type: %8X\015\012",current_char.type); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); V len = sprintf(buffer,"Buffer size: %8X\015\012",current_char.buffer_s Xize); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); V len = sprintf(buffer,"Basic chars & witdh:%8X\015\012",current_char.basic_cha Xr); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); V len = sprintf(buffer,"Extended chars.: %8X\015\012",current_char.extended X_char); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X V status = SYS$QIOW(py_s_efn, py_chan, IO$_SENSECHAR, &py_s_iosb, 0, 0, &perm_c Xhar, 8, 0, 0, 0, 0); X if (!(status & SS$_NORMAL)) X { X printf("Error reading current characteristics on PYDEVICE"); X LIB$SIGNAL(status); X } X if (!(py_s_iosb.status & SS$_NORMAL)) X { X printf("Error reading current characteristics on PYDEVICE"); X LIB$SIGNAL(py_s_iosb.status); X } X X len = sprintf(buffer,"\015\012Permanent device characteristics \015\012"); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X len = sprintf(buffer,"Device class: %8X\015\012",perm_char.class); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X len = sprintf(buffer,"Devic type: %8X\015\012",perm_char.type); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); V len = sprintf(buffer,"Buffer size: %8X\015\012",perm_char.buffer_size X); V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); V len = sprintf(buffer,"Basic chars & witdh: %8X\015\012",perm_char.basic_char) X; V status = SYS$QIOW(0, info_chan, IO$_WRITEVBLK, &info_w_iosb, 0, 0, &buffer[0] X, len, 0, 0, 0, 0); X X} X X} $ GOSUB UNPACK_FILE $ FILE_IS = "PYDRIVER.MAR" $ CHECKSUM_IS = 576816862 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X`009.TITLE`009PYDRIVER - Pseudo terminal driver interface X`009.IDENT 'V05-007A' X X;++ X; FACILITY: X; X;`009VAX/VMS Pseudo Terminal Driver interface X; X; ABSTRACT: X; X;`009The pseudo terminal consists of two devices. X;`009This is the non terminal part of the two devices. X; X; AUTHOR: X; X;`00919-Nov-1982`009Dale Moore`009Redid the TW driver for VMS 3.0 X; X;`009This program has been granted to the public domain by the author. X; X; Revision History: X; X;`009Version 'V03-001' X;`009`009DWM`009- Added Page seperators X;`009`009`009- On Last cancel, invoke hangup on TW device X;`009`009`009- changed PY_STOP and PY_STOP2 to return instead X;`009`009`009 of looping for more. X;`009`009`009- Changed last cancel to call ioc$reqcom instead of X;`009`009`009 using macro REQCOM which is a branch ioc$reqcom. X;`009Version V03-002`009- Changed to Clear word rather than clear byte X;`009`009`009 in startio routine on word field. X; X;`009Version V03-003 (Thu Dec 9 12:42:38 1982) D. Kashtan X;`009`009`009 Made into a TEMPLATE driver. X;`009Version V03-004 (Fri Dec 10 11:40:35 1982) D. Kashtan X;`009`009`009 Made EXE$... into +EXE$... in FDT dispatch table, X;`009`009`009 fixing bug that crashed system in SET/SENSE MODE/CHAR X;`009Version V03-005`009(14-Jun-1983) Dale Moore X;`009`009`009 Add R4 to calls to IOC$INITIATE. X;`009`009`009 TTY$STARTIO mucks R4 X;`009Version V03-006`009(12-Jul-1983) Mark London, MIT Plasma Fusion Center X;`009`009`009- Set terminal to NOBROADCAST when no READ QIO avail- X;`009`009`009 able so as to allow Broadcasts without hanging up. X;`009`009`009 (When no QIO available, UCB$M_INT is enabled, and X;`009`009`009 the Broadcast don't get handled. The sender of a X;`009`009`009 Broadcast goes into a wait state until the broadcast X;`009`009`009 is completed or timed-out, neither or which can X;`009`009`009 happen. Setting NOBROADCASTs at least allow the X;`009`009`009 Broadcast to finish. What is needed is a CTRLS state X;`009`009`009 that doesn't allow Broadcasts to break through.) X;`009`009`009- Added MOVC3 instruction for burst data in PY$STARTIO, X;`009`009`009 which "should" speed up the transfers. X;`009`009`009- Fixed data transfer problem by raising to fork IPL X;`009`009`009 while calling PUTNXT in PY$FDTWRITE. NOTE: TWA0 must X;`009`009`009 be a mailbox to avoid TT reads from timing out. X; X;`009Version V04-001 - Doug Davis, Digital Equipment X;`009`009`009- Most of the changes required for migration to X;`009`009`009 Version 4.0 relate to the new handling of UCB X;`009`009`009 creation and deletion. This includes adding X;`009`009`009 a CLONEDUCB entry point to the dispatch table, X;`009`009`009 and "cloning" the UNITINIT routine to handle the X;`009`009`009 required entry. Also changed the call from X;`009`009`009 IOC$CREATE_UCB to IOC$CLONE_UCB, with associated X;`009`009`009 maintainence of the UCB$V_DELETEUCB bit in the X;`009`009`009 UCB$L_STS field. X;`009`009`009- Changes were also incorporated reflecting new X;`009`009`009 methods of XON/XOFF flow control. X;`009`009`009- Although pieces of the original code have been X;`009`009`009 superceded by these changes ( example - functions X;`009`009`009 that were performed by Unit_Init for new units X;`009`009`009 are are now performed by Clone_Init ), most of X;`009`009`009 the original code was left in place and/or commented X;`009`009`009 out. X; X;`009`009`009NOTE - No subroutines preambles were modified to X;`009`009`009 reflect these changes. X; X;`009Version V04-002`009(20-Jan-1985) Mark London, MIT Plasma Fusion Center X;`009`009`009- Changed test for output characters after call to X;`009`009`009 UCB$L_TT_PUTNXT and UCB$L_TT_GETNXT. Output is X;`009`009`009 indicated in UCB$B_TT_OUTYPE. X; X;`009Version V04-003 (24-Jun-1985) Kevin Carosso, Hughes Aircraft Co., S&CG X;`009`009`009Cleaned this thing up quite a bit. X;`009`009`009- Got rid of MBX characteristic on the devices. This X;`009`009`009 was a holdover to before cloned devices really X;`009`009`009 existed. X;`009`009`009- Got rid of the UNIT_INIT routine completely. This X;`009`009`009 was replaced by a CLONE_UCB routine. X;`009`009`009- Leave the PY template device OFFLINE. This is what X;`009`009`009 other TEMPLATE devices do, to indicate that you X;`009`009`009 really cannot do I/O to the template. X;`009`009`009- Rewrote the CANCEL_IO routine to issue a DISCONNECT X;`009`009`009 on the TW device at last deassign of the PY device. X;`009`009`009 This causes the TW device to hangup on it's process. X;`009`009`009 Works quite nicely with VMS V4 connect/disconnect X;`009`009`009 mechanism. Also, the devices should never stay X;`009`009`009 around after last deassign on the PY, if you want to X;`009`009`009 reconnect, count on VMS connect/disconnect instead, X;`009`009`009 it's much less of a security hole. X;`009`009`009- Got rid of all modem operations. Improper use tended X;`009`009`009 to crash the system and they are not necessary. TW X;`009`009`009 device is always NOMODEM. HANGUP works as you want X;`009`009`009 it to without the modem stuff. X;`009`009`009- Got rid of the BRDCST on/off stuff. It doesn't seem X;`009`009`009 to be necessary any more. It also had a bug in it X;`009`009`009 somewhere that caused the terminal to start off X;`009`009`009 NOBRDCST when it shouldn't. X;`009`009`009- General house-cleaning. Got rid of commented out X;`009`009`009 lines from VMS V3 version. Fixed up typos in X;`009`009`009 comments. X; X;`009Version V04-004 (10-Feb-1986) Kevin Carosso, Hughes Aircraft Co., S&CG X;`009`009`009Changed all references to PTDRIVER to TPDRIVER because X;`009`009`009DEC (bless their little hearts) invented the *#&#$& X;`009`009`009TU81 and use PTA0: now. X; X;`009Version V04-005 (3-Sep-1986) Kevin Carosso, Hughes Aircraft Co., S&CG X;`009`009`009Fixed bug whereby the sequence ^S followed by ^Y X;`009`009`009would cause a system hang. The fix is really in X;`009`009`009TWDRIVER. X; X;`009Version V04-006 (5-Dec-1986) Kevin Carosso, Hughes Aircraft Co., S&CG X;`009`009`009Fixed the infamous character munging bug. Turns X;`009`009`009out that in FDTWRITE we were enabling interrupts X;`009`009`009after doing the PUTNXT and before checking for X;`009`009`009a char. Now check for the character and then X;`009`009`009ENBINT after we've decided what to do. I assume X;`009`009`009UCB$B_TT_OUTYPE field was getting corrupted. X; X;`009Version V04-007 (10-JUL-1987) Kevin Carosso, Hughes Aircraft Co., S&CG X;`009`009`009Fix in TWDRIVER for timeouts. Don't bother X;`009`009`009clearing the TIM bit all the time in here now. X; X;`009`009`009Also, while we're in here, lets make the device X;`009`009`009acquire "NODE$" prefixes, since mailboxes do. X; X;`009Version V04-008`009(2-NOV-1987) Kevin Carosso, Network Research Co. X;`009`009`009In PY$FDTWRITE we were overwriting the status in X;`009`009`009R0 just before jumping to EXE$ABORTIO when something X;`009`009`009goes wrong. Don't POPR into R0, but into R1. We X;`009`009`009only care about what we POPR into R3 anyway. X; X;`009`009`009Fix thanks to Gerard K Newman @ San Diego X;`009`009`009Supercomputer Center. X; X;`009Version V05-001 Digital Equipment Corp. X;`009`009`009Add support for Symmetric Multiprocessing. X; X;`009Version`009V05-002`009Digital Equipment Corp. X;`009`009`009Modify PY$CLONE_INIT to make newly cloned X;`009`009`009owned by person requesting new device. X; X;`009Version`009V05-003`009Digital Equipment Corp. X;`009`009`009Modify PY$CLONE_INIT to change device protection X;`009`009`009to be S:RWLP,O:RWLP. X; X;`009Version`009V05-004`009Digital Equipment Corp X;`009`009`009Change TP driver names to TW. (TP driver it turns X;`009`009`009out, conflicted with the VAX/PSI terminal driver.) X;`009`009`009TWDRIVER and PYDRIVER are now registered with SQM X;`009`009`009so there will be no more conflicts. X; X;`009Version`009V05-005 Digital Equipment Corp X;`009`009`009If input stopped then exit PY$FDTWRITE immediately X;`009`009`009with reason of SS$_DATAOVERUN. If we detect input X;`009`009`009stopping while inserting data return with X;`009`009`009SS$_DATAOVERUN and number of bytes inserted. X; X;`009Version V05-006`009Digital Equipment Corp. X;`009`009`009Add CODE for sending an AST if PORT XON, PORT XOFF, X;`009`009`009and PORT SET_LINE routines are called. Also add X;`009`009`009SENSEMODE, and SENSECHAR routine for reading TW device X;`009`009`009characteristics. X; X;`009Version V05-006A Kevin Carosso @ Network Research Co. X;`009`009`009Conditionalize assembly for VMS V4 or V5. There X;`009`009`009is a magic symbol at the top that is commented X;`009`009`009out for VMS V5. X; X;`009Version V05-007A Kevin Carosso @ Network Research Co. X;`009`009`009Add a missing # on an immediate. X;`009`009`009Modify PY$FDTWRITE to allow writes larger than X;`009`009`00964K by using longword rather than word instructions. X;`009`009`009Make the conditional assembly for VMS V5 automatic X;`009`009`009driven off existence of SS$_INVLICENSE. X; X;-- X`012 X`009.PAGE X`009.SBTTL`009Declarations X X`009.LIBRARY`009/SYS$LIBRARY:LIB.MLB/ X X; X; External Definitions: X; X.NOCROSS X`009$CRBDEF`009`009`009`009; Define CRB X`009$CANDEF`009`009`009`009; Define cancel codes X`009$DDBDEF`009`009`009`009; DEFINE DDB X`009$DDTDEF`009`009`009`009; DEFINE DDT X`009$DEVDEF`009`009`009`009; DEVICE CHARACTERISTICS X`009$DYNDEF`009`009`009`009; Dynamic structure definitions X`009$IODEF`009`009`009`009; I/O Function Codes X`009$IRPDEF`009`009`009`009; IRP definitions X`009$JIBDEF`009`009`009`009; Define JIB offsets X`009$ORBDEF`009`009`009`009; Define ORB offsets X`009$PCBDEF`009`009`009`009; Define PCB X`009$PRDEF`009`009`009`009; Define PR X`009$SSDEF`009`009`009`009; DEFINE System Status X; X; If SS$_INVLICENSE exists, we must be building on V5. Go ahead and X; define our conditionals so we can build a V5 driver. X; X.IF`009DEFINED`009SS$_INVLICENSE X`009VMS_V5 = 1 X`009.PRINT`009`009; PYDRIVER -- Building VMS V5 compatible driver X.IF_FALSE X`009.PRINT`009`009; PYDRIVER -- Building VMS V4 compatible driver X.ENDC X X.IF`009DEFINED`009VMS_V5 X`009$SPLCODDEF`009`009`009; Spin lock code definitions X.ENDC X X`009$TTDEF`009`009`009`009; DEFINE TERMINAL TYPES X`009$TT2DEF`009`009`009`009; Define Extended Characteristics X`009$TTYDEF`009`009`009`009; DEFINE TERMINAL DRIVER SYMBOLS X`009$TTYDEFS`009`009`009; DEFINE TERMINAL DRIVER SYMBOLS X`009$TTYMACS`009`009`009; DEFINE TERMINAL DRIVER MACROS X`009$UCBDEF`009`009`009`009; DEFINE UCB X`009$VECDEF`009`009`009`009; DEFINE VECTOR FOR CRB X.CROSS X X; X; Local definitions X; X; QIO Argument list offsets X; XP1 = 0 XP2 = 4 XP3 = 8 XP4 = 12 XP5 = 16 XP6 = 20 X; X; New device class for control end X; XDC$_PY = ^XFF XDT$_PY = 0 X X; X; Definitions that follow the standard UCB fields for TW driver X; This will all probably have to be the same as the standard term X X`009$DEFINI`009UCB`009`009`009; Start of UCB definitions X X`009.=UCB$K_TT_LENGTH`009`009; Position at end of UCB X X$DEF`009UCB$L_TW_XUCB`009.BLKL`0091`009; UCB of corresponding X`009`009`009`009`009; control/application unit X`009`009`009`009`009; call X$DEF`009UCB$L_TW_XON_AST .BLKL`0091`009; AST list for XON event notification X$DEF`009UCB$L_TW_XOFF_AST .BLKL`0091`009; AST list for XOFF event notification X$DEF`009UCB$L_TW_SET_AST .BLKL`0091`009; AST list for notification of SET_LINE X$DEF`009UCB$K_TW_LEN`009`009`009; Size of UCB X X`009$DEFEND`009UCB`009`009`009; End of UCB definitions X X; X; Definitions that follow the standard UCB fields in PY devices X; X XBUFFER_SIZE = 32 X X`009$DEFINI UCB`009`009`009; Start of UCB definitions X `009.=UCB$K_LENGTH`009`009`009; position at end of UCB V$DEF`009UCB$L_PY_XUCB`009.BLKL 1`009`009; UCB of terminal part of pseudo termin Xal V$DEF`009UCB$T_PY_BUFFER`009.BLKB`009BUFFER_SIZE ; Buffer to store characters to X be transmitted X$DEF`009UCB$K_PY_LEN`009`009`009; Size of UCB X X `009$DEFEND UCB`009`009`009; end of UCB definitions X`012 X`009.PAGE X; X; LOCAL Storage X; X`009.PSECT $$$105_PROLOGUE X X`009.SBTTL`009Standard Tables X X; X; Driver prologue table: X; XPY$DPT:: X`009DPTAB`009-`009`009`009; Driver Prologue table X`009`009END = PY$END,-`009`009; End and offset to INIT's vectors X`009`009UCBSIZE = UCB$K_PY_LEN,-; Size of UCB X`009`009FLAGS=DPT$M_NOUNLOAD,-`009`009; Don't allow unload X`009`009ADAPTER=NULL,-`009`009`009; ADAPTER TYPE X`009`009NAME`009= PYDRIVER`009`009; Name of driver X`009DPT_STORE INIT X`009DPT_STORE UCB,UCB$W_UNIT_SEED,W,0`009; SET UNIT # SEED TO ZERO X X.IF`009NOT_DEFINED`009VMS_V5 X`009DPT_STORE UCB,UCB$B_FIPL,B,8 `009`009; FORK IPL X.IF_FALSE X`009DPT_STORE UCB,UCB$B_FLCK,B,SPL$C_IOLOCK8 ; FORK LOCK X.ENDC X X`009DPT_STORE UCB,UCB$W_STS,W,-`009`009; TEMPLATE device X`009`009`009<UCB$M_TEMPLATE> X`009DPT_STORE UCB,UCB$L_DEVCHAR,L,<-`009; Characteristics X`009`009`009DEV$M_REC!-`009`009; record oriented X`009`009`009DEV$M_AVL!-`009`009; available X`009`009`009DEV$M_IDV!-`009`009; input device X`009`009`009DEV$M_ODV>`009`009; output device X`009DPT_STORE UCB,UCB$L_DEVCHAR2,L, -`009`009; Device characteristics X`009`009`009<DEV$M_NNM>`009`009`009; prefix with "NODE$" X`009DPT_STORE UCB,UCB$B_DEVCLASS,B,DC$_PY X`009DPT_STORE UCB,UCB$B_DIPL,B,8`009`009; Device IPL = FIPL (no device) X`009DPT_STORE DDB,DDB$L_DDT,D,PY$DDT X X`009DPT_STORE REINIT X`009DPT_STORE CRB,CRB$L_INTD+VEC$L_INITIAL,D,PY$INITIAL`009; Controller X`009DPT_STORE END X`012 X`009.PAGE X`009.SBTTL Driver Dispatch table and function decision table X; X; Driver Dispatch table X; X`009DDTAB`009DEVNAM`009= PY,-`009`009`009; Device name X`009`009START`009= PY$STARTIO,-`009`009; Start I/O routine X`009`009FUNCTB`009= PY$FUNCTAB,-`009`009; The function table X`009`009CANCEL`009= PY$CANCEL,-`009`009; the cancel i/o routine X`009`009CLONEDUCB = PY$CLONE_INIT`009; Entry when template cloned. X; X; Function Decision table for PY devices X; XPY$FUNCTAB: X`009FUNCTAB`009,-`009`009`009; Legal Functions X`009`009<READLBLK,- X`009`009WRITELBLK,- X`009`009READVBLK,- X`009`009WRITEVBLK,- X`009`009READPBLK,- X`009`009WRITEPBLK,- X`009`009SETMODE,- X`009`009SETCHAR,- X`009`009SENSEMODE,- X`009`009SENSECHAR,- X`009`009> X`009FUNCTAB`009,-`009`009`009; Buffered I/O functions X`009`009<READLBLK,- X`009`009WRITELBLK,- X`009`009READVBLK,- X`009`009WRITEVBLK,- X`009`009READPBLK,- X`009`009WRITEPBLK,- X`009`009> X`009FUNCTAB`009PY$FDTREAD,<READLBLK,READVBLK,READPBLK> X`009FUNCTAB PY$FDTWRITE,<WRITELBLK,WRITEVBLK,WRITEPBLK> X`009FUNCTAB PY$FDTSET,<SETMODE,SETCHAR> X`009FUNCTAB PY$FDTSENSEM,<SENSEMODE> X`009FUNCTAB`009PY$FDTSENSEC,<SENSECHAR> X X X`009.SBTTL`009Local Storage - Name of companion device X XTWSTRING:`009.ASCII`009/TWA/ XTWLENGTH = . - TWSTRING X`012 X`009.PAGE X`009.SBTTL`009PY$FDTREAD - Function decision routine for PY control read X;++ X; PY$FDTREAD X; X; Functional Description: X; X;`009This routine is called from the function decision table dispatcher X; `009to process a read physical, read logical, read virtual I/O function. X; X;`009The function first verifies the caller's parameters, terminating X;`009the request with immediate success or error if necessary. X;`009A system buffer is allocated and its X;`009address is saved in the IRP. The caller's quota is updated, and X;`009the read request is queued to the driver for startup. X; X; Inputs: X; X;`009R0,R1,R2`009= Scratch X;`009R3`009`009= IRP Address X;`009R4`009`009= Address of PCB for current process X;`009R5`009`009= Device UCB address X;`009R6`009`009= Address of CCB X;`009R7`009`009= I/O function code X;`009R8`009`009= FDT Dispatch addr X;`009R9,R10,R11`009= Scratch X;`009AP`009`009= Address of function parameter list X;`009`009`009P1(AP) = Buffer Address X;`009`009`009P2(AP) = Buffer Size X; X; Outputs: X; X;`009R0,R1,R2,R11`009= Destroyed X;`009R3-R10,AP`009= Preserved (pickled) X;`009IRP$L_SVAPTE(R3)= Address of allocated system buffer X;`009IRP$W_BOFF(R3)`009= Requested byte count X; X;`009System Buffer: X;`009`009LONGWORD/0`009= Address of start of data= buff+12 X;`009`009LONGWORD/1`009= Address of user buffer X; X;-- XPY$FDTREAD:: X`009MOVZWL`009P2(AP),R1`009; Get buffer Size X`009BNEQ`00915$ X`009JMP`00910$`009`009; Is the size zero? If so, go do it easy. X15$:`009MOVL`009P1(AP),R0`009; Get buffer Address X`009JSB`009G^EXE$READCHK`009; Do we have access to the buffer X`009PUSHR`009#^M<R0,R3>`009; Save user buffer address and IRP address X`009ADDL`009#12,R1`009`009; Add 12 bytes for buffer header X X.IF`009NOT_DEFINED`009VMS_V5 X`009JSB`009G^EXE$BUFFRQUOTA`009; Is there enough buffer space left in X`009`009`009`009`009; the quota? X`009BLBC`009R0, 30$`009`009`009; Branch if insufficient quota X`009JSB`009G^EXE$ALLOCBUF`009`009; Allocate a system buffer X.IF_FALSE V`009JSB`009G^EXE$DEBIT_BYTCNT_ALO `009; Verify enough byte quota allocate buffe Xr X`009`009`009`009`009; and charge process for useage X.ENDC X X`009BLBC`009R0,30$`009`009`009; If error report it X`009POPR`009#^M<R0,R3>`009`009; Restore user buffer and irp address X`009MOVL`009R2,IRP$L_SVAPTE(R3)`009; Save address of buffer X`009MOVW`009R1,IRP$W_BOFF(R3)`009; and requested byte count X`009MOVZWL`009R1,R1`009`009`009; convert to longword count X X.IF`009NOT_DEFINED`009VMS_V5 X`009MOVL`009PCB$L_JIB(R4),R11`009; Get Jib address X`009SUBL`009R1,JIB$L_BYTCNT(R11)`009; Adjust quota count X.ENDC X X`009MOVAB`00912(R2),(R2)`009`009; Save addr of start of user data X`009MOVL`009R0,4(R2)`009`009; Save user buffer address in 2nd X`009`009`009`009`009; longword X`009JMP`009G^EXE$QIODRVPKT`009; Queue I/O packet to start I/O routine X; X; Did he request a read of zero bytes? X; X10$:`009MOVL`009#SS$_NORMAL,R0`009`009; Everything is ok -+-+-+-+-+ End of part 3 +-+-+-+-+-