Messages in this thread Patch in this message | | | Date | Wed, 17 Nov 1999 15:19:03 -0500 | Subject | Update to 2.3.28's serial driver | From | tytso@mit ... |
| |
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/
| |