mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-21 15:45:02 +00:00
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.
This commit is contained in:
parent
7872ac5542
commit
5da172697f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120505
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user