summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@flint.arm.linux.org.uk>2003-01-08 23:21:39 +0000
committerRussell King <rmk@flint.arm.linux.org.uk>2003-01-08 23:21:39 +0000
commit077746a2ce37e3cb7d3fd7aa439e7ef52c8b6112 (patch)
treebf0e3831ea91919d61d1674a3e0f8f63f31b2ec3
parent994ee212940a805bbbca18f9866dfea64d934a6e (diff)
[SERIAL] Restrict the baud rates returnable from uart_get_baud_rate()
Supply the old termios, along with the max and min acceptable baud rate to uart_get_baud_rate(). uart_get_baud_rate() will now try to find a baud rate that satisfies the max and min constraint out of (requested rate, old rate, 9600 baud). We remove the code which performed a similar act in uart_get_divisor() and pass an appropriate min and max baud rate to uart_get_baud_rate() based on the UART clock rate.
-rw-r--r--drivers/serial/core.c122
-rw-r--r--include/linux/serial_core.h5
2 files changed, 65 insertions, 62 deletions
diff --git a/drivers/serial/core.c b/drivers/serial/core.c
index 4d6d0e72954b..02bc77240419 100644
--- a/drivers/serial/core.c
+++ b/drivers/serial/core.c
@@ -314,40 +314,68 @@ EXPORT_SYMBOL(uart_update_timeout);
* uart_get_baud_rate - return baud rate for a particular port
* @port: uart_port structure describing the port in question.
* @termios: desired termios settings.
+ * @old: old termios (or NULL)
+ * @min: minimum acceptable baud rate
+ * @max: maximum acceptable baud rate
*
* Decode the termios structure into a numeric baud rate,
* taking account of the magic 38400 baud rate (with spd_*
* flags), and mapping the %B0 rate to 9600 baud.
*/
unsigned int
-uart_get_baud_rate(struct uart_port *port, struct termios *termios)
+uart_get_baud_rate(struct uart_port *port, struct termios *termios,
+ struct termios *old, unsigned int min, unsigned int max)
{
- unsigned int baud = tty_termios_baud_rate(termios);
+ unsigned int try, baud, altbaud = 38400;
+ unsigned int flags = port->flags & UPF_SPD_MASK;
- /*
- * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
- * Die! Die! Die!
- */
- if (baud == 38400) {
- unsigned int flags = port->flags & UPF_SPD_MASK;
-
- if (flags == UPF_SPD_HI)
- baud = 57600;
- if (flags == UPF_SPD_VHI)
- baud = 115200;
- if (flags == UPF_SPD_SHI)
- baud = 230400;
- if (flags == UPF_SPD_WARP)
- baud = 460800;
- }
+ if (flags == UPF_SPD_HI)
+ altbaud = 57600;
+ if (flags == UPF_SPD_VHI)
+ altbaud = 115200;
+ if (flags == UPF_SPD_SHI)
+ altbaud = 230400;
+ if (flags == UPF_SPD_WARP)
+ altbaud = 460800;
- /*
- * Special case: B0 rate.
- */
- if (baud == 0)
- baud = 9600;
+ for (try = 0; try < 2; try++) {
+ baud = tty_termios_baud_rate(termios);
+
+ /*
+ * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
+ * Die! Die! Die!
+ */
+ if (baud == 38400)
+ baud = altbaud;
+
+ /*
+ * Special case: B0 rate.
+ */
+ if (baud == 0)
+ baud = 9600;
+
+ if (baud >= min && baud <= max)
+ return baud;
+
+ /*
+ * Oops, the quotient was zero. Try again with
+ * the old baud rate if possible.
+ */
+ termios->c_cflag &= ~CBAUD;
+ if (old) {
+ termios->c_cflag |= old->c_cflag & CBAUD;
+ old = NULL;
+ continue;
+ }
- return baud;
+ /*
+ * As a last resort, if the quotient is zero,
+ * default to 9600 bps
+ */
+ termios->c_cflag |= B9600;
+ }
+
+ return 0;
}
EXPORT_SYMBOL(uart_get_baud_rate);
@@ -355,16 +383,6 @@ EXPORT_SYMBOL(uart_get_baud_rate);
static inline unsigned int
uart_calculate_quot(struct uart_port *port, unsigned int baud)
{
- unsigned int quot;
-
- /*
- * Old custom speed handling.
- */
- if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
- quot = port->custom_divisor;
- else
- quot = port->uartclk / (16 * baud);
-
return quot;
}
@@ -387,34 +405,18 @@ unsigned int
uart_get_divisor(struct uart_port *port, struct termios *termios,
struct termios *old_termios)
{
- unsigned int quot, try;
+ unsigned int quot, baud, max = port->uartclk / 16;
- for (try = 0; try < 3; try ++) {
- unsigned int baud;
-
- /* Determine divisor based on baud rate */
- baud = uart_get_baud_rate(port, termios);
- quot = uart_calculate_quot(port, baud);
- if (quot)
- return quot;
-
- /*
- * Oops, the quotient was zero. Try again with
- * the old baud rate if possible.
- */
- termios->c_cflag &= ~CBAUD;
- if (old_termios) {
- termios->c_cflag |= old_termios->c_cflag & CBAUD;
- old_termios = NULL;
- continue;
- }
+ /* Determine divisor based on baud rate */
+ baud = uart_get_baud_rate(port, termios, old_termios, 0, max);
- /*
- * As a last resort, if the quotient is zero,
- * default to 9600 bps
- */
- termios->c_cflag |= B9600;
- }
+ /*
+ * Old custom speed handling.
+ */
+ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
+ quot = port->custom_divisor;
+ else
+ quot = port->uartclk / (16 * baud);
return quot;
}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 58fe38afbd8e..41b764e48f77 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -280,8 +280,9 @@ void uart_write_wakeup(struct uart_port *port);
*/
void uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int quot);
-unsigned int uart_get_baud_rate(struct uart_port *port,
- struct termios *termios);
+unsigned int uart_get_baud_rate(struct uart_port *port, struct termios *termios
+ struct termios *old, unsigned int min,
+ unsigned int max);
unsigned int uart_get_divisor(struct uart_port *port, struct termios *termios,
struct termios *old_termios);