patch-2.3.99-pre6 linux/drivers/char/ip2main.c

Next file: linux/drivers/char/joystick/joystick.c
Previous file: linux/drivers/char/ip2.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
@@ -10,21 +10,67 @@
 *   DESCRIPTION: Mainline code for the device driver
 *
 *******************************************************************************/
+// ToDo:
+//
+// Done:
+//
+// 1.2.9
+// Four box EX was barfing on >128k kmalloc, made structure smaller by
+// reducing output buffer size
+//
+// 1.2.8
+// Device file system support (MHW)
+//
+// 1.2.7 
+// Fixed
+// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
+//
+// 1.2.6
+//Fixes DCD problems
+//	DCD was not reported when CLOCAL was set on call to TIOCMGET
+//
+//Enhancements:
+//	TIOCMGET requests and waits for status return
+//	No DSS interrupts enabled except for DCD when needed
+//
+// For internal use only
+//
+//#define IP2DEBUG_INIT
+//#define IP2DEBUG_OPEN
+//#define IP2DEBUG_WRITE
+//#define IP2DEBUG_READ
+//#define IP2DEBUG_IOCTL
+//#define IP2DEBUG_IPL
+
+//#define IP2DEBUG_TRACE
+//#define DEBUG_FIFO
+
 /************/
 /* Includes */
 /************/
-
 #include <linux/config.h>
-#include <linux/module.h>
+// Uncomment the following if you want it compiled with modversions
+#ifdef MODULE
+#	if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#		define MODVERSIONS
+#	endif
+#	ifdef MODVERSIONS
+#		include <linux/modversions.h>
+#	endif
+#endif
+
 #include <linux/version.h>
 
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
-
+#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#ifdef	CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
@@ -50,13 +96,84 @@
 #include <asm/irq.h>
 #include <asm/bitops.h>
 
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <asm/serial.h>
-
-#include <asm/uaccess.h>
-#define		pcibios_strerror(status)	\
-	printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+#	include <linux/vmalloc.h>
+#	include <linux/init.h>
+#	include <asm/serial.h>
+#else
+#	include <linux/bios32.h>
+#endif
+
+// These VERSION switches maybe inexact because I simply don't know
+// when the various features appeared in the 2.1.XX kernels.
+// They are good enough for 2.0 vs 2.2 and if you are fooling with
+// the 2.1.XX stuff then it would be trivial for you to fix.
+// Most of these macros were stolen from some other drivers
+// so blame them.
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)
+#	include <asm/segment.h>
+#	define GET_USER(error,value,addr) error = get_user(value,addr)
+#	define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
+#	define PUT_USER(error,value,addr) error = put_user(value,addr)
+#	define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
+
+#	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)
+#		include <asm/uaccess.h>
+#		define		pcibios_strerror(status)	\
+					printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
+#	endif
+
+#else  /* 2.0.x and 2.1.x before 2.1.4 */
+
+#	define		proc_register_dynamic(a,b) proc_register(a,b) 
+
+#	define GET_USER(error,value,addr)					  \
+	do {									  \
+		error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
+		if (error == 0)							  \
+			value = get_user(addr);					  \
+	} while (0)
+
+#	define COPY_FROM_USER(error,dest,src,size)				  \
+	do {									  \
+		error = verify_area (VERIFY_READ, (void *) src, size);		  \
+		if (error == 0)							  \
+			memcpy_fromfs (dest, src, size);			  \
+	} while (0)
+
+#	define PUT_USER(error,value,addr)					   \
+	do {									   \
+		error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
+		if (error == 0)							   \
+			put_user (value, addr);					   \
+	} while (0)
+
+#	define COPY_TO_USER(error,dest,src,size)				  \
+	do {									  \
+		error = verify_area (VERIFY_WRITE, (void *) dest, size);		  \
+		if (error == 0)							  \
+			memcpy_tofs (dest, src, size);				  \
+	} while (0)
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#define __init
+#define __initfunc(a) a
+#define __initdata
+#define ioremap(a,b) vremap((a),(b))
+#define iounmap(a) vfree((a))
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
+#define signal_pending(a) ((a)->signal & ~(a)->blocked)
+#define in_interrupt()	intr_count
+#endif
 
 #include "./ip2/ip2types.h"
 #include "./ip2/ip2trace.h"
@@ -84,12 +201,17 @@
 
 /* String constants to identify ourselves */
 static char *pcName    = "Computone IntelliPort Plus multiport driver";
-static char *pcVersion = "1.2.4";
+static char *pcVersion = "1.2.9";
 
 /* String constants for port names */
 static char *pcDriver_name   = "ip2";
-static char *pcTty    		 = "ttyf";
+#ifdef	CONFIG_DEVFS_FS
+static char *pcTty    		 = "ttf/%d";
+static char *pcCallout		 = "cuf/%d";
+#else
+static char *pcTty    		 = "ttyF";
 static char *pcCallout		 = "cuf";
+#endif
 static char *pcIpl    		 = "ip2ipl";
 
 /* Serial subtype definitions */
@@ -141,12 +263,15 @@
 static void ip2_wait_until_sent(PTTY,int);
 
 static void set_params (i2ChanStrPtr, struct termios *);
-static int get_modem_info(i2ChanStrPtr, unsigned int *);
 static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);
 static int get_serial_info(i2ChanStrPtr, struct serial_struct *);
 static int set_serial_info(i2ChanStrPtr, struct serial_struct *);
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+static int     ip2_ipl_read(struct inode *, char *, size_t , loff_t *);
+#else
 static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ;
+#endif
 static ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *);
 static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
 static int ip2_ipl_open(struct inode *, struct file *);
@@ -241,13 +366,14 @@
 
 /* Configuration area for modprobe */
 #ifdef MODULE
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+#	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
+		MODULE_AUTHOR("Doug McNash");
+		MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+#	endif	/* LINUX_VERSION */
 #endif	/* MODULE */
 
 static int poll_only = 0;
 
-static int Pci_index = 0;
 static int Eisa_irq = 0;
 static int Eisa_slot = 0;
 
@@ -371,8 +497,6 @@
 #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 );
@@ -382,7 +506,7 @@
 	/* Reset the boards we have. */
 	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
 		if ( i2BoardPtrTable[i] ) {
-			iiReset ( i2BoardPtrTable[i] );
+			iiReset( i2BoardPtrTable[i] );
 		}
 	}
 
@@ -392,6 +516,10 @@
 			iiResetDelay( i2BoardPtrTable[i] );
 			/* free io addresses and Tibet */
 			release_region( ip2config.addr[i], 8 );
+#ifdef	CONFIG_DEVFS_FS
+			devfs_unregister (i2BoardPtrTable[i]->devfs_ipl_handle);
+			devfs_unregister (i2BoardPtrTable[i]->devfs_stat_handle);
+#endif
 		}
 		/* Disable and remove interrupt handler. */
 		if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {	
@@ -405,7 +533,12 @@
 	if ( ( err = tty_unregister_driver ( &ip2_callout_driver ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister callout driver (%d)\n", err);
 	}
-	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
+#ifdef	CONFIG_DEVFS_FS
+	if ( ( err = devfs_unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
+#else
+	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
+#endif
+	{
 		printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
 	}
 	remove_proc_entry("ip2mem", &proc_root);
@@ -450,9 +583,14 @@
 int __init
 old_ip2_init(void)
 {
+#ifdef	CONFIG_DEVFS_FS
+	static devfs_handle_t devfs_handle = NULL;
+	int j, box;
+#endif
 	int i;
 	int err;
 	int status = 0;
+	static int loaded = 0;
 	i2eBordStrPtr pB = NULL;
 	int rc = -1;
 
@@ -463,6 +601,15 @@
 	/* 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++;
+
 	/* if all irq config is zero we shall poll_only */
 	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
 		poll_only |= ip2config.irq[i];
@@ -502,11 +649,14 @@
 			break;
 		case PCI:
 #ifdef CONFIG_PCI
-			if (pci_present()) {
-				struct pci_dev *pci_dev_i = NULL;
-				pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
-							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
-				if (pci_dev_i != NULL) {
+#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
+			if (pcibios_present()) {
+				unsigned char pci_bus, pci_devfn;
+				int Pci_index = 0;
+				status = pcibios_find_device(PCI_VENDOR_ID_COMPUTONE,
+							  PCI_DEVICE_ID_COMPUTONE_IP2EX, Pci_index,
+							  &pci_bus, &pci_devfn);
+				if (status == 0) {
 					unsigned int addr;
 					unsigned char pci_irq;
 
@@ -517,6 +667,41 @@
 					 * one.
 					 */
 					++Pci_index;
+
+					pcibios_read_config_dword(pci_bus, pci_devfn,
+								  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");
+					}
+					pcibios_read_config_byte(pci_bus, pci_devfn,
+								  PCI_INTERRUPT_LINE, &pci_irq);
+
+					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.addr[i] = 0;
+					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
+						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
+					} else {
+						pcibios_strerror(status);
+					}
+				} 
+			} 
+#else /* LINUX_VERSION_CODE > 2.1.99 */
+			if (pci_present()) {
+				struct pci_dev *pci_dev_i = NULL;
+				pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
+							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
+				if (pci_dev_i != NULL) {
+					unsigned int addr;
+					unsigned char pci_irq;
+
+					ip2config.type[i] = PCI;
 					status =
 					pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
 					if ( addr & 1 ) {
@@ -541,6 +726,7 @@
 					}
 				} 
 			} 
+#endif	/* ! 2_0_X */
 #else
 			printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
 			printk( KERN_ERR "IP2: configured in this kernel.\n");
@@ -591,8 +777,10 @@
 	/* Initialise the relevant fields. */
 	ip2_tty_driver.magic                = TTY_DRIVER_MAGIC;
 	ip2_tty_driver.name                 = pcTty;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
 	ip2_tty_driver.driver_name          = pcDriver_name;
 	ip2_tty_driver.read_proc          	= ip2_read_proc;
+#endif
 	ip2_tty_driver.major                = IP2_TTY_MAJOR;
 	ip2_tty_driver.minor_start          = 0;
 	ip2_tty_driver.num                  = IP2_MAX_PORTS;
@@ -600,7 +788,11 @@
 	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;
+#ifdef	CONFIG_DEVFS_FS
+	ip2_tty_driver.flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+#else
 	ip2_tty_driver.flags                = TTY_DRIVER_REAL_RAW;
+#endif
 	ip2_tty_driver.refcount             = &ref_count;
 	ip2_tty_driver.table                = TtyTable;
 	ip2_tty_driver.termios              = Termios;
@@ -629,8 +821,10 @@
 	 */
 	ip2_callout_driver         = ip2_tty_driver;
 	ip2_callout_driver.name    = pcCallout;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
 	ip2_callout_driver.driver_name = pcDriver_name;
 	ip2_callout_driver.read_proc  = NULL;
+#endif
 	ip2_callout_driver.major   = IP2_CALLOUT_MAJOR;
 	ip2_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 
@@ -646,7 +840,12 @@
 		printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err);
 	} else
 	/* Register the IPL driver. */
-	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
+#ifdef	CONFIG_DEVFS_FS
+	if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl )))
+#else
+	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) )
+#endif
+	{
 		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
 	} else
 	/* Register the read_procmem thing */
@@ -660,10 +859,54 @@
 		/* Register the interrupt handler or poll handler, depending upon the
 		 * specified interrupt.
 		 */
+#ifdef	CONFIG_DEVFS_FS
+		if (!devfs_handle)
+			devfs_handle = devfs_mk_dir (NULL, "ip2", 3, NULL);
+#endif
+
 		for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+#ifdef	CONFIG_DEVFS_FS
+			char name[16];
+#endif
+
 			if ( 0 == ip2config.addr[i] ) {
 				continue;
 			}
+
+#ifdef	CONFIG_DEVFS_FS
+			sprintf( name, "ipl%d", i );
+			i2BoardPtrTable[i]->devfs_ipl_handle =
+				devfs_register (devfs_handle, name, 0,
+					DEVFS_FL_NONE,
+					IP2_IPL_MAJOR, 4 * i,
+					S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
+					0, 0, &ip2_ipl, NULL);
+
+			sprintf( name, "stat%d", i );
+			i2BoardPtrTable[i]->devfs_stat_handle =
+				devfs_register (devfs_handle, name, 0,
+					DEVFS_FL_NONE,
+					IP2_IPL_MAJOR, 4 * i + 1,
+					S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
+					0, 0, &ip2_ipl, NULL);
+
+			for ( box = 0; box < ABS_MAX_BOXES; ++box )
+			{
+			    for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
+			    {
+				if ( pB->i2eChannelMap[box] & (1 << j) )
+				{
+				    tty_register_devfs(&ip2_tty_driver,
+					0, j + ABS_BIGGEST_BOX *
+						(box+i*ABS_MAX_BOXES));
+				    tty_register_devfs(&ip2_callout_driver,
+					0, j + ABS_BIGGEST_BOX *
+						(box+i*ABS_MAX_BOXES));
+				}
+			    }
+			}
+#endif
+
 			if (poll_only) {
 					ip2config.irq[i] = CIR_POLL;
 			}
@@ -932,7 +1175,6 @@
 static void
 set_irq( int boardnum, int boardIrq )
 {
-	i2ChanStrPtr pCh;
 	unsigned char tempCommand[16];
 	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
 	unsigned long flags;
@@ -946,8 +1188,6 @@
 	 * is done.  If polling we must send 0 as the interrupt parameter.
 	 */
 
-	pCh = (i2ChanStrPtr) pB->i2eChannelPtr;
-
 	// We will get an interrupt here at the end of this function
 
 	iiDisableMailIrq(pB);
@@ -1129,7 +1369,7 @@
 	unsigned long flags;
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace(PORTN, ITRC_INPUT, 21, 0 );
+	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
 #endif
 	// Data input
 	if ( pCh->pTTY != NULL ) {
@@ -1141,7 +1381,7 @@
 			READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
 	} else {
 #ifdef IP2DEBUG_TRACE
-		ip2trace(PORTN, ITRC_INPUT, 22, 0 );
+		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
 #endif
 		i2InputFlush( pCh );
 	}
@@ -1168,7 +1408,7 @@
 	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_STATUS, 21, 1, status );
+	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
 #endif
 
 	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
@@ -1230,7 +1470,7 @@
 	}
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_STATUS, 26, 0 );
+	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
 #endif
 }
 
@@ -1305,11 +1545,8 @@
 	open_sanity_check ( pCh, pCh->pMyBord );
 #endif
 
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
+	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
 	pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, 
-				CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
 	serviceOutgoingFifo( pCh->pMyBord );
 
 	/* Block here until the port is ready (per serial and istallion) */
@@ -1401,7 +1638,7 @@
 		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
 #endif
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_OPEN, 3, 2, (pCh->flags & ASYNC_CALLOUT_ACTIVE),
+		ip2trace (CHANN, ITRC_OPEN, 3, 2, (pCh->flags & ASYNC_CALLOUT_ACTIVE),
 								(pCh->flags & ASYNC_CLOSING) );
 #endif
 		/* check for signal */
@@ -1413,7 +1650,7 @@
 	}
 	--pCh->wopen; //why count?
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_OPEN, 4, 0 );
+	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
 #endif
 	if (rc != 0 ) {
 		return rc;
@@ -1452,7 +1689,7 @@
 	serviceOutgoingFifo( pCh->pMyBord );
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_OPEN, ITRC_RETURN, 0 );
+	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
 #endif
 	return 0;
 }
@@ -1477,7 +1714,7 @@
 	}
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_CLOSE, ITRC_ENTER, 0 );
+	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
 #endif
 
 #ifdef IP2DEBUG_OPEN
@@ -1488,14 +1725,14 @@
 		MOD_DEC_USE_COUNT;
 
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_CLOSE, 2, 1, 2 );
+		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
 #endif
 		return;
 	}
 	if ( tty->count > 1 ) { /* not the last close */
 		MOD_DEC_USE_COUNT;
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_CLOSE, 2, 1, 3 );
+		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
 #endif
 		return;
 	}
@@ -1528,14 +1765,13 @@
 	i2InputFlush( pCh );
 
 	/* disable DSS reporting */
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
+	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
+				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
 	if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
 		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
 		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
 		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
 	}
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, 
-				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
 
 	serviceOutgoingFifo ( pCh->pMyBord );
 
@@ -1565,7 +1801,7 @@
 	MOD_DEC_USE_COUNT;
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
+	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
 #endif
 	return;
 }
@@ -1585,7 +1821,7 @@
 	i2ChanStrPtr  pCh = tty->driver_data;
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_HANGUP, ITRC_ENTER, 0 );
+	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
 #endif
 
 	ip2_flush_buffer(tty);
@@ -1610,7 +1846,7 @@
 	wake_up_interruptible ( &pCh->open_wait );
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_HANGUP, ITRC_RETURN, 0 );
+	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
 #endif
 }
 
@@ -1640,7 +1876,7 @@
 	unsigned long flags;
 
 #ifdef IP2DEBUG_TRACE
-   ip2trace (PORTN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
+   ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
 #endif
 
 	/* Flush out any buffered data left over from ip2_putchar() calls. */
@@ -1652,7 +1888,7 @@
 	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
 
 #ifdef IP2DEBUG_TRACE
-   ip2trace (PORTN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
+   ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
 #endif
 	return bytesSent > 0 ? bytesSent : 0;
 }
@@ -1674,7 +1910,7 @@
 	unsigned long flags;
 
 #ifdef IP2DEBUG_TRACE
-//	ip2trace (PORTN, ITRC_PUTC, ITRC_ENTER, 1, ch );
+//	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
 #endif
 
 	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
@@ -1686,7 +1922,7 @@
 		WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
 
 #ifdef IP2DEBUG_TRACE
-//	ip2trace (PORTN, ITRC_PUTC, ITRC_RETURN, 1, ch );
+//	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
 #endif
 }
 
@@ -1708,7 +1944,7 @@
 	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
 	if ( pCh->Pbuf_stuff ) {
 #ifdef IP2DEBUG_TRACE
-//	ip2trace (PORTN, ITRC_PUTC, 10, 1, strip );
+//	ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
 #endif
 		//
 		// We may need to restart i2Output if it does not fullfill this request
@@ -1742,7 +1978,7 @@
 	READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_WRITE, 11, 1, bytesFree );
+	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
 #endif
 
 	return ((bytesFree > 0) ? bytesFree : 0);
@@ -1764,7 +2000,7 @@
 	int rc;
 	unsigned long flags;
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
+	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
 #endif
 #ifdef IP2DEBUG_WRITE
 	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
@@ -1796,7 +2032,7 @@
 	unsigned long flags;
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_FLUSH, ITRC_ENTER, 0 );
+	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
 #endif
 #ifdef IP2DEBUG_WRITE
 	printk (KERN_DEBUG "IP2: flush buffer\n" );
@@ -1807,7 +2043,7 @@
 	i2FlushOutput( pCh );
 	ip2_owake(tty);
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_FLUSH, ITRC_RETURN, 0 );
+	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
 #endif
 }
 
@@ -1943,17 +2179,18 @@
 static int
 ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
 {
-	i2ChanStrPtr  pCh = DevTable[MINOR(tty->device)];
+	i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct *p_cuser;	/* user space */
 	int rc = 0;
+	unsigned long flags;
 
 	if ( pCh == NULL ) {
 		return -ENODEV;
 	}
 
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
+	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
 #endif
 
 #ifdef IP2DEBUG_IOCTL
@@ -1963,7 +2200,7 @@
 	switch(cmd) {
 	case TIOCGSERIAL:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 2, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
 #endif
 		rc = get_serial_info(pCh, (struct serial_struct *) arg);
 		if (rc)
@@ -1972,7 +2209,7 @@
 
 	case TIOCSSERIAL:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 3, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
 #endif
 		rc = set_serial_info(pCh, (struct serial_struct *) arg);
 		if (rc)
@@ -2010,7 +2247,7 @@
 	case TCSBRK:   /* SVID version: non-zero arg --> no break */
 		rc = tty_check_change(tty);
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 4, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
 #endif
 		if (!rc) {
 			ip2_wait_until_sent(tty,0);
@@ -2024,7 +2261,7 @@
 	case TCSBRKP:  /* support for POSIX tcsendbreak() */
 		rc = tty_check_change(tty);
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 5, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
 #endif
 		if (!rc) {
 			ip2_wait_until_sent(tty,0);
@@ -2036,18 +2273,18 @@
 
 	case TIOCGSOFTCAR:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 6, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
 #endif
-			rc=put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+			PUT_USER(rc,C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
 		if (rc)	
 			return rc;
 	break;
 
 	case TIOCSSOFTCAR:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 7, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
 #endif
-		rc=get_user(arg,(unsigned long *) arg);
+		GET_USER(rc,arg,(unsigned long *) arg);
 		if (rc) 
 			return rc;
 		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
@@ -2057,18 +2294,37 @@
 
 	case TIOCMGET:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 8, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
 #endif
-		rc = get_modem_info(pCh, (unsigned int *) arg);
-		if (rc) 
-			return rc;
+/*
+	FIXME - the following code is causing a NULL pointer dereference in
+	2.3.51 in an interrupt handler.  It's suppose to prompt the board
+	to return the DSS signal status immediately.  Why doesn't it do
+	the same thing in 2.2.14?
+*/
+/*
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
+		serviceOutgoingFifo( pCh->pMyBord );
+		interruptible_sleep_on(&pCh->dss_now_wait);
+		if (signal_pending(current)) {
+			return -EINTR;
+		}
+*/
+		PUT_USER(rc,
+				    ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
+				  | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
+				  | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
+				  | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
+				  | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
+				  | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0),
+				(unsigned int *) arg);
 		break;
 
 	case TIOCMBIS:
 	case TIOCMBIC:
 	case TIOCMSET:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 9, 0 );
+		ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
 #endif
 		rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
 		break;
@@ -2079,24 +2335,34 @@
 	 * for masking). Caller should use TIOCGICOUNT to see which one it was
 	 */
 	case TIOCMIWAIT:
+		save_flags(flags);cli();
 		cprev = pCh->icount;	 /* note the counters on entry */
+		restore_flags(flags);
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
+						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
+		serviceOutgoingFifo( pCh->pMyBord );
 		for(;;) {
 #ifdef IP2DEBUG_TRACE
-			ip2trace (PORTN, ITRC_IOCTL, 10, 0 );
+			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
 #endif
 			interruptible_sleep_on(&pCh->delta_msr_wait);
+#ifdef IP2DEBUG_TRACE
+			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
+#endif
 			/* see if a signal did it */
 			if (signal_pending(current)) {
 				rc = -ERESTARTSYS;
 				break;
 			}
+			save_flags(flags);cli();
 			cnow = pCh->icount; /* atomic copy */
+			restore_flags(flags);
 			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-			   cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
 				rc =  -EIO; /* no change => rc */
 				break;
 			}
-			if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
 			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
 			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
 			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
@@ -2105,7 +2371,13 @@
 			}
 			cprev = cnow;
 		}
-		/* NOTREACHED */
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
+						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
+		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
+			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
+		}
+		serviceOutgoingFifo( pCh->pMyBord );
+		return rc;
 		break;
 
 	/*
@@ -2118,14 +2390,23 @@
 	 */
 	case TIOCGICOUNT:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 11, 1, rc );
+		ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
 #endif
+		save_flags(flags);cli();
 		cnow = pCh->icount;
+		restore_flags(flags);
 		p_cuser = (struct serial_icounter_struct *) arg;
-		put_user(cnow.cts, &p_cuser->cts);
-		put_user(cnow.dsr, &p_cuser->dsr);
-		put_user(cnow.rng, &p_cuser->rng);
-		put_user(cnow.dcd, &p_cuser->dcd);
+		PUT_USER(rc,cnow.cts, &p_cuser->cts);
+		PUT_USER(rc,cnow.dsr, &p_cuser->dsr);
+		PUT_USER(rc,cnow.rng, &p_cuser->rng);
+		PUT_USER(rc,cnow.dcd, &p_cuser->dcd);
+		PUT_USER(rc,cnow.rx, &p_cuser->rx);
+		PUT_USER(rc,cnow.tx, &p_cuser->tx);
+		PUT_USER(rc,cnow.frame, &p_cuser->frame);
+		PUT_USER(rc,cnow.overrun, &p_cuser->overrun);
+		PUT_USER(rc,cnow.parity, &p_cuser->parity);
+		PUT_USER(rc,cnow.brk, &p_cuser->brk);
+		PUT_USER(rc,cnow.buf_overrun, &p_cuser->buf_overrun);
 		break;
 
 	/*
@@ -2142,43 +2423,16 @@
 
 	default:
 #ifdef IP2DEBUG_TRACE
-		ip2trace (PORTN, ITRC_IOCTL, 12, 0 );
+		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
 #endif
 		rc =  -ENOIOCTLCMD;
 		break;
 	}
 #ifdef IP2DEBUG_TRACE
-	ip2trace (PORTN, ITRC_IOCTL, ITRC_RETURN, 0 );
+	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
 #endif
 	return rc;
 }
-/******************************************************************************/
-/* Function:   get_modem_info()                                               */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to destination for data                                */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This returns the current settings of the dataset signal inputs to the user */
-/* program.                                                                   */
-/******************************************************************************/
-static int
-get_modem_info(i2ChanStrPtr pCh, unsigned int *value)
-{
-	unsigned short status;
-	unsigned int result;
-	int rc;
-
-	status = pCh->dataSetIn;	// snapshot settings
-	result = ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
-		  | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
-		  | ((status  & I2_DCD) ? TIOCM_CAR : 0)
-		  | ((status  & I2_RI) ? TIOCM_RNG : 0)
-		  | ((status  & I2_DSR) ? TIOCM_DSR : 0)
-		  | ((status  & I2_CTS) ? TIOCM_CTS : 0);
-	rc=put_user(result,value);
-	return rc;
-}
 
 /******************************************************************************/
 /* Function:   set_modem_info()                                               */
@@ -2197,7 +2451,7 @@
 	int rc;
 	unsigned int arg;
 
-	rc=get_user(arg,value);
+	GET_USER(rc,arg,value);
 	if (rc)
 		return rc;
 	switch(cmd) {
@@ -2258,7 +2512,7 @@
 get_serial_info ( i2ChanStrPtr pCh, struct serial_struct *retinfo )
 {
 	struct serial_struct tmp;
-	int rc=0;
+	int rc;
 
 	if ( !retinfo ) {
 		return -EFAULT;
@@ -2279,9 +2533,8 @@
 	tmp.close_delay = pCh->ClosingDelay;
 	tmp.closing_wait = pCh->ClosingWaitTime;
 	tmp.custom_divisor = pCh->BaudDivisor;
-   	if(copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-   		rc= -EFAULT;
-	return rc;
+   	COPY_TO_USER(rc,retinfo,&tmp,sizeof(*retinfo));
+   return rc;
 }
 
 /******************************************************************************/
@@ -2305,7 +2558,7 @@
 	if ( !new_info ) {
 		return -EFAULT;
 	}
-	rc=copy_from_user(&ns, new_info, sizeof (ns) );
+	COPY_FROM_USER(rc, &ns, new_info, sizeof (ns) );
 	if (rc) {
 		return rc;
 	}
@@ -2631,6 +2884,7 @@
 		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
 	}
 	if (cflag & CLOCAL) {
+		// Status reporting fails for DCD if this is off
 		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
 		pCh->flags &= ~ASYNC_CHECK_CD;
 	} else {
@@ -2670,10 +2924,16 @@
 /******************************************************************************/
 
 static 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+int
+ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off )
+	unsigned int minor = MINOR( pInode->i_rdev );
+#else
 ssize_t
 ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off )
 {
 	unsigned int minor = MINOR( pFile->f_dentry->d_inode->i_rdev );
+#endif
 	int rc = 0;
 
 #ifdef IP2DEBUG_IPL
@@ -2707,9 +2967,8 @@
 DumpFifoBuffer ( char *pData, int count )
 {
 #ifdef DEBUG_FIFO
-	int rc=0;
-	if(copy_to_user(pData, DBGBuf, count))
-		rc=-EFAULT;
+	int rc;
+	COPY_TO_USER(rc, pData, DBGBuf, count);
 
 	printk(KERN_DEBUG "Last index %d\n", I );
 
@@ -2730,10 +2989,10 @@
 	if ( count < (sizeof(int) * 6) ) {
 		return -EIO;
 	}
-	put_user(tracewrap, pIndex );
-	put_user(TRACEMAX, ++pIndex );
-	put_user(tracestrip, ++pIndex );
-	put_user(tracestuff, ++pIndex );
+	PUT_USER(rc, tracewrap, pIndex );
+	PUT_USER(rc, TRACEMAX, ++pIndex );
+	PUT_USER(rc, tracestrip, ++pIndex );
+	PUT_USER(rc, tracestuff, ++pIndex );
 	pData += sizeof(int) * 6;
 	count -= sizeof(int) * 6;
 
@@ -2746,21 +3005,21 @@
 	}
 	chunk = TRACEMAX - tracestrip;
 	if ( dumpcount > chunk ) {
-		rc=copy_to_user(pData, &tracebuf[tracestrip],
-			      chunk * sizeof(tracebuf[0]) )?-EFAULT:0;
+		COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
+			      chunk * sizeof(tracebuf[0]) );
 		pData += chunk * sizeof(tracebuf[0]);
 		tracestrip = 0;
 		chunk = dumpcount - chunk;
 	} else {
 		chunk = dumpcount;
 	}
-	rc=copy_to_user(pData, &tracebuf[tracestrip],
-		      chunk * sizeof(tracebuf[0]) )?-EFAULT:0
+	COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
+		      chunk * sizeof(tracebuf[0]) );
 	tracestrip += chunk;
 	tracewrap = 0;
 
-	put_user(tracestrip, ++pIndex );
-	put_user(tracestuff, ++pIndex );
+	PUT_USER(rc, tracestrip, ++pIndex );
+	PUT_USER(rc, tracestuff, ++pIndex );
 
 	return dumpcount;
 #else
@@ -2824,16 +3083,15 @@
 	case 13:
 		switch ( cmd ) {
 		case 64:	/* Driver - ip2stat */
-			put_user(ref_count, pIndex++ );
-			put_user(irq_counter, pIndex++  );
-			put_user(bh_counter, pIndex++  );
+			PUT_USER(rc, ref_count, pIndex++ );
+			PUT_USER(rc, irq_counter, pIndex++  );
+			PUT_USER(rc, bh_counter, pIndex++  );
 			break;
 
 		case 65:	/* Board  - ip2stat */
 			if ( pB ) {
-				if(copy_to_user((char*)arg, (char*)pB, sizeof(i2eBordStr) ))
-					rc=-EFAULT;
-				put_user(INB(pB->i2eStatus),
+				COPY_TO_USER(rc, (char*)arg, (char*)pB, sizeof(i2eBordStr) );
+				PUT_USER(rc, INB(pB->i2eStatus),
 					(ULONG*)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
 			} else {
 				rc = -ENODEV;
@@ -2844,8 +3102,7 @@
 			pCh = DevTable[cmd];
 			if ( pCh )
 			{
-				if(copy_to_user((char*)arg, (char*)pCh, sizeof(i2ChanStr) ))
-					rc = -EFAULT;
+				COPY_TO_USER(rc, (char*)arg, (char*)pCh, sizeof(i2ChanStr) );
 			} else {
 				rc = cmd < 64 ? -ENODEV : -EINVAL;
 			}
@@ -2857,61 +3114,60 @@
 		break;
 	case 3:	    // Trace device
 		if ( cmd == 1 ) {
-			put_user(iiSendPendingMail, pIndex++ );
-			put_user(i2InitChannels, pIndex++ );
-			put_user(i2QueueNeeds, pIndex++ );
-			put_user(i2QueueCommands, pIndex++ );
-			put_user(i2GetStatus, pIndex++ );
-			put_user(i2Input, pIndex++ );
-			put_user(i2InputFlush, pIndex++ );
-			put_user(i2Output, pIndex++ );
-			put_user(i2FlushOutput, pIndex++ );
-			put_user(i2DrainWakeup, pIndex++ );
-			put_user(i2DrainOutput, pIndex++ );
-			put_user(i2OutputFree, pIndex++ );
-			put_user(i2StripFifo, pIndex++ );
-			put_user(i2StuffFifoBypass, pIndex++ );
-			put_user(i2StuffFifoFlow, pIndex++ );
-			put_user(i2StuffFifoInline, pIndex++ );
-			put_user(i2ServiceBoard, pIndex++ );
-			put_user(serviceOutgoingFifo, pIndex++ );
-			// put_user(ip2_init, pIndex++ );
-			put_user(ip2_init_board, pIndex++ );
-			put_user(find_eisa_board, pIndex++ );
-			put_user(set_irq, pIndex++ );
-			put_user(ip2_interrupt, pIndex++ );
-			put_user(ip2_poll, pIndex++ );
-			put_user(service_all_boards, pIndex++ );
-			put_user(do_input, pIndex++ );
-			put_user(do_status, pIndex++ );
+			PUT_USER(rc, iiSendPendingMail, pIndex++ );
+			PUT_USER(rc, i2InitChannels, pIndex++ );
+			PUT_USER(rc, i2QueueNeeds, pIndex++ );
+			PUT_USER(rc, i2QueueCommands, pIndex++ );
+			PUT_USER(rc, i2GetStatus, pIndex++ );
+			PUT_USER(rc, i2Input, pIndex++ );
+			PUT_USER(rc, i2InputFlush, pIndex++ );
+			PUT_USER(rc, i2Output, pIndex++ );
+			PUT_USER(rc, i2FlushOutput, pIndex++ );
+			PUT_USER(rc, i2DrainWakeup, pIndex++ );
+			PUT_USER(rc, i2DrainOutput, pIndex++ );
+			PUT_USER(rc, i2OutputFree, pIndex++ );
+			PUT_USER(rc, i2StripFifo, pIndex++ );
+			PUT_USER(rc, i2StuffFifoBypass, pIndex++ );
+			PUT_USER(rc, i2StuffFifoFlow, pIndex++ );
+			PUT_USER(rc, i2StuffFifoInline, pIndex++ );
+			PUT_USER(rc, i2ServiceBoard, pIndex++ );
+			PUT_USER(rc, serviceOutgoingFifo, pIndex++ );
+			// PUT_USER(rc, ip2_init, pIndex++ );
+			PUT_USER(rc, ip2_init_board, pIndex++ );
+			PUT_USER(rc, find_eisa_board, pIndex++ );
+			PUT_USER(rc, set_irq, pIndex++ );
+			PUT_USER(rc, ip2_interrupt, pIndex++ );
+			PUT_USER(rc, ip2_poll, pIndex++ );
+			PUT_USER(rc, service_all_boards, pIndex++ );
+			PUT_USER(rc, do_input, pIndex++ );
+			PUT_USER(rc, do_status, pIndex++ );
 #ifndef IP2DEBUG_OPEN
-			put_user(0, pIndex++ );
+			PUT_USER(rc, 0, pIndex++ );
 #else
-			put_user(open_sanity_check, pIndex++ );
+			PUT_USER(rc, open_sanity_check, pIndex++ );
 #endif
-			put_user(ip2_open, pIndex++ );
-			put_user(ip2_close, pIndex++ );
-			put_user(ip2_hangup, pIndex++ );
-			put_user(ip2_write, pIndex++ );
-			put_user(ip2_putchar, pIndex++ );
-			put_user(ip2_flush_chars, pIndex++ );
-			put_user(ip2_write_room, pIndex++ );
-			put_user(ip2_chars_in_buf, pIndex++ );
-			put_user(ip2_flush_buffer, pIndex++ );
-
-			//put_user(ip2_wait_until_sent, pIndex++ );
-			put_user(0, pIndex++ );
-
-			put_user(ip2_throttle, pIndex++ );
-			put_user(ip2_unthrottle, pIndex++ );
-			put_user(ip2_ioctl, pIndex++ );
-			put_user(get_modem_info, pIndex++ );
-			put_user(set_modem_info, pIndex++ );
-			put_user(get_serial_info, pIndex++ );
-			put_user(set_serial_info, pIndex++ );
-			put_user(ip2_set_termios, pIndex++ );
-			put_user(ip2_set_line_discipline, pIndex++ );
-			put_user(set_params, pIndex++ );
+			PUT_USER(rc, ip2_open, pIndex++ );
+			PUT_USER(rc, ip2_close, pIndex++ );
+			PUT_USER(rc, ip2_hangup, pIndex++ );
+			PUT_USER(rc, ip2_write, pIndex++ );
+			PUT_USER(rc, ip2_putchar, pIndex++ );
+			PUT_USER(rc, ip2_flush_chars, pIndex++ );
+			PUT_USER(rc, ip2_write_room, pIndex++ );
+			PUT_USER(rc, ip2_chars_in_buf, pIndex++ );
+			PUT_USER(rc, ip2_flush_buffer, pIndex++ );
+
+			//PUT_USER(rc, ip2_wait_until_sent, pIndex++ );
+			PUT_USER(rc, 0, pIndex++ );
+
+			PUT_USER(rc, ip2_throttle, pIndex++ );
+			PUT_USER(rc, ip2_unthrottle, pIndex++ );
+			PUT_USER(rc, ip2_ioctl, pIndex++ );
+			PUT_USER(rc, set_modem_info, pIndex++ );
+			PUT_USER(rc, get_serial_info, pIndex++ );
+			PUT_USER(rc, set_serial_info, pIndex++ );
+			PUT_USER(rc, ip2_set_termios, pIndex++ );
+			PUT_USER(rc, ip2_set_line_discipline, pIndex++ );
+			PUT_USER(rc, set_params, pIndex++ );
 		} else {
 			rc = -EINVAL;
 		}
@@ -3150,7 +3406,7 @@
 	if (off >= len+begin)
 		return 0;
 
-	*start = page + (begin-off);
+	*start = page + (off-begin);
 	return ((count < begin+len-off) ? count : begin+len-off);
  }
  

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)