]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/ip2/ip2main.c
m32r: fix build due to notify_cpu_starting() change
[linux-2.6-omap-h63xx.git] / drivers / char / ip2 / ip2main.c
index 689f9dcd3b866f1bd6ca9e3a0f707f7b2de9cb39..6774572d3759e19e2c25fca4e623088cf426643a 100644 (file)
@@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
 /*************/
 
 /* String constants to identify ourselves */
-static char *pcName    = "Computone IntelliPort Plus multiport driver";
-static char *pcVersion = "1.2.14";
+static const char pcName[] = "Computone IntelliPort Plus multiport driver";
+static const char pcVersion[] = "1.2.14";
 
 /* String constants for port names */
-static char *pcDriver_name   = "ip2";
-static char *pcIpl              = "ip2ipl";
-
-// cheezy kludge or genius - you decide?
-int ip2_loadmain(int *, int *);
+static const char pcDriver_name[] = "ip2";
+static const char pcIpl[] = "ip2ipl";
 
 /***********************/
 /* Function Prototypes */
@@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = {
        .open           = ip2_ipl_open,
 }; 
 
-static unsigned long irq_counter = 0;
-static unsigned long bh_counter = 0;
+static unsigned long irq_counter;
+static unsigned long bh_counter;
 
 // Use immediate queue to service interrupts
 #define USE_IQI
@@ -252,7 +249,6 @@ static unsigned long bh_counter = 0;
  */
 #define  POLL_TIMEOUT   (jiffies + 1)
 static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-static char  TimerOn;
 
 #ifdef IP2DEBUG_TRACE
 /* Trace (debug) buffer data */
@@ -268,8 +264,8 @@ static int tracewrap;
 /**********/
 
 #if defined(MODULE) && defined(IP2DEBUG_OPEN)
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
-                   tty->name,(pCh->flags),ip2_tty_driver->refcount, \
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+                   tty->name,(pCh->flags), \
                    tty->count,/*GET_USE_COUNT(module)*/0,s)
 #else
 #define DBG_CNT(s)
@@ -287,8 +283,9 @@ static int tracewrap;
 
 MODULE_AUTHOR("Doug McNash");
 MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+MODULE_LICENSE("GPL");
 
-static int poll_only = 0;
+static int poll_only;
 
 static int Eisa_irq;
 static int Eisa_slot;
@@ -297,34 +294,46 @@ static int iindx;
 static char rirqs[IP2_MAX_BOARDS];
 static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
 
+/* Note: Add compiled in defaults to these arrays, not to the structure
+       in ip2.h any longer.  That structure WILL get overridden
+       by these values, or command line values, or insmod values!!!  =mhw=
+*/
+static int io[IP2_MAX_BOARDS];
+static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
+module_param(poll_only, bool, 0);
+MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
+
 /* for sysfs class support */
 static struct class *ip2_class;
 
-// Some functions to keep track of what irq's we have
+/* Some functions to keep track of what irqs we have */
 
-static int
-is_valid_irq(int irq)
+static int __init is_valid_irq(int irq)
 {
        int *i = Valid_Irqs;
        
-       while ((*i != 0) && (*i != irq)) {
+       while (*i != 0 && *i != irq)
                i++;
-       }
-       return (*i);
+
+       return *i;
 }
 
-static void
-mark_requested_irq( char irq )
+static void __init mark_requested_irq(char irq)
 {
        rirqs[iindx++] = irq;
 }
 
-#ifdef MODULE
-static int
-clear_requested_irq( char irq )
+static int __exit clear_requested_irq(char irq)
 {
        int i;
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
                if (rirqs[i] == irq) {
                        rirqs[i] = 0;
                        return 1;
@@ -332,17 +341,15 @@ clear_requested_irq( char irq )
        }
        return 0;
 }
-#endif
 
-static int
-have_requested_irq( char irq )
+static int have_requested_irq(char irq)
 {
-       // array init to zeros so 0 irq will not be requested as a side effect
+       /* array init to zeros so 0 irq will not be requested as a side
+        * effect */
        int i;
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i)
                if (rirqs[i] == irq)
                        return 1;
-       }
        return 0;
 }
 
@@ -361,53 +368,45 @@ have_requested_irq( char irq )
 /* handle subsequent installations of the driver. All memory allocated by the */
 /* driver should be returned since it may be unloaded from memory.            */
 /******************************************************************************/
-#ifdef MODULE
-void __exit
-ip2_cleanup_module(void)
+static void __exit ip2_cleanup_module(void)
 {
        int err;
        int i;
 
-#ifdef IP2DEBUG_INIT
-       printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
-#endif
-       /* Stop poll timer if we had one. */
-       if ( TimerOn ) {
-               del_timer ( &PollTimer );
-               TimerOn = 0;
-       }
+       del_timer_sync(&PollTimer);
 
        /* Reset the boards we have. */
-       for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( i2BoardPtrTable[i] ) {
-                       iiReset( i2BoardPtrTable[i] );
-               }
-       }
+       for (i = 0; i < IP2_MAX_BOARDS; i++)
+               if (i2BoardPtrTable[i])
+                       iiReset(i2BoardPtrTable[i]);
 
        /* The following is done at most once, if any boards were installed. */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( i2BoardPtrTable[i] ) {
-                       iiResetDelay( i2BoardPtrTable[i] );
+       for (i = 0; i < IP2_MAX_BOARDS; i++) {
+               if (i2BoardPtrTable[i]) {
+                       iiResetDelay(i2BoardPtrTable[i]);
                        /* free io addresses and Tibet */
-                       release_region( ip2config.addr[i], 8 );
+                       release_region(ip2config.addr[i], 8);
                        device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
-                       device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+                       device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
+                                               4 * i + 1));
                }
                /* Disable and remove interrupt handler. */
-               if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { 
-                       free_irq ( ip2config.irq[i], (void *)&pcName);
-                       clear_requested_irq( ip2config.irq[i]);
+               if (ip2config.irq[i] > 0 &&
+                               have_requested_irq(ip2config.irq[i])) {
+                       free_irq(ip2config.irq[i], (void *)&pcName);
+                       clear_requested_irq(ip2config.irq[i]);
                }
        }
        class_destroy(ip2_class);
-       if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
-               printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
-       }
+       err = tty_unregister_driver(ip2_tty_driver);
+       if (err)
+               printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
+                               err);
        put_tty_driver(ip2_tty_driver);
        unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
        remove_proc_entry("ip2mem", NULL);
 
-       // free memory
+       /* free memory */
        for (i = 0; i < IP2_MAX_BOARDS; i++) {
                void *pB;
 #ifdef CONFIG_PCI
@@ -417,24 +416,18 @@ ip2_cleanup_module(void)
                        ip2config.pci_dev[i] = NULL;
                }
 #endif
-               if ((pB = i2BoardPtrTable[i]) != 0 ) {
-                       kfree ( pB );
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       kfree(pB);
                        i2BoardPtrTable[i] = NULL;
                }
-               if ((DevTableMem[i]) != NULL ) {
-                       kfree ( DevTableMem[i]  );
+               if (DevTableMem[i] != NULL) {
+                       kfree(DevTableMem[i]);
                        DevTableMem[i] = NULL;
                }
        }
-
-       /* Cleanup the iiEllis subsystem. */
-       iiEllisCleanup();
-#ifdef IP2DEBUG_INIT
-       printk (KERN_DEBUG "IP2 Unloaded\n" );
-#endif
 }
 module_exit(ip2_cleanup_module);
-#endif /* MODULE */
 
 static const struct tty_operations ip2_ops = {
        .open            = ip2_open,
@@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void)
        return fw;
 }
 
-int
-ip2_loadmain(int *iop, int *irqp)
+#ifndef MODULE
+/******************************************************************************
+ *     ip2_setup:
+ *             str: kernel command line string
+ *
+ *     Can't autoprobe the boards so user must specify configuration on
+ *     kernel command line.  Sane people build it modular but the others
+ *     come here.
+ *
+ *     Alternating pairs of io,irq for up to 4 boards.
+ *             ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
+ *
+ *             io=0 => No board
+ *             io=1 => PCI
+ *             io=2 => EISA
+ *             else => ISA I/O address
+ *
+ *             irq=0 or invalid for ISA will revert to polling mode
+ *
+ *             Any value = -1, do not overwrite compiled in value.
+ *
+ ******************************************************************************/
+static int __init ip2_setup(char *str)
+{
+       int j, ints[10];        /* 4 boards, 2 parameters + 2 */
+       unsigned int i;
+
+       str = get_options(str, ARRAY_SIZE(ints), ints);
+
+       for (i = 0, j = 1; i < 4; i++) {
+               if (j > ints[0])
+                       break;
+               if (ints[j] >= 0)
+                       io[i] = ints[j];
+               j++;
+               if (j > ints[0])
+                       break;
+               if (ints[j] >= 0)
+                       irq[i] = ints[j];
+               j++;
+       }
+       return 1;
+}
+__setup("ip2=", ip2_setup);
+#endif /* !MODULE */
+
+static int __init ip2_loadmain(void)
 {
        int i, j, box;
        int err = 0;
-       static int loaded;
        i2eBordStrPtr pB = NULL;
        int rc = -1;
-       static struct pci_dev *pci_dev_i = NULL;
+       struct pci_dev *pdev = NULL;
        const struct firmware *fw = NULL;
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
+       if (poll_only) {
+               /* Hard lock the interrupts to zero */
+               irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
+       }
+
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
 
        /* process command line arguments to modprobe or
                insmod i.e. iop & irqp */
        /* irqp and iop should ALWAYS be specified now...  But we check
                them individually just to be sure, anyways... */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if (iop) {
-                       ip2config.addr[i] = iop[i];
-                       if (irqp) {
-                               if( irqp[i] >= 0 ) {
-                                       ip2config.irq[i] = irqp[i];
-                               } else {
-                                       ip2config.irq[i] = 0;
-                               }
-       // This is a little bit of a hack.  If poll_only=1 on command
-       // line back in ip2.c OR all IRQs on all specified boards are
-       // explicitly set to 0, then drop to poll only mode and override
-       // PCI or EISA interrupts.  This superceeds the old hack of
-       // triggering if all interrupts were zero (like da default).
-       // Still a hack but less prone to random acts of terrorism.
-       //
-       // What we really should do, now that the IRQ default is set
-       // to -1, is to use 0 as a hard coded, do not probe.
-       //
-       //      /\/\|=mhw=|\/\/
-                               poll_only |= irqp[i];
-                       }
-               }
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               ip2config.addr[i] = io[i];
+               if (irq[i] >= 0)
+                       ip2config.irq[i] = irq[i];
+               else
+                       ip2config.irq[i] = 0;
+       /* This is a little bit of a hack.  If poll_only=1 on command
+          line back in ip2.c OR all IRQs on all specified boards are
+          explicitly set to 0, then drop to poll only mode and override
+          PCI or EISA interrupts.  This superceeds the old hack of
+          triggering if all interrupts were zero (like da default).
+          Still a hack but less prone to random acts of terrorism.
+
+          What we really should do, now that the IRQ default is set
+          to -1, is to use 0 as a hard coded, do not probe.
+
+               /\/\|=mhw=|\/\/
+       */
+               poll_only |= irq[i];
        }
        poll_only = !poll_only;
 
        /* Announce our presence */
-       printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
-
-       // ip2 can be unloaded and reloaded for no good reason
-       // we can't let that happen here or bad things happen
-       // second load hoses board but not system - fixme later
-       if (loaded) {
-               printk( KERN_INFO "Still loaded\n" );
-               return 0;
-       }
-       loaded++;
+       printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
 
        ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
        if (!ip2_tty_driver)
                return -ENOMEM;
 
-       /* Initialise the iiEllis subsystem. */
-       iiEllisInit();
-
-       /* Initialize arrays. */
-       memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
-       memset( DevTable, 0, sizeof DevTable );
-
        /* Initialise all the boards we can find (up to the maximum). */
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               switch ( ip2config.addr[i] ) { 
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               switch (ip2config.addr[i]) {
                case 0: /* skip this slot even if card is present */
                        break;
                default: /* ISA */
                   /* ISA address must be specified */
-                       if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
-                               printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
-                                                        i, ip2config.addr[i] );
+                       if (ip2config.addr[i] < 0x100 ||
+                                       ip2config.addr[i] > 0x3f8) {
+                               printk(KERN_ERR "IP2: Bad ISA board %d "
+                                               "address %x\n", i,
+                                               ip2config.addr[i]);
                                ip2config.addr[i] = 0;
-                       } else {
-                               ip2config.type[i] = ISA;
-
-                               /* Check for valid irq argument, set for polling if invalid */
-                               if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
-                                       printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
-                                       ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
-                               }
+                               break;
+                       }
+                       ip2config.type[i] = ISA;
+
+                       /* Check for valid irq argument, set for polling if
+                        * invalid */
+                       if (ip2config.irq[i] &&
+                                       !is_valid_irq(ip2config.irq[i])) {
+                               printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
+                                               ip2config.irq[i]);
+                               /* 0 is polling and is valid in that sense */
+                               ip2config.irq[i] = 0;
                        }
                        break;
                case PCI:
 #ifdef CONFIG_PCI
-                       {
-                               int status;
+               {
+                       u32 addr;
+                       int status;
 
-                               pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
-                                                         PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
-                               if (pci_dev_i != NULL) {
-                                       unsigned int addr;
-
-                                       if (pci_enable_device(pci_dev_i)) {
-                                               printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
-                                                       pci_name(pci_dev_i));
-                                               break;
-                                       }
-                                       ip2config.type[i] = PCI;
-                                       ip2config.pci_dev[i] = pci_dev_get(pci_dev_i);
-                                       status =
-                                       pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
-                                       if ( addr & 1 ) {
-                                               ip2config.addr[i]=(USHORT)(addr&0xfffe);
-                                       } else {
-                                               printk( KERN_ERR "IP2: PCI I/O address error\n");
-                                       }
+                       pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
+                                       PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
+                       if (pdev == NULL) {
+                               ip2config.addr[i] = 0;
+                               printk(KERN_ERR "IP2: PCI board %d not "
+                                               "found\n", i);
+                               break;
+                       }
 
-//             If the PCI BIOS assigned it, lets try and use it.  If we
-//             can't acquire it or it screws up, deal with it then.
-
-//                                     if (!is_valid_irq(pci_irq)) {
-//                                             printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
-//                                             pci_irq = 0;
-//                                     }
-                                       ip2config.irq[i] = pci_dev_i->irq;
-                               } else {        // ann error
-                                       ip2config.addr[i] = 0;
-                                       printk(KERN_ERR "IP2: PCI board %d not found\n", i);
-                               } 
+                       if (pci_enable_device(pdev)) {
+                               dev_err(&pdev->dev, "can't enable device\n");
+                               break;
                        }
+                       ip2config.type[i] = PCI;
+                       ip2config.pci_dev[i] = pci_dev_get(pdev);
+                       status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
+                                       &addr);
+                       if (addr & 1)
+                               ip2config.addr[i] = (USHORT)(addr & 0xfffe);
+                       else
+                               dev_err(&pdev->dev, "I/O address error\n");
+
+                       ip2config.irq[i] = pdev->irq;
+               }
 #else
-                       printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
-                       printk( KERN_ERR "IP2: configured in this kernel.\n");
-                       printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
+                       printk(KERN_ERR "IP2: PCI card specified but PCI "
+                                       "support not enabled.\n");
+                       printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
+                                       "defined!\n");
 #endif /* CONFIG_PCI */
                        break;
                case EISA:
-                       if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
+                       ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
+                       if (ip2config.addr[i] != 0) {
                                /* Eisa_irq set as side effect, boo */
                                ip2config.type[i] = EISA;
                        } 
@@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp)
                        break;
                }       /* switch */
        }       /* for */
-       if (pci_dev_i)
-               pci_dev_put(pci_dev_i);
+       pci_dev_put(pdev);
 
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( ip2config.addr[i] ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (ip2config.addr[i]) {
                        pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
                        if (pB) {
                                i2BoardPtrTable[i] = pB;
-                               iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
-                               iiReset( pB );
-                       } else {
-                               printk(KERN_ERR "IP2: board memory allocation error\n");
-                       }
+                               iiSetAddress(pB, ip2config.addr[i],
+                                               ii2DelayTimer);
+                               iiReset(pB);
+                       } else
+                               printk(KERN_ERR "IP2: board memory allocation "
+                                               "error\n");
                }
        }
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-               if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
-                       iiResetDelay( pB );
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       iiResetDelay(pB);
                        break;
                }
        }
-       for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
                /* We don't want to request the firmware unless we have at
                   least one board */
-               if ( i2BoardPtrTable[i] != NULL ) {
+               if (i2BoardPtrTable[i] != NULL) {
                        if (!fw)
                                fw = ip2_request_firmware();
                        if (!fw)
@@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp)
        if (fw)
                release_firmware(fw);
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
 
        ip2_tty_driver->owner               = THIS_MODULE;
        ip2_tty_driver->name                 = "ttyF";
@@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp)
        ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
        ip2_tty_driver->init_termios         = tty_std_termios;
        ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-       ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+       ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
+               TTY_DRIVER_DYNAMIC_DEV;
        tty_set_operations(ip2_tty_driver, &ip2_ops);
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
 
-       /* Register the tty devices. */
-       if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) {
-               printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
+       err = tty_register_driver(ip2_tty_driver);
+       if (err) {
+               printk(KERN_ERR "IP2: failed to register tty driver\n");
                put_tty_driver(ip2_tty_driver);
-               return -EINVAL;
-       } else
-       /* Register the IPL driver. */
-       if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
-               printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
+               return err; /* leaking resources */
+       }
+
+       err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
+       if (err) {
+               printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
+                               err);
        } else {
                /* create the sysfs class */
                ip2_class = class_create(THIS_MODULE, "ip2");
@@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp)
        /* Register the read_procmem thing */
        if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
                printk(KERN_ERR "IP2: failed to register read_procmem\n");
-       } else {
+               return -EIO; /* leaking resources */
+       }
 
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
-               /* Register the interrupt handler or poll handler, depending upon the
-                * specified interrupt.
-                */
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
+       /* Register the interrupt handler or poll handler, depending upon the
+        * specified interrupt.
+        */
 
-               for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-                       if ( 0 == ip2config.addr[i] ) {
-                               continue;
-                       }
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (ip2config.addr[i] == 0)
+                       continue;
 
-                       if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-                               device_create_drvdata(ip2_class, NULL,
-                                                     MKDEV(IP2_IPL_MAJOR, 4 * i),
-                                                     NULL, "ipl%d", i);
-                               device_create_drvdata(ip2_class, NULL,
-                                                     MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-                                                     NULL, "stat%d", i);
-
-                           for ( box = 0; box < ABS_MAX_BOXES; ++box )
-                           {
-                               for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
-                               {
-                                   if ( pB->i2eChannelMap[box] & (1 << j) )
-                                   {
-                                       tty_register_device(ip2_tty_driver,
-                                           j + ABS_BIGGEST_BOX *
-                                                   (box+i*ABS_MAX_BOXES), NULL);
-                                   }
-                               }
-                           }
-                       }
+               pB = i2BoardPtrTable[i];
+               if (pB != NULL) {
+                       device_create_drvdata(ip2_class, NULL,
+                                             MKDEV(IP2_IPL_MAJOR, 4 * i),
+                                             NULL, "ipl%d", i);
+                       device_create_drvdata(ip2_class, NULL,
+                                             MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+                                             NULL, "stat%d", i);
+
+                       for (box = 0; box < ABS_MAX_BOXES; box++)
+                               for (j = 0; j < ABS_BIGGEST_BOX; j++)
+                                       if (pB->i2eChannelMap[box] & (1 << j))
+                                               tty_register_device(
+                                                       ip2_tty_driver,
+                                                       j + ABS_BIGGEST_BOX *
+                                                       (box+i*ABS_MAX_BOXES),
+                                                       NULL);
+               }
 
-                       if (poll_only) {
-//             Poll only forces driver to only use polling and
-//             to ignore the probed PCI or EISA interrupts.
-                               ip2config.irq[i] = CIR_POLL;
-                       }
-                       if ( ip2config.irq[i] == CIR_POLL ) {
+               if (poll_only) {
+                       /* Poll only forces driver to only use polling and
+                          to ignore the probed PCI or EISA interrupts. */
+                       ip2config.irq[i] = CIR_POLL;
+               }
+               if (ip2config.irq[i] == CIR_POLL) {
 retry:
-                               if (!TimerOn) {
-                                       PollTimer.expires = POLL_TIMEOUT;
-                                       add_timer ( &PollTimer );
-                                       TimerOn = 1;
-                                       printk( KERN_INFO "IP2: polling\n");
-                               }
-                       } else {
-                               if (have_requested_irq(ip2config.irq[i]))
-                                       continue;
-                               rc = request_irq( ip2config.irq[i], ip2_interrupt,
-                                       IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
-                                       pcName, i2BoardPtrTable[i]);
-                               if (rc) {
-                                       printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
-                                       ip2config.irq[i] = CIR_POLL;
-                                       printk( KERN_INFO "IP2: Polling %ld/sec.\n",
-                                                       (POLL_TIMEOUT - jiffies));
-                                       goto retry;
-                               } 
-                               mark_requested_irq(ip2config.irq[i]);
-                               /* Initialise the interrupt handler bottom half (aka slih). */
+                       if (!timer_pending(&PollTimer)) {
+                               mod_timer(&PollTimer, POLL_TIMEOUT);
+                               printk(KERN_INFO "IP2: polling\n");
                        }
-               }
-               for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-                       if ( i2BoardPtrTable[i] ) {
-                               set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
+               } else {
+                       if (have_requested_irq(ip2config.irq[i]))
+                               continue;
+                       rc = request_irq(ip2config.irq[i], ip2_interrupt,
+                               IP2_SA_FLAGS |
+                               (ip2config.type[i] == PCI ? IRQF_SHARED : 0),
+                               pcName, i2BoardPtrTable[i]);
+                       if (rc) {
+                               printk(KERN_ERR "IP2: request_irq failed: "
+                                               "error %d\n", rc);
+                               ip2config.irq[i] = CIR_POLL;
+                               printk(KERN_INFO "IP2: Polling %ld/sec.\n",
+                                               (POLL_TIMEOUT - jiffies));
+                               goto retry;
                        }
+                       mark_requested_irq(ip2config.irq[i]);
+                       /* Initialise the interrupt handler bottom half
+                        * (aka slih). */
                }
        }
-       ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
-       goto out;
+
+       for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+               if (i2BoardPtrTable[i]) {
+                       /* set and enable board interrupt */
+                       set_irq(i, ip2config.irq[i]);
+               }
+       }
+
+       ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
+
+       return 0;
 
 out_chrdev:
        unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-out:
+       /* unregister and put tty here */
        return err;
 }
+module_init(ip2_loadmain);
 
 /******************************************************************************/
 /* Function:   ip2_init_board()                                               */
@@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void)
 {
        int i;
        i2eBordStrPtr  pB;
-       const int irq = 0;
 
-       ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
+       ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
 
        /* Service just the boards on the list using this irq */
        for( i = 0; i < i2nBoards; ++i ) {
@@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void)
 //             Only process those boards which match our IRQ.
 //                     IRQ = 0 for polled boards, we won't poll "IRQ" boards
 
-               if ( pB && (pB->i2eUsingIrq == irq) ) {
+               if (pB && pB->i2eUsingIrq == 0)
                        ip2_irq_work(pB);
-               }
        }
 
        ++irq_counter;
@@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg)
 {
        ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
 
-       TimerOn = 0; // it's the truth but not checked in service
-
        // Just polled boards, IRQ = 0 will hit all non-interrupt boards.
        // It will NOT poll boards handled by hard interrupts.
        // The issue of queued BH interrupts is handled in ip2_interrupt().
        ip2_polled_interrupt();
 
-       PollTimer.expires = POLL_TIMEOUT;
-       add_timer( &PollTimer );
-       TimerOn = 1;
+       mod_timer(&PollTimer, POLL_TIMEOUT);
 
        ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
 }
@@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
        case 13:
                switch ( cmd ) {
                case 64:        /* Driver - ip2stat */
-                       rc = put_user(ip2_tty_driver->refcount, pIndex++ );
+                       rc = put_user(-1, pIndex++ );
                        rc = put_user(irq_counter, pIndex++  );
                        rc = put_user(bh_counter, pIndex++  );
                        break;