Loading drivers/char/epca.c +158 −118 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ #include <linux/slab.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include <asm/io.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/spinlock.h> #include <linux/pci.h> #include "digiPCI.h" Loading Loading @@ -73,7 +73,8 @@ static int invalid_lilo_config; */ static DEFINE_SPINLOCK(epca_lock); /* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */ /* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */ static struct board_info boards[MAXBOARDS]; static struct tty_driver *pc_driver; Loading Loading @@ -185,7 +186,7 @@ static void pc_throttle(struct tty_struct * tty); static void pc_unthrottle(struct tty_struct *tty); static void digi_send_break(struct channel *ch, int msec); static void setup_empty_event(struct tty_struct *tty, struct channel *ch); void epca_setup(char *, int *); static void epca_setup(char *, int *); static int pc_write(struct tty_struct *, const unsigned char *, int); static int pc_init(void); Loading Loading @@ -393,7 +394,7 @@ static struct channel *verifyChannel(struct tty_struct *tty) */ if (tty) { struct channel *ch = (struct channel *)tty->driver_data; if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) { if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { if (ch->magic == EPCA_MAGIC) return ch; } Loading Loading @@ -424,7 +425,8 @@ static void pc_close(struct tty_struct *tty, struct file *filp) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if (tty_hung_up_p(filp)) { spin_unlock_irqrestore(&epca_lock, flags); Loading @@ -439,7 +441,6 @@ static void pc_close(struct tty_struct *tty, struct file *filp) spin_unlock_irqrestore(&epca_lock, flags); return; } /* Port open only once go ahead with shutdown & reset */ BUG_ON(ch->count < 0); Loading @@ -454,9 +455,11 @@ static void pc_close(struct tty_struct *tty, struct file *filp) spin_unlock_irqrestore(&epca_lock, flags); if (ch->asyncflags & ASYNC_INITIALIZED) { /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ setup_empty_event(tty, ch); tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ /* 30 seconds timeout */ tty_wait_until_sent(tty, 3000); } pc_flush_buffer(tty); Loading Loading @@ -522,12 +525,12 @@ static void shutdown(struct channel *ch) static void pc_hangup(struct tty_struct *tty) { struct channel *ch; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; pc_flush_buffer(tty); Loading Loading @@ -569,7 +572,8 @@ static int pc_write(struct tty_struct *tty, * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return 0; /* Make a pointer to the channel data structure found on the board. */ Loading Loading @@ -644,19 +648,17 @@ static int pc_write(struct tty_struct *tty, static int pc_write_room(struct tty_struct *tty) { int remain; int remain = 0; struct channel *ch; unsigned long flags; unsigned int head, tail; struct board_chan __iomem *bc; remain = 0; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); Loading @@ -668,8 +670,8 @@ static int pc_write_room(struct tty_struct *tty) tail = readw(&bc->tout); /* Wrap tail if necessary */ tail &= (ch->txbufsize - 1); if ((remain = tail - head - 1) < 0 ) remain = tail - head - 1; if (remain < 0) remain += ch->txbufsize; if (remain && (ch->statusflags & LOWWAIT) == 0) { Loading @@ -691,12 +693,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty) unsigned long flags; struct channel *ch; struct board_chan __iomem *bc; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return 0; spin_lock_irqsave(&epca_lock, flags); Loading @@ -707,7 +709,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty) head = readw(&bc->tin); ctail = readw(&ch->mailbox->cout); if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) chars = 0; else { /* Begin if some space on the card has been used */ head = readw(&bc->tin) & (ch->txbufsize - 1); Loading @@ -717,7 +720,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty) * pc_write_room here we are finding the amount of bytes in the * buffer filled. Not the amount of bytes empty. */ if ((remain = tail - head - 1) < 0 ) remain = tail - head - 1; if (remain < 0) remain += ch->txbufsize; chars = (int)(ch->txbufsize - remain); /* Loading Loading @@ -746,7 +750,8 @@ static void pc_flush_buffer(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return; spin_lock_irqsave(&epca_lock, flags); Loading @@ -767,14 +772,16 @@ static void pc_flush_chars(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; spin_lock_irqsave(&epca_lock, flags); /* * If not already set and the transmitter is busy setup an * event to indicate when the transmit empties. */ if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); } Loading Loading @@ -831,8 +838,7 @@ static int block_til_ready(struct tty_struct *tty, while (1) { set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(ch->asyncflags & ASYNC_INITIALIZED)) { !(ch->asyncflags & ASYNC_INITIALIZED)) { if (ch->asyncflags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else Loading Loading @@ -995,8 +1001,8 @@ static void __exit epca_module_exit(void) del_timer_sync(&epca_timer); if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info)) { if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info)) { printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); return; } Loading Loading @@ -1323,7 +1329,7 @@ static void post_fep_init(unsigned int crd) } else { /* Fix up the mappings for ISA/EISA etc */ /* FIXME: 64K - can we be smarter ? */ bd->re_map_membase = ioremap(bd->membase, 0x10000); bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000); } if (crd != 0) Loading Loading @@ -1354,7 +1360,8 @@ static void post_fep_init(unsigned int crd) * XEPORTS (address 0xc22) points at the number of channels the card * supports. (For 64XE, XI, XEM, and XR use 0xc02) */ if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) shrinkmem = 1; if (bd->type < PCIXEM) if (!request_region((int)bd->port, 4, board_desc[bd->type])) Loading Loading @@ -1453,9 +1460,11 @@ static void post_fep_init(unsigned int crd) case PCXEVE: case PCXE: ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9); break; Loading Loading @@ -1511,7 +1520,8 @@ static void post_fep_init(unsigned int crd) printk(KERN_INFO "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); memwinoff(bd, 0); } Loading @@ -1519,7 +1529,7 @@ static void epcapoll(unsigned long ignored) { unsigned long flags; int crd; volatile unsigned int head, tail; unsigned int head, tail; struct channel *ch; struct board_info *bd; Loading Loading @@ -1585,7 +1595,9 @@ static void doevent(int crd) chan0 = card_ptr[crd]; epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); assertgwinon(chan0); while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */ while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */ assertgwinon(chan0); eventbuf = bd->re_map_membase + tail + ISTART; /* Get the channel the event occurred on */ Loading @@ -1609,7 +1621,8 @@ static void doevent(int crd) goto next; } if ((bc = ch->brdchan) == NULL) bc = ch->brdchan; if (bc == NULL) goto next; if (event & DATA_IND) { /* Begin DATA_IND */ Loading @@ -1621,10 +1634,11 @@ static void doevent(int crd) /* A modem signal change has been indicated */ ch->imodem = mstat; if (ch->asyncflags & ASYNC_CHECK_CD) { if (mstat & ch->dcd) /* We are now receiving dcd */ /* We are now receiving dcd */ if (mstat & ch->dcd) wake_up_interruptible(&ch->open_wait); else pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ else /* No dcd; hangup */ pc_sched_event(ch, EPCA_EVENT_HANGUP); } } tty = ch->tty; Loading @@ -1639,7 +1653,8 @@ static void doevent(int crd) tty_wakeup(tty); } } else if (event & EMPTYTX_IND) { /* This event is generated by setup_empty_event */ /* This event is generated by setup_empty_event */ ch->statusflags &= ~TXBUSY; if (ch->statusflags & EMPTYWAIT) { ch->statusflags &= ~EMPTYWAIT; Loading Loading @@ -1682,8 +1697,10 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, memaddr = ch->board->re_map_membase; if (head >= (cmdMax - cmdStart) || (head & 03)) { printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); return; } if (bytecmd) { Loading Loading @@ -1876,8 +1893,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) * Command sets channels iflag structure on the board. Such * things as input soft flow control, handling of parity * errors, and break handling are all set here. * * break handling, parity handling, input stripping, * flow control chars */ /* break handling, parity handling, input stripping, flow control chars */ fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); } /* Loading Loading @@ -1983,18 +2002,21 @@ static void receive_data(struct channel *ch) if (readb(&bc->orun)) { writeb(0, &bc->orun); printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name); printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n", tty->name); tty_insert_flip_char(tty, 0, TTY_OVERRUN); } rxwinon(ch); while (bytesAvailable > 0) { /* Begin while there is data on the card */ while (bytesAvailable > 0) { /* Begin while there is data on the card */ wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; /* * Even if head has wrapped around only report the amount of * data to be equal to the size - tail. Remember memcpy can't * automaticly wrap around the receive buffer. */ dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; /* Make sure we don't overflow the buffer */ dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead); if (dataToRead == 0) Loading Loading @@ -2167,7 +2189,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, bc = ch->brdchan; else return -EINVAL; /* * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in * /usr/src/linux/drivers/char for a good example. In particular think Loading @@ -2178,7 +2199,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, retval = tty_check_change(tty); if (retval) return retval; /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading @@ -2190,8 +2212,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, retval = tty_check_change(tty); if (retval) return retval; /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading Loading @@ -2232,7 +2254,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, case DIGI_SETAF: lock_kernel(); if (cmd == DIGI_SETAW) { /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading Loading @@ -2300,18 +2323,21 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, if (copy_from_user(&dflow, argp, sizeof(dflow))) return -EFAULT; if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); if (cmd == DIGI_SETFLOW) { ch->fepstartc = ch->startc = dflow.startc; ch->fepstopc = ch->stopc = dflow.stopc; fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); } else { ch->fepstartca = ch->startca = dflow.startc; ch->fepstopca = ch->stopca = dflow.stopc; fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); } if (ch->statusflags & TXSTOPPED) Loading @@ -2335,7 +2361,9 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ ch = verifyChannel(tty); if (ch != NULL) { /* Begin if channel valid */ spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); epcaparam(tty, ch); Loading @@ -2362,7 +2390,7 @@ static void do_softint(struct work_struct *work) if (tty && tty->driver_data) { if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { tty_hangup(tty); /* FIXME: module removal race here - AKPM */ tty_hangup(tty); wake_up_interruptible(&ch->open_wait); ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; } Loading @@ -2382,9 +2410,11 @@ static void pc_stop(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ globalwinon(ch); /* STOP transmitting now !! */ fepcmd(ch, PAUSETX, 0, 0, 0, 0); Loading @@ -2402,11 +2432,14 @@ static void pc_start(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; spin_lock_irqsave(&epca_lock, flags); /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ struct board_chan __iomem *bc; globalwinon(ch); bc = ch->brdchan; Loading Loading @@ -2436,7 +2469,8 @@ static void pc_throttle(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if ((ch->statusflags & RXSTOPPED) == 0) { globalwinon(ch); Loading @@ -2456,8 +2490,10 @@ static void pc_unthrottle(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { /* Just in case output was resumed because of a change in Digi-flow */ ch = verifyChannel(tty); if (ch != NULL) { /* Just in case output was resumed because of a change in Digi-flow */ spin_lock_irqsave(&epca_lock, flags); if (ch->statusflags & RXSTOPPED) { globalwinon(ch); Loading Loading @@ -2502,7 +2538,7 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch) memoff(ch); } void epca_setup(char *str, int *ints) static void epca_setup(char *str, int *ints) { struct board_info board; int index, loop, last; Loading Loading @@ -2531,14 +2567,16 @@ void epca_setup(char *str, int *ints) * instructing the driver to ignore epcaconfig.) For * this reason we check for 2. */ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ nbdevs = 0; num_cards = 0; return; } /* End ignore epcaconfig as well as lilo cmd line */ if (board.status > 2) { printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_STATUS; return; Loading Loading @@ -2592,7 +2630,8 @@ void epca_setup(char *str, int *ints) case 6: board.membase = ints[index]; if (ints[index] <= 0) { printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n", (unsigned int)board.membase); invalid_lilo_config = 1; setup_error_code |= INVALID_MEM_BASE; return; Loading Loading @@ -2805,7 +2844,8 @@ static int __devinit epca_init_one(struct pci_dev *pdev, goto err_out; } boards[board_idx].re_map_port = ioremap(addr + PCI_IO_OFFSET, 0x200000); boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET, 0x200000); if (!boards[board_idx].re_map_port) { printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", 0x200000, addr + PCI_IO_OFFSET); Loading @@ -2818,7 +2858,7 @@ static int __devinit epca_init_one(struct pci_dev *pdev, goto err_out_free_iounmap; } boards[board_idx].re_map_membase = ioremap(addr, 0x200000); boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000); if (!boards[board_idx].re_map_membase) { printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", 0x200000, addr + PCI_IO_OFFSET); Loading Loading
drivers/char/epca.c +158 −118 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ #include <linux/slab.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include <asm/io.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/spinlock.h> #include <linux/pci.h> #include "digiPCI.h" Loading Loading @@ -73,7 +73,8 @@ static int invalid_lilo_config; */ static DEFINE_SPINLOCK(epca_lock); /* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */ /* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */ static struct board_info boards[MAXBOARDS]; static struct tty_driver *pc_driver; Loading Loading @@ -185,7 +186,7 @@ static void pc_throttle(struct tty_struct * tty); static void pc_unthrottle(struct tty_struct *tty); static void digi_send_break(struct channel *ch, int msec); static void setup_empty_event(struct tty_struct *tty, struct channel *ch); void epca_setup(char *, int *); static void epca_setup(char *, int *); static int pc_write(struct tty_struct *, const unsigned char *, int); static int pc_init(void); Loading Loading @@ -393,7 +394,7 @@ static struct channel *verifyChannel(struct tty_struct *tty) */ if (tty) { struct channel *ch = (struct channel *)tty->driver_data; if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) { if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) { if (ch->magic == EPCA_MAGIC) return ch; } Loading Loading @@ -424,7 +425,8 @@ static void pc_close(struct tty_struct *tty, struct file *filp) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if (tty_hung_up_p(filp)) { spin_unlock_irqrestore(&epca_lock, flags); Loading @@ -439,7 +441,6 @@ static void pc_close(struct tty_struct *tty, struct file *filp) spin_unlock_irqrestore(&epca_lock, flags); return; } /* Port open only once go ahead with shutdown & reset */ BUG_ON(ch->count < 0); Loading @@ -454,9 +455,11 @@ static void pc_close(struct tty_struct *tty, struct file *filp) spin_unlock_irqrestore(&epca_lock, flags); if (ch->asyncflags & ASYNC_INITIALIZED) { /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ setup_empty_event(tty, ch); tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ /* 30 seconds timeout */ tty_wait_until_sent(tty, 3000); } pc_flush_buffer(tty); Loading Loading @@ -522,12 +525,12 @@ static void shutdown(struct channel *ch) static void pc_hangup(struct tty_struct *tty) { struct channel *ch; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; pc_flush_buffer(tty); Loading Loading @@ -569,7 +572,8 @@ static int pc_write(struct tty_struct *tty, * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return 0; /* Make a pointer to the channel data structure found on the board. */ Loading Loading @@ -644,19 +648,17 @@ static int pc_write(struct tty_struct *tty, static int pc_write_room(struct tty_struct *tty) { int remain; int remain = 0; struct channel *ch; unsigned long flags; unsigned int head, tail; struct board_chan __iomem *bc; remain = 0; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); Loading @@ -668,8 +670,8 @@ static int pc_write_room(struct tty_struct *tty) tail = readw(&bc->tout); /* Wrap tail if necessary */ tail &= (ch->txbufsize - 1); if ((remain = tail - head - 1) < 0 ) remain = tail - head - 1; if (remain < 0) remain += ch->txbufsize; if (remain && (ch->statusflags & LOWWAIT) == 0) { Loading @@ -691,12 +693,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty) unsigned long flags; struct channel *ch; struct board_chan __iomem *bc; /* * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return 0; spin_lock_irqsave(&epca_lock, flags); Loading @@ -707,7 +709,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty) head = readw(&bc->tin); ctail = readw(&ch->mailbox->cout); if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0) chars = 0; else { /* Begin if some space on the card has been used */ head = readw(&bc->tin) & (ch->txbufsize - 1); Loading @@ -717,7 +720,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty) * pc_write_room here we are finding the amount of bytes in the * buffer filled. Not the amount of bytes empty. */ if ((remain = tail - head - 1) < 0 ) remain = tail - head - 1; if (remain < 0) remain += ch->txbufsize; chars = (int)(ch->txbufsize - remain); /* Loading Loading @@ -746,7 +750,8 @@ static void pc_flush_buffer(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) == NULL) ch = verifyChannel(tty); if (ch == NULL) return; spin_lock_irqsave(&epca_lock, flags); Loading @@ -767,14 +772,16 @@ static void pc_flush_chars(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; spin_lock_irqsave(&epca_lock, flags); /* * If not already set and the transmitter is busy setup an * event to indicate when the transmit empties. */ if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT)) setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); } Loading Loading @@ -831,8 +838,7 @@ static int block_til_ready(struct tty_struct *tty, while (1) { set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || !(ch->asyncflags & ASYNC_INITIALIZED)) { !(ch->asyncflags & ASYNC_INITIALIZED)) { if (ch->asyncflags & ASYNC_HUP_NOTIFY) retval = -EAGAIN; else Loading Loading @@ -995,8 +1001,8 @@ static void __exit epca_module_exit(void) del_timer_sync(&epca_timer); if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info)) { if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info)) { printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n"); return; } Loading Loading @@ -1323,7 +1329,7 @@ static void post_fep_init(unsigned int crd) } else { /* Fix up the mappings for ISA/EISA etc */ /* FIXME: 64K - can we be smarter ? */ bd->re_map_membase = ioremap(bd->membase, 0x10000); bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000); } if (crd != 0) Loading Loading @@ -1354,7 +1360,8 @@ static void post_fep_init(unsigned int crd) * XEPORTS (address 0xc22) points at the number of channels the card * supports. (For 64XE, XI, XEM, and XR use 0xc02) */ if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3)) shrinkmem = 1; if (bd->type < PCIXEM) if (!request_region((int)bd->port, 4, board_desc[bd->type])) Loading Loading @@ -1453,9 +1460,11 @@ static void post_fep_init(unsigned int crd) case PCXEVE: case PCXE: ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9); break; Loading Loading @@ -1511,7 +1520,8 @@ static void post_fep_init(unsigned int crd) printk(KERN_INFO "Digi PC/Xx Driver V%s: %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n", VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports); memwinoff(bd, 0); } Loading @@ -1519,7 +1529,7 @@ static void epcapoll(unsigned long ignored) { unsigned long flags; int crd; volatile unsigned int head, tail; unsigned int head, tail; struct channel *ch; struct board_info *bd; Loading Loading @@ -1585,7 +1595,9 @@ static void doevent(int crd) chan0 = card_ptr[crd]; epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range"); assertgwinon(chan0); while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */ while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */ assertgwinon(chan0); eventbuf = bd->re_map_membase + tail + ISTART; /* Get the channel the event occurred on */ Loading @@ -1609,7 +1621,8 @@ static void doevent(int crd) goto next; } if ((bc = ch->brdchan) == NULL) bc = ch->brdchan; if (bc == NULL) goto next; if (event & DATA_IND) { /* Begin DATA_IND */ Loading @@ -1621,10 +1634,11 @@ static void doevent(int crd) /* A modem signal change has been indicated */ ch->imodem = mstat; if (ch->asyncflags & ASYNC_CHECK_CD) { if (mstat & ch->dcd) /* We are now receiving dcd */ /* We are now receiving dcd */ if (mstat & ch->dcd) wake_up_interruptible(&ch->open_wait); else pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */ else /* No dcd; hangup */ pc_sched_event(ch, EPCA_EVENT_HANGUP); } } tty = ch->tty; Loading @@ -1639,7 +1653,8 @@ static void doevent(int crd) tty_wakeup(tty); } } else if (event & EMPTYTX_IND) { /* This event is generated by setup_empty_event */ /* This event is generated by setup_empty_event */ ch->statusflags &= ~TXBUSY; if (ch->statusflags & EMPTYWAIT) { ch->statusflags &= ~EMPTYWAIT; Loading Loading @@ -1682,8 +1697,10 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte, memaddr = ch->board->re_map_membase; if (head >= (cmdMax - cmdStart) || (head & 03)) { printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__, cmd, head); printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__, cmdMax, cmdStart); return; } if (bytecmd) { Loading Loading @@ -1876,8 +1893,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) * Command sets channels iflag structure on the board. Such * things as input soft flow control, handling of parity * errors, and break handling are all set here. * * break handling, parity handling, input stripping, * flow control chars */ /* break handling, parity handling, input stripping, flow control chars */ fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0); } /* Loading Loading @@ -1983,18 +2002,21 @@ static void receive_data(struct channel *ch) if (readb(&bc->orun)) { writeb(0, &bc->orun); printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name); printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n", tty->name); tty_insert_flip_char(tty, 0, TTY_OVERRUN); } rxwinon(ch); while (bytesAvailable > 0) { /* Begin while there is data on the card */ while (bytesAvailable > 0) { /* Begin while there is data on the card */ wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail; /* * Even if head has wrapped around only report the amount of * data to be equal to the size - tail. Remember memcpy can't * automaticly wrap around the receive buffer. */ dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable; /* Make sure we don't overflow the buffer */ dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead); if (dataToRead == 0) Loading Loading @@ -2167,7 +2189,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, bc = ch->brdchan; else return -EINVAL; /* * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in * /usr/src/linux/drivers/char for a good example. In particular think Loading @@ -2178,7 +2199,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, retval = tty_check_change(tty); if (retval) return retval; /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading @@ -2190,8 +2212,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, retval = tty_check_change(tty); if (retval) return retval; /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading Loading @@ -2232,7 +2254,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, case DIGI_SETAF: lock_kernel(); if (cmd == DIGI_SETAW) { /* Setup an event to indicate when the transmit buffer empties */ /* Setup an event to indicate when the transmit buffer empties */ spin_lock_irqsave(&epca_lock, flags); setup_empty_event(tty, ch); spin_unlock_irqrestore(&epca_lock, flags); Loading Loading @@ -2300,18 +2323,21 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, if (copy_from_user(&dflow, argp, sizeof(dflow))) return -EFAULT; if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin if setflow toggled */ spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); if (cmd == DIGI_SETFLOW) { ch->fepstartc = ch->startc = dflow.startc; ch->fepstopc = ch->stopc = dflow.stopc; fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1); } else { ch->fepstartca = ch->startca = dflow.startc; ch->fepstopca = ch->stopca = dflow.stopc; fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1); } if (ch->statusflags & TXSTOPPED) Loading @@ -2335,7 +2361,9 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { /* Begin if channel valid */ ch = verifyChannel(tty); if (ch != NULL) { /* Begin if channel valid */ spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); epcaparam(tty, ch); Loading @@ -2362,7 +2390,7 @@ static void do_softint(struct work_struct *work) if (tty && tty->driver_data) { if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { tty_hangup(tty); /* FIXME: module removal race here - AKPM */ tty_hangup(tty); wake_up_interruptible(&ch->open_wait); ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE; } Loading @@ -2382,9 +2410,11 @@ static void pc_stop(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */ globalwinon(ch); /* STOP transmitting now !! */ fepcmd(ch, PAUSETX, 0, 0, 0, 0); Loading @@ -2402,11 +2432,14 @@ static void pc_start(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; spin_lock_irqsave(&epca_lock, flags); /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ /* Just in case output was resumed because of a change in Digi-flow */ if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ struct board_chan __iomem *bc; globalwinon(ch); bc = ch->brdchan; Loading Loading @@ -2436,7 +2469,8 @@ static void pc_throttle(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { ch = verifyChannel(tty); if (ch != NULL) { spin_lock_irqsave(&epca_lock, flags); if ((ch->statusflags & RXSTOPPED) == 0) { globalwinon(ch); Loading @@ -2456,8 +2490,10 @@ static void pc_unthrottle(struct tty_struct *tty) * verifyChannel returns the channel from the tty struct if it is * valid. This serves as a sanity check. */ if ((ch = verifyChannel(tty)) != NULL) { /* Just in case output was resumed because of a change in Digi-flow */ ch = verifyChannel(tty); if (ch != NULL) { /* Just in case output was resumed because of a change in Digi-flow */ spin_lock_irqsave(&epca_lock, flags); if (ch->statusflags & RXSTOPPED) { globalwinon(ch); Loading Loading @@ -2502,7 +2538,7 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch) memoff(ch); } void epca_setup(char *str, int *ints) static void epca_setup(char *str, int *ints) { struct board_info board; int index, loop, last; Loading Loading @@ -2531,14 +2567,16 @@ void epca_setup(char *str, int *ints) * instructing the driver to ignore epcaconfig.) For * this reason we check for 2. */ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */ nbdevs = 0; num_cards = 0; return; } /* End ignore epcaconfig as well as lilo cmd line */ if (board.status > 2) { printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status); invalid_lilo_config = 1; setup_error_code |= INVALID_BOARD_STATUS; return; Loading Loading @@ -2592,7 +2630,8 @@ void epca_setup(char *str, int *ints) case 6: board.membase = ints[index]; if (ints[index] <= 0) { printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase); printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n", (unsigned int)board.membase); invalid_lilo_config = 1; setup_error_code |= INVALID_MEM_BASE; return; Loading Loading @@ -2805,7 +2844,8 @@ static int __devinit epca_init_one(struct pci_dev *pdev, goto err_out; } boards[board_idx].re_map_port = ioremap(addr + PCI_IO_OFFSET, 0x200000); boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET, 0x200000); if (!boards[board_idx].re_map_port) { printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", 0x200000, addr + PCI_IO_OFFSET); Loading @@ -2818,7 +2858,7 @@ static int __devinit epca_init_one(struct pci_dev *pdev, goto err_out_free_iounmap; } boards[board_idx].re_map_membase = ioremap(addr, 0x200000); boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000); if (!boards[board_idx].re_map_membase) { printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n", 0x200000, addr + PCI_IO_OFFSET); Loading