Update to the serial driver

tytso@MIT.EDU
Thu, 16 Apr 1998 11:28:03 -0400


Hi Linus,

Could you please apply the enclosed patches to the 2.1 tree?
They represent updates to the serial driver, and fixes the following
problems:

* The interrupt probing now uses the standard IRQ probing
routines provided by Linux, instead of trying to roll its own.
This makes the autodetection more robust, and saves almost 1k
from the serial driver. (Actually, the serial IRQ
autodetection predates the standard IRQ probing routines, but
they weren't removed in favor of the centralized IRQ probing
routines until now.) Thanks to Etienne Lorrain for providing
this patch.

* Fixed a race condition rs_write() where it was calling
copy_from_user with interrupts disabled. Apparently this only
bit SMP systems under heavy load. (Sorry I don't have a SMP
machine yet...) Thanks to Jean Wolter for pointing this out.

* The message stating that the /dev/cua?? devices are obsolete
now prints the device involved and which program tried to open
the device. Thanks to Paul Gortmaker for providing thie
patch.

* Make the serial driver much more architecture independent.
Instead of validating the irq by checking against a hard-coded
16, it now checks against NR_IRQS. The check to see if irq 2
should be changed to be irq 9 has been moved into a
irq_cannonicalize function, to be defined in
include/arch/irq.h. Finally, the i386 and alpha specific
parts of the rs_table initialization have been moved to
include/asm/serial.h. (This is what makes the patches look so
big, but it's mostly rearranging existing code.) Russell
King proposed these changes for the ARM port (although I
didn't take his patches exactly as he proposed them.)

Linus, if you could apply these patches to the 2.1 tree, I'd
appreicate it. Thanks!!

- Ted

Patch generated: on Thu Apr 16 11:24:05 EDT 1998 by tytso@rsts-11.mit.edu
against Linux version 2.1.96

===================================================================
RCS file: Documentation/RCS/Configure.help,v
retrieving revision 1.1
diff -u -r1.1 Documentation/Configure.help
--- Documentation/Configure.help 1998/04/15 19:53:44 1.1
+++ Documentation/Configure.help 1998/04/15 19:53:55
@@ -956,6 +956,19 @@
serial ports on the same board to share a single IRQ. To enable
support for this in the serial driver, say Y here.

+Autodetect IRQ on standard ports (unsafe)
+CONFIG_SERIAL_DETECT_IRQ
+ Enable this option if you want the kernel to try to guess which IRQ
+ is configured during the boot sequence and you're too lazy to edit
+ the boot scripts to use the setserial command. This option can be
+ unsafe and should not be enabled on most machines. It is far
+ better to dynamically request autoconfiguration during the boot-time
+ scripts using the setserial command. You can change the IRQ and/or
+ request automatic IRQ configuration at any time by using the
+ "setserial" program. I wouldn't include this config option at all except
+ people keep bellyaching about it. I guess they are really are too lazy
+ to edit their boot scripts. :-) If unsure, say No.
+
Support special multiport boards
CONFIG_SERIAL_MULTIPORT
Some multiport serial ports have special ports which are used to
===================================================================
RCS file: drivers/char/RCS/Config.in,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/Config.in
--- drivers/char/Config.in 1998/04/15 19:53:45 1.1
+++ drivers/char/Config.in 1998/04/15 19:53:55
@@ -16,6 +16,7 @@
if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
+ bool ' Autodetect IRQ on standard ports (unsafe)' CONFIG_SERIAL_DETECT_IRQ
bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
fi
===================================================================
RCS file: include/linux/RCS/serial.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/serial.h
--- include/linux/serial.h 1998/04/15 19:53:45 1.1
+++ include/linux/serial.h 1998/04/15 19:53:55
@@ -85,8 +85,10 @@
#define ASYNC_SPD_SHI 0x1000 /* Use 230400 instead of 38400 bps */
#define ASYNC_SPD_WARP 0x1010 /* Use 460800 instead of 38400 bps */

-#define ASYNC_FLAGS 0x1FFF /* Possible legal async flags */
-#define ASYNC_USR_MASK 0x1430 /* Legal flags that non-privileged
+#define ASYNC_LOW_LATENCY 0x2000 /* Request low latency behaviour */
+
+#define ASYNC_FLAGS 0x2FFF /* Possible legal async flags */
+#define ASYNC_USR_MASK 0x3430 /* Legal flags that non-privileged
* users can set or reset */

/* Internal flags used only by kernel/chr_drv/serial.c */
===================================================================
RCS file: drivers/char/RCS/serial.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/serial.c
--- drivers/char/serial.c 1998/04/15 19:53:45 1.1
+++ drivers/char/serial.c 1998/04/16 15:19:37
@@ -25,50 +25,18 @@
* 8/97: Fix bug in rs_set_termios with RTS
* Stanislav V. Voronyi <stas@uanet.kharkov.ua>
*
+ * 3/98: Change the IRQ detection, use of probe_irq_o*(),
+ * supress TIOCSERGWILD and TIOCSERSWILD
+ * Etienne Lorrain <etienne.lorrain@ibm.net>
+ *
+ * 4/98: Added changes to support the ARM architecture proposed by
+ * Russell King
+ *
* This module exports the following rs232 io functions:
*
* int rs_init(void);
*/

-#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/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/malloc.h>
-#include <linux/init.h>
-#ifdef CONFIG_SERIAL_CONSOLE
-#include <linux/console.h>
-#endif
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-
-static char *serial_name = "Serial driver";
-static char *serial_version = "4.24";
-
-static DECLARE_TASK_QUEUE(tq_serial);
-
-static struct tty_driver serial_driver, callout_driver;
-static int serial_refcount;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
/*
* Serial driver configuration section. Here are the various options:
*
@@ -86,6 +54,9 @@
* CONFIG_SERIAL_SHARE_IRQ
* Enables support for multiple serial ports on one IRQ
*
+ * CONFIG_SERIAL_DETECT_IRQ
+ * Enable the autodetection of IRQ on standart ports
+ *
* SERIAL_PARANOIA_CHECK
* Check the magic number for the async_structure where
* ever possible.
@@ -100,6 +71,7 @@

#define CONFIG_SERIAL_MANY_PORTS
#define CONFIG_SERIAL_SHARE_IRQ
+#define CONFIG_SERIAL_DETECT_IRQ
#define CONFIG_SERIAL_MULTIPORT
#define CONFIG_HUB6
#endif
@@ -133,7 +105,7 @@

#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)

-#define _INLINE_ inline
+#define SERIAL_INLINE

#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
@@ -143,22 +115,70 @@
#endif

/*
+ * End of serial driver configuration section.
+ */
+
+#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/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/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/serial.h>
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
+static char *serial_name = "Serial driver";
+static char *serial_version = "4.25";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* 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[16];
+static struct async_struct *IRQ_ports[NR_IRQS];
#ifdef CONFIG_SERIAL_MULTIPORT
-static struct rs_multiport_struct rs_multiport[16];
+static struct rs_multiport_struct rs_multiport[NR_IRQS];
#endif
-static int IRQ_timeout[16];
-static volatile int rs_irq_triggered;
-static volatile int rs_triggered;
-static int rs_wild_int_mask;
+static int IRQ_timeout[NR_IRQS];
#ifdef CONFIG_SERIAL_CONSOLE
static struct console sercons;
#endif

+static unsigned detect_uart_irq (struct serial_state * state);
static void autoconfig(struct serial_state * info);
static void change_speed(struct async_struct *info);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -180,109 +200,9 @@
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
{ 0, 0}
};
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD ( 1843200 / 16 )
-
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST )
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define FOURPORT_FLAGS ASYNC_FOURPORT
-#define ACCENT_FLAGS 0
-#define BOCA_FLAGS 0
-#define HUB6_FLAGS 0
-#endif
-
-/*
- * The following define the access methods for the HUB6 card. All
- * access is through two ports for all 24 possible chips. The card is
- * selected through the high 2 bits, the port on that card with the
- * "middle" 3 bits, and the register on that port with the bottom
- * 3 bits.
- *
- * While the access port and interrupt is configurable, the default
- * port locations are 0x302 for the port control register, and 0x303
- * for the data read/write register. Normally, the interrupt is at irq3
- * but can be anything from 3 to 7 inclusive. Note that using 3 will
- * require disabling com2.
- */
-
-#define C_P(card,port) (((card)<<6|(port)<<3) + 1)

static struct serial_state rs_table[] = {
- /* UART CLK PORT IRQ FLAGS */
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
-#ifdef CONFIG_SERIAL_MANY_PORTS
- { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */
- { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */
- { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */
- { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */
-
- { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */
- { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */
- { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */
- { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */
-
- { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */
- { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */
- { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare; user configurable) */
- { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare; user configurable) */
-
- { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */
- { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */
- { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */
- { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */
- { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */
- { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */
- { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */
- { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */
- { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */
- { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */
- { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */
- { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */
- { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */
- { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */
- { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */
- { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */
-
-/* You can have up to four HUB6's in the system, but I've only
- * included two cards here for a total of twelve ports.
- */
-#ifdef CONFIG_HUB6
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) }, /* ttyS32 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) }, /* ttyS33 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) }, /* ttyS34 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) }, /* ttyS35 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) }, /* ttyS36 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) }, /* ttyS37 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) }, /* ttyS38 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) }, /* ttyS39 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) }, /* ttyS40 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) }, /* ttyS41 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */
- { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */
-#endif
-#endif /* CONFIG_SERIAL_MANY_PORTS */
-#ifdef CONFIG_MCA
- { 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS },
- { 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS },
- { 0, BASE_BAUD, 0x4220, 3, STD_COM_FLAGS },
- { 0, BASE_BAUD, 0x4228, 3, STD_COM_FLAGS },
- { 0, BASE_BAUD, 0x5220, 3, STD_COM_FLAGS },
- { 0, BASE_BAUD, 0x5228, 3, STD_COM_FLAGS },
-#endif
+ SERIAL_PORT_DFNS /* Defined in serial.h */
};

#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))
@@ -304,7 +224,7 @@
* buffer across all the serial ports, since it significantly saves
* memory if large numbers of serial ports are open.
*/
-static unsigned char *tmp_buf = 0;
+static unsigned char *tmp_buf;
static struct semaphore tmp_buf_sem = MUTEX;

static inline int serial_paranoia_check(struct async_struct *info,
@@ -443,17 +363,6 @@
*/

/*
- * This is the serial driver's interrupt routine while we are probing
- * for submarines.
- */
-static void rs_probe(int irq, void *dev_id, struct pt_regs * regs)
-{
- rs_irq_triggered = irq;
- rs_triggered |= 1 << irq;
- return;
-}
-
-/*
* This routine is used by the interrupt handler to schedule
* processing in the software interrupt portion of the driver.
*/
@@ -923,7 +832,7 @@
unsigned int i;

if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
- for (i=1; i < 16; i++) {
+ for (i=1; i < NR_IRQS; i++) {
info = IRQ_ports[i];
if (!info)
continue;
@@ -975,38 +884,6 @@
*/

/*
- * Grab all interrupts in preparation for doing an automatic irq
- * detection. dontgrab is a mask of irq's _not_ to grab. Returns a
- * mask of irq's which were grabbed and should therefore be freed
- * using free_all_interrupts().
- */
-static int grab_all_interrupts(int dontgrab)
-{
- int irq_lines = 0;
- int i, mask;
-
- for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
- if (!(mask & dontgrab) && !request_irq(i, rs_probe, SA_INTERRUPT, "serial probe", NULL)) {
- irq_lines |= mask;
- }
- }
- return irq_lines;
-}
-
-/*
- * Release all interrupts grabbed by grab_all_interrupts
- */
-static void free_all_interrupts(int irq_lines)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- if (irq_lines & (1 << i))
- free_irq(i, NULL);
- }
-}
-
-/*
* 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....
@@ -1541,44 +1418,61 @@

if (!tty || !info->xmit_buf || !tmp_buf)
return 0;
-
- if (from_user)
- down(&tmp_buf_sem);
+
save_flags(flags);
- while (1) {
- cli();
- c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- if (c <= 0)
- break;
+ if (from_user) {
+ down(&tmp_buf_sem);
+ while (1) {
+ c = MIN(count,
+ MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0)
+ break;

- if (from_user) {
c -= copy_from_user(tmp_buf, buf, c);
if (!c) {
if (!ret)
ret = -EFAULT;
break;
}
+ cli();
c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
- } else
+ info->xmit_head = ((info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+ up(&tmp_buf_sem);
+ } else {
+ while (1) {
+ cli();
+ c = MIN(count,
+ MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0) {
+ restore_flags(flags);
+ break;
+ }
memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
- info->xmit_cnt += c;
- restore_flags(flags);
- buf += c;
- count -= c;
- ret += c;
+ info->xmit_head = ((info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ restore_flags(flags);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
}
- if (from_user)
- up(&tmp_buf_sem);
if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
!(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
serial_out(info, UART_IER, info->IER);
}
- restore_flags(flags);
return ret;
}

@@ -1759,10 +1653,9 @@
goto check_and_exit;
}

- if (new_serial.irq == 2)
- new_serial.irq = 9;
+ new_serial.irq = irq_cannonicalize(new_serial.irq);

- if ((new_serial.irq > 15) || (new_serial.port > 0xffff) ||
+ if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
(new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) {
return -EINVAL;
}
@@ -1793,6 +1686,7 @@
state->type = new_serial.type;
state->close_delay = new_serial.close_delay * HZ/100;
state->closing_wait = new_serial.closing_wait * HZ/100;
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
info->xmit_fifo_size = state->xmit_fifo_size =
new_serial.xmit_fifo_size;

@@ -1951,9 +1845,9 @@

shutdown(info);

- cli();
autoconfig(info->state);
- sti();
+ if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0))
+ info->state->irq = detect_uart_irq(info->state);

retval = startup(info);
if (retval)
@@ -1984,50 +1878,6 @@
restore_flags(flags);
}

-/*
- * This routine returns a bitfield of "wild interrupts". Basically,
- * any unclaimed interrupts which is flapping around.
- */
-static int check_wild_interrupts(int doprint)
-{
- int i, mask;
- int wild_interrupts = 0;
- int irq_lines;
- unsigned long timeout;
- unsigned long flags;
-
- /* Turn on interrupts (they may be off) */
- save_flags(flags); sti();
-
- irq_lines = grab_all_interrupts(0);
-
- /*
- * Delay for 0.1 seconds -- we use a busy loop since this may
- * occur during the bootup sequence
- */
- timeout = jiffies+HZ/10;
- while (timeout >= jiffies)
- ;
-
- rs_triggered = 0; /* Reset after letting things settle */
-
- timeout = jiffies+HZ/10;
- while (timeout >= jiffies)
- ;
-
- for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
- if ((rs_triggered & (1 << i)) &&
- (irq_lines & (1 << i))) {
- wild_interrupts |= mask;
- if (doprint)
- printk("Wild interrupt? (IRQ %d)\n", i);
- }
- }
- free_all_interrupts(irq_lines);
- restore_flags(flags);
- return wild_interrupts;
-}
-
#ifdef CONFIG_SERIAL_MULTIPORT
static int get_multiport_struct(struct async_struct * info,
struct serial_multiport_struct *retinfo)
@@ -2155,8 +2005,7 @@
return -ENODEV;

if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
- (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) &&
+ (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
@@ -2178,23 +2027,9 @@
case TIOCSERCONFIG:
return do_autoconfig(info);

- case TIOCSERGWILD:
- return put_user(rs_wild_int_mask,
- (unsigned int *) arg);
case TIOCSERGETLSR: /* Get line status register */
return get_lsr_info(info, (unsigned int *) arg);

- case TIOCSERSWILD:
- if (!suser())
- return -EPERM;
- error = get_user(rs_wild_int_mask,
- (unsigned int *) arg);
- if (error)
- return error;
- if (rs_wild_int_mask < 0)
- rs_wild_int_mask = check_wild_interrupts(0);
- return 0;
-
case TIOCSERGSTRUCT:
if (copy_to_user((struct async_struct *) arg,
info, sizeof(struct async_struct)))
@@ -2216,7 +2051,7 @@
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
* Caller should use TIOCGICOUNT to see which one it was
*/
- case TIOCMIWAIT:
+ case TIOCMIWAIT:
cli();
/* note the counters on entry */
cprev = info->state->icount;
@@ -2707,6 +2542,7 @@
#endif
tty->driver_data = info;
info->tty = tty;
+ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;

if (!tmp_buf) {
page = get_free_page(GFP_KERNEL);
@@ -2778,7 +2614,7 @@
* /proc fs routines....
*/

-static int inline line_info(char *buf, struct serial_state *state)
+static inline int line_info(char *buf, struct serial_state *state)
{
struct async_struct *info = state->info, scr_info;
char stat_buf[30], control, status;
@@ -2906,7 +2742,10 @@
#endif
#ifdef CONFIG_SERIAL_SHARE_IRQ
printk(" SHARE_IRQ");
+#endif
#define SERIAL_OPT
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+ printk(" DETECT_IRQ");
#endif
#ifdef SERIAL_OPT
printk(" enabled\n");
@@ -2917,105 +2756,54 @@
}

/*
- * This routine is called by do_auto_irq(); it attempts to determine
- * which interrupt a serial port is configured to use. It is not
- * fool-proof, but it works a large part of the time.
- */
-static int get_auto_irq(struct async_struct *info)
-{
-
- unsigned char save_MCR, save_IER;
- unsigned long timeout;
-#ifdef CONFIG_SERIAL_MANY_PORTS
- unsigned char save_ICP=0;
- unsigned short ICP=0, port = info->port;
-#endif
+ * This routine detect the IRQ of a serial port by clearing OUT2 when
+ * no UART interrupt are requested (IER = 0) (*GPL*). This seems to work at
+ * each time, as long as no other device permanently request the IRQ.
+ * If no IRQ is detected, or multiple IRQ appear, this function returns 0.
+ * The variable "state" and the field "state->port" should not be null.
+ */
+static unsigned detect_uart_irq (struct serial_state * state)
+{
+ int irq;
+ unsigned long irqs;
+ unsigned char save_mcr;
+ struct async_struct scr_info; /* serial_{in,out} because HUB6 */

-
- /*
- * Enable interrupts and see who answers
- */
- rs_irq_triggered = 0;
- cli();
- save_IER = serial_inp(info, UART_IER);
- save_MCR = serial_inp(info, UART_MCR);
#ifdef CONFIG_SERIAL_MANY_PORTS
- if (info->flags & ASYNC_FOURPORT) {
- serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
- serial_outp(info, UART_IER, 0x0f); /* enable all intrs */
- ICP = (port & 0xFE0) | 0x01F;
+ unsigned char save_ICP=0; /* no warning */
+ unsigned short ICP=0;
+
+ if (state->flags & ASYNC_FOURPORT) {
+ ICP = (state->port & 0xFE0) | 0x01F;
save_ICP = inb_p(ICP);
outb_p(0x80, ICP);
(void) inb_p(ICP);
- } else
-#endif
- {
- serial_outp(info, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
- serial_outp(info, UART_IER, 0x0f); /* enable all intrs */
- }
- sti();
- /*
- * Next, clear the interrupt registers.
- */
- (void)serial_inp(info, UART_LSR);
- (void)serial_inp(info, UART_RX);
- (void)serial_inp(info, UART_IIR);
- (void)serial_inp(info, UART_MSR);
-
- timeout = jiffies+ ((2*HZ)/100);
- while (timeout >= jiffies) {
- if (rs_irq_triggered)
- break;
}
- /*
- * Now check to see if we got any business, and clean up.
- */
- cli();
- serial_outp(info, UART_IER, save_IER);
- serial_outp(info, UART_MCR, save_MCR);
-#ifdef CONFIG_SERIAL_MANY_PORTS
- if (info->flags & ASYNC_FOURPORT)
- outb_p(save_ICP, ICP);
#endif
- sti();
- return(rs_irq_triggered);
-}
+ scr_info.magic = SERIAL_MAGIC;
+ scr_info.port = state->port;
+ scr_info.flags = state->flags;
+#ifdef CONFIG_HUB6
+ scr_info.hub6 = state->hub6;
+#endif

-/*
- * Calls get_auto_irq() multiple times, to make sure we don't get
- * faked out by random interrupts
- */
-static int do_auto_irq(struct async_struct * info)
-{
- unsigned port = info->port;
- int irq_lines = 0;
- int irq_try_1 = 0, irq_try_2 = 0;
- int retries;
- unsigned long flags;
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+ save_mcr = serial_inp(&scr_info, UART_MCR);

- if (!port)
- return 0;
+ serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+ irqs = probe_irq_on();
+ serial_outp(&scr_info, UART_MCR, 0);
+ udelay (1);
+ irq = probe_irq_off(irqs);

- /* Turn on interrupts (they may be off) */
- save_flags(flags); sti();
+ serial_outp(&scr_info, UART_MCR, save_mcr);

- irq_lines = grab_all_interrupts(rs_wild_int_mask);
-
- for (retries = 0; retries < 5; retries++) {
- if (!irq_try_1)
- irq_try_1 = get_auto_irq(info);
- if (!irq_try_2)
- irq_try_2 = get_auto_irq(info);
- if (irq_try_1 && irq_try_2) {
- if (irq_try_1 == irq_try_2)
- break;
- irq_try_1 = irq_try_2 = 0;
- }
- }
- restore_flags(flags);
- free_all_interrupts(irq_lines);
- return (irq_try_1 == irq_try_2) ? irq_try_1 : 0;
+#ifdef CONFIG_SERIAL_MANY_PORTS
+ if (state->flags & ASYNC_FOURPORT)
+ outb_p(save_ICP, ICP);
+#endif
+ return (irq > 0)? irq : 0;
}

/*
@@ -3041,6 +2829,9 @@
info->magic = SERIAL_MAGIC;
info->port = state->port;
info->flags = state->flags;
+#ifdef CONFIG_HUB6
+ info->hub6 = state->hub6;
+#endif

save_flags(flags); cli();

@@ -3086,13 +2877,6 @@
}
}

- /*
- * If the AUTO_IRQ flag is set, try to do the automatic IRQ
- * detection.
- */
- if (state->flags & ASYNC_AUTO_IRQ)
- state->irq = do_auto_irq(info);
-
scratch2 = serial_in(info, UART_LCR);
serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */
@@ -3174,6 +2958,7 @@
serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT));
(void)serial_in(info, UART_RX);
+ serial_outp(info, UART_IER, 0);

restore_flags(flags);
}
@@ -3191,15 +2976,21 @@
{
int i;
struct serial_state * state;
-
+ extern void atomwide_serial_init (void);
+ extern void dualsp_serial_init (void);
+
+#ifdef CONFIG_ATOMWIDE_SERIAL
+ atomwide_serial_init ();
+#endif
+#ifdef CONFIG_DUALSP_SERIAL
+ dualsp_serial_init ();
+#endif
+
init_bh(SERIAL_BH, do_serial_bh);
timer_table[RS_TIMER].fn = rs_timer;
timer_table[RS_TIMER].expires = 0;
-#ifdef CONFIG_AUTO_IRQ
- rs_wild_int_mask = check_wild_interrupts(1);
-#endif

- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NR_IRQS; i++) {
IRQ_ports[i] = 0;
IRQ_timeout[i] = 0;
#ifdef CONFIG_SERIAL_MULTIPORT
@@ -3291,17 +3082,26 @@
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
- if (state->irq == 2)
- state->irq = 9;
- if (state->type == PORT_UNKNOWN) {
- if (!(state->flags & ASYNC_BOOT_AUTOCONF))
- continue;
- if (check_region(state->port,8))
- continue;
- autoconfig(state);
- if (state->type == PORT_UNKNOWN)
- continue;
+ state->irq = irq_cannonicalize(state->irq);
+ if (check_region(state->port,8)) {
+ state->type = PORT_UNKNOWN;
+ continue;
}
+ if ( (state->type == PORT_UNKNOWN)
+ && (state->flags & ASYNC_BOOT_AUTOCONF))
+ autoconfig(state);
+ }
+ /*
+ * Detect the IRQ only once every port is initialised,
+ * because some 16450 do not reset to 0 the MCR register.
+ */
+ for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+ if (state->type == PORT_UNKNOWN)
+ continue;
+ if ( (state->flags & ASYNC_BOOT_AUTOCONF)
+ && (state->flags & ASYNC_AUTO_IRQ)
+ && (state->port != 0))
+ state->irq = detect_uart_irq(state);
printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n",
state->line,
(state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
@@ -3354,10 +3154,14 @@
printk("register_serial(): autoconfig failed\n");
return -1;
}
+ restore_flags(flags);
+
+ if ((state->flags & ASYNC_AUTO_IRQ) && (state->port != 0))
+ state->irq = detect_uart_irq(state);
+
printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n",
state->line, state->port, state->irq,
uart_config[state->type].name);
- restore_flags(flags);
return state->line;
}

@@ -3597,7 +3401,7 @@
* Divisor, bytesize and parity
*/
ser = rs_table + co->index;
- quot = BASE_BAUD / baud;
+ quot = ser->baud_base / baud;
cval = cflag & (CSIZE | CSTOPB);
#if defined(__powerpc__) || defined(__alpha__)
cval >>= 8;
@@ -3613,13 +3417,12 @@
* Disable UART interrupts, set DTR and RTS high
* and set speed.
*/
- outb(cval, ser->port + UART_LCR); /* don't assume that DLAB is clear */
- outb(0, ser->port + UART_IER);
- outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);
outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */
outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */
outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */
outb(cval, ser->port + UART_LCR); /* reset DLAB */
+ outb(0, ser->port + UART_IER);
+ outb(UART_MCR_DTR | UART_MCR_RTS, ser->port + UART_MCR);

/*
* If we read 0xff from the LSR, there is no UART here.
===================================================================
RCS file: drivers/char/RCS/tty_io.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/tty_io.c
--- drivers/char/tty_io.c 1998/04/15 19:53:45 1.1
+++ drivers/char/tty_io.c 1998/04/16 14:34:23
@@ -131,12 +131,13 @@
/*
* This routine returns the name of tty.
*/
+#define TTY_NUMBER(tty) (MINOR((tty)->device) - (tty)->driver.minor_start + \
+ (tty)->driver.name_base)
+
char *tty_name(struct tty_struct *tty, char *buf)
{
if (tty)
- sprintf(buf, "%s%d", tty->driver.name,
- MINOR(tty->device) - tty->driver.minor_start +
- tty->driver.name_base);
+ sprintf(buf, "%s%d", tty->driver.name, TTY_NUMBER(tty));
else
strcpy(buf, "NULL tty");
return buf;
@@ -1287,9 +1288,17 @@
tty->pgrp = current->pgrp;
}
if ((tty->driver.type == TTY_DRIVER_TYPE_SERIAL) &&
- (tty->driver.subtype == SERIAL_TYPE_CALLOUT)) {
- printk(KERN_INFO "Warning, %s opened, is a deprecated tty "
- "callout device\n", tty_name(tty, buf));
+ (tty->driver.subtype == SERIAL_TYPE_CALLOUT) &&
+ (tty->count == 1)) {
+ static int nr_warns = 0;
+ if (nr_warns < 5) {
+ printk(KERN_WARNING "tty_io.c: "
+ "process %d (%s) used obsolete /dev/%s - "
+ "update software to use /dev/ttyS%d\n",
+ current->pid, current->comm,
+ tty_name(tty, buf), TTY_NUMBER(tty));
+ nr_warns++;
+ }
}
return 0;
}
===================================================================
RCS file: include/asm-i386/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-i386/irq.h
--- include/asm-i386/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-i386/irq.h 1998/04/15 19:53:55
@@ -18,6 +18,11 @@

#define TIMER_IRQ 0

+static __inline__ int irq_cannonicalize(int irq)
+{
+ return ((irq == 2) ? 9 : irq);
+}
+
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);

===================================================================
RCS file: include/asm-alpha/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-alpha/irq.h
--- include/asm-alpha/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-alpha/irq.h 1998/04/16 15:23:56
@@ -52,6 +52,14 @@

#endif

+static __inline__ int irq_cannonicalize(int irq)
+{
+ /*
+ * XXX is this true for all Alpha's? The old serial driver
+ * did it this way for years without any complaints, so....
+ */
+ return ((irq == 2) ? 9 : irq);
+}

extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
===================================================================
RCS file: include/asm-m68k/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-m68k/irq.h
--- include/asm-m68k/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-m68k/irq.h 1998/04/15 19:53:55
@@ -45,6 +45,11 @@

#define IRQ_SCHED_TIMER (8) /* interrupt source for scheduling timer */

+static __inline__ int irq_cannonicalize(int irq)
+{
+ return irq;
+}
+
/*
* Machine specific interrupt sources.
*
===================================================================
RCS file: include/asm-ppc/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-ppc/irq.h
--- include/asm-ppc/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-ppc/irq.h 1998/04/15 19:53:55
@@ -15,6 +15,11 @@
#define irq_to_openpic(n) ((n)-NUM_8259_INTERRUPTS)
#define IRQ_8259_CASCADE NUM_8259_INTERRUPTS

+static __inline__ int irq_cannonicalize(int irq)
+{
+ return irq;
+}
+
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);

===================================================================
RCS file: include/asm-sparc/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-sparc/irq.h
--- include/asm-sparc/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-sparc/irq.h 1998/04/15 19:53:55
@@ -66,6 +66,11 @@
#define irq_exit(cpu, irq) (local_irq_count[cpu]--)
#endif

+static __inline__ int irq_cannonicalize(int irq)
+{
+ return irq;
+}
+
/* Dave Redman (djhr@tadpole.co.uk)
* changed these to function pointers.. it saves cycles and will allow
* the irq dependencies to be split into different files at a later date
===================================================================
RCS file: include/asm-sparc64/RCS/irq.h,v
retrieving revision 1.1
diff -u -r1.1 include/asm-sparc64/irq.h
--- include/asm-sparc64/irq.h 1998/04/15 19:53:45 1.1
+++ include/asm-sparc64/irq.h 1998/04/15 19:53:55
@@ -75,4 +75,9 @@
return retval;
}

+static __inline__ int irq_cannonicalize(int irq)
+{
+ return irq;
+}
+
#endif
--- /dev/null Mon Dec 31 23:00:00 1979
+++ include/asm-i386/serial.h Thu Apr 16 11:17:22 1998
@@ -0,0 +1,126 @@
+/*
+ * include/asm-i386/serial.h
+ */
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#endif
+
+/*
+ * The following define the access methods for the HUB6 card. All
+ * access is through two ports for all 24 possible chips. The card is
+ * selected through the high 2 bits, the port on that card with the
+ * "middle" 3 bits, and the register on that port with the bottom
+ * 3 bits.
+ *
+ * While the access port and interrupt is configurable, the default
+ * port locations are 0x302 for the port control register, and 0x303
+ * for the data read/write register. Normally, the interrupt is at irq3
+ * but can be anything from 3 to 7 inclusive. Note that using 3 will
+ * require disabling com2.
+ */
+
+#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
+ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \
+ { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ \
+ { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ \
+ { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */ \
+ { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */ \
+ { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */ \
+ { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */ \
+ { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \
+ { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \
+ { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \
+ { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \
+ { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \
+ { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \
+ { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */ \
+ { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */ \
+ { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */ \
+ { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */ \
+ { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */ \
+ { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */ \
+ { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */ \
+ { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */ \
+ { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */ \
+ { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */ \
+ { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \
+ { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \
+ { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+/* You can have up to four HUB6's in the system, but I've only
+ * included two cards here for a total of twelve ports.
+ */
+#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
+#define HUB6_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) }, /* ttyS32 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) }, /* ttyS33 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) }, /* ttyS34 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) }, /* ttyS35 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) }, /* ttyS36 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) }, /* ttyS37 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) }, /* ttyS38 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) }, /* ttyS39 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) }, /* ttyS40 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) }, /* ttyS41 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) }, /* ttyS42 */ \
+ { 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) }, /* ttyS43 */
+#else
+#define HUB6_SERIAL_PORT_DFNS
+#endif
+
+#ifdef CONFIG_MCA
+#define MCA_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, 0x3220, 3, STD_COM_FLAGS }, \
+ { 0, BASE_BAUD, 0x3228, 3, STD_COM_FLAGS }, \
+ { 0, BASE_BAUD, 0x4220, 3, STD_COM_FLAGS }, \
+ { 0, BASE_BAUD, 0x4228, 3, STD_COM_FLAGS }, \
+ { 0, BASE_BAUD, 0x5220, 3, STD_COM_FLAGS }, \
+ { 0, BASE_BAUD, 0x5228, 3, STD_COM_FLAGS },
+#else
+#define MCA_SERIAL_PORT_DFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DEFNS \
+ EXTRA_SERIAL_PORT_DEFNS \
+ HUB6_SERIAL_PORT_DFNS \
+ MCA_SERIAL_PORT_DFNS
+
--- /dev/null Mon Dec 31 23:00:00 1979
+++ include/asm-alpha/serial.h Wed Apr 15 15:53:55 1998
@@ -0,0 +1,73 @@
+/*
+ * include/asm-alpha/serial.h
+ */
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
+ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \
+ { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ \
+ { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ \
+ { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */ \
+ { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */ \
+ { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */ \
+ { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */ \
+ { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \
+ { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \
+ { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \
+ { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \
+ { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \
+ { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \
+ { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */ \
+ { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */ \
+ { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */ \
+ { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */ \
+ { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */ \
+ { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */ \
+ { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */ \
+ { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */ \
+ { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */ \
+ { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */ \
+ { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \
+ { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \
+ { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DEFNS \
+ EXTRA_SERIAL_PORT_DEFNS

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu