diff -urN linux-2.4.28/Documentation/computone.txt linux-2.4.28ct/Documentation/computone.txt --- linux-2.4.28/Documentation/computone.txt 2001-11-02 20:26:17.000000000 -0500 +++ linux-2.4.28ct/Documentation/computone.txt 2004-12-22 22:00:39.000000000 -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 Primary Author: Doug McNash -Support: support@computone.com +Support: mhw@wittsend.com Fixes and Updates: Mike Warfield 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.4.28; it will probably not work with earlier v1.X kernels,. 2. QUICK INSTALLATION diff -urN linux-2.4.28/drivers/char/ip2/i2ellis.c linux-2.4.28ct/drivers/char/ip2/i2ellis.c --- linux-2.4.28/drivers/char/ip2/i2ellis.c 2001-10-24 15:05:18.000000000 -0400 +++ linux-2.4.28ct/drivers/char/ip2/i2ellis.c 2004-12-22 21:39:13.000000000 -0500 @@ -605,7 +605,7 @@ set_current_state( TASK_INTERRUPTIBLE ); - pDelayTimer->expires = jiffies + ( mseconds + 9 ) / 10; + pDelayTimer->expires = jiffies + ((HZ * mseconds + 999) / 1000); pDelayTimer->function = ii2DelayWakeup; pDelayTimer->data = 0; diff -urN linux-2.4.28/drivers/char/ip2/i2ellis.h linux-2.4.28ct/drivers/char/ip2/i2ellis.h --- linux-2.4.28/drivers/char/ip2/i2ellis.h 2001-10-24 15:05:18.000000000 -0400 +++ linux-2.4.28ct/drivers/char/ip2/i2ellis.h 2004-12-22 22:34:38.000000000 -0500 @@ -403,7 +403,6 @@ // For queuing interupt bottom half handlers. /\/\|=mhw=|\/\/ struct tq_struct tqueue_interrupt; - struct timer_list SendPendingTimer; // Used by iiSendPending unsigned int SendPendingRetry; #ifdef CONFIG_DEVFS_FS diff -urN linux-2.4.28/drivers/char/ip2/i2lib.c linux-2.4.28ct/drivers/char/ip2/i2lib.c --- linux-2.4.28/drivers/char/ip2/i2lib.c 2002-08-02 20:39:43.000000000 -0400 +++ linux-2.4.28ct/drivers/char/ip2/i2lib.c 2004-12-22 22:35:26.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 ); + } } } } @@ -1329,8 +1338,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.4.28/drivers/char/ip2/ip2types.h linux-2.4.28ct/drivers/char/ip2/ip2types.h --- linux-2.4.28/drivers/char/ip2/ip2types.h 1999-08-23 13:23:23.000000000 -0400 +++ linux-2.4.28ct/drivers/char/ip2/ip2types.h 2004-12-22 12:05:27.000000000 -0500 @@ -49,6 +49,10 @@ short irq[IP2_MAX_BOARDS]; unsigned short addr[IP2_MAX_BOARDS]; int type[IP2_MAX_BOARDS]; +#ifdef CONFIG_PCI + struct pci_dev *pci_dev[IP2_MAX_BOARDS]; +#endif + } ip2config_t; #endif diff -urN linux-2.4.28/drivers/char/ip2main.c linux-2.4.28ct/drivers/char/ip2main.c --- linux-2.4.28/drivers/char/ip2main.c 2004-11-17 06:54:21.000000000 -0500 +++ linux-2.4.28ct/drivers/char/ip2main.c 2004-12-22 22:36:08.000000000 -0500 @@ -19,6 +19,26 @@ // // Done: // +// 1.2.18 /\/\|=mhw=|\/\/ +// Fixed jiffies math in ii2DelayTimer... +// How long has THIS been broken? Delay was basically a noop... +// 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 . +// +// 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 consistant with kernel style @@ -227,7 +247,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"; @@ -437,7 +457,7 @@ } return 0; } -#endif +#endif /* MODULE */ static int __init have_requested_irq( char irq ) @@ -545,6 +565,12 @@ // free memory for (i = 0; i < IP2_MAX_BOARDS; i++) { void *pB; +#ifdef CONFIG_PCI + if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { + pci_disable_device(ip2config.pci_dev[i]); + ip2config.pci_dev[i] = NULL; + } +#endif if ((pB = i2BoardPtrTable[i]) != 0 ) { kfree ( pB ); i2BoardPtrTable[i] = NULL; @@ -604,17 +630,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. @@ -700,17 +721,12 @@ } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - pcibios_read_config_byte(pci_bus, pci_devfn, + if (ip2config.irq[i] != 0) { + pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, &pci_irq); -// 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_irq; + ip2config.irq[i] = pci_irq; + } } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { @@ -727,9 +743,15 @@ PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); if (pci_dev_i != NULL) { unsigned int addr; - unsigned char pci_irq; + + 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_i; status = pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); if ( addr & 1 ) { @@ -737,18 +759,8 @@ } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - status = - pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); - -// 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_irq; - } else { // ann error + ip2config.irq[i] = pci_dev_i->irq; + } else { // an error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { printk( KERN_ERR "IP2: PCI board %d not found\n", i ); @@ -964,6 +976,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 */ @@ -1375,8 +1395,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 ) ) ) { #ifdef USE_IQI if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { @@ -1391,9 +1413,8 @@ mark_bh(IMMEDIATE_BH); } #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 */ } @@ -1417,6 +1438,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 @@ -1424,7 +1448,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 ); @@ -3198,7 +3230,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 ) { PUT_USER(rc, iiSendPendingMail, pIndex++ ); PUT_USER(rc, i2InitChannels, pIndex++ ); @@ -3259,6 +3300,7 @@ } break; +#endif default: rc = -ENODEV;