X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fchar%2Fspecialix.c;h=2c24fcdc722a920fe00861be3b77fe76f168d2e6;hb=0c53b9fbcca8870e4f4b248f4ed5fdadd43a01b6;hp=1b5330299e30fa965086eae13d601a1e80e29be3;hpb=326f28e9ec4b2619c2fd410593fc95fcb0ba6b41;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 1b53302..2c24fcd 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -72,13 +72,12 @@ /* * There is a bunch of documentation about the card, jumpers, config * settings, restrictions, cables, device names and numbers in - * Documentation/specialix.txt + * Documentation/serial/specialix.txt */ -#include #include -#include +#include #include #include #include @@ -88,12 +87,14 @@ #include #include #include +#include #include #include #include #include #include -#include +#include +#include #include "specialix_io8.h" #include "cd1865.h" @@ -111,9 +112,10 @@ static int sx_debug; static int sx_rxfifo = SPECIALIX_RXFIFO; +static int sx_rtscts; #ifdef DEBUG -#define dprintk(f, str...) if (sx_debug & f) printk (str) +#define dprintk(f, str...) if (sx_debug & f) printk(str) #else #define dprintk(f, str...) /* nothing */ #endif @@ -132,10 +134,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; #define SX_DEBUG_FIFO 0x0800 -#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__) -#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __FUNCTION__) - -#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) +#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) +#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) /* Configurable options: */ @@ -143,17 +143,6 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; /* Am I paranoid or not ? ;-) */ #define SPECIALIX_PARANOIA_CHECK -/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help) - When the IRQ routine leaves the chip in a state that is keeps on - requiring attention, the timer doesn't help either. */ -#undef SPECIALIX_TIMER - -#ifdef SPECIALIX_TIMER -static int sx_poll = HZ; -#endif - - - /* * The following defines are mostly for testing purposes. But if you need * some nice reporting in your syslog, you can define them also. @@ -163,32 +152,13 @@ static int sx_poll = HZ; -#ifdef CONFIG_SPECIALIX_RTSCTS -#define SX_CRTSCTS(bla) 1 -#else -#define SX_CRTSCTS(tty) C_CRTSCTS(tty) -#endif - - -/* Used to be outb (0xff, 0x80); */ -#define short_pause() udelay (1) - #define SPECIALIX_LEGAL_FLAGS \ (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) -#undef RS_EVENT_WRITE_WAKEUP -#define RS_EVENT_WRITE_WAKEUP 0 - static struct tty_driver *specialix_driver; -static unsigned char * tmp_buf; - -static unsigned long baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 0, -}; static struct specialix_board sx_board[SX_NBOARD] = { { 0, SX_IOBASE1, 9, }, @@ -200,21 +170,14 @@ static struct specialix_board sx_board[SX_NBOARD] = { static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; -#ifdef SPECIALIX_TIMER -static struct timer_list missed_irq_timer; -static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs); -#endif - - - -static inline int sx_paranoia_check(struct specialix_port const * port, +static int sx_paranoia_check(struct specialix_port const *port, char *name, const char *routine) { #ifdef SPECIALIX_PARANOIA_CHECK - static const char *badmagic = - KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; - static const char *badinfo = - KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; + static const char *badmagic = KERN_ERR + "sx: Warning: bad specialix port magic number for device %s in %s\n"; + static const char *badinfo = KERN_ERR + "sx: Warning: null specialix port for device %s in %s\n"; if (!port) { printk(badinfo, name, routine); @@ -236,66 +199,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port, */ /* Get board number from pointer */ -static inline int board_No (struct specialix_board * bp) +static inline int board_No(struct specialix_board *bp) { return bp - sx_board; } /* Get port number from pointer */ -static inline int port_No (struct specialix_port const * port) +static inline int port_No(struct specialix_port const *port) { return SX_PORT(port - sx_port); } /* Get pointer to board from pointer to port */ -static inline struct specialix_board * port_Board(struct specialix_port const * port) +static inline struct specialix_board *port_Board( + struct specialix_port const *port) { return &sx_board[SX_BOARD(port - sx_port)]; } /* Input Byte from CL CD186x register */ -static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg) +static inline unsigned char sx_in(struct specialix_board *bp, + unsigned short reg) { bp->reg = reg | 0x80; - outb (reg | 0x80, bp->base + SX_ADDR_REG); - return inb (bp->base + SX_DATA_REG); + outb(reg | 0x80, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); } /* Output Byte to CL CD186x register */ -static inline void sx_out(struct specialix_board * bp, unsigned short reg, +static inline void sx_out(struct specialix_board *bp, unsigned short reg, unsigned char val) { bp->reg = reg | 0x80; - outb (reg | 0x80, bp->base + SX_ADDR_REG); - outb (val, bp->base + SX_DATA_REG); + outb(reg | 0x80, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); } /* Input Byte from CL CD186x register */ -static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg) +static inline unsigned char sx_in_off(struct specialix_board *bp, + unsigned short reg) { bp->reg = reg; - outb (reg, bp->base + SX_ADDR_REG); - return inb (bp->base + SX_DATA_REG); + outb(reg, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); } /* Output Byte to CL CD186x register */ -static inline void sx_out_off(struct specialix_board * bp, unsigned short reg, - unsigned char val) +static inline void sx_out_off(struct specialix_board *bp, + unsigned short reg, unsigned char val) { bp->reg = reg; - outb (reg, bp->base + SX_ADDR_REG); - outb (val, bp->base + SX_DATA_REG); + outb(reg, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); } /* Wait for Channel Command Register ready */ -static inline void sx_wait_CCR(struct specialix_board * bp) +static void sx_wait_CCR(struct specialix_board *bp) { unsigned long delay, flags; unsigned char ccr; @@ -306,7 +272,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) spin_unlock_irqrestore(&bp->lock, flags); if (!ccr) return; - udelay (1); + udelay(1); } printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); @@ -314,7 +280,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) /* Wait for Channel Command Register ready */ -static inline void sx_wait_CCR_off(struct specialix_board * bp) +static void sx_wait_CCR_off(struct specialix_board *bp) { unsigned long delay; unsigned char crr; @@ -326,7 +292,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) spin_unlock_irqrestore(&bp->lock, flags); if (!crr) return; - udelay (1); + udelay(1); } printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); @@ -337,7 +303,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) * specialix IO8+ IO range functions. */ -static inline int sx_request_io_range(struct specialix_board * bp) +static int sx_request_io_range(struct specialix_board *bp) { return request_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, @@ -345,27 +311,15 @@ static inline int sx_request_io_range(struct specialix_board * bp) } -static inline void sx_release_io_range(struct specialix_board * bp) +static void sx_release_io_range(struct specialix_board *bp) { - release_region(bp->base, - bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); + release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? + SX_PCI_IO_SPACE : SX_IO_SPACE); } -/* Must be called with enabled interrupts */ -/* Ugly. Very ugly. Don't use this for anything else than initialization - code */ -static inline void sx_long_delay(unsigned long delay) -{ - unsigned long i; - - for (i = jiffies + delay; time_after(i, jiffies); ) ; -} - - - /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ -static int sx_set_irq ( struct specialix_board *bp) +static int sx_set_irq(struct specialix_board *bp) { int virq; int i; @@ -375,15 +329,24 @@ static int sx_set_irq ( struct specialix_board *bp) return 1; switch (bp->irq) { /* In the same order as in the docs... */ - case 15: virq = 0;break; - case 12: virq = 1;break; - case 11: virq = 2;break; - case 9: virq = 3;break; - default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq); - return 0; + case 15: + virq = 0; + break; + case 12: + virq = 1; + break; + case 11: + virq = 2; + break; + case 9: + virq = 3; + break; + default:printk(KERN_ERR + "Speclialix: cannot set irq to %d.\n", bp->irq); + return 0; } spin_lock_irqsave(&bp->lock, flags); - for (i=0;i<2;i++) { + for (i = 0; i < 2; i++) { sx_out(bp, CD186x_CAR, i); sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); } @@ -393,7 +356,7 @@ static int sx_set_irq ( struct specialix_board *bp) /* Reset and setup CD186x chip */ -static int sx_init_CD186x(struct specialix_board * bp) +static int sx_init_CD186x(struct specialix_board *bp) { unsigned long flags; int scaler; @@ -404,7 +367,7 @@ static int sx_init_CD186x(struct specialix_board * bp) spin_lock_irqsave(&bp->lock, flags); sx_out_off(bp, CD186x_CCR, CCR_HARDRESET); /* Reset CD186x chip */ spin_unlock_irqrestore(&bp->lock, flags); - sx_long_delay(HZ/20); /* Delay 0.05 sec */ + msleep(50); /* Delay 0.05 sec */ spin_lock_irqsave(&bp->lock, flags); sx_out_off(bp, CD186x_GIVR, SX_ID); /* Set ID for this chip */ sx_out_off(bp, CD186x_GICR, 0); /* Clear all bits */ @@ -412,7 +375,7 @@ static int sx_init_CD186x(struct specialix_board * bp) sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ /* Set RegAckEn */ - sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); + sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); /* Setting up prescaler. We need 4 ticks per 1 ms */ scaler = SX_OSCFREQ/SPECIALIX_TPS; @@ -421,9 +384,9 @@ static int sx_init_CD186x(struct specialix_board * bp) sx_out_off(bp, CD186x_PPRL, scaler & 0xff); spin_unlock_irqrestore(&bp->lock, flags); - if (!sx_set_irq (bp)) { + if (!sx_set_irq(bp)) { /* Figure out how to pass this along... */ - printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq); + printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); rv = 0; } @@ -432,16 +395,16 @@ static int sx_init_CD186x(struct specialix_board * bp) } -static int read_cross_byte (struct specialix_board *bp, int reg, int bit) +static int read_cross_byte(struct specialix_board *bp, int reg, int bit) { int i; int t; unsigned long flags; spin_lock_irqsave(&bp->lock, flags); - for (i=0, t=0;i<8;i++) { - sx_out_off (bp, CD186x_CAR, i); - if (sx_in_off (bp, reg) & bit) + for (i = 0, t = 0; i < 8; i++) { + sx_out_off(bp, CD186x_CAR, i); + if (sx_in_off(bp, reg) & bit) t |= 1 << i; } spin_unlock_irqrestore(&bp->lock, flags); @@ -450,39 +413,10 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) } -#ifdef SPECIALIX_TIMER -void missed_irq (unsigned long data) -{ - unsigned char irq; - unsigned long flags; - struct specialix_board *bp = (struct specialix_board *)data; - - spin_lock_irqsave(&bp->lock, flags); - irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) & - (SRSR_RREQint | - SRSR_TREQint | - SRSR_MREQint); - spin_unlock_irqrestore(&bp->lock, flags); - if (irq) { - printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); - sx_interrupt (((struct specialix_board *)data)->irq, - (void*)data, NULL); - } - missed_irq_timer.expires = jiffies + sx_poll; - add_timer (&missed_irq_timer); -} -#endif - - - /* Main probing routine, also sets irq. */ static int sx_probe(struct specialix_board *bp) { unsigned char val1, val2; -#if 0 - int irqs = 0; - int retries; -#endif int rev; int chip; @@ -495,17 +429,18 @@ static int sx_probe(struct specialix_board *bp) /* Are the I/O ports here ? */ sx_out_off(bp, CD186x_PPRL, 0x5a); - short_pause (); + udelay(1); val1 = sx_in_off(bp, CD186x_PPRL); sx_out_off(bp, CD186x_PPRL, 0xa5); - short_pause (); + udelay(1); val2 = sx_in_off(bp, CD186x_PPRL); - if ((val1 != 0x5a) || (val2 != 0xa5)) { - printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", - board_No(bp), bp->base); + if (val1 != 0x5a || val2 != 0xa5) { + printk(KERN_INFO + "sx%d: specialix IO8+ Board at 0x%03x not found.\n", + board_No(bp), bp->base); sx_release_io_range(bp); func_exit(); return 1; @@ -513,10 +448,11 @@ static int sx_probe(struct specialix_board *bp) /* Check the DSR lines that Specialix uses as board identification */ - val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); - val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); - dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n", - board_No(bp), val1, val2); + val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); + val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); + dprintk(SX_DEBUG_INIT, + "sx%d: DSR lines are: %02x, rts lines are: %02x\n", + board_No(bp), val1, val2); /* They managed to switch the bit order between the docs and the IO8+ card. The new PCI card now conforms to old docs. @@ -524,7 +460,8 @@ static int sx_probe(struct specialix_board *bp) old card. */ val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; if (val1 != val2) { - printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", + printk(KERN_INFO + "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", board_No(bp), val2, bp->base, val1); sx_release_io_range(bp); func_exit(); @@ -532,47 +469,6 @@ static int sx_probe(struct specialix_board *bp) } -#if 0 - /* It's time to find IRQ for this board */ - for (retries = 0; retries < 5 && irqs <= 0; retries++) { - irqs = probe_irq_on(); - sx_init_CD186x(bp); /* Reset CD186x chip */ - sx_out(bp, CD186x_CAR, 2); /* Select port 2 */ - sx_wait_CCR(bp); - sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ - sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ - sx_long_delay(HZ/20); - irqs = probe_irq_off(irqs); - - dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); - dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR)); - dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR)); - dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR)); - dprintk (SX_DEBUG_INIT, "\n"); - - /* Reset CD186x again */ - if (!sx_init_CD186x(bp)) { - /* Hmmm. This is dead code anyway. */ - } - - dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", - val1, val2, val3); - - } - -#if 0 - if (irqs <= 0) { - printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", - board_No(bp), bp->base); - sx_release_io_range(bp); - func_exit(); - return 1; - } -#endif - printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs); - if (irqs > 0) - bp->irq = irqs; -#endif /* Reset CD186x again */ if (!sx_init_CD186x(bp)) { sx_release_io_range(bp); @@ -584,7 +480,7 @@ static int sx_probe(struct specialix_board *bp) bp->flags |= SX_BOARD_PRESENT; /* Chip revcode pkgtype - GFRCR SRCR bit 7 + GFRCR SRCR bit 7 CD180 rev B 0x81 0 CD180 rev C 0x82 0 CD1864 rev A 0x82 1 @@ -594,27 +490,32 @@ static int sx_probe(struct specialix_board *bp) */ switch (sx_in_off(bp, CD186x_GFRCR)) { - case 0x82:chip = 1864;rev='A';break; - case 0x83:chip = 1865;rev='A';break; - case 0x84:chip = 1865;rev='B';break; - case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */ - default:chip=-1;rev='x'; + case 0x82: + chip = 1864; + rev = 'A'; + break; + case 0x83: + chip = 1865; + rev = 'A'; + break; + case 0x84: + chip = 1865; + rev = 'B'; + break; + case 0x85: + chip = 1865; + rev = 'C'; + break; /* Does not exist at this time */ + default: + chip = -1; + rev = 'x'; } - dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); - -#ifdef SPECIALIX_TIMER - init_timer (&missed_irq_timer); - missed_irq_timer.function = missed_irq; - missed_irq_timer.data = (unsigned long) bp; - missed_irq_timer.expires = jiffies + sx_poll; - add_timer (&missed_irq_timer); -#endif + dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); - printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", - board_No(bp), - bp->base, bp->irq, - chip, rev); + printk(KERN_INFO + "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", + board_No(bp), bp->base, bp->irq, chip, rev); func_exit(); return 0; @@ -625,31 +526,22 @@ static int sx_probe(struct specialix_board *bp) * Interrupt processing routines. * */ -static inline void sx_mark_event(struct specialix_port * port, int event) -{ - func_enter(); - - set_bit(event, &port->event); - schedule_work(&port->tqueue); - - func_exit(); -} - - -static inline struct specialix_port * sx_get_port(struct specialix_board * bp, - unsigned char const * what) +static struct specialix_port *sx_get_port(struct specialix_board *bp, + unsigned char const *what) { unsigned char channel; - struct specialix_port * port = NULL; + struct specialix_port *port = NULL; channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; - dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel); + dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); if (channel < CD186x_NCH) { port = &sx_port[board_No(bp) * SX_NPORT + channel]; - dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%x\n",board_No(bp) * SX_NPORT + channel, port, port->flags & ASYNC_INITIALIZED); + dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", + board_No(bp) * SX_NPORT + channel, port, + port->port.flags & ASYNC_INITIALIZED); - if (port->flags & ASYNC_INITIALIZED) { - dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port); + if (port->port.flags & ASYNC_INITIALIZED) { + dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); func_exit(); return port; } @@ -660,7 +552,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, } -static inline void sx_receive_exc(struct specialix_board * bp) +static void sx_receive_exc(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; @@ -671,27 +563,29 @@ static inline void sx_receive_exc(struct specialix_board * bp) port = sx_get_port(bp, "Receive"); if (!port) { - dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); func_exit(); return; } - tty = port->tty; + tty = port->port.tty; status = sx_in(bp, CD186x_RCSR); - dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); + dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); if (status & RCSR_OE) { port->overrun++; - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n", - board_No(bp), port_No(port), port->overrun); + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Overrun. Total %ld overruns.\n", + board_No(bp), port_No(port), port->overrun); } status &= port->mark_mask; /* This flip buffer check needs to be below the reading of the status register to reset the chip's IRQ.... */ if (tty_buffer_request_room(tty, 1) == 0) { - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n", - board_No(bp), port_No(port)); + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Working around flip buffer overflow.\n", + board_No(bp), port_No(port)); func_exit(); return; } @@ -702,8 +596,9 @@ static inline void sx_receive_exc(struct specialix_board * bp) return; } if (status & RCSR_TOUT) { - printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", - board_No(bp), port_No(port)); + printk(KERN_INFO + "sx%d: port %d: Receiver timeout. Hardware problems ?\n", + board_No(bp), port_No(port)); func_exit(); return; @@ -711,7 +606,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n", board_No(bp), port_No(port)); flag = TTY_BREAK; - if (port->flags & ASYNC_SAK) + if (port->port.flags & ASYNC_SAK) do_SAK(tty); } else if (status & RCSR_PE) @@ -726,13 +621,13 @@ static inline void sx_receive_exc(struct specialix_board * bp) else flag = TTY_NORMAL; - if(tty_insert_flip_char(tty, ch, flag)) + if (tty_insert_flip_char(tty, ch, flag)) tty_flip_buffer_push(tty); func_exit(); } -static inline void sx_receive(struct specialix_board * bp) +static void sx_receive(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; @@ -740,19 +635,18 @@ static inline void sx_receive(struct specialix_board * bp) func_enter(); - if (!(port = sx_get_port(bp, "Receive"))) { - dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + port = sx_get_port(bp, "Receive"); + if (port == NULL) { + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); func_exit(); return; } - tty = port->tty; + tty = port->port.tty; count = sx_in(bp, CD186x_RDCR); - dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); + dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); port->hits[count > 8 ? 9 : count]++; - tty_buffer_request_room(tty, count); - while (count--) tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL); tty_flip_buffer_push(tty); @@ -760,19 +654,20 @@ static inline void sx_receive(struct specialix_board * bp) } -static inline void sx_transmit(struct specialix_board * bp) +static void sx_transmit(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; unsigned char count; func_enter(); - if (!(port = sx_get_port(bp, "Transmit"))) { + port = sx_get_port(bp, "Transmit"); + if (port == NULL) { func_exit(); return; } - dprintk (SX_DEBUG_TX, "port: %p\n", port); - tty = port->tty; + dprintk(SX_DEBUG_TX, "port: %p\n", port); + tty = port->port.tty; if (port->IER & IER_TXEMPTY) { /* FIFO drained */ @@ -803,7 +698,8 @@ static inline void sx_transmit(struct specialix_board * bp) sx_out(bp, CD186x_TDR, CD186x_C_ESC); sx_out(bp, CD186x_TDR, CD186x_C_DELAY); sx_out(bp, CD186x_TDR, count); - if (!(port->break_length -= count)) + port->break_length -= count; + if (port->break_length == 0) port->break_length--; } else { sx_out(bp, CD186x_TDR, CD186x_C_ESC); @@ -832,37 +728,37 @@ static inline void sx_transmit(struct specialix_board * bp) sx_out(bp, CD186x_IER, port->IER); } if (port->xmit_cnt <= port->wakeup_chars) - sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); + tty_wakeup(tty); func_exit(); } -static inline void sx_check_modem(struct specialix_board * bp) +static void sx_check_modem(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; unsigned char mcr; int msvr_cd; - dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); - if (!(port = sx_get_port(bp, "Modem"))) + dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); + port = sx_get_port(bp, "Modem"); + if (port == NULL) return; - tty = port->tty; + tty = port->port.tty; mcr = sx_in(bp, CD186x_MCR); - printk ("mcr = %02x.\n", mcr); if ((mcr & MCR_CDCHG)) { - dprintk (SX_DEBUG_SIGNALS, "CD just changed... "); + dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; if (msvr_cd) { - dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); - wake_up_interruptible(&port->open_wait); + dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); + wake_up_interruptible(&port->port.open_wait); } else { - dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); - schedule_work(&port->tqueue_hangup); + dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); + tty_hangup(tty); } } @@ -872,7 +768,7 @@ static inline void sx_check_modem(struct specialix_board * bp) tty->hw_stopped = 0; port->IER |= IER_TXRDY; if (port->xmit_cnt <= port->wakeup_chars) - sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); + tty_wakeup(tty); } else { tty->hw_stopped = 1; port->IER &= ~IER_TXRDY; @@ -884,7 +780,7 @@ static inline void sx_check_modem(struct specialix_board * bp) tty->hw_stopped = 0; port->IER |= IER_TXRDY; if (port->xmit_cnt <= port->wakeup_chars) - sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); + tty_wakeup(tty); } else { tty->hw_stopped = 1; port->IER &= ~IER_TXRDY; @@ -899,23 +795,25 @@ static inline void sx_check_modem(struct specialix_board * bp) /* The main interrupt processing routine */ -static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sx_interrupt(int dummy, void *dev_id) { unsigned char status; unsigned char ack; - struct specialix_board *bp; + struct specialix_board *bp = dev_id; unsigned long loop = 0; int saved_reg; unsigned long flags; func_enter(); - bp = dev_id; spin_lock_irqsave(&bp->lock, flags); - dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); - if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) { - dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq); + dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, + port_No(sx_get_port(bp, "INT")), + SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); + if (!(bp->flags & SX_BOARD_ACTIVE)) { + dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", + bp->irq); spin_unlock_irqrestore(&bp->lock, flags); func_exit(); return IRQ_NONE; @@ -923,10 +821,11 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) saved_reg = bp->reg; - while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & - (SRSR_RREQint | - SRSR_TREQint | - SRSR_MREQint)))) { + while (++loop < 16) { + status = sx_in(bp, CD186x_SRSR) & + (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); + if (status == 0) + break; if (status & SRSR_RREQint) { ack = sx_in(bp, CD186x_RRAR); @@ -935,8 +834,9 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) else if (ack == (SX_ID | GIVR_IT_REXC)) sx_receive_exc(bp); else - printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", - board_No(bp), status, ack); + printk(KERN_ERR + "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", + board_No(bp), status, ack); } else if (status & SRSR_TREQint) { ack = sx_in(bp, CD186x_TRAR); @@ -945,14 +845,16 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) sx_transmit(bp); else printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", - board_No(bp), status, ack, port_No (sx_get_port (bp, "Int"))); + board_No(bp), status, ack, + port_No(sx_get_port(bp, "Int"))); } else if (status & SRSR_MREQint) { ack = sx_in(bp, CD186x_MRAR); if (ack == (SX_ID | GIVR_IT_MODEM)) sx_check_modem(bp); else - printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", + printk(KERN_ERR + "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", board_No(bp), status, ack); } @@ -960,7 +862,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ } bp->reg = saved_reg; - outb (bp->reg, bp->base + SX_ADDR_REG); + outb(bp->reg, bp->base + SX_ADDR_REG); spin_unlock_irqrestore(&bp->lock, flags); func_exit(); return IRQ_HANDLED; @@ -971,36 +873,26 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) * Routines for open & close processing. */ -static void turn_ints_off (struct specialix_board *bp) +static void turn_ints_off(struct specialix_board *bp) { unsigned long flags; func_enter(); - if (bp->flags & SX_BOARD_IS_PCI) { - /* This was intended for enabeling the interrupt on the - * PCI card. However it seems that it's already enabled - * and as PCI interrupts can be shared, there is no real - * reason to have to turn it off. */ - } - spin_lock_irqsave(&bp->lock, flags); - (void) sx_in_off (bp, 0); /* Turn off interrupts. */ + (void) sx_in_off(bp, 0); /* Turn off interrupts. */ spin_unlock_irqrestore(&bp->lock, flags); func_exit(); } -static void turn_ints_on (struct specialix_board *bp) +static void turn_ints_on(struct specialix_board *bp) { unsigned long flags; func_enter(); - if (bp->flags & SX_BOARD_IS_PCI) { - /* play with the PCI chip. See comment above. */ - } spin_lock_irqsave(&bp->lock, flags); - (void) sx_in (bp, 0); /* Turn ON interrupts. */ + (void) sx_in(bp, 0); /* Turn ON interrupts. */ spin_unlock_irqrestore(&bp->lock, flags); func_exit(); @@ -1008,7 +900,7 @@ static void turn_ints_on (struct specialix_board *bp) /* Called with disabled interrupts */ -static inline int sx_setup_board(struct specialix_board * bp) +static int sx_setup_board(struct specialix_board *bp) { int error; @@ -1016,14 +908,16 @@ static inline int sx_setup_board(struct specialix_board * bp) return 0; if (bp->flags & SX_BOARD_IS_PCI) - error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT | SA_SHIRQ, "specialix IO8+", bp); + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); else - error = request_irq(bp->irq, sx_interrupt, SA_INTERRUPT, "specialix IO8+", bp); + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED, "specialix IO8+", bp); if (error) return error; - turn_ints_on (bp); + turn_ints_on(bp); bp->flags |= SX_BOARD_ACTIVE; return 0; @@ -1031,7 +925,7 @@ static inline int sx_setup_board(struct specialix_board * bp) /* Called with disabled interrupts */ -static inline void sx_shutdown_board(struct specialix_board *bp) +static void sx_shutdown_board(struct specialix_board *bp) { func_enter(); @@ -1042,22 +936,26 @@ static inline void sx_shutdown_board(struct specialix_board *bp) bp->flags &= ~SX_BOARD_ACTIVE; - dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", - bp->irq, board_No (bp)); + dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", + bp->irq, board_No(bp)); free_irq(bp->irq, bp); - - turn_ints_off (bp); - - + turn_ints_off(bp); func_exit(); } +static unsigned int sx_crtscts(struct tty_struct *tty) +{ + if (sx_rtscts) + return C_CRTSCTS(tty); + return 1; +} /* * Setting up port characteristics. * Must be called with disabled interrupts */ -static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) +static void sx_change_speed(struct specialix_board *bp, + struct specialix_port *port) { struct tty_struct *tty; unsigned long baud; @@ -1069,7 +967,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p func_enter(); - if (!(tty = port->tty) || !tty->termios) { + tty = port->port.tty; + if (!tty || !tty->termios) { func_exit(); return; } @@ -1082,46 +981,36 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* The Specialix board doens't implement the RTS lines. They are used to set the IRQ level. Don't touch them. */ - if (SX_CRTSCTS(tty)) + if (sx_crtscts(tty)) port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); else port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); spin_unlock_irqrestore(&bp->lock, flags); - dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); - baud = C_BAUD(tty); + dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); + baud = tty_get_baud_rate(tty); - if (baud & CBAUDEX) { - baud &= ~CBAUDEX; - if (baud < 1 || baud > 2) - port->tty->termios->c_cflag &= ~CBAUDEX; - else - baud += 15; + if (baud == 38400) { + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) + baud = 57600; + if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) + baud = 115200; } - if (baud == 15) { - if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baud ++; - if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baud += 2; - } - - if (!baud_table[baud]) { + if (!baud) { /* Drop DTR & exit */ - dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); - if (!SX_CRTSCTS (tty)) { - port -> MSVR &= ~ MSVR_DTR; + dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); + if (!sx_crtscts(tty)) { + port->MSVR &= ~MSVR_DTR; spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_MSVR, port->MSVR ); + sx_out(bp, CD186x_MSVR, port->MSVR); spin_unlock_irqrestore(&bp->lock, flags); - } - else - dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); + } else + dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); return; } else { /* Set DTR on */ - if (!SX_CRTSCTS (tty)) { - port ->MSVR |= MSVR_DTR; - } + if (!sx_crtscts(tty)) + port->MSVR |= MSVR_DTR; } /* @@ -1130,28 +1019,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* Set baud rate for port */ tmp = port->custom_divisor ; - if ( tmp ) - printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n" - "This is an untested option, please be carefull.\n", - port_No (port), tmp); + if (tmp) + printk(KERN_INFO + "sx%d: Using custom baud rate divisor %ld. \n" + "This is an untested option, please be careful.\n", + port_No(port), tmp); else - tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + - CD186x_TPC/2) / CD186x_TPC); + tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / + CD186x_TPC); - if ((tmp < 0x10) && time_before(again, jiffies)) { + if (tmp < 0x10 && time_before(again, jiffies)) { again = jiffies + HZ * 60; /* Page 48 of version 2.0 of the CL-CD1865 databook */ if (tmp >= 12) { - printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Performance degradation is possible.\n" - "Read specialix.txt for more info.\n", - port_No (port), tmp); + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Performance degradation is possible.\n" + "Read specialix.txt for more info.\n", + port_No(port), tmp); } else { - printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Warning: overstressing Cirrus chip. " - "This might not work.\n" - "Read specialix.txt for more info.\n", - port_No (port), tmp); + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Warning: overstressing Cirrus chip. This might not work.\n" + "Read specialix.txt for more info.\n", port_No(port), tmp); } } spin_lock_irqsave(&bp->lock, flags); @@ -1160,11 +1048,10 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p sx_out(bp, CD186x_RBPRL, tmp & 0xff); sx_out(bp, CD186x_TBPRL, tmp & 0xff); spin_unlock_irqrestore(&bp->lock, flags); - if (port->custom_divisor) { - baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; - baud = ( baud + 5 ) / 10; - } else - baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ + if (port->custom_divisor) + baud = (SX_OSCFREQ + port->custom_divisor/2) / + port->custom_divisor; + baud = (baud + 5) / 10; /* Estimated CPS */ /* Two timer ticks seems enough to wakeup something like SLIP driver */ tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; @@ -1178,16 +1065,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p sx_out(bp, CD186x_RTPR, tmp); spin_unlock_irqrestore(&bp->lock, flags); switch (C_CSIZE(tty)) { - case CS5: + case CS5: cor1 |= COR1_5BITS; break; - case CS6: + case CS6: cor1 |= COR1_6BITS; break; - case CS7: + case CS7: cor1 |= COR1_7BITS; break; - case CS8: + case CS8: cor1 |= COR1_8BITS; break; } @@ -1224,7 +1111,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; spin_lock_irqsave(&bp->lock, flags); - tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); + tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & + (MSVR_CTS|MSVR_DSR)); spin_unlock_irqrestore(&bp->lock, flags); #else port->COR2 |= COR2_CTSAE; @@ -1268,7 +1156,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); /* Setting up modem option registers */ - dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2); + dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", + mcor1, mcor2); sx_out(bp, CD186x_MCOR1, mcor1); sx_out(bp, CD186x_MCOR2, mcor2); spin_unlock_irqrestore(&bp->lock, flags); @@ -1287,13 +1176,14 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* Must be called with interrupts enabled */ -static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port) +static int sx_setup_port(struct specialix_board *bp, + struct specialix_port *port) { unsigned long flags; func_enter(); - if (port->flags & ASYNC_INITIALIZED) { + if (port->port.flags & ASYNC_INITIALIZED) { func_exit(); return 0; } @@ -1302,7 +1192,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port /* We may sleep in get_zeroed_page() */ unsigned long tmp; - if (!(tmp = get_zeroed_page(GFP_KERNEL))) { + tmp = get_zeroed_page(GFP_KERNEL); + if (tmp == 0L) { func_exit(); return -ENOMEM; } @@ -1317,12 +1208,12 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port spin_lock_irqsave(&port->lock, flags); - if (port->tty) - clear_bit(TTY_IO_ERROR, &port->tty->flags); + if (port->port.tty) + clear_bit(TTY_IO_ERROR, &port->port.tty->flags); port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; sx_change_speed(bp, port); - port->flags |= ASYNC_INITIALIZED; + port->port.flags |= ASYNC_INITIALIZED; spin_unlock_irqrestore(&port->lock, flags); @@ -1333,7 +1224,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port /* Must be called with interrupts disabled */ -static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port) +static void sx_shutdown_port(struct specialix_board *bp, + struct specialix_port *port) { struct tty_struct *tty; int i; @@ -1341,17 +1233,17 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * func_enter(); - if (!(port->flags & ASYNC_INITIALIZED)) { + if (!(port->port.flags & ASYNC_INITIALIZED)) { func_exit(); return; } if (sx_debug & SX_DEBUG_FIFO) { - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", - board_No(bp), port_No(port), port->overrun); - for (i = 0; i < 10; i++) { + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: %ld overruns, FIFO hits [ ", + board_No(bp), port_No(port), port->overrun); + for (i = 0; i < 10; i++) dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); - } dprintk(SX_DEBUG_FIFO, "].\n"); } @@ -1364,7 +1256,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); - if (!(tty = port->tty) || C_HUPCL(tty)) { + tty = port->port.tty; + if (tty == NULL || C_HUPCL(tty)) { /* Drop DTR */ sx_out(bp, CD186x_MSVDTR, 0); } @@ -1379,7 +1272,7 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * spin_unlock_irqrestore(&bp->lock, flags); if (tty) set_bit(TTY_IO_ERROR, &tty->flags); - port->flags &= ~ASYNC_INITIALIZED; + port->port.flags &= ~ASYNC_INITIALIZED; if (!bp->count) sx_shutdown_board(bp); @@ -1387,8 +1280,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * } -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct specialix_port *port) +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct specialix_port *port) { DECLARE_WAITQUEUE(wait, current); struct specialix_board *bp = port_Board(port); @@ -1403,9 +1296,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, * If the device is in the middle of being closed, then block * until it's done, and then try again. */ - if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->close_wait); - if (port->flags & ASYNC_HUP_NOTIFY) { + if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { + interruptible_sleep_on(&port->port.close_wait); + if (port->port.flags & ASYNC_HUP_NOTIFY) { func_exit(); return -EAGAIN; } else { @@ -1420,7 +1313,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { - port->flags |= ASYNC_NORMAL_ACTIVE; + port->port.flags |= ASYNC_NORMAL_ACTIVE; func_exit(); return 0; } @@ -1436,37 +1329,36 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, * exit, either normal or abnormal. */ retval = 0; - add_wait_queue(&port->open_wait, &wait); + add_wait_queue(&port->port.open_wait, &wait); spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { - port->count--; - } + if (!tty_hung_up_p(filp)) + port->port.count--; spin_unlock_irqrestore(&port->lock, flags); - port->blocked_open++; + port->port.blocked_open++; while (1) { spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; - if (SX_CRTSCTS (tty)) { + if (sx_crtscts(tty)) { /* Activate RTS */ port->MSVR |= MSVR_DTR; /* WTF? */ - sx_out (bp, CD186x_MSVR, port->MSVR); + sx_out(bp, CD186x_MSVR, port->MSVR); } else { /* Activate DTR */ port->MSVR |= MSVR_DTR; - sx_out (bp, CD186x_MSVR, port->MSVR); + sx_out(bp, CD186x_MSVR, port->MSVR); } spin_unlock_irqrestore(&bp->lock, flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { - if (port->flags & ASYNC_HUP_NOTIFY) + !(port->port.flags & ASYNC_INITIALIZED)) { + if (port->port.flags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else retval = -ERESTARTSYS; break; } - if (!(port->flags & ASYNC_CLOSING) && + if (!(port->port.flags & ASYNC_CLOSING) && (do_clocal || CD)) break; if (signal_pending(current)) { @@ -1477,30 +1369,29 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); + remove_wait_queue(&port->port.open_wait, &wait); spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { - port->count++; - } - port->blocked_open--; + if (!tty_hung_up_p(filp)) + port->port.count++; + port->port.blocked_open--; spin_unlock_irqrestore(&port->lock, flags); if (retval) { func_exit(); return retval; } - port->flags |= ASYNC_NORMAL_ACTIVE; + port->port.flags |= ASYNC_NORMAL_ACTIVE; func_exit(); return 0; } -static int sx_open(struct tty_struct * tty, struct file * filp) +static int sx_open(struct tty_struct *tty, struct file *filp) { int board; int error; - struct specialix_port * port; - struct specialix_board * bp; + struct specialix_port *port; + struct specialix_board *bp; int i; unsigned long flags; @@ -1517,34 +1408,38 @@ static int sx_open(struct tty_struct * tty, struct file * filp) port = sx_port + board * SX_NPORT + SX_PORT(tty->index); port->overrun = 0; for (i = 0; i < 10; i++) - port->hits[i]=0; + port->hits[i] = 0; - dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n", - board, bp, port, SX_PORT(tty->index)); + dprintk(SX_DEBUG_OPEN, + "Board = %d, bp = %p, port = %p, portno = %d.\n", + board, bp, port, SX_PORT(tty->index)); if (sx_paranoia_check(port, tty->name, "sx_open")) { func_enter(); return -ENODEV; } - if ((error = sx_setup_board(bp))) { + error = sx_setup_board(bp); + if (error) { func_exit(); return error; } spin_lock_irqsave(&bp->lock, flags); - port->count++; + port->port.count++; bp->count++; tty->driver_data = port; - port->tty = tty; + port->port.tty = tty; spin_unlock_irqrestore(&bp->lock, flags); - if ((error = sx_setup_port(bp, port))) { + error = sx_setup_port(bp, port); + if (error) { func_enter(); return error; } - if ((error = block_til_ready(tty, filp, port))) { + error = block_til_ready(tty, filp, port); + if (error) { func_enter(); return error; } @@ -1553,10 +1448,31 @@ static int sx_open(struct tty_struct * tty, struct file * filp) return 0; } +static void sx_flush_buffer(struct tty_struct *tty) +{ + struct specialix_port *port = tty->driver_data; + unsigned long flags; + struct specialix_board *bp; + + func_enter(); -static void sx_close(struct tty_struct * tty, struct file * filp) + if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) { + func_exit(); + return; + } + + bp = port_Board(port); + spin_lock_irqsave(&port->lock, flags); + port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; + spin_unlock_irqrestore(&port->lock, flags); + tty_wakeup(tty); + + func_exit(); +} + +static void sx_close(struct tty_struct *tty, struct file *filp) { - struct specialix_port *port = (struct specialix_port *) tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; unsigned long timeout; @@ -1575,15 +1491,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } bp = port_Board(port); - if ((tty->count == 1) && (port->count != 1)) { + if (tty->count == 1 && port->port.count != 1) { printk(KERN_ERR "sx%d: sx_close: bad port count;" " tty->count is 1, port count is %d\n", - board_No(bp), port->count); - port->count = 1; + board_No(bp), port->port.count); + port->port.count = 1; } - if (port->count > 1) { - port->count--; + if (port->port.count > 1) { + port->port.count--; bp->count--; spin_unlock_irqrestore(&port->lock, flags); @@ -1591,26 +1507,25 @@ static void sx_close(struct tty_struct * tty, struct file * filp) func_exit(); return; } - port->flags |= ASYNC_CLOSING; + port->port.flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); - dprintk (SX_DEBUG_OPEN, "Closing\n"); - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { - tty_wait_until_sent(tty, port->closing_wait); - } + dprintk(SX_DEBUG_OPEN, "Closing\n"); + if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, port->port.closing_wait); /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the * line status register. */ - dprintk (SX_DEBUG_OPEN, "Closed\n"); + dprintk(SX_DEBUG_OPEN, "Closed\n"); port->IER &= ~IER_RXD; - if (port->flags & ASYNC_INITIALIZED) { + if (port->port.flags & ASYNC_INITIALIZED) { port->IER &= ~IER_TXRDY; port->IER |= IER_TXEMPTY; spin_lock_irqsave(&bp->lock, flags); @@ -1623,11 +1538,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp) * important if there is a transmit FIFO! */ timeout = jiffies+HZ; - while(port->IER & IER_TXEMPTY) { - set_current_state (TASK_INTERRUPTIBLE); + while (port->IER & IER_TXEMPTY) { + set_current_state(TASK_INTERRUPTIBLE); msleep_interruptible(jiffies_to_msecs(port->timeout)); if (time_after(jiffies, timeout)) { - printk (KERN_INFO "Timeout waiting for close\n"); + printk(KERN_INFO "Timeout waiting for close\n"); break; } } @@ -1635,42 +1550,42 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } if (--bp->count < 0) { - printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); + printk(KERN_ERR + "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); bp->count = 0; } - if (--port->count < 0) { - printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n", - board_No(bp), port_No(port), port->count); - port->count = 0; + if (--port->port.count < 0) { + printk(KERN_ERR + "sx%d: sx_close: bad port count for tty%d: %d\n", + board_No(bp), port_No(port), port->port.count); + port->port.count = 0; } sx_shutdown_port(bp, port); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); + sx_flush_buffer(tty); tty_ldisc_flush(tty); spin_lock_irqsave(&port->lock, flags); tty->closing = 0; - port->event = 0; - port->tty = NULL; + port->port.tty = NULL; spin_unlock_irqrestore(&port->lock, flags); - if (port->blocked_open) { - if (port->close_delay) { - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - } - wake_up_interruptible(&port->open_wait); + if (port->port.blocked_open) { + if (port->port.close_delay) + msleep_interruptible( + jiffies_to_msecs(port->port.close_delay)); + wake_up_interruptible(&port->port.open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&port->close_wait); + port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + wake_up_interruptible(&port->port.close_wait); func_exit(); } -static int sx_write(struct tty_struct * tty, - const unsigned char *buf, int count) +static int sx_write(struct tty_struct *tty, + const unsigned char *buf, int count) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; int c, total = 0; unsigned long flags; @@ -1683,7 +1598,7 @@ static int sx_write(struct tty_struct * tty, bp = port_Board(port); - if (!port->xmit_buf || !tmp_buf) { + if (!port->xmit_buf) { func_exit(); return 0; } @@ -1720,48 +1635,50 @@ static int sx_write(struct tty_struct * tty, } -static void sx_put_char(struct tty_struct * tty, unsigned char ch) +static int sx_put_char(struct tty_struct *tty, unsigned char ch) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; unsigned long flags; - struct specialix_board * bp; + struct specialix_board *bp; func_enter(); if (sx_paranoia_check(port, tty->name, "sx_put_char")) { func_exit(); - return; + return 0; } - dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); + dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); if (!port->xmit_buf) { func_exit(); - return; + return 0; } bp = port_Board(port); spin_lock_irqsave(&port->lock, flags); - dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf); - if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) { + dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", + port->xmit_cnt, port->xmit_buf); + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { spin_unlock_irqrestore(&port->lock, flags); - dprintk (SX_DEBUG_TX, "Exit size\n"); + dprintk(SX_DEBUG_TX, "Exit size\n"); func_exit(); - return; + return 0; } - dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); + dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); port->xmit_buf[port->xmit_head++] = ch; port->xmit_head &= SERIAL_XMIT_SIZE - 1; port->xmit_cnt++; spin_unlock_irqrestore(&port->lock, flags); func_exit(); + return 1; } -static void sx_flush_chars(struct tty_struct * tty) +static void sx_flush_chars(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; unsigned long flags; - struct specialix_board * bp = port_Board(port); + struct specialix_board *bp = port_Board(port); func_enter(); @@ -1784,9 +1701,9 @@ static void sx_flush_chars(struct tty_struct * tty) } -static int sx_write_room(struct tty_struct * tty) +static int sx_write_room(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; int ret; func_enter(); @@ -1807,7 +1724,7 @@ static int sx_write_room(struct tty_struct * tty) static int sx_chars_in_buffer(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; func_enter(); @@ -1819,65 +1736,39 @@ static int sx_chars_in_buffer(struct tty_struct *tty) return port->xmit_cnt; } - -static void sx_flush_buffer(struct tty_struct *tty) -{ - struct specialix_port *port = (struct specialix_port *)tty->driver_data; - unsigned long flags; - struct specialix_board * bp; - - func_enter(); - - if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) { - func_exit(); - return; - } - - bp = port_Board(port); - spin_lock_irqsave(&port->lock, flags); - port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; - spin_unlock_irqrestore(&port->lock, flags); - tty_wakeup(tty); - - func_exit(); -} - - static int sx_tiocmget(struct tty_struct *tty, struct file *file) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; - struct specialix_board * bp; + struct specialix_port *port = tty->driver_data; + struct specialix_board *bp; unsigned char status; unsigned int result; unsigned long flags; func_enter(); - if (sx_paranoia_check(port, tty->name, __FUNCTION__)) { + if (sx_paranoia_check(port, tty->name, __func__)) { func_exit(); return -ENODEV; } bp = port_Board(port); - spin_lock_irqsave (&bp->lock, flags); + spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); status = sx_in(bp, CD186x_MSVR); spin_unlock_irqrestore(&bp->lock, flags); - dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", - port_No(port), status, sx_in (bp, CD186x_CAR)); - dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); - if (SX_CRTSCTS(port->tty)) { - result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ - | ((status & MSVR_DTR) ? TIOCM_RTS : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", + port_No(port), status, sx_in(bp, CD186x_CAR)); + dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); + if (sx_crtscts(port->port.tty)) { + result = TIOCM_DTR | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_RTS : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } else { - result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ - | ((status & MSVR_DTR) ? TIOCM_DTR : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + result = TIOCM_RTS | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_DTR : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } func_exit(); @@ -1889,13 +1780,13 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) static int sx_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; unsigned long flags; struct specialix_board *bp; func_enter(); - if (sx_paranoia_check(port, tty->name, __FUNCTION__)) { + if (sx_paranoia_check(port, tty->name, __func__)) { func_exit(); return -ENODEV; } @@ -1903,57 +1794,50 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, bp = port_Board(port); spin_lock_irqsave(&port->lock, flags); - /* if (set & TIOCM_RTS) - port->MSVR |= MSVR_RTS; */ - /* if (set & TIOCM_DTR) - port->MSVR |= MSVR_DTR; */ - - if (SX_CRTSCTS(port->tty)) { + if (sx_crtscts(port->port.tty)) { if (set & TIOCM_RTS) port->MSVR |= MSVR_DTR; } else { if (set & TIOCM_DTR) port->MSVR |= MSVR_DTR; } - - /* if (clear & TIOCM_RTS) - port->MSVR &= ~MSVR_RTS; */ - /* if (clear & TIOCM_DTR) - port->MSVR &= ~MSVR_DTR; */ - if (SX_CRTSCTS(port->tty)) { + if (sx_crtscts(port->port.tty)) { if (clear & TIOCM_RTS) port->MSVR &= ~MSVR_DTR; } else { if (clear & TIOCM_DTR) port->MSVR &= ~MSVR_DTR; } - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); sx_out(bp, CD186x_CAR, port_No(port)); sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); spin_unlock_irqrestore(&port->lock, flags); func_exit(); return 0; } -static inline void sx_send_break(struct specialix_port * port, unsigned long length) +static int sx_send_break(struct tty_struct *tty, int length) { + struct specialix_port *port = tty->driver_data; struct specialix_board *bp = port_Board(port); unsigned long flags; func_enter(); + if (length == 0 || length == -1) + return -EOPNOTSUPP; - spin_lock_irqsave (&port->lock, flags); + spin_lock_irqsave(&port->lock, flags); port->break_length = SPECIALIX_TPS / HZ * length; port->COR2 |= COR2_ETC; port->IER |= IER_TXRDY; - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); sx_out(bp, CD186x_CAR, port_No(port)); sx_out(bp, CD186x_COR2, port->COR2); sx_out(bp, CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); - spin_unlock_irqrestore (&port->lock, flags); + spin_unlock(&bp->lock); + spin_unlock_irqrestore(&port->lock, flags); sx_wait_CCR(bp); spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_CORCHG2); @@ -1961,72 +1845,59 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len sx_wait_CCR(bp); func_exit(); + return 0; } -static inline int sx_set_serial_info(struct specialix_port * port, - struct serial_struct __user * newinfo) +static int sx_set_serial_info(struct specialix_port *port, + struct serial_struct __user *newinfo) { struct serial_struct tmp; struct specialix_board *bp = port_Board(port); int change_speed; func_enter(); - /* - if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) { - func_exit(); - return -EFAULT; - } - */ + if (copy_from_user(&tmp, newinfo, sizeof(tmp))) { func_enter(); return -EFAULT; } -#if 0 - if ((tmp.irq != bp->irq) || - (tmp.port != bp->base) || - (tmp.type != PORT_CIRRUS) || - (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) || - (tmp.custom_divisor != 0) || - (tmp.xmit_fifo_size != CD186x_NFIFO) || - (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) { - func_exit(); - return -EINVAL; - } -#endif + lock_kernel(); - change_speed = ((port->flags & ASYNC_SPD_MASK) != + change_speed = ((port->port.flags & ASYNC_SPD_MASK) != (tmp.flags & ASYNC_SPD_MASK)); change_speed |= (tmp.custom_divisor != port->custom_divisor); if (!capable(CAP_SYS_ADMIN)) { - if ((tmp.close_delay != port->close_delay) || - (tmp.closing_wait != port->closing_wait) || + if ((tmp.close_delay != port->port.close_delay) || + (tmp.closing_wait != port->port.closing_wait) || ((tmp.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) { + (port->port.flags & ~ASYNC_USR_MASK))) { func_exit(); + unlock_kernel(); return -EPERM; } - port->flags = ((port->flags & ~ASYNC_USR_MASK) | - (tmp.flags & ASYNC_USR_MASK)); + port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | + (tmp.flags & ASYNC_USR_MASK)); port->custom_divisor = tmp.custom_divisor; } else { - port->flags = ((port->flags & ~ASYNC_FLAGS) | - (tmp.flags & ASYNC_FLAGS)); - port->close_delay = tmp.close_delay; - port->closing_wait = tmp.closing_wait; + port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | + (tmp.flags & ASYNC_FLAGS)); + port->port.close_delay = tmp.close_delay; + port->port.closing_wait = tmp.closing_wait; port->custom_divisor = tmp.custom_divisor; } - if (change_speed) { + if (change_speed) sx_change_speed(bp, port); - } + func_exit(); + unlock_kernel(); return 0; } -static inline int sx_get_serial_info(struct specialix_port * port, +static int sx_get_serial_info(struct specialix_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -2034,22 +1905,19 @@ static inline int sx_get_serial_info(struct specialix_port * port, func_enter(); - /* - if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp))) - return -EFAULT; - */ - memset(&tmp, 0, sizeof(tmp)); + lock_kernel(); tmp.type = PORT_CIRRUS; tmp.line = port - sx_port; tmp.port = bp->base; tmp.irq = bp->irq; - tmp.flags = port->flags; + tmp.flags = port->port.flags; tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC; - tmp.close_delay = port->close_delay * HZ/100; - tmp.closing_wait = port->closing_wait * HZ/100; + tmp.close_delay = port->port.close_delay * HZ/100; + tmp.closing_wait = port->port.closing_wait * HZ/100; tmp.custom_divisor = port->custom_divisor; tmp.xmit_fifo_size = CD186x_NFIFO; + unlock_kernel(); if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { func_exit(); return -EFAULT; @@ -2060,11 +1928,10 @@ static inline int sx_get_serial_info(struct specialix_port * port, } -static int sx_ioctl(struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) +static int sx_ioctl(struct tty_struct *tty, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; - int retval; + struct specialix_port *port = tty->driver_data; void __user *argp = (void __user *)arg; func_enter(); @@ -2075,51 +1942,14 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, } switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) { - func_exit(); - return retval; - } - tty_wait_until_sent(tty, 0); - if (!arg) - sx_send_break(port, HZ/4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) { - func_exit(); - return retval; - } - tty_wait_until_sent(tty, 0); - sx_send_break(port, arg ? arg*(HZ/10) : HZ/4); + case TIOCGSERIAL: func_exit(); - return 0; - case TIOCGSOFTCAR: - if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) { - func_exit(); - return -EFAULT; - } - func_exit(); - return 0; - case TIOCSSOFTCAR: - if (get_user(arg, (unsigned long __user *) argp)) { - func_exit(); - return -EFAULT; - } - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - func_exit(); - return 0; - case TIOCGSERIAL: - func_exit(); return sx_get_serial_info(port, argp); - case TIOCSSERIAL: - func_exit(); + case TIOCSSERIAL: + func_exit(); return sx_set_serial_info(port, argp); - default: - func_exit(); + default: + func_exit(); return -ENOIOCTLCMD; } func_exit(); @@ -2127,9 +1957,9 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, } -static void sx_throttle(struct tty_struct * tty) +static void sx_throttle(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; @@ -2143,21 +1973,21 @@ static void sx_throttle(struct tty_struct * tty) bp = port_Board(port); /* Use DTR instead of RTS ! */ - if (SX_CRTSCTS (tty)) + if (sx_crtscts(tty)) port->MSVR &= ~MSVR_DTR; else { /* Auch!!! I think the system shouldn't call this then. */ /* Or maybe we're supposed (allowed?) to do our side of hw handshake anyway, even when hardware handshake is off. When you see this in your logs, please report.... */ - printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", - port_No (port)); + printk(KERN_ERR + "sx%d: Need to throttle, but can't (hardware hs is off)\n", + port_No(port)); } spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); spin_unlock_irqrestore(&bp->lock, flags); if (I_IXOFF(tty)) { - spin_unlock_irqrestore(&bp->lock, flags); sx_wait_CCR(bp); spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_SSCH2); @@ -2172,9 +2002,9 @@ static void sx_throttle(struct tty_struct * tty) } -static void sx_unthrottle(struct tty_struct * tty) +static void sx_unthrottle(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; @@ -2189,12 +2019,12 @@ static void sx_unthrottle(struct tty_struct * tty) spin_lock_irqsave(&port->lock, flags); /* XXXX Use DTR INSTEAD???? */ - if (SX_CRTSCTS(tty)) { + if (sx_crtscts(tty)) port->MSVR |= MSVR_DTR; - } /* Else clause: see remark in "sx_throttle"... */ - spin_lock_irqsave(&bp->lock, flags); + /* Else clause: see remark in "sx_throttle"... */ + spin_lock(&bp->lock); sx_out(bp, CD186x_CAR, port_No(port)); - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); if (I_IXOFF(tty)) { spin_unlock_irqrestore(&port->lock, flags); sx_wait_CCR(bp); @@ -2204,18 +2034,18 @@ static void sx_unthrottle(struct tty_struct * tty) sx_wait_CCR(bp); spin_lock_irqsave(&port->lock, flags); } - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); sx_out(bp, CD186x_MSVR, port->MSVR); - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); spin_unlock_irqrestore(&port->lock, flags); func_exit(); } -static void sx_stop(struct tty_struct * tty) +static void sx_stop(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; @@ -2230,19 +2060,19 @@ static void sx_stop(struct tty_struct * tty) spin_lock_irqsave(&port->lock, flags); port->IER &= ~IER_TXRDY; - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); sx_out(bp, CD186x_CAR, port_No(port)); sx_out(bp, CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); spin_unlock_irqrestore(&port->lock, flags); func_exit(); } -static void sx_start(struct tty_struct * tty) +static void sx_start(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; @@ -2258,44 +2088,19 @@ static void sx_start(struct tty_struct * tty) spin_lock_irqsave(&port->lock, flags); if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { port->IER |= IER_TXRDY; - spin_lock_irqsave(&bp->lock, flags); + spin_lock(&bp->lock); sx_out(bp, CD186x_CAR, port_No(port)); sx_out(bp, CD186x_IER, port->IER); - spin_unlock_irqrestore(&bp->lock, flags); + spin_unlock(&bp->lock); } spin_unlock_irqrestore(&port->lock, flags); func_exit(); } - -/* - * This routine is called from the work-queue when the interrupt - * routine has signalled that a hangup has occurred. The path of - * hangup processing is: - * - * serial interrupt routine -> (workqueue) -> - * do_sx_hangup() -> tty->hangup() -> sx_hangup() - * - */ -static void do_sx_hangup(void *private_) -{ - struct specialix_port *port = (struct specialix_port *) private_; - struct tty_struct *tty; - - func_enter(); - - tty = port->tty; - if (tty) - tty_hangup(tty); /* FIXME: module removal race here */ - - func_exit(); -} - - -static void sx_hangup(struct tty_struct * tty) +static void sx_hangup(struct tty_struct *tty) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; struct specialix_board *bp; unsigned long flags; @@ -2310,36 +2115,33 @@ static void sx_hangup(struct tty_struct * tty) sx_shutdown_port(bp, port); spin_lock_irqsave(&port->lock, flags); - port->event = 0; - bp->count -= port->count; + bp->count -= port->port.count; if (bp->count < 0) { - printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); + printk(KERN_ERR + "sx%d: sx_hangup: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); bp->count = 0; } - port->count = 0; - port->flags &= ~ASYNC_NORMAL_ACTIVE; - port->tty = NULL; + port->port.count = 0; + port->port.flags &= ~ASYNC_NORMAL_ACTIVE; + port->port.tty = NULL; spin_unlock_irqrestore(&port->lock, flags); - wake_up_interruptible(&port->open_wait); + wake_up_interruptible(&port->port.open_wait); func_exit(); } -static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) +static void sx_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) { - struct specialix_port *port = (struct specialix_port *)tty->driver_data; + struct specialix_port *port = tty->driver_data; unsigned long flags; - struct specialix_board * bp; + struct specialix_board *bp; if (sx_paranoia_check(port, tty->name, "sx_set_termios")) return; - if (tty->termios->c_cflag == old_termios->c_cflag && - tty->termios->c_iflag == old_termios->c_iflag) - return; - bp = port_Board(port); spin_lock_irqsave(&port->lock, flags); sx_change_speed(port_Board(port), port); @@ -2352,28 +2154,7 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios } } - -static void do_softint(void *private_) -{ - struct specialix_port *port = (struct specialix_port *) private_; - struct tty_struct *tty; - - func_enter(); - - if(!(tty = port->tty)) { - func_exit(); - return; - } - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) { - tty_wakeup(tty); - //wake_up_interruptible(&tty->write_wait); - } - - func_exit(); -} - -static struct tty_operations sx_ops = { +static const struct tty_operations sx_ops = { .open = sx_open, .close = sx_close, .write = sx_write, @@ -2391,6 +2172,7 @@ static struct tty_operations sx_ops = { .hangup = sx_hangup, .tiocmget = sx_tiocmget, .tiocmset = sx_tiocmset, + .break_ctl = sx_send_break, }; static int sx_init_drivers(void) @@ -2407,12 +2189,6 @@ static int sx_init_drivers(void) return 1; } - if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) { - printk(KERN_ERR "sx: Couldn't get free page.\n"); - put_tty_driver(specialix_driver); - func_exit(); - return 1; - } specialix_driver->owner = THIS_MODULE; specialix_driver->name = "ttyW"; specialix_driver->major = SPECIALIX_NORMAL_MAJOR; @@ -2421,26 +2197,25 @@ static int sx_init_drivers(void) specialix_driver->init_termios = tty_std_termios; specialix_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - specialix_driver->flags = TTY_DRIVER_REAL_RAW; + specialix_driver->init_termios.c_ispeed = 9600; + specialix_driver->init_termios.c_ospeed = 9600; + specialix_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_HARDWARE_BREAK; tty_set_operations(specialix_driver, &sx_ops); - if ((error = tty_register_driver(specialix_driver))) { + error = tty_register_driver(specialix_driver); + if (error) { put_tty_driver(specialix_driver); - free_page((unsigned long)tmp_buf); - printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", - error); + printk(KERN_ERR + "sx: Couldn't register specialix IO8+ driver, error = %d\n", + error); func_exit(); return 1; } memset(sx_port, 0, sizeof(sx_port)); for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { sx_port[i].magic = SPECIALIX_MAGIC; - INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]); - INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]); - sx_port[i].close_delay = 50 * HZ/100; - sx_port[i].closing_wait = 3000 * HZ/100; - init_waitqueue_head(&sx_port[i].open_wait); - init_waitqueue_head(&sx_port[i].close_wait); + tty_port_init(&sx_port[i].port); spin_lock_init(&sx_port[i].lock); } @@ -2452,7 +2227,6 @@ static void sx_release_drivers(void) { func_enter(); - free_page((unsigned long)tmp_buf); tty_unregister_driver(specialix_driver); put_tty_driver(specialix_driver); func_exit(); @@ -2470,14 +2244,14 @@ static int __init specialix_init(void) printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); -#ifdef CONFIG_SPECIALIX_RTSCTS - printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); -#else - printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); -#endif + if (sx_rtscts) + printk(KERN_INFO + "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); + else + printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); for (i = 0; i < SX_NBOARD; i++) - sx_board[i].lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&sx_board[i].lock); if (sx_init_drivers()) { func_exit(); @@ -2492,28 +2266,31 @@ static int __init specialix_init(void) { struct pci_dev *pdev = NULL; - i=0; + i = 0; while (i < SX_NBOARD) { if (sx_board[i].flags & SX_BOARD_PRESENT) { i++; continue; } - pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_IO8, - pdev); - if (!pdev) break; + pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_IO8, pdev); + if (!pdev) + break; if (pci_enable_device(pdev)) continue; sx_board[i].irq = pdev->irq; - sx_board[i].base = pci_resource_start (pdev, 2); + sx_board[i].base = pci_resource_start(pdev, 2); sx_board[i].flags |= SX_BOARD_IS_PCI; if (!sx_probe(&sx_board[i])) - found ++; + found++; } + /* May exit pci_get sequence early with lots of boards */ + if (pdev != NULL) + pci_dev_put(pdev); } #endif @@ -2529,16 +2306,13 @@ static int __init specialix_init(void) } static int iobase[SX_NBOARD] = {0,}; - -static int irq [SX_NBOARD] = {0,}; +static int irq[SX_NBOARD] = {0,}; module_param_array(iobase, int, NULL, 0); module_param_array(irq, int, NULL, 0); module_param(sx_debug, int, 0); +module_param(sx_rtscts, int, 0); module_param(sx_rxfifo, int, 0); -#ifdef SPECIALIX_TIMER -module_param(sx_poll, int, 0); -#endif /* * You can setup up to 4 boards. @@ -2556,10 +2330,10 @@ static int __init specialix_init_module(void) func_enter(); if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { - for(i = 0; i < SX_NBOARD; i++) { + for (i = 0; i < SX_NBOARD; i++) { sx_board[i].base = iobase[i]; sx_board[i].irq = irq[i]; - sx_board[i].count= 0; + sx_board[i].count = 0; } } @@ -2578,14 +2352,17 @@ static void __exit specialix_exit_module(void) for (i = 0; i < SX_NBOARD; i++) if (sx_board[i].flags & SX_BOARD_PRESENT) sx_release_io_range(&sx_board[i]); -#ifdef SPECIALIX_TIMER - del_timer (&missed_irq_timer); -#endif - func_exit(); } +static struct pci_device_id specialx_pci_tbl[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) }, + { } +}; +MODULE_DEVICE_TABLE(pci, specialx_pci_tbl); + module_init(specialix_init_module); module_exit(specialix_exit_module); MODULE_LICENSE("GPL"); +MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR);