diff options
-rw-r--r-- | drivers/char/isicom.c | 163 | ||||
-rw-r--r-- | include/linux/isicom.h | 3 |
2 files changed, 81 insertions, 85 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 9ede7c211cc1..49f88c9006cb 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -135,6 +135,17 @@ | |||
135 | 135 | ||
136 | #include <linux/isicom.h> | 136 | #include <linux/isicom.h> |
137 | 137 | ||
138 | #define InterruptTheCard(base) outw(0, (base) + 0xc) | ||
139 | #define ClearInterrupt(base) inw((base) + 0x0a) | ||
140 | |||
141 | #ifdef DEBUG | ||
142 | #define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str) | ||
143 | #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) | ||
144 | #else | ||
145 | #define pr_dbg(str...) do { } while (0) | ||
146 | #define isicom_paranoia_check(a, b, c) 0 | ||
147 | #endif | ||
148 | |||
138 | static struct pci_device_id isicom_pci_tbl[] = { | 149 | static struct pci_device_id isicom_pci_tbl[] = { |
139 | { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 150 | { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
140 | { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 151 | { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
@@ -161,7 +172,6 @@ static void isicom_tx(unsigned long _data); | |||
161 | static void isicom_start(struct tty_struct *tty); | 172 | static void isicom_start(struct tty_struct *tty); |
162 | 173 | ||
163 | static unsigned char *tmp_buf; | 174 | static unsigned char *tmp_buf; |
164 | static DECLARE_MUTEX(tmp_buf_sem); | ||
165 | 175 | ||
166 | /* baud index mappings from linux defns to isi */ | 176 | /* baud index mappings from linux defns to isi */ |
167 | 177 | ||
@@ -599,23 +609,20 @@ static int ISILoad_ioctl(struct inode *inode, struct file *filp, | |||
599 | * | 609 | * |
600 | */ | 610 | */ |
601 | 611 | ||
602 | static inline int isicom_paranoia_check(struct isi_port const *port, char *name, | 612 | static inline int __isicom_paranoia_check(struct isi_port const *port, |
603 | const char *routine) | 613 | char *name, const char *routine) |
604 | { | 614 | { |
605 | #ifdef ISICOM_DEBUG | ||
606 | static const char *badmagic = | ||
607 | KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n"; | ||
608 | static const char *badport = | ||
609 | KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n"; | ||
610 | if (!port) { | 615 | if (!port) { |
611 | printk(badport, name, routine); | 616 | printk(KERN_WARNING "ISICOM: Warning: bad isicom magic for " |
617 | "dev %s in %s.\n", name, routine); | ||
612 | return 1; | 618 | return 1; |
613 | } | 619 | } |
614 | if (port->magic != ISICOM_MAGIC) { | 620 | if (port->magic != ISICOM_MAGIC) { |
615 | printk(badmagic, name, routine); | 621 | printk(KERN_WARNING "ISICOM: Warning: NULL isicom port for " |
622 | "dev %s in %s.\n", name, routine); | ||
616 | return 1; | 623 | return 1; |
617 | } | 624 | } |
618 | #endif | 625 | |
619 | return 0; | 626 | return 0; |
620 | } | 627 | } |
621 | 628 | ||
@@ -674,12 +681,10 @@ static void isicom_tx(unsigned long _data) | |||
674 | unlock_card(&isi_card[card]); | 681 | unlock_card(&isi_card[card]); |
675 | continue; | 682 | continue; |
676 | } | 683 | } |
677 | #ifdef ISICOM_DEBUG | 684 | pr_dbg("txing %d bytes, port%d.\n", txcount, |
678 | printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", | 685 | port->channel + 1); |
679 | txcount, port->channel+1); | 686 | outw((port->channel << isi_card[card].shift_count) | txcount, |
680 | #endif | 687 | base); |
681 | outw((port->channel << isi_card[card].shift_count) | txcount | ||
682 | , base); | ||
683 | residue = NO; | 688 | residue = NO; |
684 | wrd = 0; | 689 | wrd = 0; |
685 | while (1) { | 690 | while (1) { |
@@ -725,8 +730,11 @@ static void isicom_tx(unsigned long _data) | |||
725 | 730 | ||
726 | /* schedule another tx for hopefully in about 10ms */ | 731 | /* schedule another tx for hopefully in about 10ms */ |
727 | sched_again: | 732 | sched_again: |
728 | if (!re_schedule) | 733 | if (!re_schedule) { |
729 | return; | 734 | re_schedule = 2; |
735 | return; | ||
736 | } | ||
737 | |||
730 | init_timer(&tx); | 738 | init_timer(&tx); |
731 | tx.expires = jiffies + HZ/100; | 739 | tx.expires = jiffies + HZ/100; |
732 | tx.data = 0; | 740 | tx.data = 0; |
@@ -830,9 +838,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
830 | if (port->status & ISI_DCD) { | 838 | if (port->status & ISI_DCD) { |
831 | if (!(header & ISI_DCD)) { | 839 | if (!(header & ISI_DCD)) { |
832 | /* Carrier has been lost */ | 840 | /* Carrier has been lost */ |
833 | #ifdef ISICOM_DEBUG | 841 | pr_dbg("interrupt: DCD->low.\n"); |
834 | printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n"); | ||
835 | #endif | ||
836 | port->status &= ~ISI_DCD; | 842 | port->status &= ~ISI_DCD; |
837 | schedule_work(&port->hangup_tq); | 843 | schedule_work(&port->hangup_tq); |
838 | } | 844 | } |
@@ -840,9 +846,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
840 | else { | 846 | else { |
841 | if (header & ISI_DCD) { | 847 | if (header & ISI_DCD) { |
842 | /* Carrier has been detected */ | 848 | /* Carrier has been detected */ |
843 | #ifdef ISICOM_DEBUG | 849 | pr_dbg("interrupt: DCD->high.\n"); |
844 | printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n"); | ||
845 | #endif | ||
846 | port->status |= ISI_DCD; | 850 | port->status |= ISI_DCD; |
847 | wake_up_interruptible(&port->open_wait); | 851 | wake_up_interruptible(&port->open_wait); |
848 | } | 852 | } |
@@ -899,21 +903,18 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
899 | break; | 903 | break; |
900 | 904 | ||
901 | case 2: /* Statistics */ | 905 | case 2: /* Statistics */ |
902 | printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n"); | 906 | pr_dbg("isicom_interrupt: stats!!!.\n"); |
903 | break; | 907 | break; |
904 | 908 | ||
905 | default: | 909 | default: |
906 | printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n"); | 910 | pr_dbg("Intr: Unknown code in status packet.\n"); |
907 | break; | 911 | break; |
908 | } | 912 | } |
909 | } | 913 | } |
910 | else { /* Data Packet */ | 914 | else { /* Data Packet */ |
911 | 915 | ||
912 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); | 916 | count = tty_prepare_flip_string(tty, &rp, byte_count & ~1); |
913 | #ifdef ISICOM_DEBUG | 917 | pr_dbg("Intr: Can rx %d of %d bytes.\n", count, byte_count); |
914 | printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", | ||
915 | count, byte_count); | ||
916 | #endif | ||
917 | word_count = count >> 1; | 918 | word_count = count >> 1; |
918 | insw(base, rp, word_count); | 919 | insw(base, rp, word_count); |
919 | byte_count -= (word_count << 1); | 920 | byte_count -= (word_count << 1); |
@@ -922,8 +923,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
922 | byte_count -= 2; | 923 | byte_count -= 2; |
923 | } | 924 | } |
924 | if (byte_count > 0) { | 925 | if (byte_count > 0) { |
925 | printk(KERN_DEBUG "ISICOM: Intr(0x%lx:%d): Flip buffer overflow! dropping bytes...\n", | 926 | pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping " |
926 | base, channel+1); | 927 | "bytes...\n", base, channel + 1); |
927 | while(byte_count > 0) { /* drain out unread xtra data */ | 928 | while(byte_count > 0) { /* drain out unread xtra data */ |
928 | inw(base); | 929 | inw(base); |
929 | byte_count -= 2; | 930 | byte_count -= 2; |
@@ -1116,9 +1117,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, struct isi | |||
1116 | /* block if port is in the process of being closed */ | 1117 | /* block if port is in the process of being closed */ |
1117 | 1118 | ||
1118 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 1119 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
1119 | #ifdef ISICOM_DEBUG | 1120 | pr_dbg("block_til_ready: close in progress.\n"); |
1120 | printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n"); | ||
1121 | #endif | ||
1122 | interruptible_sleep_on(&port->close_wait); | 1121 | interruptible_sleep_on(&port->close_wait); |
1123 | if (port->flags & ASYNC_HUP_NOTIFY) | 1122 | if (port->flags & ASYNC_HUP_NOTIFY) |
1124 | return -EAGAIN; | 1123 | return -EAGAIN; |
@@ -1129,9 +1128,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, struct isi | |||
1129 | /* if non-blocking mode is set ... */ | 1128 | /* if non-blocking mode is set ... */ |
1130 | 1129 | ||
1131 | if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { | 1130 | if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { |
1132 | #ifdef ISICOM_DEBUG | 1131 | pr_dbg("block_til_ready: non-block mode.\n"); |
1133 | printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n"); | ||
1134 | #endif | ||
1135 | port->flags |= ASYNC_NORMAL_ACTIVE; | 1132 | port->flags |= ASYNC_NORMAL_ACTIVE; |
1136 | return 0; | 1133 | return 0; |
1137 | } | 1134 | } |
@@ -1271,7 +1268,7 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
1271 | set_bit(TTY_IO_ERROR, &tty->flags); | 1268 | set_bit(TTY_IO_ERROR, &tty->flags); |
1272 | 1269 | ||
1273 | if (--card->count < 0) { | 1270 | if (--card->count < 0) { |
1274 | printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 1271 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", |
1275 | card->base, card->count); | 1272 | card->base, card->count); |
1276 | card->count = 0; | 1273 | card->count = 0; |
1277 | } | 1274 | } |
@@ -1294,9 +1291,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp) | |||
1294 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) | 1291 | if (isicom_paranoia_check(port, tty->name, "isicom_close")) |
1295 | return; | 1292 | return; |
1296 | 1293 | ||
1297 | #ifdef ISICOM_DEBUG | 1294 | pr_dbg("Close start!!!.\n"); |
1298 | printk(KERN_DEBUG "ISICOM: Close start!!!.\n"); | ||
1299 | #endif | ||
1300 | 1295 | ||
1301 | spin_lock_irqsave(&card->card_lock, flags); | 1296 | spin_lock_irqsave(&card->card_lock, flags); |
1302 | if (tty_hung_up_p(filp)) { | 1297 | if (tty_hung_up_p(filp)) { |
@@ -1347,9 +1342,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp) | |||
1347 | if (port->blocked_open) { | 1342 | if (port->blocked_open) { |
1348 | spin_unlock_irqrestore(&card->card_lock, flags); | 1343 | spin_unlock_irqrestore(&card->card_lock, flags); |
1349 | if (port->close_delay) { | 1344 | if (port->close_delay) { |
1350 | #ifdef ISICOM_DEBUG | 1345 | pr_dbg("scheduling until time out.\n"); |
1351 | printk(KERN_DEBUG "ISICOM: scheduling until time out.\n"); | ||
1352 | #endif | ||
1353 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); | 1346 | msleep_interruptible(jiffies_to_msecs(port->close_delay)); |
1354 | } | 1347 | } |
1355 | spin_lock_irqsave(&card->card_lock, flags); | 1348 | spin_lock_irqsave(&card->card_lock, flags); |
@@ -1786,42 +1779,44 @@ static struct tty_operations isicom_ops = { | |||
1786 | .tiocmset = isicom_tiocmset, | 1779 | .tiocmset = isicom_tiocmset, |
1787 | }; | 1780 | }; |
1788 | 1781 | ||
1789 | static int __devinit register_drivers(void) | 1782 | static int __devinit isicom_register_tty_driver(void) |
1790 | { | 1783 | { |
1791 | int error; | 1784 | int error = -ENOMEM; |
1792 | 1785 | ||
1793 | /* tty driver structure initialization */ | 1786 | /* tty driver structure initialization */ |
1794 | isicom_normal = alloc_tty_driver(PORT_COUNT); | 1787 | isicom_normal = alloc_tty_driver(PORT_COUNT); |
1795 | if (!isicom_normal) | 1788 | if (!isicom_normal) |
1796 | return -ENOMEM; | 1789 | goto end; |
1797 | 1790 | ||
1798 | isicom_normal->owner = THIS_MODULE; | 1791 | isicom_normal->owner = THIS_MODULE; |
1799 | isicom_normal->name = "ttyM"; | 1792 | isicom_normal->name = "ttyM"; |
1800 | isicom_normal->devfs_name = "isicom/"; | 1793 | isicom_normal->devfs_name = "isicom/"; |
1801 | isicom_normal->major = ISICOM_NMAJOR; | 1794 | isicom_normal->major = ISICOM_NMAJOR; |
1802 | isicom_normal->minor_start = 0; | 1795 | isicom_normal->minor_start = 0; |
1803 | isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; | 1796 | isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; |
1804 | isicom_normal->subtype = SERIAL_TYPE_NORMAL; | 1797 | isicom_normal->subtype = SERIAL_TYPE_NORMAL; |
1805 | isicom_normal->init_termios = tty_std_termios; | 1798 | isicom_normal->init_termios = tty_std_termios; |
1806 | isicom_normal->init_termios.c_cflag = | 1799 | isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | |
1807 | B9600 | CS8 | CREAD | HUPCL |CLOCAL; | 1800 | CLOCAL; |
1808 | isicom_normal->flags = TTY_DRIVER_REAL_RAW; | 1801 | isicom_normal->flags = TTY_DRIVER_REAL_RAW; |
1809 | tty_set_operations(isicom_normal, &isicom_ops); | 1802 | tty_set_operations(isicom_normal, &isicom_ops); |
1810 | 1803 | ||
1811 | if ((error=tty_register_driver(isicom_normal))!=0) { | 1804 | if ((error = tty_register_driver(isicom_normal))) { |
1812 | printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n", | 1805 | pr_dbg("Couldn't register the dialin driver, error=%d\n", |
1813 | error); | 1806 | error); |
1814 | put_tty_driver(isicom_normal); | 1807 | put_tty_driver(isicom_normal); |
1815 | return error; | ||
1816 | } | 1808 | } |
1817 | return 0; | 1809 | end: |
1810 | return error; | ||
1818 | } | 1811 | } |
1819 | 1812 | ||
1820 | static void unregister_drivers(void) | 1813 | static void isicom_unregister_tty_driver(void) |
1821 | { | 1814 | { |
1822 | int error = tty_unregister_driver(isicom_normal); | 1815 | int error; |
1823 | if (error) | 1816 | |
1824 | printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error); | 1817 | if ((error = tty_unregister_driver(isicom_normal))) |
1818 | pr_dbg("couldn't unregister normal driver, error=%d.\n", error); | ||
1819 | |||
1825 | put_tty_driver(isicom_normal); | 1820 | put_tty_driver(isicom_normal); |
1826 | } | 1821 | } |
1827 | 1822 | ||
@@ -1891,7 +1886,7 @@ static int __devinit isicom_init(void) | |||
1891 | free_page((unsigned long)tmp_buf); | 1886 | free_page((unsigned long)tmp_buf); |
1892 | return 0; | 1887 | return 0; |
1893 | } | 1888 | } |
1894 | if (register_drivers()) | 1889 | if (isicom_register_tty_driver()) |
1895 | { | 1890 | { |
1896 | unregister_ioregion(); | 1891 | unregister_ioregion(); |
1897 | free_page((unsigned long)tmp_buf); | 1892 | free_page((unsigned long)tmp_buf); |
@@ -1899,7 +1894,7 @@ static int __devinit isicom_init(void) | |||
1899 | } | 1894 | } |
1900 | if (!register_isr()) | 1895 | if (!register_isr()) |
1901 | { | 1896 | { |
1902 | unregister_drivers(); | 1897 | isicom_unregister_tty_driver(); |
1903 | /* ioports already uregistered in register_isr */ | 1898 | /* ioports already uregistered in register_isr */ |
1904 | free_page((unsigned long)tmp_buf); | 1899 | free_page((unsigned long)tmp_buf); |
1905 | return 0; | 1900 | return 0; |
@@ -1936,14 +1931,6 @@ static int __devinit isicom_init(void) | |||
1936 | static int io[4]; | 1931 | static int io[4]; |
1937 | static int irq[4]; | 1932 | static int irq[4]; |
1938 | 1933 | ||
1939 | MODULE_AUTHOR("MultiTech"); | ||
1940 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); | ||
1941 | MODULE_LICENSE("GPL"); | ||
1942 | module_param_array(io, int, NULL, 0); | ||
1943 | MODULE_PARM_DESC(io, "I/O ports for the cards"); | ||
1944 | module_param_array(irq, int, NULL, 0); | ||
1945 | MODULE_PARM_DESC(irq, "Interrupts for the cards"); | ||
1946 | |||
1947 | static int __devinit isicom_setup(void) | 1934 | static int __devinit isicom_setup(void) |
1948 | { | 1935 | { |
1949 | struct pci_dev *dev = NULL; | 1936 | struct pci_dev *dev = NULL; |
@@ -2047,11 +2034,15 @@ static int __devinit isicom_setup(void) | |||
2047 | 2034 | ||
2048 | static void __exit isicom_exit(void) | 2035 | static void __exit isicom_exit(void) |
2049 | { | 2036 | { |
2037 | unsigned int index = 0; | ||
2038 | |||
2050 | re_schedule = 0; | 2039 | re_schedule = 0; |
2051 | /* FIXME */ | 2040 | |
2052 | msleep(1000); | 2041 | while (re_schedule != 2 && index++ < 100) |
2042 | msleep(10); | ||
2043 | |||
2053 | unregister_isr(); | 2044 | unregister_isr(); |
2054 | unregister_drivers(); | 2045 | isicom_unregister_tty_driver(); |
2055 | unregister_ioregion(); | 2046 | unregister_ioregion(); |
2056 | if (tmp_buf) | 2047 | if (tmp_buf) |
2057 | free_page((unsigned long)tmp_buf); | 2048 | free_page((unsigned long)tmp_buf); |
@@ -2061,3 +2052,11 @@ static void __exit isicom_exit(void) | |||
2061 | 2052 | ||
2062 | module_init(isicom_setup); | 2053 | module_init(isicom_setup); |
2063 | module_exit(isicom_exit); | 2054 | module_exit(isicom_exit); |
2055 | |||
2056 | MODULE_AUTHOR("MultiTech"); | ||
2057 | MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech"); | ||
2058 | MODULE_LICENSE("GPL"); | ||
2059 | module_param_array(io, int, NULL, 0); | ||
2060 | MODULE_PARM_DESC(io, "I/O ports for the cards"); | ||
2061 | module_param_array(irq, int, NULL, 0); | ||
2062 | MODULE_PARM_DESC(irq, "Interrupts for the cards"); | ||
diff --git a/include/linux/isicom.h b/include/linux/isicom.h index 7c6eae7f6ed7..06cb7baa6db8 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h | |||
@@ -98,9 +98,6 @@ typedef struct { | |||
98 | #define ISICOM_INITIATE_XONXOFF 0x04 | 98 | #define ISICOM_INITIATE_XONXOFF 0x04 |
99 | #define ISICOM_RESPOND_XONXOFF 0x08 | 99 | #define ISICOM_RESPOND_XONXOFF 0x08 |
100 | 100 | ||
101 | #define InterruptTheCard(base) (outw(0,(base)+0xc)) | ||
102 | #define ClearInterrupt(base) (inw((base)+0x0a)) | ||
103 | |||
104 | #define BOARD(line) (((line) >> 4) & 0x3) | 101 | #define BOARD(line) (((line) >> 4) & 0x3) |
105 | 102 | ||
106 | /* isi kill queue bitmap */ | 103 | /* isi kill queue bitmap */ |