diff options
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r-- | drivers/char/isicom.c | 166 |
1 files changed, 28 insertions, 138 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 04e4549299ba..24aa6e88e223 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -328,11 +328,13 @@ static inline void drop_rts(struct isi_port *port) } /* card->lock MUST NOT be held */ -static inline void raise_dtr_rts(struct isi_port *port) + +static void isicom_raise_dtr_rts(struct tty_port *port) { - struct isi_board *card = port->card; + struct isi_port *ip = container_of(port, struct isi_port, port); + struct isi_board *card = ip->card; unsigned long base = card->base; - u16 channel = port->channel; + u16 channel = ip->channel; if (!lock_card(card)) return; @@ -340,7 +342,7 @@ static inline void raise_dtr_rts(struct isi_port *port) outw(0x8000 | (channel << card->shift_count) | 0x02, base); outw(0x0f04, base); InterruptTheCard(base); - port->status |= (ISI_DTR | ISI_RTS); + ip->status |= (ISI_DTR | ISI_RTS); unlock_card(card); } @@ -830,80 +832,10 @@ static int isicom_setup_port(struct tty_struct *tty) return 0; } -static int block_til_ready(struct tty_struct *tty, struct file *filp, - struct isi_port *port) +static int isicom_carrier_raised(struct tty_port *port) { - struct isi_board *card = port->card; - int do_clocal = 0, retval; - unsigned long flags; - DECLARE_WAITQUEUE(wait, current); - - /* block if port is in the process of being closed */ - - if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { - pr_dbg("block_til_ready: close in progress.\n"); - interruptible_sleep_on(&port->port.close_wait); - if (port->port.flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; - } - - /* if non-blocking mode is set ... */ - - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - pr_dbg("block_til_ready: non-block mode.\n"); - port->port.flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (C_CLOCAL(tty)) - do_clocal = 1; - - /* block waiting for DCD to be asserted, and while - callout dev is busy */ - retval = 0; - add_wait_queue(&port->port.open_wait, &wait); - - spin_lock_irqsave(&card->card_lock, flags); - if (!tty_hung_up_p(filp)) - port->port.count--; - port->port.blocked_open++; - spin_unlock_irqrestore(&card->card_lock, flags); - - while (1) { - raise_dtr_rts(port); - - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { - if (port->port.flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->port.flags & ASYNC_CLOSING) && - (do_clocal || (port->status & ISI_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&port->port.open_wait, &wait); - spin_lock_irqsave(&card->card_lock, flags); - if (!tty_hung_up_p(filp)) - port->port.count++; - port->port.blocked_open--; - spin_unlock_irqrestore(&card->card_lock, flags); - if (retval) - return retval; - port->port.flags |= ASYNC_NORMAL_ACTIVE; - return 0; + struct isi_port *ip = container_of(port, struct isi_port, port); + return (ip->status & ISI_DCD)?1 : 0; } static int isicom_open(struct tty_struct *tty, struct file *filp) @@ -932,12 +864,13 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) isicom_setup_board(card); + /* FIXME: locking on port.count etc */ port->port.count++; tty->driver_data = port; tty_port_tty_set(&port->port, tty); error = isicom_setup_port(tty); if (error == 0) - error = block_til_ready(tty, filp, port); + error = tty_port_block_til_ready(&port->port, tty, filp); return error; } @@ -1012,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty) static void isicom_close(struct tty_struct *tty, struct file *filp) { - struct isi_port *port = tty->driver_data; + struct isi_port *ip = tty->driver_data; + struct tty_port *port = &ip->port; struct isi_board *card; unsigned long flags; - if (!port) - return; - card = port->card; - if (isicom_paranoia_check(port, tty->name, "isicom_close")) - return; - - pr_dbg("Close start!!!.\n"); - - spin_lock_irqsave(&card->card_lock, flags); - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&card->card_lock, flags); - return; - } - - if (tty->count == 1 && port->port.count != 1) { - printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " - "count tty->count = 1 port count = %d.\n", - card->base, port->port.count); - port->port.count = 1; - } - if (--port->port.count < 0) { - printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " - "count for channel%d = %d", card->base, port->channel, - port->port.count); - port->port.count = 0; - } + BUG_ON(!ip); - if (port->port.count) { - spin_unlock_irqrestore(&card->card_lock, flags); + card = ip->card; + if (isicom_paranoia_check(ip, tty->name, "isicom_close")) return; - } - port->port.flags |= ASYNC_CLOSING; - tty->closing = 1; - spin_unlock_irqrestore(&card->card_lock, flags); - if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->port.closing_wait); /* indicate to the card that no more data can be received on this port */ spin_lock_irqsave(&card->card_lock, flags); - if (port->port.flags & ASYNC_INITIALIZED) { - card->port_status &= ~(1 << port->channel); + if (port->flags & ASYNC_INITIALIZED) { + card->port_status &= ~(1 << ip->channel); outw(card->port_status, card->base + 0x02); } - isicom_shutdown_port(port); + isicom_shutdown_port(ip); spin_unlock_irqrestore(&card->card_lock, flags); isicom_flush_buffer(tty); - tty_ldisc_flush(tty); - - spin_lock_irqsave(&card->card_lock, flags); - tty->closing = 0; - - if (port->port.blocked_open) { - spin_unlock_irqrestore(&card->card_lock, flags); - if (port->port.close_delay) { - pr_dbg("scheduling until time out.\n"); - msleep_interruptible( - jiffies_to_msecs(port->port.close_delay)); - } - spin_lock_irqsave(&card->card_lock, flags); - wake_up_interruptible(&port->port.open_wait); - } - port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); - wake_up_interruptible(&port->port.close_wait); - spin_unlock_irqrestore(&card->card_lock, flags); + + tty_port_close_end(port, tty); } /* write et all */ @@ -1420,10 +1307,7 @@ static void isicom_hangup(struct tty_struct *tty) isicom_shutdown_port(port); spin_unlock_irqrestore(&port->card->card_lock, flags); - port->port.count = 0; - port->port.flags &= ~ASYNC_NORMAL_ACTIVE; - tty_port_tty_set(&port->port, NULL); - wake_up_interruptible(&port->port.open_wait); + tty_port_hangup(&port->port); } @@ -1452,6 +1336,11 @@ static const struct tty_operations isicom_ops = { .break_ctl = isicom_send_break, }; +static const struct tty_port_operations isicom_port_ops = { + .carrier_raised = isicom_carrier_raised, + .raise_dtr_rts = isicom_raise_dtr_rts, +}; + static int __devinit reset_card(struct pci_dev *pdev, const unsigned int card, unsigned int *signature) { @@ -1794,6 +1683,7 @@ static int __init isicom_init(void) spin_lock_init(&isi_card[idx].card_lock); for (channel = 0; channel < 16; channel++, port++) { tty_port_init(&port->port); + port->port.ops = &isicom_port_ops; port->magic = ISICOM_MAGIC; port->card = &isi_card[idx]; port->channel = channel; |