Commit 493c6685 authored by Russell King's avatar Russell King

[SERIAL] uart_get_divisor() and uart_get_baud_rate() takes termios.

Currently, uart_get_divisor() and uart_get_baud_rate() take a tty
structure.  We really want them to take a termios structure so we
can avoid passing a tty structure all  the way down to the low level
drivers.

In order to do this, we need to be able to convert a termios
structure to a numeric baud rate - we provide tty_termios_baud_rate() in
tty_io.c for this purpose.  It performs a subset of the
tty_get_baud_rate() functionality, but without any "alt_speed"
kludge.

We finally export uart_get_baud_rate() and uart_get_divisor() to for
low level drivers to use.  We now have all the functions in place
to support ports which want to have access to the real baud rate
rather than a divisor value.
parent 9f22efdf
...@@ -372,6 +372,8 @@ int tty_check_change(struct tty_struct * tty) ...@@ -372,6 +372,8 @@ int tty_check_change(struct tty_struct * tty)
return -ERESTARTSYS; return -ERESTARTSYS;
} }
EXPORT_SYMBOL(tty_check_change);
static ssize_t hung_up_tty_read(struct file * file, char * buf, static ssize_t hung_up_tty_read(struct file * file, char * buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -540,6 +542,8 @@ void tty_hangup(struct tty_struct * tty) ...@@ -540,6 +542,8 @@ void tty_hangup(struct tty_struct * tty)
schedule_work(&tty->hangup_work); schedule_work(&tty->hangup_work);
} }
EXPORT_SYMBOL(tty_hangup);
void tty_vhangup(struct tty_struct * tty) void tty_vhangup(struct tty_struct * tty)
{ {
#ifdef TTY_DEBUG_HANGUP #ifdef TTY_DEBUG_HANGUP
...@@ -556,6 +560,8 @@ int tty_hung_up_p(struct file * filp) ...@@ -556,6 +560,8 @@ int tty_hung_up_p(struct file * filp)
return (filp->f_op == &hung_up_tty_fops); return (filp->f_op == &hung_up_tty_fops);
} }
EXPORT_SYMBOL(tty_hung_up_p);
/* /*
* This function is typically called only by the session leader, when * This function is typically called only by the session leader, when
* it wants to disassociate itself from its controlling tty. * it wants to disassociate itself from its controlling tty.
...@@ -1886,6 +1892,8 @@ void do_SAK(struct tty_struct *tty) ...@@ -1886,6 +1892,8 @@ void do_SAK(struct tty_struct *tty)
schedule_work(&tty->SAK_work); schedule_work(&tty->SAK_work);
} }
EXPORT_SYMBOL(do_SAK);
/* /*
* This routine is called out of the software interrupt to flush data * This routine is called out of the software interrupt to flush data
* from the flip buffer to the line discipline. * from the flip buffer to the line discipline.
...@@ -1946,34 +1954,44 @@ static int baud_table[] = { ...@@ -1946,34 +1954,44 @@ static int baud_table[] = {
#endif #endif
}; };
static int n_baud_table = sizeof(baud_table)/sizeof(int); static int n_baud_table = ARRAY_SIZE(baud_table);
int tty_get_baud_rate(struct tty_struct *tty) int tty_termios_baud_rate(struct termios *termios)
{ {
unsigned int cflag, i; unsigned int cbaud = termios->c_cflag & CBAUD;
cflag = tty->termios->c_cflag; if (cbaud & CBAUDEX) {
cbaud &= ~CBAUDEX;
i = cflag & CBAUD; if (cbaud < 1 || cbaud + 15 > n_baud_table)
if (i & CBAUDEX) { termios->c_cflag &= ~CBAUDEX;
i &= ~CBAUDEX;
if (i < 1 || i+15 >= n_baud_table)
tty->termios->c_cflag &= ~CBAUDEX;
else else
i += 15; cbaud += 15;
} }
if (i==15 && tty->alt_speed) {
return baud_table[cbaud];
}
EXPORT_SYMBOL(tty_termios_baud_rate);
int tty_get_baud_rate(struct tty_struct *tty)
{
int baud = tty_termios_baud_rate(tty->termios);
if (baud == 38400 && tty->alt_speed) {
if (!tty->warned) { if (!tty->warned) {
printk(KERN_WARNING "Use of setserial/setrocket to " printk(KERN_WARNING "Use of setserial/setrocket to "
"set SPD_* flags is deprecated\n"); "set SPD_* flags is deprecated\n");
tty->warned = 1; tty->warned = 1;
} }
return(tty->alt_speed); baud = tty->alt_speed;
} }
return baud_table[i]; return baud;
} }
EXPORT_SYMBOL(tty_get_baud_rate);
void tty_flip_buffer_push(struct tty_struct *tty) void tty_flip_buffer_push(struct tty_struct *tty)
{ {
if (tty->low_latency) if (tty->low_latency)
......
...@@ -313,16 +313,16 @@ EXPORT_SYMBOL(uart_update_timeout); ...@@ -313,16 +313,16 @@ EXPORT_SYMBOL(uart_update_timeout);
/** /**
* uart_get_baud_rate - return baud rate for a particular port * uart_get_baud_rate - return baud rate for a particular port
* @port: uart_port structure describing the port in question. * @port: uart_port structure describing the port in question.
* @tty: the tty structure corresponding to this port * @termios: desired termios settings.
* *
* Decode the termios structure into a numeric baud rate, * Decode the termios structure into a numeric baud rate,
* taking account of the magic 38400 baud rate (with spd_* * taking account of the magic 38400 baud rate (with spd_*
* flags), and mapping the %B0 rate to 9600 baud. * flags), and mapping the %B0 rate to 9600 baud.
*/ */
static unsigned int unsigned int
uart_get_baud_rate(struct uart_port *port, struct tty_struct *tty) uart_get_baud_rate(struct uart_port *port, struct termios *termios)
{ {
unsigned int baud = tty_get_baud_rate(tty); unsigned int baud = tty_termios_baud_rate(termios);
/* /*
* The spd_hi, spd_vhi, spd_shi, spd_warp kludge... * The spd_hi, spd_vhi, spd_shi, spd_warp kludge...
...@@ -350,8 +350,10 @@ uart_get_baud_rate(struct uart_port *port, struct tty_struct *tty) ...@@ -350,8 +350,10 @@ uart_get_baud_rate(struct uart_port *port, struct tty_struct *tty)
return baud; return baud;
} }
static inline EXPORT_SYMBOL(uart_get_baud_rate);
unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud)
static inline unsigned int
uart_calculate_quot(struct uart_port *port, unsigned int baud)
{ {
unsigned int quot; unsigned int quot;
...@@ -369,7 +371,7 @@ unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud) ...@@ -369,7 +371,7 @@ unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud)
/** /**
* uart_get_divisor - return uart clock divisor * uart_get_divisor - return uart clock divisor
* @port: uart_port structure describing the port. * @port: uart_port structure describing the port.
* @tty: desired tty settings * @termios: desired termios settings
* @old_termios: the original port settings, or NULL * @old_termios: the original port settings, or NULL
* *
* Calculate the uart clock divisor for the port. If the * Calculate the uart clock divisor for the port. If the
...@@ -381,8 +383,8 @@ unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud) ...@@ -381,8 +383,8 @@ unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud)
* *
* If 9600 baud fails, we return a zero divisor. * If 9600 baud fails, we return a zero divisor.
*/ */
static unsigned int unsigned int
uart_get_divisor(struct uart_port *port, struct tty_struct *tty, uart_get_divisor(struct uart_port *port, struct termios *termios,
struct termios *old_termios) struct termios *old_termios)
{ {
unsigned int quot, try; unsigned int quot, try;
...@@ -391,7 +393,7 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty, ...@@ -391,7 +393,7 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
unsigned int baud; unsigned int baud;
/* Determine divisor based on baud rate */ /* Determine divisor based on baud rate */
baud = uart_get_baud_rate(port, tty); baud = uart_get_baud_rate(port, termios);
quot = uart_calculate_quot(port, baud); quot = uart_calculate_quot(port, baud);
if (quot) if (quot)
break; break;
...@@ -400,10 +402,9 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty, ...@@ -400,10 +402,9 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
* Oops, the quotient was zero. Try again with * Oops, the quotient was zero. Try again with
* the old baud rate if possible. * the old baud rate if possible.
*/ */
tty->termios->c_cflag &= ~CBAUD; termios->c_cflag &= ~CBAUD;
if (old_termios) { if (old_termios) {
tty->termios->c_cflag |= termios->c_cflag |= old_termios->c_cflag & CBAUD;
(old_termios->c_cflag & CBAUD);
old_termios = NULL; old_termios = NULL;
continue; continue;
} }
...@@ -412,43 +413,48 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty, ...@@ -412,43 +413,48 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
* As a last resort, if the quotient is zero, * As a last resort, if the quotient is zero,
* default to 9600 bps * default to 9600 bps
*/ */
tty->termios->c_cflag |= B9600; termios->c_cflag |= B9600;
} }
return quot; return quot;
} }
EXPORT_SYMBOL(uart_get_divisor);
static void static void
uart_change_speed(struct uart_info *info, struct termios *old_termios) uart_change_speed(struct uart_info *info, struct termios *old_termios)
{ {
struct tty_struct *tty = info->tty;
struct uart_port *port = info->port; struct uart_port *port = info->port;
unsigned int quot, cflag, bits, try; struct termios *termios;
unsigned int quot;
/* /*
* If we have no tty, termios, or the port does not exist, * If we have no tty, termios, or the port does not exist,
* then we can't set the parameters for this port. * then we can't set the parameters for this port.
*/ */
if (!info->tty || !info->tty->termios || port->type == PORT_UNKNOWN) if (!tty || !tty->termios || port->type == PORT_UNKNOWN)
return; return;
termios = tty->termios;
/* /*
* Set flags based on termios cflag * Set flags based on termios cflag
*/ */
cflag = info->tty->termios->c_cflag; if (termios->c_cflag & CRTSCTS)
quot = uart_get_divisor(port, tty, old_termios);
uart_update_timeout(port, cflag, quot);
if (cflag & CRTSCTS)
info->flags |= UIF_CTS_FLOW; info->flags |= UIF_CTS_FLOW;
else else
info->flags &= ~UIF_CTS_FLOW; info->flags &= ~UIF_CTS_FLOW;
if (cflag & CLOCAL)
if (termios->c_cflag & CLOCAL)
info->flags &= ~UIF_CHECK_CD; info->flags &= ~UIF_CHECK_CD;
else else
info->flags |= UIF_CHECK_CD; info->flags |= UIF_CHECK_CD;
port->ops->change_speed(port, cflag, info->tty->termios->c_iflag, quot); quot = uart_get_divisor(port, termios, old_termios);
uart_update_timeout(port, termios->c_cflag, quot);
port->ops->change_speed(port, termios->c_cflag, termios->c_iflag, quot);
} }
static inline void static inline void
......
...@@ -397,6 +397,7 @@ extern void do_SAK(struct tty_struct *tty); ...@@ -397,6 +397,7 @@ extern void do_SAK(struct tty_struct *tty);
extern void disassociate_ctty(int priv); extern void disassociate_ctty(int priv);
extern void tty_flip_buffer_push(struct tty_struct *tty); extern void tty_flip_buffer_push(struct tty_struct *tty);
extern int tty_get_baud_rate(struct tty_struct *tty); extern int tty_get_baud_rate(struct tty_struct *tty);
extern int tty_termios_baud_rate(struct termios *termios);
/* n_tty.c */ /* n_tty.c */
extern struct tty_ldisc tty_ldisc_N_TTY; extern struct tty_ldisc tty_ldisc_N_TTY;
......
...@@ -353,13 +353,8 @@ EXPORT_SYMBOL(generic_file_writev); ...@@ -353,13 +353,8 @@ EXPORT_SYMBOL(generic_file_writev);
EXPORT_SYMBOL(iov_shorten); EXPORT_SYMBOL(iov_shorten);
/* tty routines */ /* tty routines */
EXPORT_SYMBOL(tty_hangup);
EXPORT_SYMBOL(tty_wait_until_sent); EXPORT_SYMBOL(tty_wait_until_sent);
EXPORT_SYMBOL(tty_check_change);
EXPORT_SYMBOL(tty_hung_up_p);
EXPORT_SYMBOL(tty_flip_buffer_push); EXPORT_SYMBOL(tty_flip_buffer_push);
EXPORT_SYMBOL(tty_get_baud_rate);
EXPORT_SYMBOL(do_SAK);
/* filesystem registration */ /* filesystem registration */
EXPORT_SYMBOL(register_filesystem); EXPORT_SYMBOL(register_filesystem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment