aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mxser.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2009-01-02 08:45:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-02 13:19:38 -0500
commit31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch)
tree39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/mxser.c
parentc9b3976e3fec266be25c5001a70aa0a890b6c476 (diff)
tty_port: Add a port level carrier detect operation
This is the first step to generalising the various pieces of waiting logic duplicated in all sorts of serial drivers. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r--drivers/char/mxser.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 047766915411..eafbbcf355e7 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -541,13 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
541 return status; 541 return status;
542} 542}
543 543
544static int mxser_carrier_raised(struct tty_port *port)
545{
546 struct mxser_port *mp = container_of(port, struct mxser_port, port);
547 return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
548}
549
544static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, 550static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
545 struct mxser_port *port) 551 struct mxser_port *mp)
546{ 552{
547 DECLARE_WAITQUEUE(wait, current); 553 DECLARE_WAITQUEUE(wait, current);
548 int retval; 554 int retval;
549 int do_clocal = 0; 555 int do_clocal = 0;
550 unsigned long flags; 556 unsigned long flags;
557 int cd;
558 struct tty_port *port = &mp->port;
551 559
552 /* 560 /*
553 * If non-blocking mode is set, or the port is not enabled, 561 * If non-blocking mode is set, or the port is not enabled,
@@ -555,7 +563,7 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
555 */ 563 */
556 if ((filp->f_flags & O_NONBLOCK) || 564 if ((filp->f_flags & O_NONBLOCK) ||
557 test_bit(TTY_IO_ERROR, &tty->flags)) { 565 test_bit(TTY_IO_ERROR, &tty->flags)) {
558 port->port.flags |= ASYNC_NORMAL_ACTIVE; 566 port->flags |= ASYNC_NORMAL_ACTIVE;
559 return 0; 567 return 0;
560 } 568 }
561 569
@@ -565,34 +573,33 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
565 /* 573 /*
566 * Block waiting for the carrier detect and the line to become 574 * Block waiting for the carrier detect and the line to become
567 * free (i.e., not in use by the callout). While we are in 575 * free (i.e., not in use by the callout). While we are in
568 * this loop, port->port.count is dropped by one, so that 576 * this loop, port->count is dropped by one, so that
569 * mxser_close() knows when to free things. We restore it upon 577 * mxser_close() knows when to free things. We restore it upon
570 * exit, either normal or abnormal. 578 * exit, either normal or abnormal.
571 */ 579 */
572 retval = 0; 580 retval = 0;
573 add_wait_queue(&port->port.open_wait, &wait); 581 add_wait_queue(&port->open_wait, &wait);
574 582
575 spin_lock_irqsave(&port->slock, flags); 583 spin_lock_irqsave(&mp->slock, flags);
576 if (!tty_hung_up_p(filp)) 584 if (!tty_hung_up_p(filp))
577 port->port.count--; 585 port->count--;
578 spin_unlock_irqrestore(&port->slock, flags); 586 spin_unlock_irqrestore(&mp->slock, flags);
579 port->port.blocked_open++; 587 port->blocked_open++;
580 while (1) { 588 while (1) {
581 spin_lock_irqsave(&port->slock, flags); 589 spin_lock_irqsave(&mp->slock, flags);
582 outb(inb(port->ioaddr + UART_MCR) | 590 outb(inb(mp->ioaddr + UART_MCR) |
583 UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); 591 UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
584 spin_unlock_irqrestore(&port->slock, flags); 592 spin_unlock_irqrestore(&mp->slock, flags);
585 set_current_state(TASK_INTERRUPTIBLE); 593 set_current_state(TASK_INTERRUPTIBLE);
586 if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { 594 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
587 if (port->port.flags & ASYNC_HUP_NOTIFY) 595 if (port->flags & ASYNC_HUP_NOTIFY)
588 retval = -EAGAIN; 596 retval = -EAGAIN;
589 else 597 else
590 retval = -ERESTARTSYS; 598 retval = -ERESTARTSYS;
591 break; 599 break;
592 } 600 }
593 if (!(port->port.flags & ASYNC_CLOSING) && 601 cd = tty_port_carrier_raised(port);
594 (do_clocal || 602 if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
595 (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
596 break; 603 break;
597 if (signal_pending(current)) { 604 if (signal_pending(current)) {
598 retval = -ERESTARTSYS; 605 retval = -ERESTARTSYS;
@@ -601,13 +608,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
601 schedule(); 608 schedule();
602 } 609 }
603 set_current_state(TASK_RUNNING); 610 set_current_state(TASK_RUNNING);
604 remove_wait_queue(&port->port.open_wait, &wait); 611 remove_wait_queue(&port->open_wait, &wait);
605 if (!tty_hung_up_p(filp)) 612 if (!tty_hung_up_p(filp))
606 port->port.count++; 613 port->count++;
607 port->port.blocked_open--; 614 port->blocked_open--;
608 if (retval) 615 if (retval)
609 return retval; 616 return retval;
610 port->port.flags |= ASYNC_NORMAL_ACTIVE; 617 port->flags |= ASYNC_NORMAL_ACTIVE;
611 return 0; 618 return 0;
612} 619}
613 620
@@ -2449,6 +2456,10 @@ static const struct tty_operations mxser_ops = {
2449 .tiocmset = mxser_tiocmset, 2456 .tiocmset = mxser_tiocmset,
2450}; 2457};
2451 2458
2459struct tty_port_operations mxser_port_ops = {
2460 .carrier_raised = mxser_carrier_raised,
2461};
2462
2452/* 2463/*
2453 * The MOXA Smartio/Industio serial driver boot-time initialization code! 2464 * The MOXA Smartio/Industio serial driver boot-time initialization code!
2454 */ 2465 */
@@ -2482,6 +2493,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
2482 for (i = 0; i < brd->info->nports; i++) { 2493 for (i = 0; i < brd->info->nports; i++) {
2483 info = &brd->ports[i]; 2494 info = &brd->ports[i];
2484 tty_port_init(&info->port); 2495 tty_port_init(&info->port);
2496 info->port.ops = &mxser_port_ops;
2485 info->board = brd; 2497 info->board = brd;
2486 info->stop_rx = 0; 2498 info->stop_rx = 0;
2487 info->ldisc_stop_rx = 0; 2499 info->ldisc_stop_rx = 0;