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)
return -ERESTARTSYS;
}
EXPORT_SYMBOL(tty_check_change);
static ssize_t hung_up_tty_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
......@@ -540,6 +542,8 @@ void tty_hangup(struct tty_struct * tty)
schedule_work(&tty->hangup_work);
}
EXPORT_SYMBOL(tty_hangup);
void tty_vhangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
......@@ -556,6 +560,8 @@ int tty_hung_up_p(struct file * filp)
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
* it wants to disassociate itself from its controlling tty.
......@@ -1886,6 +1892,8 @@ void do_SAK(struct tty_struct *tty)
schedule_work(&tty->SAK_work);
}
EXPORT_SYMBOL(do_SAK);
/*
* This routine is called out of the software interrupt to flush data
* from the flip buffer to the line discipline.
......@@ -1946,34 +1954,44 @@ static int baud_table[] = {
#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 (i & CBAUDEX) {
i &= ~CBAUDEX;
if (i < 1 || i+15 >= n_baud_table)
tty->termios->c_cflag &= ~CBAUDEX;
if (cbaud < 1 || cbaud + 15 > n_baud_table)
termios->c_cflag &= ~CBAUDEX;
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) {
printk(KERN_WARNING "Use of setserial/setrocket to "
"set SPD_* flags is deprecated\n");
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)
{
if (tty->low_latency)
......
......@@ -313,16 +313,16 @@ 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.
* @tty: the tty structure corresponding to this port
* @termios: desired termios settings.
*
* 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.
*/
static unsigned int
uart_get_baud_rate(struct uart_port *port, struct tty_struct *tty)
unsigned int
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...
......@@ -350,8 +350,10 @@ uart_get_baud_rate(struct uart_port *port, struct tty_struct *tty)
return baud;
}
static inline
unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud)
EXPORT_SYMBOL(uart_get_baud_rate);
static inline unsigned int
uart_calculate_quot(struct uart_port *port, unsigned int baud)
{
unsigned int quot;
......@@ -369,7 +371,7 @@ unsigned int uart_calculate_quot(struct uart_port *port, unsigned int baud)
/**
* uart_get_divisor - return uart clock divisor
* @port: uart_port structure describing the port.
* @tty: desired tty settings
* @termios: desired termios settings
* @old_termios: the original port settings, or NULL
*
* 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)
*
* If 9600 baud fails, we return a zero divisor.
*/
static unsigned int
uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
unsigned int
uart_get_divisor(struct uart_port *port, struct termios *termios,
struct termios *old_termios)
{
unsigned int quot, try;
......@@ -391,7 +393,7 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
unsigned int baud;
/* 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);
if (quot)
break;
......@@ -400,10 +402,9 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
* Oops, the quotient was zero. Try again with
* the old baud rate if possible.
*/
tty->termios->c_cflag &= ~CBAUD;
termios->c_cflag &= ~CBAUD;
if (old_termios) {
tty->termios->c_cflag |=
(old_termios->c_cflag & CBAUD);
termios->c_cflag |= old_termios->c_cflag & CBAUD;
old_termios = NULL;
continue;
}
......@@ -412,43 +413,48 @@ uart_get_divisor(struct uart_port *port, struct tty_struct *tty,
* As a last resort, if the quotient is zero,
* default to 9600 bps
*/
tty->termios->c_cflag |= B9600;
termios->c_cflag |= B9600;
}
return quot;
}
EXPORT_SYMBOL(uart_get_divisor);
static void
uart_change_speed(struct uart_info *info, struct termios *old_termios)
{
struct tty_struct *tty = info->tty;
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,
* 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;
termios = tty->termios;
/*
* Set flags based on termios cflag
*/
cflag = info->tty->termios->c_cflag;
quot = uart_get_divisor(port, tty, old_termios);
uart_update_timeout(port, cflag, quot);
if (cflag & CRTSCTS)
if (termios->c_cflag & CRTSCTS)
info->flags |= UIF_CTS_FLOW;
else
info->flags &= ~UIF_CTS_FLOW;
if (cflag & CLOCAL)
if (termios->c_cflag & CLOCAL)
info->flags &= ~UIF_CHECK_CD;
else
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
......
......@@ -397,6 +397,7 @@ extern void do_SAK(struct tty_struct *tty);
extern void disassociate_ctty(int priv);
extern void tty_flip_buffer_push(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 */
extern struct tty_ldisc tty_ldisc_N_TTY;
......
......@@ -353,13 +353,8 @@ EXPORT_SYMBOL(generic_file_writev);
EXPORT_SYMBOL(iov_shorten);
/* tty routines */
EXPORT_SYMBOL(tty_hangup);
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_get_baud_rate);
EXPORT_SYMBOL(do_SAK);
/* filesystem registration */
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