aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/isicom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r--drivers/char/isicom.c166
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 */
331static inline void raise_dtr_rts(struct isi_port *port) 331
332static 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
833static int block_til_ready(struct tty_struct *tty, struct file *filp, 835static 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
909static int isicom_open(struct tty_struct *tty, struct file *filp) 841static 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
1013static void isicom_close(struct tty_struct *tty, struct file *filp) 946static 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
1339static const struct tty_port_operations isicom_port_ops = {
1340 .carrier_raised = isicom_carrier_raised,
1341 .raise_dtr_rts = isicom_raise_dtr_rts,
1342};
1343
1455static int __devinit reset_card(struct pci_dev *pdev, 1344static 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;