diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:45:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:38 -0500 |
commit | 31f35939d1d9bcfb3099b32c67b896d2792603f9 (patch) | |
tree | 39b6ceaf0e7477e0357ff8235814f579adad3f28 /drivers/char/mxser.c | |
parent | c9b3976e3fec266be25c5001a70aa0a890b6c476 (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.c | 54 |
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 | ||
544 | static 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 | |||
544 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | 550 | static 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 | ||
2459 | struct 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; |