|
From: James S. <jsi...@us...> - 2001-12-13 04:46:55
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/serial
In directory usw-pr-cvs1:/tmp/cvs-serv2658/drivers/serial
Modified Files:
serial_21285.c serial_8250.c serial_8250.h serial_8250_pci.c
serial_8250_pnp.c serial_amba.c serial_anakin.c
serial_clps711x.c serial_core.c serial_sa1100.c
serial_uart00.c
Log Message:
More serial driver updates.
Index: serial_21285.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_21285.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- serial_21285.c 2001/11/01 21:38:35 1.6
+++ serial_21285.c 2001/12/13 04:46:52 1.7
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/console.h>
+#include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -39,378 +40,325 @@
#define SERIAL_21285_AUXNAME "cuafb"
#define SERIAL_21285_AUXMAJOR 205
#define SERIAL_21285_AUXMINOR 4
-
-#ifdef CONFIG_SERIAL_21285_OLD
-#include <asm/mach-types.h>
-/*
- * Compatability with a mistake made a long time ago.
- * Note - the use of "ttyI", "/dev/ttyS0" and major/minor 5,64
- * is HIGHLY DEPRECIATED, and will be removed in the 2.5
- * kernel series.
- * -- rmk 15/04/2000
- */
-#define SERIAL_21285_OLD_NAME "ttyI"
-#define SERIAL_21285_OLD_MAJOR TTY_MAJOR
-#define SERIAL_21285_OLD_MINOR 64
-static struct tty_driver rs285_old_driver;
-#endif
+#define RXSTAT_DUMMY_READ 0x80000000
+#define RXSTAT_FRAME (1 << 0)
+#define RXSTAT_PARITY (1 << 1)
+#define RXSTAT_OVERRUN (1 << 2)
+#define RXSTAT_ANYERR (RXSTAT_FRAME|RXSTAT_PARITY|RXSTAT_OVERRUN)
-static struct tty_driver rs285_driver, callout_driver;
-static int rs285_refcount;
-static struct tty_struct *rs285_table[1];
+#define H_UBRLCR_BREAK (1 << 0)
+#define H_UBRLCR_PARENB (1 << 1)
+#define H_UBRLCR_PAREVN (1 << 2)
+#define H_UBRLCR_STOPB (1 << 3)
+#define H_UBRLCR_FIFO (1 << 4)
-static struct termios *rs285_termios[1];
-static struct termios *rs285_termios_locked[1];
+static struct tty_driver normal, callout;
+static struct tty_struct *serial21285_table[1];
+static struct termios *serial21285_termios[1];
+static struct termios *serial21285_termios_locked[1];
+static const char serial21285_name[] = "Footbridge UART";
-static char wbuf[1000], *putp = wbuf, *getp = wbuf, x_char;
-static struct tty_struct *rs285_tty;
-static int rs285_use_count;
+/*
+ * The documented expression for selecting the divisor is:
+ * BAUD_BASE / baud - 1
+ * However, typically BAUD_BASE is not divisible by baud, so
+ * we want to select the divisor that gives us the minimum
+ * error. Therefore, we want:
+ * int(BAUD_BASE / baud - 0.5) ->
+ * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
+ * int((BAUD_BASE - (baud >> 1)) / baud)
+ */
-static int rs285_write_room(struct tty_struct *tty)
+static void serial21285_stop_tx(struct uart_port *port, u_int from_tty)
{
- return putp >= getp ? (sizeof(wbuf) - (long) putp + (long) getp) : ((long) getp - (long) putp - 1);
+ disable_irq(IRQ_CONTX);
}
-static void rs285_rx_int(int irq, void *dev_id, struct pt_regs *regs)
+static void serial21285_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
{
- if (!rs285_tty) {
- disable_irq(IRQ_CONRX);
- return;
- }
- while (!(*CSR_UARTFLG & 0x10)) {
- int ch, flag;
- ch = *CSR_UARTDR;
- flag = *CSR_RXSTAT;
- if (flag & 4)
- tty_insert_flip_char(rs285_tty, 0, TTY_OVERRUN);
- if (flag & 2)
- flag = TTY_PARITY;
- else if (flag & 1)
- flag = TTY_FRAME;
- tty_insert_flip_char(rs285_tty, ch, flag);
- }
- tty_flip_buffer_push(rs285_tty);
+ if (nonempty)
+ enable_irq(IRQ_CONTX);
}
-static void rs285_send_xchar(struct tty_struct *tty, char ch)
+static void serial21285_stop_rx(struct uart_port *port)
{
- x_char = ch;
- enable_irq(IRQ_CONTX);
+ disable_irq(IRQ_CONRX);
}
-static void rs285_throttle(struct tty_struct *tty)
+static void serial21285_enable_ms(struct uart_port *port)
{
- if (I_IXOFF(tty))
- rs285_send_xchar(tty, STOP_CHAR(tty));
}
-static void rs285_unthrottle(struct tty_struct *tty)
+static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
{
- if (I_IXOFF(tty)) {
- if (x_char)
- x_char = 0;
- else
- rs285_send_xchar(tty, START_CHAR(tty));
- }
-}
+ struct uart_info *info = dev_id;
+ struct uart_port *port = info->port;
+ struct tty_struct *tty = info->tty;
+ unsigned int status, ch, rxs, max_count = 256;
-static void rs285_tx_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- while (!(*CSR_UARTFLG & 0x20)) {
- if (x_char) {
- *CSR_UARTDR = x_char;
- x_char = 0;
- continue;
+ status = *CSR_UARTFLG;
+ while (status & 0x10 && max_count--) {
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty->flip.tqueue.routine((void *)tty);
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+ return;
+ }
}
- if (putp == getp) {
- disable_irq(IRQ_CONTX);
- break;
+
+ ch = *CSR_UARTDR;
+
+ *tty->flip.char_buf_ptr = ch;
+ *tty->flip.flag_buf_ptr = TTY_NORMAL;
+ port->icount.rx++;
+
+ rxs = *CSR_RXSTAT | RXSTAT_DUMMY_READ;
+ if (rxs & RXSTAT_ANYERR) {
+ if (rxs & RXSTAT_PARITY)
+ port->icount.parity++;
+ else if (rxs & RXSTAT_FRAME)
+ port->icount.frame++;
+ if (rxs & RXSTAT_OVERRUN)
+ port->icount.overrun++;
+
+ rxs &= port->read_status_mask;
+
+ if (rxs & RXSTAT_PARITY)
+ *tty->flip.flag_buf_ptr = TTY_PARITY;
+ else if (rxs & RXSTAT_FRAME)
+ *tty->flip.flag_buf_ptr = TTY_FRAME;
}
- *CSR_UARTDR = *getp;
- if (++getp >= wbuf + sizeof(wbuf))
- getp = wbuf;
+
+ if ((rxs & port->ignore_status_mask) == 0) {
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ }
+ if ((rxs & RXSTAT_OVERRUN) &&
+ tty->flip.count < TTY_FLIPBUF_SIZE) {
+ /*
+ * Overrun is special, since it's reported
+ * immediately, and doesn't affect the current
+ * character.
+ */
+ *tty->flip.char_buf_ptr++ = 0;
+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ tty->flip.count++;
+ }
+ status = *CSR_UARTFLG;
}
- if (rs285_tty)
- wake_up_interruptible(&rs285_tty->write_wait);
+ tty_flip_buffer_push(tty);
}
-static inline int rs285_xmit(int ch)
+static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs)
{
- if (putp + 1 == getp || (putp + 1 == wbuf + sizeof(wbuf) && getp == wbuf))
- return 0;
- *putp = ch;
- if (++putp >= wbuf + sizeof(wbuf))
- putp = wbuf;
- enable_irq(IRQ_CONTX);
- return 1;
+ struct uart_info *info = dev_id;
+ struct uart_port *port = info->port;
+ int count = 256;
+
+ if (port->x_char) {
+ *CSR_UARTDR = port->x_char;
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+ if (info->xmit.head == info->xmit.tail
+ || info->tty->stopped
+ || info->tty->hw_stopped) {
+ serial21285_stop_tx(port, 0);
+ return;
+ }
+
+ do {
+ *CSR_UARTDR = info->xmit.buf[info->xmit.tail];
+ info->xmit.tail = (info->xmit.tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (info->xmit.head == info->xmit.tail)
+ break;
+ } while (--count > 0 && !(*CSR_UARTFLG & 0x20));
+
+ if (CIRC_CNT(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) <
+ WAKEUP_CHARS)
+ uart_event(info, EVT_WRITE_WAKEUP);
+
+ if (info->xmit.head == info->xmit.tail)
+ serial21285_stop_tx(port, 0);
}
-static int rs285_write(struct tty_struct *tty, int from_user,
- const u_char * buf, int count)
+static u_int serial21285_tx_empty(struct uart_port *port)
{
- int i;
+ return (*CSR_UARTFLG & 8) ? 0 : TIOCSER_TEMT;
+}
- if (from_user && verify_area(VERIFY_READ, buf, count))
- return -EINVAL;
+/* no modem control lines */
+static u_int serial21285_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
- for (i = 0; i < count; i++) {
- char ch;
- if (from_user)
- __get_user(ch, buf + i);
- else
- ch = buf[i];
- if (!rs285_xmit(ch))
- break;
- }
- return i;
+static void serial21285_set_mctrl(struct uart_port *port, u_int mctrl)
+{
}
-static void rs285_put_char(struct tty_struct *tty, u_char ch)
+static void serial21285_break_ctl(struct uart_port *port, int break_state)
{
- rs285_xmit(ch);
+ u_int h_lcr;
+
+ h_lcr = *CSR_H_UBRLCR;
+ if (break_state)
+ h_lcr |= H_UBRLCR_BREAK;
+ else
+ h_lcr &= ~H_UBRLCR_BREAK;
+ *CSR_H_UBRLCR = h_lcr;
}
-static int rs285_chars_in_buffer(struct tty_struct *tty)
+static int serial21285_startup(struct uart_port *port, struct uart_info *info)
{
- return sizeof(wbuf) - rs285_write_room(tty);
+ int ret;
+
+ ret = request_irq(IRQ_CONRX, serial21285_rx_chars, 0,
+ serial21285_name, info);
+ if (ret == 0) {
+ ret = request_irq(IRQ_CONTX, serial21285_tx_chars, 0,
+ serial21285_name, info);
+ if (ret)
+ free_irq(IRQ_CONRX, info);
+ }
+ return ret;
}
-static void rs285_flush_buffer(struct tty_struct *tty)
+static void serial21285_shutdown(struct uart_port *port, struct uart_info *info)
{
- disable_irq(IRQ_CONTX);
- putp = getp = wbuf;
- if (x_char)
- enable_irq(IRQ_CONTX);
+ free_irq(IRQ_CONTX, info);
+ free_irq(IRQ_CONRX, info);
}
-static inline void rs285_set_cflag(int cflag)
+static void
+serial21285_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
{
- int h_lcr, baud, quot;
+ u_int h_lcr;
switch (cflag & CSIZE) {
- case CS5:
- h_lcr = 0x10;
- break;
- case CS6:
- h_lcr = 0x30;
- break;
- case CS7:
- h_lcr = 0x50;
- break;
- default: /* CS8 */
- h_lcr = 0x70;
- break;
-
+ case CS5: h_lcr = 0x00; break;
+ case CS6: h_lcr = 0x20; break;
+ case CS7: h_lcr = 0x40; break;
+ default: /* CS8 */ h_lcr = 0x60; break;
}
- if (cflag & CSTOPB)
- h_lcr |= 0x08;
- if (cflag & PARENB)
- h_lcr |= 0x02;
- if (!(cflag & PARODD))
- h_lcr |= 0x04;
- switch (cflag & CBAUD) {
- case B200: baud = 200; break;
- case B300: baud = 300; break;
- case B1200: baud = 1200; break;
- case B1800: baud = 1800; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- default:
- case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
+ if (cflag & CSTOPB)
+ h_lcr |= H_UBRLCR_STOPB;
+ if (cflag & PARENB) {
+ h_lcr |= H_UBRLCR_PARENB;
+ if (!(cflag & PARODD))
+ h_lcr |= H_UBRLCR_PAREVN;
}
+ if (port->fifosize)
+ h_lcr |= H_UBRLCR_FIFO;
+
+ port->read_status_mask = RXSTAT_OVERRUN;
+ if (iflag & INPCK)
+ port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
+
/*
- * The documented expression for selecting the divisor is:
- * BAUD_BASE / baud - 1
- * However, typically BAUD_BASE is not divisible by baud, so
- * we want to select the divisor that gives us the minimum
- * error. Therefore, we want:
- * int(BAUD_BASE / baud - 0.5) ->
- * int(BAUD_BASE / baud - (baud >> 1) / baud) ->
- * int((BAUD_BASE - (baud >> 1)) / baud)
+ * Characters to ignore
*/
- quot = (BAUD_BASE - (baud >> 1)) / baud;
+ port->ignore_status_mask = 0;
+ if (iflag & IGNPAR)
+ port->ignore_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
+ if (iflag & IGNBRK && iflag & IGNPAR)
+ port->ignore_status_mask |= RXSTAT_OVERRUN;
+ /*
+ * Ignore all characters if CREAD is not set.
+ */
+ if ((cflag & CREAD) == 0)
+ port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+
*CSR_UARTCON = 0;
*CSR_L_UBRLCR = quot & 0xff;
*CSR_M_UBRLCR = (quot >> 8) & 0x0f;
*CSR_H_UBRLCR = h_lcr;
*CSR_UARTCON = 1;
}
-
-static void rs285_set_termios(struct tty_struct *tty, struct termios *old)
-{
- if (old && tty->termios->c_cflag == old->c_cflag)
- return;
- rs285_set_cflag(tty->termios->c_cflag);
-}
-
-static void rs285_stop(struct tty_struct *tty)
+static const char *serial21285_type(struct uart_port *port)
{
- disable_irq(IRQ_CONTX);
+ return port->type == PORT_21285 ? "DC21285" : NULL;
}
-static void rs285_start(struct tty_struct *tty)
+static void serial21285_release_port(struct uart_port *port)
{
- enable_irq(IRQ_CONTX);
+ release_mem_region(port->mapbase, 32);
}
-static void rs285_wait_until_sent(struct tty_struct *tty, int timeout)
+static int serial21285_request_port(struct uart_port *port)
{
- int orig_jiffies = jiffies;
- while (*CSR_UARTFLG & 8) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
- set_current_state(TASK_RUNNING);
+ return request_mem_region(port->mapbase, 32, serial21285_name)
+ != NULL ? 0 : -EBUSY;
}
-static int rs285_open(struct tty_struct *tty, struct file *filp)
+static void serial21285_config_port(struct uart_port *port, int flags)
{
- int line;
-
- MOD_INC_USE_COUNT;
- line = MINOR(tty->device) - tty->driver.minor_start;
- if (line) {
- MOD_DEC_USE_COUNT;
- return -ENODEV;
- }
-
- tty->driver_data = NULL;
- if (!rs285_tty)
- rs285_tty = tty;
-
- enable_irq(IRQ_CONRX);
- rs285_use_count++;
- return 0;
+ if (flags & UART_CONFIG_TYPE && serial21285_request_port(port) == 0)
+ port->type = PORT_21285;
}
-static void rs285_close(struct tty_struct *tty, struct file *filp)
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int serial21285_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- if (!--rs285_use_count) {
- rs285_wait_until_sent(tty, 0);
- disable_irq(IRQ_CONRX);
- disable_irq(IRQ_CONTX);
- rs285_tty = NULL;
- }
- MOD_DEC_USE_COUNT;
+ int ret = 0;
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_21285)
+ ret = -EINVAL;
+ if (ser->irq != NO_IRQ)
+ ret = -EINVAL;
+ if (ser->baud_base != port->uartclk / 16)
+ ret = -EINVAL;
+ return ret;
}
-
-static int __init rs285_init(void)
-{
- int baud = B9600;
- if (machine_is_personal_server())
- baud = B57600;
-
- rs285_driver.magic = TTY_DRIVER_MAGIC;
- rs285_driver.driver_name = "serial_21285";
- rs285_driver.name = SERIAL_21285_NAME;
- rs285_driver.major = SERIAL_21285_MAJOR;
- rs285_driver.minor_start = SERIAL_21285_MINOR;
- rs285_driver.num = 1;
- rs285_driver.type = TTY_DRIVER_TYPE_SERIAL;
- rs285_driver.subtype = SERIAL_TYPE_NORMAL;
- rs285_driver.init_termios = tty_std_termios;
- rs285_driver.init_termios.c_cflag = baud | CS8 | CREAD | HUPCL | CLOCAL;
- rs285_driver.flags = TTY_DRIVER_REAL_RAW;
- rs285_driver.refcount = &rs285_refcount;
- rs285_driver.table = rs285_table;
- rs285_driver.termios = rs285_termios;
- rs285_driver.termios_locked = rs285_termios_locked;
-
- rs285_driver.open = rs285_open;
- rs285_driver.close = rs285_close;
- rs285_driver.write = rs285_write;
- rs285_driver.put_char = rs285_put_char;
- rs285_driver.write_room = rs285_write_room;
- rs285_driver.chars_in_buffer = rs285_chars_in_buffer;
- rs285_driver.flush_buffer = rs285_flush_buffer;
- rs285_driver.throttle = rs285_throttle;
- rs285_driver.unthrottle = rs285_unthrottle;
- rs285_driver.send_xchar = rs285_send_xchar;
- rs285_driver.set_termios = rs285_set_termios;
- rs285_driver.stop = rs285_stop;
- rs285_driver.start = rs285_start;
- rs285_driver.wait_until_sent = rs285_wait_until_sent;
-
- callout_driver = rs285_driver;
- callout_driver.name = SERIAL_21285_AUXNAME;
- callout_driver.major = SERIAL_21285_AUXMAJOR;
- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
-
- if (request_irq(IRQ_CONRX, rs285_rx_int, 0, "rs285", NULL))
- panic("Couldn't get rx irq for rs285");
-
- if (request_irq(IRQ_CONTX, rs285_tx_int, 0, "rs285", NULL))
- panic("Couldn't get tx irq for rs285");
-
-#ifdef CONFIG_SERIAL_21285_OLD
- if (!machine_is_ebsa285() && !machine_is_netwinder()) {
- rs285_old_driver = rs285_driver;
- rs285_old_driver.name = SERIAL_21285_OLD_NAME;
- rs285_old_driver.major = SERIAL_21285_OLD_MAJOR;
- rs285_old_driver.minor_start = SERIAL_21285_OLD_MINOR;
-
- if (tty_register_driver(&rs285_old_driver))
- printk(KERN_ERR "Couldn't register old 21285 serial driver\n");
- }
-#endif
-
- if (tty_register_driver(&rs285_driver))
- printk(KERN_ERR "Couldn't register 21285 serial driver\n");
- if (tty_register_driver(&callout_driver))
- printk(KERN_ERR "Couldn't register 21285 callout driver\n");
+static struct uart_ops serial21285_ops = {
+ tx_empty: serial21285_tx_empty,
+ get_mctrl: serial21285_get_mctrl,
+ set_mctrl: serial21285_set_mctrl,
+ stop_tx: serial21285_stop_tx,
+ start_tx: serial21285_start_tx,
+ stop_rx: serial21285_stop_rx,
+ enable_ms: serial21285_enable_ms,
+ break_ctl: serial21285_break_ctl,
+ startup: serial21285_startup,
+ shutdown: serial21285_shutdown,
+ change_speed: serial21285_change_speed,
+ type: serial21285_type,
+ release_port: serial21285_release_port,
+ request_port: serial21285_request_port,
+ config_port: serial21285_config_port,
+ verify_port: serial21285_verify_port,
+};
- return 0;
-}
+static struct uart_port serial21285_port = {
+ membase: 0,
+ mapbase: 0x42000160,
+ iotype: SERIAL_IO_MEM,
+ irq: NO_IRQ,
+ uartclk: 0,
+ fifosize: 16,
+ ops: &serial21285_ops,
+ flags: ASYNC_BOOT_AUTOCONF,
+};
-static void __exit rs285_fini(void)
+static void serial21285_setup_ports(void)
{
- unsigned long flags;
- int ret;
-
- save_flags(flags);
- cli();
- ret = tty_unregister_driver(&callout_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 callout driver "
- "(%d)\n", ret);
- ret = tty_unregister_driver(&rs285_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister 21285 driver (%d)\n",
- ret);
-#ifdef CONFIG_SERIAL_21285_OLD
- if (!machine_is_ebsa285() && !machine_is_netwinder()) {
- ret = tty_unregister_driver(&rs285_old_driver);
- if (ret)
- printk(KERN_ERR "Unable to unregister old 21285 "
- "driver (%d)\n", ret);
- }
-#endif
- free_irq(IRQ_CONTX, NULL);
- free_irq(IRQ_CONRX, NULL);
- restore_flags(flags);
+ serial21285_port.uartclk = mem_fclk_21285 / 16;
}
-module_init(rs285_init);
-module_exit(rs285_fini);
-
#ifdef CONFIG_SERIAL_21285_CONSOLE
/************** console driver *****************/
-static void rs285_console_write(struct console *co, const char *s, u_int count)
+static void serial21285_console_write(struct console *co, const char *s, u_int count)
{
int i;
@@ -426,8 +374,13 @@
enable_irq(IRQ_CONTX);
}
-static int rs285_console_wait_key(struct console *co)
+static kdev_t serial21285_console_device(struct console *c)
{
+ return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
+}
+
+static int serial21285_console_wait_key(struct console *co)
+{
int c;
disable_irq(IRQ_CONRX);
@@ -437,104 +390,45 @@
return c;
}
-static kdev_t rs285_console_device(struct console *c)
+static void __init
+serial21285_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
{
- return MKDEV(SERIAL_21285_MAJOR, SERIAL_21285_MINOR);
}
-static int __init rs285_console_setup(struct console *co, char *options)
+static int __init serial21285_console_setup(struct console *co, char *options)
{
+ struct uart_port *port = &serial21285_port;
int baud = 9600;
int bits = 8;
int parity = 'n';
- int cflag = CREAD | HUPCL | CLOCAL;
+ int flow = 'n';
if (machine_is_personal_server())
baud = 57600;
- if (options) {
- char *s = options;
- baud = simple_strtoul(options, NULL, 10);
- while (*s >= '0' && *s <= '9')
- s++;
- if (*s)
- parity = *s++;
- if (*s)
- bits = *s - '0';
- }
-
/*
- * Now construct a cflag setting.
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
*/
- switch (baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 9600:
- cflag |= B9600;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- default:
- cflag |= B9600;
- break;
- }
- switch (bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- cflag |= CS8;
- break;
- }
- switch (parity) {
- case 'o':
- case 'O':
- cflag |= PARODD;
- break;
- case 'e':
- case 'E':
- cflag |= PARENB;
- break;
- }
- co->cflag = cflag;
- rs285_set_cflag(cflag);
- rs285_console_write(NULL, "\e[2J\e[Hboot ", 12);
if (options)
- rs285_console_write(NULL, options, strlen(options));
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
else
- rs285_console_write(NULL, "no options", 10);
- rs285_console_write(NULL, "\n", 1);
+ serial21285_get_options(port, &baud, &parity, &bits);
- return 0;
+ return uart_set_options(port, co, baud, parity, bits, flow);
}
#ifdef CONFIG_SERIAL_21285_OLD
-static struct console rs285_old_cons =
+static struct console serial21285_old_cons =
{
SERIAL_21285_OLD_NAME,
- rs285_console_write,
+ serial21285_console_write,
NULL,
- rs285_console_device,
- rs285_console_wait_key,
+ serial21285_console_device,
+ serial21285_console_wait_key,
NULL,
- rs285_console_setup,
+ serial21285_console_setup,
CON_PRINTBUFFER,
-1,
0,
@@ -542,27 +436,63 @@
};
#endif
-static struct console rs285_cons =
+static struct console serial21285_console =
{
name: SERIAL_21285_NAME,
- write: rs285_console_write,
- device: rs285_console_device,
- wait_key: rs285_console_wait_key,
- setup: rs285_console_setup,
+ write: serial21285_console_write,
+ device: serial21285_console_device,
+ wait_key: serial21285_console_wait_key,
+ setup: serial21285_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
};
void __init rs285_console_init(void)
{
-#ifdef CONFIG_SERIAL_21285_OLD
- if (!machine_is_ebsa285() && !machine_is_netwinder())
- register_console(&rs285_old_cons);
+ serial21285_setup_ports();
+ register_console(&serial21285_console);
+}
+
+#define SERIAL_21285_CONSOLE &serial21285_console
+#else
+#define SERIAL_21285_CONSOLE NULL
#endif
- register_console(&rs285_cons);
+
+static struct uart_driver serial21285_reg = {
+ owner: THIS_MODULE,
+ normal_major: SERIAL_21285_MAJOR,
+#ifdef CONFIG_DEVFS_FS
+ normal_name: "ttyFB%d",
+ callout_name: "cuafb%d",
+#else
+ normal_name: "ttyFB",
+ callout_name: "cuafb",
+#endif
+ normal_driver: &normal,
+ callout_major: SERIAL_21285_AUXMAJOR,
+ callout_driver: &callout,
+ table: serial21285_table,
+ termios: serial21285_termios,
+ termios_locked: serial21285_termios_locked,
+ minor: SERIAL_21285_MINOR,
+ nr: 1,
+ port: &serial21285_port,
+ cons: SERIAL_21285_CONSOLE,
+};
+
+static int __init serial21285_init(void)
+{
+ serial21285_setup_ports();
+ return uart_register_driver(&serial21285_reg);
}
-#endif /* CONFIG_SERIAL_21285_CONSOLE */
+static void __exit serial21285_exit(void)
+{
+ uart_unregister_driver(&serial21285_reg);
+}
+
+module_init(serial21285_init);
+module_exit(serial21285_exit);
EXPORT_NO_SYMBOLS;
Index: serial_8250.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- serial_8250.c 2001/11/23 01:44:33 1.10
+++ serial_8250.c 2001/12/13 04:46:52 1.11
@@ -102,7 +102,7 @@
/*
* Here we define the default xmit fifo size used for each type of UART.
*/
-static struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
+static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
{ "unknown", 1, 0 },
{ "8250", 1, 0 },
{ "16450", 1, 0 },
@@ -857,6 +857,8 @@
#endif
do {
+ spin_lock(&info->lock);
+
if (!info->tty ||
(serial_in(info->port, UART_IIR) & UART_IIR_NO_INT)) {
if (!end_mark)
@@ -871,6 +873,8 @@
serial8250_handle_port(info, regs);
next:
+ spin_unlock(&info->lock);
+
info = info->next_info;
if (info)
continue;
@@ -918,6 +922,8 @@
first_multi = inb(port_monitor);
#endif
+ spin_lock(&info->lock);
+
do {
serial8250_handle_port(info, regs);
if (pass_counter++ > RS_ISR_PASS_LIMIT) {
@@ -930,6 +936,9 @@
printk("IIR = %x...", serial_in(info->port, UART_IIR));
#endif
} while (!(serial_in(info->port, UART_IIR) & UART_IIR_NO_INT));
+
+ spin_unlock(&info->lock);
+
#ifdef CONFIG_SERIAL_8250_MULTIPORT
if (port_monitor)
printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n",
@@ -968,6 +977,7 @@
first_multi = inb(multi->port_monitor);
while (1) {
+ spin_lock(info->lock);
if (!info->tty ||
(serial_in(info->port, UART_IIR) & UART_IIR_NO_INT))
goto next;
@@ -975,6 +985,7 @@
serial8250_handle_port(info, regs);
next:
+ spin_unlock(info->lock);
info = info->next;
if (info)
continue;
@@ -1613,6 +1624,16 @@
return 0;
}
+static const char *
+serial8250_type(struct uart_port *port)
+{
+ int type = port->type;
+
+ if (type >= PORT_MAX_8250)
+ type = 0;
+ return uart_config[type].name;
+}
+
static struct uart_ops serial8250_pops = {
tx_empty: serial8250_tx_empty,
set_mctrl: serial8250_set_mctrl,
@@ -1626,6 +1647,7 @@
shutdown: serial8250_shutdown,
change_speed: serial8250_change_speed,
pm: serial8250_pm,
+ type: serial8250_type,
release_port: serial8250_release_port,
request_port: serial8250_request_port,
config_port: serial8250_config_port,
Index: serial_8250.h
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
Index: serial_8250_pci.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pci.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- serial_8250_pci.c 2001/12/02 07:03:59 1.11
+++ serial_8250_pci.c 2001/12/13 04:46:52 1.12
@@ -1078,4 +1078,4 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-//MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
+MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
Index: serial_8250_pnp.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pnp.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- serial_8250_pnp.c 2001/12/02 07:03:59 1.6
+++ serial_8250_pnp.c 2001/12/13 04:46:52 1.7
@@ -549,5 +549,5 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
-//MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
+MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
Index: serial_amba.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_amba.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- serial_amba.c 2001/11/23 01:44:33 1.9
+++ serial_amba.c 2001/12/13 04:46:52 1.10
@@ -511,6 +511,11 @@
restore_flags(flags);
}
+static const char *ambauart_type(struct uart_port *port)
+{
+ return port->type == PORT_AMBA ? "AMBA" : NULL;
+}
+
/*
* Release the memory region(s) being used by 'port'
*/
@@ -566,6 +571,7 @@
startup: ambauart_startup,
shutdown: ambauart_shutdown,
change_speed: ambauart_change_speed,
+ type: ambauart_type,
release_port: ambauart_release_port,
request_port: ambauart_request_port,
config_port: ambauart_config_port,
Index: serial_anakin.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_anakin.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- serial_anakin.c 2001/11/23 01:44:33 1.2
+++ serial_anakin.c 2001/12/13 04:46:52 1.3
@@ -337,6 +337,11 @@
restore_flags(flags);
}
+static const char *anakin_type(struct port *port)
+{
+ return port->type == PORT_ANAKIN ? "ANAKIN" : NULL;
+}
+
static struct uart_ops anakin_pops = {
tx_empty: anakin_tx_empty,
set_mctrl: anakin_set_mctrl,
@@ -349,6 +354,7 @@
startup: anakin_startup,
shutdown: anakin_shutdown,
change_speed: anakin_change_speed,
+ type: anakin_type,
};
static struct uart_port anakin_ports[UART_NR] = {
Index: serial_clps711x.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_clps711x.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- serial_clps711x.c 2001/11/23 01:44:33 1.9
+++ serial_clps711x.c 2001/12/13 04:46:52 1.10
@@ -406,6 +406,11 @@
restore_flags(flags);
}
+static const char *clps711xuart_type(struct uart_port *port)
+{
+ return port->type == PORT_CLPS711X ? "CLPS711x" : NULL;
+}
+
/*
* Configure/autoconfigure the port.
*/
@@ -436,6 +441,7 @@
startup: clps711xuart_startup,
shutdown: clps711xuart_shutdown,
change_speed: clps711xuart_change_speed,
+ type: clps711xuart_type,
config_port: clps711xuart_config_port,
release_port: clps711xuart_release_port,
request_port: clps711xuart_request_port,
Index: serial_core.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_core.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- serial_core.c 2001/11/23 01:44:33 1.16
+++ serial_core.c 2001/12/13 04:46:52 1.17
@@ -1506,7 +1506,15 @@
static const char *uart_type(struct uart_port *port)
{
- return "";
+ const char *str = NULL;
+
+ if (port->ops->type)
+ str = port->ops->type(port);
+
+ if (!str)
+ str = "unknown";
+
+ return str;
}
static int uart_line_info(char *buf, struct uart_driver *drv, int i)
@@ -1705,6 +1713,7 @@
extern void rs285_console_init(void);
extern void sa1100_rs_console_init(void);
extern void serial8250_console_init(void);
+extern void uart00_console_init(void);
/*
* Central "initialise all serial consoles" container. Needs to be killed.
@@ -1745,60 +1754,105 @@
* We don't actually save any state; the serial driver has enough
* state held internally to re-setup the port when we come out of D3.
*/
-static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
+static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate)
{
- if (rqst == PM_SUSPEND || rqst == PM_RESUME) {
- struct uart_state *state = dev->data;
- struct uart_port *port = state->port;
- struct uart_ops *ops = port->ops;
- int pm_state = (int)data;
- int running = state->info &&
- state->info->flags & ASYNC_INITIALIZED;
+ struct uart_port *port = state->port;
+ struct uart_ops *ops = port->ops;
+ int running = state->info &&
+ state->info->flags & ASYNC_INITIALIZED;
- if (port->type == PORT_UNKNOWN)
- return 0;
+ if (port->type == PORT_UNKNOWN)
+ return 0;
//printk("pm: %08x: %d -> %d, %srunning\n", port->iobase, dev->state, pm_state, running ? "" : "not ");
- if (pm_state == 0) {
- if (ops->pm)
- ops->pm(port, pm_state, dev->state);
- if (running) {
- ops->set_mctrl(port, 0);
- ops->startup(port, state->info);
- uart_change_speed(state->info, NULL);
- ops->set_mctrl(port, state->info->mctrl);
- ops->start_tx(port, 1, 0);
- }
+ if (pm_state == 0) {
+ if (ops->pm)
+ ops->pm(port, pm_state, oldstate);
+ if (running) {
+ ops->set_mctrl(port, 0);
+ ops->startup(port, state->info);
+ uart_change_speed(state->info, NULL);
+ ops->set_mctrl(port, state->info->mctrl);
+ ops->start_tx(port, 1, 0);
+ }
- /*
- * Re-enable the console device after suspending.
- */
- if (state->cons && state->cons->index == port->line)
- state->cons->flags |= CON_ENABLED;
- } else if (pm_state == 1) {
- if (ops->pm)
- ops->pm(port, pm_state, dev->state);
- } else {
- /*
- * Disable the console device before suspending.
- */
- if (state->cons && state->cons->index == port->line)
- state->cons->flags &= ~CON_ENABLED;
+ /*
+ * Re-enable the console device after suspending.
+ */
+ if (state->cons && state->cons->index == port->line)
+ state->cons->flags |= CON_ENABLED;
+ } else if (pm_state == 1) {
+ if (ops->pm)
+ ops->pm(port, pm_state, oldstate);
+ } else {
+ /*
+ * Disable the console device before suspending.
+ */
+ if (state->cons && state->cons->index == port->line)
+ state->cons->flags &= ~CON_ENABLED;
- if (running) {
- ops->stop_tx(port, 0);
- ops->set_mctrl(port, 0);
- ops->stop_rx(port);
- ops->shutdown(port, state->info);
- }
- if (ops->pm)
- ops->pm(port, pm_state, dev->state);
+ if (running) {
+ ops->stop_tx(port, 0);
+ ops->set_mctrl(port, 0);
+ ops->stop_rx(port);
+ ops->shutdown(port, state->info);
}
+ if (ops->pm)
+ ops->pm(port, pm_state, oldstate);
}
return 0;
}
+
+/*
+ * Wakeup support.
+ */
+static int uart_pm_set_wakeup(struct uart_state *state, int data)
+{
+ int err = 0;
+
+ if (state->port->ops->set_wake)
+ err = state->port->ops->set_wake(state->port, data);
+
+ return err;
+}
+
+static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+ struct uart_state *state = dev->data;
+ int err = 0;
+
+ switch (rqst) {
+ case PM_SUSPEND:
+ case PM_RESUME:
+ err = uart_pm_set_state(state, (int)data, dev->state);
+ break;
+
+ case PM_SET_WAKEUP:
+ err = uart_pm_set_wakeup(state, (int)data);
+ break;
+ }
+ return err;
+}
#endif
+static inline void
+uart_report_port(struct uart_driver *drv, struct uart_port *port)
+{
+ printk("%s%d at ", drv->normal_name, port->line);
+ switch (port->iotype) {
+ case SERIAL_IO_PORT:
+ printk("I/O 0x%x", port->iobase);
+ break;
+ case SERIAL_IO_HUB6:
+ printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
+ break;
+ case SERIAL_IO_MEM:
+ printk("MEM 0x%x", port->mapbase);
+ break;
+ }
+ printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
+}
+
static void
uart_setup_port(struct uart_driver *drv, struct uart_state *state)
{
@@ -1842,6 +1896,7 @@
state->port->line);
tty_register_devfs(drv->callout_driver, 0, drv->minor +
state->port->line);
+ uart_report_port(drv, port);
}
#ifdef CONFIG_PM
@@ -2091,7 +2146,7 @@
#if 0 //def CONFIG_PM
/* we have already registered the power management handlers */
- state->pm = pm_register(PM_SYS_DEV, PM_SYS_CON, uart_pm);
+ state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
if (state->pm) {
state->pm->data = state;
@@ -2113,6 +2168,9 @@
state->port->line);
tty_register_devfs(drv->callout_driver, 0, drv->minor +
state->port->line);
+
+ uart_report_port(drv, state->port);
+
up(&state->count_sem);
return i;
}
Index: serial_sa1100.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_sa1100.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- serial_sa1100.c 2001/11/23 01:44:33 1.14
+++ serial_sa1100.c 2001/12/13 04:46:52 1.15
@@ -271,6 +271,7 @@
unsigned int status, pass_counter = 0;
status = UART_GET_UTSR0(port);
+ status &= (SM_TO_UTSR0(port->read_status_mask) | ~UTSR0_TFS);
do {
if (status & (UTSR0_RFS | UTSR0_RID)) {
/* Clear the receiver idle bit, if set */
@@ -294,12 +295,12 @@
}
#endif
}
- status &= SM_TO_UTSR0(port->read_status_mask);
if (status & UTSR0_TFS)
sa1100_tx_chars(info);
if (pass_counter++ > SA1100_ISR_PASS_LIMIT)
break;
status = UART_GET_UTSR0(port);
+ status &= (SM_TO_UTSR0(port->read_status_mask) | ~UTSR0_TFS);
} while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
}
@@ -451,6 +452,11 @@
UART_PUT_UTCR3(port, old_utcr3);
}
+static const char *sa1100_type(struct uart_port *port)
+{
+ return port->type == PORT_SA1100 ? "SA1100" : NULL;
+}
+
/*
* Release the memory region(s) being used by 'port'.
*/
@@ -514,6 +520,7 @@
startup: sa1100_startup,
shutdown: sa1100_shutdown,
change_speed: sa1100_change_speed,
+ type: sa1100_type,
release_port: sa1100_release_port,
request_port: sa1100_request_port,
config_port: sa1100_config_port,
@@ -565,9 +572,10 @@
sa1100_pops.get_mctrl = fns->get_mctrl;
if (fns->set_mctrl)
sa1100_pops.set_mctrl = fns->set_mctrl;
- sa1100_open = fns->open;
- sa1100_close = fns->close;
- sa1100_pops.pm = fns->pm;
+ sa1100_open = fns->open;
+ sa1100_close = fns->close;
+ sa1100_pops.pm = fns->pm;
+ sa1100_pops.set_wake = fns->set_wake;
}
void __init sa1100_register_uart(int idx, int port)
Index: serial_uart00.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_uart00.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- serial_uart00.c 2001/11/23 01:44:33 1.2
+++ serial_uart00.c 2001/12/13 04:46:52 1.3
@@ -530,6 +530,11 @@
UART_PUT_MCR(port, UART_GET_MCR(port) &~UART_MCR_BR_MSK);
}
+static const char *uart00_type(struct uart_port *port)
+{
+ return port->type == PORT_UART00 ? "UART00" : NULL;
+}
+
/*
* Release the memory region(s) being used by 'port'
*/
@@ -585,6 +590,7 @@
startup: uart00_startup,
shutdown: uart00_shutdown,
change_speed: uart00_change_speed,
+ type: uart00_type,
release_port: uart00_release_port,
request_port: uart00_request_port,
config_port: uart00_config_port,
|