Update to 2.3.28's serial driver

tytso@mit.edu
Wed, 17 Nov 1999 15:19:03 -0500


Hi Linus,

Enclosed please find an update to the serial driver. I'd appreciate it
if you would apply this to your sources. Enhancements here include:

* Removal of backwards compatibility gunk for compiling this
driver with older kernel versions. (For people who wish to
use this driver with older kernels, they should grab the
stand-alone serial driver, found at my serial web page
<http://web.mit.edu/tytso/www/linux/serial>.)

This should make Linus happy since none of the compatibility
gunk is in his tree; it's been moved out to serial_compat.h in
the stand-alone driver distribution.

* Add support for using the magic sysreq feature when using a
serial console; it is accessed using by an RS-232 break
signal.

* Add support for a number of new PCI serial boards, including
from SIIG, Chase Research, and Computune.

* Add support for GSC-bus attached serial devices (for the HP
PA-RISC port).

* Some UART's lock up when the 16C950 test writes to the LSR
register. Move the 16C950 test after the StarTech test to
avoid locking up these older UART's.

* request_irq() is now passed a non-NULL dev_id, to facilitate
sharing IRQ's.

Thanks!!

- Ted

Patch generated: on Wed Nov 17 15:03:45 EST 1999 by tytso@universal.thunk.org
against Linux version 2.3.28

===================================================================
RCS file: drivers/char/RCS/serial.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/serial.c
--- drivers/char/serial.c 1999/11/17 03:03:11 1.1
+++ drivers/char/serial.c 1999/11/17 20:03:06
@@ -44,6 +44,9 @@
* int rs_init(void);
*/

+static char *serial_version = "4.91";
+static char *serial_revdate = "1999-11-17";
+
/*
* Serial driver configuration section. Here are the various options:
*
@@ -88,8 +91,13 @@

#if (defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= 131072))
#define ENABLE_SERIAL_PCI
+#ifndef CONFIG_SERIAL_SHARE_IRQ
#define CONFIG_SERIAL_SHARE_IRQ
#endif
+#ifndef CONFIG_SERIAL_MANY_PORTS
+#define CONFIG_SERIAL_MANY_PORTS
+#endif
+#endif

/* Set of debugging defines */

@@ -98,6 +106,7 @@
#undef SERIAL_DEBUG_FLOW
#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
#undef SERIAL_DEBUG_PCI
+#undef SERIAL_DEBUG_AUTOCONF

/* Sanity checks */

@@ -119,10 +128,9 @@
#define RS_STROBE_TIME (10*HZ)
#define RS_ISR_PASS_LIMIT 256

-#define IRQ_T(state) \
- ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
-
+#if (defined(__i386__) && (CPU==386 || CPU==486))
#define SERIAL_INLINE
+#endif

#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
@@ -146,12 +154,14 @@
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
+#include <linux/module.h>
#else /* !NEW_MODULES */
#ifdef MODVERSIONS
#define MODULE
#endif
-#endif /* NEW_MODULES */
#include <linux/module.h>
+#endif /* NEW_MODULES */
+
#include <linux/types.h>
#ifdef LOCAL_HEADERS
#include "serial_local.h"
@@ -160,7 +170,7 @@
#include <linux/serialP.h>
#include <linux/serial_reg.h>
#include <asm/serial.h>
-static char *serial_version = "4.30";
+#define LOCAL_VERSTRING ""
#endif

#include <linux/errno.h>
@@ -177,10 +187,11 @@
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/malloc.h>
-#if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
+#if (LINUX_VERSION_CODE >= 131343)
#include <linux/init.h>
-#else
-#define __initfunc(x) x
+#endif
+#if (LINUX_VERSION_CODE >= 131336)
+#include <asm/uaccess.h>
#endif
#include <linux/delay.h>
#ifdef CONFIG_SERIAL_CONSOLE
@@ -190,6 +201,14 @@
#include <linux/pci.h>
#endif

+/*
+ * All of the compatibilty code so we can compile serial.c against
+ * older kernels is hidden in serial_compat.h
+ */
+#if (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
+#include "serial_compat.h"
+#endif
+
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -203,6 +222,8 @@

#ifdef SERIAL_INLINE
#define _INLINE_ inline
+#else
+#define _INLINE_
#endif

static char *serial_name = "Serial driver";
@@ -233,6 +254,7 @@
static int IRQ_timeout[NR_IRQS];
#ifdef CONFIG_SERIAL_CONSOLE
static struct console sercons;
+static unsigned long break_pressed; /* break, really ... */
#endif

static unsigned detect_uart_irq (struct serial_state * state);
@@ -274,7 +296,11 @@
#define NR_PCI_BOARDS 8
static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS];
static int serial_pci_board_idx = 0;
+#ifdef PCI_NUM_RESOURCES
#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
+#else
+#define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r])
+#endif
#endif /* ENABLE_SERIAL_PCI */

static struct tty_struct *serial_table[NR_PORTS];
@@ -301,87 +327,6 @@
static struct semaphore tmp_buf_sem = MUTEX;
#endif

-/*
- * Provide backwards compatibility for kernels prior to 2.1.XX.
- */
-#if (LINUX_VERSION_CODE < 0x20000)
-typedef dev_t kdev_t;
-#endif
-
-#if (LINUX_VERSION_CODE < 0x02017E)
-static signed long schedule_timeout(signed long timeout)
-{
- unsigned long expire;
-
- expire = timeout + jiffies;
-
- current->timeout = jiffies + timeout;
- schedule();
-
- timeout = expire - jiffies;
- return timeout < 0 ? 0 : timeout;
-}
-#endif
-
-#ifndef time_after
-#define time_after(a,b) ((long)(b) - (long)(a) < 0)
-#endif
-
-#if (LINUX_VERSION_CODE < 0x020100)
-static inline int irq_cannonicalize(int irq)
-{
- return ((irq == 2) ? 9 : irq);
-}
-#endif
-
-#if (LINUX_VERSION_CODE < 131336)
-static int copy_from_user(void *to, const void *from_user, unsigned long len)
-{
- int error;
-
- error = verify_area(VERIFY_READ, from_user, len);
- if (error)
- return len;
- memcpy_fromfs(to, from_user, len);
- return 0;
-}
-
-static int copy_to_user(void *to_user, const void *from, unsigned long len)
-{
- int error;
-
- error = verify_area(VERIFY_WRITE, to_user, len);
- if (error)
- return len;
- memcpy_tofs(to_user, from, len);
- return 0;
-}
-
-static inline int signal_pending(struct task_struct *p)
-{
- return (p->signal & (~p->blocked != 0));
-}
-
-#else
-#include <asm/uaccess.h>
-#endif
-
-#ifdef CAP_SYS_ADMIN
-#define serial_isroot() (capable(CAP_SYS_ADMIN))
-#else
-#define serial_isroot() (suser())
-#endif
-
-#if (LINUX_VERSION_CODE < 131394) /* 2.1.66 */
-#define test_and_clear_bit(x,y) clear_bit(x,y)
-
-static inline void remove_bh(int nr)
-{
- bh_base[nr] = NULL;
- bh_mask &= ~(1 << nr);
-}
-#endif
-

static inline int serial_paranoia_check(struct async_struct *info,
kdev_t device, const char *routine)
@@ -404,78 +349,63 @@
return 0;
}

-static inline unsigned int serial_in(struct async_struct *info, int offset)
+static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset)
{
+ switch (info->io_type) {
#ifdef CONFIG_HUB6
- if (info->hub6) {
- outb(info->hub6 - 1 + offset, info->port);
- return inb(info->port+1);
- } else
+ case SERIAL_IO_HUB6:
+ outb(info->hub6 - 1 + offset, info->port);
+ return inb(info->port+1);
#endif
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
- if (info->iomem_base)
- return readb(info->iomem_base + (offset<<info->iomem_reg_shift));
- else
+ case SERIAL_IO_MEM:
+ return readb(info->iomem_base +
+ (offset<<info->iomem_reg_shift));
+#endif
+#ifdef CONFIG_SERIAL_GSC
+ case SERIAL_IO_GSC:
+ return gsc_readb(info->iomem_base + offset);
#endif
- return inb(info->port + offset);
+ default:
+ return inb(info->port + offset);
+ }
}

-static inline unsigned int serial_inp(struct async_struct *info, int offset)
+static _INLINE_ void serial_out(struct async_struct *info, int offset,
+ int value)
{
+ switch (info->io_type) {
#ifdef CONFIG_HUB6
- if (info->hub6) {
- outb(info->hub6 - 1 + offset, info->port);
- return inb_p(info->port+1);
- } else
+ case SERIAL_IO_HUB6:
+ outb(info->hub6 - 1 + offset, info->port);
+ outb(value, info->port+1);
+ break;
#endif
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
- if (info->iomem_base)
- return readb(info->iomem_base + (offset<<info->iomem_reg_shift));
- else
+ case SERIAL_IO_MEM:
+ writeb(value, info->iomem_base +
+ (offset<<info->iomem_reg_shift));
+ break;
#endif
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
- return inb(info->port + offset);
-#else
- return inb_p(info->port + offset);
+#ifdef CONFIG_SERIAL_GSC
+ case SERIAL_IO_GSC:
+ gsc_writeb(value, info->iomem_base + offset);
+ break;
#endif
+ default:
+ outb(value, info->port+offset);
+ }
}

-static inline void serial_out(struct async_struct *info, int offset, int value)
-{
-#ifdef CONFIG_HUB6
- if (info->hub6) {
- outb(info->hub6 - 1 + offset, info->port);
- outb(value, info->port+1);
- } else
-#endif
-#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
- if (info->iomem_base)
- writeb(value, info->iomem_base + (offset<<info->iomem_reg_shift));
- else
-#endif
- outb(value, info->port+offset);
-}
+/*
+ * We used to support using pause I/O for certain machines. We
+ * haven't supported this for a while, but just in case it's badly
+ * needed for certain old 386 machines, I've left these #define's
+ * in....
+ */
+#define serial_inp(info, offset) serial_in(info, offset)
+#define serial_outp(info, offset, value) serial_out(info, offset, value)

-static inline void serial_outp(struct async_struct *info, int offset,
- int value)
-{
-#ifdef CONFIG_HUB6
- if (info->hub6) {
- outb(info->hub6 - 1 + offset, info->port);
- outb_p(value, info->port+1);
- } else
-#endif
-#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
- if (info->iomem_base)
- writeb(value, info->iomem_base + (offset<<info->iomem_reg_shift));
- else
-#endif
-#ifdef CONFIG_SERIAL_NOPAUSE_IO
- outb(value, info->port+offset);
-#else
- outb_p(value, info->port+offset);
-#endif
-}

/*
* For the 16C950
@@ -579,7 +509,7 @@
}

static _INLINE_ void receive_chars(struct async_struct *info,
- int *status)
+ int *status, struct pt_regs * regs)
{
struct tty_struct *tty = info->tty;
unsigned char ch;
@@ -590,7 +520,7 @@
do {
ch = serial_inp(info, UART_RX);
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- break;
+ goto ignore_char;
*tty->flip.char_buf_ptr = ch;
icount->rx++;

@@ -629,6 +559,15 @@
#ifdef SERIAL_DEBUG_INTR
printk("handling break....");
#endif
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+ if (info->line == sercons.index) {
+ if (!break_pressed) {
+ break_pressed = jiffies;
+ goto ignore_char;
+ }
+ break_pressed = 0;
+ }
+#endif
*tty->flip.flag_buf_ptr = TTY_BREAK;
if (info->flags & ASYNC_SAK)
do_SAK(tty);
@@ -642,14 +581,25 @@
* 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.count++;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ goto ignore_char;
+ }
+ }
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
+ if (break_pressed && info->line == 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
tty->flip.flag_buf_ptr++;
tty->flip.char_buf_ptr++;
tty->flip.count++;
@@ -819,7 +769,7 @@
printk("status = %x...", status);
#endif
if (status & UART_LSR_DR)
- receive_chars(info, &status);
+ receive_chars(info, &status, regs);
check_modem_status(info);
if (status & UART_LSR_THRE)
transmit_chars(info, 0);
@@ -883,7 +833,7 @@
printk("status = %x...", status);
#endif
if (status & UART_LSR_DR)
- receive_chars(info, &status);
+ receive_chars(info, &status, regs);
check_modem_status(info);
if (status & UART_LSR_THRE)
transmit_chars(info, 0);
@@ -946,7 +896,7 @@
printk("status = %x...", status);
#endif
if (status & UART_LSR_DR)
- receive_chars(info, &status);
+ receive_chars(info, &status, regs);
check_modem_status(info);
if (status & UART_LSR_THRE)
transmit_chars(info, 0);
@@ -1041,7 +991,7 @@
unsigned long flags;

if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
- for (i=1; i < NR_IRQS; i++) {
+ for (i=0; i < NR_IRQS; i++) {
info = IRQ_ports[i];
if (!info)
continue;
@@ -1228,7 +1178,7 @@
*/
if (serial_inp(info, UART_LSR) == 0xff) {
printk("LSR safety check engaged!\n");
- if (serial_isroot()) {
+ if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
} else
@@ -1243,7 +1193,7 @@
!IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) {
#ifdef CONFIG_SERIAL_SHARE_IRQ
- free_irq(state->irq, NULL);
+ free_irq(state->irq, &IRQ_ports[state->irq]);
#ifdef CONFIG_SERIAL_MULTIPORT
if (rs_multiport[state->irq].port1)
handler = rs_interrupt_multi;
@@ -1257,10 +1207,10 @@
} else
handler = rs_interrupt_single;

- retval = request_irq(state->irq, handler, IRQ_T(state),
- "serial", NULL);
+ retval = request_irq(state->irq, handler, SA_SHIRQ,
+ "serial", &IRQ_ports[state->irq]);
if (retval) {
- if (serial_isroot()) {
+ if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR,
&info->tty->flags);
@@ -1409,15 +1359,16 @@
if (state->irq && (!IRQ_ports[state->irq] ||
!IRQ_ports[state->irq]->next_port)) {
if (IRQ_ports[state->irq]) {
- free_irq(state->irq, NULL);
+ free_irq(state->irq, &IRQ_ports[state->irq]);
retval = request_irq(state->irq, rs_interrupt_single,
- IRQ_T(state), "serial", NULL);
+ SA_SHIRQ, "serial",
+ &IRQ_ports[state->irq]);

if (retval)
printk("serial shutdown: request_irq: error %d"
" Couldn't reacquire IRQ.\n", retval);
} else
- free_irq(state->irq, NULL);
+ free_irq(state->irq, &IRQ_ports[state->irq]);
}

if (info->xmit_buf) {
@@ -1445,8 +1396,11 @@
serial_outp(info, UART_MCR, info->MCR);

/* disable FIFO's */
- serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+ serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT));
+ serial_outp(info, UART_FCR, 0);
+
(void)serial_in(info, UART_RX); /* read data port to reset things */

if (info->tty)
@@ -1922,6 +1876,7 @@
tmp.closing_wait = state->closing_wait;
tmp.custom_divisor = state->custom_divisor;
tmp.hub6 = state->hub6;
+ tmp.io_type = state->io_type;
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1944,7 +1899,7 @@
change_port = (new_serial.port != state->port) ||
(new_serial.hub6 != state->hub6);

- if (!serial_isroot()) {
+ if (!capable(CAP_SYS_ADMIN)) {
if (change_irq || change_port ||
(new_serial.baud_base != state->baud_base) ||
(new_serial.type != state->type) ||
@@ -1963,7 +1918,7 @@

new_serial.irq = irq_cannonicalize(new_serial.irq);

- if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
+ if ((new_serial.irq >= NR_IRQS) ||
(new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
(new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
(new_serial.type == PORT_STARTECH)) {
@@ -1973,7 +1928,7 @@
if ((new_serial.type != state->type) ||
(new_serial.xmit_fifo_size <= 0))
new_serial.xmit_fifo_size =
- uart_config[state->type].dfl_xmit_fifo_size;
+ uart_config[new_serial.type].dfl_xmit_fifo_size;

/* Make sure address is not already in use */
if (new_serial.type) {
@@ -1998,17 +1953,17 @@
info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
(info->flags & ASYNC_INTERNAL_FLAGS));
state->custom_divisor = new_serial.custom_divisor;
- state->type = new_serial.type;
state->close_delay = new_serial.close_delay * HZ/100;
state->closing_wait = new_serial.closing_wait * HZ/100;
-#if (LINUX_VERSION_CODE > 0x200100)
+#if (LINUX_VERSION_CODE > 0x20100)
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
#endif
info->xmit_fifo_size = state->xmit_fifo_size =
new_serial.xmit_fifo_size;

- if (state->type != PORT_UNKNOWN && state->port)
+ if ((state->type != PORT_UNKNOWN) && state->port)
release_region(state->port,8);
+ state->type = new_serial.type;
if (change_port || change_irq) {
/*
* We need to shutdown the serial port at the old
@@ -2018,6 +1973,10 @@
state->irq = new_serial.irq;
info->port = state->port = new_serial.port;
info->hub6 = state->hub6 = new_serial.hub6;
+ if (info->hub6)
+ info->io_type = state->io_type = SERIAL_IO_HUB6;
+ else if (info->io_type == SERIAL_IO_HUB6)
+ info->io_type = state->io_type = SERIAL_IO_PORT;
}
if ((state->type != PORT_UNKNOWN) && state->port)
request_region(state->port,8,"serial(set)");
@@ -2068,6 +2027,18 @@
status = serial_in(info, UART_LSR);
restore_flags(flags);
result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+
+ /*
+ * If we're about to load something into the transmit
+ * register, we'll pretend the transmitter isn't empty to
+ * avoid a race condition (depending on when the transmit
+ * interrupt happens).
+ */
+ if (info->x_char ||
+ ((info->xmit_cnt > 0) && !info->tty->stopped &&
+ !info->tty->hw_stopped))
+ result &= TIOCSER_TEMT;
+
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
return 0;
@@ -2162,7 +2133,7 @@
{
int retval;

- if (!serial_isroot())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;

if (info->state->count > 1)
@@ -2265,7 +2236,7 @@
int retval;
void (*handler)(int, void *, struct pt_regs *);

- if (!serial_isroot())
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
state = info->state;

@@ -2318,14 +2289,14 @@

if (IRQ_ports[state->irq]->next_port &&
(was_multi != now_multi)) {
- free_irq(state->irq, NULL);
+ free_irq(state->irq, &IRQ_ports[state->irq]);
if (now_multi)
handler = rs_interrupt_multi;
else
handler = rs_interrupt;

- retval = request_irq(state->irq, handler, IRQ_T(state),
- "serial", NULL);
+ retval = request_irq(state->irq, handler, SA_SHIRQ,
+ "serial", &IRQ_ports[state->irq]);
if (retval) {
printk("Couldn't reallocate serial interrupt "
"driver!!\n");
@@ -2652,7 +2623,7 @@
info->tty = 0;
if (info->blocked_open) {
if (info->close_delay) {
- current->state = TASK_INTERRUPTIBLE;
+ set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(info->close_delay);
}
wake_up_interruptible(&info->open_wait);
@@ -2716,14 +2687,14 @@
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
#endif
- current->state = TASK_INTERRUPTIBLE;
+ 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;
+ set_current_state(TASK_RUNNING);
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
@@ -2759,11 +2730,7 @@
static int block_til_ready(struct tty_struct *tty, struct file * filp,
struct async_struct *info)
{
-#ifdef DECLARE_WAITQUEUE
DECLARE_WAITQUEUE(wait, current);
-#else
- struct wait_queue wait = { current, NULL };
-#endif
struct serial_state *state = info->state;
int retval;
int do_clocal = 0, extra_count = 0;
@@ -2880,7 +2847,7 @@
#endif
schedule();
}
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
if (extra_count)
state->count++;
@@ -2912,14 +2879,13 @@
return -ENOMEM;
}
memset(info, 0, sizeof(struct async_struct));
-#ifdef DECLARE_WAITQUEUE
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
init_waitqueue_head(&info->delta_msr_wait);
-#endif
info->magic = SERIAL_MAGIC;
info->port = sstate->port;
info->flags = sstate->flags;
+ info->io_type = sstate->io_type;
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
info->iomem_base = sstate->iomem_base;
info->iomem_reg_shift = sstate->iomem_reg_shift;
@@ -3126,7 +3092,8 @@
int i, len = 0, l;
off_t begin = 0;

- len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+ len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n",
+ serial_version, LOCAL_VERSTRING, serial_revdate);
for (i = 0; i < NR_PORTS && len < 4000; i++) {
l = line_info(page + len, &rs_table[i]);
len += l;
@@ -3160,7 +3127,8 @@
*/
static _INLINE_ void show_serial_version(void)
{
- printk(KERN_INFO "%s version %s with", serial_name, serial_version);
+ printk(KERN_INFO "%s version %s%s (%s) with", serial_name,
+ serial_version, LOCAL_VERSTRING, serial_revdate);
#ifdef CONFIG_HUB6
printk(" HUB-6");
#define SERIAL_OPT
@@ -3298,11 +3266,11 @@
}

/*
- * This is a helper routine to autodetect StarTech/Exar UART's. When
- * this function is called we know it is at least a StarTech 16650 V2,
- * but it might be one of several StarTech UARTs, or one of its
- * clones. (We treat the broken original StarTech 16650 V1 as a
- * 16550A, and why not? Startech doesn't seem to even acknowledge its
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
+ * its clones. (We treat the broken original StarTech 16650 V1 as a
+ * 16550, and why not? Startech doesn't seem to even acknowledge its
* existence.)
*
* What evil have men's minds wrought...
@@ -3311,39 +3279,48 @@
struct serial_state *state,
unsigned long flags)
{
- unsigned char scratch, status1, status2, old_fctr, old_emsr;
+ unsigned char scratch, scratch2, scratch3;

/*
- * Here we check for the XR16C85x family. We do this by
- * checking for to see if we can replace the scratch register
- * with the receive FIFO count register.
+ * First we check to see if it's an Oxford Semiconductor UART.
*
- * XXX I don't have one of these chips, but it should also be
- * possible to check for them by setting DLL and DLM to 0, and
- * then reading back DLL and DLM. If the DLM reads back as
- * 0x10, then the UART is a XR16C850 and the DLL contains the
- * chip revision.
- */
- old_fctr = serial_inp(info, UART_FCTR);
- serial_outp(info, UART_FCTR, old_fctr | UART_FCTR_SCR_SWAP);
- old_emsr = serial_inp(info, UART_EMSR);
- serial_outp(info, UART_EMSR, 0x00);
- serial_outp(info, UART_LCR, 0x00);
- scratch = serial_in(info, UART_SCR);
- serial_outp(info, UART_SCR, 0xa5);
- status1 = serial_in(info, UART_SCR);
- serial_outp(info, UART_SCR, 0x5a);
- status2 = serial_in(info, UART_SCR);
- serial_outp(info, UART_SCR, scratch);
- if ((status1 != 0xa5) || (status2 != 0x5a)) {
- serial_outp(info, UART_LCR, 0xBF);
- serial_outp(info, UART_FCTR, old_fctr | UART_FCTR_SCR_SWAP);
- serial_outp(info, UART_EMSR, old_emsr);
- serial_outp(info, UART_FCTR, old_fctr);
+ * If we have to do this here because some non-National
+ * Semiconductor clone chips lock up if you try writing to the
+ * LSR register (which serial_icr_read does)
+ */
+ if (state->type == PORT_16550A) {
+ /* Check for Oxford Semiconductor 16C950 */
+ scratch = serial_icr_read(info, UART_ID1);
+ scratch2 = serial_icr_read(info, UART_ID2);
+ scratch3 = serial_icr_read(info, UART_ID3);
+
+ if (scratch == 0x16 && scratch2 == 0xC9 &&
+ (scratch3 == 0x50 || scratch3 == 0x52 ||
+ scratch3 == 0x54)) {
+ state->type = PORT_16C950;
+ state->revision = serial_icr_read(info, UART_REV);
+ return;
+ }
+ }
+
+ /*
+ * We check for a XR16C850 by setting DLL and DLM to 0, and
+ * then reading back DLL and DLM. If DLM reads back 0x10,
+ * then the UART is a XR16C850 and the DLL contains the chip
+ * revision. If DLM reads back 0x14, then the UART is a
+ * XR16C854.
+ *
+ */
+ serial_outp(info, UART_LCR, UART_LCR_DLAB);
+ serial_outp(info, UART_DLL, 0);
+ serial_outp(info, UART_DLM, 0);
+ state->revision = serial_inp(info, UART_DLL);
+ scratch = serial_inp(info, UART_DLM);
+ serial_outp(info, UART_LCR, 0);
+ if (scratch == 0x10 || scratch == 0x14) {
state->type = PORT_16850;
return;
}
- serial_outp(info, UART_IER, old_fctr);

/*
* We distinguish between the '654 and the '650 by counting
@@ -3368,10 +3345,16 @@
static void autoconfig(struct serial_state * state)
{
unsigned char status1, status2, scratch, scratch2, scratch3;
+ unsigned char save_lcr, save_mcr;
struct async_struct *info, scr_info;
unsigned long flags;

state->type = PORT_UNKNOWN;
+
+#ifdef SERIAL_DEBUG_AUTOCONF
+ printk("Testing ttyS%d (0x%04x, 0x%04x)...\n", state->line,
+ state->port, (unsigned) state->iomem_base);
+#endif

if (!CONFIGURED_SERIAL_PORT(state))
return;
@@ -3385,6 +3368,7 @@
#ifdef CONFIG_HUB6
info->hub6 = state->hub6;
#endif
+ info->io_type = state->io_type;
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
info->iomem_base = state->iomem_base;
info->iomem_reg_shift = state->iomem_reg_shift;
@@ -3405,15 +3389,29 @@
*/
scratch = serial_inp(info, UART_IER);
serial_outp(info, UART_IER, 0);
+#ifdef __i386__
outb(0xff, 0x080);
+#endif
scratch2 = serial_inp(info, UART_IER);
+ serial_outp(info, UART_IER, 0x0F);
+#ifdef __i386__
+ outb(0, 0x080);
+#endif
+ scratch3 = serial_inp(info, UART_IER);
serial_outp(info, UART_IER, scratch);
- if (scratch2) {
+ if (scratch2 || scratch3 != 0x0F) {
+#ifdef SERIAL_DEBUG_AUTOCONF
+ printk("serial: ttyS%d: simple autoconfig failed\n",
+ state->line);
+#endif
restore_flags(flags);
return; /* We failed; there's nothing here */
}
}

+ save_mcr = serial_in(info, UART_MCR);
+ save_lcr = serial_in(info, UART_LCR);
+
/*
* Check to see if a UART is really there. Certain broken
* internal modems based on the Rockwell chipset fail this
@@ -3424,18 +3422,18 @@
* that conflicts with COM 1-4 --- we hope!
*/
if (!(state->flags & ASYNC_SKIP_TEST)) {
- scratch = serial_inp(info, UART_MCR);
- serial_outp(info, UART_MCR, UART_MCR_LOOP | scratch);
serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
status1 = serial_inp(info, UART_MSR) & 0xF0;
- serial_outp(info, UART_MCR, scratch);
+ serial_outp(info, UART_MCR, save_mcr);
if (status1 != 0x90) {
+#ifdef SERIAL_DEBUG_AUTOCONF
+ printk("serial: ttyS%d: no UART loopback failed\n",
+ state->line);
+#endif
restore_flags(flags);
return;
}
- }
-
- 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 */
serial_outp(info, UART_LCR, 0);
@@ -3456,21 +3454,6 @@
break;
}
if (state->type == PORT_16550A) {
- /* Check for Oxford Semiconductor 16C950 */
- unsigned char scratch4;
-
- scratch = serial_icr_read(info, UART_ID1);
- scratch4 = serial_icr_read(info, UART_ID2);
- scratch3 = serial_icr_read(info, UART_ID3);
-
- if (scratch == 0x16 && scratch4 == 0xC9 &&
- (scratch3 == 0x50 || scratch3 == 0x52 ||
- scratch3 == 0x54)) {
- state->type = PORT_16C950;
- state->revision = serial_icr_read(info, UART_REV);
- }
- }
- if (state->type == PORT_16550A) {
/* Check for Startech UART's */
serial_outp(info, UART_LCR, UART_LCR_DLAB);
if (serial_in(info, UART_EFR) == 0) {
@@ -3483,7 +3466,7 @@
}
if (state->type == PORT_16550A) {
/* Check for TI 16750 */
- serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+ serial_outp(info, UART_LCR, save_lcr | UART_LCR_DLAB);
serial_outp(info, UART_FCR,
UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
scratch = serial_in(info, UART_IIR) >> 5;
@@ -3504,7 +3487,7 @@
}
serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
}
- serial_outp(info, UART_LCR, scratch2);
+ serial_outp(info, UART_LCR, save_lcr);
if (state->type == PORT_16450) {
scratch = serial_in(info, UART_SCR);
serial_outp(info, UART_SCR, 0xa5);
@@ -3529,9 +3512,11 @@
/*
* Reset the UART.
*/
- serial_outp(info, UART_MCR, 0x00 | ALPHA_KLUDGE_MCR); /* Don't ask */
- serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+ serial_outp(info, UART_MCR, save_mcr);
+ serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR |
UART_FCR_CLEAR_XMIT));
+ serial_outp(info, UART_FCR, 0);
(void)serial_in(info, UART_RX);
serial_outp(info, UART_IER, 0);

@@ -3562,11 +3547,11 @@
*
* Note that __init is a no-op if MODULE is defined; we depend on this.
*/
-static void __init pci_plx9050_fn(struct pci_dev *dev,
+static int __init pci_plx9050_fn(struct pci_dev *dev,
struct pci_board *board,
int enable)
{
- u8 data, *p;
+ u8 data, *p, scratch;

pci_read_config_byte(dev, PCI_COMMAND, &data);

@@ -3576,12 +3561,94 @@

/* enable/disable interrupts */
p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80);
- writel(enable ? 0x41 : 0x00, p + 0x4c);
+ if (board->vendor == PCI_VENDOR_ID_PANACOM) {
+ scratch = readl(p + 0x4c);
+ if (enable)
+ scratch |= 0x40;
+ else
+ scratch &= ~0x40;
+ writel(scratch, p + 0x4c);
+ } else
+ writel(enable ? 0x41 : 0x00, p + 0x4c);
iounmap(p);

if (!enable)
pci_write_config_byte(dev, PCI_COMMAND,
data & ~PCI_COMMAND_MEMORY);
+ return 0;
+}
+
+/*
+ * SIIG serial cards have an PCI interface chip which also controls
+ * the UART clocking frequency. Each UART can be clocked independently
+ * (except cards equiped with 4 UARTs) and initial clocking settings
+ * are stored in the EEPROM chip. It can cause problems because this
+ * version of serial driver doesn't support differently clocked UART's
+ * on single PCI card. To prevent this, initialization functions set
+ * high frequency clocking for all UART's on given card. It is safe (I
+ * hope) because it doesn't touch EEPROM settings to prevent conflicts
+ * with other OSes (like M$ DOS).
+ *
+ * SIIG support added by Andrey Panin <pazke@mail.tp.ru>, 10/1999
+ *
+ * There is two family of SIIG serial cards with different PCI
+ * interface chip and different configuration methods:
+ * - 10x cards have control registers in IO and/or memory space;
+ * - 20x cards have control registers in standard PCI configuration space.
+ */
+
+#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)
+
+static int __init pci_siig10x_fn(struct pci_dev *dev,
+ struct pci_board *board,
+ int enable)
+{
+ u16 data, *p;
+
+ if (!enable) return 0;
+
+ p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80);
+
+ switch (dev->device & 0xfff8) {
+ case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
+ data = 0xffdf;
+ break;
+ case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
+ data = 0xf7ff;
+ break;
+ default: /* 1S1P, 4S */
+ data = 0xfffb;
+ break;
+ }
+
+ writew(readw(p + 0x28) & data, p + 0x28);
+ iounmap(p);
+ return 0;
+}
+
+#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
+#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)
+
+static int __init pci_siig20x_fn(struct pci_dev *dev,
+ struct pci_board *board,
+ int enable)
+{
+ u8 data;
+
+ if (!enable) return 0;
+
+ /* Change clock frequency for the first UART. */
+ pci_read_config_byte(dev, 0x6f, &data);
+ pci_write_config_byte(dev, 0x6f, data & 0xef);
+
+ /* If this card has 2 UART, we have to do the same with second UART. */
+ if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) ||
+ ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) {
+ pci_read_config_byte(dev, 0x73, &data);
+ pci_write_config_byte(dev, 0x73, data & 0xef);
+ }
+ return 0;
}

/*
@@ -3592,9 +3659,9 @@
/*
* Vendor ID, Device ID,
* Subvendor ID, Subdevice ID,
- * Number of Ports, Base (Maximum) Baud Rate,
- * Offset of register holding Uart register offset
- * Mask to apply to above register's value
+ * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
+ * Offset to get to next UART's registers
+ * Register shift to use for memory-mapped I/O
*/
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
PCI_SUBVENDOR_ID_CONNECT_TECH,
@@ -3677,7 +3744,7 @@
SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
PCI_ANY_ID, PCI_ANY_ID,
- SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 8, 115200 },
+ SPCI_FL_BASE2, 8, 115200 },
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
PCI_ANY_ID, PCI_ANY_ID,
SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 },
@@ -3691,12 +3758,226 @@
0x400, 7, pci_plx9050_fn },
{ PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
PCI_ANY_ID, PCI_ANY_ID,
- SPCI_FL_BASE2 | SPCI_FL_IOMEM, 4, 921600,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,
0x400, 7, pci_plx9050_fn },
{ PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
PCI_ANY_ID, PCI_ANY_ID,
- SPCI_FL_BASE2 | SPCI_FL_IOMEM, 2, 921600,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
0x400, 7, pci_plx9050_fn },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST4,
+ SPCI_FL_BASE2, 4, 460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST8,
+ SPCI_FL_BASE2, 8, 460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16,
+ SPCI_FL_BASE2, 16, 460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIFAST,
+ PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC,
+ SPCI_FL_BASE2, 16, 460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+ PCI_SUBDEVICE_ID_CHASE_PCIRAS4,
+ SPCI_FL_BASE2, 4, 460800 },
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+ PCI_SUBVENDOR_ID_CHASE_PCIRAS,
+ PCI_SUBDEVICE_ID_CHASE_PCIRAS8,
+ SPCI_FL_BASE2, 8, 460800 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 4, 115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 2, 115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 8, 115200 },
+ { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 8, 115200 },
+ { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
+ SPCI_FL_BASE0 , 4, 115200 },
+ { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954,
+ PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4,
+ SPCI_FL_BASE0 , 4, 921600 },
+ { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 , 2, 921600 },
+ { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_SERIAL,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 460800,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 460800,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 460800,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2, 1, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig10x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0, 1, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig20x_fn },
+ { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600,
+ 0, 0, pci_siig20x_fn },
+ /* Computone devices submitted by Doug McNash dmcnash@computone.com */
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
+ SPCI_FL_IOMEM | SPCI_FL_BASE0, 4, 921600,
+ 0x40, 2, NULL, 0x200 },
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8,
+ SPCI_FL_IOMEM | SPCI_FL_BASE0, 8, 921600,
+ 0x40, 2, NULL, 0x200 },
+ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
+ PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6,
+ SPCI_FL_IOMEM | SPCI_FL_BASE0, 6, 921600,
+ 0x40, 2, NULL, 0x200 },
+ /*
+ * Untested PCI modems, sent in from various folks...
+ */
+ /* at+t zoom 56K faxmodem, from dougd@shieldsbag.com */
+ { PCI_VENDOR_ID_ATT, 0x442,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 1, 115200 },
+ /* at&t unknown modem, from jimd@esoft.com */
+ { PCI_VENDOR_ID_ATT, 0x480,
+ PCI_ANY_ID, PCI_ANY_ID,
+ SPCI_FL_BASE1, 1, 115200 },
+ /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
+ { PCI_VENDOR_ID_ROCKWELL, 0x1004,
+ 0x1048, 0x1500,
+ SPCI_FL_BASE1, 1, 115200 },
+ /* 3Com US Robotics 56k* Voice Internal PCI, model# 2884 */
+ /* from evidal@iti.upv.es */
+ /* XXX complete guess this may not work!!! */
+ { PCI_VENDOR_ID_USR, 0x1006,
+ 0x12b9, 0x0060,
+ SPCI_FL_BASE1 | SPCI_FL_IOMEM, 1, 115200 },
{ 0, }
};

@@ -3767,18 +4048,22 @@
* Run the initialization function, if any
*/
if (board->init_fn)
- (board->init_fn)(dev, board, 1);
+ if ((board->init_fn)(dev, board, 1) != 0)
+ continue;

/*
* Register the serial board in the array so we can
* shutdown the board later, if necessary.
*/
+ if (serial_pci_board_idx >= NR_PCI_BOARDS)
+ continue;
serial_pci_board[serial_pci_board_idx].board = board;
serial_pci_board[serial_pci_board_idx].dev = dev;
serial_pci_board_idx++;

base_idx = board->flags & SPCI_FL_BASE_MASK;
- port = PCI_BASE_ADDRESS(dev, base_idx);
+ port = PCI_BASE_ADDRESS(dev, base_idx) +
+ board->first_uart_offset;
if (board->flags & SPCI_FL_IOMEM)
port &= PCI_BASE_ADDRESS_MEM_MASK;
else
@@ -3829,6 +4114,7 @@
fake_state.port = port;
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
if (board->flags & SPCI_FL_IOMEM) {
+ fake_state.io_type = SERIAL_IO_MEM;
fake_state.iomem_base =
ioremap(port, board->uart_offset);
fake_state.iomem_reg_shift = board->reg_shift;
@@ -3869,6 +4155,16 @@
dualsp_serial_init ();
#endif

+ if (timer_table[RS_TIMER].fn) {
+ printk("RS_TIMER already set, another serial driver "
+ "already loaded?\n");
+#ifdef MODULE
+ printk("Can't load serial driver module over built-in "
+ "serial driver\n");
+#endif
+ return -EBUSY;
+ }
+
init_bh(SERIAL_BH, do_serial_bh);
timer_table[RS_TIMER].fn = rs_timer;
timer_table[RS_TIMER].expires = 0;
@@ -3974,6 +4270,8 @@
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
state->irq = irq_cannonicalize(state->irq);
+ if (state->hub6)
+ state->io_type = SERIAL_IO_HUB6;
if (state->port && check_region(state->port,8))
continue;
if (state->flags & ASYNC_BOOT_AUTOCONF)
@@ -4035,10 +4333,13 @@
state->irq = req->irq;
state->port = req->port;
state->flags = req->flags;
+ state->io_type = req->io_type;
#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
state->iomem_base = req->iomem_base;
state->iomem_reg_shift = req->iomem_reg_shift;
#endif
+ if (req->baud_base)
+ state->baud_base = req->baud_base;

autoconfig(state);
if (state->type == PORT_UNKNOWN) {
@@ -4103,13 +4404,12 @@
restore_flags(flags);

for (i = 0; i < NR_PORTS; i++) {
+ if ((info = rs_table[i].info)) {
+ rs_table[i].info = NULL;
+ kfree_s(info, sizeof(struct async_struct));
+ }
if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port)
release_region(rs_table[i].port, 8);
- info = rs_table[i].info;
- if (info) {
- rs_table[i].info = NULL;
- kfree_s(info, sizeof(struct async_struct));
- }
#if defined(ENABLE_SERIAL_PCI) && defined (CONFIG_SERIAL_PCI_MEMMAPPED)
if (rs_table[i].iomem_base)
iounmap(rs_table[i].iomem_base);
@@ -4140,20 +4440,20 @@

#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)

+static struct async_struct async_sercons;
+
/*
* Wait for transmitter & holding register to empty
*/
-static inline void wait_for_xmitr(struct serial_state *ser)
+static inline void wait_for_xmitr(struct async_struct *info)
{
- int lsr;
unsigned int tmout = 1000000;

- do {
- lsr = inb(ser->port + UART_LSR);
- if (--tmout == 0) break;
- } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
+ while (--tmout &&
+ ((serial_in(info, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY));
}

+
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
@@ -4161,31 +4461,30 @@
static void serial_console_write(struct console *co, const char *s,
unsigned count)
{
- struct serial_state *ser;
+ static struct async_struct *info = &async_sercons;
int ier;
unsigned i;

- ser = rs_table + co->index;
/*
* First save the IER then disable the interrupts
*/
- ier = inb(ser->port + UART_IER);
- outb(0x00, ser->port + UART_IER);
+ ier = serial_in(info, UART_IER);
+ serial_out(info, UART_IER, 0x00);

/*
* Now, do each character
*/
for (i = 0; i < count; i++, s++) {
- wait_for_xmitr(ser);
+ wait_for_xmitr(info);

/*
* Send the character out.
* If a LF, also do CR...
*/
- outb(*s, ser->port + UART_TX);
+ serial_out(info, UART_TX, *s);
if (*s == 10) {
- wait_for_xmitr(ser);
- outb(13, ser->port + UART_TX);
+ wait_for_xmitr(info);
+ serial_out(info, UART_TX, 13);
}
}

@@ -4193,8 +4492,8 @@
* Finally, Wait for transmitter & holding register to empty
* and restore the IER
*/
- wait_for_xmitr(ser);
- outb(ier, ser->port + UART_IER);
+ wait_for_xmitr(info);
+ serial_out(info, UART_IER, ier);
}

/*
@@ -4202,30 +4501,26 @@
*/
static int serial_console_wait_key(struct console *co)
{
- struct serial_state *ser;
- int ier;
- int lsr;
- int c;
+ static struct async_struct *info;
+ int ier, c;

- ser = rs_table + co->index;
+ info = &async_sercons;

/*
* First save the IER then disable the interrupts so
* that the real driver for the port does not get the
* character.
*/
- ier = inb(ser->port + UART_IER);
- outb(0x00, ser->port + UART_IER);
-
- do {
- lsr = inb(ser->port + UART_LSR);
- } while (!(lsr & UART_LSR_DR));
- c = inb(ser->port + UART_RX);
+ ier = serial_in(info, UART_IER);
+ serial_out(info, UART_IER, 0x00);
+
+ while ((serial_in(info, UART_LSR) & UART_LSR_DR) == 0);
+ c = serial_in(info, UART_RX);

/*
* Restore the interrupts
*/
- outb(ier, ser->port + UART_IER);
+ serial_out(info, UART_IER, ier);

return c;
}
@@ -4243,7 +4538,8 @@
*/
static int __init serial_console_setup(struct console *co, char *options)
{
- struct serial_state *ser;
+ static struct async_struct *info;
+ struct serial_state *state;
unsigned cval;
int baud = 9600;
int bits = 8;
@@ -4251,6 +4547,9 @@
int cflag = CREAD | HUPCL | CLOCAL;
int quot = 0;
char *s;
+#if defined(CONFIG_KDB)
+ extern int kdb_port;
+#endif

if (options) {
baud = simple_strtoul(options, NULL, 10);
@@ -4313,8 +4612,21 @@
/*
* Divisor, bytesize and parity
*/
- ser = rs_table + co->index;
- quot = ser->baud_base / baud;
+ state = rs_table + co->index;
+ info = &async_sercons;
+ info->magic = SERIAL_MAGIC;
+ info->state = state;
+ info->port = state->port;
+ info->flags = state->flags;
+#ifdef CONFIG_HUB6
+ info->hub6 = state->hub6;
+#endif
+ info->io_type = state->io_type;
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+ info->iomem_base = state->iomem_base;
+ info->iomem_reg_shift = state->iomem_reg_shift;
+#endif
+ quot = state->baud_base / baud;
cval = cflag & (CSIZE | CSTOPB);
#if defined(__powerpc__) || defined(__alpha__)
cval >>= 8;
@@ -4330,18 +4642,27 @@
* Disable UART interrupts, set DTR and RTS high
* and set speed.
*/
- 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);
+ serial_out(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */
+ serial_out(info, UART_DLL, quot & 0xff); /* LS of divisor */
+ serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */
+ serial_out(info, UART_LCR, cval); /* reset DLAB */
+ serial_out(info, UART_IER, 0);
+ serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);

/*
* If we read 0xff from the LSR, there is no UART here.
*/
- if (inb(ser->port + UART_LSR) == 0xff)
+ if (serial_in(info, UART_LSR) == 0xff)
return -1;
+
+#if defined(CONFIG_KDB)
+ /*
+ * Remember I/O port for kdb
+ */
+ if (kdb_port == 0 )
+ kdb_port = ser->port;
+#endif /* CONFIG_KDB */
+
return 0;
}

===================================================================
RCS file: include/linux/RCS/serial.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/serial.h
--- include/linux/serial.h 1999/11/17 03:03:11 1.1
+++ include/linux/serial.h 1999/11/17 20:03:06
@@ -20,7 +20,8 @@
int custom_divisor;
int baud_base;
unsigned short close_delay;
- char reserved_char[2];
+ char io_type;
+ char reserved_char[1];
int hub6;
unsigned short closing_wait; /* time to wait before closing */
unsigned short closing_wait2; /* no longer used... */
@@ -37,20 +38,6 @@
#define ASYNC_CLOSING_WAIT_NONE 65535

/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
-
-/*
- * Counters of the input lines (CTS, DSR, RI, CD) interrupts
- */
-struct async_icount {
- __u32 cts, dsr, rng, dcd, tx, rx;
- __u32 frame, parity, overrun, brk;
- __u32 buf_overrun;
-};
-
-/*
* These are the supported serial types.
*/
#define PORT_UNKNOWN 0
@@ -67,6 +54,11 @@
#define PORT_16654 11
#define PORT_16850 12
#define PORT_MAX 12
+
+#define SERIAL_IO_PORT 0
+#define SERIAL_IO_HUB6 1
+#define SERIAL_IO_MEM 2
+#define SERIAL_IO_GSC 3

struct serial_uart_config {
char *name;
===================================================================
RCS file: include/linux/RCS/serialP.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/serialP.h
--- include/linux/serialP.h 1999/11/17 03:03:11 1.1
+++ include/linux/serialP.h 1999/11/17 20:03:06
@@ -19,11 +19,18 @@
* For definitions of the flags field, see tty.h
*/

-#include <linux/config.h>
#include <linux/termios.h>
#include <linux/tqueue.h>
#include <linux/wait.h>

+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
+};

struct serial_state {
int magic;
@@ -45,6 +52,7 @@
struct async_icount icount;
struct termios normal_termios;
struct termios callout_termios;
+ int io_type;
struct async_struct *info;
};

@@ -80,6 +88,7 @@
int xmit_cnt;
u8 *iomem_base;
u16 iomem_reg_shift;
+ int io_type;
struct tq_struct tqueue;
#ifdef DECLARE_WAITQUEUE
wait_queue_head_t open_wait;
@@ -99,6 +108,10 @@
#define SERIAL_MAGIC 0x5301
#define SSTATE_MAGIC 0x5302

+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096

/*
* Events are used to schedule things to happen at timer-interrupt
@@ -132,7 +145,6 @@
#define ALPHA_KLUDGE_MCR 0
#endif

-#ifdef CONFIG_PCI
/*
* Structures and definitions for PCI support
*/
@@ -147,8 +159,9 @@
int base_baud;
int uart_offset;
int reg_shift;
- void (*init_fn)(struct pci_dev *dev, struct pci_board *board,
+ int (*init_fn)(struct pci_dev *dev, struct pci_board *board,
int enable);
+ int first_uart_offset;
};

struct pci_board_inst {
@@ -158,7 +171,6 @@

#ifndef PCI_ANY_ID
#define PCI_ANY_ID (~0)
-#endif
#endif

#define SPCI_FL_BASE_MASK 0x0007
===================================================================
RCS file: include/linux/RCS/serial_reg.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/serial_reg.h
===================================================================
RCS file: include/linux/RCS/pci_ids.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/pci_ids.h
--- include/linux/pci_ids.h 1999/11/17 03:03:11 1.1
+++ include/linux/pci_ids.h 1999/11/17 03:11:48
@@ -434,6 +434,10 @@
#define PCI_VENDOR_ID_LEADTEK 0x107d
#define PCI_DEVICE_ID_LEADTEK_805 0x0000

+#define PCI_VENDOR_ID_INTERPHASE 0x107e
+#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
+#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005
+
#define PCI_VENDOR_ID_CONTAQ 0x1080
#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600
#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693
@@ -783,6 +787,7 @@
#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000
#define PCI_DEVICE_ID_SPECIALIX_XIO 0x4000
#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000
+#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004

#define PCI_VENDOR_ID_AURAVISION 0x11d1
#define PCI_DEVICE_ID_AURAVISION_VXP524 0x01f7
@@ -874,9 +879,13 @@
#define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI 0x5000
#define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371

+#define PCI_VENDOR_ID_ROCKWELL 0x127A
+
#define PCI_VENDOR_ID_ALTEON 0x12ae
#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001

+#define PCI_VENDOR_ID_USR 0x12B9
+
#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232 0x0001
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232 0x0002
@@ -893,30 +902,65 @@
#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018

+#define PCI_SUBVENDOR_ID_CHASE_PCIFAST 0x12E0
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4 0x0031
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8 0x0021
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16 0x0011
+#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC 0x0041
+#define PCI_SUBVENDOR_ID_CHASE_PCIRAS 0x124D
+#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4 0xF001
+#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8 0xF010
+
#define PCI_VENDOR_ID_CBOARDS 0x1307
#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001

#define PCI_VENDOR_ID_SIIG 0x131f
+#define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000
+#define PCI_DEVICE_ID_SIIG_1S_10x_650 0x1001
+#define PCI_DEVICE_ID_SIIG_1S_10x_850 0x1002
#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010
#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011
#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012
#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020
#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021
+#define PCI_DEVICE_ID_SIIG_2S_10x_550 0x1030
+#define PCI_DEVICE_ID_SIIG_2S_10x_650 0x1031
+#define PCI_DEVICE_ID_SIIG_2S_10x_850 0x1032
#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034
#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035
#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036
+#define PCI_DEVICE_ID_SIIG_4S_10x_550 0x1050
+#define PCI_DEVICE_ID_SIIG_4S_10x_650 0x1051
+#define PCI_DEVICE_ID_SIIG_4S_10x_850 0x1052
+#define PCI_DEVICE_ID_SIIG_1S_20x_550 0x2000
+#define PCI_DEVICE_ID_SIIG_1S_20x_650 0x2001
+#define PCI_DEVICE_ID_SIIG_1S_20x_850 0x2002
#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020
#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021
+#define PCI_DEVICE_ID_SIIG_2S_20x_550 0x2030
+#define PCI_DEVICE_ID_SIIG_2S_20x_650 0x2031
+#define PCI_DEVICE_ID_SIIG_2S_20x_850 0x2032
#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040
#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041
#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042
#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010
#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011
#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012
+#define PCI_DEVICE_ID_SIIG_4S_20x_550 0x2050
+#define PCI_DEVICE_ID_SIIG_4S_20x_650 0x2051
+#define PCI_DEVICE_ID_SIIG_4S_20x_850 0x2052
#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060
#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062

+#define PCI_VENDOR_ID_QUATECH 0x135C
+#define PCI_DEVICE_ID_QUATECH_QSC100 0x0010
+#define PCI_DEVICE_ID_QUATECH_DSC100 0x0020
+#define PCI_DEVICE_ID_QUATECH_DSC200 0x0030
+#define PCI_DEVICE_ID_QUATECH_QSC200 0x0040
+#define PCI_DEVICE_ID_QUATECH_ESC100D 0x0050
+#define PCI_DEVICE_ID_QUATECH_ESC100M 0x0060
+
#define PCI_VENDOR_ID_SEALEVEL 0x135e
#define PCI_DEVICE_ID_SEALEVEL_U530 0x7101
#define PCI_DEVICE_ID_SEALEVEL_UCOMM2 0x7201
@@ -929,11 +973,18 @@
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a

#define PCI_VENDOR_ID_LAVA 0x1407
+#define PCI_DEVICE_ID_LAVA_DUAL_SERIAL 0x0100
#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8003 /* two PCI devices on a card */
#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR 0x8800

+#define PCI_VENDOR_ID_TIMEDIA 0x1409
+#define PCI_DEVICE_ID_TIMEDIA_1889 0x7168
+
+#define PCI_VENDOR_ID_OXSEMI 0x1415
+#define PCI_DEVICE_ID_OXSEMI_16PCI954 0x9501
+
#define PCI_VENDOR_ID_PANACOM 0x14d4
#define PCI_DEVICE_ID_PANACOM_QUADMODEM 0x0400
#define PCI_DEVICE_ID_PANACOM_DUALMODEM 0x0402
@@ -1022,8 +1073,6 @@
#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
-#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
-#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291

#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180
#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181
@@ -1034,6 +1083,14 @@
#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca

+#define PCI_VENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_DEVICE_ID_COMPUTONE_IP2EX 0x0291
+#define PCI_DEVICE_ID_COMPUTONE_PG 0x0302
+#define PCI_SUBVENDOR_ID_COMPUTONE 0x8e0e
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG4 0x0001
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG8 0x0002
+#define PCI_SUBDEVICE_ID_COMPUTONE_PG6 0x0003
+
#define PCI_VENDOR_ID_KTI 0x8e2e
#define PCI_DEVICE_ID_KTI_ET32P2 0x3000

@@ -1099,15 +1156,4 @@
#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
#define PCI_DEVICE_ID_ARK_2000MT 0xa0a1

-#define PCI_VENDOR_ID_INTERPHASE 0x107e
-#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
-#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005
-
-#define PCI_VENDOR_ID_INTERPHASE 0x107e
-#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
-#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005
-
-#define PCI_VENDOR_ID_INTERPHASE 0x107e
-#define PCI_DEVICE_ID_INTERPHASE_5526 0x0004
-#define PCI_DEVICE_ID_INTERPHASE_55x6 0x0005

===================================================================
RCS file: drivers/acorn/char/RCS/serial-card.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/acorn/char/serial-card.c
--- drivers/acorn/char/serial-card.c 1999/11/17 03:03:11 1.1
+++ drivers/acorn/char/serial-card.c 1999/11/17 03:11:48
@@ -55,6 +55,8 @@
{
struct serial_struct req;

+ memset(&req, 0, sizeof(serial_struct));
+
req.baud_base = MY_BAUD_BASE;
req.irq = irq;
req.port = port;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/