From 7f114818d52199f9375644b3868683486b7b8660 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 1 Dec 2002 10:32:09 +0000 Subject: [SERIAL] Pass "iomap" base from probe modules Patch from Randolph Chung, slightly modified by rmk. When displaying the details of memory mapped serial ports, we want to show some sane base value. The cookie returned from ioremap can be meaningless to users (and developers), especially when the cookie could be a dynamically allocated virtual address. The more useful cookie is the value passed into ioremap. We already have support for handling this cookie internally - we haven't allowed the PCI probe module to hand it to the higher levels until now. --- include/linux/serial.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/serial.h b/include/linux/serial.h index d9d93ae8ad3b..b0469a236a13 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -48,6 +48,7 @@ struct serial_struct { unsigned char *iomem_base; unsigned short iomem_reg_shift; unsigned int port_high; + unsigned long iomap_base; /* cookie passed into ioremap */ int reserved[1]; }; -- cgit v1.2.3 From b1a5ffda2f93d79f9e9aa7f478edd6e732748075 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 1 Dec 2002 15:37:49 +0000 Subject: [SERIAL] Move custom_divisor from uart_state to uart_port. This is another step towards moving the divisor calculations into the low level drivers, thereby allowing the faster baud rates mentioned in the previous cset. Moving this field to uart_port means that the low level drivers do not have to know about the uart_state structure. --- drivers/serial/core.c | 12 ++++++------ include/linux/serial_core.h | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/serial/core.c b/drivers/serial/core.c index c51ffbdc349c..ad247096e6ed 100644 --- a/drivers/serial/core.c +++ b/drivers/serial/core.c @@ -309,7 +309,7 @@ unsigned int uart_calculate_quot(struct uart_info *info, unsigned int baud) /* Old HI/VHI/custom speed handling */ if (baud == 38400 && ((port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)) - quot = info->state->custom_divisor; + quot = port->custom_divisor; else quot = port->uartclk / (16 * baud); @@ -617,7 +617,7 @@ static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) tmp.baud_base = port->uartclk / 16; tmp.close_delay = state->close_delay; tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; + tmp.custom_divisor = port->custom_divisor; tmp.hub6 = port->hub6; tmp.io_type = port->iotype; tmp.iomem_reg_shift = port->regshift; @@ -672,7 +672,7 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) new_serial.type != port->type; old_flags = port->flags; - old_custom_divisor = state->custom_divisor; + old_custom_divisor = port->custom_divisor; if (!capable(CAP_SYS_ADMIN)) { retval = -EPERM; @@ -685,7 +685,7 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) goto exit; port->flags = ((port->flags & ~UPF_USR_MASK) | (new_serial.flags & UPF_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; + port->custom_divisor = new_serial.custom_divisor; goto check_and_exit; } @@ -777,7 +777,7 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) port->irq = new_serial.irq; port->uartclk = new_serial.baud_base * 16; port->flags = new_serial.flags & UPF_FLAGS; - state->custom_divisor = new_serial.custom_divisor; + port->custom_divisor = new_serial.custom_divisor; state->close_delay = new_serial.close_delay * HZ / 100; state->closing_wait = new_serial.closing_wait * HZ / 100; port->fifosize = new_serial.xmit_fifo_size; @@ -789,7 +789,7 @@ uart_set_info(struct uart_info *info, struct serial_struct *newinfo) goto exit; if (info->flags & UIF_INITIALIZED) { if (((old_flags ^ port->flags) & UPF_SPD_MASK) || - old_custom_divisor != state->custom_divisor) + old_custom_divisor != port->custom_divisor) uart_change_speed(info, NULL); } else retval = uart_startup(info, 1); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index fe25d0fa6b94..84e021607be9 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -186,6 +186,7 @@ struct uart_port { unsigned int timeout; /* character-based timeout */ unsigned int type; /* port type */ struct uart_ops *ops; + unsigned int custom_divisor; unsigned int line; /* port index */ unsigned long mapbase; /* for ioremap */ unsigned char hub6; /* this should be in the 8250 driver */ @@ -204,8 +205,6 @@ struct uart_state { #define USF_CLOSING_WAIT_INF (0) #define USF_CLOSING_WAIT_NONE (65535) - unsigned int custom_divisor; - int count; struct uart_info *info; struct uart_port *port; -- cgit v1.2.3 From 493c66851eb42271bdcbb5a092f1402bce146872 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 1 Dec 2002 16:38:04 +0000 Subject: [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. --- drivers/char/tty_io.c | 44 ++++++++++++++++++++++++++++------------- drivers/serial/core.c | 54 ++++++++++++++++++++++++++++----------------------- include/linux/tty.h | 1 + kernel/ksyms.c | 5 ----- 4 files changed, 62 insertions(+), 42 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index d693b48f47db..cf880e8cacae 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -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) diff --git a/drivers/serial/core.c b/drivers/serial/core.c index af35d6150054..118e92152fd6 100644 --- a/drivers/serial/core.c +++ b/drivers/serial/core.c @@ -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 diff --git a/include/linux/tty.h b/include/linux/tty.h index 81c8d745f708..11b82d2c98ae 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -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; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 092018c75a66..98093272d3e8 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -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); -- cgit v1.2.3