=================================================================== RCS file: drivers/char/RCS/ChangeLog,v retrieving revision 1.1 diff -u -r1.1 drivers/char/ChangeLog --- 1.1 1995/02/11 05:37:49 +++ drivers/char/ChangeLog 1995/02/13 05:00:01 @@ -1,3 +1,53 @@ +Sun Feb 12 23:57:48 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl, + set_multiport_struct, get_multiport_struct): Add + provisions for a new type of interrutp service routine, + which better supports multiple serial ports on a single + IRQ. + +Sun Feb 5 19:35:11 1995 Theodore Y. Ts'o (tytso@rt-11) + + * tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent): + * serial.c (rs_ioctl, rs_close): + * cyclades.c (cy_ioctl, cy_close): + * n_tty.c (n_tty_close): Rename wait_until_sent to + tty_wait_until_sent, so that it's a better name to export + in ksyms.c. + +Sat Feb 4 23:36:20 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_close): Added missing check for closing_wait2 being + ASYNC_CLOSING_WAIT_NONE. + +Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (rs_init, set_serial_info, get_serial_info, rs_close): + Support close_wait and close_wait2 in the serial driver. + This is helpful for slow devices (like serial plotters) so + that their outputs don't get flushed upon device close. + This has to be configurable because normally we don't want + ports to be hung up for long periods of time during a + close when they are not connected to a device, or the + device is powered off. + + The default is to wait 30 seconds after shutting down the + receiver (to prevent echo wars). This is done by setting + close_wait=ASYNC_CLOSE_WAIT_NONE, close_wait2 = 3000. If + XON/XOFF handshaking is used, then the 30 second timeout + should happen before the receiver is shutdown; this is + done by reversing the values of close_wait and + close_wait2. In the case of a very slow device, the + timeouts for close_wait or close_wait2 should be lengthed. + If either value is set to 0, the kernel will wait forever + for all of the data to be transmitted. + +Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11) + + * serial.c (startup, change_speed, rs_init): Add support to detect + the StarTech 16650 chip. Treat it as a 16450 for now, + because of its FIFO bugs. + Thu Jan 5 21:21:57 1995 * serial.c: (receive_char): Added counter to prevent infinite loop =================================================================== RCS file: drivers/char/RCS/serial.c,v retrieving revision 1.1 diff -u -r1.1 drivers/char/serial.c --- 1.1 1995/02/11 05:37:52 +++ drivers/char/serial.c 1995/02/13 17:16:13 @@ -67,12 +67,13 @@ #define SERIAL_PARANOIA_CHECK #define CONFIG_SERIAL_NOPAUSE_IO #define SERIAL_DO_RESTART -#define CONFIG_SERIAL_NEW_ISR #undef SERIAL_DEBUG_INTR #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_FLOW +#define RS_STROBE_TIME 10 + #define _INLINE_ inline /* @@ -81,6 +82,7 @@ */ static struct async_struct *IRQ_ports[16]; +static struct rs_multiport_struct rs_multiport[16]; static int IRQ_timeout[16]; static volatile int rs_irq_triggered; static volatile int rs_triggered; @@ -420,9 +422,7 @@ if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) { info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif return; } @@ -445,9 +445,7 @@ if (info->xmit_cnt <= 0) { info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif } } @@ -480,9 +478,7 @@ #endif info->tty->hw_stopped = 0; info->IER |= UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); return; } @@ -493,15 +489,12 @@ #endif info->tty->hw_stopped = 1; info->IER &= ~UART_IER_THRI; -#ifdef CONFIG_SERIAL_NEW_ISR serial_out(info, UART_IER, info->IER); -#endif } } } } -#ifdef CONFIG_SERIAL_NEW_ISR /* * This is the serial driver's generic interrupt routine */ @@ -511,6 +504,8 @@ struct async_struct * info; int pass_counter = 0; struct async_struct *end_mark = 0; + int first_multi = 0; + struct rs_multiport_struct *multi; #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt(%d)...", irq); @@ -520,6 +515,10 @@ if (!info) return; + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); + do { if (!info->tty || (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) { @@ -554,6 +553,9 @@ continue; } } while (end_mark != info); + if (multi->port_monitor) + printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, inb(multi->port_monitor)); #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif @@ -566,7 +568,9 @@ { int status; int pass_counter = 0; + int first_multi = 0; struct async_struct * info; + struct rs_multiport_struct *multi; #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt_single(%d)...", irq); @@ -576,6 +580,10 @@ if (!info || !info->tty) return; + multi = &rs_multiport[irq]; + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); + do { status = serial_inp(info, UART_LSR) & info->read_status_mask; #ifdef SERIAL_DEBUG_INTR @@ -594,102 +602,95 @@ } } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); info->last_active = jiffies; + if (multi->port_monitor) + printk("rs port monitor (single) irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, inb(multi->port_monitor)); #ifdef SERIAL_DEBUG_INTR printk("end.\n"); #endif } -#else /* CONFIG_SERIAL_NEW_ISR */ - /* - * This is the serial driver's generic interrupt routine + * This is the serial driver's for multiport boards */ -static void rs_interrupt(int irq, struct pt_regs * regs) +static void rs_interrupt_multi(int irq, struct pt_regs * regs) { int status; struct async_struct * info; - int done = 1, pass_counter = 0; + int pass_counter = 0; + int first_multi= 0; + struct rs_multiport_struct *multi; - #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt(%d)...", irq); + printk("rs_interrupt_multi(%d)...", irq); #endif info = IRQ_ports[irq]; if (!info) return; + multi = &rs_multiport[irq]; + if (!multi->port1) { + /* Should never happen */ + printk("rs_interrupt_multi: NULL port1!\n"); + return; + } + if (multi->port_monitor) + first_multi = inb(multi->port_monitor); while (1) { - if (!info->tty) + if (!info->tty || + (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) goto next; - serial_outp(info, UART_IER, 0); + info->last_active = jiffies; + status = serial_inp(info, UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) { +#ifdef SERIAL_DEBUG_INTR + printk("status = %x...", status); +#endif + if (status & UART_LSR_DR) receive_chars(info, &status); - done = 0; - } check_modem_status(info); if (status & UART_LSR_THRE) - transmit_chars(info, &done); + transmit_chars(info, 0); next: - info = info->next_port; - if (!info) { - info = IRQ_ports[irq]; - if (done) - break; - done = 1; - if (pass_counter++ > 64) { -#if 0 - printk("rs loop break\n"); + info = info->next_port; + if (info) + continue; + + info = IRQ_ports[irq]; + if (pass_counter++ > 64) { +#if 1 + printk("rs_multi loop break\n"); #endif - break; /* Prevent infinite loops */ - } + break; /* Prevent infinite loops */ } - } - - /* - * Reset the IER registers; info is already set up from the - * above while loop. - */ - do - serial_outp(info, UART_IER, info->IER); - while ((info = info->next_port) != NULL); -} - -/* - * This is the serial driver's interrupt routine for a single port - */ -static void rs_interrupt_single(int irq, struct pt_regs * regs) -{ - int status; - struct async_struct * info; - - + if (multi->port_monitor) + printk("rs port monitor irq %d: 0x%x, 0x%x\n", + info->irq, first_multi, + inb(multi->port_monitor)); + if ((inb(multi->port1) & multi->mask1) != multi->match1) + continue; + if (!multi->port2) + break; + if ((inb(multi->port2) & multi->mask2) != multi->match2) + continue; + if (!multi->port3) + break; + if ((inb(multi->port3) & multi->mask3) != multi->match3) + continue; + if (!multi->port4) + break; + if ((inb(multi->port4) & multi->mask4) == multi->match4) + continue; + break; + } #ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); + printk("end.\n"); #endif - - info = IRQ_ports[irq]; - if (!info || !info->tty) - return; - - serial_outp(info, UART_IER, 0); - status = serial_inp(info, UART_LSR) & info->read_status_mask; - if (status & UART_LSR_DR) - receive_chars(info, &status); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - - /* - * Reset the IER register - */ - serial_outp(info, UART_IER, info->IER); } -#endif /* CONFIG_SERIAL_NEW_ISR */ /* * ------------------------------------------------------------------- @@ -747,7 +748,7 @@ struct async_struct *info; unsigned int i; - if ((jiffies - last_strobe) >= 60*HZ) { + if ((jiffies - last_strobe) >= RS_STROBE_TIME*HZ) { for (i=1; i < 16; i++) { info = IRQ_ports[i]; if (!info) @@ -760,14 +761,17 @@ serial_out(info, UART_IER, info->IER); info = info->next_port; } while (info); - rs_interrupt(i, NULL); + if (rs_multiport[i].port1) + rs_interrupt_multi(i, NULL); + else + rs_interrupt(i, NULL); } else rs_interrupt_single(i, NULL); sti(); } } last_strobe = jiffies; - timer_table[RS_TIMER].expires = jiffies + 60 * HZ; + timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME * HZ; timer_active |= 1 << RS_TIMER; if (IRQ_ports[0]) { @@ -877,7 +881,11 @@ * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) */ - if (info->type == PORT_16550A) { + if (info->type == PORT_16650) { + serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + info->xmit_fifo_size = 1; /* disabled for now */ + } else if (info->type == PORT_16550A) { serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); info->xmit_fifo_size = 16; @@ -906,7 +914,10 @@ !IRQ_ports[info->irq]->next_port)) { if (IRQ_ports[info->irq]) { free_irq(info->irq); - handler = rs_interrupt; + if (rs_multiport[info->irq].port1) + handler = rs_interrupt_multi; + else + handler = rs_interrupt; } else handler = rs_interrupt_single; @@ -1148,6 +1159,18 @@ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; else fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } else if (info->type == PORT_16650) { + /* + * On the 16650, we disable the FIFOs altogether + * because of a design bug in how the implement + * things. We could support it by completely changing + * how we handle the interrupt driver, but not today.... + * + * N.B. Because there's no way to set a FIFO trigger + * at 1 char, we'd probably disable at speed below + * 2400 baud anyway... + */ + fcr = 0; } else fcr = 0; @@ -1404,6 +1427,8 @@ tmp.flags = info->flags; tmp.baud_base = info->baud_base; tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.closing_wait2 = info->closing_wait2; tmp.custom_divisor = info->custom_divisor; tmp.hub6 = info->hub6; memcpy_tofs(retinfo,&tmp,sizeof(*retinfo)); @@ -1471,6 +1496,8 @@ info->custom_divisor = new_serial.custom_divisor; info->type = new_serial.type; info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + info->closing_wait2 = new_serial.closing_wait2; release_region(info->port,8); if (change_port || change_irq) { @@ -1676,6 +1703,101 @@ return wild_interrupts; } +static int get_multiport_struct(struct async_struct * info, + struct serial_multiport_struct *retinfo) +{ + struct serial_multiport_struct ret; + struct rs_multiport_struct *multi; + + multi = &rs_multiport[info->irq]; + + ret.port_monitor = multi->port_monitor; + + ret.port1 = multi->port1; + ret.mask1 = multi->mask1; + ret.match1 = multi->match1; + + ret.port2 = multi->port2; + ret.mask2 = multi->mask2; + ret.match2 = multi->match2; + + ret.port3 = multi->port3; + ret.mask3 = multi->mask3; + ret.match3 = multi->match3; + + ret.port4 = multi->port4; + ret.mask4 = multi->mask4; + ret.match4 = multi->match4; + + ret.irq = info->irq; + + memcpy_tofs(retinfo,&ret,sizeof(*retinfo)); + return 0; + +} + +static int set_multiport_struct(struct async_struct * info, + struct serial_multiport_struct *in_multi) +{ + struct serial_multiport_struct new_multi; + struct rs_multiport_struct *multi; + int was_multi, now_multi; + int retval; + void (*handler)(int, struct pt_regs *); + + if (!suser()) + return -EPERM; + if (!in_multi) + return -EFAULT; + memcpy_fromfs(&new_multi, in_multi, + sizeof(struct serial_multiport_struct)); + + if (new_multi.irq != info->irq || info->irq == 0 || + !IRQ_ports[info->irq]) + return -EINVAL; + + multi = &rs_multiport[info->irq]; + was_multi = (multi->port1 != 0); + + multi->port_monitor = new_multi.port_monitor; + + multi->port1 = new_multi.port1; + multi->mask1 = new_multi.mask1; + multi->match1 = new_multi.match1; + + multi->port2 = new_multi.port2; + multi->mask2 = new_multi.mask2; + multi->match2 = new_multi.match2; + + multi->port3 = new_multi.port3; + multi->mask3 = new_multi.mask3; + multi->match3 = new_multi.match3; + + multi->port4 = new_multi.port4; + multi->mask4 = new_multi.mask4; + multi->match4 = new_multi.match4; + + now_multi = (multi->port1 != 0); + + if (IRQ_ports[info->irq]->next_port && + (was_multi != now_multi)) { + free_irq(info->irq); + if (now_multi) + handler = rs_interrupt_multi; + else + handler = rs_interrupt; + + retval = request_irq(info->irq, handler, SA_INTERRUPT, + "serial"); + if (retval) { + printk("Couldn't reallocate serial interrupt " + "driver!!\n"); + } + } + + return 0; +} + static int rs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { @@ -1778,6 +1900,16 @@ info, sizeof(struct async_struct)); return 0; + case TIOCSERGETMULTI: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_multiport_struct)); + if (error) + return error; + return get_multiport_struct(info, + (struct serial_multiport_struct *) arg); + case TIOCSERSETMULTI: + return set_multiport_struct(info, + (struct serial_multiport_struct *) arg); default: return -ENOIOCTLCMD; } @@ -1871,6 +2003,8 @@ info->normal_termios = *tty->termios; if (info->flags & ASYNC_CALLOUT_ACTIVE) info->callout_termios = *tty->termios; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the @@ -1881,7 +2015,8 @@ info->read_status_mask &= ~UART_LSR_DR; if (info->flags & ASYNC_INITIALIZED) { serial_out(info, UART_IER, info->IER); - tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ + if (info->closing_wait2 != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait2); /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -2155,7 +2290,7 @@ */ static void show_serial_version(void) { - printk("Serial driver version 4.00 with"); + printk("Serial driver version 4.10 with"); #ifdef CONFIG_HUB6 printk(" HUB-6"); #define SERIAL_OPT @@ -2329,6 +2464,10 @@ if (info->flags & ASYNC_AUTO_IRQ) info->irq = do_auto_irq(info); + scratch2 = serial_in(info, UART_LCR); + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + serial_outp(info, UART_EFR, 0); /* EFR is the same as FCR */ + serial_outp(info, UART_LCR, scratch2); serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); scratch = serial_in(info, UART_IIR) >> 6; info->xmit_fifo_size = 1; @@ -2343,8 +2482,15 @@ info->type = PORT_16550; break; case 3: - info->type = PORT_16550A; - info->xmit_fifo_size = 16; + serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB); + if (serial_in(info, UART_EFR) == 0) { + info->type = PORT_16650; + info->xmit_fifo_size = 32; + } else { + info->type = PORT_16550A; + info->xmit_fifo_size = 16; + } + serial_outp(info, UART_LCR, scratch2); break; } if (info->type == PORT_16450) { @@ -2398,6 +2544,7 @@ for (i = 0; i < 16; i++) { IRQ_ports[i] = 0; IRQ_timeout[i] = 0; + memset(&rs_multiport[i], 0, sizeof(struct rs_multiport_struct)); } show_serial_version(); @@ -2458,6 +2605,8 @@ info->type = PORT_UNKNOWN; info->custom_divisor = 0; info->close_delay = 50; + info->closing_wait = ASYNC_CLOSING_WAIT_NONE; + info->closing_wait2 = 3000; info->x_char = 0; info->event = 0; info->count = 0; @@ -2492,6 +2641,9 @@ break; case PORT_16550A: printk(" is a 16550A\n"); + break; + case PORT_16650: + printk(" is a 16650\n"); break; default: printk("\n"); =================================================================== RCS file: include/linux/RCS/termios.h,v retrieving revision 1.1 diff -u -r1.1 include/linux/termios.h --- 1.1 1995/02/12 20:29:45 +++ include/linux/termios.h 1995/02/12 20:31:02 @@ -54,6 +54,8 @@ #define TIOCSLCKTRMIOS 0x5457 #define TIOCSERGSTRUCT 0x5458 /* For debugging only */ #define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ /* Used for packet mode */ #define TIOCPKT_DATA 0 @@ -193,6 +195,7 @@ #define CBAUDEX 0010000 #define B57600 0010001 #define B115200 0010002 +#define B230400 0010003 #define CIBAUD 002003600000 /* input baud rate (not used) */ #define CRTSCTS 020000000000 /* flow control */ =================================================================== RCS file: include/linux/RCS/serial.h,v retrieving revision 1.1 diff -u -r1.1 include/linux/serial.h --- 1.1 1995/02/11 05:37:58 +++ include/linux/serial.h 1995/02/13 13:32:22 @@ -22,10 +22,19 @@ unsigned short close_delay; char reserved_char[2]; int hub6; - int reserved[5]; + unsigned short closing_wait; /* time to wait before rcvr shutdown */ + unsigned short closing_wait2; /* time to wait after rcvr shutdown */ + int reserved[4]; }; /* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define ASYNC_CLOSING_WAIT_INF 0 +#define ASYNC_CLOSING_WAIT_NONE 65535 + +/* * These are the supported serial types. */ #define PORT_UNKNOWN 0 @@ -33,8 +42,9 @@ #define PORT_16450 2 #define PORT_16550 3 #define PORT_16550A 4 -#define PORT_CIRRUS 5 -#define PORT_MAX 5 +#define PORT_CIRRUS 5 /* Hey! Who put this there? */ +#define PORT_16650 6 +#define PORT_MAX 6 /* * Definitions for async_struct (and serial_struct) flags field @@ -70,6 +80,23 @@ #define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ #define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ +/* + * Multiport serial configuration structure --- external structure + */ +struct serial_multiport_struct { + int irq; + int port1; + unsigned char mask1, match1; + int port2; + unsigned char mask2, match2; + int port3; + unsigned char mask3, match3; + int port4; + unsigned char mask4, match4; + int port_monitor; + int reserved[32]; +}; + #ifdef __KERNEL__ /* * This is our internal structure for each serial port's state. @@ -96,6 +123,8 @@ int custom_divisor; int x_char; /* xon/xoff character */ int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; int IER; /* Interrupt Enable Register */ int MCR; /* Modem control register */ int MCR_noint; /* MCR with interrupts off */ @@ -132,6 +161,21 @@ */ #define RS_EVENT_WRITE_WAKEUP 0 #define RS_EVENT_HANGUP 1 + +/* + * Multiport serial configuration structure --- internal structure + */ +struct rs_multiport_struct { + int port1; + unsigned char mask1, match1; + int port2; + unsigned char mask2, match2; + int port3; + unsigned char mask3, match3; + int port4; + unsigned char mask4, match4; + int port_monitor; +}; /* Export to allow PCMCIA to use this - Dave Hinds */ extern int register_serial(struct serial_struct *req); =================================================================== RCS file: include/linux/RCS/serial_reg.h,v retrieving revision 1.1 diff -u -r1.1 include/linux/serial_reg.h --- 1.1 1995/02/11 05:38:03 +++ include/linux/serial_reg.h 1995/02/11 05:38:14 @@ -21,6 +21,8 @@ #define UART_IER 1 /* Out: Interrupt Enable Register */ #define UART_IIR 2 /* In: Interrupt ID Register */ #define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_EFR 2 /* I/O: Extended Features Register */ + /* (DLAB=1, 16C660 only) */ #define UART_LCR 3 /* Out: Line Control Register */ #define UART_MCR 4 /* Out: Modem Control Register */ #define UART_LSR 5 /* In: Line Status Register */ @@ -29,6 +31,7 @@ /* * These are the definitions for the FIFO Control Register + * (16650 only) */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ @@ -39,6 +42,15 @@ #define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ #define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ #define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ +/* 16650 redefinitions */ +#define UART_FCR6_R_TRIGGER_8 0x00 /* Mask for receive trigger set at 1 */ +#define UART_FCR6_R_TRIGGER_16 0x40 /* Mask for receive trigger set at 4 */ +#define UART_FCR6_R_TRIGGER_24 0x80 /* Mask for receive trigger set at 8 */ +#define UART_FCR6_R_TRIGGER_28 0xC0 /* Mask for receive trigger set at 14 */ +#define UART_FCR6_T_TRIGGER_16 0x00 /* Mask for transmit trigger set at 16 */ +#define UART_FCR6_T_TRIGGER_8 0x10 /* Mask for transmit trigger set at 8 */ +#define UART_FCR6_T_TRIGGER_24 0x20 /* Mask for transmit trigger set at 24 */ +#define UART_FCR6_T_TRIGGER_30 0x30 /* Mask for transmit trigger set at 30 */ /* * These are the definitions for the Line Control Register @@ -108,6 +120,18 @@ #define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +/* + * These are the definitions for the Extended Features Register + * (StarTech 16C660 only, when DLAB=1) + */ +#define UART_EFR_CTS 0x80 /* CTS flow control */ +#define UART_EFR_RTS 0x40 /* RTS flow control */ +#define UART_EFR_SCD 0x20 /* Special character detect */ +#define UART_EFR_ENI 0x10 /* Enhanced Interrupt */ +/* + * the low four bits control software flow control + */ #endif /* _LINUX_SERIAL_REG_H */