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/riscom8.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/riscom8.c')
-rw-r--r-- | drivers/char/riscom8.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 2c6c8f33d6b4..6ad1c2aa2a98 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -857,23 +857,40 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
857 | rc_shutdown_board(bp); | 857 | rc_shutdown_board(bp); |
858 | } | 858 | } |
859 | 859 | ||
860 | static int carrier_raised(struct tty_port *port) | ||
861 | { | ||
862 | struct riscom_port *p = container_of(port, struct riscom_port, port); | ||
863 | struct riscom_board *bp = port_Board(p); | ||
864 | unsigned long flags; | ||
865 | int CD; | ||
866 | |||
867 | spin_lock_irqsave(&riscom_lock, flags); | ||
868 | rc_out(bp, CD180_CAR, port_No(p)); | ||
869 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | ||
870 | rc_out(bp, CD180_MSVR, MSVR_RTS); | ||
871 | bp->DTR &= ~(1u << port_No(p)); | ||
872 | rc_out(bp, RC_DTR, bp->DTR); | ||
873 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
874 | return CD; | ||
875 | } | ||
876 | |||
860 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 877 | static int block_til_ready(struct tty_struct *tty, struct file *filp, |
861 | struct riscom_port *port) | 878 | struct riscom_port *rp) |
862 | { | 879 | { |
863 | DECLARE_WAITQUEUE(wait, current); | 880 | DECLARE_WAITQUEUE(wait, current); |
864 | struct riscom_board *bp = port_Board(port); | ||
865 | int retval; | 881 | int retval; |
866 | int do_clocal = 0; | 882 | int do_clocal = 0; |
867 | int CD; | 883 | int CD; |
868 | unsigned long flags; | 884 | unsigned long flags; |
885 | struct tty_port *port = &rp->port; | ||
869 | 886 | ||
870 | /* | 887 | /* |
871 | * If the device is in the middle of being closed, then block | 888 | * If the device is in the middle of being closed, then block |
872 | * until it's done, and then try again. | 889 | * until it's done, and then try again. |
873 | */ | 890 | */ |
874 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | 891 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
875 | interruptible_sleep_on(&port->port.close_wait); | 892 | interruptible_sleep_on(&port->close_wait); |
876 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 893 | if (port->flags & ASYNC_HUP_NOTIFY) |
877 | return -EAGAIN; | 894 | return -EAGAIN; |
878 | else | 895 | else |
879 | return -ERESTARTSYS; | 896 | return -ERESTARTSYS; |
@@ -885,7 +902,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
885 | */ | 902 | */ |
886 | if ((filp->f_flags & O_NONBLOCK) || | 903 | if ((filp->f_flags & O_NONBLOCK) || |
887 | (tty->flags & (1 << TTY_IO_ERROR))) { | 904 | (tty->flags & (1 << TTY_IO_ERROR))) { |
888 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 905 | port->flags |= ASYNC_NORMAL_ACTIVE; |
889 | return 0; | 906 | return 0; |
890 | } | 907 | } |
891 | 908 | ||
@@ -900,37 +917,29 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
900 | * exit, either normal or abnormal. | 917 | * exit, either normal or abnormal. |
901 | */ | 918 | */ |
902 | retval = 0; | 919 | retval = 0; |
903 | add_wait_queue(&port->port.open_wait, &wait); | 920 | add_wait_queue(&port->open_wait, &wait); |
904 | 921 | ||
905 | spin_lock_irqsave(&riscom_lock, flags); | 922 | spin_lock_irqsave(&riscom_lock, flags); |
906 | 923 | ||
907 | if (!tty_hung_up_p(filp)) | 924 | if (!tty_hung_up_p(filp)) |
908 | port->port.count--; | 925 | port->count--; |
909 | 926 | ||
910 | spin_unlock_irqrestore(&riscom_lock, flags); | 927 | spin_unlock_irqrestore(&riscom_lock, flags); |
911 | 928 | ||
912 | port->port.blocked_open++; | 929 | port->blocked_open++; |
913 | while (1) { | 930 | while (1) { |
914 | spin_lock_irqsave(&riscom_lock, flags); | ||
915 | |||
916 | rc_out(bp, CD180_CAR, port_No(port)); | ||
917 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | ||
918 | rc_out(bp, CD180_MSVR, MSVR_RTS); | ||
919 | bp->DTR &= ~(1u << port_No(port)); | ||
920 | rc_out(bp, RC_DTR, bp->DTR); | ||
921 | |||
922 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
923 | 931 | ||
932 | CD = tty_port_carrier_raised(port); | ||
924 | set_current_state(TASK_INTERRUPTIBLE); | 933 | set_current_state(TASK_INTERRUPTIBLE); |
925 | if (tty_hung_up_p(filp) || | 934 | if (tty_hung_up_p(filp) || |
926 | !(port->port.flags & ASYNC_INITIALIZED)) { | 935 | !(port->flags & ASYNC_INITIALIZED)) { |
927 | if (port->port.flags & ASYNC_HUP_NOTIFY) | 936 | if (port->flags & ASYNC_HUP_NOTIFY) |
928 | retval = -EAGAIN; | 937 | retval = -EAGAIN; |
929 | else | 938 | else |
930 | retval = -ERESTARTSYS; | 939 | retval = -ERESTARTSYS; |
931 | break; | 940 | break; |
932 | } | 941 | } |
933 | if (!(port->port.flags & ASYNC_CLOSING) && | 942 | if (!(port->flags & ASYNC_CLOSING) && |
934 | (do_clocal || CD)) | 943 | (do_clocal || CD)) |
935 | break; | 944 | break; |
936 | if (signal_pending(current)) { | 945 | if (signal_pending(current)) { |
@@ -940,14 +949,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
940 | schedule(); | 949 | schedule(); |
941 | } | 950 | } |
942 | __set_current_state(TASK_RUNNING); | 951 | __set_current_state(TASK_RUNNING); |
943 | remove_wait_queue(&port->port.open_wait, &wait); | 952 | remove_wait_queue(&port->open_wait, &wait); |
944 | if (!tty_hung_up_p(filp)) | 953 | if (!tty_hung_up_p(filp)) |
945 | port->port.count++; | 954 | port->count++; |
946 | port->port.blocked_open--; | 955 | port->blocked_open--; |
947 | if (retval) | 956 | if (retval) |
948 | return retval; | 957 | return retval; |
949 | 958 | ||
950 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | 959 | port->flags |= ASYNC_NORMAL_ACTIVE; |
951 | return 0; | 960 | return 0; |
952 | } | 961 | } |
953 | 962 | ||
@@ -1510,6 +1519,11 @@ static const struct tty_operations riscom_ops = { | |||
1510 | .break_ctl = rc_send_break, | 1519 | .break_ctl = rc_send_break, |
1511 | }; | 1520 | }; |
1512 | 1521 | ||
1522 | static const struct tty_port_operations riscom_port_ops = { | ||
1523 | .carrier_raised = carrier_raised, | ||
1524 | }; | ||
1525 | |||
1526 | |||
1513 | static int __init rc_init_drivers(void) | 1527 | static int __init rc_init_drivers(void) |
1514 | { | 1528 | { |
1515 | int error; | 1529 | int error; |
@@ -1541,6 +1555,7 @@ static int __init rc_init_drivers(void) | |||
1541 | memset(rc_port, 0, sizeof(rc_port)); | 1555 | memset(rc_port, 0, sizeof(rc_port)); |
1542 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { | 1556 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { |
1543 | tty_port_init(&rc_port[i].port); | 1557 | tty_port_init(&rc_port[i].port); |
1558 | rc_port[i].port.ops = &riscom_port_ops; | ||
1544 | rc_port[i].magic = RISCOM8_MAGIC; | 1559 | rc_port[i].magic = RISCOM8_MAGIC; |
1545 | } | 1560 | } |
1546 | return 0; | 1561 | return 0; |