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.c163
1 files changed, 81 insertions, 82 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
138static struct pci_device_id isicom_pci_tbl[] = { 149static 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);
161static void isicom_start(struct tty_struct *tty); 172static void isicom_start(struct tty_struct *tty);
162 173
163static unsigned char *tmp_buf; 174static unsigned char *tmp_buf;
164static 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
602static inline int isicom_paranoia_check(struct isi_port const *port, char *name, 612static 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 */
727sched_again: 732sched_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
1789static int __devinit register_drivers(void) 1782static 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; 1809end:
1810 return error;
1818} 1811}
1819 1812
1820static void unregister_drivers(void) 1813static 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)
1936static int io[4]; 1931static int io[4];
1937static int irq[4]; 1932static int irq[4];
1938 1933
1939MODULE_AUTHOR("MultiTech");
1940MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
1941MODULE_LICENSE("GPL");
1942module_param_array(io, int, NULL, 0);
1943MODULE_PARM_DESC(io, "I/O ports for the cards");
1944module_param_array(irq, int, NULL, 0);
1945MODULE_PARM_DESC(irq, "Interrupts for the cards");
1946
1947static int __devinit isicom_setup(void) 1934static 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
2048static void __exit isicom_exit(void) 2035static 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
2062module_init(isicom_setup); 2053module_init(isicom_setup);
2063module_exit(isicom_exit); 2054module_exit(isicom_exit);
2055
2056MODULE_AUTHOR("MultiTech");
2057MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
2058MODULE_LICENSE("GPL");
2059module_param_array(io, int, NULL, 0);
2060MODULE_PARM_DESC(io, "I/O ports for the cards");
2061module_param_array(irq, int, NULL, 0);
2062MODULE_PARM_DESC(irq, "Interrupts for the cards");