ian@sibyl.eleceng.ua.OZ (Ian Dall) (04/06/88)
There appears to be a bug in the code to impliment the TCSETA[F,W] code Sys5.2 rel 2. I would be interested to know if this bug is a) already known or b) fixed in later releases. According to the "termio" man pages "TCSETA Set the parameters associated with the terminal from the structure referenced by arg. The change is immediate. TCSETAW Wait for the output to drain before setting the new parameters. This form should be used when changing parameters that will affect output." The implication is that the converse of the last sentence holds. And that providing your change does not affect output post processing TCSETA should be fine. In practice this turns out not to be the case. I only have a binary licence which does include the hardware tt driver source but not the generic tt driver stuff. The hardware tt driver calls ttiocom and if it returns non zero goes and stuffs things in the DUART registers to set up baud rates no of stop bits etc. Not too surprisingly this tends to corrupt anything the DUART is in the process of outputing. Using adb on the kernal to find out what ttiocom does (remember I don't have the source) reveals that the code must be some thing like: ttiocom(.........) { . . . switch ( command ) case TCSETAW: case TCSETAF: ttywait(...); if (command == TCSETAF) ttyflush(....); case TCSETA: . . . /* code to get parameters from users area */ return(1); case TCGETA: . . . /* code to put parameters into users area */ break; case TCSBRK: . . . break; case TCXONC: . . . break; case TCFLSH: . . . break; return(0); } I contend that this code should only return 1 if the HARDWARE setup has changed. Many (most?) TCSETAs will NOT change the hardware setup. Something like replacing the "return (1);" with if ( old_c_cflag == c_cflag ) break; else return (1); should do the trick. Do later SysVs do this? Perhaps other hardware is less fussy and don't get upset by setting the hardware registers to the same as they already are. Here is a test program so you can see if your system exhibits this bug. If the output is garbled you have the bug. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by ian on Wed Apr 6 16:07:04 CST 1988 # Contents: checktermio.c echo x - checktermio.c sed 's/^@//' > "checktermio.c" <<'@//E*O*F checktermio.c//' #include <termio.h> #include <stdio.h> #define TSET TCSETA int kbd_count; char *kbd_ptr, kbd_buffer[256]; char longstring[] = "The quick brown fox jumped over the lazy dogs back and\ made him howl horribly.\n"; main() { register i; for (i=1; i < 20; i++) { printf(longstring); read_avail_input(); } } read_avail_input () { struct termio tnow, told; if (ioctl (fileno (stdin), TCGETA, &tnow) < 0) return; told = tnow; tnow.c_lflag &= ~ICANON; tnow.c_cc[VMIN] = 0; tnow.c_cc[VTIME] = 0; ioctl (fileno (stdin), TCSETA, &tnow); kbd_ptr = kbd_buffer; kbd_count = read (fileno (stdin), kbd_buffer, sizeof kbd_buffer); ioctl (fileno (stdin), TCSETA, &told); } @//E*O*F checktermio.c// chmod u=rw,g=r,o=r checktermio.c exit 0
geoff@desint.UUCP (Geoff Kuenning) (04/14/88)
In article <107@sibyl.eleceng.ua.OZ> ian@sibyl.OZ (Ian Dall) writes: > The hardware tt driver calls ttiocom and if it returns non zero goes and > stuffs things in the DUART registers to set up baud rates no of stop bits > etc. Not too surprisingly this tends to corrupt anything the DUART is in > the process of outputing. Your hardware driver is broken. The driver should *never* modify the DUART settings while characters are still in its output buffers. With most DUARTs, there is a way to tell whether the output buffers (usually two of them) are empty yet. Your code may have to loop, calling swtch() (and, I think, setrun()) until those two characters are sent. > I contend that this code should only return 1 if the HARDWARE setup has > changed. Many (most?) TCSETAs will NOT change the hardware setup. > > Something like replacing the "return (1);" with > > if ( old_c_cflag == c_cflag ) break; In general, it is not possible to predict what tty settings will change the hardware setup. On complex hardware, changing iflag or oflag could require changing the hardware. Conversely, on many DUARTs, not every bit in cflag requires a hardware change. I'd recommend changing the driver to keep track of the current hardware settings on each port, and to compare these with the new ones whenever the ioctl routine is called. If no change is needed, don't change the hardware unnecessarily. If something has changed, be sure to wait until the output buffers have drained before clobbering them. -- Geoff Kuenning geoff@ITcorp.com {uunet,trwrb}!desint!geoff