From 5da172697f8683ff3f14c9f13f5e7a78d93834a5 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Sat, 27 Sep 2003 11:13:59 +0000 Subject: [PATCH] Cleaned up and fixed setting of speeds in comparam(): - Removed conversion of a zero input speed to the output speed. This has been done better in ttioctl() since rev.1.108 of kern/tty.c almost 5 years ago. comparam() did the conversion incompletely for the case where the output speed is also zero. It had complications to avoid using zero speeds, but would still have used a zero input speed for setting watermarks if kern/tty.c had passed one. - Never permit the input speed to be different from the output speed. There was no validity check on the input speed for the case of a zero output speed. Then we didn't change the physical speeds, but we used the unvalidated input speed for setting watermarks and didn't return an error, so ttioctl() stored the unvalidated input speed in the tty struct where it could cause problems later. - Removed complications that were to avoid using a divisor of 0. The divisor is now always valid if the speed is accepted. --- sys/dev/sio/sio.c | 51 +++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index cfc87ed70255..e8f88a831522 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -2217,24 +2217,16 @@ comparam(tp, t) if (com == NULL) return (ENODEV); - /* do historical conversions */ - if (t->c_ispeed == 0) - t->c_ispeed = t->c_ospeed; - /* check requested parameters */ - if (t->c_ospeed == 0) - divisor = 0; - else { - if (t->c_ispeed != t->c_ospeed) - return (EINVAL); - divisor = siodivisor(com->rclk, t->c_ispeed); - if (divisor == 0) - return (EINVAL); - } + if (t->c_ispeed != (t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed)) + return (EINVAL); + divisor = siodivisor(com->rclk, t->c_ispeed); + if (divisor == 0) + return (EINVAL); /* parameters are OK, convert them to the com struct and the device */ s = spltty(); - if (divisor == 0) + if (t->c_ospeed == 0) (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ else (void)commctl(com, TIOCM_DTR, DMBIS); @@ -2261,7 +2253,7 @@ comparam(tp, t) if (cflag & CSTOPB) cfcr |= CFCR_STOPB; - if (com->hasfifo && divisor != 0) { + if (com->hasfifo) { /* * Use a fifo trigger level low enough so that the input * latency from the fifo is less than about 16 msec and @@ -2276,7 +2268,7 @@ comparam(tp, t) * without producing silo overflow errors. */ com->fifo_image = com->unit == siotsunit ? 0 - : t->c_ospeed <= 4800 + : t->c_ispeed <= 4800 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH; #ifdef COM_ESP /* @@ -2297,21 +2289,18 @@ comparam(tp, t) */ (void) siosetwater(com, t->c_ispeed); - if (divisor != 0) { - sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB); - /* - * Only set the divisor registers if they would change, - * since on some 16550 incompatibles (UMC8669F), setting - * them while input is arriving them loses sync until - * data stops arriving. - */ - dlbl = divisor & 0xFF; - if (sio_getreg(com, com_dlbl) != dlbl) - sio_setreg(com, com_dlbl, dlbl); - dlbh = divisor >> 8; - if (sio_getreg(com, com_dlbh) != dlbh) - sio_setreg(com, com_dlbh, dlbh); - } + sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB); + /* + * Only set the divisor registers if they would change, since on + * some 16550 incompatibles (UMC8669F), setting them while input + * is arriving loses sync until data stops arriving. + */ + dlbl = divisor & 0xFF; + if (sio_getreg(com, com_dlbl) != dlbl) + sio_setreg(com, com_dlbl, dlbl); + dlbh = divisor >> 8; + if (sio_getreg(com, com_dlbh) != dlbh) + sio_setreg(com, com_dlbh, dlbh); if (!(tp->t_state & TS_TTSTOP)) com->state |= CS_TTGO;