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) | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /* card->lock MUST NOT be held */ | 330 | /* card->lock MUST NOT be held */ |
331 | static inline void raise_dtr_rts(struct isi_port *port) | 331 | |
332 | static void isicom_raise_dtr_rts(struct tty_port *port) | ||
332 | { | 333 | { |
333 | struct isi_board *card = port->card; | 334 | struct isi_port *ip = container_of(port, struct isi_port, port); |
335 | struct isi_board *card = ip->card; | ||
334 | unsigned long base = card->base; | 336 | unsigned long base = card->base; |
335 | u16 channel = port->channel; | 337 | u16 channel = ip->channel; |
336 | 338 | ||
337 | if (!lock_card(card)) | 339 | if (!lock_card(card)) |
338 | return; | 340 | return; |
@@ -340,7 +342,7 @@ static inline void raise_dtr_rts(struct isi_port *port) | |||
340 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 342 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
341 | outw(0x0f04, base); | 343 | outw(0x0f04, base); |
342 | InterruptTheCard(base); | 344 | InterruptTheCard(base); |
343 | port->status |= (ISI_DTR | ISI_RTS); | 345 | ip->status |= (ISI_DTR | ISI_RTS); |
344 | unlock_card(card); | 346 | unlock_card(card); |
345 | } | 347 | } |
346 | 348 | ||
@@ -830,80 +832,10 @@ static int isicom_setup_port(struct tty_struct *tty) | |||
830 | return 0; | 832 | return 0; |
831 | } | 833 | } |
832 | 834 | ||
833 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | 835 | static int isicom_carrier_raised(struct tty_port *port) |
834 | struct isi_port *port) | ||
835 | { | 836 | { |
836 | struct isi_board *card = port->card; | 837 | struct isi_port *ip = container_of(port, struct isi_port, port); |
837 | int do_clocal = 0, retval; | 838 | return (ip->status & ISI_DCD)?1 : 0; |
838 | unsigned long flags; | ||
839 | DECLARE_WAITQUEUE(wait, current); | ||
840 | |||
841 | /* block if port is in the process of being closed */ | ||
842 | |||
843 | if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) { | ||
844 | pr_dbg("block_til_ready: close in progress.\n"); | ||
845 | interruptible_sleep_on(&port->port.close_wait); | ||
846 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
847 | return -EAGAIN; | ||
848 | else | ||
849 | return -ERESTARTSYS; | ||
850 | } | ||
851 | |||
852 | /* if non-blocking mode is set ... */ | ||
853 | |||
854 | if ((filp->f_flags & O_NONBLOCK) || | ||
855 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
856 | pr_dbg("block_til_ready: non-block mode.\n"); | ||
857 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | if (C_CLOCAL(tty)) | ||
862 | do_clocal = 1; | ||
863 | |||
864 | /* block waiting for DCD to be asserted, and while | ||
865 | callout dev is busy */ | ||
866 | retval = 0; | ||
867 | add_wait_queue(&port->port.open_wait, &wait); | ||
868 | |||
869 | spin_lock_irqsave(&card->card_lock, flags); | ||
870 | if (!tty_hung_up_p(filp)) | ||
871 | port->port.count--; | ||
872 | port->port.blocked_open++; | ||
873 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
874 | |||
875 | while (1) { | ||
876 | raise_dtr_rts(port); | ||
877 | |||
878 | set_current_state(TASK_INTERRUPTIBLE); | ||
879 | if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { | ||
880 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
881 | retval = -EAGAIN; | ||
882 | else | ||
883 | retval = -ERESTARTSYS; | ||
884 | break; | ||
885 | } | ||
886 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
887 | (do_clocal || (port->status & ISI_DCD))) { | ||
888 | break; | ||
889 | } | ||
890 | if (signal_pending(current)) { | ||
891 | retval = -ERESTARTSYS; | ||
892 | break; | ||
893 | } | ||
894 | schedule(); | ||
895 | } | ||
896 | set_current_state(TASK_RUNNING); | ||
897 | remove_wait_queue(&port->port.open_wait, &wait); | ||
898 | spin_lock_irqsave(&card->card_lock, flags); | ||
899 | if (!tty_hung_up_p(filp)) | ||
900 | port->port.count++; | ||
901 | port->port.blocked_open--; | ||
902 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
903 | if (retval) | ||
904 | return retval; | ||
905 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
906 | return 0; | ||
907 | } | 839 | } |
908 | 840 | ||
909 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 841 | 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) | |||
932 | 864 | ||
933 | isicom_setup_board(card); | 865 | isicom_setup_board(card); |
934 | 866 | ||
867 | /* FIXME: locking on port.count etc */ | ||
935 | port->port.count++; | 868 | port->port.count++; |
936 | tty->driver_data = port; | 869 | tty->driver_data = port; |
937 | tty_port_tty_set(&port->port, tty); | 870 | tty_port_tty_set(&port->port, tty); |
938 | error = isicom_setup_port(tty); | 871 | error = isicom_setup_port(tty); |
939 | if (error == 0) | 872 | if (error == 0) |
940 | error = block_til_ready(tty, filp, port); | 873 | error = tty_port_block_til_ready(&port->port, tty, filp); |
941 | return error; | 874 | return error; |
942 | } | 875 | } |
943 | 876 | ||
@@ -1012,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
1012 | 945 | ||
1013 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 946 | static void isicom_close(struct tty_struct *tty, struct file *filp) |
1014 | { | 947 | { |
1015 | struct isi_port *port = tty->driver_data; | 948 | struct isi_port *ip = tty->driver_data; |
949 | struct tty_port *port = &ip->port; | ||
1016 | struct isi_board *card; | 950 | struct isi_board *card; |
1017 | unsigned long flags; | 951 | unsigned long flags; |
1018 | 952 | ||
1019 | if (!port) | 953 | BUG_ON(!ip); |
1020 | return; | ||
1021 | card = port->card; | ||
1022 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) | ||
1023 | return; | ||
1024 | |||
1025 | pr_dbg("Close start!!!.\n"); | ||
1026 | |||
1027 | spin_lock_irqsave(&card->card_lock, flags); | ||
1028 | if (tty_hung_up_p(filp)) { | ||
1029 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1030 | return; | ||
1031 | } | ||
1032 | |||
1033 | if (tty->count == 1 && port->port.count != 1) { | ||
1034 | printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " | ||
1035 | "count tty->count = 1 port count = %d.\n", | ||
1036 | card->base, port->port.count); | ||
1037 | port->port.count = 1; | ||
1038 | } | ||
1039 | if (--port->port.count < 0) { | ||
1040 | printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port " | ||
1041 | "count for channel%d = %d", card->base, port->channel, | ||
1042 | port->port.count); | ||
1043 | port->port.count = 0; | ||
1044 | } | ||
1045 | 954 | ||
1046 | if (port->port.count) { | 955 | card = ip->card; |
1047 | spin_unlock_irqrestore(&card->card_lock, flags); | 956 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) |
1048 | return; | 957 | return; |
1049 | } | ||
1050 | port->port.flags |= ASYNC_CLOSING; | ||
1051 | tty->closing = 1; | ||
1052 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1053 | 958 | ||
1054 | if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1055 | tty_wait_until_sent(tty, port->port.closing_wait); | ||
1056 | /* indicate to the card that no more data can be received | 959 | /* indicate to the card that no more data can be received |
1057 | on this port */ | 960 | on this port */ |
1058 | spin_lock_irqsave(&card->card_lock, flags); | 961 | spin_lock_irqsave(&card->card_lock, flags); |
1059 | if (port->port.flags & ASYNC_INITIALIZED) { | 962 | if (port->flags & ASYNC_INITIALIZED) { |
1060 | card->port_status &= ~(1 << port->channel); | 963 | card->port_status &= ~(1 << ip->channel); |
1061 | outw(card->port_status, card->base + 0x02); | 964 | outw(card->port_status, card->base + 0x02); |
1062 | } | 965 | } |
1063 | isicom_shutdown_port(port); | 966 | isicom_shutdown_port(ip); |
1064 | spin_unlock_irqrestore(&card->card_lock, flags); | 967 | spin_unlock_irqrestore(&card->card_lock, flags); |
1065 | 968 | ||
1066 | isicom_flush_buffer(tty); | 969 | isicom_flush_buffer(tty); |
1067 | tty_ldisc_flush(tty); | 970 | |
1068 | 971 | tty_port_close_end(port, tty); | |
1069 | spin_lock_irqsave(&card->card_lock, flags); | ||
1070 | tty->closing = 0; | ||
1071 | |||
1072 | if (port->port.blocked_open) { | ||
1073 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1074 | if (port->port.close_delay) { | ||
1075 | pr_dbg("scheduling until time out.\n"); | ||
1076 | msleep_interruptible( | ||
1077 | jiffies_to_msecs(port->port.close_delay)); | ||
1078 | } | ||
1079 | spin_lock_irqsave(&card->card_lock, flags); | ||
1080 | wake_up_interruptible(&port->port.open_wait); | ||
1081 | } | ||
1082 | port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
1083 | wake_up_interruptible(&port->port.close_wait); | ||
1084 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1085 | } | 972 | } |
1086 | 973 | ||
1087 | /* write et all */ | 974 | /* write et all */ |
@@ -1420,10 +1307,7 @@ static void isicom_hangup(struct tty_struct *tty) | |||
1420 | isicom_shutdown_port(port); | 1307 | isicom_shutdown_port(port); |
1421 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1308 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1422 | 1309 | ||
1423 | port->port.count = 0; | 1310 | tty_port_hangup(&port->port); |
1424 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1425 | tty_port_tty_set(&port->port, NULL); | ||
1426 | wake_up_interruptible(&port->port.open_wait); | ||
1427 | } | 1311 | } |
1428 | 1312 | ||
1429 | 1313 | ||
@@ -1452,6 +1336,11 @@ static const struct tty_operations isicom_ops = { | |||
1452 | .break_ctl = isicom_send_break, | 1336 | .break_ctl = isicom_send_break, |
1453 | }; | 1337 | }; |
1454 | 1338 | ||
1339 | static const struct tty_port_operations isicom_port_ops = { | ||
1340 | .carrier_raised = isicom_carrier_raised, | ||
1341 | .raise_dtr_rts = isicom_raise_dtr_rts, | ||
1342 | }; | ||
1343 | |||
1455 | static int __devinit reset_card(struct pci_dev *pdev, | 1344 | static int __devinit reset_card(struct pci_dev *pdev, |
1456 | const unsigned int card, unsigned int *signature) | 1345 | const unsigned int card, unsigned int *signature) |
1457 | { | 1346 | { |
@@ -1794,6 +1683,7 @@ static int __init isicom_init(void) | |||
1794 | spin_lock_init(&isi_card[idx].card_lock); | 1683 | spin_lock_init(&isi_card[idx].card_lock); |
1795 | for (channel = 0; channel < 16; channel++, port++) { | 1684 | for (channel = 0; channel < 16; channel++, port++) { |
1796 | tty_port_init(&port->port); | 1685 | tty_port_init(&port->port); |
1686 | port->port.ops = &isicom_port_ops; | ||
1797 | port->magic = ISICOM_MAGIC; | 1687 | port->magic = ISICOM_MAGIC; |
1798 | port->card = &isi_card[idx]; | 1688 | port->card = &isi_card[idx]; |
1799 | port->channel = channel; | 1689 | port->channel = channel; |