diff -urN linux-2.6.9-1.6_FC2/Documentation/computone.txt linux-2.6.9-1.6_FC2-ct/Documentation/computone.txt
--- linux-2.6.9-1.6_FC2/Documentation/computone.txt	2004-10-18 17:54:55.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/Documentation/computone.txt	2004-12-22 22:46:29.618565672 -0500
@@ -6,11 +6,11 @@
 These notes are for the drivers which have already been integrated into the
 kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
 
-Version: 1.2.14
-Date: 11/01/2001
+Version: 1.2.18
+Date: 12/22/2004
 Historical Author: Andrew Manison <amanison@america.net>
 Primary Author: Doug McNash
-Support: support@computone.com
+Support: mhw@wittsend.com
 Fixes and Updates: Mike Warfield <mhw@wittsend.com>
 
 This file assumes that you are using the Computone drivers which are
@@ -26,7 +26,7 @@
 products previous to the Intelliport II.
 
 This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.4.14; it will probably not work with earlier v1.X kernels,.
+to v2.6.9; it will probably not work with earlier v1.X kernels,.
 
 
 2. QUICK INSTALLATION
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2/i2cmd.c linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2cmd.c
--- linux-2.6.9-1.6_FC2/drivers/char/ip2/i2cmd.c	2004-10-18 17:53:50.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2cmd.c	2004-12-22 18:52:12.000000000 -0500
@@ -139,7 +139,9 @@
 //static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
 static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
 //static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
+#ifdef	ENABLE_DSSNOW
 static UCHAR ct89[]={ 1, BYP,     0x59                     }; // DSS_NOW
+#endif
 //static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
 //static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
 
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2/i2ellis.c linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2ellis.c
--- linux-2.6.9-1.6_FC2/drivers/char/ip2/i2ellis.c	2004-10-18 17:53:06.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2ellis.c	2004-12-22 21:31:48.000000000 -0500
@@ -606,7 +606,7 @@
 
 	set_current_state( TASK_INTERRUPTIBLE );
 
-	pDelayTimer->expires  = jiffies + ( mseconds + 9 ) / 10;
+	pDelayTimer->expires  = jiffies + msecs_to_jiffies( mseconds );
 	pDelayTimer->function = ii2DelayWakeup;
 	pDelayTimer->data     = 0;
 
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2/i2ellis.h linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2ellis.h
--- linux-2.6.9-1.6_FC2/drivers/char/ip2/i2ellis.h	2004-10-18 17:53:09.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2ellis.h	2004-12-22 18:45:40.000000000 -0500
@@ -403,7 +403,7 @@
 //	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
 	struct work_struct	tqueue_interrupt;
 
-	struct timer_list  SendPendingTimer;   // Used by iiSendPending
+//	struct timer_list  SendPendingTimer;   // Used by iiSendPending
 	unsigned int	SendPendingRetry;
 } i2eBordStr, *i2eBordStrPtr;
 
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2/i2lib.c linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2lib.c
--- linux-2.6.9-1.6_FC2/drivers/char/ip2/i2lib.c	2004-10-18 17:55:29.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2/i2lib.c	2004-12-22 18:48:43.000000000 -0500
@@ -174,8 +174,12 @@
 			pB->i2eWaitingForEmptyFifo |=
 				(pB->i2eOutMailWaiting & MB_OUT_STUFFED);
 			pB->i2eOutMailWaiting = 0;
+			if( pB->SendPendingRetry ) {
+				printk( KERN_DEBUG "IP2: iiSendPendingMail: busy board pickup on %d\n", pB->SendPendingRetry );
+			}
 			pB->SendPendingRetry = 0;
 		} else {
+#ifdef IP2_USE_TIMER_WAIT
 /*		The only time we hit this area is when "iiTrySendMail" has
 		failed.  That only occurs when the outbound mailbox is
 		still busy with the last message.  We take a short breather
@@ -193,6 +197,11 @@
 			} else {
 				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
 			}
+#endif
+			pB->SendPendingRetry++;
+			if( 0 == ( pB->SendPendingRetry % 8 ) ) {
+				printk( KERN_ERR "IP2: iiSendPendingMail: board busy, retry %d\n", pB->SendPendingRetry );
+			}
 		}
 	}
 }
@@ -1325,8 +1334,9 @@
 	remove_wait_queue(&(pCh->pBookmarkWait), &wait);
 
 	// if expires == 0 then timer poped, then do not need to del_timer
+	// jiffy wrap per Tim Schmielau (tim@physik3.uni-rostock.de)
 	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
+			time_before(jiffies, pCh->BookmarkTimer.expires)) {
 		del_timer( &(pCh->BookmarkTimer) );
 		pCh->BookmarkTimer.expires = 0;
 
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2.c linux-2.6.9-1.6_FC2-ct/drivers/char/ip2.c
--- linux-2.6.9-1.6_FC2/drivers/char/ip2.c	2004-10-18 17:54:08.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2.c	2004-12-22 21:22:47.000000000 -0500
@@ -6,6 +6,8 @@
 //  __initdata should work as advertized
 //
 
+// Removed use of __init for declarations in 2.6 kernel...
+
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/init.h>
@@ -46,7 +48,7 @@
 MODULE_PARM_DESC(poll_only,"Do not use card interrupts");
 
 
-static int __init ip2_init(void)
+static int ip2_init(void)
 {
 	if( poll_only ) {
 		/* Hard lock the interrupts to zero */
@@ -55,7 +57,14 @@
 
 	return ip2_loadmain(io,irq,(unsigned char *)fip_firm,sizeof(fip_firm));
 }
+
+static void ip2_exit(void)
+{
+	return;
+}
+
 module_init(ip2_init);
+module_exit(ip2_exit);
 
 MODULE_LICENSE("GPL");
 
@@ -81,7 +90,7 @@
  *		Any value = -1, do not overwrite compiled in value.
  *
  ******************************************************************************/
-static int __init ip2_setup(char *str)
+static int ip2_setup(char *str)
 {
 	int	ints[10];	/* 4 boards, 2 parameters + 2 */
 	int	i, j;
diff -urN linux-2.6.9-1.6_FC2/drivers/char/ip2main.c linux-2.6.9-1.6_FC2-ct/drivers/char/ip2main.c
--- linux-2.6.9-1.6_FC2/drivers/char/ip2main.c	2004-10-18 17:55:36.000000000 -0400
+++ linux-2.6.9-1.6_FC2-ct/drivers/char/ip2main.c	2004-12-22 22:31:24.000000000 -0500
@@ -19,6 +19,30 @@
 //
 // Done:
 //
+// 1.2.18	/\/\|=mhw=|\/\/
+// Removed use of __init macro.  Definition and utilization changed in 2.6
+// Fixed jiffies math in ii2DelayTimer
+//	How long has THIS been broken?  Delay was basically a noop...
+// Removed set_modem_info declaration
+//	(where did the function go???)
+// Cleaned up some comments
+// Dumped some groady tracing code that hasn't been used (or tested) in
+//	years and was only a source of warning messages.
+//
+// 1.2.17	/\/\|=mhw=|\/\/
+// PCI fixes submitted by Bjorn Helgaas
+//	Added calls to Add pci_enable_device()/pci_disable_device() per
+//	submitted patches.  My thanks to Bjorn Helgaas <bjorn.helgaas@hp.com>.
+//
+// 1.2.16	/\/\|=mhw=|\/\/
+// Yet another shot at the busy board timing window (use the poll timer).
+//	Because of this, the poll timer is always enabled...
+// Cleaned up some comments on immediate interrupt mode (ppp code elsewhere
+//	has been fixed and the new busy board logic won't throw a hairball).
+//
+// 1.2.15	dmc
+// Fixed jiffy wrap, PCI card may now be set to poll.
+//
 // 1.2.14	/\/\|=mhw=|\/\/
 // Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
 // Changed the definition of ip2trace to be more consistent with kernel style
@@ -150,7 +174,7 @@
 
 /* String constants to identify ourselves */
 static char *pcName    = "Computone IntelliPort Plus multiport driver";
-static char *pcVersion = "1.2.14";
+static char *pcVersion = "1.2.18";
 
 /* String constants for port names */
 static char *pcDriver_name   = "ip2";
@@ -202,7 +226,6 @@
 static void ip2_wait_until_sent(PTTY,int);
 
 static void set_params (i2ChanStrPtr, struct termios *);
-static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);
 static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
 
@@ -307,7 +330,7 @@
 
 // Some functions to keep track of what irq's we have
 
-static int __init
+static int
 is_valid_irq(int irq)
 {
 	int *i = Valid_Irqs;
@@ -318,14 +341,14 @@
 	return (*i);
 }
 
-static void __init
+static void
 mark_requested_irq( char irq )
 {
 	rirqs[iindx++] = irq;
 }
 
 #ifdef MODULE
-static int __init
+static int
 clear_requested_irq( char irq )
 {
 	int i;
@@ -337,9 +360,9 @@
 	}
 	return 0;
 }
-#endif
+#endif /* MODULE */
 
-static int __init
+static int
 have_requested_irq( char irq )
 {
 	// array init to zeros so 0 irq will not be requested as a side effect
@@ -523,17 +546,12 @@
 		if (iop) {
 			ip2config.addr[i] = iop[i];
 			if (irqp) {
-				if( irqp[i] >= 0 ) {
-					ip2config.irq[i] = irqp[i];
-				} else {
-					ip2config.irq[i] = 0;
-				}
+				ip2config.irq[i] = irqp[i];
 	// 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.
@@ -616,15 +634,8 @@
 						printk( KERN_ERR "IP2: PCI I/O address error\n");
 					}
 
-//		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
+				} else {	// an error
 					ip2config.addr[i] = 0;
 					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
 						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
@@ -789,6 +800,14 @@
 				/* Initialise the interrupt handler bottom half (aka slih). */
 			}
 		}
+
+		if (!TimerOn) {
+//		Kick the timer on for stuck board safeties...
+			PollTimer.expires = POLL_TIMEOUT;
+			add_timer ( &PollTimer );
+			TimerOn = 1;
+		}
+
 		for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
 			if ( i2BoardPtrTable[i] ) {
 				set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
@@ -818,7 +837,7 @@
 /* the board, the channel structures are initialized, and the board details   */
 /* are reported on the console.                                               */
 /******************************************************************************/
-static void __init
+static void
 ip2_init_board( int boardnum )
 {
 	int i;
@@ -961,7 +980,7 @@
 /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
 /* it returns the base address of the controller.                             */
 /******************************************************************************/
-static unsigned short __init
+static unsigned short
 find_eisa_board( int start_slot )
 {
 	int i, j;
@@ -1208,8 +1227,10 @@
 
 //		Only process those boards which match our IRQ.
 //			IRQ = 0 for polled boards, we won't poll "IRQ" boards
+//		Add an additional "check" if the irq is zero for boards
+//		which are "stuck"
 
-		if ( pB && (pB->i2eUsingIrq == irq) ) {
+		if ( pB && ( pB->i2eUsingIrq == irq || ( 0 == irq && 0 != pB->SendPendingRetry ) ) ) {
 			handled = 1;
 #ifdef USE_IQI
 
@@ -1224,9 +1245,8 @@
 //			Make sure the immediate queue is flagged to fire.
 		    }
 #else
-//		We are using immediate servicing here.  This sucks and can
-//		cause all sorts of havoc with ppp and others.  The failsafe
-//		check on iiSendPendingMail could also throw a hairball.
+//		We are using immediate servicing here.  Suboptimal
+//			to say the least...
 			i2ServiceBoard( pB );
 #endif /* USE_IQI */
 		}
@@ -1251,6 +1271,9 @@
 static void
 ip2_poll(unsigned long arg)
 {
+	int i;
+	i2eBordStrPtr	pB;
+
 	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
 
 	TimerOn = 0; // it's the truth but not checked in service
@@ -1258,7 +1281,15 @@
 	// 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 interrups is handled in ip2_interrupt().
-	ip2_interrupt(0, NULL, NULL);
+
+	for( i = 0; i < i2nBoards; ++i ) {
+		pB = i2BoardPtrTable[i];
+	// Service the board if the irq indicates a polled board
+	// OR if the SendPendingRetry indicates a retry state in the board
+		if ( pB && ( 0 == pB->i2eUsingIrq || 0 != pB->SendPendingRetry ) ) {
+			i2ServiceBoard( pB );
+		}
+	}
 
 	PollTimer.expires = POLL_TIMEOUT;
 	add_timer( &PollTimer );
@@ -2002,7 +2033,9 @@
 static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
 {
 	i2ChanStrPtr pCh = DevTable[tty->index];
+#ifdef	ENABLE_DSSNOW
 	wait_queue_t wait;
+#endif
 
 	if (pCh == NULL)
 		return -ENODEV;
@@ -2015,7 +2048,7 @@
 */
 
 /*	This thing is still busted in the 1.2.12 driver on 2.4.x
-	and even hoses the serial console so the oops can be trapped.
+	and even hoses the serial console so the oops can't be trapped.
 		/\/\|=mhw=|\/\/			*/
 
 #ifdef	ENABLE_DSSNOW
@@ -2912,7 +2945,16 @@
 	case 2:	    // Ping device
 		rc = -EINVAL;
 		break;
+
+#ifdef IP2_TRACE_DEVICE
 	case 3:	    // Trace device
+/*
+	This may have been useful at one time during early development
+	but has not been used for years and is just a source of excess
+	baggage and unused code and warnings.  The client programs that
+	understood this returned "blob" don't even currently compile...
+	Disabled until needed in the future.  /\/\|=mhw=|\/\/  12/22/2004
+*/
 		if ( cmd == 1 ) {
 			rc = put_user(iiSendPendingMail, pIndex++ );
 			rc = put_user(i2InitChannels, pIndex++ );
@@ -2973,6 +3015,7 @@
 		}
 
 		break;
+#endif
 
 	default:
 		rc = -ENODEV;
