CVSROOT: /home/cvs
Module name: linux
Changes by: ralf@ftp.linux-mips.org 05/03/04 17:24:33
Modified files:
arch/mips : Kconfig
arch/mips/configs: jmr3927_defconfig
arch/mips/jmr3927/rbhma3100: setup.c
arch/mips/tx4927/toshiba_rbtx4927: toshiba_rbtx4927_setup.c
drivers/char : Kconfig Makefile
drivers/serial : Kconfig
include/asm-mips: serial.h
include/asm-mips/jmr3927: jmr3927.h
Added files:
drivers/serial : serial_txx9.c
Removed files:
drivers/char : serial_tx3912.c serial_tx3912.h serial_txx9.c
serial_txx927.c
Log message:
Replace old txx9 with drivers/serial/ new-style txx9 driver.
diff -urN linux/arch/mips/Kconfig linux/arch/mips/Kconfig
--- linux/arch/mips/Kconfig 2005/03/01 06:33:16 1.143
+++ linux/arch/mips/Kconfig 2005/03/04 17:24:32 1.144
@@ -623,6 +623,7 @@
config TOSHIBA_RBTX4927
bool "Support for Toshiba TBTX49[23]7 board"
select DMA_NONCOHERENT
+ select HAS_TXX9_SERIAL
select HW_HAS_PCI
select I8259
select ISA
@@ -769,6 +770,7 @@
config MIPS_TX3927
bool
+ select HAS_TXX9_SERIAL
config PCI_MARVELL
bool
diff -urN linux/arch/mips/configs/jmr3927_defconfig
linux/arch/mips/configs/jmr3927_defconfig
--- linux/arch/mips/configs/jmr3927_defconfig 2005/03/02 18:12:08 1.45
+++ linux/arch/mips/configs/jmr3927_defconfig 2005/03/04 17:24:32 1.46
@@ -467,10 +467,6 @@
# CONFIG_SX is not set
# CONFIG_RIO is not set
# CONFIG_STALDRV is not set
-# CONFIG_SERIAL_TX3912 is not set
-CONFIG_TXX927_SERIAL=y
-CONFIG_TXX927_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_TXX9 is not set
#
# Serial drivers
@@ -480,6 +476,12 @@
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_TXX9=y
+CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
# CONFIG_UNIX98_PTYS is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
diff -urN linux/arch/mips/jmr3927/rbhma3100/setup.c
linux/arch/mips/jmr3927/rbhma3100/setup.c
--- linux/arch/mips/jmr3927/rbhma3100/setup.c 2005/01/13 14:05:30 1.17
+++ linux/arch/mips/jmr3927/rbhma3100/setup.c 2005/03/04 17:24:32 1.18
@@ -44,6 +44,11 @@
#include <linux/ioport.h>
#include <linux/param.h> /* for HZ */
#include <linux/delay.h>
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
#include <asm/addrspace.h>
#include <asm/time.h>
@@ -211,8 +216,8 @@
*/
ioport_resource.start = pci_io_resource.start;
ioport_resource.end = pci_io_resource.end;
- iomem_resource.start = pci_mem_resource.start;
- iomem_resource.end = pci_mem_resource.end;
+ iomem_resource.start = 0;
+ iomem_resource.end = 0xffffffff;
/* Reboot on panic */
panic_timeout = 180;
@@ -265,13 +270,33 @@
strcat(argptr, " ip=bootp");
}
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_TXX9
+ {
+ extern int early_serial_txx9_setup(struct uart_port *port);
+ int i;
+ struct uart_port req;
+ for(i = 0; i < 2; i++) {
+ memset(&req, 0, sizeof(req));
+ req.line = i;
+ req.iotype = UPIO_MEM;
+ req.membase = (char *)TX3927_SIO_REG(i);
+ req.mapbase = TX3927_SIO_REG(i);
+ req.irq = i == 0 ?
+ JMR3927_IRQ_IRC_SIO0 : JMR3927_IRQ_IRC_SIO1;
+ if (i == 0)
+ req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+ req.uartclk = JMR3927_IMCLK;
+ early_serial_txx9_setup(&req);
+ }
+ }
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
argptr = prom_getcmdline();
if ((argptr = strstr(argptr, "console=")) == NULL) {
argptr = prom_getcmdline();
strcat(argptr, " console=ttyS1,115200");
}
#endif
+#endif
}
early_initcall(jmr3927_setup);
diff -urN linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
--- linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
2005/01/05 22:29:20 1.14
+++ linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
2005/03/04 17:24:33 1.15
@@ -77,6 +77,11 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#endif
+#ifdef CONFIG_SERIAL_TXX9
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#endif
#undef TOSHIBA_RBTX4927_SETUP_DEBUG
@@ -920,12 +925,30 @@
#endif /* CONFIG_PCI */
+#ifdef CONFIG_SERIAL_TXX9
+ {
+ extern int early_serial_txx9_setup(struct uart_port *port);
+ int i;
+ struct uart_port req;
+ for(i = 0; i < 2; i++) {
+ memset(&req, 0, sizeof(req));
+ req.line = i;
+ req.iotype = UPIO_MEM;
+ req.membase = (char *)(0xff1ff300 + i * 0x100);
+ req.mapbase = 0xff1ff300 + i * 0x100;
+ req.irq = 32 + i;
+ req.flags |= UPF_BUGGY_UART /*HAVE_CTS_LINE*/;
+ req.uartclk = 50000000;
+ early_serial_txx9_setup(&req);
+ }
+ }
#ifdef CONFIG_SERIAL_TXX9_CONSOLE
argptr = prom_getcmdline();
if (strstr(argptr, "console=") == NULL) {
strcat(argptr, " console=ttyS0,38400");
}
#endif
+#endif
#ifdef CONFIG_ROOT_NFS
argptr = prom_getcmdline();
diff -urN linux/drivers/char/Kconfig linux/drivers/char/Kconfig
--- linux/drivers/char/Kconfig 2005/01/25 04:28:12 1.48
+++ linux/drivers/char/Kconfig 2005/03/04 17:24:33 1.49
@@ -364,38 +364,6 @@
tristate "Au1000 USB Raw Device support"
depends on MIPS && MIPS_AU1000 && AU1000_USB_DEVICE=y &&
AU1000_USB_TTY!=y && AU1X00_USB_DEVICE
-config SERIAL_TX3912
- bool "TX3912/PR31700 serial port support"
- depends on MIPS && CPU_TX39XX=y
- help
- The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core;
- see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
- Say Y here to enable kernel support for the on-board serial port.
-
-config SERIAL_TX3912_CONSOLE
- bool "Console on TX3912/PR31700 serial port"
- depends on SERIAL_TX3912
- help
- The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core;
- see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
- Say Y here to direct console I/O to the on-board serial port.
-
-config TXX927_SERIAL
- bool "TXx927 SIO support"
- depends on MIPS && CPU_TX39XX=y
-
-config TXX927_SERIAL_CONSOLE
- bool "TXx927 SIO Console support"
- depends on TXX927_SERIAL
-
-config SERIAL_TXX9
- bool "TMPTX39XX/49XX SIO support"
- depends on MIPS && TOSHIBA_BOARDS=y
-
-config SERIAL_TXX9_CONSOLE
- bool "TMPTX39XX/49XX SIO Console support"
- depends on SERIAL_TXX9
-
config SIBYTE_SB1250_DUART
bool "Support for BCM1xxx onchip DUART"
depends on MIPS && SIBYTE_SB1xxx_SOC=y
diff -urN linux/drivers/char/Makefile linux/drivers/char/Makefile
--- linux/drivers/char/Makefile 2004/11/18 19:14:35 1.134
+++ linux/drivers/char/Makefile 2005/03/04 17:24:33 1.135
@@ -20,8 +20,6 @@
obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o
obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
-obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o
-obj-$(CONFIG_SERIAL_TXX9) += generic_serial.o serial_txx9.o
obj-$(CONFIG_ROCKETPORT) += rocket.o
obj-$(CONFIG_SERIAL167) += serial167.o
obj-$(CONFIG_CYCLADES) += cyclades.o
diff -urN linux/drivers/char/serial_tx3912.c linux/drivers/char/serial_tx3912.c
--- linux/drivers/char/Attic/serial_tx3912.c Fri Mar 4 17:24:33 2005
1.16
+++ linux/drivers/char/Attic/serial_tx3912.c 1970/01/01 00:00:002002
@@ -1,812 +0,0 @@
-/*
- * drivers/char/serial_tx3912.c
- *
- * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Serial driver for TMPR3912/05 and PR31700 processors
- */
-#include <linux/init.h>
-#include <linux/config.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/console.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/tx3912.h>
-#include "serial_tx3912.h"
-
-/*
- * Forward declarations for serial routines
- */
-static void rs_disable_tx_interrupts (void * ptr);
-static void rs_enable_tx_interrupts (void * ptr);
-static void rs_disable_rx_interrupts (void * ptr);
-static void rs_enable_rx_interrupts (void * ptr);
-static int rs_get_CD (void * ptr);
-static void rs_shutdown_port (void * ptr);
-static int rs_set_real_termios (void *ptr);
-static int rs_chars_in_buffer (void * ptr);
-
-/*
- * Used by generic serial driver to access hardware
- */
-static struct real_driver rs_real_driver = {
- .disable_tx_interrupts = rs_disable_tx_interrupts,
- .enable_tx_interrupts = rs_enable_tx_interrupts,
- .disable_rx_interrupts = rs_disable_rx_interrupts,
- .enable_rx_interrupts = rs_enable_rx_interrupts,
- .get_CD = rs_get_CD,
- .shutdown_port = rs_shutdown_port,
- .set_real_termios = rs_set_real_termios,
- .chars_in_buffer = rs_chars_in_buffer,
-};
-
-/*
- * Structures and usage counts
- */
-static struct tty_driver *rs_driver;
-static struct rs_port *rs_port;
-static int rs_initialized;
-
-
-/*
- * Receive a character
- */
-static inline void receive_char_pio(struct rs_port *port)
-{
- struct tty_struct *tty = port->gs.tty;
- unsigned char ch;
- int counter = 2048;
-
- /* While there are characters */
- while (counter > 0) {
- if (!(inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_RXHOLDFULL))
- break;
- ch = inb(TX3912_UARTA_DATA);
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- *tty->flip.char_buf_ptr++ = ch;
- *tty->flip.flag_buf_ptr++ = 0;
- tty->flip.count++;
- }
- udelay(1);
- counter--;
- }
-
- tty_flip_buffer_push(tty);
-}
-
-/*
- * Transmit a character
- */
-static inline void transmit_char_pio(struct rs_port *port)
-{
- /* TX while bytes available */
- for (;;) {
- if (!(inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_EMPTY))
- break;
- else if (port->x_char) {
- outb(port->x_char, TX3912_UARTA_DATA);
- port->icount.tx++;
- port->x_char = 0;
- }
- else if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped ||
- port->gs.tty->hw_stopped) {
- break;
- }
- else {
- outb(port->gs.xmit_buf[port->gs.xmit_tail++],
- TX3912_UARTA_DATA);
- port->icount.tx++;
- port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1;
- if (--port->gs.xmit_cnt <= 0) {
- break;
- }
- }
- udelay(10);
- }
-
- if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped ||
- port->gs.tty->hw_stopped) {
- rs_disable_tx_interrupts(port);
- }
-
- if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
- tty_wakeup(port->gs.tty);
- rs_dprintk(TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc
(%d)....\n",
- port->gs.wakeup_chars);
- wake_up_interruptible(&port->gs.tty->write_wait);
- }
-}
-
-/*
- * We don't have MSR
- */
-static inline void check_modem_status(struct rs_port *port)
-{
- wake_up_interruptible(&port->gs.open_wait);
-}
-
-/*
- * RX interrupt handler
- */
-static inline void rs_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags, status;
-
- save_and_cli(flags);
-
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "rs_rx_interrupt...");
-
- /* Get the interrupts */
- status = inl(TX3912_INT2_STATUS);
-
- /* Clear any interrupts we might be about to handle */
- outl(TX3912_INT2_UARTA_RX_BITS, TX3912_INT2_CLEAR);
-
- if(!rs_port || !rs_port->gs.tty) {
- restore_flags(flags);
- return;
- }
-
- /* RX Receiver Holding Register Overrun */
- if(status & TX3912_INT2_UARTATXOVERRUNINT) {
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "overrun");
- rs_port->icount.overrun++;
- }
-
- /* RX Frame Error */
- if(status & TX3912_INT2_UARTAFRAMEERRINT) {
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "frame error");
- rs_port->icount.frame++;
- }
-
- /* Break signal received */
- if(status & TX3912_INT2_UARTABREAKINT) {
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "break");
- rs_port->icount.brk++;
- }
-
- /* RX Parity Error */
- if(status & TX3912_INT2_UARTAPARITYINT) {
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "parity error");
- rs_port->icount.parity++;
- }
-
- /* Byte received */
- if(status & TX3912_INT2_UARTARXINT) {
- receive_char_pio(rs_port);
- }
-
- restore_flags(flags);
-
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "end.\n");
-}
-
-/*
- * TX interrupt handler
- */
-static inline void rs_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags, status;
-
- save_and_cli(flags);
-
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "rs_tx_interrupt...");
-
- /* Get the interrupts */
- status = inl(TX3912_INT2_STATUS);
-
- if(!rs_port || !rs_port->gs.tty) {
- restore_flags(flags);
- return;
- }
-
- /* Clear interrupts */
- outl(TX3912_INT2_UARTA_TX_BITS, TX3912_INT2_CLEAR);
-
- /* TX holding register empty - transmit a byte */
- if(status & TX3912_INT2_UARTAEMPTYINT) {
- transmit_char_pio(rs_port);
- }
-
- /* TX Transmit Holding Register Overrun (shouldn't happen) */
- if(status & TX3912_INT2_UARTATXOVERRUNINT) {
- printk( "rs_tx_interrupt: TX overrun\n");
- }
-
- restore_flags(flags);
-
- rs_dprintk(TX3912_UART_DEBUG_INTERRUPTS, "end.\n");
-}
-
-/*
- * Here are the routines that actually interface with the generic driver
- */
-static void rs_disable_tx_interrupts (void * ptr)
-{
- unsigned long flags;
-
- save_and_cli(flags);
-
- outl(inl(TX3912_INT2_ENABLE) & ~TX3912_INT2_UARTA_TX_BITS,
- TX3912_INT2_ENABLE);
- outl(TX3912_INT2_UARTA_TX_BITS, TX3912_INT2_CLEAR);
-
- restore_flags(flags);
-}
-
-static void rs_enable_tx_interrupts (void * ptr)
-{
- unsigned long flags;
-
- save_and_cli(flags);
-
- outl(TX3912_INT2_UARTA_TX_BITS, TX3912_INT2_CLEAR);
- outl(inl(TX3912_INT2_ENABLE) | TX3912_INT2_UARTA_TX_BITS,
- TX3912_INT2_ENABLE);
- transmit_char_pio(rs_port);
-
- restore_flags(flags);
-}
-
-static void rs_disable_rx_interrupts (void * ptr)
-{
- unsigned long flags;
-
- save_and_cli(flags);
-
- outl(inl(TX3912_INT2_ENABLE) & ~TX3912_INT2_UARTA_RX_BITS,
- TX3912_INT2_ENABLE);
- outl(TX3912_INT2_UARTA_RX_BITS, TX3912_INT2_CLEAR);
-
- restore_flags(flags);
-}
-
-static void rs_enable_rx_interrupts (void * ptr)
-{
- unsigned long flags;
-
- save_and_cli(flags);
-
- outl(inl(TX3912_INT2_ENABLE) | TX3912_INT2_UARTA_RX_BITS,
- TX3912_INT2_ENABLE);
- while (inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_RXHOLDFULL)
- inb(TX3912_UARTA_DATA);
- outl(TX3912_INT2_UARTA_RX_BITS, TX3912_INT2_CLEAR);
-
- restore_flags(flags);
-}
-
-/*
- * We have no CD
- */
-static int rs_get_CD (void * ptr)
-{
- return 1;
-}
-
-/*
- * Shut down the port
- */
-static void rs_shutdown_port (void * ptr)
-{
- func_enter();
- rs_port->gs.flags &= ~GS_ACTIVE;
- func_exit();
-}
-
-static int rs_set_real_termios (void *ptr)
-{
- unsigned int ctrl1 = 0;
- unsigned int ctrl2 = 0;
-
- /* Set baud rate */
- switch (rs_port->gs.baud) {
- case 0:
- goto done;
- case 1200:
- ctrl2 = TX3912_UART_CTRL2_B1200;
- break;
- case 2400:
- ctrl2 = TX3912_UART_CTRL2_B2400;
- break;
- case 4800:
- ctrl2 = TX3912_UART_CTRL2_B4800;
- break;
- case 9600:
- ctrl2 = TX3912_UART_CTRL2_B9600;
- break;
- case 19200:
- ctrl2 = TX3912_UART_CTRL2_B19200;
- break;
- case 38400:
- ctrl2 = TX3912_UART_CTRL2_B38400;
- break;
- case 57600:
- ctrl2 = TX3912_UART_CTRL2_B57600;
- break;
- case 115200:
- default:
- ctrl2 = TX3912_UART_CTRL2_B115200;
- break;
- }
-
- /* Clear current UARTA settings */
- ctrl1 = inl(TX3912_UARTA_CTRL1) & 0xf000000f;
-
- /* Set parity */
- if(C_PARENB(rs_port->gs.tty)) {
- if (!C_PARODD(rs_port->gs.tty))
- ctrl1 |= (TX3912_UART_CTRL1_ENPARITY |
- TX3912_UART_CTRL1_EVENPARITY);
- else
- ctrl1 |= TX3912_UART_CTRL1_ENPARITY;
- }
-
- /* Set data size */
- switch(rs_port->gs.tty->termios->c_cflag & CSIZE) {
- case CS7:
- ctrl1 |= TX3912_UART_CTRL1_BIT_7;
- break;
- case CS5:
- case CS6:
- printk(KERN_ERR "Data byte size unsupported. Defaulting
to CS8\n");
- case CS8:
- default:
- ctrl1 &= ~TX3912_UART_CTRL1_BIT_7;
- }
-
- /* Set stop bits */
- if(C_CSTOPB(rs_port->gs.tty))
- ctrl1 |= TX3912_UART_CTRL1_TWOSTOP;
-
- /* Write the control registers */
- outl(ctrl2, TX3912_UARTA_CTRL2);
- outl(0, TX3912_UARTA_DMA_CTRL1);
- outl(0, TX3912_UARTA_DMA_CTRL2);
- outl(ctrl1, TX3912_UARTA_CTRL1);
-
- /* Loop until the UART is on */
- while(~inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_UARTON);
-
-done:
- func_exit();
- return 0;
-}
-
-/*
- * Anyone in the buffer?
- */
-static int rs_chars_in_buffer (void * ptr)
-{
- return ((inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_EMPTY) ? 0 : 1);
-}
-
-/*
- * Open the serial port
- */
-static int rs_open(struct tty_struct * tty, struct file * filp)
-{
- int retval;
-
- func_enter();
-
- if (!rs_initialized) {
- return -EIO;
- }
-
- rs_dprintk(TX3912_UART_DEBUG_OPEN, "Serial opening...\n");
-
- tty->driver_data = rs_port;
- rs_port->gs.tty = tty;
- rs_port->gs.count++;
-
- /*
- * Start up serial port
- */
- retval = gs_init_port(&rs_port->gs);
- rs_dprintk(TX3912_UART_DEBUG_OPEN, "Finished gs_init...\n");
- if(retval) {
- rs_port->gs.count--;
- return retval;
- }
-
- rs_port->gs.flags |= GS_ACTIVE;
-
- rs_enable_rx_interrupts(rs_port);
- rs_enable_tx_interrupts(rs_port);
-
- retval = gs_block_til_ready(&rs_port->gs, filp);
- if(retval) {
- rs_port->gs.count--;
- return retval;
- }
-
- func_exit();
-
- return 0;
-}
-
-/*
- * Serial ioctl call
- */
-static int rs_ioctl(struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- int ival, rc;
-
- rc = 0;
- switch (cmd) {
- case TIOCGSOFTCAR:
- rc = put_user((tty->termios->c_cflag & CLOCAL) ? 1 : 0,
- (unsigned int *) arg);
- break;
- case TIOCSSOFTCAR:
- if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
- tty->termios->c_cflag =
- (tty->termios->c_cflag & ~CLOCAL) |
- (ival ? CLOCAL : 0);
- }
- break;
- case TIOCGSERIAL:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct))) == 0)
- rc = gs_getserial(&rs_port->gs,
- (struct serial_struct *) arg);
- break;
- case TIOCSSERIAL:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(struct serial_struct))) == 0)
- rc = gs_setserial(&rs_port->gs, (struct
serial_struct *) arg);
- break;
- default:
- rc = -ENOIOCTLCMD;
- break;
- }
-
- return rc;
-}
-
-/*
- * Send xchar
- */
-static void rs_send_xchar(struct tty_struct * tty, char ch)
-{
- func_enter();
-
- rs_port->x_char = ch;
- if (ch) {
- rs_enable_tx_interrupts(tty);
- }
-
- func_exit();
-}
-
-/*
- * Throttle characters as directed by upper tty layer
- */
-static void rs_throttle(struct tty_struct * tty)
-{
-#ifdef TX3912_UART_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- func_enter();
-
- if (I_IXOFF(tty))
- rs_send_xchar(tty, STOP_CHAR(tty));
-
- func_exit();
-}
-
-/*
- * Un-throttle characters as directed by upper tty layer
- */
-static void rs_unthrottle(struct tty_struct * tty)
-{
-#ifdef TX3912_UART_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- func_enter();
-
- if (I_IXOFF(tty)) {
- if (rs_port->x_char)
- rs_port->x_char = 0;
- else
- rs_send_xchar(tty, START_CHAR(tty));
- }
-
- func_exit();
-}
-
-static struct tty_operations rs_ops = {
- .open = rs_open,
- .close = gs_close,
- .write = gs_write,
- .put_char = gs_put_char,
- .flush_chars = gs_flush_chars,
- .write_room = gs_write_room,
- .chars_in_buffer = gs_chars_in_buffer,
- .flush_buffer = gs_flush_buffer,
- .ioctl = rs_ioctl,
- .throttle = rs_throttle,
- .unthrottle = rs_unthrottle,
- .set_termios = gs_set_termios,
- .stop = gs_stop,
- .start = gs_start,
- .hangup = gs_hangup,
-};
-
-/*
- * Initialize the serial port
- */
-static void __init tx3912_rs_init(void)
-{
- func_enter();
-
- rs_driver = alloc_tty_driver(TX3912_UART_NPORTS);
- if (!rs_driver)
- return -ENOMEM;
-
- rs_dprintk(TX3912_UART_DEBUG_INIT, "Initializing serial...\n");
-
- /* Allocate critical structures */
- if(!(rs_tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL))) {
- return;
- }
- if(!(rs_port = kmalloc(sizeof(struct rs_port), GFP_KERNEL))) {
- kfree(rs_tty);
- return;
- }
- if(!(rs_termios = kmalloc(sizeof(struct termios), GFP_KERNEL))) {
- kfree(rs_port);
- kfree(rs_tty);
- return;
- }
- if(!(rs_termios_locked = kmalloc(sizeof(struct termios), GFP_KERNEL))) {
- kfree(rs_termios);
- kfree(rs_port);
- kfree(rs_tty);
- return;
- }
-
- /* Zero out the structures */
- memset(rs_tty, 0, sizeof(struct tty_struct));
- memset(rs_port, 0, sizeof(struct rs_port));
- memset(rs_termios, 0, sizeof(struct termios));
- memset(rs_termios_locked, 0, sizeof(struct termios));
- memset(&rs_driver, 0, sizeof(rs_driver));
- memset(&rs_callout_driver, 0, sizeof(rs_callout_driver));
-
- /* Fill in hardware specific port structure */
- rs_port->gs.callout_termios = tty_std_termios;
- rs_port->gs.normal_termios = tty_std_termios;
- rs_port->gs.magic = SERIAL_MAGIC;
- rs_port->gs.close_delay = HZ/2;
- rs_port->gs.closing_wait = 30 * HZ;
- rs_port->gs.rd = &rs_real_driver;
-#ifdef NEW_WRITE_LOCKING
- rs_port->gs.port_write_sem = MUTEX;
-#endif
-#ifdef DECLARE_WAITQUEUE
- init_waitqueue_head(&rs_port->gs.open_wait);
- init_waitqueue_head(&rs_port->gs.close_wait);
-#endif
-
- rs_driver->owner = THIS_MODULE;
- rs_driver->driver_name = "serial";
- rs_driver->name = "ttyS";
- rs_driver->major = TTY_MAJOR;
- rs_driver->minor_start = 64;
- rs_driver->type = TTY_DRIVER_TYPE_SERIAL;
- rs_driver->subtype = SERIAL_TYPE_NORMAL;
- rs_driver->init_termios = tty_std_termios;
- rs_driver->init_termios.c_cflag =
- B115200 | CS8 | CREAD | HUPCL | CLOCAL;
- tty_set_operations(rs_driver, &rs_ops);
- if ((error = tty_register_driver(rs_driver))) {
- printk(KERN_ERR "Unable to register serial driver\n");
- put_tty_driver(rs_driver);
- goto error;
- }
-
- /* Assign IRQs */
- if(request_irq(2, rs_tx_interrupt, SA_SHIRQ,
- "uarta_tx", rs_port)) {
- printk(KERN_ERR "Cannot allocate IRQ for UARTA_TX.\n");
- goto error;
- }
-
- if(request_irq(3, rs_rx_interrupt, SA_SHIRQ,
- "uarta_rx", rs_port)) {
- printk(KERN_ERR "Cannot allocate IRQ for UARTA_RX.\n");
- goto error;
- }
-
- /* Enable the serial receive interrupt */
- rs_enable_rx_interrupts(rs_port);
-
-#ifndef CONFIG_SERIAL_TX3912_CONSOLE
- /* Write the control registers */
- outl(TX3912_UART_CTRL2_B115200, TX3912_UARTA_CTRL2);
- outl(0x00000000, TX3912_UARTA_DMA_CTRL1);
- outl(0x00000000, TX3912_UARTA_DMA_CTRL2);
- outl(inl(TX3912_UARTA_CTRL1) | TX3912_UART_CTRL1_ENUART,
- TX3912_UARTA_CTRL1);
-
- /* Loop until the UART is on */
- while(~inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_UARTON);
-#endif
-
- rs_initialized = 1;
- func_exit();
- return;
-
-error:
- kfree(rs_termios_locked);
- kfree(rs_termios);
- kfree(rs_port);
- kfree(rs_tty);
- func_exit();
-}
-module_init(tx3912_rs_init);
-
-/*
- * Begin serial console routines
- */
-#ifdef CONFIG_SERIAL_TX3912_CONSOLE
-void serial_outc(unsigned char c)
-{
- int i;
- unsigned long int2;
-
- /* Disable UARTA_TX interrupts */
- int2 = inl(TX3912_INT2_ENABLE);
- outl(inl(TX3912_INT2_ENABLE) & ~TX3912_INT2_UARTA_TX_BITS,
- TX3912_INT2_ENABLE);
-
- /* Wait for UARTA_TX register to empty */
- i = 10000;
- while(!(inl(TX3912_INT2_STATUS) & TX3912_INT2_UARTATXINT) && i--);
- outl(TX3912_INT2_UARTA_TX_BITS, TX3912_INT2_CLEAR);
-
- /* Send the character */
- outl(c, TX3912_UARTA_DATA);
-
- /* Wait for UARTA_TX register to empty */
- i = 10000;
- while(!(inl(TX3912_INT2_STATUS) & TX3912_INT2_UARTATXINT) && i--);
- outl(TX3912_INT2_UARTA_TX_BITS, TX3912_INT2_CLEAR);
-
- /* Enable UARTA_TX interrupts */
- outl(int2, TX3912_INT2_ENABLE);
-}
-
-static void serial_console_write(struct console *co, const char *s,
- unsigned count)
-{
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- if (*s == '\n')
- serial_outc('\r');
- serial_outc(*s++);
- }
-}
-
-static struct tty_driver *serial_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return rs_driver;
-}
-
-static __init int serial_console_setup(struct console *co, char *options)
-{
- int baud = 115200;
- int bits = 8;
- int parity = 'n';
- char *s;
- unsigned int ctrl1 = 0;
- unsigned int ctrl2 = 0;
-
- if (options) {
- baud = simple_strtoul(options, NULL, 10);
- s = options;
- while(*s >= '0' && *s <= '9')
- s++;
- if (*s) parity = *s++;
- if (*s) bits = *s++ - '0';
- }
-
- switch(baud) {
- case 1200:
- ctrl2 = TX3912_UART_CTRL2_B1200;
- break;
- case 2400:
- ctrl2 = TX3912_UART_CTRL2_B2400;
- break;
- case 4800:
- ctrl2 = TX3912_UART_CTRL2_B4800;
- break;
- case 9600:
- ctrl2 = TX3912_UART_CTRL2_B9600;
- break;
- case 19200:
- ctrl2 = TX3912_UART_CTRL2_B19200;
- break;
- case 38400:
- ctrl2 = TX3912_UART_CTRL2_B38400;
- break;
- case 57600:
- ctrl2 = TX3912_UART_CTRL2_B57600;
- break;
- case 115200:
- default:
- ctrl2 = TX3912_UART_CTRL2_B115200;
- break;
- }
-
- switch(bits) {
- case 7:
- ctrl1 = TX3912_UART_CTRL1_BIT_7;
- break;
- default:
- break;
- }
-
- switch(parity) {
- case 'o': case 'O':
- ctrl1 |= TX3912_UART_CTRL1_ENPARITY;
- break;
- case 'e': case 'E':
- ctrl1 |= (TX3912_UART_CTRL1_ENPARITY |
- TX3912_UART_CTRL1_EVENPARITY);
- break;
- default:
- break;
- }
-
- /* Write the control registers */
- outl(ctrl2, TX3912_UARTA_CTRL2);
- outl(0x00000000, TX3912_UARTA_DMA_CTRL1);
- outl(0x00000000, TX3912_UARTA_DMA_CTRL2);
- outl((ctrl1 | TX3912_UART_CTRL1_ENUART), TX3912_UARTA_CTRL1);
-
- /* Loop until the UART is on */
- while(~inl(TX3912_UARTA_CTRL1) & TX3912_UART_CTRL1_UARTON);
-
- return 0;
-}
-
-static struct console sercons = {
- .name = "ttyS",
- .write = serial_console_write,
- .device = serial_console_device,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1
-};
-
-static int __init tx3912_console_init(void)
-{
- register_console(&sercons);
- return 0;
-}
-console_initcall(tx3912_console_init);
-
-#endif
diff -urN linux/drivers/char/serial_tx3912.h linux/drivers/char/serial_tx3912.h
--- linux/drivers/char/Attic/serial_tx3912.h Fri Mar 4 17:24:33 2005
1.3
+++ linux/drivers/char/Attic/serial_tx3912.h 1970/01/01 00:00:002002
@@ -1,58 +0,0 @@
-/*
- * drivers/char/serial_tx3912.h
- *
- * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Serial driver for TMPR3912/05 and PR31700 processors
- */
-#include <linux/serialP.h>
-#include <linux/generic_serial.h>
-
-#undef TX3912_UART_DEBUG
-
-#ifdef TX3912_UART_DEBUG
-#define TX3912_UART_DEBUG_OPEN 0x00000001
-#define TX3912_UART_DEBUG_SETTING 0x00000002
-#define TX3912_UART_DEBUG_FLOW 0x00000004
-#define TX3912_UART_DEBUG_MODEMSIGNALS 0x00000008
-#define TX3912_UART_DEBUG_TERMIOS 0x00000010
-#define TX3912_UART_DEBUG_TRANSMIT 0x00000020
-#define TX3912_UART_DEBUG_RECEIVE 0x00000040
-#define TX3912_UART_DEBUG_INTERRUPTS 0x00000080
-#define TX3912_UART_DEBUG_PROBE 0x00000100
-#define TX3912_UART_DEBUG_INIT 0x00000200
-#define TX3912_UART_DEBUG_CLEANUP 0x00000400
-#define TX3912_UART_DEBUG_CLOSE 0x00000800
-#define TX3912_UART_DEBUG_FIRMWARE 0x00001000
-#define TX3912_UART_DEBUG_MEMTEST 0x00002000
-#define TX3912_UART_DEBUG_THROTTLE 0x00004000
-#define TX3912_UART_DEBUG_NO_TX 0xffffffdf
-#define TX3912_UART_DEBUG_ALL 0xffffffff
-
-#define rs_dprintk(f, str...) if(TX3912_UART_DEBUG_NO_TX & f) printk(str)
-#define func_enter() rs_dprintk(TX3912_UART_DEBUG_FLOW, \
- "rs: enter %s\n", __FUNCTION__)
-#define func_exit() rs_dprintk(TX3912_UART_DEBUG_FLOW, \
- "rs: exit %s\n", __FUNCTION__)
-#else
-#define rs_dprintk(f, str...)
-#define func_enter()
-#define func_exit()
-#endif
-
-/*
- * Hardware specific serial port structure
- */
-struct rs_port {
- struct gs_port gs; /* Must be first field! */
- struct wait_queue *shutdown_wait;
- int stat_flags;
- struct async_icount icount; /* Counters for 4 input IRQs */
- int read_status_mask;
- int ignore_status_mask;
- int x_char; /* XON/XOFF character */
-};
diff -urN linux/drivers/char/serial_txx9.c linux/drivers/char/serial_txx9.c
--- linux/drivers/char/Attic/serial_txx9.c Fri Mar 4 17:24:33 2005
1.5
+++ linux/drivers/char/Attic/serial_txx9.c 1970/01/01 00:00:002002
@@ -1,1744 +0,0 @@
-/*
- * drivers/char/serial_txx9.c
- *
- * Copyright (C) 1999 Harald Koerfgen
- * Copyright (C) 2000 Jim Pick <jim@jimpick.com>
- * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
- * Copyright (C) 2000-2002 Toshiba Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-#include <linux/init.h>
-#include <linux/config.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <linux/serial.h>
-#include <linux/generic_serial.h>
-#include <linux/pci.h>
-#ifdef CONFIG_MAGIC_SYSRQ
-#include <linux/sysrq.h>
-#endif
-#include <asm/irq.h>
-
-#define DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-static char *serial_version = "0.30-mvl";
-static char *serial_name = "TX39/49 Serial driver";
-static struct tty_driver *serial_driver;
-
-#define GS_INTERNAL_FLAGS (GS_TX_INTEN|GS_RX_INTEN|GS_ACTIVE)
-
-#define TXX9_SERIAL_MAGIC 0x39274927
-
-#ifdef CONFIG_SERIAL
-/* "ttyS","cua" is used for standard serial driver */
-#define TXX9_TTY_NAME "ttyTX"
-#define TXX9_TTY_DEVFS_NAME "tts/TX%d"
-#define TXX9_TTY_MINOR_START (64 + 64) /* ttyTX0(128), ttyTX1(129) */
-#define TXX9_CU_NAME "cuatx"
-#define TXX9_CU_DEVFS_NAME "cua/TX%d"
-#else
-/* acts like standard serial driver */
-#define TXX9_TTY_NAME "ttyS"
-#define TXX9_TTY_DEVFS_NAME "tts/%d"
-#define TXX9_TTY_MINOR_START 64
-#define TXX9_CU_NAME "cua"
-#define TXX9_CU_DEVFS_NAME "cua/%d"
-#endif
-#define TXX9_TTY_MAJOR TTY_MAJOR
-#define TXX9_TTYAUX_MAJOR TTYAUX_MAJOR
-
-#define TXX9_SERIAL_HAVE_CTS_LINE 1
-
-#ifdef CONFIG_PCI
-/* support for Toshiba TC86C001 SIO */
-#define ENABLE_SERIAL_TXX9_PCI
-#endif
-
-/*
- * Number of serial ports
- */
-#ifdef ENABLE_SERIAL_TXX9_PCI
-#define NR_PCI_BOARDS 4
-#define NR_PORTS (2 + NR_PCI_BOARDS)
-#else
-#define NR_PORTS 2
-#endif
-
-/*
- * Hardware specific serial port structure
- */
-static struct rs_port {
- struct gs_port gs; /* Must be first field! */
-
- unsigned long base;
- int irq;
- int baud_base;
- int flags;
- struct async_icount icount;
- int x_char; /* XON/XOFF character */
- int read_status_mask;
- int ignore_status_mask;
- int quot;
- char io_type;
-#ifdef ENABLE_SERIAL_TXX9_PCI
- struct pci_dev * pci_dev;
-#endif
-} rs_ports[NR_PORTS]
-#ifdef CONFIG_TOSHIBA_RBTX4925
-= {
- /* NR_PORTS = 0 */
- {base: 0xff1f0000 + 0xf300,
- .irq = 36,
- .baud_base = 40000000 / 16 / 2,
- .io_type = -1, /* virtual memory mapped */
- .flags = TXX9_SERIAL_HAVE_CTS_LINE,},
- /* NR_PORTS = 1 */
- {base: 0xff1f0000 + 0xf400,
- .irq = 37,
- .baud_base = 40000000 / 16 / 2,
- .io_type = -1, /* virtual memory mapped */
- .flags = TXX9_SERIAL_HAVE_CTS_LINE,}
-};
-#endif
-#ifdef CONFIG_TOSHIBA_RBTX4927
-= {
- /* NR_PORTS = 0 */
- {base: 0xff1f0000 + 0xf300,
- .irq = 32,
- .baud_base = 50000000 / 16 / 2,
- .io_type = -1, /* virtual memory mapped */
- .flags = TXX9_SERIAL_HAVE_CTS_LINE,},
- /* NR_PORTS = 1 */
- {base: 0xff1f0000 + 0xf400,
- .irq = 33,
- .baud_base = 50000000 / 16 / 2,
- .io_type = -1, /* virtual memory mapped */
- .flags = TXX9_SERIAL_HAVE_CTS_LINE,}
-};
-#endif
-
-/* TXX9 Serial Registers */
-#define TXX9_SILCR 0x00
-#define TXX9_SIDICR 0x04
-#define TXX9_SIDISR 0x08
-#define TXX9_SICISR 0x0c
-#define TXX9_SIFCR 0x10
-#define TXX9_SIFLCR 0x14
-#define TXX9_SIBGR 0x18
-#define TXX9_SITFIFO 0x1c
-#define TXX9_SIRFIFO 0x20
-
-/* SILCR : Line Control */
-#define TXX9_SILCR_SCS_MASK 0x00000060
-#define TXX9_SILCR_SCS_IMCLK 0x00000000
-#define TXX9_SILCR_SCS_IMCLK_BG 0x00000020
-#define TXX9_SILCR_SCS_SCLK 0x00000040
-#define TXX9_SILCR_SCS_SCLK_BG 0x00000060
-#define TXX9_SILCR_UEPS 0x00000010
-#define TXX9_SILCR_UPEN 0x00000008
-#define TXX9_SILCR_USBL_MASK 0x00000004
-//#define TXX9_SILCR_USBL_1BIT 0x00000004
-//#define TXX9_SILCR_USBL_2BIT 0x00000000
-#define TXX9_SILCR_USBL_1BIT 0x00000000
-#define TXX9_SILCR_USBL_2BIT 0x00000004
-#define TXX9_SILCR_UMODE_MASK 0x00000003
-#define TXX9_SILCR_UMODE_8BIT 0x00000000
-#define TXX9_SILCR_UMODE_7BIT 0x00000001
-
-/* SIDICR : DMA/Int. Control */
-#define TXX9_SIDICR_TDE 0x00008000
-#define TXX9_SIDICR_RDE 0x00004000
-#define TXX9_SIDICR_TIE 0x00002000
-#define TXX9_SIDICR_RIE 0x00001000
-#define TXX9_SIDICR_SPIE 0x00000800
-#define TXX9_SIDICR_CTSAC 0x00000600
-#define TXX9_SIDICR_STIE_MASK 0x0000003f
-#define TXX9_SIDICR_STIE_OERS 0x00000020
-#define TXX9_SIDICR_STIE_CTSS 0x00000010
-#define TXX9_SIDICR_STIE_RBRKD 0x00000008
-#define TXX9_SIDICR_STIE_TRDY 0x00000004
-#define TXX9_SIDICR_STIE_TXALS 0x00000002
-#define TXX9_SIDICR_STIE_UBRKD 0x00000001
-
-/* SIDISR : DMA/Int. Status */
-#define TXX9_SIDISR_UBRK 0x00008000
-#define TXX9_SIDISR_UVALID 0x00004000
-#define TXX9_SIDISR_UFER 0x00002000
-#define TXX9_SIDISR_UPER 0x00001000
-#define TXX9_SIDISR_UOER 0x00000800
-#define TXX9_SIDISR_ERI 0x00000400
-#define TXX9_SIDISR_TOUT 0x00000200
-#define TXX9_SIDISR_TDIS 0x00000100
-#define TXX9_SIDISR_RDIS 0x00000080
-#define TXX9_SIDISR_STIS 0x00000040
-#define TXX9_SIDISR_RFDN_MASK 0x0000001f
-
-/* SICISR : Change Int. Status */
-#define TXX9_SICISR_OERS 0x00000020
-#define TXX9_SICISR_CTSS 0x00000010
-#define TXX9_SICISR_RBRKD 0x00000008
-#define TXX9_SICISR_TRDY 0x00000004
-#define TXX9_SICISR_TXALS 0x00000002
-#define TXX9_SICISR_UBRKD 0x00000001
-
-/* SIFCR : FIFO Control */
-#define TXX9_SIFCR_SWRST 0x00008000
-#define TXX9_SIFCR_RDIL_MASK 0x00000180
-#define TXX9_SIFCR_RDIL_1 0x00000000
-#define TXX9_SIFCR_RDIL_4 0x00000080
-#define TXX9_SIFCR_RDIL_8 0x00000100
-#define TXX9_SIFCR_RDIL_12 0x00000180
-#define TXX9_SIFCR_RDIL_MAX 0x00000180
-#define TXX9_SIFCR_TDIL_MASK 0x00000018
-#define TXX9_SIFCR_TDIL_MASK 0x00000018
-#define TXX9_SIFCR_TDIL_1 0x00000000
-#define TXX9_SIFCR_TDIL_4 0x00000001
-#define TXX9_SIFCR_TDIL_8 0x00000010
-#define TXX9_SIFCR_TDIL_MAX 0x00000010
-#define TXX9_SIFCR_TFRST 0x00000004
-#define TXX9_SIFCR_RFRST 0x00000002
-#define TXX9_SIFCR_FRSTE 0x00000001
-#define TXX9_SIO_TX_FIFO 8
-#define TXX9_SIO_RX_FIFO 16
-
-/* SIFLCR : Flow Control */
-#define TXX9_SIFLCR_RCS 0x00001000
-#define TXX9_SIFLCR_TES 0x00000800
-#define TXX9_SIFLCR_RTSSC 0x00000200
-#define TXX9_SIFLCR_RSDE 0x00000100
-#define TXX9_SIFLCR_TSDE 0x00000080
-#define TXX9_SIFLCR_RTSTL_MASK 0x0000001e
-#define TXX9_SIFLCR_RTSTL_MAX 0x0000001e
-#define TXX9_SIFLCR_TBRK 0x00000001
-
-/* SIBGR : Baudrate Control */
-#define TXX9_SIBGR_BCLK_MASK 0x00000300
-#define TXX9_SIBGR_BCLK_T0 0x00000000
-#define TXX9_SIBGR_BCLK_T2 0x00000100
-#define TXX9_SIBGR_BCLK_T4 0x00000200
-#define TXX9_SIBGR_BCLK_T6 0x00000300
-#define TXX9_SIBGR_BRD_MASK 0x000000ff
-
-static /*inline*/ unsigned int
-sio_in(struct rs_port *port, int offset)
-{
- if (port->io_type < 0)
- /* don't use __raw_readl that does swapping for big endian */
- return (*(volatile unsigned long*)(port->base + offset));
- else
- return inl(port->base + offset);
-}
-
-static /*inline*/ void
-sio_out(struct rs_port *port, int offset, unsigned int value)
-{
- if (port->io_type < 0)
- /* don't use __raw_writel that does swapping for big endian */
- (*(volatile unsigned long*)(port->base + offset))=(value);
- else
- outl(value, port->base + offset);
-}
-
-static inline void
-sio_mask(struct rs_port *port, int offset, unsigned int value)
-{
- sio_out(port, offset, sio_in(port, offset) & ~value);
-}
-static inline void
-sio_set(struct rs_port *port, int offset, unsigned int value)
-{
- sio_out(port, offset, sio_in(port, offset) | value);
-}
-
-/*
- * Forward declarations for serial routines
- */
-static void rs_disable_tx_interrupts (void * ptr);
-static void rs_enable_tx_interrupts (void * ptr);
-static void rs_disable_rx_interrupts (void * ptr);
-static void rs_enable_rx_interrupts (void * ptr);
-static int rs_get_CD (void * ptr);
-static void rs_shutdown_port (void * ptr);
-static int rs_set_real_termios (void *ptr);
-static int rs_chars_in_buffer (void * ptr);
-static void rs_hungup (void *ptr);
-static void rs_getserial (void*, struct serial_struct *sp);
-static void rs_close (void *ptr);
-
-/*
- * Used by generic serial driver to access hardware
- */
-static struct real_driver rs_real_driver = {
- .disable_tx_interrupts = rs_disable_tx_interrupts,
- .enable_tx_interrupts = rs_enable_tx_interrupts,
- .disable_rx_interrupts = rs_disable_rx_interrupts,
- .enable_rx_interrupts = rs_enable_rx_interrupts,
- get_CD: rs_get_CD,
- .shutdown_port = rs_shutdown_port,
- .set_real_termios = rs_set_real_termios,
- .chars_in_buffer = rs_chars_in_buffer,
- .close = rs_close,
- .hungup = rs_hungup,
- .getserial = rs_getserial,
-};
-
-/*
- * Structures and such for TTY sessions and usage counts
- */
-static struct tty_driver rs_driver, rs_callout_driver;
-static struct tty_struct *rs_table[NR_PORTS];
-static struct termios *rs_termios[NR_PORTS];
-static struct termios *rs_termios_locked[NR_PORTS];
-int rs_refcount;
-int rs_initialized = 0;
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
-static struct console sercons;
-#endif
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-static unsigned long break_pressed; /* break, really ... */
-#endif
-
-static inline void receive_chars(struct rs_port *port,
- int *status, struct pt_regs *regs)
-{
- struct tty_struct *tty = port->gs.tty;
- unsigned char ch;
- struct async_icount *icount;
- int max_count = 256;
-
- icount = &port->icount;
- do {
- if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
- return;
- }
- ch = sio_in(port, TXX9_SIRFIFO);
- *tty->flip.char_buf_ptr = ch;
- icount->rx++;
-
- *tty->flip.flag_buf_ptr = 0;
- if (*status & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
- TXX9_SIDISR_UFER | TXX9_SIDISR_UOER)) {
- /*
- * For statistics only
- */
- if (*status & TXX9_SIDISR_UBRK) {
- *status &= ~(TXX9_SIDISR_UFER |
TXX9_SIDISR_UPER);
- icount->brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
- if (port == &rs_ports[sercons.index]) {
- if (!break_pressed) {
- break_pressed = jiffies;
- goto ignore_char;
- }
- break_pressed = 0;
- }
-#endif
- if (port->gs.flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (*status & TXX9_SIDISR_UPER)
- icount->parity++;
- else if (*status & TXX9_SIDISR_UFER)
- icount->frame++;
- if (*status & TXX9_SIDISR_UOER)
- icount->overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- *status &= port->read_status_mask;
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- /* Break flag is updated by reading RFIFO. */
-#endif
- if (*status & (TXX9_SIDISR_UBRK)) {
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- } else if (*status & TXX9_SIDISR_UPER)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- else if (*status & TXX9_SIDISR_UFER)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- }
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
- if (break_pressed && port == &rs_ports[sercons.index]) {
- if (ch != 0 &&
- time_before(jiffies, break_pressed + HZ*5)) {
- handle_sysrq(ch, regs, NULL, NULL);
- break_pressed = 0;
- goto ignore_char;
- }
- break_pressed = 0;
- }
-#endif
- if ((*status & port->ignore_status_mask) == 0) {
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- }
- if ((*status & TXX9_SIDISR_UOER) &&
- (tty->flip.count < TTY_FLIPBUF_SIZE)) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character
- */
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- }
-#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
- ignore_char:
-#endif
- *status = sio_in(port, TXX9_SIDISR);
- } while ((!(*status & TXX9_SIDISR_UVALID)) && (max_count-- > 0));
- tty_flip_buffer_push(tty);
-}
-
-static inline void transmit_chars(struct rs_port *port)
-{
- int count;
-
- if (port->x_char) {
- sio_out(port, TXX9_SITFIFO, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
- if (port->gs.xmit_cnt <= 0
- || port->gs.tty->stopped
- || port->gs.tty->hw_stopped) {
- rs_disable_tx_interrupts(port);
- return;
- }
-
- count = TXX9_SIO_TX_FIFO;
- do {
- sio_out(port, TXX9_SITFIFO,
port->gs.xmit_buf[port->gs.xmit_tail++]);
- port->gs.xmit_tail &= SERIAL_XMIT_SIZE-1;
- port->icount.tx++;
- if (--port->gs.xmit_cnt <= 0)
- break;
- } while (--count > 0);
-
- if (port->gs.xmit_cnt <= 0 || port->gs.tty->stopped ||
- port->gs.tty->hw_stopped) {
- rs_disable_tx_interrupts(port);
- }
-
- if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
- if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- port->gs.tty->ldisc.write_wakeup)
- (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
- wake_up_interruptible(&port->gs.tty->write_wait);
- }
-}
-
-static inline void check_modem_status(struct rs_port *port)
-{
- /* We don't have a carrier detect line - but just respond
- like we had one anyways so that open() becomes unblocked */
- wake_up_interruptible(&port->gs.open_wait);
-}
-
-#define RS_ISR_PASS_LIMIT 256
-
-static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- struct rs_port * port = (struct rs_port *)dev_id;
- unsigned long flags;
- int status;
- int pass_counter = 0;
-
- local_irq_save(flags);
-
- if (!port || !port->gs.tty) {
- local_irq_restore(flags);
- return;
- }
-
- do {
- status = sio_in(port, TXX9_SIDISR);
- if (!(sio_in(port, TXX9_SIDICR) & TXX9_SIDICR_TIE))
- status &= ~TXX9_SIDISR_TDIS;
- if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
- TXX9_SIDISR_TOUT)))
- break;
-
- if (status & TXX9_SIDISR_RDIS)
- receive_chars(port, &status, regs);
-#if 0 /* RTS/CTS are controled by HW. (if possible) */
- check_modem_status(port);
-#endif
- if (status & TXX9_SIDISR_TDIS)
- transmit_chars(port);
- /* Clear TX/RX Int. Status */
- sio_mask(port, TXX9_SIDISR,
- TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
- TXX9_SIDISR_TOUT);
-
- if (pass_counter++ > RS_ISR_PASS_LIMIT) {
- break;
- }
- } while (1);
- local_irq_restore(flags);
-}
-
-/*
- ***********************************************************************
- * Here are the routines that actually *
- * interface with the generic_serial driver *
- ***********************************************************************
- */
-static void rs_disable_tx_interrupts (void * ptr)
-{
- struct rs_port *port = ptr;
- unsigned long flags;
-
- local_irq_save(flags);
- port->gs.flags &= ~GS_TX_INTEN;
- sio_mask(port, TXX9_SIDICR, TXX9_SIDICR_TIE);
- local_irq_restore(flags);
-}
-
-static void rs_enable_tx_interrupts (void * ptr)
-{
- struct rs_port *port = ptr;
- unsigned long flags;
-
- local_irq_save(flags);
- sio_set(port, TXX9_SIDICR, TXX9_SIDICR_TIE);
- local_irq_restore(flags);
-}
-
-static void rs_disable_rx_interrupts (void * ptr)
-{
- struct rs_port *port = ptr;
- unsigned long flags;
-
- local_irq_save(flags);
- port->read_status_mask &= ~TXX9_SIDISR_RDIS;
-#if 0
- sio_mask(port, TXX9_SIDICR, TXX9_SIDICR_RIE);
-#endif
- local_irq_restore(flags);
-}
-
-static void rs_enable_rx_interrupts (void * ptr)
-{
- struct rs_port *port = ptr;
- sio_set(port, TXX9_SIDICR, TXX9_SIDICR_RIE);
-}
-
-
-static int rs_get_CD (void * ptr)
-{
- /* No Carried Detect in Hardware - just return true */
- return (1);
-}
-
-static void rs_shutdown_port (void * ptr)
-{
- struct rs_port *port = ptr;
-
- port->gs.flags &= ~GS_ACTIVE;
-
- free_irq(port->irq, port);
- sio_out(port, TXX9_SIDICR, 0); /* disable all intrs */
- /* disable break condition */
- sio_mask(port, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- if (port == &rs_ports[sercons.index]) {
-#endif
- if (!port->gs.tty || (port->gs.tty->termios->c_cflag & HUPCL)) {
- /* drop RTS */
- sio_set(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- /* TXX9-SIO can not control DTR... */
- }
-
- /* reset FIFO's */
- sio_set(port, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
- /* clear reset */
- sio_mask(port, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
- /* Disable RX/TX */
- sio_set(port, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- }
-#endif
-}
-
-static int rs_set_real_termios (void *ptr)
-{
- struct rs_port *port = ptr;
- int quot = 0, baud_base, baud;
- unsigned cflag, cval, fcr = 0;
- int bits;
- unsigned long flags;
-
- if (!port->gs.tty || !port->gs.tty->termios)
- return 0;
- cflag = port->gs.tty->termios->c_cflag;
- cval = sio_in(port, TXX9_SILCR);
- /* byte size and parity */
- cval &= ~TXX9_SILCR_UMODE_MASK;
- switch (cflag & CSIZE) {
- case CS7:
- cval |= TXX9_SILCR_UMODE_7BIT;
- bits = 9;
- break;
- case CS5: /* not supported */
- case CS6: /* not supported */
- case CS8:
- default:
- cval |= TXX9_SILCR_UMODE_8BIT;
- bits = 10;
- break;
- }
- cval &= ~TXX9_SILCR_USBL_MASK;
- if (cflag & CSTOPB) {
- cval |= TXX9_SILCR_USBL_2BIT;
- bits++;
- } else {
- cval |= TXX9_SILCR_USBL_1BIT;
- }
-
- cval &= ~(TXX9_SILCR_UPEN | TXX9_SILCR_UEPS);
- if (cflag & PARENB) {
- cval |= TXX9_SILCR_UPEN;
- bits++;
- }
- if (!(cflag & PARODD))
- cval |= TXX9_SILCR_UEPS;
-
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(port->gs.tty);
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
- baud_base = port->baud_base;
- quot = (baud_base + baud / 2) / baud;
- /* As a last resort, if the quotient is zero, default to 9600 bps */
- if (!quot)
- quot = (baud_base + 9600 / 2) / 9600;
- port->quot = quot;
-
- /* Set up FIFO's */
- /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
- fcr = TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1;
-
- /* CTS flow control flag */
- if (cflag & CRTSCTS) {
- port->gs.flags |= ASYNC_CTS_FLOW;
- if (port->flags & TXX9_SERIAL_HAVE_CTS_LINE)
- sio_out(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES |
- TXX9_SIFLCR_RTSTL_MAX /* 15 */);
- } else {
- port->gs.flags &= ~ASYNC_CTS_FLOW;
- sio_mask(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES |
- TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
- }
-
- /*
- * Set up parity check flag
- */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- port->read_status_mask = TXX9_SIDISR_UOER |
- TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
- if (I_INPCK(port->gs.tty))
- port->read_status_mask |= TXX9_SIDISR_UFER | TXX9_SIDISR_UPER;
- if (I_BRKINT(port->gs.tty) || I_PARMRK(port->gs.tty))
- port->read_status_mask |= TXX9_SIDISR_UBRK;
-
- /*
- * Characters to ignore
- */
- port->ignore_status_mask = 0;
- if (I_IGNPAR(port->gs.tty))
- port->ignore_status_mask |= TXX9_SIDISR_UPER | TXX9_SIDISR_UFER;
- if (I_IGNBRK(port->gs.tty)) {
- port->ignore_status_mask |= TXX9_SIDISR_UBRK;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (I_IGNPAR(port->gs.tty))
- port->ignore_status_mask |= TXX9_SIDISR_UOER;
- }
-#if 0 /* XXX: This cause problem with some programs(init, mingetty, etc) */
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- port->ignore_status_mask |= TXX9_SIDISR_RDIS;
-#endif
- local_irq_save(flags);
- cval &= ~TXX9_SILCR_SCS_IMCLK;
- sio_out(port, TXX9_SILCR, cval | TXX9_SILCR_SCS_IMCLK_BG);
- sio_out(port, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
- sio_out(port, TXX9_SIFCR, fcr);
- local_irq_restore(flags);
- return 0;
-}
-
-static int rs_chars_in_buffer (void * ptr)
-{
- struct rs_port *port = ptr;
-
- /* return 0 if transmitter disabled. */
- if (sio_in(port, TXX9_SIFLCR) & TXX9_SIFLCR_TSDE)
- return 0;
- return (sio_in(port, TXX9_SICISR) & TXX9_SICISR_TXALS) ? 0 : 1;
-}
-
-/* ********************************************************************** *
- * Here are the routines that actually *
- * interface with the rest of the system *
- * ********************************************************************** */
-static int rs_open (struct tty_struct * tty, struct file * filp)
-{
- struct rs_port *port;
- int retval, line;
-
- if (!rs_initialized) {
- return -EIO;
- }
-
- line = tty->index;
-
- if ((line < 0) || (line >= NR_PORTS))
- return -ENODEV;
-
- /* Pre-initialized already */
- port = & rs_ports[line];
-
- if (!port->base)
- return -ENODEV;
-
- tty->driver_data = port;
- port->gs.tty = tty;
- port->gs.count++;
-
- /*
- * Start up serial port
- */
- retval = gs_init_port(&port->gs);
- if (retval) {
- port->gs.count--;
- return retval;
- }
-
- port->gs.flags |= GS_ACTIVE;
-
- if (port->gs.count == 1) {
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in rs_set_real_termios())
- */
- sio_set(port, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST |
- TXX9_SIFCR_FRSTE);
- /* clear reset */
- sio_mask(port, TXX9_SIFCR,
- TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST |
- TXX9_SIFCR_FRSTE);
- sio_out(port, TXX9_SIDICR, 0);
-
- retval = request_irq(port->irq, rs_interrupt, SA_SHIRQ,
- "serial_txx9", port);
- if (retval) {
- printk(KERN_ERR "serial_txx9: request_irq: err %d\n",
- retval);
- port->gs.count--;
- return retval;
- }
- /*
- * Clear the interrupt registers.
- */
- sio_out(port, TXX9_SIDISR, 0);
-
- /* HW RTS/CTS control */
- if (port->flags & TXX9_SERIAL_HAVE_CTS_LINE)
- sio_out(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES |
- TXX9_SIFLCR_RTSTL_MAX /* 15 */);
- }
-
- /* Enable RX/TX */
- sio_mask(port, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
-
- /*
- * Finally, enable interrupts
- */
- rs_enable_rx_interrupts(port);
-
- /*
- * and set the speed of the serial port
- */
- rs_set_real_termios(port);
-
- retval = gs_block_til_ready(&port->gs, filp);
-
- if (retval) {
- if (port->gs.count == 1) {
- free_irq(port->irq, port);
- }
- port->gs.count--;
- return retval;
- }
- /* tty->low_latency = 1; */
-
- if (port->gs.count == 1)
- rs_set_real_termios(port);
-
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
- if (sercons.cflag && sercons.index == line) {
- tty->termios->c_cflag = sercons.cflag;
- sercons.cflag = 0;
- rs_set_real_termios(port);
- }
-#endif
- return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline int line_info(char *buf, struct rs_port *port)
-{
- char stat_buf[30];
- int ret;
- unsigned long flags;
-
- ret = sprintf(buf, "%d: uart:txx9 io%s:%lx irq:%d",
- port - &rs_ports[0],
- port->io_type < 0 ? "mem" : "port",
- port->base, port->irq);
-
- if (!port->base) {
- ret += sprintf(buf+ret, "\n");
- return ret;
- }
-
- /*
- * Figure out the current RS-232 lines
- */
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- local_irq_save(flags);
- if (!(sio_in(port, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC))
- strcat(stat_buf, "|RTS");
- if (!(sio_in(port, TXX9_SICISR) & TXX9_SICISR_CTSS))
- strcat(stat_buf, "|CTS");
- local_irq_restore(flags);
-
- if (port->quot) {
- ret += sprintf(buf+ret, " baud:%d",
- port->baud_base / port->quot);
- }
-
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- port->icount.tx, port->icount.rx);
-
- if (port->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", port->icount.frame);
-
- if (port->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", port->icount.parity);
-
- if (port->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", port->icount.brk);
-
- if (port->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", port->icount.overrun);
-
- /*
- * Last thing is the RS-232 status lines
- */
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
- return ret;
-}
-
-static int rs_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- int i, len = 0, l;
- off_t begin = 0;
-
- len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
- l = line_info(page + len, &rs_ports[i]);
- len += l;
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- }
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (begin-off);
- return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-static void rs_close (void *ptr)
-{
-#if 0
- struct rs_port *port = ptr;
- free_irq(port->irq, port);
-#endif
-}
-
-/* I haven't the foggiest why the decrement use count has to happen
- here. The whole linux serial drivers stuff needs to be redesigned.
- My guess is that this is a hack to minimize the impact of a bug
- elsewhere. Thinking about it some more. (try it sometime) Try
- running minicom on a serial port that is driven by a modularized
- driver. Have the modem hangup. Then remove the driver module. Then
- exit minicom. I expect an "oops". -- REW */
-static void rs_hungup (void *ptr)
-{
-}
-
-static void rs_getserial (void *ptr, struct serial_struct *sp)
-{
- struct rs_port *port = ptr;
- struct tty_struct *tty = port->gs.tty;
- /* some applications (busybox, dbootstrap, etc.) look this */
- sp->line = tty->index;
-}
-
-/*
- * rs_break() --- routine which turns the break handling on or off
- */
-static void rs_break(struct tty_struct *tty, int break_state)
-{
- struct rs_port *port = tty->driver_data;
- unsigned long flags;
-
- if (!port->base)
- return;
- local_irq_save(flags);
- if (break_state == -1)
- sio_set(port, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
- else
- sio_mask(port, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
- local_irq_restore(flags);
-}
-
-static int get_modem_info(struct rs_port *port, unsigned int *value)
-{
- unsigned int result;
- unsigned long flags;
-
- local_irq_save(flags);
- result = ((sio_in(port, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC) ? 0 :
TIOCM_RTS)
- | ((sio_in(port, TXX9_SICISR) & TXX9_SICISR_CTSS) ? 0 :
TIOCM_CTS);
- local_irq_restore(flags);
- return put_user(result,value);
-}
-
-static int set_modem_info(struct rs_port *port, unsigned int cmd,
- unsigned int *value)
-{
- int error = 0;
- unsigned int arg;
- unsigned long flags;
-
- if (copy_from_user(&arg, value, sizeof(int)))
- return -EFAULT;
-
- local_irq_save(flags);
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- sio_mask(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- sio_set(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- break;
- case TIOCMSET:
- if (arg & TIOCM_RTS)
- sio_mask(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- else
- sio_set(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- break;
- default:
- error = -EINVAL;
- }
- local_irq_restore(flags);
- return error;
-}
-
-static int rs_ioctl (struct tty_struct * tty, struct file * filp,
- unsigned int cmd, unsigned long arg)
-{
- int rc;
- struct rs_port *port = tty->driver_data;
- int ival;
-
- rc = 0;
- switch (cmd) {
- case TIOCMGET:
- return get_modem_info(port, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(port, cmd, (unsigned int *) arg);
- return 0;
- case TIOCGSOFTCAR:
- rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
- (unsigned int *) arg);
- break;
- case TIOCSSOFTCAR:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(int))) == 0) {
- get_user(ival, (unsigned int *) arg);
- tty->termios->c_cflag =
- (tty->termios->c_cflag & ~CLOCAL) |
- (ival ? CLOCAL : 0);
- }
- break;
- case TIOCGSERIAL:
- if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
- sizeof(struct serial_struct))) == 0)
- rc = gs_getserial(&port->gs, (struct serial_struct *)
arg);
- break;
- case TIOCSSERIAL:
- if ((rc = verify_area(VERIFY_READ, (void *) arg,
- sizeof(struct serial_struct))) == 0)
- rc = gs_setserial(&port->gs, (struct serial_struct *)
arg);
- break;
- default:
- rc = -ENOIOCTLCMD;
- break;
- }
-
- return rc;
-}
-
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_send_xchar(struct tty_struct * tty, char ch)
-{
- struct rs_port *port = (struct rs_port *)tty->driver_data;
-
- port->x_char = ch;
- if (ch) {
- /* Make sure transmit interrupts are on */
- rs_enable_tx_interrupts(tty);
- }
-}
-
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
- struct rs_port *port = (struct rs_port *)tty->driver_data;
- unsigned long flags;
-
- if (I_IXOFF(tty))
- rs_send_xchar(tty, STOP_CHAR(tty));
- if (tty->termios->c_cflag & CRTSCTS) {
- local_irq_save(flags);
- /* drop RTS */
- sio_set(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- local_irq_restore(flags);
- }
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
- struct rs_port *port = tty->driver_data;
- unsigned long flags;
-
- if (I_IXOFF(tty)) {
- if (port->x_char)
- port->x_char = 0;
- else
- rs_send_xchar(tty, START_CHAR(tty));
- }
- if (tty->termios->c_cflag & CRTSCTS) {
- local_irq_save(flags);
- sio_mask(port, TXX9_SIFLCR,
- TXX9_SIFLCR_RTSSC | TXX9_SIFLCR_RSDE);
- local_irq_restore(flags);
- }
-}
-
-/* ********************************************************************** *
- * Here are the initialization routines. *
- * ********************************************************************** */
-
-static inline void show_serial_version(void)
-{
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-static int rs_init_portstructs(void)
-{
- struct rs_port *port;
- int i;
-
- /* Adjust the values in the "driver" */
- rs_driver.termios = rs_termios;
- rs_driver.termios_locked = rs_termios_locked;
-
- port = rs_ports;
- for (i=0; i < NR_PORTS;i++) {
- port->gs.magic = TXX9_SERIAL_MAGIC;
- port->gs.close_delay = HZ/2;
- port->gs.closing_wait = 30 * HZ;
- port->gs.rd = &rs_real_driver;
-#ifdef NEW_WRITE_LOCKING
- port->gs.port_write_sem = MUTEX;
-#endif
-#ifdef DECLARE_WAITQUEUE
- init_waitqueue_head(&port->gs.open_wait);
- init_waitqueue_head(&port->gs.close_wait);
-#endif
- port++;
- }
-
- return 0;
-}
-
-static int rs_init_drivers(void)
-{
- int error;
-
- memset(&rs_driver, 0, sizeof(rs_driver));
- rs_driver.magic = TTY_DRIVER_MAGIC;
- rs_driver.driver_name = "serial_txx9";
-#if defined(CONFIG_DEVFS_FS)
- rs_driver.name = TXX9_TTY_DEVFS_NAME;
-#else
- rs_driver.name = TXX9_TTY_NAME;
-#endif
- rs_driver.major = TXX9_TTY_MAJOR;
- rs_driver.minor_start = TXX9_TTY_MINOR_START;
- rs_driver.num = NR_PORTS;
- rs_driver.type = TTY_DRIVER_TYPE_SERIAL;
- rs_driver.subtype = SERIAL_TYPE_NORMAL;
- rs_driver.init_termios = tty_std_termios;
- rs_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- rs_driver.refcount = &rs_refcount;
- rs_driver.termios = rs_termios;
- rs_driver.termios_locked = rs_termios_locked;
-
- rs_driver.open = rs_open;
- rs_driver.close = gs_close;
- rs_driver.write = gs_write;
- rs_driver.put_char = gs_put_char;
- rs_driver.flush_chars = gs_flush_chars;
- rs_driver.write_room = gs_write_room;
- rs_driver.chars_in_buffer = gs_chars_in_buffer;
- rs_driver.flush_buffer = gs_flush_buffer;
- rs_driver.ioctl = rs_ioctl;
- rs_driver.throttle = rs_throttle;
- rs_driver.unthrottle = rs_unthrottle;
- rs_driver.set_termios = gs_set_termios;
- rs_driver.stop = gs_stop;
- rs_driver.start = gs_start;
- rs_driver.hangup = gs_hangup;
- rs_driver.break_ctl = rs_break;
- rs_driver.read_proc = rs_read_proc;
-
- rs_callout_driver = rs_driver;
-#if defined(CONFIG_DEVFS_FS)
- rs_callout_driver.name = TXX9_CU_DEVFS_NAME;
-#else
- rs_callout_driver.name = TXX9_CU_NAME;
-#endif
- if ((error = tty_register_driver(&rs_driver))) {
- printk(KERN_ERR
- "Couldn't register serial driver, error = %d\n",
- error);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * This routine is called by txx9_rs_init() to initialize a specific serial
- * port.
- */
-static void txx9_config(struct rs_port *port)
-{
- unsigned long flags;
-
- if (port - &rs_ports[0] != sercons.index) {
- local_irq_save(flags);
- /*
- * Reset the UART.
- */
- sio_out(port, TXX9_SIFCR, TXX9_SIFCR_SWRST);
-#ifdef CONFIG_CPU_TX49XX
- /* TX4925 BUG WORKAROUND. Accessing SIOC register
- * immediately after soft reset causes bus error. */
- wbflush();/* change iob(); */
- udelay(1);
-#endif
- while (sio_in(port, TXX9_SIFCR) & TXX9_SIFCR_SWRST)
- ;
- /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
- sio_set(port, TXX9_SIFCR,
- TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
- /* initial settings */
- sio_out(port, TXX9_SILCR,
- TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
- TXX9_SILCR_SCS_IMCLK_BG);
- sio_out(port, TXX9_SIBGR,
- ((port->baud_base + 9600 / 2) / 9600) |
- TXX9_SIBGR_BCLK_T0);
- local_irq_restore(flags);
- }
- DBG("txx9_config: port->io_type is %d\n", port->io_type);
- if (port->io_type < 0)
- request_mem_region(port->base, 36, "serial_txx9");
- else
- request_region(port->base, 36, "serial_txx9");
-}
-
-#ifdef ENABLE_SERIAL_TXX9_PCI
-static int __devinit serial_txx9_init_one(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- int rc, i;
- struct rs_port *port;
-
- rc = pci_enable_device(dev);
- if (rc) return rc;
-
- /* find empty slot */
- for (i = 0; i < NR_PORTS && rs_ports[i].base; i++)
- ;
- if (i == NR_PORTS)
- return -ENODEV;
- port = &rs_ports[i];
- DBG("port number is %d\n",i);
-
- port->pci_dev = dev;
- port->base = pci_resource_start(dev, 1);
-
- DBG("port->base is %x\n",(u32)port->base);
- port->io_type = SERIAL_IO_PORT;
- port->irq = dev->irq;
- port->flags |= TXX9_SERIAL_HAVE_CTS_LINE;
- port->baud_base = 66670000 / 16 / 2; /* 66.67MHz */
- DBG("port->baud_base %x\n",port->baud_base);
-
- txx9_config(port);
-
- printk(KERN_INFO
- "%s%d at 0x%08lx (irq = %d) is a TX39/49 SIO\n",
- TXX9_TTY_NAME, i, port->base, port->irq);
- return 0;
-}
-
-static void __devexit serial_txx9_remove_one(struct pci_dev *dev)
-{
- int i;
- for (i = 0; i < NR_PORTS; i++) {
- if (rs_ports[i].pci_dev == dev) {
- rs_ports[i].irq = 0;
- rs_ports[i].base = 0;
- rs_ports[i].pci_dev = 0;
- /* XXX NOT IMPLEMENTED YET */
- break;
- }
- }
-}
-
-static struct pci_device_id serial_txx9_pci_tbl[] __devinitdata = {
-#ifdef PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC
- { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- 0 },
-#endif
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
-
-static struct pci_driver serial_txx9_pci_driver = {
- .name = "serial_txx9",
- .probe = serial_txx9_init_one,
- .remove = __devexit_p(serial_txx9_remove_one),
- .id_table = serial_txx9_pci_tbl,
-};
-
-/*
- * Query PCI space for known serial boards
- * If found, add them to the PCI device space in rs_table[]
- */
-static void __devinit probe_serial_txx9_pci(void)
-{
- /* Register call PCI serial devices. Null out
- * the driver name upon failure, as a signal
- * not to attempt to unregister the driver later
- */
- if (pci_module_init (&serial_txx9_pci_driver) != 0)
- serial_txx9_pci_driver.name = "";
-
- return;
-}
-#endif /* ENABLE_SERIAL_TXX9_PCI */
-
-static int __init txx9_rs_init(void)
-{
- int rc;
- struct rs_port *port;
- int i;
-
-#ifndef ENABLE_SERIAL_TXX9_PCI
- for (i = 0, port = &rs_ports[0]; i < NR_PORTS; i++,port++) {
- if (port->base)
- goto config_ok;
- }
- return -ENODEV;
- config_ok:
-#endif
-
- show_serial_version();
- rc = rs_init_portstructs ();
- rs_init_drivers ();
- for (i = 0, port = &rs_ports[0]; i < NR_PORTS; i++,port++) {
- if (!port->base)
- continue;
- if (port->io_type < 0) {
- if (check_mem_region(port->base, 36))
- continue;
- } else {
- if (check_region(port->base, 36))
- continue;
- }
- txx9_config(port);
- printk(KERN_INFO
- "%s%d at 0x%08lx (irq = %d) is a TX39/49 SIO\n",
- TXX9_TTY_NAME, i, port->base, port->irq);
- }
-
- /* Note: I didn't do anything to enable the second UART */
- if (rc >= 0)
- rs_initialized++;
-
-#ifdef ENABLE_SERIAL_TXX9_PCI
- probe_serial_txx9_pci();
-#endif
- return 0;
-}
-
-/*
- * This is for use by architectures that know their serial console
- * attributes only at run time. Not to be invoked after rs_init().
- */
-int __init early_serial_txx9_setup(int line, unsigned long base, int irq,
- int baud_base, int have_cts)
-{
- if (line >= NR_PORTS)
- return(-ENOENT);
- rs_ports[line].base = base;
- rs_ports[line].irq = irq;
- rs_ports[line].baud_base = baud_base;
- rs_ports[line].io_type = -1; /* virtual memory mapped */
- if (have_cts)
- rs_ports[line].flags |= TXX9_SERIAL_HAVE_CTS_LINE;
- return(0);
-}
-
-static void __exit txx9_rs_fini(void)
-{
- unsigned long flags;
- int e1, e2;
- int i;
-
- local_irq_save(flags);
- if ((e1 = tty_unregister_driver(&rs_driver)))
- printk("serial: failed to unregister serial driver (%d)\n",
- e1);
- if ((e2 = tty_unregister_driver(&rs_callout_driver)))
- printk("serial: failed to unregister callout driver (%d)\n",
- e2);
- local_irq_restore(flags);
-
- for (i = 0; i < NR_PORTS; i++) {
- if (!rs_ports[i].base)
- continue;
- if (rs_ports[i].io_type < 0)
- release_mem_region(rs_ports[i].base, 36);
- else
- release_region(rs_ports[i].base, 36);
- }
-
-#ifdef ENABLE_SERIAL_PCI
- if (serial_txx9_pci_driver.name[0])
- pci_unregister_driver (&serial_txx9_pci_driver);
-#endif
-}
-
-module_init(txx9_rs_init);
-module_exit(txx9_rs_fini);
-MODULE_DESCRIPTION("TX39/49 serial driver");
-MODULE_AUTHOR("TOSHIBA Corporation");
-MODULE_LICENSE("GPL");
-
-/*
- * Begin serial console routines
- */
-#ifdef CONFIG_SERIAL_TXX9_CONSOLE
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct rs_port *port)
-{
- unsigned int tmout = 1000000;
-
- do {
- if (--tmout == 0) break;
- } while (!(sio_in(port, TXX9_SICISR) & TXX9_SICISR_TXALS));
-
- /* Wait for flow control if necessary */
-#if (ASYNC_INTERNAL_FLAGS & GS_INTERNAL_FLAGS) == 0 /* check conflict... */
- if (port->gs.flags & ASYNC_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- (sio_in(port, TXX9_SICISR) & TXX9_SICISR_CTSS));
- }
-#endif
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void serial_console_write(struct console *co, const char *s,
- unsigned count)
-{
- struct rs_port *port = &rs_ports[co->index];
- int ier;
- unsigned i;
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = sio_in(port, TXX9_SIDICR);
- sio_out(port, TXX9_SIDICR, 0);
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++, s++) {
- wait_for_xmitr(port);
-
- /*
- * Send the character out.
- * If a LF, also do CR...
- */
- sio_out(port, TXX9_SITFIFO, *s);
- if (*s == 10) {
- wait_for_xmitr(port);
- sio_out(port, TXX9_SITFIFO, 13);
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- wait_for_xmitr(port);
- sio_out(port, TXX9_SIDICR, ier);
-}
-
-static struct tty_driver *serial_console_device(struct console *c, int *index)
-{
- *index = c->index;
- return &rs_driver;
-}
-
-static int serial_console_setup(struct console *co, char *options)
-{
- struct rs_port *port;
- unsigned cval;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int doflow = 0;
- int cflag = CREAD | HUPCL | CLOCAL;
- int quot = 0;
- char *s;
-
- if (co->index < 0 || co->index >= NR_PORTS)
- return -1;
- if (options) {
- baud = simple_strtoul(options, NULL, 10);
- s = options;
- while(*s >= '0' && *s <= '9')
- s++;
- if (*s) parity = *s++;
- if (*s) bits = *s - '0';
- if (*s) doflow = (*s++ == 'r');
- }
-
- /*
- * Now construct a cflag setting.
- */
- switch(baud) {
- case 1200: cflag |= B1200; break;
- case 2400: cflag |= B2400; break;
- case 4800: cflag |= B4800; break;
- case 19200: cflag |= B19200; break;
- case 38400: cflag |= B38400; break;
- case 57600: cflag |= B57600; break;
- case 115200: cflag |= B115200; break;
- default:
- /*
- * Set this to a sane value to prevent a divide error
- */
- baud = 9600;
- case 9600: cflag |= B9600; break;
- }
-
- switch(bits) {
- case 7: cflag |= CS7; break;
- default:
- case 8: cflag |= CS8; break;
- }
- switch(parity) {
- case 'o': case 'O': cflag |= PARODD; break;
- case 'e': case 'E': cflag |= PARENB; break;
- }
- co->cflag = cflag;
-
- port = &rs_ports[co->index];
- if (!port->base)
- return -1;
-
- /*
- * Divisor, bytesize and parity
- */
-#if (ASYNC_INTERNAL_FLAGS & GS_INTERNAL_FLAGS) == 0 /* check conflict... */
- if (doflow)
- port->gs.flags |= ASYNC_CONS_FLOW;
-#endif
- quot = port->baud_base / baud;
- switch (cflag & CSIZE) {
- case CS7: cval = TXX9_SILCR_UMODE_7BIT; break;
- default:
- case CS8: cval = TXX9_SILCR_UMODE_8BIT; break;
- }
- if (cflag & CSTOPB)
- cval |= TXX9_SILCR_USBL_2BIT;
- else
- cval |= TXX9_SILCR_USBL_1BIT;
- if (cflag & PARENB)
- cval |= TXX9_SILCR_UPEN;
- if (!(cflag & PARODD))
- cval |= TXX9_SILCR_UEPS;
-
- /*
- * Disable UART interrupts, set DTR and RTS high
- * and set speed.
- */
- sio_out(port, TXX9_SIDICR, 0);
- sio_out(port, TXX9_SILCR, cval | TXX9_SILCR_SCS_IMCLK_BG);
- sio_out(port, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
- /* no RTS/CTS control */
- sio_out(port, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
- /* Enable RX/TX */
- sio_mask(port, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
-
- /* console port should not use RTC/CTS. */
- port->flags &= ~TXX9_SERIAL_HAVE_CTS_LINE;
- return 0;
-}
-
-static struct console sercons = {
- .name = TXX9_TTY_NAME,
- .write = serial_console_write,
- .device = serial_console_device,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int __init txx9_serial_console_init(void)
-{
- register_console(&sercons);
-
- return 0;
-}
-
-console_initcall(txx9_serial_console_init);
-
-#endif
-
-/******************************************************************************/
-/* BEG: KDBG Routines
*/
-/******************************************************************************/
-
-#ifdef CONFIG_KGDB
-int kgdb_init_count = 0;
-
-void txx9_sio_kgdb_hook(unsigned int port, unsigned int baud_rate)
-{
- static struct resource kgdb_resource;
- int ret;
-
- /* prevent initialization by driver */
- kgdb_resource.name = "serial_txx9(debug)";
- kgdb_resource.start = rs_ports[port].base;
- kgdb_resource.end = rs_ports[port].base + 36 - 1;
- kgdb_resource.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-
- ret = request_resource(&iomem_resource, &kgdb_resource);
- if(ret == -EBUSY)
- printk(" serial_txx9(debug): request_resource failed\n");
-
- return;
-}
-void
-txx9_sio_kdbg_init( unsigned int port_number )
-{
- if ( port_number == 1 ) {
- txx9_sio_kgdb_hook( port_number, 38400 );
- } else {
- printk("Bad Port Number [%u] != [1]\n",port_number);
- }
- return;
-}
-
-u8
-txx9_sio_kdbg_rd( void )
-{
- unsigned int status,ch;
-
- if ( kgdb_init_count == 0 )
- {
- txx9_sio_kdbg_init( 1 );
- kgdb_init_count = 1;
- }
-
- while ( 1 )
- {
- status = sio_in(&rs_ports[1], TXX9_SIDISR);
- if ( status & 0x1f )
- {
- ch = sio_in(&rs_ports[1], TXX9_SIRFIFO );
- break;
- }
- }
-
- return( ch );
-}
-
-int
-txx9_sio_kdbg_wr( u8 ch )
-{
- unsigned int status;
-
- if ( kgdb_init_count == 0 )
- {
- txx9_sio_kdbg_init( 1 );
- kgdb_init_count = 1;
- }
-
- while ( 1 )
- {
- status = sio_in(&rs_ports[1], TXX9_SICISR);
- if (status & TXX9_SICISR_TRDY)
- {
- if ( ch == '\n' )
- {
- txx9_sio_kdbg_wr( '\r' );
- }
- sio_out(&rs_ports[1], TXX9_SITFIFO, (u32)ch );
-
- break;
- }
- }
-
- return( 1 );
-}
-#endif /* CONFIG_KGDB */
-
-
-/******************************************************************************/
-/* END: KDBG Routines
*/
-/******************************************************************************/
-
-
-void txx9_raw_output(char c)
-{
- struct rs_port *port = &rs_ports[0];
- if ( c == '\n' )
- {
- sio_out(port, TXX9_SITFIFO, '\r');
- wait_for_xmitr(port);
- }
- sio_out(port, TXX9_SITFIFO, c);
- wait_for_xmitr(port);
- return;
-}
-
-
diff -urN linux/drivers/char/serial_txx927.c linux/drivers/char/serial_txx927.c
--- linux/drivers/char/Attic/serial_txx927.c Fri Mar 4 17:24:33 2005
1.4
+++ linux/drivers/char/Attic/serial_txx927.c 1970/01/01 00:00:002002
@@ -1,2331 +0,0 @@
-/*
- * drivers/char/serial_txx927.c
- * driver for TX[34]927 SIO
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- * ahennessy@mvista.com
- *
- * Based on drivers/char/serial.c
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-#undef SERIAL_DEBUG_PCI
-#undef SERIAL_DEBUG_AUTOCONF
-
-#ifdef MODULE
-#undef CONFIG_TXX927_SERIAL_CONSOLE
-#endif
-
-#define CONFIG_SERIAL_RSA
-
-#define RS_STROBE_TIME (10*HZ)
-#define RS_ISR_PASS_LIMIT 256
-
-/*
- * End of serial driver configuration section.
- */
-
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
-#include <linux/module.h>
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/circ_buf.h>
-#include <linux/serial_reg.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/serialP.h>
-#include <linux/delay.h>
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
-#include <linux/console.h>
-#endif
-#ifdef CONFIG_MAGIC_SYSRQ
-#include <linux/sysrq.h>
-#endif
-
-#include <asm/system.h>
-#include <asm/serial.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-#include <asm/jmr3927/txx927.h>
-#include <asm/bootinfo.h>
-#ifdef CONFIG_TOSHIBA_JMR3927
-#include <asm/jmr3927/jmr3927.h>
-#endif
-
-#define _INLINE_ inline
-
-#ifdef CONFIG_MAC_SERIAL
-#define SERIAL_DEV_OFFSET 2
-#else
-#define SERIAL_DEV_OFFSET 0
-#endif
-
-static char *serial_name = "TXx927 Serial driver";
-static char *serial_version = "0.02";
-
-static DECLARE_TASK_QUEUE(tq_serial);
-
-static struct tty_driver serial_driver, callout_driver;
-static int serial_refcount;
-
-static struct timer_list serial_timer;
-
-extern unsigned long get_txx927_uart_baud(void);
-
-/* serial subtype definitions */
-#ifndef SERIAL_TYPE_NORMAL
-#define SERIAL_TYPE_NORMAL 1
-#define SERIAL_TYPE_CALLOUT 2
-#endif
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/*
- * IRQ_timeout - How long the timeout should be for each IRQ
- * should be after the IRQ has been active.
- */
-
-static struct async_struct *IRQ_ports[NR_IRQS];
-static int IRQ_timeout[NR_IRQS];
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
-static struct console sercons;
-#endif
-#if defined(CONFIG_TXX927_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-static unsigned long break_pressed; /* break, really ... */
-#endif
-
-static void change_speed(struct async_struct *info, struct termios *old);
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-
-#ifndef PREPARE_FUNC
-#define PREPARE_FUNC(dev) (dev->prepare)
-#define ACTIVATE_FUNC(dev) (dev->activate)
-#define DEACTIVATE_FUNC(dev) (dev->deactivate)
-#endif
-
-#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-
-
-#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- kdevname(tty->device), (info->flags),
serial_refcount,info->count,tty->count,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-#define SERIAL_DRIVER_NAME "TXx927SIO"
-
-#ifdef CONFIG_SERIAL
-/* "ttyS","cua" is used for standard serial driver */
-#define TXX927_TTY_NAME "ttySC"
-#define TXX927_TTY_MINOR_START (64 + 16) /* ttySC0(80), ttySC1(81) */
-#define TXX927_CU_NAME "cuac"
-#define TXX927_SERIAL_BH TXX927SERIAL_BH
-#else
-/* acts like standard serial driver */
-#define TXX927_TTY_NAME "ttyS"
-#define TXX927_TTY_MINOR_START 64
-#define TXX927_CU_NAME "cua"
-#define TXX927_SERIAL_BH SERIAL_BH
-#endif
-#define TXX927_TTY_MAJOR TTY_MAJOR
-#define TXX927_TTYAUX_MAJOR TTYAUX_MAJOR
-
-#define ASYNC_HAVE_CTS_LINE ASYNC_BOOT_AUTOCONF /* reuse */
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
- SERIAL_PORT_DFNS /* Defined in serial.h */
-};
-
-#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
-
-static struct tty_struct *serial_table[NR_PORTS];
-static struct termios *serial_termios[NR_PORTS];
-static struct termios *serial_termios_locked[NR_PORTS];
-
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf;
-#ifdef DECLARE_MUTEX
-static DECLARE_MUTEX(tmp_buf_sem);
-#else
-static struct semaphore tmp_buf_sem = MUTEX;
-#endif
-
-static inline int serial_paranoia_check(struct async_struct *info,
- kdev_t device, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
- static const char *badmagic =
- "Warning: bad magic number for serial struct (%s) in %s\n";
- static const char *badinfo =
- "Warning: null async_struct for (%s) in %s\n";
-
- if (!info) {
- printk(badinfo, kdevname(device), routine);
- return 1;
- }
- if (info->magic != SERIAL_MAGIC) {
- printk(badmagic, kdevname(device), routine);
- return 1;
- }
-#endif
- return 0;
-}
-
-static inline struct txx927_sio_reg *sio_reg(struct async_struct *info)
-{
- return (struct txx927_sio_reg *)info->port;
-}
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct async_struct *info)
-{
- unsigned int tmout = 1000000;
-
- do {
- if (--tmout == 0) break;
- } while (!(sio_reg(info)->cisr & TXx927_SICISR_TXALS));
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_stop(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_stop"))
- return;
-
- save_flags(flags); cli();
- if (info->IER & UART_IER_THRI) {
- info->IER &= ~UART_IER_THRI;
- sio_reg(info)->dicr &= ~TXx927_SIDICR_TIE;
- }
- restore_flags(flags);
-}
-
-static void rs_start(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_start"))
- return;
-
- save_flags(flags); cli();
- if (info->xmit.head != info->xmit.tail
- && info->xmit.buf
- && !(info->IER & UART_IER_THRI)) {
- info->IER |= UART_IER_THRI;
- sio_reg(info)->dicr |= TXx927_SIDICR_TIE;
- }
- restore_flags(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines. All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt(). They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off. People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible. After you are done making modifications, it is not a bad
- * idea to do:
- *
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * - Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static _INLINE_ void rs_sched_event(struct async_struct *info,
- int event)
-{
- info->event |= 1 << event;
- queue_task(&info->tqueue, &tq_serial);
- mark_bh(TXX927_SERIAL_BH);
-}
-
-static _INLINE_ void receive_chars(struct async_struct *info,
- int *status)
-{
- struct tty_struct *tty = info->tty;
- unsigned char ch;
- int ignored = 0;
- struct async_icount *icount;
-
- icount = &info->state->icount;
- do {
- ch = sio_reg(info)->rfifo;
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
- *tty->flip.char_buf_ptr = ch;
- icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
- printk("DR%02x:%02x...", ch, *status);
-#endif
- *tty->flip.flag_buf_ptr = 0;
- if (*status & (TXx927_SIDISR_UBRK | TXx927_SIDISR_UPER |
- TXx927_SIDISR_UFER | TXx927_SIDISR_UOER)) {
- /*
- * For statistics only
- */
- if (*status & TXx927_SIDISR_UBRK) {
- *status &= ~(TXx927_SIDISR_UFER |
TXx927_SIDISR_UPER);
- icount->brk++;
- } else if (*status & TXx927_SIDISR_UPER)
- icount->parity++;
- else if (*status & TXx927_SIDISR_UFER)
- icount->frame++;
- if (*status & TXx927_SIDISR_UOER)
- icount->overrun++;
-
- /*
- * Now check to see if character should be
- * ignored, and mask off conditions which
- * should be ignored.
- */
- if (*status & info->ignore_status_mask) {
- if (++ignored > 100)
- break;
- goto ignore_char;
- }
- *status &= info->read_status_mask;
-
- if (*status & (TXx927_SIDISR_UBRK)) {
-#ifdef SERIAL_DEBUG_INTR
- printk("handling break....");
-#endif
- *tty->flip.flag_buf_ptr = TTY_BREAK;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- } else if (*status & TXx927_SIDISR_UPER)
- *tty->flip.flag_buf_ptr = TTY_PARITY;
- else if (*status & TXx927_SIDISR_UFER)
- *tty->flip.flag_buf_ptr = TTY_FRAME;
- if (*status & TXx927_SIDISR_UOER) {
- /*
- * Overrun is special, since it's
- * reported immediately, and doesn't
- * affect the current character
- */
- if (tty->flip.count < TTY_FLIPBUF_SIZE) {
- tty->flip.count++;
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- *tty->flip.flag_buf_ptr = TTY_OVERRUN;
- }
- }
- }
- tty->flip.flag_buf_ptr++;
- tty->flip.char_buf_ptr++;
- tty->flip.count++;
- ignore_char:
- *status = sio_reg(info)->disr;
- } while (!(*status & TXx927_SIDISR_UVALID));
-
- tty_flip_buffer_push(tty);
-}
-
-static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
-{
- int count;
-
- wait_for_xmitr(info);
-
- if (info->x_char) {
- sio_reg(info)->tfifo = info->x_char;
- info->state->icount.tx++;
- info->x_char = 0;
- if (intr_done)
- *intr_done = 0;
- return;
- }
-
- if (info->xmit.head == info->xmit.tail
- || info->tty->stopped
- || info->tty->hw_stopped) {
- sio_reg(info)->dicr &= ~TXx927_SIDICR_TIE;
- return;
- }
-
- count = info->xmit_fifo_size;
- do {
- sio_reg(info)->tfifo = info->xmit.buf[info->xmit.tail++];
- info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
- info->state->icount.tx++;
- if (info->xmit.head == info->xmit.tail)
- break;
- } while (--count > 0);
-
- if (CIRC_CNT(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-
-#ifdef SERIAL_DEBUG_INTR
- printk("THRE...");
-#endif
- if (intr_done)
- *intr_done = 0;
-
- if (info->xmit.head == info->xmit.tail) {
- sio_reg(info)->dicr &= ~TXx927_SIDICR_TIE;
- }
-}
-
-static _INLINE_ void check_modem_status(struct async_struct *info)
-{
- /* RTS/CTS are controled by HW. (if possible) */
-}
-
-/*
- * This is the serial driver's interrupt routine for a single port
- */
-static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
-{
- int status;
- int pass_counter = 0;
- struct async_struct * info;
-
-#ifdef SERIAL_DEBUG_INTR
- printk("rs_interrupt_single(%d)...", irq);
-#endif
-
- info = IRQ_ports[irq];
- if (!info || !info->tty)
- return;
-
- do {
- status = sio_reg(info)->disr;
-#ifdef SERIAL_DEBUG_INTR
- printk("status = %x...", status);
-#endif
- if (!(sio_reg(info)->dicr & TXx927_SIDICR_TIE))
- status &= ~TXx927_SIDISR_TDIS;
- if (!(status & (TXx927_SIDISR_TDIS | TXx927_SIDISR_RDIS |
TXx927_SIDISR_TOUT)))
- break;
-
- if (status & TXx927_SIDISR_RDIS)
- receive_chars(info, &status);
- check_modem_status(info);
- if (status & TXx927_SIDISR_TDIS)
- transmit_chars(info, 0);
- /* Clear TX/RX Int. Status */
- sio_reg(info)->disr &= ~(TXx927_SIDISR_TDIS |
TXx927_SIDISR_RDIS | TXx927_SIDISR_TOUT);
-
- if (pass_counter++ > RS_ISR_PASS_LIMIT) {
-#ifdef SERIAL_DEBUG_INTR
- printk("rs_single loop break.\n");
-#endif
- break;
- }
- } while (1);
- info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
- printk("end.\n");
-#endif
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-static void do_serial_bh(void)
-{
- run_task_queue(&tq_serial);
-}
-
-static void do_softint(void *private_)
-{
- struct async_struct *info = (struct async_struct *) private_;
- struct tty_struct *tty;
-
- tty = info->tty;
- if (!tty)
- return;
-
- if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
- wake_up_interruptible(&tty->write_wait);
-#ifdef SERIAL_HAVE_POLL_WAIT
- wake_up_interruptible(&tty->poll_wait);
-#endif
- }
-}
-
-/*
- * This subroutine is called when the RS_TIMER goes off. It is used
- * by the serial driver to handle ports that do not have an interrupt
- * (irq=0). This doesn't work very well for 16450's, but gives barely
- * passable results for a 16550A. (Although at the expense of much
- * CPU overhead).
- */
-static void rs_timer(unsigned long dummy)
-{
- static unsigned long last_strobe;
- struct async_struct *info;
- unsigned int i;
- unsigned long flags;
-
- if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
- for (i=0; i < NR_IRQS; i++) {
- info = IRQ_ports[i];
- if (!info)
- continue;
- save_flags(flags); cli();
- rs_interrupt_single(i, NULL, NULL);
- restore_flags(flags);
- }
- }
- last_strobe = jiffies;
- mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
-
-#if 0
- if (IRQ_ports[0]) {
- save_flags(flags); cli();
- rs_interrupt_single(0, NULL, NULL);
- restore_flags(flags);
-
- mod_timer(&serial_timer, jiffies + IRQ_timeout[0]);
- }
-#endif
-}
-
-/*
- * ---------------------------------------------------------------
- * Low level utility subroutines for the serial driver: routines to
- * figure out the appropriate timeout for an interrupt chain, routines
- * to initialize and startup a serial port, and routines to shutdown a
- * serial port. Useful stuff like that.
- * ---------------------------------------------------------------
- */
-
-/*
- * This routine figures out the correct timeout for a particular IRQ.
- * It uses the smallest timeout of all of the serial ports in a
- * particular interrupt chain. Now only used for IRQ 0....
- */
-static void figure_IRQ_timeout(int irq)
-{
- struct async_struct *info;
- int timeout = 60*HZ; /* 60 seconds === a long time :-) */
-
- info = IRQ_ports[irq];
- if (!info) {
- IRQ_timeout[irq] = 60*HZ;
- return;
- }
- while (info) {
- if (info->timeout < timeout)
- timeout = info->timeout;
- info = info->next_port;
- }
- if (!irq)
- timeout = timeout / 2;
- IRQ_timeout[irq] = timeout ? timeout : 1;
-}
-
-static int startup(struct async_struct * info)
-{
- unsigned long flags;
- int retval=0;
- struct serial_state *state= info->state;
- unsigned long page;
-
- page = get_zeroed_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- save_flags(flags); cli();
-
- if (info->flags & ASYNC_INITIALIZED) {
- free_page(page);
- goto errout;
- }
-
- if (!state->port) {
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
- free_page(page);
- goto errout;
- }
- if (info->xmit.buf)
- free_page(page);
- else
- info->xmit.buf = (unsigned char *) page;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("starting up ttys%d (irq %d)...", info->line, state->irq);
-#endif
-
- /*
- * Clear the FIFO buffers and disable them
- * (they will be reenabled in change_speed())
- */
- sio_reg(info)->fcr |= TXx927_SIFCR_TFRST | TXx927_SIFCR_RFRST |
- TXx927_SIFCR_FRSTE;
- /* clear reset */
- sio_reg(info)->fcr &= ~(TXx927_SIFCR_TFRST | TXx927_SIFCR_RFRST |
- TXx927_SIFCR_FRSTE);
-
- /*
- * Allocate the IRQ if necessary
- */
- if (state->irq && (!IRQ_ports[state->irq] ||
- !IRQ_ports[state->irq]->next_port)) {
- if (IRQ_ports[state->irq]) {
- retval = -EBUSY;
- goto errout;
- }
-
- retval = request_irq(state->irq, rs_interrupt_single,
- SA_INTERRUPT,
- "txx927serial", NULL);
- if (retval) {
- if (capable(CAP_SYS_ADMIN)) {
- if (info->tty)
- set_bit(TTY_IO_ERROR,
- &info->tty->flags);
- retval = 0;
- }
- goto errout;
- }
- }
-
- /*
- * Insert serial port into IRQ chain.
- */
- info->prev_port = 0;
- info->next_port = IRQ_ports[state->irq];
- if (info->next_port)
- info->next_port->prev_port = info;
- IRQ_ports[state->irq] = info;
- figure_IRQ_timeout(state->irq);
-
- /*
- * Clear the interrupt registers.
- */
- sio_reg(info)->disr = 0;
-
- /*
- * Now, initialize the UART
- */
- /* HW RTS/CTS control */
- if (state->flags & ASYNC_HAVE_CTS_LINE)
- sio_reg(info)->flcr = TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES |
- TXx927_SIFLCR_RTSTL_MAX /* 15 */;
- /* Enable RX/TX */
- sio_reg(info)->flcr &= ~(TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE);
-
- /*
- * Finally, enable interrupts
- */
- sio_reg(info)->dicr = TXx927_SIDICR_RIE;
-
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
- info->xmit.head = info->xmit.tail = 0;
-
- /*
- * Set up the tty->alt_speed kludge
- */
- if (info->tty) {
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
- info->tty->alt_speed = 57600;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
- info->tty->alt_speed = 115200;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
- info->tty->alt_speed = 230400;
- if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
- info->tty->alt_speed = 460800;
- }
-
- /*
- * and set the speed of the serial port
- */
- change_speed(info, 0);
-
- info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
- return 0;
-
-errout:
- restore_flags(flags);
- return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct async_struct * info)
-{
- unsigned long flags;
- struct serial_state *state;
- int retval;
-
- if (!(info->flags & ASYNC_INITIALIZED))
- return;
-
- state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("Shutting down serial port %d (irq %d)....", info->line,
- state->irq);
-#endif
-
- save_flags(flags); cli(); /* Disable interrupts */
-
- /*
- * First unlink the serial port from the IRQ chain...
- */
- if (info->next_port)
- info->next_port->prev_port = info->prev_port;
- if (info->prev_port)
- info->prev_port->next_port = info->next_port;
- else
- IRQ_ports[state->irq] = info->next_port;
- figure_IRQ_timeout(state->irq);
-
- /*
- * Free the IRQ, if necessary
- */
- if (state->irq && (!IRQ_ports[state->irq] ||
- !IRQ_ports[state->irq]->next_port)) {
- if (IRQ_ports[state->irq]) {
- free_irq(state->irq, NULL);
- retval = request_irq(state->irq, rs_interrupt_single,
- SA_INTERRUPT, "txx927serial",
NULL);
-
- if (retval)
- printk(KERN_WARNING "txx927serial shutdown:
request_irq: error %d"
- " Couldn't reacquire IRQ.\n", retval);
- } else
- free_irq(state->irq, NULL);
- }
-
- if (info->xmit.buf) {
- free_page((unsigned long) info->xmit.buf);
- info->xmit.buf = 0;
- }
-
- sio_reg(info)->dicr = 0; /* disable all intrs */
-
- /* disable break condition */
- sio_reg(info)->flcr &= ~TXx927_SIFLCR_TBRK;
-
- if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
- /* drop RTS */
- sio_reg(info)->flcr |= TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE;
- /* TXx927-SIO can not control DTR... */
- }
-
- /* reset FIFO's */
- sio_reg(info)->fcr |= TXx927_SIFCR_TFRST | TXx927_SIFCR_RFRST |
- TXx927_SIFCR_FRSTE;
- /* clear reset */
- sio_reg(info)->fcr &= ~(TXx927_SIFCR_TFRST | TXx927_SIFCR_RFRST |
- TXx927_SIFCR_FRSTE);
-
- /* DON'T disable Rx/Tx here, ie. DON'T set either
- * TXx927_SIFLCR_RSDE or TXx927_SIFLCR_TSDE in flcr
- */
-
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
-
- info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(struct async_struct *info,
- struct termios *old_termios)
-{
- int quot = 0, baud_base, baud;
- unsigned cflag, cval;
- int bits;
- unsigned long flags;
-
- if (!info->tty || !info->tty->termios)
- return;
- cflag = info->tty->termios->c_cflag;
- if (!info->port)
- return;
-
- cval = sio_reg(info)->lcr;
- /* byte size and parity */
- cval &= ~TXx927_SILCR_UMODE_MASK;
- switch (cflag & CSIZE) {
- case CS7:
- cval |= TXx927_SILCR_UMODE_7BIT;
- bits = 9;
- break;
- case CS5: /* not supported */
- case CS6: /* not supported */
- case CS8:
- default:
- cval |= TXx927_SILCR_UMODE_8BIT;
- bits = 10;
- break;
- }
- cval &= ~TXx927_SILCR_USBL_MASK;
- if (cflag & CSTOPB) {
- cval |= TXx927_SILCR_USBL_2BIT;
- bits++;
- } else {
- cval |= TXx927_SILCR_USBL_1BIT;
- }
-
- cval &= ~(TXx927_SILCR_UPEN|TXx927_SILCR_UEPS);
- if (cflag & PARENB) {
- cval |= TXx927_SILCR_UPEN;
- bits++;
- }
- if (!(cflag & PARODD))
- cval |= TXx927_SILCR_UEPS;
-
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(info->tty);
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
- baud_base = info->state->baud_base;
- quot = (baud_base + baud / 2) / baud;
- /* If the quotient is zero refuse the change */
- if (!quot && old_termios) {
- info->tty->termios->c_cflag &= ~CBAUD;
- info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
- baud = tty_get_baud_rate(info->tty);
- if (!baud)
- baud = 9600;
- quot = (baud_base + baud / 2) / baud;
- }
- /* As a last resort, if the quotient is zero, default to 9600 bps */
- if (!quot)
- quot = (baud_base + 9600 / 2) / 9600;
- info->quot = quot;
- info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
- info->timeout += HZ/50; /* Add .02 seconds of slop */
-
- /* CTS flow control flag */
- if (cflag & CRTSCTS) {
- info->flags |= ASYNC_CTS_FLOW;
- if (info->state->flags & ASYNC_HAVE_CTS_LINE)
- sio_reg(info)->flcr = TXx927_SIFLCR_RCS |
TXx927_SIFLCR_TES |
- TXx927_SIFLCR_RTSTL_MAX /* 15 */;
- } else {
- info->flags &= ~ASYNC_CTS_FLOW;
- sio_reg(info)->flcr &= ~(TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES
| TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE);
- }
-
- /*
- * Set up parity check flag
- */
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
- info->read_status_mask = TXx927_SIDISR_UOER |
- TXx927_SIDISR_TDIS | TXx927_SIDISR_RDIS;
- if (I_INPCK(info->tty))
- info->read_status_mask |= TXx927_SIDISR_UFER |
TXx927_SIDISR_UPER;
- if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
- info->read_status_mask |= TXx927_SIDISR_UBRK;
-
- /*
- * Characters to ignore
- */
- info->ignore_status_mask = 0;
- if (I_IGNPAR(info->tty))
- info->ignore_status_mask |= TXx927_SIDISR_UPER |
TXx927_SIDISR_UFER;
- if (I_IGNBRK(info->tty)) {
- info->ignore_status_mask |= TXx927_SIDISR_UBRK;
- /*
- * If we're ignore parity and break indicators, ignore
- * overruns too. (For real raw support).
- */
- if (I_IGNPAR(info->tty))
- info->ignore_status_mask |= TXx927_SIDISR_UOER;
- }
- /*
- * !!! ignore all characters if CREAD is not set
- */
- if ((cflag & CREAD) == 0)
- info->ignore_status_mask |= TXx927_SIDISR_RDIS;
- save_flags(flags); cli();
- sio_reg(info)->lcr = cval | TXx927_SILCR_SCS_IMCLK_BG;
- sio_reg(info)->bgr = quot | TXx927_SIBGR_BCLK_T0;
- restore_flags(flags);
-}
-
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_put_char"))
- return;
-
- if (!tty || !info->xmit.buf)
- return;
-
- save_flags(flags); cli();
- if (CIRC_SPACE(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE) == 0) {
- restore_flags(flags);
- return;
- }
-
- info->xmit.buf[info->xmit.head++] = ch;
- info->xmit.head &= SERIAL_XMIT_SIZE-1;
- restore_flags(flags);
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
- return;
-
- if (info->xmit.head == info->xmit.tail
- || tty->stopped
- || tty->hw_stopped
- || !info->xmit.buf)
- return;
-
- save_flags(flags); cli();
- sio_reg(info)->dicr |= TXx927_SIDICR_TIE;
- restore_flags(flags);
-}
-
-static int rs_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count)
-{
- int c, ret = 0;
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_write"))
- return 0;
-
- if (!tty || !info->xmit.buf || !tmp_buf)
- return 0;
-
- save_flags(flags);
-
- if (from_user) {
- down(&tmp_buf_sem);
- while (1) {
- int c1;
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
-
- if (count < c)
- c = count;
- if (c <= 0)
- break;
-
- c -= copy_from_user(tmp_buf, buf, c);
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- cli();
- c1 = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
-
- if (c1 < c)
- c = c1;
- memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
- }
- up(&tmp_buf_sem);
- } else {
- cli();
- while (1) {
- c = CIRC_SPACE_TO_END(info->xmit.head,
- info->xmit.tail,
- SERIAL_XMIT_SIZE);
-
- if (count < c)
- c = count;
- if (c <= 0) {
- break;
- }
- memcpy(info->xmit.buf + info->xmit.head, buf, c);
- info->xmit.head = ((info->xmit.head + c) &
- (SERIAL_XMIT_SIZE-1));
- buf += c;
- count -= c;
- ret += c;
- }
- restore_flags(flags);
- }
- if (info->xmit.head != info->xmit.tail
- && !tty->stopped
- && !tty->hw_stopped
- && !(info->IER & UART_IER_THRI))
- sio_reg(info)->dicr |= TXx927_SIDICR_TIE;
-
- return ret;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->device, "rs_write_room"))
- return 0;
-
- return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
- return 0;
-
- return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
- return;
- save_flags(flags); cli();
- info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
- wake_up_interruptible(&tty->write_wait);
-#ifdef SERIAL_HAVE_POLL_WAIT
- wake_up_interruptible(&tty->poll_wait);
-#endif
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_send_xchar(struct tty_struct *tty, char ch)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
-
-
- if (serial_paranoia_check(info, tty->device, "rs_send_char"))
- return;
-
- info->x_char = ch;
- if (ch) {
- /* Make sure transmit interrupts are on */
- sio_reg(info)->dicr |= TXx927_SIDICR_TIE;
- }
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("throttle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->device, "rs_throttle"))
- return;
-
- if (I_IXOFF(tty))
- rs_send_xchar(tty, STOP_CHAR(tty));
-
- if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags); cli();
- /* drop RTS */
- sio_reg(info)->flcr |= TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE;
- restore_flags(flags);
- }
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
- char buf[64];
-
- printk("unthrottle %s: %d....\n", tty_name(tty, buf),
- tty->ldisc.chars_in_buffer(tty));
-#endif
-
- if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
- return;
-
- if (I_IXOFF(tty)) {
- if (info->x_char)
- info->x_char = 0;
- else
- rs_send_xchar(tty, START_CHAR(tty));
- }
- if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags); cli();
- sio_reg(info)->flcr &=
~(TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE);
- restore_flags(flags);
- }
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_modem_info(struct async_struct * info, unsigned int *value)
-{
- unsigned int result;
- unsigned long flags;
-
- save_flags(flags); cli();
- result = ((sio_reg(info)->flcr & TXx927_SIFLCR_RTSSC) ? 0 : TIOCM_RTS)
- | ((sio_reg(info)->cisr & TXx927_SICISR_CTSS) ? 0 : TIOCM_CTS);
- restore_flags(flags);
- return put_user(result,value);
-}
-
-static int set_modem_info(struct async_struct * info, unsigned int cmd,
- unsigned int *value)
-{
- int error;
- unsigned int arg;
- unsigned long flags;
-
- error = get_user(arg, value);
- if (error)
- return error;
- save_flags(flags); cli();
- switch (cmd) {
- case TIOCMBIS:
- if (arg & TIOCM_RTS)
- sio_reg(info)->flcr &=
~(TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE);
- break;
- case TIOCMBIC:
- if (arg & TIOCM_RTS)
- sio_reg(info)->flcr |=
TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE;
- break;
- case TIOCMSET:
- sio_reg(info)->flcr =
- (sio_reg(info)->flcr &
~(TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE)) |
- ((arg & TIOCM_RTS) ? 0 :
TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE);
- break;
- default:
- error = -EINVAL;
- }
- restore_flags(flags);
- return error;
-}
-
-/*
- * rs_break() --- routine which turns the break handling on or off
- */
-static void rs_break(struct tty_struct *tty, int break_state)
-{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
-
- if (serial_paranoia_check(info, tty->device, "rs_break"))
- return;
-
- if (!info->port)
- return;
- save_flags(flags); cli();
- if (break_state == -1)
- sio_reg(info)->flcr |= TXx927_SIFLCR_TBRK;
- else
- sio_reg(info)->flcr &= ~TXx927_SIFLCR_TBRK;
- restore_flags(flags);
-}
-
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
-
- if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
- return -ENODEV;
-
- if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
- if (tty->flags & (1 << TTY_IO_ERROR))
- return -EIO;
- }
-
- switch (cmd) {
- case TIOCMGET:
- return get_modem_info(info, (unsigned int *) arg);
- case TIOCMBIS:
- case TIOCMBIC:
- case TIOCMSET:
- return set_modem_info(info, cmd, (unsigned int *) arg);
- return 0;
- case TIOCGSERIAL:
- printk("TIOCGSERIAL\n");
- return 0;
- case TIOCSSERIAL:
- printk("TIOCSSERIAL\n");
- return 0;
- case TIOCSERCONFIG:
- printk("TIOCSERCONFIG\n");
- return 0;
-
- case TIOCSERGETLSR: /* Get line status register */
- printk("TIOCSERGETLSR\n");
- return 0;
-
- case TIOCSERGSTRUCT:
- printk("TIOCSERGSTRUCT\n");
- return 0;
-
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
- printk("TIOCMIWAIT\n");
- return 0;
-
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- printk("TIOCGICOUNT\n");
- return 0;
-
- case TIOCSERGWILD:
- case TIOCSERSWILD:
- /* "setserial -W" is called in Debian boot */
- printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
- return 0;
-
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
-static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
- unsigned long flags;
- unsigned int cflag = tty->termios->c_cflag;
-
- if ( (cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
- change_speed(info, old_termios);
-
- /* Handle transition to B0 status */
- if ((old_termios->c_cflag & CBAUD) &&
- !(cflag & CBAUD)) {
- save_flags(flags); cli();
- sio_reg(info)->flcr |= TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE;
- restore_flags(flags);
- }
-
- /* Handle transition away from B0 status */
- if (!(old_termios->c_cflag & CBAUD) &&
- (cflag & CBAUD)) {
- if (!(tty->termios->c_cflag & CRTSCTS) ||
- !test_bit(TTY_THROTTLED, &tty->flags)) {
- save_flags(flags); cli();
- sio_reg(info)->flcr &=
~(TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE);
- restore_flags(flags);
- }
- }
-
- /* Handle turning off CRTSCTS */
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- rs_start(tty);
- }
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- *
- * This routine is called when the serial port gets closed. First, we
- * wait for the last remaining data to be sent. Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_close(struct tty_struct *tty, struct file * filp)
-{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- struct serial_state *state;
- unsigned long flags;
-
- if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
- return;
-
- state = info->state;
-
- save_flags(flags); cli();
-
- if (tty_hung_up_p(filp)) {
- restore_flags(flags);
- return;
- }
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
- if ((tty->count == 1) && (state->count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. state->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk(KERN_WARNING "rs_close: bad serial port count;
tty->count is 1, "
- "state->count is %d\n", state->count);
- state->count = 1;
- }
- if (--state->count < 0) {
- printk(KERN_WARNING "rs_close: bad serial port count for
ttys%d: %d\n",
- info->line, state->count);
- state->count = 0;
- }
- if (state->count) {
- restore_flags(flags);
- return;
- }
- info->flags |= ASYNC_CLOSING;
- /*
- * Save the termios structure, since this port may have
- * separate termios for callout and dialin.
- */
- if (info->flags & ASYNC_NORMAL_ACTIVE)
- info->state->normal_termios = *tty->termios;
- if (info->flags & ASYNC_CALLOUT_ACTIVE)
- info->state->callout_termios = *tty->termios;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->closing_wait);
- /*
- * At this point we stop accepting input. To do this, we
- * disable the receive line status interrupts, and tell the
- * interrupt driver to stop checking the data ready bit in the
- * line status register.
- */
- info->read_status_mask &= ~TXx927_SIDISR_RDIS;
- if (info->flags & ASYNC_INITIALIZED) {
-#if 0
- sio_reg(info)->dicr &= ~TXx927_SIDICR_RIE;
-#endif
- /*
- * Before we drop DTR, make sure the UART transmitter
- * has completely drained; this is especially
- * important if there is a transmit FIFO!
- */
- rs_wait_until_sent(tty, info->timeout);
- }
- shutdown(info);
- if (tty->driver.flush_buffer)
- tty->driver.flush_buffer(tty);
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
- tty->closing = 0;
- info->event = 0;
- info->tty = 0;
- if (info->blocked_open) {
- if (info->close_delay) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(info->close_delay);
- }
- wake_up_interruptible(&info->open_wait);
- }
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
- ASYNC_CLOSING);
- wake_up_interruptible(&info->close_wait);
- restore_flags(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- unsigned long orig_jiffies, char_time;
- int cisr;
-
- if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
- return;
-
- if (info->xmit_fifo_size == 0)
- return; /* Just in case.... */
-
- orig_jiffies = jiffies;
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
- char_time = char_time / 5;
- if (char_time == 0)
- char_time = 1;
- if (timeout)
- char_time = MIN(char_time, timeout);
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than info->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*info->timeout.
- */
- if (!timeout || timeout > 2*info->timeout)
- timeout = 2*info->timeout;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
- printk("jiff=%lu...", jiffies);
-#endif
- while (!((cisr = sio_reg(info)->cisr) & TXx927_SICISR_TXALS)) {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("cisr = %d (jiff=%lu)...", cisr, jiffies);
-#endif
- __set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
- if (signal_pending(current))
- break;
- if (timeout && time_after(jiffies, orig_jiffies + timeout))
- break;
- }
- current->state = TASK_RUNNING;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk("cisr = %d (jiff=%lu)...done\n", cisr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_hangup(struct tty_struct *tty)
-{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
- struct serial_state *state = info->state;
-
- if (serial_paranoia_check(info, tty->device, "rs_hangup"))
- return;
-
- state = info->state;
-
- rs_flush_buffer(tty);
- shutdown(info);
- info->event = 0;
- state->count = 0;
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
- info->tty = 0;
- wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
- struct async_struct *info)
-{
- DECLARE_WAITQUEUE(wait, current);
- struct serial_state *state = info->state;
- int retval;
- int do_clocal = 0, extra_count = 0;
- unsigned long flags;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- return ((info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * If this is a callout device, then just make sure the normal
- * device isn't being used.
- */
- if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
- if (info->flags & ASYNC_NORMAL_ACTIVE)
- return -EBUSY;
- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_SESSION_LOCKOUT) &&
- (info->session != current->session))
- return -EBUSY;
- if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_PGRP_LOCKOUT) &&
- (info->pgrp != current->pgrp))
- return -EBUSY;
- info->flags |= ASYNC_CALLOUT_ACTIVE;
- return 0;
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- if (info->flags & ASYNC_CALLOUT_ACTIVE)
- return -EBUSY;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (info->flags & ASYNC_CALLOUT_ACTIVE) {
- if (state->normal_termios.c_cflag & CLOCAL)
- do_clocal = 1;
- } else {
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
- }
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, state->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready before block: ttys%d, count = %d\n",
- state->line, state->count);
-#endif
- save_flags(flags); cli();
- if (!tty_hung_up_p(filp)) {
- extra_count = 1;
- state->count--;
- }
- restore_flags(flags);
- info->blocked_open++;
- while (1) {
- save_flags(flags); cli();
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (tty->termios->c_cflag & CBAUD))
- sio_reg(info)->flcr &=
~(TXx927_SIFLCR_RTSSC|TXx927_SIFLCR_RSDE);
- restore_flags(flags);
- current->state = TASK_INTERRUPTIBLE;
- if (tty_hung_up_p(filp) ||
- !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
- retval = -EAGAIN;
-#endif
- break;
- }
- if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
- !(info->flags & ASYNC_CLOSING))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
- schedule();
- }
- current->state = TASK_RUNNING;
- remove_wait_queue(&info->open_wait, &wait);
- if (extra_count)
- state->count++;
- info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
- printk("block_til_ready after blocking: ttys%d, count = %d\n",
- info->line, state->count);
-#endif
- if (retval)
- return retval;
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
-}
-
-static int get_async_struct(int line, struct async_struct **ret_info)
-{
- struct async_struct *info;
- struct serial_state *sstate;
-
-#ifdef REMOTE_DEBUG
- if (kdb_port_info.state && line == kdb_port_info.line)
- return -ENODEV;
-#endif
- sstate = rs_table + line;
- sstate->count++;
- if (sstate->info) {
- *ret_info = sstate->info;
- return 0;
- }
- info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
- if (!info) {
- sstate->count--;
- return -ENOMEM;
- }
- memset(info, 0, sizeof(struct async_struct));
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->delta_msr_wait);
- info->magic = SERIAL_MAGIC;
- info->port = sstate->port;
- info->flags = sstate->flags;
- info->io_type = sstate->io_type;
- info->xmit_fifo_size = sstate->xmit_fifo_size;
- info->line = line;
- info->tqueue.routine = do_softint;
- info->tqueue.data = info;
- info->state = sstate;
- if (sstate->info) {
- kfree(info);
- *ret_info = sstate->info;
- return 0;
- }
- *ret_info = sstate->info = info;
- return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_open(struct tty_struct *tty, struct file * filp)
-{
- struct async_struct *info;
- int retval, line;
- unsigned long page;
-
- line = minor(tty->device) - tty->driver.minor_start;
- if ((line < 0) || (line >= NR_PORTS)) {
- return -ENODEV;
- }
- retval = get_async_struct(line, &info);
- if (retval) {
- return retval;
- }
- tty->driver_data = info;
- info->tty = tty;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
- info->state->count);
-#endif
- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- if (!tmp_buf) {
- page = get_free_page(GFP_KERNEL);
- if (!page) {
- return -ENOMEM;
- }
- if (tmp_buf)
- free_page(page);
- else
- tmp_buf = (unsigned char *) page;
- }
-
- /*
- * If the port is the middle of closing, bail out now
- */
- if (tty_hung_up_p(filp) ||
- (info->flags & ASYNC_CLOSING)) {
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- return ((info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
- return -EAGAIN;
-#endif
- }
-
- /*
- * Start up serial port
- */
- retval = startup(info);
- if (retval) {
- return retval;
- }
-
- retval = block_til_ready(tty, filp, info);
- if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open returning after block_til_ready with %d\n",
- retval);
-#endif
- return retval;
- }
-
- if ((info->state->count == 1) &&
- (info->flags & ASYNC_SPLIT_TERMIOS)) {
- if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
- *tty->termios = info->state->normal_termios;
- else
- *tty->termios = info->state->callout_termios;
- change_speed(info, 0);
- }
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
- if (sercons.cflag && sercons.index == line) {
- tty->termios->c_cflag = sercons.cflag;
- sercons.cflag = 0;
- change_speed(info, 0);
- }
-#endif
- info->session = current->session;
- info->pgrp = current->pgrp;
-
-#ifdef SERIAL_DEBUG_OPEN
- printk("rs_open ttys%d successful...", info->line);
-#endif
- return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline int line_info(char *buf, struct serial_state *state)
-{
- struct async_struct *info = state->info, scr_info;
- char stat_buf[30];
- int ret;
- unsigned long flags;
-
- ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d",
- state->line, SERIAL_DRIVER_NAME,
- state->port, state->irq);
-
- if (!state->port) {
- ret += sprintf(buf+ret, "\n");
- return ret;
- }
-
- /*
- * Figure out the current RS-232 lines
- */
- if (!info) {
- info = &scr_info; /* This is just for serial_{in,out} */
-
- info->magic = SERIAL_MAGIC;
- info->port = state->port;
- info->flags = state->flags;
- info->quot = 0;
- info->tty = 0;
- }
-
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- save_flags(flags); cli();
- if (!(sio_reg(info)->flcr & TXx927_SIFLCR_RTSSC))
- strcat(stat_buf, "|RTS");
- if (!(sio_reg(info)->cisr & TXx927_SICISR_CTSS))
- strcat(stat_buf, "|CTS");
- restore_flags(flags);
-
- if (info->quot) {
- ret += sprintf(buf+ret, " baud:%d",
- state->baud_base / info->quot);
- }
-
- ret += sprintf(buf+ret, " tx:%d rx:%d",
- state->icount.tx, state->icount.rx);
-
- if (state->icount.frame)
- ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
-
- if (state->icount.parity)
- ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
-
- if (state->icount.brk)
- ret += sprintf(buf+ret, " brk:%d", state->icount.brk);
-
- if (state->icount.overrun)
- ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
-
- /*
- * Last thing is the RS-232 status lines
- */
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
- return ret;
-}
-
-static int rs_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- int i, len = 0, l;
- off_t begin = 0;
-
- len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
- l = line_info(page + len, &rs_table[i]);
- len += l;
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- }
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (begin-off);
- return ((count < begin+len-off) ? count : begin+len-off);
-}
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static _INLINE_ void show_serial_version(void)
-{
- printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-/*
- * The serial driver boot-time initialization code!
- */
-static int __init rs_init(void)
-{
- int i;
- struct serial_state * state;
-
- if (rs_table[0].port == 0)
- return -ENODEV;
-
- init_bh(TXX927_SERIAL_BH, do_serial_bh);
- init_timer(&serial_timer);
- serial_timer.function = rs_timer;
- mod_timer(&serial_timer, jiffies + RS_STROBE_TIME);
-
- for (i = 0; i < NR_IRQS; i++) {
- IRQ_ports[i] = 0;
- IRQ_timeout[i] = 0;
- }
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
- /*
- * The interrupt of the serial console port
- * can't be shared.
- */
- if (sercons.flags & CON_CONSDEV) {
- for(i = 0; i < NR_PORTS; i++)
- if (i != sercons.index &&
- rs_table[i].irq == rs_table[sercons.index].irq)
- rs_table[i].irq = 0;
- }
-#endif
- show_serial_version();
-
- /* Initialize the tty_driver structure */
-
- memset(&serial_driver, 0, sizeof(struct tty_driver));
- serial_driver.magic = TTY_DRIVER_MAGIC;
- serial_driver.driver_name = "txx927serial";
-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
- serial_driver.name = "tts/%d";
-#else
- serial_driver.name = "ttyS";
-#endif
- serial_driver.major = TXX927_TTY_MAJOR;
- serial_driver.minor_start = TXX927_TTY_MINOR_START + SERIAL_DEV_OFFSET;
- serial_driver.num = NR_PORTS;
- serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver.subtype = SERIAL_TYPE_NORMAL;
- serial_driver.init_termios = tty_std_termios;
- serial_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
- serial_driver.refcount = &serial_refcount;
- serial_driver.table = serial_table;
- serial_driver.termios = serial_termios;
- serial_driver.termios_locked = serial_termios_locked;
-
- serial_driver.open = rs_open;
- serial_driver.close = rs_close;
- serial_driver.write = rs_write;
- serial_driver.put_char = rs_put_char;
- serial_driver.flush_chars = rs_flush_chars;
- serial_driver.write_room = rs_write_room;
- serial_driver.chars_in_buffer = rs_chars_in_buffer;
- serial_driver.flush_buffer = rs_flush_buffer;
- serial_driver.ioctl = rs_ioctl;
- serial_driver.throttle = rs_throttle;
- serial_driver.unthrottle = rs_unthrottle;
- serial_driver.send_xchar = rs_send_xchar;
- serial_driver.set_termios = rs_set_termios;
- serial_driver.stop = rs_stop;
- serial_driver.start = rs_start;
- serial_driver.hangup = rs_hangup;
- serial_driver.break_ctl = rs_break;
- serial_driver.wait_until_sent = rs_wait_until_sent;
- serial_driver.read_proc = rs_read_proc;
-
- /*
- * The callout device is just like normal device except for
- * major number and the subtype code.
- */
- callout_driver = serial_driver;
-#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
- callout_driver.name = "cua/%d";
-#else
- callout_driver.name = "cua";
-#endif
- callout_driver.major = TTYAUX_MAJOR;
- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- callout_driver.read_proc = 0;
- callout_driver.proc_entry = 0;
-
- if (tty_register_driver(&serial_driver)){
- panic("Couldn't register serial driver\n");
- }
- if (tty_register_driver(&callout_driver)) {
- panic("Couldn't register callout driver\n");
- }
-
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- state->magic = SSTATE_MAGIC;
- state->line = i;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->callout_termios = callout_driver.init_termios;
- state->normal_termios = serial_driver.init_termios;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- state->irq = irq_cannonicalize(state->irq);
- state->xmit_fifo_size = TXx927_SIO_TX_FIFO;
- if (state->hub6)
- state->io_type = SERIAL_IO_HUB6;
- if (state->port) {
- continue;
- }
- }
-
- for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
- if (state->type == PORT_UNKNOWN) {
- continue;
- }
- printk(KERN_INFO "%s%02d at 0x%04lx (irq = %d) is a %s\n",
- TXX927_TTY_NAME,
- state->line,
- state->port, state->irq,
- SERIAL_DRIVER_NAME);
- tty_register_devfs(&serial_driver, 0,
- serial_driver.minor_start + state->line);
- tty_register_devfs(&callout_driver, 0,
- callout_driver.minor_start + state->line);
- }
- return 0;
-}
-
-static void __exit rs_fini(void)
-{
- unsigned long flags;
- int e1, e2;
- int i;
- struct async_struct *info;
-
- del_timer_sync(&serial_timer);
- save_flags(flags); cli();
- remove_bh(TXX927_SERIAL_BH);
- if ((e1 = tty_unregister_driver(&serial_driver)))
- printk(KERN_WARNING "serial: failed to unregister serial driver
(%d)\n",
- e1);
- if ((e2 = tty_unregister_driver(&callout_driver)))
- printk(KERN_WARNING "serial: failed to unregister callout
driver (%d)\n",
- e2);
- restore_flags(flags);
-
- for (i = 0; i < NR_PORTS; i++) {
- if ((info = rs_table[i].info)) {
- rs_table[i].info = NULL;
- kfree(info);
- }
- }
- if (tmp_buf) {
- unsigned long pg = (unsigned long) tmp_buf;
- tmp_buf = NULL;
- free_page(pg);
- }
-}
-
-module_init(rs_init);
-module_exit(rs_fini);
-MODULE_DESCRIPTION("TXX927 serial driver");
-
-/*
- * ------------------------------------------------------------
- * Serial console driver
- * ------------------------------------------------------------
- */
-#ifdef CONFIG_TXX927_SERIAL_CONSOLE
-
-static struct async_struct async_sercons;
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- */
-static void serial_console_write(struct console *co, const char *s,
- unsigned count)
-{
- static struct async_struct *info = &async_sercons;
- int ier;
- unsigned i;
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = sio_reg(info)->dicr;
- sio_reg(info)->dicr = 0;
-
-
- /*
- * Now, do each character
- */
- for (i = 0; i < count; i++, s++) {
- wait_for_xmitr(info);
-
- /*
- * Send the character out.
- * If a LF, also do CR...
- */
- sio_reg(info)->tfifo = *s;
- if (*s == 10) {
- wait_for_xmitr(info);
- sio_reg(info)->tfifo = 13;
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- wait_for_xmitr(info);
- sio_reg(info)->dicr = ier;
-}
-
-static kdev_t serial_console_device(struct console *c)
-{
- return mk_kdev(TXX927_TTY_MAJOR, TXX927_TTY_MINOR_START + c->index);
-}
-
-/*
- * Setup initial baud/bits/parity. We do two things here:
- * - construct a cflag setting for the first rs_open()
- * - initialize the serial port
- * Return non-zero if we didn't find a serial port.
- */
-static int serial_console_setup(struct console *co, char *options)
-{
- static struct async_struct *info;
- struct serial_state *state;
- unsigned cval;
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int cflag = CREAD | HUPCL | CLOCAL;
- int quot = 0;
- char *s;
-
- if (co->index < 0 || co->index >= NR_PORTS) {
- return -1;
- }
- if (options) {
- baud = simple_strtoul(options, NULL, 10);
- s = options;
- while(*s >= '0' && *s <= '9')
- s++;
- if (*s) parity = *s++;
- if (*s) bits = *s - '0';
- }
-
- /*
- * Now construct a cflag setting.
- */
- switch(baud) {
- case 1200:
- cflag |= B1200;
- break;
- case 2400:
- cflag |= B2400;
- break;
- case 4800:
- cflag |= B4800;
- break;
- case 19200:
- cflag |= B19200;
- break;
- case 38400:
- cflag |= B38400;
- break;
- case 57600:
- cflag |= B57600;
- break;
- case 115200:
- cflag |= B115200;
- break;
- case 9600:
- default:
- cflag |= B9600;
- break;
- }
- switch(bits) {
- case 7:
- cflag |= CS7;
- break;
- default:
- case 8:
- cflag |= CS8;
- break;
- }
- switch(parity) {
- case 'o': case 'O':
- cflag |= PARODD;
- break;
- case 'e': case 'E':
- cflag |= PARENB;
- break;
- }
- co->cflag = cflag;
-
- /*
- * Divisor, bytesize and parity
- */
- state = rs_table + co->index;
- info = &async_sercons;
- info->magic = SERIAL_MAGIC;
- info->state = state;
- info->port = state->port;
- info->flags = state->flags;
- info->io_type = state->io_type;
- info->iomem_base = state->iomem_base;
- info->iomem_reg_shift = state->iomem_reg_shift;
- quot = state->baud_base / baud;
-
- switch (cflag & CSIZE) {
- case CS7: cval = TXx927_SILCR_UMODE_7BIT; break;
- default:
- case CS8: cval = TXx927_SILCR_UMODE_8BIT; break;
- }
- if (cflag & CSTOPB)
- cval |= TXx927_SILCR_USBL_2BIT;
- else
- cval |= TXx927_SILCR_USBL_1BIT;
- if (cflag & PARENB)
- cval |= TXx927_SILCR_UPEN;
- if (!(cflag & PARODD))
- cval |= TXx927_SILCR_UEPS;
-
- /*
- * Disable UART interrupts, set DTR and RTS high
- * and set speed.
- */
- sio_reg(info)->dicr = 0;
- sio_reg(info)->lcr = cval | TXx927_SILCR_SCS_IMCLK_BG;
- sio_reg(info)->bgr = quot | TXx927_SIBGR_BCLK_T0;
- /* HW RTS/CTS control */
- if (info->flags & ASYNC_HAVE_CTS_LINE)
- sio_reg(info)->flcr = TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES |
- TXx927_SIFLCR_RTSTL_MAX /* 15 */;
- /* Enable RX/TX */
- sio_reg(info)->flcr &= ~(TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE);
-
- return 0;
-}
-
-static struct console sercons = {
- .name = TXX927_TTY_NAME,
- .write = serial_console_write,
- .device = serial_console_device,
- .setup = serial_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/*
- * Register console.
- */
-void __init txx927_console_init(void)
-{
- register_console(&sercons);
-}
-#endif
diff -urN linux/drivers/serial/serial_txx9.c linux/drivers/serial/serial_txx9.c
--- linux/drivers/serial/serial_txx9.c 1970/01/01 00:00:00
+++ linux/drivers/serial/serial_txx9.c Fri Mar 4 17:24:33 2005 1.1
@@ -0,0 +1,1177 @@
+/*
+ * drivers/serial/serial_txx9.c
+ *
+ * Derived from many drivers using generic_serial interface,
+ * especially serial_tx3912.c by Steven J. Hill and r39xx_serial.c
+ * (was in Linux/VR tree) by Jim Pick.
+ *
+ * Copyright (C) 1999 Harald Koerfgen
+ * Copyright (C) 2000 Jim Pick <jim@jimpick.com>
+ * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com)
+ * Copyright (C) 2000-2002 Toshiba Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Serial driver for TX3927/TX4927/TX4925/TX4938 internal SIO controller
+ *
+ * Revision History:
+ * 0.30 Initial revision. (Renamed from serial_txx927.c)
+ * 0.31 Use save_flags instead of local_irq_save.
+ * 0.32 Support SCLK.
+ * 0.33 Switch TXX9_TTY_NAME by CONFIG_SERIAL_TXX9_STDSERIAL.
+ * Support TIOCSERGETLSR.
+ * 0.34 Support slow baudrate.
+ * 0.40 Merge codes from mainstream kernel (2.4.22).
+ * 0.41 Fix console checking in rs_shutdown_port().
+ * Disable flow-control in serial_console_write().
+ * 0.42 Fix minor compiler warning.
+ * 1.00 Kernel 2.6. Converted to new serial core (based on 8250.c).
+ * 1.01 Set fifosize to make tx_empry called properly.
+ * Use standard uart_get_divisor.
+ * 1.02 Cleanup. (import 8250.c changes)
+ * 1.03 Fix low-latency mode. (import 8250.c changes)
+ */
+#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_TXX9_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+static char *serial_version = "1.03";
+static char *serial_name = "TX39/49 Serial driver";
+
+#define PASS_LIMIT 256
+
+#if !defined(CONFIG_SERIAL_TXX9_STDSERIAL)
+/* "ttyS" is used for standard serial driver */
+#define TXX9_TTY_NAME "ttyTX"
+#define TXX9_TTY_DEVFS_NAME "tttx/"
+#define TXX9_TTY_MINOR_START (64 + 64) /* ttyTX0(128), ttyTX1(129) */
+#else
+/* acts like standard serial driver */
+#define TXX9_TTY_NAME "ttyS"
+#define TXX9_TTY_DEVFS_NAME "tts/"
+#define TXX9_TTY_MINOR_START 64
+#endif
+#define TXX9_TTY_MAJOR TTY_MAJOR
+
+/* flag aliases */
+#define UPF_TXX9_HAVE_CTS_LINE UPF_BUGGY_UART
+#define UPF_TXX9_USE_SCLK UPF_MAGIC_MULTIPLIER
+
+#ifdef CONFIG_PCI
+/* support for Toshiba TC86C001 SIO */
+#define ENABLE_SERIAL_TXX9_PCI
+#endif
+
+/*
+ * Number of serial ports
+ */
+#ifdef ENABLE_SERIAL_TXX9_PCI
+#define NR_PCI_BOARDS 4
+#define UART_NR (2 + NR_PCI_BOARDS)
+#else
+#define UART_NR 2
+#endif
+
+struct uart_txx9_port {
+ struct uart_port port;
+
+ /*
+ * We provide a per-port pm hook.
+ */
+ void (*pm)(struct uart_port *port,
+ unsigned int state, unsigned int old);
+};
+
+#define TXX9_REGION_SIZE 0x24
+
+/* TXX9 Serial Registers */
+#define TXX9_SILCR 0x00
+#define TXX9_SIDICR 0x04
+#define TXX9_SIDISR 0x08
+#define TXX9_SICISR 0x0c
+#define TXX9_SIFCR 0x10
+#define TXX9_SIFLCR 0x14
+#define TXX9_SIBGR 0x18
+#define TXX9_SITFIFO 0x1c
+#define TXX9_SIRFIFO 0x20
+
+/* SILCR : Line Control */
+#define TXX9_SILCR_SCS_MASK 0x00000060
+#define TXX9_SILCR_SCS_IMCLK 0x00000000
+#define TXX9_SILCR_SCS_IMCLK_BG 0x00000020
+#define TXX9_SILCR_SCS_SCLK 0x00000040
+#define TXX9_SILCR_SCS_SCLK_BG 0x00000060
+#define TXX9_SILCR_UEPS 0x00000010
+#define TXX9_SILCR_UPEN 0x00000008
+#define TXX9_SILCR_USBL_MASK 0x00000004
+#define TXX9_SILCR_USBL_1BIT 0x00000000
+#define TXX9_SILCR_USBL_2BIT 0x00000004
+#define TXX9_SILCR_UMODE_MASK 0x00000003
+#define TXX9_SILCR_UMODE_8BIT 0x00000000
+#define TXX9_SILCR_UMODE_7BIT 0x00000001
+
+/* SIDICR : DMA/Int. Control */
+#define TXX9_SIDICR_TDE 0x00008000
+#define TXX9_SIDICR_RDE 0x00004000
+#define TXX9_SIDICR_TIE 0x00002000
+#define TXX9_SIDICR_RIE 0x00001000
+#define TXX9_SIDICR_SPIE 0x00000800
+#define TXX9_SIDICR_CTSAC 0x00000600
+#define TXX9_SIDICR_STIE_MASK 0x0000003f
+#define TXX9_SIDICR_STIE_OERS 0x00000020
+#define TXX9_SIDICR_STIE_CTSS 0x00000010
+#define TXX9_SIDICR_STIE_RBRKD 0x00000008
+#define TXX9_SIDICR_STIE_TRDY 0x00000004
+#define TXX9_SIDICR_STIE_TXALS 0x00000002
+#define TXX9_SIDICR_STIE_UBRKD 0x00000001
+
+/* SIDISR : DMA/Int. Status */
+#define TXX9_SIDISR_UBRK 0x00008000
+#define TXX9_SIDISR_UVALID 0x00004000
+#define TXX9_SIDISR_UFER 0x00002000
+#define TXX9_SIDISR_UPER 0x00001000
+#define TXX9_SIDISR_UOER 0x00000800
+#define TXX9_SIDISR_ERI 0x00000400
+#define TXX9_SIDISR_TOUT 0x00000200
+#define TXX9_SIDISR_TDIS 0x00000100
+#define TXX9_SIDISR_RDIS 0x00000080
+#define TXX9_SIDISR_STIS 0x00000040
+#define TXX9_SIDISR_RFDN_MASK 0x0000001f
+
+/* SICISR : Change Int. Status */
+#define TXX9_SICISR_OERS 0x00000020
+#define TXX9_SICISR_CTSS 0x00000010
+#define TXX9_SICISR_RBRKD 0x00000008
+#define TXX9_SICISR_TRDY 0x00000004
+#define TXX9_SICISR_TXALS 0x00000002
+#define TXX9_SICISR_UBRKD 0x00000001
+
+/* SIFCR : FIFO Control */
+#define TXX9_SIFCR_SWRST 0x00008000
+#define TXX9_SIFCR_RDIL_MASK 0x00000180
+#define TXX9_SIFCR_RDIL_1 0x00000000
+#define TXX9_SIFCR_RDIL_4 0x00000080
+#define TXX9_SIFCR_RDIL_8 0x00000100
+#define TXX9_SIFCR_RDIL_12 0x00000180
+#define TXX9_SIFCR_RDIL_MAX 0x00000180
+#define TXX9_SIFCR_TDIL_MASK 0x00000018
+#define TXX9_SIFCR_TDIL_MASK 0x00000018
+#define TXX9_SIFCR_TDIL_1 0x00000000
+#define TXX9_SIFCR_TDIL_4 0x00000001
+#define TXX9_SIFCR_TDIL_8 0x00000010
+#define TXX9_SIFCR_TDIL_MAX 0x00000010
+#define TXX9_SIFCR_TFRST 0x00000004
+#define TXX9_SIFCR_RFRST 0x00000002
+#define TXX9_SIFCR_FRSTE 0x00000001
+#define TXX9_SIO_TX_FIFO 8
+#define TXX9_SIO_RX_FIFO 16
+
+/* SIFLCR : Flow Control */
+#define TXX9_SIFLCR_RCS 0x00001000
+#define TXX9_SIFLCR_TES 0x00000800
+#define TXX9_SIFLCR_RTSSC 0x00000200
+#define TXX9_SIFLCR_RSDE 0x00000100
+#define TXX9_SIFLCR_TSDE 0x00000080
+#define TXX9_SIFLCR_RTSTL_MASK 0x0000001e
+#define TXX9_SIFLCR_RTSTL_MAX 0x0000001e
+#define TXX9_SIFLCR_TBRK 0x00000001
+
+/* SIBGR : Baudrate Control */
+#define TXX9_SIBGR_BCLK_MASK 0x00000300
+#define TXX9_SIBGR_BCLK_T0 0x00000000
+#define TXX9_SIBGR_BCLK_T2 0x00000100
+#define TXX9_SIBGR_BCLK_T4 0x00000200
+#define TXX9_SIBGR_BCLK_T6 0x00000300
+#define TXX9_SIBGR_BRD_MASK 0x000000ff
+
+static inline unsigned int sio_in(struct uart_txx9_port *up, int offset)
+{
+ switch (up->port.iotype) {
+ default:
+ return *(volatile u32 *)(up->port.membase + offset);
+ case UPIO_PORT:
+ return inl(up->port.iobase + offset);
+ }
+}
+
+static inline void
+sio_out(struct uart_txx9_port *up, int offset, int value)
+{
+ switch (up->port.iotype) {
+ default:
+ *(volatile u32 *)(up->port.membase + offset) = value;
+ break;
+ case UPIO_PORT:
+ outl(value, up->port.iobase + offset);
+ break;
+ }
+}
+
+static inline void
+sio_mask(struct uart_txx9_port *up, int offset, unsigned int value)
+{
+ sio_out(up, offset, sio_in(up, offset) & ~value);
+}
+static inline void
+sio_set(struct uart_txx9_port *up, int offset, unsigned int value)
+{
+ sio_out(up, offset, sio_in(up, offset) | value);
+}
+
+static inline void
+sio_quot_set(struct uart_txx9_port *up, int quot)
+{
+ quot >>= 1;
+ if (quot < 256)
+ sio_out(up, TXX9_SIBGR, quot | TXX9_SIBGR_BCLK_T0);
+ else if (quot < (256 << 2))
+ sio_out(up, TXX9_SIBGR, (quot >> 2) | TXX9_SIBGR_BCLK_T2);
+ else if (quot < (256 << 4))
+ sio_out(up, TXX9_SIBGR, (quot >> 4) | TXX9_SIBGR_BCLK_T4);
+ else if (quot < (256 << 6))
+ sio_out(up, TXX9_SIBGR, (quot >> 6) | TXX9_SIBGR_BCLK_T6);
+ else
+ sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6);
+}
+
+static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void serial_txx9_start_tx(struct uart_port *port, unsigned int
tty_start)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ sio_set(up, TXX9_SIDICR, TXX9_SIDICR_TIE);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void serial_txx9_stop_rx(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ up->port.read_status_mask &= ~TXX9_SIDISR_RDIS;
+#if 0
+ sio_mask(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
+#endif
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void serial_txx9_enable_ms(struct uart_port *port)
+{
+ /* TXX9-SIO can not control DTR... */
+}
+
+static inline void
+receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs
*regs)
+{
+ struct tty_struct *tty = up->port.info->tty;
+ unsigned char ch;
+ unsigned int disr = *status;
+ int max_count = 256;
+ char flag;
+
+ do {
+ /* The following is not allowed by the tty layer and
+ unsafe. It should be fixed ASAP */
+ if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+ if (tty->low_latency) {
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ }
+ /* If this failed then we will throw away the
+ bytes but must do so to clear interrupts */
+ }
+ ch = sio_in(up, TXX9_SIRFIFO);
+ flag = TTY_NORMAL;
+ up->port.icount.rx++;
+
+ if (unlikely(disr & (TXX9_SIDISR_UBRK | TXX9_SIDISR_UPER |
+ TXX9_SIDISR_UFER | TXX9_SIDISR_UOER))) {
+ /*
+ * For statistics only
+ */
+ if (disr & TXX9_SIDISR_UBRK) {
+ disr &= ~(TXX9_SIDISR_UFER | TXX9_SIDISR_UPER);
+ up->port.icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(&up->port))
+ goto ignore_char;
+ } else if (disr & TXX9_SIDISR_UPER)
+ up->port.icount.parity++;
+ else if (disr & TXX9_SIDISR_UFER)
+ up->port.icount.frame++;
+ if (disr & TXX9_SIDISR_UOER)
+ up->port.icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ingored.
+ */
+ disr &= up->port.read_status_mask;
+
+ if (disr & TXX9_SIDISR_UBRK) {
+ flag = TTY_BREAK;
+ } else if (disr & TXX9_SIDISR_UPER)
+ flag = TTY_PARITY;
+ else if (disr & TXX9_SIDISR_UFER)
+ flag = TTY_FRAME;
+ }
+ if (uart_handle_sysrq_char(&up->port, ch, regs))
+ goto ignore_char;
+ if ((disr & up->port.ignore_status_mask) == 0) {
+ tty_insert_flip_char(tty, ch, flag);
+ }
+ if ((disr & TXX9_SIDISR_UOER) &&
+ tty->flip.count < TTY_FLIPBUF_SIZE) {
+ /*
+ * Overrun is special, since it's reported
+ * immediately, and doesn't affect the current
+ * character.
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+ ignore_char:
+ disr = sio_in(up, TXX9_SIDISR);
+ } while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
+ tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ *status = disr;
+}
+
+static inline void transmit_chars(struct uart_txx9_port *up)
+{
+ struct circ_buf *xmit = &up->port.info->xmit;
+ int count;
+
+ if (up->port.x_char) {
+ sio_out(up, TXX9_SITFIFO, up->port.x_char);
+ up->port.icount.tx++;
+ up->port.x_char = 0;
+ return;
+ }
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+ serial_txx9_stop_tx(&up->port, 0);
+ return;
+ }
+
+ count = TXX9_SIO_TX_FIFO;
+ do {
+ sio_out(up, TXX9_SITFIFO, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ up->port.icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&up->port);
+
+ if (uart_circ_empty(xmit))
+ serial_txx9_stop_tx(&up->port, 0);
+}
+
+static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs
*regs)
+{
+ int pass_counter = 0;
+ struct uart_txx9_port *up = dev_id;
+ unsigned int status;
+
+ while (1) {
+ spin_lock(&up->port.lock);
+ status = sio_in(up, TXX9_SIDISR);
+ if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
+ status &= ~TXX9_SIDISR_TDIS;
+ if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
+ TXX9_SIDISR_TOUT))) {
+ spin_unlock(&up->port.lock);
+ break;
+ }
+
+ if (status & TXX9_SIDISR_RDIS)
+ receive_chars(up, &status, regs);
+ if (status & TXX9_SIDISR_TDIS)
+ transmit_chars(up);
+ /* Clear TX/RX Int. Status */
+ sio_mask(up, TXX9_SIDISR,
+ TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
+ TXX9_SIDISR_TOUT);
+ spin_unlock(&up->port.lock);
+
+ if (pass_counter++ > PASS_LIMIT)
+ break;
+ }
+
+ return pass_counter ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static unsigned int serial_txx9_tx_empty(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret;
+}
+
+static unsigned int serial_txx9_get_mctrl(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = ((sio_in(up, TXX9_SIFLCR) & TXX9_SIFLCR_RTSSC) ? 0 : TIOCM_RTS)
+ | ((sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS) ? 0 :
TIOCM_CTS);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret;
+}
+
+static void serial_txx9_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (mctrl & TIOCM_RTS)
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
+ else
+ sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSSC);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void serial_txx9_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ if (break_state == -1)
+ sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
+ else
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial_txx9_startup(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+ int retval;
+
+ /*
+ * Clear the FIFO buffers and disable them.
+ * (they will be reeanbled in set_termios())
+ */
+ sio_set(up, TXX9_SIFCR,
+ TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
+ /* clear reset */
+ sio_mask(up, TXX9_SIFCR,
+ TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
+ sio_out(up, TXX9_SIDICR, 0);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ sio_out(up, TXX9_SIDISR, 0);
+
+ retval = request_irq(up->port.irq, serial_txx9_interrupt,
+ SA_SHIRQ, "serial_txx9", up);
+ if (retval)
+ return retval;
+
+ /*
+ * Now, initialize the UART
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+ serial_txx9_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /* Enable RX/TX */
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
+
+ /*
+ * Finally, enable interrupts.
+ */
+ sio_set(up, TXX9_SIDICR, TXX9_SIDICR_RIE);
+
+ return 0;
+}
+
+static void serial_txx9_shutdown(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+
+ /*
+ * Disable interrupts from this port
+ */
+ sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ serial_txx9_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * Disable break condition
+ */
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
+
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+ if (up->port.cons && up->port.line == up->port.cons->index) {
+ free_irq(up->port.irq, up);
+ return;
+ }
+#endif
+ /* reset FIFOs */
+ sio_set(up, TXX9_SIFCR,
+ TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
+ /* clear reset */
+ sio_mask(up, TXX9_SIFCR,
+ TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE);
+
+ /* Disable RX/TX */
+ sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
+
+ free_irq(up->port.irq, up);
+}
+
+static void
+serial_txx9_set_termios(struct uart_port *port, struct termios *termios,
+ struct termios *old)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned int cval, fcr = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
+
+ cval = sio_in(up, TXX9_SILCR);
+ /* byte size and parity */
+ cval &= ~TXX9_SILCR_UMODE_MASK;
+ switch (termios->c_cflag & CSIZE) {
+ case CS7:
+ cval |= TXX9_SILCR_UMODE_7BIT;
+ break;
+ default:
+ case CS5: /* not supported */
+ case CS6: /* not supported */
+ case CS8:
+ cval |= TXX9_SILCR_UMODE_8BIT;
+ break;
+ }
+
+ cval &= ~TXX9_SILCR_USBL_MASK;
+ if (termios->c_cflag & CSTOPB)
+ cval |= TXX9_SILCR_USBL_2BIT;
+ else
+ cval |= TXX9_SILCR_USBL_1BIT;
+ cval &= ~(TXX9_SILCR_UPEN | TXX9_SILCR_UEPS);
+ if (termios->c_cflag & PARENB)
+ cval |= TXX9_SILCR_UPEN;
+ if (!(termios->c_cflag & PARODD))
+ cval |= TXX9_SILCR_UEPS;
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16/2);
+ quot = uart_get_divisor(port, baud);
+
+ /* Set up FIFOs */
+ /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
+ fcr = TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1;
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ up->port.read_status_mask = TXX9_SIDISR_UOER |
+ TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS;
+ if (termios->c_iflag & INPCK)
+ up->port.read_status_mask |= TXX9_SIDISR_UFER |
TXX9_SIDISR_UPER;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ up->port.read_status_mask |= TXX9_SIDISR_UBRK;
+
+ /*
+ * Characteres to ignore
+ */
+ up->port.ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= TXX9_SIDISR_UPER |
TXX9_SIDISR_UFER;
+ if (termios->c_iflag & IGNBRK) {
+ up->port.ignore_status_mask |= TXX9_SIDISR_UBRK;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ up->port.ignore_status_mask |= TXX9_SIDISR_UOER;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= TXX9_SIDISR_RDIS;
+
+ /* CTS flow control flag */
+ if ((termios->c_cflag & CRTSCTS) &&
+ (up->port.flags & UPF_TXX9_HAVE_CTS_LINE)) {
+ sio_set(up, TXX9_SIFLCR,
+ TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
+ } else {
+ sio_mask(up, TXX9_SIFLCR,
+ TXX9_SIFLCR_RCS | TXX9_SIFLCR_TES);
+ }
+
+ sio_out(up, TXX9_SILCR, cval);
+ sio_quot_set(up, quot);
+ sio_out(up, TXX9_SIFCR, fcr);
+
+ serial_txx9_set_mctrl(&up->port, up->port.mctrl);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static void
+serial_txx9_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ if (state) {
+ /* sleep */
+
+ if (up->pm)
+ up->pm(port, state, oldstate);
+ } else {
+ /* wake */
+
+ if (up->pm)
+ up->pm(port, state, oldstate);
+ }
+}
+
+static int serial_txx9_request_resource(struct uart_txx9_port *up)
+{
+ unsigned int size = TXX9_REGION_SIZE;
+ int ret = 0;
+
+ switch (up->port.iotype) {
+ default:
+ if (!up->port.mapbase)
+ break;
+
+ if (!request_mem_region(up->port.mapbase, size, "serial_txx9"))
{
+ ret = -EBUSY;
+ break;
+ }
+
+ if (up->port.flags & UPF_IOREMAP) {
+ up->port.membase = ioremap(up->port.mapbase, size);
+ if (!up->port.membase) {
+ release_mem_region(up->port.mapbase, size);
+ ret = -ENOMEM;
+ }
+ }
+ break;
+
+ case UPIO_PORT:
+ if (!request_region(up->port.iobase, size, "serial_txx9"))
+ ret = -EBUSY;
+ break;
+ }
+ return ret;
+}
+
+static void serial_txx9_release_resource(struct uart_txx9_port *up)
+{
+ unsigned int size = TXX9_REGION_SIZE;
+
+ switch (up->port.iotype) {
+ default:
+ if (!up->port.mapbase)
+ break;
+
+ if (up->port.flags & UPF_IOREMAP) {
+ iounmap(up->port.membase);
+ up->port.membase = NULL;
+ }
+
+ release_mem_region(up->port.mapbase, size);
+ break;
+
+ case UPIO_PORT:
+ release_region(up->port.iobase, size);
+ break;
+ }
+}
+
+static void serial_txx9_release_port(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ serial_txx9_release_resource(up);
+}
+
+static int serial_txx9_request_port(struct uart_port *port)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ return serial_txx9_request_resource(up);
+}
+
+static void serial_txx9_config_port(struct uart_port *port, int uflags)
+{
+ struct uart_txx9_port *up = (struct uart_txx9_port *)port;
+ unsigned long flags;
+ int ret;
+
+ /*
+ * Find the region that we can probe for. This in turn
+ * tells us whether we can probe for the type of port.
+ */
+ ret = serial_txx9_request_resource(up);
+ if (ret < 0)
+ return;
+ port->type = PORT_TXX9;
+ up->port.fifosize = TXX9_SIO_TX_FIFO;
+
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+ if (up->port.line == up->port.cons->index)
+ return;
+#endif
+ spin_lock_irqsave(&up->port.lock, flags);
+ /*
+ * Reset the UART.
+ */
+ sio_out(up, TXX9_SIFCR, TXX9_SIFCR_SWRST);
+#ifdef CONFIG_CPU_TX49XX
+ /* TX4925 BUG WORKAROUND. Accessing SIOC register
+ * immediately after soft reset causes bus error. */
+ iob();
+ udelay(1);
+#endif
+ while (sio_in(up, TXX9_SIFCR) & TXX9_SIFCR_SWRST)
+ ;
+ /* TX Int by FIFO Empty, RX Int by Receiving 1 char. */
+ sio_set(up, TXX9_SIFCR,
+ TXX9_SIFCR_TDIL_MAX | TXX9_SIFCR_RDIL_1);
+ /* initial settings */
+ sio_out(up, TXX9_SILCR,
+ TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
+ ((up->port.flags & UPF_TXX9_USE_SCLK) ?
+ TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
+ sio_quot_set(up, uart_get_divisor(port, 9600));
+ sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int
+serial_txx9_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (ser->irq < 0 ||
+ ser->baud_base < 9600 || ser->type != PORT_TXX9)
+ return -EINVAL;
+ return 0;
+}
+
+static const char *
+serial_txx9_type(struct uart_port *port)
+{
+ return "txx9";
+}
+
+static struct uart_ops serial_txx9_pops = {
+ .tx_empty = serial_txx9_tx_empty,
+ .set_mctrl = serial_txx9_set_mctrl,
+ .get_mctrl = serial_txx9_get_mctrl,
+ .stop_tx = serial_txx9_stop_tx,
+ .start_tx = serial_txx9_start_tx,
+ .stop_rx = serial_txx9_stop_rx,
+ .enable_ms = serial_txx9_enable_ms,
+ .break_ctl = serial_txx9_break_ctl,
+ .startup = serial_txx9_startup,
+ .shutdown = serial_txx9_shutdown,
+ .set_termios = serial_txx9_set_termios,
+ .pm = serial_txx9_pm,
+ .type = serial_txx9_type,
+ .release_port = serial_txx9_release_port,
+ .request_port = serial_txx9_request_port,
+ .config_port = serial_txx9_config_port,
+ .verify_port = serial_txx9_verify_port,
+};
+
+static struct uart_txx9_port serial_txx9_ports[UART_NR];
+
+static void __init serial_txx9_register_ports(struct uart_driver *drv)
+{
+ int i;
+
+ for (i = 0; i < UART_NR; i++) {
+ struct uart_txx9_port *up = &serial_txx9_ports[i];
+
+ up->port.line = i;
+ up->port.ops = &serial_txx9_pops;
+ uart_add_one_port(drv, &up->port);
+ }
+}
+
+#ifdef CONFIG_SERIAL_TXX9_CONSOLE
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_txx9_port *up)
+{
+ unsigned int tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ while (--tmout &&
+ !(sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS))
+ udelay(1);
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ tmout = 1000000;
+ while (--tmout &&
+ (sio_in(up, TXX9_SICISR) & TXX9_SICISR_CTSS))
+ udelay(1);
+ }
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+static void
+serial_txx9_console_write(struct console *co, const char *s, unsigned int
count)
+{
+ struct uart_txx9_port *up = &serial_txx9_ports[co->index];
+ unsigned int ier, flcr;
+ int i;
+
+ /*
+ * First save the UER then disable the interrupts
+ */
+ ier = sio_in(up, TXX9_SIDICR);
+ sio_out(up, TXX9_SIDICR, 0);
+ /*
+ * Disable flow-control if enabled (and unnecessary)
+ */
+ flcr = sio_in(up, TXX9_SIFLCR);
+ if (!(up->port.flags & UPF_CONS_FLOW) && (flcr & TXX9_SIFLCR_TES))
+ sio_out(up, TXX9_SIFLCR, flcr & ~TXX9_SIFLCR_TES);
+
+ /*
+ * Now, do each character
+ */
+ for (i = 0; i < count; i++, s++) {
+ wait_for_xmitr(up);
+
+ /*
+ * Send the character out.
+ * If a LF, also do CR...
+ */
+ sio_out(up, TXX9_SITFIFO, *s);
+ if (*s == 10) {
+ wait_for_xmitr(up);
+ sio_out(up, TXX9_SITFIFO, 13);
+ }
+ }
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up);
+ sio_out(up, TXX9_SIFLCR, flcr);
+ sio_out(up, TXX9_SIDICR, ier);
+}
+
+static int serial_txx9_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ struct uart_txx9_port *up;
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ if (co->index >= UART_NR)
+ co->index = 0;
+ up = &serial_txx9_ports[co->index];
+ port = &up->port;
+ if (!port->ops)
+ return -ENODEV;
+
+ /*
+ * Temporary fix.
+ */
+ spin_lock_init(&port->lock);
+
+ /*
+ * Disable UART interrupts, set DTR and RTS high
+ * and set speed.
+ */
+ sio_out(up, TXX9_SIDICR, 0);
+ /* initial settings */
+ sio_out(up, TXX9_SILCR,
+ TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT |
+ ((port->flags & UPF_TXX9_USE_SCLK) ?
+ TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG));
+ sio_out(up, TXX9_SIFLCR, TXX9_SIFLCR_RTSTL_MAX /* 15 */);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver serial_txx9_reg;
+static struct console serial_txx9_console = {
+ .name = TXX9_TTY_NAME,
+ .write = serial_txx9_console_write,
+ .device = uart_console_device,
+ .setup = serial_txx9_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &serial_txx9_reg,
+};
+
+static int __init serial_txx9_console_init(void)
+{
+ register_console(&serial_txx9_console);
+ return 0;
+}
+console_initcall(serial_txx9_console_init);
+
+static int __init serial_txx9_late_console_init(void)
+{
+ if (!(serial_txx9_console.flags & CON_ENABLED))
+ register_console(&serial_txx9_console);
+ return 0;
+}
+late_initcall(serial_txx9_late_console_init);
+
+#define SERIAL_TXX9_CONSOLE &serial_txx9_console
+#else
+#define SERIAL_TXX9_CONSOLE NULL
+#endif
+
+static struct uart_driver serial_txx9_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial_txx9",
+ .devfs_name = TXX9_TTY_DEVFS_NAME,
+ .dev_name = TXX9_TTY_NAME,
+ .major = TXX9_TTY_MAJOR,
+ .minor = TXX9_TTY_MINOR_START,
+ .nr = UART_NR,
+ .cons = SERIAL_TXX9_CONSOLE,
+};
+
+int __init early_serial_txx9_setup(struct uart_port *port)
+{
+ if (port->line >= ARRAY_SIZE(serial_txx9_ports))
+ return -ENODEV;
+
+ serial_txx9_ports[port->line].port = *port;
+ serial_txx9_ports[port->line].port.ops = &serial_txx9_pops;
+ serial_txx9_ports[port->line].port.flags |= UPF_BOOT_AUTOCONF;
+ return 0;
+}
+
+#ifdef ENABLE_SERIAL_TXX9_PCI
+/**
+ * serial_txx9_suspend_port - suspend one serial port
+ * @line: serial line number
+ * @level: the level of port suspension, as per uart_suspend_port
+ *
+ * Suspend one serial port.
+ */
+static void serial_txx9_suspend_port(int line)
+{
+ uart_suspend_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
+}
+
+/**
+ * serial_txx9_resume_port - resume one serial port
+ * @line: serial line number
+ * @level: the level of port resumption, as per uart_resume_port
+ *
+ * Resume one serial port.
+ */
+static void serial_txx9_resume_port(int line)
+{
+ uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port);
+}
+
+/*
+ * Probe one serial board. Unfortunately, there is no rhyme nor reason
+ * to the arrangement of serial ports on a PCI card.
+ */
+static int __devinit
+pciserial_txx9_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ struct uart_port port;
+ int line;
+ int rc;
+
+ rc = pci_enable_device(dev);
+ if (rc)
+ return rc;
+
+ memset(&port, 0, sizeof(port));
+ port.ops = &serial_txx9_pops;
+ port.flags |= UPF_BOOT_AUTOCONF; /* uart_ops.config_port will be called
*/
+ port.flags |= UPF_TXX9_HAVE_CTS_LINE;
+ port.uartclk = 66670000;
+ port.irq = dev->irq;
+ port.iotype = UPIO_PORT;
+ port.iobase = pci_resource_start(dev, 1);
+ line = uart_register_port(&serial_txx9_reg, &port);
+ if (line < 0) {
+ printk(KERN_WARNING "Couldn't register serial port %s: %d\n",
pci_name(dev), line);
+ }
+ pci_set_drvdata(dev, (void *)(long)line);
+
+ return 0;
+}
+
+static void __devexit pciserial_txx9_remove_one(struct pci_dev *dev)
+{
+ int line = (int)(long)pci_get_drvdata(dev);
+
+ pci_set_drvdata(dev, NULL);
+
+ if (line) {
+ uart_unregister_port(&serial_txx9_reg, line);
+ pci_disable_device(dev);
+ }
+}
+
+static int pciserial_txx9_suspend_one(struct pci_dev *dev, u32 state)
+{
+ int line = (int)(long)pci_get_drvdata(dev);
+
+ if (line)
+ serial_txx9_suspend_port(line);
+ return 0;
+}
+
+static int pciserial_txx9_resume_one(struct pci_dev *dev)
+{
+ int line = (int)(long)pci_get_drvdata(dev);
+
+ if (line)
+ serial_txx9_resume_port(line);
+ return 0;
+}
+
+static struct pci_device_id serial_txx9_pci_tbl[] = {
+ { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, 0 },
+ { 0, }
+};
+
+static struct pci_driver serial_txx9_pci_driver = {
+ .name = "serial_txx9",
+ .probe = pciserial_txx9_init_one,
+ .remove = __devexit_p(pciserial_txx9_remove_one),
+ .suspend = pciserial_txx9_suspend_one,
+ .resume = pciserial_txx9_resume_one,
+ .id_table = serial_txx9_pci_tbl,
+};
+
+MODULE_DEVICE_TABLE(pci, serial_txx9_pci_tbl);
+#endif /* ENABLE_SERIAL_TXX9_PCI */
+
+static int __init serial_txx9_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+
+ ret = uart_register_driver(&serial_txx9_reg);
+ if (ret >= 0) {
+ serial_txx9_register_ports(&serial_txx9_reg);
+
+#ifdef ENABLE_SERIAL_TXX9_PCI
+ ret = pci_module_init(&serial_txx9_pci_driver);
+#endif
+ }
+ return ret;
+}
+
+static void __exit serial_txx9_exit(void)
+{
+ int i;
+
+#ifdef ENABLE_SERIAL_TXX9_PCI
+ pci_unregister_driver(&serial_txx9_pci_driver);
+#endif
+ for (i = 0; i < UART_NR; i++)
+ uart_remove_one_port(&serial_txx9_reg,
&serial_txx9_ports[i].port);
+
+ uart_unregister_driver(&serial_txx9_reg);
+}
+
+module_init(serial_txx9_init);
+module_exit(serial_txx9_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TX39/49 serial driver");
+
+MODULE_ALIAS_CHARDEV_MAJOR(TXX9_TTY_MAJOR);
diff -urN linux/drivers/serial/Kconfig linux/drivers/serial/Kconfig
--- linux/drivers/serial/Kconfig 2005/01/25 04:28:44 1.39
+++ linux/drivers/serial/Kconfig 2005/03/04 17:24:33 1.40
@@ -792,4 +792,22 @@
If you use an M3T-M32700UT or an OPSPUT platform,
please say Y.
+config SERIAL_TXX9
+ bool "TMPTX39XX/49XX SIO support"
+ depends HAS_TXX9_SERIAL
+ select SERIAL_CORE
+ default y
+
+config HAS_TXX9_SERIAL
+ bool
+
+config SERIAL_TXX9_CONSOLE
+ bool "TMPTX39XX/49XX SIO Console support"
+ depends on SERIAL_TXX9=y
+ select SERIAL_CORE_CONSOLE
+
+config SERIAL_TXX9_STDSERIAL
+ bool "TX39XX/49XX SIO act as standard serial"
+ depends on !SERIAL_8250 && SERIAL_TXX9
+
endmenu
diff -urN linux/include/asm-mips/serial.h linux/include/asm-mips/serial.h
--- linux/include/asm-mips/serial.h 2005/03/04 15:13:37 1.63
+++ linux/include/asm-mips/serial.h 2005/03/04 17:24:33 1.64
@@ -129,17 +129,6 @@
#define IVR_SERIAL_PORT_DEFNS
#endif
-#ifdef CONFIG_TOSHIBA_JMR3927
-#include <asm/jmr3927/jmr3927.h>
-#define TXX927_SERIAL_PORT_DEFNS \
- { .baud_base = JMR3927_BASE_BAUD, .port = UART0_ADDR, .irq = UART0_INT, \
- .flags = UART0_FLAGS, .type = 1 }, \
- { .baud_base = JMR3927_BASE_BAUD, .port = UART1_ADDR, .irq = UART1_INT, \
- .flags = UART1_FLAGS, .type = 1 },
-#else
-#define TXX927_SERIAL_PORT_DEFNS
-#endif
-
#ifdef CONFIG_SERIAL_AU1X00
#include <asm/mach-au1x00/au1000.h>
#ifdef CONFIG_SOC_AU1000
@@ -427,7 +416,6 @@
MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
- TXX927_SERIAL_PORT_DEFNS \
AU1000_SERIAL_PORT_DEFNS
#endif /* _ASM_SERIAL_H */
diff -urN linux/include/asm-mips/jmr3927/jmr3927.h
linux/include/asm-mips/jmr3927/jmr3927.h
--- linux/include/asm-mips/jmr3927/jmr3927.h 2003/07/17 02:38:34 1.5
+++ linux/include/asm-mips/jmr3927/jmr3927.h 2005/03/04 17:24:33 1.6
@@ -202,20 +202,6 @@
#endif /* !__ASSEMBLY__ */
/*
- * UART defines for serial.h
- */
-
-/* use Pre-scaler T0 (1/2) */
-#define JMR3927_BASE_BAUD (JMR3927_IMCLK / 2 / 16)
-
-#define UART0_ADDR 0xfffef300
-#define UART1_ADDR 0xfffef400
-#define UART0_INT JMR3927_IRQ_IRC_SIO0
-#define UART1_INT JMR3927_IRQ_IRC_SIO1
-#define UART0_FLAGS ASYNC_BOOT_AUTOCONF
-#define UART1_FLAGS 0
-
-/*
* IRQ mappings
*/
|