File: /usr/src/linux/drivers/char/ip2main.c

1     /*
2     *
3     *   (c) 1999 by Computone Corporation
4     *
5     ********************************************************************************
6     *
7     *   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
8     *                serial I/O controllers.
9     *
10     *   DESCRIPTION: Mainline code for the device driver
11     *
12     *******************************************************************************/
13     // ToDo:
14     //
15     // Done:
16     //
17     // 1.2.9
18     // Four box EX was barfing on >128k kmalloc, made structure smaller by
19     // reducing output buffer size
20     //
21     // 1.2.8
22     // Device file system support (MHW)
23     //
24     // 1.2.7 
25     // Fixed
26     // Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
27     //
28     // 1.2.6
29     //Fixes DCD problems
30     //	DCD was not reported when CLOCAL was set on call to TIOCMGET
31     //
32     //Enhancements:
33     //	TIOCMGET requests and waits for status return
34     //	No DSS interrupts enabled except for DCD when needed
35     //
36     // For internal use only
37     //
38     //#define IP2DEBUG_INIT
39     //#define IP2DEBUG_OPEN
40     //#define IP2DEBUG_WRITE
41     //#define IP2DEBUG_READ
42     //#define IP2DEBUG_IOCTL
43     //#define IP2DEBUG_IPL
44     
45     //#define IP2DEBUG_TRACE
46     //#define DEBUG_FIFO
47     
48     /************/
49     /* Includes */
50     /************/
51     #include <linux/config.h>
52     // Uncomment the following if you want it compiled with modversions
53     
54     #include <linux/version.h>
55     
56     #include <linux/ctype.h>
57     #include <linux/string.h>
58     #include <linux/fcntl.h>
59     #include <linux/errno.h>
60     #include <linux/module.h>
61     #include <linux/signal.h>
62     #include <linux/sched.h>
63     #ifdef	CONFIG_DEVFS_FS
64     #include <linux/devfs_fs_kernel.h>
65     #endif
66     #include <linux/timer.h>
67     #include <linux/interrupt.h>
68     #include <linux/pci.h>
69     #include <linux/mm.h>
70     #include <linux/slab.h>
71     #include <linux/major.h>
72     #include <linux/wait.h>
73     
74     #include <linux/tty.h>
75     #include <linux/tty_flip.h>
76     #include <linux/termios.h>
77     #include <linux/tty_driver.h>
78     #include <linux/serial.h>
79     #include <linux/ptrace.h>
80     #include <linux/ioport.h>
81     
82     #include <linux/cdk.h>
83     #include <linux/comstats.h>
84     #include <linux/delay.h>
85     
86     #include <asm/system.h>
87     #include <asm/io.h>
88     #include <asm/irq.h>
89     #include <asm/bitops.h>
90     
91     #ifndef KERNEL_VERSION
92     #define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
93     #endif
94     
95     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
96     #	include <linux/vmalloc.h>
97     #	include <linux/init.h>
98     #	include <asm/serial.h>
99     #else
100     #	include <linux/bios32.h>
101     #endif
102     
103     // These VERSION switches maybe inexact because I simply don't know
104     // when the various features appeared in the 2.1.XX kernels.
105     // They are good enough for 2.0 vs 2.2 and if you are fooling with
106     // the 2.1.XX stuff then it would be trivial for you to fix.
107     // Most of these macros were stolen from some other drivers
108     // so blame them.
109     
110     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)
111     #	include <asm/segment.h>
112     #	define GET_USER(error,value,addr) error = get_user(value,addr)
113     #	define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
114     #	define PUT_USER(error,value,addr) error = put_user(value,addr)
115     #	define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
116     
117     #	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)
118     #		include <asm/uaccess.h>
119     #		define		pcibios_strerror(status)	\
120     					printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
121     #	endif
122     
123     #else  /* 2.0.x and 2.1.x before 2.1.4 */
124     
125     #	define		proc_register_dynamic(a,b) proc_register(a,b) 
126     
127     #	define GET_USER(error,value,addr)					  \
128     	do {									  \
129     		error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
130     		if (error == 0)							  \
131     			value = get_user(addr);					  \
132     	} while (0)
133     
134     #	define COPY_FROM_USER(error,dest,src,size)				  \
135     	do {									  \
136     		error = verify_area (VERIFY_READ, (void *) src, size);		  \
137     		if (error == 0)							  \
138     			memcpy_fromfs (dest, src, size);			  \
139     	} while (0)
140     
141     #	define PUT_USER(error,value,addr)					   \
142     	do {									   \
143     		error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
144     		if (error == 0)							   \
145     			put_user (value, addr);					   \
146     	} while (0)
147     
148     #	define COPY_TO_USER(error,dest,src,size)				  \
149     	do {									  \
150     		error = verify_area (VERIFY_WRITE, (void *) dest, size);		  \
151     		if (error == 0)							  \
152     			memcpy_tofs (dest, src, size);				  \
153     	} while (0)
154     
155     #endif
156     
157     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
158     #define __init
159     #define __initfunc(a) a
160     #define __initdata
161     #define ioremap(a,b) vremap((a),(b))
162     #define iounmap(a) vfree((a))
163     #define SERIAL_TYPE_NORMAL	1
164     #define SERIAL_TYPE_CALLOUT	2
165     #define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
166     #define signal_pending(a) ((a)->signal & ~(a)->blocked)
167     #define in_interrupt()	intr_count
168     #endif
169     
170     #include "./ip2/ip2types.h"
171     #include "./ip2/ip2trace.h"
172     #include "./ip2/ip2ioctl.h"
173     #include "./ip2/ip2.h"
174     #include "./ip2/i2ellis.h"
175     #include "./ip2/i2lib.h"
176     
177     /*****************
178      * /proc/ip2mem  *
179      *****************/
180     
181     #include <linux/proc_fs.h>
182     
183     static int ip2_read_procmem(char *, char **, off_t, int);
184     int ip2_read_proc(char *, char **, off_t, int, int *, void * );
185     
186     /********************/
187     /* Type Definitions */
188     /********************/
189     
190     /*************/
191     /* Constants */
192     /*************/
193     
194     /* String constants to identify ourselves */
195     static char *pcName    = "Computone IntelliPort Plus multiport driver";
196     static char *pcVersion = "1.2.9";
197     
198     /* String constants for port names */
199     static char *pcDriver_name   = "ip2";
200     #ifdef	CONFIG_DEVFS_FS
201     static char *pcTty    		 = "ttf/%d";
202     static char *pcCallout		 = "cuf/%d";
203     #else
204     static char *pcTty    		 = "ttyF";
205     static char *pcCallout		 = "cuf";
206     #endif
207     static char *pcIpl    		 = "ip2ipl";
208     
209     /* Serial subtype definitions */
210     #define SERIAL_TYPE_NORMAL    1
211     #define SERIAL_TYPE_CALLOUT   2
212     
213     // cheezy kludge or genius - you decide?
214     int ip2_loadmain(int *, int *, unsigned char *, int);
215     static unsigned char *Fip_firmware;
216     static int Fip_firmware_size;
217     
218     /***********************/
219     /* Function Prototypes */
220     /***********************/
221     
222     /* Global module entry functions */
223     #ifdef MODULE
224     int init_module(void);
225     void cleanup_module(void);
226     #endif
227     
228     int old_ip2_init(void);
229     
230     /* Private (static) functions */
231     static int  ip2_open(PTTY, struct file *);
232     static void ip2_close(PTTY, struct file *);
233     static int  ip2_write(PTTY, int, const unsigned char *, int);
234     static void ip2_putchar(PTTY, unsigned char);
235     static void ip2_flush_chars(PTTY);
236     static int  ip2_write_room(PTTY);
237     static int  ip2_chars_in_buf(PTTY);
238     static void ip2_flush_buffer(PTTY);
239     static int  ip2_ioctl(PTTY, struct file *, UINT, ULONG);
240     static void ip2_set_termios(PTTY, struct termios *);
241     static void ip2_set_line_discipline(PTTY);
242     static void ip2_throttle(PTTY);
243     static void ip2_unthrottle(PTTY);
244     static void ip2_stop(PTTY);
245     static void ip2_start(PTTY);
246     static void ip2_hangup(PTTY);
247     
248     static void set_irq(int, int);
249     static void ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs);
250     static void ip2_poll(unsigned long arg);
251     static inline void service_all_boards(void);
252     static inline void do_input(i2ChanStrPtr pCh);
253     static inline void do_status(i2ChanStrPtr pCh);
254     
255     static void ip2_wait_until_sent(PTTY,int);
256     
257     static void set_params (i2ChanStrPtr, struct termios *);
258     static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);
259     static int get_serial_info(i2ChanStrPtr, struct serial_struct *);
260     static int set_serial_info(i2ChanStrPtr, struct serial_struct *);
261     
262     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
263     static int     ip2_ipl_read(struct inode *, char *, size_t , loff_t *);
264     #else
265     static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ;
266     #endif
267     static ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *);
268     static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
269     static int ip2_ipl_open(struct inode *, struct file *);
270     
271     void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
272     static int DumpTraceBuffer(char *, int);
273     static int DumpFifoBuffer( char *, int);
274     
275     static void ip2_init_board(int);
276     static unsigned short find_eisa_board(int);
277     
278     /***************/
279     /* Static Data */
280     /***************/
281     
282     static struct tty_driver ip2_tty_driver;
283     static struct tty_driver ip2_callout_driver;
284     
285     static int ref_count;
286     
287     /* Here, then is a table of board pointers which the interrupt routine should
288      * scan through to determine who it must service.
289      */
290     static unsigned short i2nBoards; // Number of boards here
291     
292     static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
293     
294     static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
295     //DevTableMem just used to save addresses for kfree
296     static void  *DevTableMem[IP2_MAX_BOARDS];
297     
298     static struct tty_struct * TtyTable[IP2_MAX_PORTS];
299     static struct termios    * Termios[IP2_MAX_PORTS];
300     static struct termios    * TermiosLocked[IP2_MAX_PORTS];
301     
302     /* This is the driver descriptor for the ip2ipl device, which is used to
303      * download the loadware to the boards.
304      */
305     static struct file_operations ip2_ipl = {
306     	owner:		THIS_MODULE,
307     	read:		ip2_ipl_read,
308     	write:		ip2_ipl_write,
309     	ioctl:		ip2_ipl_ioctl,
310     	open:		ip2_ipl_open,
311     }; 
312     
313     static long irq_counter;
314     static long bh_counter;
315     
316     // Use immediate queue to service interrupts
317     //#define USE_IQI	// PCI&2.2 needs work
318     //#define USE_IQ	// PCI&2.2 needs work
319     
320     /* The timer_list entry for our poll routine. If interrupt operation is not
321      * selected, the board is serviced periodically to see if anything needs doing.
322      */
323     #define  POLL_TIMEOUT   (jiffies + 1)
324     static struct timer_list PollTimer = { function: ip2_poll };
325     static char  TimerOn;
326     
327     #ifdef IP2DEBUG_TRACE
328     /* Trace (debug) buffer data */
329     #define TRACEMAX  1000
330     static unsigned long tracebuf[TRACEMAX];
331     static int tracestuff;
332     static int tracestrip;
333     static int tracewrap;
334     #endif
335     
336     /**********/
337     /* Macros */
338     /**********/
339     
340     #if defined(MODULE) && defined(IP2DEBUG_OPEN)
341     #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
342     		    kdevname(tty->device),(pCh->flags),ref_count, \
343     		    tty->count,/*GET_USE_COUNT(module)*/0,s)
344     #else
345     #define DBG_CNT(s)
346     #endif
347     
348     #define MIN(a,b)	( ( (a) < (b) ) ? (a) : (b) )
349     #define MAX(a,b)	( ( (a) > (b) ) ? (a) : (b) )
350     
351     /********/
352     /* Code */
353     /********/
354     
355     #include "./ip2/i2ellis.c"    /* Extremely low-level interface services */
356     #include "./ip2/i2cmd.c"      /* Standard loadware command definitions */
357     #include "./ip2/i2lib.c"      /* High level interface services */
358     
359     /* Configuration area for modprobe */
360     #ifdef MODULE
361     #	if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
362     		MODULE_AUTHOR("Doug McNash");
363     		MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
364     #	endif	/* LINUX_VERSION */
365     #endif	/* MODULE */
366     
367     static int poll_only;
368     
369     static int Eisa_irq;
370     static int Eisa_slot;
371     
372     static int iindx;
373     static char rirqs[IP2_MAX_BOARDS];
374     static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
375     
376     /******************************************************************************/
377     /* Initialisation Section                                                     */
378     /******************************************************************************/
379     int 
380     ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize) 
381     {
382     	int i;
383     	/* process command line arguments to modprobe or insmod i.e. iop & irqp */
384     	/* otherwise ip2config is initialized by what's in ip2/ip2.h */
385     	/* command line trumps initialization in ip2.h */
386     	/* first two args are null if builtin to kernel */
387     	if ((irqp != NULL) || (iop != NULL)) {
388     		for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
389     			if (irqp && irqp[i]) {
390     				ip2config.irq[i] = irqp[i];
391     			}
392     			if (iop && iop[i]) {
393     				ip2config.addr[i] = iop[i];
394     			}
395     		}
396     	}
397     	Fip_firmware = firmware;
398     	Fip_firmware_size = firmsize;
399     	return old_ip2_init();
400     }
401     
402     // Some functions to keep track of what irq's we have
403     
404     static int __init
405     is_valid_irq(int irq)
406     {
407     	int *i = Valid_Irqs;
408     	
409     	while ((*i != 0) && (*i != irq)) {
410     		i++;
411     	}
412     	return (*i);
413     }
414     
415     static void __init
416     mark_requested_irq( char irq )
417     {
418     	rirqs[iindx++] = irq;
419     }
420     
421     #ifdef MODULE
422     static int __init
423     clear_requested_irq( char irq )
424     {
425     	int i;
426     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
427     		if (rirqs[i] == irq) {
428     			rirqs[i] = 0;
429     			return 1;
430     		}
431     	}
432     	return 0;
433     }
434     #endif
435     
436     static int __init
437     have_requested_irq( char irq )
438     {
439     	// array init to zeros so 0 irq will not be requested as a side effect
440     	int i;
441     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
442     		if (rirqs[i] == irq)
443     			return 1;
444     	}
445     	return 0;
446     }
447     
448     /******************************************************************************/
449     /* Function:   init_module()                                                  */
450     /* Parameters: None                                                           */
451     /* Returns:    Success (0)                                                    */
452     /*                                                                            */
453     /* Description:                                                               */
454     /* This is a required entry point for an installable module. It simply calls  */
455     /* the driver initialisation function and returns what it returns.            */
456     /******************************************************************************/
457     #ifdef MODULE
458     int
459     init_module(void)
460     {
461     #ifdef IP2DEBUG_INIT
462     	printk (KERN_DEBUG "Loading module ...\n" );
463     #endif
464         //was	return old_ip2_init();
465         return 0;
466     }
467     #endif /* MODULE */
468     
469     /******************************************************************************/
470     /* Function:   cleanup_module()                                               */
471     /* Parameters: None                                                           */
472     /* Returns:    Nothing                                                        */
473     /*                                                                            */
474     /* Description:                                                               */
475     /* This is a required entry point for an installable module. It has to return */
476     /* the device and the driver to a passive state. It should not be necessary   */
477     /* to reset the board fully, especially as the loadware is downloaded         */
478     /* externally rather than in the driver. We just want to disable the board    */
479     /* and clear the loadware to a reset state. To allow this there has to be a   */
480     /* way to detect whether the board has the loadware running at init time to   */
481     /* handle subsequent installations of the driver. All memory allocated by the */
482     /* driver should be returned since it may be unloaded from memory.            */
483     /******************************************************************************/
484     #ifdef MODULE
485     void
486     cleanup_module(void)
487     {
488     	int err;
489     	int i;
490     
491     #ifdef IP2DEBUG_INIT
492     	printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
493     #endif
494     	/* Stop poll timer if we had one. */
495     	if ( TimerOn ) {
496     		del_timer ( &PollTimer );
497     		TimerOn = 0;
498     	}
499     
500     	/* Reset the boards we have. */
501     	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
502     		if ( i2BoardPtrTable[i] ) {
503     			iiReset( i2BoardPtrTable[i] );
504     		}
505     	}
506     
507     	/* The following is done at most once, if any boards were installed. */
508     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
509     		if ( i2BoardPtrTable[i] ) {
510     			iiResetDelay( i2BoardPtrTable[i] );
511     			/* free io addresses and Tibet */
512     			release_region( ip2config.addr[i], 8 );
513     #ifdef	CONFIG_DEVFS_FS
514     			devfs_unregister (i2BoardPtrTable[i]->devfs_ipl_handle);
515     			devfs_unregister (i2BoardPtrTable[i]->devfs_stat_handle);
516     #endif
517     		}
518     		/* Disable and remove interrupt handler. */
519     		if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {	
520     			free_irq ( ip2config.irq[i], (void *)&pcName);
521     			clear_requested_irq( ip2config.irq[i]);
522     		}
523     	}
524     	if ( ( err = tty_unregister_driver ( &ip2_tty_driver ) ) ) {
525     		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
526     	}
527     	if ( ( err = tty_unregister_driver ( &ip2_callout_driver ) ) ) {
528     		printk(KERN_ERR "IP2: failed to unregister callout driver (%d)\n", err);
529     	}
530     #ifdef	CONFIG_DEVFS_FS
531     	if ( ( err = devfs_unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
532     #else
533     	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
534     #endif
535     	{
536     		printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
537     	}
538     	remove_proc_entry("ip2mem", &proc_root);
539     
540     	// free memory
541     	for (i = 0; i < IP2_MAX_BOARDS; i++) {
542     		void *pB;
543     		if ((pB = i2BoardPtrTable[i]) != 0 ) {
544     			kfree ( pB );
545     			i2BoardPtrTable[i] = NULL;
546     		}
547     		if ((DevTableMem[i]) != NULL ) {
548     			kfree ( DevTableMem[i]  );
549     			DevTableMem[i] = NULL;
550     		}
551     	}
552     
553     	/* Cleanup the iiEllis subsystem. */
554     	iiEllisCleanup();
555     #ifdef IP2DEBUG_INIT
556     	printk (KERN_DEBUG "IP2 Unloaded\n" );
557     #endif
558     }
559     #endif /* MODULE */
560     
561     /******************************************************************************/
562     /* Function:   old_ip2_init()                                                 */
563     /* Parameters: irq, io from command line of insmod et. al.                    */
564     /* Returns:    Success (0)                                                    */
565     /*                                                                            */
566     /* Description:                                                               */
567     /* This was the required entry point for all drivers (now in ip2.c)           */
568     /* It performs all                                                            */
569     /* initialisation of the devices and driver structures, and registers itself  */
570     /* with the relevant kernel modules.                                          */
571     /******************************************************************************/
572     /* SA_INTERRUPT- if set blocks all interrupts else only this line */
573     /* SA_SHIRQ    - for shared irq PCI or maybe EISA only */
574     /* SA_RANDOM   - can be source for cert. random number generators */
575     #define IP2_SA_FLAGS	0
576     
577     int __init
578     old_ip2_init(void)
579     {
580     #ifdef	CONFIG_DEVFS_FS
581     	static devfs_handle_t devfs_handle;
582     	int j, box;
583     #endif
584     	int i;
585     	int err;
586     	int status = 0;
587     	static int loaded;
588     	i2eBordStrPtr pB = NULL;
589     	int rc = -1;
590     
591     #ifdef IP2DEBUG_TRACE
592     	ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
593     #endif
594     
595     	/* Announce our presence */
596     	printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
597     
598     	// ip2 can be unloaded and reloaded for no good reason
599     	// we can't let that happen here or bad things happen
600     	// second load hoses board but not system - fixme later
601     	if (loaded) {
602     		printk( KERN_INFO "Still loaded\n" );
603     		return 0;
604     	}
605     	loaded++;
606     
607     	/* if all irq config is zero we shall poll_only */
608     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
609     		poll_only |= ip2config.irq[i];
610     	}
611     	poll_only = !poll_only;
612     
613     	/* Initialise the iiEllis subsystem. */
614     	iiEllisInit();
615     
616     	/* Initialize arrays. */
617     	memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
618     	memset( DevTable, 0, sizeof DevTable );
619     	memset( TtyTable, 0, sizeof TtyTable );
620     	memset( Termios, 0, sizeof Termios );
621     	memset( TermiosLocked, 0, sizeof TermiosLocked );
622     
623     	/* Initialise all the boards we can find (up to the maximum). */
624     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
625     		switch ( ip2config.addr[i] ) { 
626     		case 0:	/* skip this slot even if card is present */
627     			break;
628     		default: /* ISA */
629     		   /* ISA address must be specified */
630     			if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
631     				printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
632     							 i, ip2config.addr[i] );
633     				ip2config.addr[i] = 0;
634     			} else {
635     				ip2config.type[i] = ISA;
636     
637     				/* Check for valid irq argument, set for polling if invalid */
638     				if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
639     					printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
640     					ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
641     				}
642     			}
643     			break;
644     		case PCI:
645     #ifdef CONFIG_PCI
646     #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
647     			if (pcibios_present()) {
648     				unsigned char pci_bus, pci_devfn;
649     				int Pci_index = 0;
650     				status = pcibios_find_device(PCI_VENDOR_ID_COMPUTONE,
651     							  PCI_DEVICE_ID_COMPUTONE_IP2EX, Pci_index,
652     							  &pci_bus, &pci_devfn);
653     				if (status == 0) {
654     					unsigned int addr;
655     					unsigned char pci_irq;
656     
657     					ip2config.type[i] = PCI;
658     					/* 
659     					 * Update Pci_index, so that the next time we go
660     					 * searching for a PCI board we find a different
661     					 * one.
662     					 */
663     					++Pci_index;
664     
665     					pcibios_read_config_dword(pci_bus, pci_devfn,
666     								  PCI_BASE_ADDRESS_1, &addr);
667     					if ( addr & 1 ) {
668     						ip2config.addr[i]=(USHORT)(addr&0xfffe);
669     					} else {
670     						printk( KERN_ERR "IP2: PCI I/O address error\n");
671     					}
672     					pcibios_read_config_byte(pci_bus, pci_devfn,
673     								  PCI_INTERRUPT_LINE, &pci_irq);
674     
675     					if (!is_valid_irq(pci_irq)) {
676     						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
677     						pci_irq = 0;
678     					}
679     					ip2config.irq[i] = pci_irq;
680     				} else {	// ann error
681     					ip2config.addr[i] = 0;
682     					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
683     						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
684     					} else {
685     						pcibios_strerror(status);
686     					}
687     				} 
688     			} 
689     #else /* LINUX_VERSION_CODE > 2.1.99 */
690     			if (pci_present()) {
691     				struct pci_dev *pci_dev_i = NULL;
692     				pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
693     							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
694     				if (pci_dev_i != NULL) {
695     					unsigned int addr;
696     					unsigned char pci_irq;
697     
698     					ip2config.type[i] = PCI;
699     					status =
700     					pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
701     					if ( addr & 1 ) {
702     						ip2config.addr[i]=(USHORT)(addr&0xfffe);
703     					} else {
704     						printk( KERN_ERR "IP2: PCI I/O address error\n");
705     					}
706     					status =
707     					pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
708     
709     					if (!is_valid_irq(pci_irq)) {
710     						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
711     						pci_irq = 0;
712     					}
713     					ip2config.irq[i] = pci_irq;
714     				} else {	// ann error
715     					ip2config.addr[i] = 0;
716     					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
717     						printk( KERN_ERR "IP2: PCI board %d not found\n", i );
718     					} else {
719     						pcibios_strerror(status);
720     					}
721     				} 
722     			} 
723     #endif	/* ! 2_0_X */
724     #else
725     			printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
726     			printk( KERN_ERR "IP2: configured in this kernel.\n");
727     			printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
728     #endif /* CONFIG_PCI */
729     			break;
730     		case EISA:
731     			if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
732     				/* Eisa_irq set as side effect, boo */
733     				ip2config.type[i] = EISA;
734     			} 
735     			ip2config.irq[i] = Eisa_irq;
736     			break;
737     		}	/* switch */
738     	}	/* for */
739     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
740     		if ( ip2config.addr[i] ) {
741     			pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL);
742     			if ( pB != NULL ) {
743     				i2BoardPtrTable[i] = pB;
744     				memset( pB, 0, sizeof(i2eBordStr) );
745     				iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
746     				iiReset( pB );
747     			} else {
748     				printk(KERN_ERR "IP2: board memory allocation error\n");
749     			}
750     		}
751     	}
752     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
753     		if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
754     			iiResetDelay( pB );
755     			break;
756     		}
757     	}
758     	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
759     		if ( i2BoardPtrTable[i] != NULL ) {
760     			ip2_init_board( i );
761     		}
762     	}
763     
764     #ifdef IP2DEBUG_TRACE
765     	ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
766     #endif
767     
768     	/* Zero out the normal tty device structure. */
769     	memset ( &ip2_tty_driver, 0, sizeof ip2_tty_driver );
770     
771     	/* Initialise the relevant fields. */
772     	ip2_tty_driver.magic                = TTY_DRIVER_MAGIC;
773     	ip2_tty_driver.name                 = pcTty;
774     #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
775     	ip2_tty_driver.driver_name          = pcDriver_name;
776     	ip2_tty_driver.read_proc          	= ip2_read_proc;
777     #endif
778     	ip2_tty_driver.major                = IP2_TTY_MAJOR;
779     	ip2_tty_driver.minor_start          = 0;
780     	ip2_tty_driver.num                  = IP2_MAX_PORTS;
781     	ip2_tty_driver.type                 = TTY_DRIVER_TYPE_SERIAL;
782     	ip2_tty_driver.subtype              = SERIAL_TYPE_NORMAL;
783     	ip2_tty_driver.init_termios         = tty_std_termios;
784     	ip2_tty_driver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
785     #ifdef	CONFIG_DEVFS_FS
786     	ip2_tty_driver.flags                = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
787     #else
788     	ip2_tty_driver.flags                = TTY_DRIVER_REAL_RAW;
789     #endif
790     	ip2_tty_driver.refcount             = &ref_count;
791     	ip2_tty_driver.table                = TtyTable;
792     	ip2_tty_driver.termios              = Termios;
793     	ip2_tty_driver.termios_locked       = TermiosLocked;
794     
795     	/* Setup the pointers to the implemented functions. */
796     	ip2_tty_driver.open            = ip2_open;
797     	ip2_tty_driver.close           = ip2_close;
798     	ip2_tty_driver.write           = ip2_write;
799     	ip2_tty_driver.put_char        = ip2_putchar;
800     	ip2_tty_driver.flush_chars     = ip2_flush_chars;
801     	ip2_tty_driver.write_room      = ip2_write_room;
802     	ip2_tty_driver.chars_in_buffer = ip2_chars_in_buf;
803     	ip2_tty_driver.flush_buffer    = ip2_flush_buffer;
804     	ip2_tty_driver.ioctl           = ip2_ioctl;
805     	ip2_tty_driver.throttle        = ip2_throttle;
806     	ip2_tty_driver.unthrottle      = ip2_unthrottle;
807     	ip2_tty_driver.set_termios     = ip2_set_termios;
808     	ip2_tty_driver.set_ldisc       = ip2_set_line_discipline;
809     	ip2_tty_driver.stop            = ip2_stop;
810     	ip2_tty_driver.start           = ip2_start;
811     	ip2_tty_driver.hangup          = ip2_hangup;
812     
813     	/* Initialise the callout driver structure from the tty driver, and
814     	 * make the needed adjustments.
815     	 */
816     	ip2_callout_driver         = ip2_tty_driver;
817     	ip2_callout_driver.name    = pcCallout;
818     #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
819     	ip2_callout_driver.driver_name = pcDriver_name;
820     	ip2_callout_driver.read_proc  = NULL;
821     #endif
822     	ip2_callout_driver.major   = IP2_CALLOUT_MAJOR;
823     	ip2_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
824     
825     #ifdef IP2DEBUG_TRACE
826     	ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
827     #endif
828     
829     	/* Register the tty devices. */
830     	if ( ( err = tty_register_driver ( &ip2_tty_driver ) ) ) {
831     		printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
832     	} else
833     	if ( ( err = tty_register_driver ( &ip2_callout_driver ) ) ) {
834     		printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err);
835     	} else
836     	/* Register the IPL driver. */
837     #ifdef	CONFIG_DEVFS_FS
838     	if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl )))
839     #else
840     	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) )
841     #endif
842     	{
843     		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
844     	} else
845     	/* Register the read_procmem thing */
846     	if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) {
847     		printk(KERN_ERR "IP2: failed to register read_procmem\n");
848     	} else {
849     
850     #ifdef IP2DEBUG_TRACE
851     	ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
852     #endif
853     		/* Register the interrupt handler or poll handler, depending upon the
854     		 * specified interrupt.
855     		 */
856     #ifdef	CONFIG_DEVFS_FS
857     		if (!devfs_handle)
858     			devfs_handle = devfs_mk_dir (NULL, "ip2", NULL);
859     #endif
860     
861     		for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
862     #ifdef	CONFIG_DEVFS_FS
863     			char name[16];
864     #endif
865     
866     			if ( 0 == ip2config.addr[i] ) {
867     				continue;
868     			}
869     
870     #ifdef	CONFIG_DEVFS_FS
871     			sprintf( name, "ipl%d", i );
872     			i2BoardPtrTable[i]->devfs_ipl_handle =
873     				devfs_register (devfs_handle, name,
874     					DEVFS_FL_DEFAULT,
875     					IP2_IPL_MAJOR, 4 * i,
876     					S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
877     					&ip2_ipl, NULL);
878     
879     			sprintf( name, "stat%d", i );
880     			i2BoardPtrTable[i]->devfs_stat_handle =
881     				devfs_register (devfs_handle, name,
882     					DEVFS_FL_DEFAULT,
883     					IP2_IPL_MAJOR, 4 * i + 1,
884     					S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
885     					&ip2_ipl, NULL);
886     
887     			for ( box = 0; box < ABS_MAX_BOXES; ++box )
888     			{
889     			    for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
890     			    {
891     				if ( pB->i2eChannelMap[box] & (1 << j) )
892     				{
893     				    tty_register_devfs(&ip2_tty_driver,
894     					0, j + ABS_BIGGEST_BOX *
895     						(box+i*ABS_MAX_BOXES));
896     				    tty_register_devfs(&ip2_callout_driver,
897     					0, j + ABS_BIGGEST_BOX *
898     						(box+i*ABS_MAX_BOXES));
899     				}
900     			    }
901     			}
902     #endif
903     
904     			if (poll_only) {
905     					ip2config.irq[i] = CIR_POLL;
906     			}
907     			if ( ip2config.irq[i] == CIR_POLL ) {
908     retry:
909     				if (!TimerOn) {
910     					PollTimer.expires = POLL_TIMEOUT;
911     					add_timer ( &PollTimer );
912     					TimerOn = 1;
913     					printk( KERN_INFO "IP2: polling\n");
914     				}
915     			} else {
916     				if (have_requested_irq(ip2config.irq[i]))
917     					continue;
918     				rc = request_irq( ip2config.irq[i], ip2_interrupt,
919     					IP2_SA_FLAGS | (ip2config.type[i] == PCI ? SA_SHIRQ : 0),
920     					pcName, (void *)&pcName);
921     				if (rc) {
922     					printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
923     					ip2config.irq[i] = CIR_POLL;
924     					printk( KERN_INFO "IP2: Polling %ld/sec.\n",
925     							(POLL_TIMEOUT - jiffies));
926     					goto retry;
927     				} 
928     				mark_requested_irq(ip2config.irq[i]);
929     				/* Initialise the interrupt handler bottom half (aka slih). */
930     			}
931     		}
932     		for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
933     			if ( i2BoardPtrTable[i] ) {
934     				set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
935     			}
936     		}
937     	}
938     #ifdef IP2DEBUG_TRACE
939     	ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
940     #endif
941     
942     	return 0;
943     }
944     
945     /******************************************************************************/
946     /* Function:   ip2_init_board()                                               */
947     /* Parameters: Index of board in configuration structure                      */
948     /* Returns:    Success (0)                                                    */
949     /*                                                                            */
950     /* Description:                                                               */
951     /* This function initializes the specified board. The loadware is copied to   */
952     /* the board, the channel structures are initialized, and the board details   */
953     /* are reported on the console.                                               */
954     /******************************************************************************/
955     static void __init
956     ip2_init_board( int boardnum )
957     {
958     	int i,rc;
959     	int nports = 0, nboxes = 0;
960     	i2ChanStrPtr pCh;
961     	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
962     
963     	if ( !iiInitialize ( pB ) ) {
964     		printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
965     			 pB->i2eBase, pB->i2eError );
966     		kfree ( pB );
967     		i2BoardPtrTable[boardnum] = NULL;
968     		return;
969     	}
970     	printk(KERN_INFO "Board %d: addr=0x%x irq=%d ", boardnum + 1,
971     	       ip2config.addr[boardnum], ip2config.irq[boardnum] );
972     
973     	if (0 != ( rc = check_region( ip2config.addr[boardnum], 8))) {
974     		i2BoardPtrTable[boardnum] = NULL;
975     		printk(KERN_ERR "bad addr=0x%x rc = %d\n",
976     				ip2config.addr[boardnum], rc );
977     		return;
978     	}
979     	request_region( ip2config.addr[boardnum], 8, pcName );
980     
981     	if ( iiDownloadAll ( pB, (loadHdrStrPtr)Fip_firmware, 1, Fip_firmware_size )
982     	    != II_DOWN_GOOD ) {
983     		printk ( KERN_ERR "IP2:failed to download loadware " );
984     	} else {
985     		printk ( KERN_INFO "fv=%d.%d.%d lv=%d.%d.%d\n",
986     			 pB->i2ePom.e.porVersion,
987     			 pB->i2ePom.e.porRevision,
988     			 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
989     			 pB->i2eLRevision, pB->i2eLSub );
990     	}
991     
992     	switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
993     
994     	default:
995     		printk( KERN_ERR "IP2: Unknown board type, ID = %x",
996     				pB->i2ePom.e.porID );
997     		nports = 0;
998     		goto ex_exit;
999     		break;
1000     
1001     	case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
1002     		printk ( KERN_INFO "ISA-4" );
1003     		nports = 4;
1004     		break;
1005     
1006     	case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
1007     		printk ( KERN_INFO "ISA-8 std" );
1008     		nports = 8;
1009     		break;
1010     
1011     	case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
1012     		printk ( KERN_INFO "ISA-8 RJ11" );
1013     		nports = 8;
1014     		break;
1015     
1016     	case POR_ID_FIIEX: /* IntelliPort IIEX */
1017     	{
1018     		int portnum = IP2_PORTS_PER_BOARD * boardnum;
1019     		int            box;
1020     
1021     		for( box = 0; box < ABS_MAX_BOXES; ++box ) {
1022     			if ( pB->i2eChannelMap[box] != 0 ) {
1023     				++nboxes;
1024     			}
1025     			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
1026     				if ( pB->i2eChannelMap[box] & 1<< i ) {
1027     					++nports;
1028     				}
1029     			}
1030     		}
1031     		DevTableMem[boardnum] = pCh =
1032     			kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
1033     		if ( !i2InitChannels( pB, nports, pCh ) ) {
1034     			printk(KERN_ERR "i2InitChannels failed: %d\n",pB->i2eError);
1035     		}
1036     		pB->i2eChannelPtr = &DevTable[portnum];
1037     		pB->i2eChannelCnt = ABS_MOST_PORTS;
1038     
1039     		for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
1040     			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
1041     				if ( pB->i2eChannelMap[box] & (1 << i) ) {
1042     					DevTable[portnum + i] = pCh;
1043     					pCh->port_index = portnum + i;
1044     					pCh++;
1045     				}
1046     			}
1047     		}
1048     		printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit",
1049     			nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
1050     		}
1051     		goto ex_exit;
1052     		break;
1053     	}
1054     	DevTableMem[boardnum] = pCh =
1055     		kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
1056     	pB->i2eChannelPtr = pCh;
1057     	pB->i2eChannelCnt = nports;
1058     	i2InitChannels ( pB, pB->i2eChannelCnt, pCh );
1059     	pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
1060     
1061     	for( i = 0; i < pB->i2eChannelCnt; ++i ) {
1062     		DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
1063     		pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
1064     		pCh++;
1065     	}
1066     ex_exit:
1067     	printk ( KERN_INFO "\n" );
1068     }
1069     
1070     /******************************************************************************/
1071     /* Function:   find_eisa_board ( int start_slot )                             */
1072     /* Parameters: First slot to check                                            */
1073     /* Returns:    Address of EISA IntelliPort II controller                      */
1074     /*                                                                            */
1075     /* Description:                                                               */
1076     /* This function searches for an EISA IntelliPort controller, starting        */
1077     /* from the specified slot number. If the motherboard is not identified as an */
1078     /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
1079     /* it returns the base address of the controller.                             */
1080     /******************************************************************************/
1081     static unsigned short __init
1082     find_eisa_board( int start_slot )
1083     {
1084     	int i, j;
1085     	unsigned int idm = 0;
1086     	unsigned int idp = 0;
1087     	unsigned int base = 0;
1088     	unsigned int value;
1089     	int setup_address;
1090     	int setup_irq;
1091     	int ismine = 0;
1092     
1093     	/*
1094     	 * First a check for an EISA motherboard, which we do by comparing the
1095     	 * EISA ID registers for the system board and the first couple of slots.
1096     	 * No slot ID should match the system board ID, but on an ISA or PCI
1097     	 * machine the odds are that an empty bus will return similar values for
1098     	 * each slot.
1099     	 */
1100     	i = 0x0c80;
1101     	value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
1102     	for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
1103     		j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
1104     		if ( value == j )
1105     			return 0;
1106     	}
1107     
1108     	/*
1109     	 * OK, so we are inclined to believe that this is an EISA machine. Find
1110     	 * an IntelliPort controller.
1111     	 */
1112     	for( i = start_slot; i < 16; i++ ) {
1113     		base = i << 12;
1114     		idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
1115     		idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
1116     		ismine = 0;
1117     		if ( idm == 0x0e8e ) {
1118     			if ( idp == 0x0281 || idp == 0x0218 ) {
1119     				ismine = 1;
1120     			} else if ( idp == 0x0282 || idp == 0x0283 ) {
1121     				ismine = 3;	/* Can do edge-trigger */
1122     			}
1123     			if ( ismine ) {
1124     				Eisa_slot = i;
1125     				break;
1126     			}
1127     		}
1128     	}
1129     	if ( !ismine )
1130     		return 0;
1131     
1132     	/* It's some sort of EISA card, but at what address is it configured? */
1133     
1134     	setup_address = base + 0xc88;
1135     	value = inb(base + 0xc86);
1136     	setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
1137     
1138     	if ( (ismine & 2) && !(value & 0x10) ) {
1139     		ismine = 1;	/* Could be edging, but not */
1140     	}
1141     
1142     	if ( Eisa_irq == 0 ) {
1143     		Eisa_irq = setup_irq;
1144     	} else if ( Eisa_irq != setup_irq ) {
1145     		printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
1146     	}
1147     
1148     #ifdef IP2DEBUG_INIT
1149     printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
1150     	       base >> 12, idm, idp, setup_address);
1151     	if ( Eisa_irq ) {
1152     		printk(KERN_DEBUG ", Interrupt %d %s\n",
1153     		       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
1154     	} else {
1155     		printk(KERN_DEBUG ", (polled)\n");
1156     	}
1157     #endif
1158     	return setup_address;
1159     }
1160     
1161     /******************************************************************************/
1162     /* Function:   set_irq()                                                      */
1163     /* Parameters: index to board in board table                                  */
1164     /*             IRQ to use                                                     */
1165     /* Returns:    Success (0)                                                    */
1166     /*                                                                            */
1167     /* Description:                                                               */
1168     /******************************************************************************/
1169     static void
1170     set_irq( int boardnum, int boardIrq )
1171     {
1172     	unsigned char tempCommand[16];
1173     	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
1174     	unsigned long flags;
1175     
1176     	/*
1177     	 * Notify the boards they may generate interrupts. This is done by
1178     	 * sending an in-line command to channel 0 on each board. This is why
1179     	 * the channels have to be defined already. For each board, if the
1180     	 * interrupt has never been defined, we must do so NOW, directly, since
1181     	 * board will not send flow control or even give an interrupt until this
1182     	 * is done.  If polling we must send 0 as the interrupt parameter.
1183     	 */
1184     
1185     	// We will get an interrupt here at the end of this function
1186     
1187     	iiDisableMailIrq(pB);
1188     
1189     	/* We build up the entire packet header. */
1190     	CHANNEL_OF(tempCommand) = 0;
1191     	PTYPE_OF(tempCommand) = PTYPE_INLINE;
1192     	CMD_COUNT_OF(tempCommand) = 2;
1193     	(CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
1194     	(CMD_OF(tempCommand))[1] = boardIrq;
1195     	/*
1196     	 * Write to FIFO; don't bother to adjust fifo capacity for this, since
1197     	 * board will respond almost immediately after SendMail hit.
1198     	 */
1199     	WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1200     	iiWriteBuf(pB, tempCommand, 4);
1201     	WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1202     	pB->i2eUsingIrq = boardIrq;
1203     	pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
1204     
1205     	/* Need to update number of boards before you enable mailbox int */
1206     	++i2nBoards;
1207     
1208     	CHANNEL_OF(tempCommand) = 0;
1209     	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1210     	CMD_COUNT_OF(tempCommand) = 6;
1211     	(CMD_OF(tempCommand))[0] = 88;	// SILO
1212     	(CMD_OF(tempCommand))[1] = 64;	// chars
1213     	(CMD_OF(tempCommand))[2] = 32;	// ms
1214     
1215     	(CMD_OF(tempCommand))[3] = 28;	// MAX_BLOCK
1216     	(CMD_OF(tempCommand))[4] = 64;	// chars
1217     
1218     	(CMD_OF(tempCommand))[5] = 87;	// HW_TEST
1219     	WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1220     	iiWriteBuf(pB, tempCommand, 8);
1221     	WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1222     
1223     	CHANNEL_OF(tempCommand) = 0;
1224     	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1225     	CMD_COUNT_OF(tempCommand) = 1;
1226     	(CMD_OF(tempCommand))[0] = 84;	/* get BOX_IDS */
1227     	iiWriteBuf(pB, tempCommand, 3);
1228     
1229     #ifdef XXX
1230     	// enable heartbeat for test porpoises
1231     	CHANNEL_OF(tempCommand) = 0;
1232     	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1233     	CMD_COUNT_OF(tempCommand) = 2;
1234     	(CMD_OF(tempCommand))[0] = 44;	/* get ping */
1235     	(CMD_OF(tempCommand))[1] = 200;	/* 200 ms */
1236     	WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1237     	iiWriteBuf(pB, tempCommand, 4);
1238     	WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1239     #endif
1240     
1241     	iiEnableMailIrq(pB);
1242     	iiSendPendingMail(pB);
1243     }
1244     
1245     /******************************************************************************/
1246     /* Interrupt Handler Section                                                  */
1247     /******************************************************************************/
1248     
1249     static inline void
1250     service_all_boards()
1251     {
1252     	int i;
1253     	i2eBordStrPtr  pB;
1254     
1255     	/* Service every board on the list */
1256     	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
1257     		pB = i2BoardPtrTable[i];
1258     		if ( pB ) {
1259     			i2ServiceBoard( pB );
1260     		}
1261     	}
1262     }
1263     
1264     
1265     #ifdef USE_IQI
1266     static struct tq_struct 
1267     senior_service =
1268     {	// it's the death that worse than fate
1269     	NULL,
1270     	0,
1271     	(void(*)(void*)) service_all_boards,
1272     	NULL,	//later - board address XXX
1273     };
1274     #endif
1275     
1276     /******************************************************************************/
1277     /* Function:   ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs)    */
1278     /* Parameters: irq - interrupt number                                         */
1279     /*             pointer to optional device ID structure                        */
1280     /*             pointer to register structure                                  */
1281     /* Returns:    Nothing                                                        */
1282     /*                                                                            */
1283     /* Description:                                                               */
1284     /*                                                                            */
1285     /*                                                                            */
1286     /******************************************************************************/
1287     static void
1288     ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs)
1289     {
1290     	int i;
1291     	i2eBordStrPtr  pB;
1292     
1293     #ifdef IP2DEBUG_TRACE
1294     	ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
1295     #endif
1296     
1297     #ifdef USE_IQI
1298     
1299     	queue_task(&senior_service, &tq_immediate);
1300     	mark_bh(IMMEDIATE_BH);
1301     
1302     #else
1303     	/* Service just the boards on the list using this irq */
1304     	for( i = 0; i < i2nBoards; ++i ) {
1305     		pB = i2BoardPtrTable[i];
1306     		if ( pB && (pB->i2eUsingIrq == irq) ) {
1307     			i2ServiceBoard( pB );
1308     		}
1309     	}
1310     
1311     #endif /* USE_IQI */
1312     
1313     	++irq_counter;
1314     
1315     #ifdef IP2DEBUG_TRACE
1316     	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1317     #endif
1318     }
1319     
1320     /******************************************************************************/
1321     /* Function:   ip2_poll(unsigned long arg)                                    */
1322     /* Parameters: ?                                                              */
1323     /* Returns:    Nothing                                                        */
1324     /*                                                                            */
1325     /* Description:                                                               */
1326     /* This function calls the library routine i2ServiceBoard for each board in   */
1327     /* the board table. This is used instead of the interrupt routine when polled */
1328     /* mode is specified.                                                         */
1329     /******************************************************************************/
1330     static void
1331     ip2_poll(unsigned long arg)
1332     {
1333     #ifdef IP2DEBUG_TRACE
1334     	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
1335     #endif
1336     	TimerOn = 0; // it's the truth but not checked in service
1337     
1338     	bh_counter++; 
1339     
1340     #ifdef USE_IQI
1341     
1342     	queue_task(&senior_service, &tq_immediate);
1343     	mark_bh(IMMEDIATE_BH);
1344     
1345     #else
1346     	// Just polled boards, service_all might be better
1347     	ip2_interrupt(0, NULL, NULL);
1348     
1349     #endif /* USE_IQI */
1350     
1351     	PollTimer.expires = POLL_TIMEOUT;
1352     	add_timer( &PollTimer );
1353     	TimerOn = 1;
1354     
1355     #ifdef IP2DEBUG_TRACE
1356     	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1357     #endif
1358     }
1359     
1360     static inline void 
1361     do_input( i2ChanStrPtr pCh )
1362     {
1363     	unsigned long flags;
1364     
1365     #ifdef IP2DEBUG_TRACE
1366     	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
1367     #endif
1368     	// Data input
1369     	if ( pCh->pTTY != NULL ) {
1370     		READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
1371     		if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
1372     			READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
1373     			i2Input( pCh );
1374     		} else
1375     			READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
1376     	} else {
1377     #ifdef IP2DEBUG_TRACE
1378     		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
1379     #endif
1380     		i2InputFlush( pCh );
1381     	}
1382     }
1383     
1384     // code duplicated from n_tty (ldisc)
1385     static inline void 
1386     isig(int sig, struct tty_struct *tty, int flush)
1387     {
1388     	if (tty->pgrp > 0)
1389     		kill_pg(tty->pgrp, sig, 1);
1390     	if (flush || !L_NOFLSH(tty)) {
1391     		if ( tty->ldisc.flush_buffer )  
1392     			tty->ldisc.flush_buffer(tty);
1393     		i2InputFlush( tty->driver_data );
1394     	}
1395     }
1396     
1397     static inline void
1398     do_status( i2ChanStrPtr pCh )
1399     {
1400     	int status;
1401     
1402     	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
1403     
1404     #ifdef IP2DEBUG_TRACE
1405     	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
1406     #endif
1407     
1408     	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
1409     		if ( (status & I2_BRK) ) {
1410     			// code duplicated from n_tty (ldisc)
1411     			if (I_IGNBRK(pCh->pTTY))
1412     				goto skip_this;
1413     			if (I_BRKINT(pCh->pTTY)) {
1414     				isig(SIGINT, pCh->pTTY, 1);
1415     				goto skip_this;
1416     			}
1417     			wake_up_interruptible(&pCh->pTTY->read_wait);
1418     		}
1419     #ifdef NEVER_HAPPENS_AS_SETUP_XXX
1420     	// and can't work because we don't know the_char
1421     	// as the_char is reported on a seperate path
1422     	// The intelligent board does this stuff as setup
1423     	{
1424     	char brkf = TTY_NORMAL;
1425     	unsigned char brkc = '\0';
1426     	unsigned char tmp;
1427     		if ( (status & I2_BRK) ) {
1428     			brkf = TTY_BREAK;
1429     			brkc = '\0';
1430     		} 
1431     		else if (status & I2_PAR) {
1432     			brkf = TTY_PARITY;
1433     			brkc = the_char;
1434     		} else if (status & I2_FRA) {
1435     			brkf = TTY_FRAME;
1436     			brkc = the_char;
1437     		} else if (status & I2_OVR) {
1438     			brkf = TTY_OVERRUN;
1439     			brkc = the_char;
1440     		}
1441     		tmp = pCh->pTTY->real_raw;
1442     		pCh->pTTY->real_raw = 0;
1443     		pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
1444     		pCh->pTTY->real_raw = tmp;
1445     	}
1446     #endif /* NEVER_HAPPENS_AS_SETUP_XXX */
1447     	}
1448     skip_this:
1449     
1450     	if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
1451     		wake_up_interruptible(&pCh->delta_msr_wait);
1452     
1453     		if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
1454     			if ( status & I2_DCD ) {
1455     				if ( pCh->wopen ) {
1456     					wake_up_interruptible ( &pCh->open_wait );
1457     				}
1458     			} else if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) ) {
1459     				if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
1460     					tty_hangup( pCh->pTTY );
1461     				}
1462     			}
1463     		}
1464     	}
1465     
1466     #ifdef IP2DEBUG_TRACE
1467     	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
1468     #endif
1469     }
1470     
1471     /******************************************************************************/
1472     /* Device Open/Close/Ioctl Entry Point Section                                */
1473     /******************************************************************************/
1474     
1475     /******************************************************************************/
1476     /* Function:   open_sanity_check()                                            */
1477     /* Parameters: Pointer to tty structure                                       */
1478     /*             Pointer to file structure                                      */
1479     /* Returns:    Success or failure                                             */
1480     /*                                                                            */
1481     /* Description:                                                               */
1482     /* Verifies the structure magic numbers and cross links.                      */
1483     /******************************************************************************/
1484     #ifdef IP2DEBUG_OPEN
1485     static void 
1486     open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
1487     {
1488     	if ( pBrd->i2eValid != I2E_MAGIC ) {
1489     		printk(KERN_ERR "IP2: invalid board structure\n" );
1490     	} else if ( pBrd != pCh->pMyBord ) {
1491     		printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
1492     			 pCh->pMyBord );
1493     	} else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
1494     		printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
1495     	} else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
1496     	} else {
1497     		printk(KERN_INFO "IP2: all pointers check out!\n" );
1498     	}
1499     }
1500     #endif
1501     
1502     
1503     /******************************************************************************/
1504     /* Function:   ip2_open()                                                     */
1505     /* Parameters: Pointer to tty structure                                       */
1506     /*             Pointer to file structure                                      */
1507     /* Returns:    Success or failure                                             */
1508     /*                                                                            */
1509     /* Description: (MANDATORY)                                                   */
1510     /* A successful device open has to run a gauntlet of checks before it         */
1511     /* completes. After some sanity checking and pointer setup, the function      */
1512     /* blocks until all conditions are satisfied. It then initialises the port to */
1513     /* the default characteristics and returns.                                   */
1514     /******************************************************************************/
1515     static int
1516     ip2_open( PTTY tty, struct file *pFile )
1517     {
1518     	int rc = 0;
1519     	int do_clocal = 0;
1520     	i2ChanStrPtr  pCh = DevTable[MINOR(tty->device)];
1521     
1522     #ifdef IP2DEBUG_TRACE
1523     	ip2trace (MINOR(tty->device), ITRC_OPEN, ITRC_ENTER, 0 );
1524     #endif
1525     
1526     	if ( pCh == NULL ) {
1527     		return -ENODEV;
1528     	}
1529     	/* Setup pointer links in device and tty structures */
1530     	pCh->pTTY = tty;
1531     	tty->driver_data = pCh;
1532     	MOD_INC_USE_COUNT;
1533     
1534     #ifdef IP2DEBUG_OPEN
1535     	printk(KERN_DEBUG 
1536     			"IP2:open(tty=%p,pFile=%p):dev=%x,maj=%d,min=%d,ch=%d,idx=%d\n",
1537     	       tty, pFile, tty->device, MAJOR(tty->device), MINOR(tty->device),
1538     			 pCh->infl.hd.i2sChannel, pCh->port_index);
1539     	open_sanity_check ( pCh, pCh->pMyBord );
1540     #endif
1541     
1542     	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
1543     	pCh->dataSetOut |= (I2_DTR | I2_RTS);
1544     	serviceOutgoingFifo( pCh->pMyBord );
1545     
1546     	/* Block here until the port is ready (per serial and istallion) */
1547     	/*
1548     	 * 1. If the port is in the middle of closing wait for the completion
1549     	 *    and then return the appropriate error.
1550     	 */
1551     	if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
1552     		if ( pCh->flags & ASYNC_CLOSING ) {
1553     			interruptible_sleep_on( &pCh->close_wait);
1554     		}
1555     		if ( tty_hung_up_p(pFile) ) {
1556     			return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
1557     		}
1558     	}
1559     	/*
1560     	 * 2. If this is a callout device, make sure the normal port is not in
1561     	 *    use, and that someone else doesn't have the callout device locked.
1562     	 *    (These are the only tests the standard serial driver makes for
1563     	 *    callout devices.)
1564     	 */
1565     	if ( tty->driver.subtype == SERIAL_TYPE_CALLOUT ) {
1566     		if ( pCh->flags & ASYNC_NORMAL_ACTIVE ) {
1567     			return -EBUSY;
1568     		}
1569     		if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE )  &&
1570     		    ( pCh->flags & ASYNC_SESSION_LOCKOUT ) &&
1571     		    ( pCh->session != current->session ) ) {
1572     			return -EBUSY;
1573     		}
1574     		if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) &&
1575     		    ( pCh->flags & ASYNC_PGRP_LOCKOUT )   &&
1576     		    ( pCh->pgrp != current->pgrp ) ) {
1577     			return -EBUSY;
1578     		}
1579     		pCh->flags |= ASYNC_CALLOUT_ACTIVE;
1580     		goto noblock;
1581     	}
1582     	/*
1583     	 * 3. Handle a non-blocking open of a normal port.
1584     	 */
1585     	if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
1586     		if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) {
1587     			return -EBUSY;
1588     		}
1589     		pCh->flags |= ASYNC_NORMAL_ACTIVE;
1590     		goto noblock;
1591     	}
1592     	/*
1593     	 * 4. Now loop waiting for the port to be free and carrier present
1594     	 *    (if required).
1595     	 */
1596     	if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) {
1597     		if ( pCh->NormalTermios.c_cflag & CLOCAL ) {
1598     			do_clocal = 1;
1599     		}
1600     	} else {
1601     		if ( tty->termios->c_cflag & CLOCAL ) {
1602     			do_clocal = 1;
1603     		}
1604     	}
1605     
1606     #ifdef IP2DEBUG_OPEN
1607     	printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
1608     #endif
1609     
1610     	++pCh->wopen;
1611     	for(;;) {
1612     		if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE)) {
1613     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
1614     			pCh->dataSetOut |= (I2_DTR | I2_RTS);
1615     			serviceOutgoingFifo( pCh->pMyBord );
1616     		}
1617     		if ( tty_hung_up_p(pFile) ) {
1618     			return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
1619     		}
1620     		if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) &&
1621     				!(pCh->flags & ASYNC_CLOSING) && 
1622     				(do_clocal || (pCh->dataSetIn & I2_DCD) )) {
1623     			rc = 0;
1624     			break;
1625     		}
1626     
1627     #ifdef IP2DEBUG_OPEN
1628     		printk(KERN_DEBUG "ASYNC_CALLOUT_ACTIVE = %s\n",
1629     			(pCh->flags & ASYNC_CALLOUT_ACTIVE)?"True":"False");
1630     		printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
1631     			(pCh->flags & ASYNC_CLOSING)?"True":"False");
1632     		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
1633     #endif
1634     #ifdef IP2DEBUG_TRACE
1635     		ip2trace (CHANN, ITRC_OPEN, 3, 2, (pCh->flags & ASYNC_CALLOUT_ACTIVE),
1636     								(pCh->flags & ASYNC_CLOSING) );
1637     #endif
1638     		/* check for signal */
1639     		if (signal_pending(current)) {
1640     			rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
1641     			break;
1642     		}
1643     		interruptible_sleep_on(&pCh->open_wait);
1644     	}
1645     	--pCh->wopen; //why count?
1646     #ifdef IP2DEBUG_TRACE
1647     	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
1648     #endif
1649     	if (rc != 0 ) {
1650     		return rc;
1651     	}
1652     	pCh->flags |= ASYNC_NORMAL_ACTIVE;
1653     
1654     noblock:
1655     
1656     	/* first open - Assign termios structure to port */
1657     	if ( tty->count == 1 ) {
1658     		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1659     		if ( pCh->flags & ASYNC_SPLIT_TERMIOS ) {
1660     			if ( tty->driver.subtype == SERIAL_TYPE_NORMAL ) {
1661     				*tty->termios = pCh->NormalTermios;
1662     			} else {
1663     				*tty->termios = pCh->CalloutTermios;
1664     			}
1665     		}
1666     		/* Now we must send the termios settings to the loadware */
1667     		set_params( pCh, NULL );
1668     	}
1669     
1670     	/* override previous and never reset ??? */
1671     	pCh->session = current->session;
1672     	pCh->pgrp = current->pgrp;
1673     
1674     	/*
1675     	 * Now set any i2lib options. These may go away if the i2lib code ends
1676     	 * up rolled into the mainline.
1677     	 */
1678     	pCh->channelOptions |= CO_NBLOCK_WRITE;
1679     
1680     #ifdef IP2DEBUG_OPEN
1681     	printk (KERN_DEBUG "IP2: open completed\n" );
1682     #endif
1683     	serviceOutgoingFifo( pCh->pMyBord );
1684     
1685     #ifdef IP2DEBUG_TRACE
1686     	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
1687     #endif
1688     	return 0;
1689     }
1690     
1691     /******************************************************************************/
1692     /* Function:   ip2_close()                                                    */
1693     /* Parameters: Pointer to tty structure                                       */
1694     /*             Pointer to file structure                                      */
1695     /* Returns:    Nothing                                                        */
1696     /*                                                                            */
1697     /* Description:                                                               */
1698     /*                                                                            */
1699     /*                                                                            */
1700     /******************************************************************************/
1701     static void
1702     ip2_close( PTTY tty, struct file *pFile )
1703     {
1704     	i2ChanStrPtr  pCh = tty->driver_data;
1705     
1706     	if ( !pCh ) {
1707     		return;
1708     	}
1709     
1710     #ifdef IP2DEBUG_TRACE
1711     	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
1712     #endif
1713     
1714     #ifdef IP2DEBUG_OPEN
1715     	printk(KERN_DEBUG "IP2:close ttyF%02X:\n",MINOR(tty->device));
1716     #endif
1717     
1718     	if ( tty_hung_up_p ( pFile ) ) {
1719     		MOD_DEC_USE_COUNT;
1720     
1721     #ifdef IP2DEBUG_TRACE
1722     		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
1723     #endif
1724     		return;
1725     	}
1726     	if ( tty->count > 1 ) { /* not the last close */
1727     		MOD_DEC_USE_COUNT;
1728     #ifdef IP2DEBUG_TRACE
1729     		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
1730     #endif
1731     		return;
1732     	}
1733     	pCh->flags |= ASYNC_CLOSING;	// last close actually
1734     
1735     	/*
1736     	 * Save the termios structure, since this port may have separate termios
1737     	 * for callout and dialin.
1738     	 */
1739     	if (pCh->flags & ASYNC_NORMAL_ACTIVE)
1740     		pCh->NormalTermios = *tty->termios;
1741     	if (pCh->flags & ASYNC_CALLOUT_ACTIVE)
1742     		pCh->CalloutTermios = *tty->termios;
1743     
1744     	tty->closing = 1;
1745     
1746     	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
1747     		/*
1748     		 * Before we drop DTR, make sure the transmitter has completely drained.
1749     		 * This uses an timeout, after which the close
1750     		 * completes.
1751     		 */
1752     		ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
1753     	}
1754     	/*
1755     	 * At this point we stop accepting input. Here we flush the channel
1756     	 * input buffer which will allow the board to send up more data. Any
1757     	 * additional input is tossed at interrupt/poll time.
1758     	 */
1759     	i2InputFlush( pCh );
1760     
1761     	/* disable DSS reporting */
1762     	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
1763     				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1764     	if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
1765     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
1766     		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1767     		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1768     	}
1769     
1770     	serviceOutgoingFifo ( pCh->pMyBord );
1771     
1772     	if ( tty->driver.flush_buffer ) 
1773     		tty->driver.flush_buffer(tty);
1774     	if ( tty->ldisc.flush_buffer )  
1775     		tty->ldisc.flush_buffer(tty);
1776     	tty->closing = 0;
1777     	
1778     	pCh->pTTY = NULL;
1779     
1780     	if (pCh->wopen) {
1781     		if (pCh->ClosingDelay) {
1782     			current->state = TASK_INTERRUPTIBLE;
1783     			schedule_timeout(pCh->ClosingDelay);
1784     		}
1785     		wake_up_interruptible(&pCh->open_wait);
1786     	}
1787     
1788     	pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
1789     	wake_up_interruptible(&pCh->close_wait);
1790     
1791     #ifdef IP2DEBUG_OPEN
1792     	DBG_CNT("ip2_close: after wakeups--");
1793     #endif
1794     
1795     	MOD_DEC_USE_COUNT;
1796     
1797     #ifdef IP2DEBUG_TRACE
1798     	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
1799     #endif
1800     	return;
1801     }
1802     
1803     /******************************************************************************/
1804     /* Function:   ip2_hangup()                                                   */
1805     /* Parameters: Pointer to tty structure                                       */
1806     /* Returns:    Nothing                                                        */
1807     /*                                                                            */
1808     /* Description:                                                               */
1809     /*                                                                            */
1810     /*                                                                            */
1811     /******************************************************************************/
1812     static void
1813     ip2_hangup ( PTTY tty )
1814     {
1815     	i2ChanStrPtr  pCh = tty->driver_data;
1816     
1817     #ifdef IP2DEBUG_TRACE
1818     	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
1819     #endif
1820     
1821     	ip2_flush_buffer(tty);
1822     
1823     	/* disable DSS reporting */
1824     
1825     	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
1826     	i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1827     	if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
1828     		i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
1829     		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1830     		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1831     	}
1832     	i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
1833     				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1834     	serviceOutgoingFifo ( pCh->pMyBord );
1835     
1836     	wake_up_interruptible ( &pCh->delta_msr_wait );
1837     
1838     	pCh->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1839     	pCh->pTTY = NULL;
1840     	wake_up_interruptible ( &pCh->open_wait );
1841     
1842     #ifdef IP2DEBUG_TRACE
1843     	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
1844     #endif
1845     }
1846     
1847     /******************************************************************************/
1848     /******************************************************************************/
1849     /* Device Output Section                                                      */
1850     /******************************************************************************/
1851     /******************************************************************************/
1852     
1853     /******************************************************************************/
1854     /* Function:   ip2_write()                                                    */
1855     /* Parameters: Pointer to tty structure                                       */
1856     /*             Flag denoting data is in user (1) or kernel (0) space          */
1857     /*             Pointer to data                                                */
1858     /*             Number of bytes to write                                       */
1859     /* Returns:    Number of bytes actually written                               */
1860     /*                                                                            */
1861     /* Description: (MANDATORY)                                                   */
1862     /*                                                                            */
1863     /*                                                                            */
1864     /******************************************************************************/
1865     static int
1866     ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
1867     {
1868     	i2ChanStrPtr  pCh = tty->driver_data;
1869     	int bytesSent = 0;
1870     	unsigned long flags;
1871     
1872     #ifdef IP2DEBUG_TRACE
1873        ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
1874     #endif
1875     
1876     	/* Flush out any buffered data left over from ip2_putchar() calls. */
1877     	ip2_flush_chars( tty );
1878     
1879     	/* This is the actual move bit. Make sure it does what we need!!!!! */
1880     	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1881     	bytesSent = i2Output( pCh, pData, count, user );
1882     	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1883     
1884     #ifdef IP2DEBUG_TRACE
1885        ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
1886     #endif
1887     	return bytesSent > 0 ? bytesSent : 0;
1888     }
1889     
1890     /******************************************************************************/
1891     /* Function:   ip2_putchar()                                                  */
1892     /* Parameters: Pointer to tty structure                                       */
1893     /*             Character to write                                             */
1894     /* Returns:    Nothing                                                        */
1895     /*                                                                            */
1896     /* Description:                                                               */
1897     /*                                                                            */
1898     /*                                                                            */
1899     /******************************************************************************/
1900     static void
1901     ip2_putchar( PTTY tty, unsigned char ch )
1902     {
1903     	i2ChanStrPtr  pCh = tty->driver_data;
1904     	unsigned long flags;
1905     
1906     #ifdef IP2DEBUG_TRACE
1907     //	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
1908     #endif
1909     
1910     	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1911     	pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
1912     	if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
1913     		WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1914     		ip2_flush_chars( tty );
1915     	} else
1916     		WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1917     
1918     #ifdef IP2DEBUG_TRACE
1919     //	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
1920     #endif
1921     }
1922     
1923     /******************************************************************************/
1924     /* Function:   ip2_flush_chars()                                              */
1925     /* Parameters: Pointer to tty structure                                       */
1926     /* Returns:    Nothing                                                        */
1927     /*                                                                            */
1928     /* Description:                                                               */
1929     /*                                                                            */
1930     /******************************************************************************/
1931     static void
1932     ip2_flush_chars( PTTY tty )
1933     {
1934     	int   strip;
1935     	i2ChanStrPtr  pCh = tty->driver_data;
1936     	unsigned long flags;
1937     
1938     	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1939     	if ( pCh->Pbuf_stuff ) {
1940     #ifdef IP2DEBUG_TRACE
1941     //	ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
1942     #endif
1943     		//
1944     		// We may need to restart i2Output if it does not fullfill this request
1945     		//
1946     		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 );
1947     		if ( strip != pCh->Pbuf_stuff ) {
1948     			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
1949     		}
1950     		pCh->Pbuf_stuff -= strip;
1951     	}
1952     	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1953     }
1954     
1955     /******************************************************************************/
1956     /* Function:   ip2_write_room()                                               */
1957     /* Parameters: Pointer to tty structure                                       */
1958     /* Returns:    Number of bytes that the driver can accept                     */
1959     /*                                                                            */
1960     /* Description:                                                               */
1961     /*                                                                            */
1962     /******************************************************************************/
1963     static int
1964     ip2_write_room ( PTTY tty )
1965     {
1966     	int bytesFree;
1967     	i2ChanStrPtr  pCh = tty->driver_data;
1968     	unsigned long flags;
1969     
1970     	READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1971     	bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
1972     	READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1973     
1974     #ifdef IP2DEBUG_TRACE
1975     	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
1976     #endif
1977     
1978     	return ((bytesFree > 0) ? bytesFree : 0);
1979     }
1980     
1981     /******************************************************************************/
1982     /* Function:   ip2_chars_in_buf()                                             */
1983     /* Parameters: Pointer to tty structure                                       */
1984     /* Returns:    Number of bytes queued for transmission                        */
1985     /*                                                                            */
1986     /* Description:                                                               */
1987     /*                                                                            */
1988     /*                                                                            */
1989     /******************************************************************************/
1990     static int
1991     ip2_chars_in_buf ( PTTY tty )
1992     {
1993     	i2ChanStrPtr  pCh = tty->driver_data;
1994     	int rc;
1995     	unsigned long flags;
1996     #ifdef IP2DEBUG_TRACE
1997     	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
1998     #endif
1999     #ifdef IP2DEBUG_WRITE
2000     	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
2001     				 pCh->Obuf_char_count + pCh->Pbuf_stuff,
2002     				 pCh->Obuf_char_count, pCh->Pbuf_stuff );
2003     #endif
2004     	READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
2005     	rc =  pCh->Obuf_char_count;
2006     	READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
2007     	READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
2008     	rc +=  pCh->Pbuf_stuff;
2009     	READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
2010     	return rc;
2011     }
2012     
2013     /******************************************************************************/
2014     /* Function:   ip2_flush_buffer()                                             */
2015     /* Parameters: Pointer to tty structure                                       */
2016     /* Returns:    Nothing                                                        */
2017     /*                                                                            */
2018     /* Description:                                                               */
2019     /*                                                                            */
2020     /*                                                                            */
2021     /******************************************************************************/
2022     static void
2023     ip2_flush_buffer( PTTY tty )
2024     {
2025     	i2ChanStrPtr  pCh = tty->driver_data;
2026     	unsigned long flags;
2027     
2028     #ifdef IP2DEBUG_TRACE
2029     	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
2030     #endif
2031     #ifdef IP2DEBUG_WRITE
2032     	printk (KERN_DEBUG "IP2: flush buffer\n" );
2033     #endif
2034     	WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
2035     	pCh->Pbuf_stuff = 0;
2036     	WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
2037     	i2FlushOutput( pCh );
2038     	ip2_owake(tty);
2039     #ifdef IP2DEBUG_TRACE
2040     	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
2041     #endif
2042     }
2043     
2044     /******************************************************************************/
2045     /* Function:   ip2_wait_until_sent()                                          */
2046     /* Parameters: Pointer to tty structure                                       */
2047     /*             Timeout for wait.                                              */
2048     /* Returns:    Nothing                                                        */
2049     /*                                                                            */
2050     /* Description:                                                               */
2051     /* This function is used in place of the normal tty_wait_until_sent, which    */
2052     /* only waits for the driver buffers to be empty (or rather, those buffers    */
2053     /* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
2054     /* indeterminate number of bytes buffered on the board.                       */
2055     /******************************************************************************/
2056     static void
2057     ip2_wait_until_sent ( PTTY tty, int timeout )
2058     {
2059     	int i = jiffies;
2060     	i2ChanStrPtr  pCh = tty->driver_data;
2061     
2062     	tty_wait_until_sent(tty, timeout );
2063     	if ( (i = timeout - (jiffies -i)) > 0)
2064     		i2DrainOutput( pCh, i );
2065     }
2066     
2067     /******************************************************************************/
2068     /******************************************************************************/
2069     /* Device Input Section                                                       */
2070     /******************************************************************************/
2071     /******************************************************************************/
2072     
2073     /******************************************************************************/
2074     /* Function:   ip2_throttle()                                                 */
2075     /* Parameters: Pointer to tty structure                                       */
2076     /* Returns:    Nothing                                                        */
2077     /*                                                                            */
2078     /* Description:                                                               */
2079     /*                                                                            */
2080     /*                                                                            */
2081     /******************************************************************************/
2082     static void
2083     ip2_throttle ( PTTY tty )
2084     {
2085     	i2ChanStrPtr  pCh = tty->driver_data;
2086     
2087     #ifdef IP2DEBUG_READ
2088     	printk (KERN_DEBUG "IP2: throttle\n" );
2089     #endif
2090     	/*
2091     	 * Signal the poll/interrupt handlers not to forward incoming data to
2092     	 * the line discipline. This will cause the buffers to fill up in the
2093     	 * library and thus cause the library routines to send the flow control
2094     	 * stuff.
2095     	 */
2096     	pCh->throttled = 1;
2097     }
2098     
2099     /******************************************************************************/
2100     /* Function:   ip2_unthrottle()                                               */
2101     /* Parameters: Pointer to tty structure                                       */
2102     /* Returns:    Nothing                                                        */
2103     /*                                                                            */
2104     /* Description:                                                               */
2105     /*                                                                            */
2106     /*                                                                            */
2107     /******************************************************************************/
2108     static void
2109     ip2_unthrottle ( PTTY tty )
2110     {
2111     	i2ChanStrPtr  pCh = tty->driver_data;
2112     	unsigned long flags;
2113     
2114     #ifdef IP2DEBUG_READ
2115     	printk (KERN_DEBUG "IP2: unthrottle\n" );
2116     #endif
2117     
2118     	/* Pass incoming data up to the line discipline again. */
2119     	pCh->throttled = 0;
2120      	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2121     	serviceOutgoingFifo( pCh->pMyBord );
2122     	READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
2123     	if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
2124     		READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
2125     #ifdef IP2DEBUG_READ
2126     		printk (KERN_DEBUG "i2Input called from unthrottle\n" );
2127     #endif
2128     		i2Input( pCh );
2129     	} else
2130     		READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
2131     }
2132     
2133     static void
2134     ip2_start ( PTTY tty )
2135     {
2136      	i2ChanStrPtr  pCh = DevTable[MINOR(tty->device)];
2137     
2138      	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2139      	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
2140      	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
2141     #ifdef IP2DEBUG_WRITE
2142     	printk (KERN_DEBUG "IP2: start tx\n" );
2143     #endif
2144     }
2145     
2146     static void
2147     ip2_stop ( PTTY tty )
2148     {
2149      	i2ChanStrPtr  pCh = DevTable[MINOR(tty->device)];
2150     
2151      	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
2152     #ifdef IP2DEBUG_WRITE
2153     	printk (KERN_DEBUG "IP2: stop tx\n" );
2154     #endif
2155     }
2156     
2157     /******************************************************************************/
2158     /* Device Ioctl Section                                                       */
2159     /******************************************************************************/
2160     
2161     /******************************************************************************/
2162     /* Function:   ip2_ioctl()                                                    */
2163     /* Parameters: Pointer to tty structure                                       */
2164     /*             Pointer to file structure                                      */
2165     /*             Command                                                        */
2166     /*             Argument                                                       */
2167     /* Returns:    Success or failure                                             */
2168     /*                                                                            */
2169     /* Description:                                                               */
2170     /*                                                                            */
2171     /*                                                                            */
2172     /******************************************************************************/
2173     static int
2174     ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2175     {
2176     	i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
2177     	struct async_icount cprev, cnow;	/* kernel counter temps */
2178     	struct serial_icounter_struct *p_cuser;	/* user space */
2179     	int rc = 0;
2180     	unsigned long flags;
2181     
2182     	if ( pCh == NULL ) {
2183     		return -ENODEV;
2184     	}
2185     
2186     #ifdef IP2DEBUG_TRACE
2187     	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
2188     #endif
2189     
2190     #ifdef IP2DEBUG_IOCTL
2191     	printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
2192     #endif
2193     
2194     	switch(cmd) {
2195     	case TIOCGSERIAL:
2196     #ifdef IP2DEBUG_TRACE
2197     		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
2198     #endif
2199     		rc = get_serial_info(pCh, (struct serial_struct *) arg);
2200     		if (rc)
2201     			return rc;
2202     		break;
2203     
2204     	case TIOCSSERIAL:
2205     #ifdef IP2DEBUG_TRACE
2206     		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
2207     #endif
2208     		rc = set_serial_info(pCh, (struct serial_struct *) arg);
2209     		if (rc)
2210     			return rc;
2211     		break;
2212     
2213     	case TCXONC:
2214     		rc = tty_check_change(tty);
2215     		if (rc)
2216     			return rc;
2217     		switch (arg) {
2218     		case TCOOFF:
2219     			//return  -ENOIOCTLCMD;
2220     			break;
2221     		case TCOON:
2222     			//return  -ENOIOCTLCMD;
2223     			break;
2224     		case TCIOFF:
2225     			if (STOP_CHAR(tty) != __DISABLED_CHAR) {
2226     				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2227     						CMD_XMIT_NOW(STOP_CHAR(tty)));
2228     			}
2229     			break;
2230     		case TCION:
2231     			if (START_CHAR(tty) != __DISABLED_CHAR) {
2232     				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2233     						CMD_XMIT_NOW(START_CHAR(tty)));
2234     			}
2235     			break;
2236     		default:
2237     			return -EINVAL;
2238     		}
2239     		return 0;
2240     
2241     	case TCSBRK:   /* SVID version: non-zero arg --> no break */
2242     		rc = tty_check_change(tty);
2243     #ifdef IP2DEBUG_TRACE
2244     		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
2245     #endif
2246     		if (!rc) {
2247     			ip2_wait_until_sent(tty,0);
2248     			if (!arg) {
2249     				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
2250     				serviceOutgoingFifo( pCh->pMyBord );
2251     			}
2252     		}
2253     		break;
2254     
2255     	case TCSBRKP:  /* support for POSIX tcsendbreak() */
2256     		rc = tty_check_change(tty);
2257     #ifdef IP2DEBUG_TRACE
2258     		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
2259     #endif
2260     		if (!rc) {
2261     			ip2_wait_until_sent(tty,0);
2262     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2263     				CMD_SEND_BRK(arg ? arg*100 : 250));
2264     			serviceOutgoingFifo ( pCh->pMyBord );	
2265     		}
2266     		break;
2267     
2268     	case TIOCGSOFTCAR:
2269     #ifdef IP2DEBUG_TRACE
2270     		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
2271     #endif
2272     			PUT_USER(rc,C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
2273     		if (rc)	
2274     			return rc;
2275     	break;
2276     
2277     	case TIOCSSOFTCAR:
2278     #ifdef IP2DEBUG_TRACE
2279     		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
2280     #endif
2281     		GET_USER(rc,arg,(unsigned long *) arg);
2282     		if (rc) 
2283     			return rc;
2284     		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
2285     					 | (arg ? CLOCAL : 0));
2286     		
2287     		break;
2288     
2289     	case TIOCMGET:
2290     #ifdef IP2DEBUG_TRACE
2291     		ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
2292     #endif
2293     /*
2294     	FIXME - the following code is causing a NULL pointer dereference in
2295     	2.3.51 in an interrupt handler.  It's suppose to prompt the board
2296     	to return the DSS signal status immediately.  Why doesn't it do
2297     	the same thing in 2.2.14?
2298     */
2299     /*
2300     		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
2301     		serviceOutgoingFifo( pCh->pMyBord );
2302     		interruptible_sleep_on(&pCh->dss_now_wait);
2303     		if (signal_pending(current)) {
2304     			return -EINTR;
2305     		}
2306     */
2307     		PUT_USER(rc,
2308     				    ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
2309     				  | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
2310     				  | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
2311     				  | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
2312     				  | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
2313     				  | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0),
2314     				(unsigned int *) arg);
2315     		break;
2316     
2317     	case TIOCMBIS:
2318     	case TIOCMBIC:
2319     	case TIOCMSET:
2320     #ifdef IP2DEBUG_TRACE
2321     		ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
2322     #endif
2323     		rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
2324     		break;
2325     
2326     	/*
2327     	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
2328     	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
2329     	 * for masking). Caller should use TIOCGICOUNT to see which one it was
2330     	 */
2331     	case TIOCMIWAIT:
2332     		save_flags(flags);cli();
2333     		cprev = pCh->icount;	 /* note the counters on entry */
2334     		restore_flags(flags);
2335     		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
2336     						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
2337     		serviceOutgoingFifo( pCh->pMyBord );
2338     		for(;;) {
2339     #ifdef IP2DEBUG_TRACE
2340     			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
2341     #endif
2342     			interruptible_sleep_on(&pCh->delta_msr_wait);
2343     #ifdef IP2DEBUG_TRACE
2344     			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
2345     #endif
2346     			/* see if a signal did it */
2347     			if (signal_pending(current)) {
2348     				rc = -ERESTARTSYS;
2349     				break;
2350     			}
2351     			save_flags(flags);cli();
2352     			cnow = pCh->icount; /* atomic copy */
2353     			restore_flags(flags);
2354     			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2355     				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
2356     				rc =  -EIO; /* no change => rc */
2357     				break;
2358     			}
2359     			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2360     			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2361     			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
2362     			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2363     				rc =  0;
2364     				break;
2365     			}
2366     			cprev = cnow;
2367     		}
2368     		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
2369     						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
2370     		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
2371     			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
2372     		}
2373     		serviceOutgoingFifo( pCh->pMyBord );
2374     		return rc;
2375     		break;
2376     
2377     	/*
2378     	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2379     	 * Return: write counters to the user passed counter struct
2380     	 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2381     	 * only 0->1 is counted. The controller is quite capable of counting
2382     	 * both, but this done to preserve compatibility with the standard
2383     	 * serial driver.
2384     	 */
2385     	case TIOCGICOUNT:
2386     #ifdef IP2DEBUG_TRACE
2387     		ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
2388     #endif
2389     		save_flags(flags);cli();
2390     		cnow = pCh->icount;
2391     		restore_flags(flags);
2392     		p_cuser = (struct serial_icounter_struct *) arg;
2393     		PUT_USER(rc,cnow.cts, &p_cuser->cts);
2394     		PUT_USER(rc,cnow.dsr, &p_cuser->dsr);
2395     		PUT_USER(rc,cnow.rng, &p_cuser->rng);
2396     		PUT_USER(rc,cnow.dcd, &p_cuser->dcd);
2397     		PUT_USER(rc,cnow.rx, &p_cuser->rx);
2398     		PUT_USER(rc,cnow.tx, &p_cuser->tx);
2399     		PUT_USER(rc,cnow.frame, &p_cuser->frame);
2400     		PUT_USER(rc,cnow.overrun, &p_cuser->overrun);
2401     		PUT_USER(rc,cnow.parity, &p_cuser->parity);
2402     		PUT_USER(rc,cnow.brk, &p_cuser->brk);
2403     		PUT_USER(rc,cnow.buf_overrun, &p_cuser->buf_overrun);
2404     		break;
2405     
2406     	/*
2407     	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2408     	 * will be passed to the line discipline for it to handle.
2409     	 */
2410     	case TIOCSERCONFIG:
2411     	case TIOCSERGWILD:
2412     	case TIOCSERGETLSR:
2413     	case TIOCSERSWILD:
2414     	case TIOCSERGSTRUCT:
2415     	case TIOCSERGETMULTI:
2416     	case TIOCSERSETMULTI:
2417     
2418     	default:
2419     #ifdef IP2DEBUG_TRACE
2420     		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
2421     #endif
2422     		rc =  -ENOIOCTLCMD;
2423     		break;
2424     	}
2425     #ifdef IP2DEBUG_TRACE
2426     	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
2427     #endif
2428     	return rc;
2429     }
2430     
2431     /******************************************************************************/
2432     /* Function:   set_modem_info()                                               */
2433     /* Parameters: Pointer to channel structure                                   */
2434     /*             Specific ioctl command                                         */
2435     /*             Pointer to source for new settings                             */
2436     /* Returns:    Nothing                                                        */
2437     /*                                                                            */
2438     /* Description:                                                               */
2439     /* This returns the current settings of the dataset signal inputs to the user */
2440     /* program.                                                                   */
2441     /******************************************************************************/
2442     static int
2443     set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value)
2444     {
2445     	int rc;
2446     	unsigned int arg;
2447     
2448     	GET_USER(rc,arg,value);
2449     	if (rc)
2450     		return rc;
2451     	switch(cmd) {
2452     	case TIOCMBIS:
2453     		if (arg & TIOCM_RTS) {
2454     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2455     			pCh->dataSetOut |= I2_RTS;
2456     		}
2457     		if (arg & TIOCM_DTR) {
2458     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2459     			pCh->dataSetOut |= I2_DTR;
2460     		}
2461     		break;
2462     	case TIOCMBIC:
2463     		if (arg & TIOCM_RTS) {
2464     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2465     			pCh->dataSetOut &= ~I2_RTS;
2466     		}
2467     		if (arg & TIOCM_DTR) {
2468     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2469     			pCh->dataSetOut &= ~I2_DTR;
2470     		}
2471     		break;
2472     	case TIOCMSET:
2473     		if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) {
2474     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2475     			pCh->dataSetOut |= I2_RTS;
2476     		} else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) {
2477     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2478     			pCh->dataSetOut &= ~I2_RTS;
2479     		}
2480     		if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) {
2481     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2482     			pCh->dataSetOut |= I2_DTR;
2483     		} else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) {
2484     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2485     			pCh->dataSetOut &= ~I2_DTR;
2486     		}
2487     		break;
2488     	default:
2489     		return -EINVAL;
2490     	}
2491     	serviceOutgoingFifo( pCh->pMyBord );
2492     	return 0;
2493     }
2494     
2495     /******************************************************************************/
2496     /* Function:   GetSerialInfo()                                                */
2497     /* Parameters: Pointer to channel structure                                   */
2498     /*             Pointer to old termios structure                               */
2499     /* Returns:    Nothing                                                        */
2500     /*                                                                            */
2501     /* Description:                                                               */
2502     /* This is to support the setserial command, and requires processing of the   */
2503     /* standard Linux serial structure.                                           */
2504     /******************************************************************************/
2505     static int
2506     get_serial_info ( i2ChanStrPtr pCh, struct serial_struct *retinfo )
2507     {
2508     	struct serial_struct tmp;
2509     	int rc;
2510     
2511     	if ( !retinfo ) {
2512     		return -EFAULT;
2513     	}
2514     
2515     	memset ( &tmp, 0, sizeof(tmp) );
2516     	tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
2517     	if (BID_HAS_654(tmp.type)) {
2518     		tmp.type = PORT_16650;
2519     	} else {
2520     		tmp.type = PORT_CIRRUS;
2521     	}
2522     	tmp.line = pCh->port_index;
2523     	tmp.port = pCh->pMyBord->i2eBase;
2524     	tmp.irq  = ip2config.irq[pCh->port_index/64];
2525     	tmp.flags = pCh->flags;
2526     	tmp.baud_base = pCh->BaudBase;
2527     	tmp.close_delay = pCh->ClosingDelay;
2528     	tmp.closing_wait = pCh->ClosingWaitTime;
2529     	tmp.custom_divisor = pCh->BaudDivisor;
2530        	COPY_TO_USER(rc,retinfo,&tmp,sizeof(*retinfo));
2531        return rc;
2532     }
2533     
2534     /******************************************************************************/
2535     /* Function:   SetSerialInfo()                                                */
2536     /* Parameters: Pointer to channel structure                                   */
2537     /*             Pointer to old termios structure                               */
2538     /* Returns:    Nothing                                                        */
2539     /*                                                                            */
2540     /* Description:                                                               */
2541     /* This function provides support for setserial, which uses the TIOCSSERIAL   */
2542     /* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
2543     /* change the IRQ, address or type of the port the ioctl fails.               */
2544     /******************************************************************************/
2545     static int
2546     set_serial_info( i2ChanStrPtr pCh, struct serial_struct *new_info )
2547     {
2548     	struct serial_struct ns;
2549     	int   old_flags, old_baud_divisor;
2550     	int     rc = 0;
2551     
2552     	if ( !new_info ) {
2553     		return -EFAULT;
2554     	}
2555     	COPY_FROM_USER(rc, &ns, new_info, sizeof (ns) );
2556     	if (rc) {
2557     		return rc;
2558     	}
2559     	/*
2560     	 * We don't allow setserial to change IRQ, board address, type or baud
2561     	 * base. Also line nunber as such is meaningless but we use it for our
2562     	 * array index so it is fixed also.
2563     	 */
2564     	if ( (ns.irq  	    != ip2config.irq[pCh->port_index])
2565     	    || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
2566     	    || (ns.baud_base != pCh->BaudBase)
2567     	    || (ns.line      != pCh->port_index) ) {
2568     		return -EINVAL;
2569     	}
2570     
2571     	old_flags = pCh->flags;
2572     	old_baud_divisor = pCh->BaudDivisor;
2573     
2574     	if ( !suser() ) {
2575     		if ( ( ns.close_delay != pCh->ClosingDelay ) ||
2576     		    ( (ns.flags & ~ASYNC_USR_MASK) !=
2577     		      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
2578     			return -EPERM;
2579     		}
2580     
2581     		pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
2582     			       (ns.flags & ASYNC_USR_MASK);
2583     		pCh->BaudDivisor = ns.custom_divisor;
2584     	} else {
2585     		pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
2586     			       (ns.flags & ASYNC_FLAGS);
2587     		pCh->BaudDivisor = ns.custom_divisor;
2588     		pCh->ClosingDelay = ns.close_delay * HZ/100;
2589     		pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
2590     	}
2591     
2592     	if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
2593     	    || (old_baud_divisor != pCh->BaudDivisor) ) {
2594     		// Invalidate speed and reset parameters
2595     		set_params( pCh, NULL );
2596     	}
2597     
2598     	return rc;
2599     }
2600     
2601     /******************************************************************************/
2602     /* Function:   ip2_set_termios()                                              */
2603     /* Parameters: Pointer to tty structure                                       */
2604     /*             Pointer to old termios structure                               */
2605     /* Returns:    Nothing                                                        */
2606     /*                                                                            */
2607     /* Description:                                                               */
2608     /*                                                                            */
2609     /*                                                                            */
2610     /******************************************************************************/
2611     static void
2612     ip2_set_termios( PTTY tty, struct termios *old_termios )
2613     {
2614     	i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
2615     
2616     #ifdef IP2DEBUG_IOCTL
2617     	printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
2618     #endif
2619     
2620     	set_params( pCh, old_termios );
2621     }
2622     
2623     /******************************************************************************/
2624     /* Function:   ip2_set_line_discipline()                                      */
2625     /* Parameters: Pointer to tty structure                                       */
2626     /* Returns:    Nothing                                                        */
2627     /*                                                                            */
2628     /* Description:  Does nothing                                                 */
2629     /*                                                                            */
2630     /*                                                                            */
2631     /******************************************************************************/
2632     static void
2633     ip2_set_line_discipline ( PTTY tty )
2634     {
2635     #ifdef IP2DEBUG_IOCTL
2636     	printk (KERN_DEBUG "IP2: set line discipline\n" );
2637     #endif
2638     #ifdef IP2DEBUG_TRACE
2639     	ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
2640     #endif
2641     }
2642     
2643     /******************************************************************************/
2644     /* Function:   SetLine Characteristics()                                      */
2645     /* Parameters: Pointer to channel structure                                   */
2646     /* Returns:    Nothing                                                        */
2647     /*                                                                            */
2648     /* Description:                                                               */
2649     /* This routine is called to update the channel structure with the new line   */
2650     /* characteristics, and send the appropriate commands to the board when they  */
2651     /* change.                                                                    */
2652     /******************************************************************************/
2653     static void
2654     set_params( i2ChanStrPtr pCh, struct termios *o_tios )
2655     {
2656     	tcflag_t cflag, iflag, lflag;
2657     	char stop_char, start_char;
2658     	struct termios dummy;
2659     
2660     	lflag = pCh->pTTY->termios->c_lflag;
2661     	cflag = pCh->pTTY->termios->c_cflag;
2662     	iflag = pCh->pTTY->termios->c_iflag;
2663     
2664     	if (o_tios == NULL) {
2665     		dummy.c_lflag = ~lflag;
2666     		dummy.c_cflag = ~cflag;
2667     		dummy.c_iflag = ~iflag;
2668     		o_tios = &dummy;
2669     	}
2670     
2671     	{
2672     		switch ( cflag & CBAUD ) {
2673     		case B0:
2674     			i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
2675     			pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
2676     			i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
2677     			pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
2678     			goto service_it;
2679     			break;
2680     		case B38400:
2681     			/*
2682     			 * This is the speed that is overloaded with all the other high
2683     			 * speeds, depending upon the flag settings.
2684     			 */
2685     			if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
2686     				pCh->speed = CBR_57600;
2687     			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
2688     				pCh->speed = CBR_115200;
2689     			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
2690     				pCh->speed = CBR_C1;
2691     			} else {
2692     				pCh->speed = CBR_38400;
2693     			}
2694     			break;
2695     		case B50:      pCh->speed = CBR_50;      break;
2696     		case B75:      pCh->speed = CBR_75;      break;
2697     		case B110:     pCh->speed = CBR_110;     break;
2698     		case B134:     pCh->speed = CBR_134;     break;
2699     		case B150:     pCh->speed = CBR_150;     break;
2700     		case B200:     pCh->speed = CBR_200;     break;
2701     		case B300:     pCh->speed = CBR_300;     break;
2702     		case B600:     pCh->speed = CBR_600;     break;
2703     		case B1200:    pCh->speed = CBR_1200;    break;
2704     		case B1800:    pCh->speed = CBR_1800;    break;
2705     		case B2400:    pCh->speed = CBR_2400;    break;
2706     		case B4800:    pCh->speed = CBR_4800;    break;
2707     		case B9600:    pCh->speed = CBR_9600;    break;
2708     		case B19200:   pCh->speed = CBR_19200;   break;
2709     		case B57600:   pCh->speed = CBR_57600;   break;
2710     		case B115200:  pCh->speed = CBR_115200;  break;
2711     		case B153600:  pCh->speed = CBR_153600;  break;
2712     		case B230400:  pCh->speed = CBR_230400;  break;
2713     		case B307200:  pCh->speed = CBR_307200;  break;
2714     		case B460800:  pCh->speed = CBR_460800;  break;
2715     		case B921600:  pCh->speed = CBR_921600;  break;
2716     		default:       pCh->speed = CBR_9600;    break;
2717     		}
2718     		if ( pCh->speed == CBR_C1 ) {
2719     			// Process the custom speed parameters.
2720     			int bps = pCh->BaudBase / pCh->BaudDivisor;
2721     			if ( bps == 921600 ) {
2722     				pCh->speed = CBR_921600;
2723     			} else {
2724     				bps = bps/10;
2725     				i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
2726     			}
2727     		}
2728     		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
2729     		
2730     		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
2731     		pCh->dataSetOut |= (I2_DTR | I2_RTS);
2732     	}
2733     	if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
2734     	{
2735     		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
2736     			CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
2737     	}
2738     	if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
2739     	{
2740     		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2741     			CMD_SETPAR( 
2742     				(cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
2743     			)
2744     		);
2745     	}
2746     	/* byte size and parity */
2747     	if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
2748     	{
2749     		int datasize;
2750     		switch ( cflag & CSIZE ) {
2751     		case CS5: datasize = CSZ_5; break;
2752     		case CS6: datasize = CSZ_6; break;
2753     		case CS7: datasize = CSZ_7; break;
2754     		case CS8: datasize = CSZ_8; break;
2755     		default:  datasize = CSZ_5; break;	/* as per serial.c */
2756     		}
2757     		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
2758     	}
2759     	/* Process CTS flow control flag setting */
2760     	if ( (cflag & CRTSCTS) ) {
2761     		i2QueueCommands(PTYPE_INLINE, pCh, 100,
2762     						2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
2763     	} else {
2764     		i2QueueCommands(PTYPE_INLINE, pCh, 100,
2765     						2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
2766     	}
2767     	//
2768     	// Process XON/XOFF flow control flags settings
2769     	//
2770     	stop_char = STOP_CHAR(pCh->pTTY);
2771     	start_char = START_CHAR(pCh->pTTY);
2772     
2773     	//////////// can't be \000
2774     	if (stop_char == __DISABLED_CHAR ) 
2775     	{
2776     		stop_char = ~__DISABLED_CHAR; 
2777     	}
2778     	if (start_char == __DISABLED_CHAR ) 
2779     	{
2780     		start_char = ~__DISABLED_CHAR;
2781     	}
2782     	/////////////////////////////////
2783     
2784     	if ( o_tios->c_cc[VSTART] != start_char ) 
2785     	{
2786     		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
2787     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
2788     	}
2789     	if ( o_tios->c_cc[VSTOP] != stop_char ) 
2790     	{
2791     		 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
2792     		 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
2793     	}
2794     	if (stop_char == __DISABLED_CHAR ) 
2795     	{
2796     		stop_char = ~__DISABLED_CHAR;  //TEST123
2797     		goto no_xoff;
2798     	}
2799     	if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
2800     	{
2801     		if ( iflag & IXOFF ) {	// Enable XOFF output flow control
2802     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
2803     		} else {	// Disable XOFF output flow control
2804     no_xoff:
2805     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
2806     		}
2807     	}
2808     	if (start_char == __DISABLED_CHAR ) 
2809     	{
2810     		goto no_xon;
2811     	}
2812     	if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
2813     	{
2814     		if ( iflag & IXON ) {
2815     			if ( iflag & IXANY ) { // Enable XON/XANY output flow control
2816     				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
2817     			} else { // Enable XON output flow control
2818     				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
2819     			}
2820     		} else { // Disable XON output flow control
2821     no_xon:
2822     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
2823     		}
2824     	}
2825     	if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
2826     	{
2827     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
2828     				CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
2829     	}
2830     	if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
2831     	{
2832     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
2833     				CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
2834     	}
2835     
2836     	if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
2837     			^	( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
2838     	{
2839     		char brkrpt = 0;
2840     		char parrpt = 0;
2841     
2842     		if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
2843     			/* Ignore breaks altogether */
2844     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
2845     		} else {
2846     			if ( iflag & BRKINT ) {
2847     				if ( iflag & PARMRK ) {
2848     					brkrpt = 0x0a;	// exception an inline triple
2849     				} else {
2850     					brkrpt = 0x1a;	// exception and NULL
2851     				}
2852     				brkrpt |= 0x04;	// flush input
2853     			} else {
2854     				if ( iflag & PARMRK ) {
2855     					brkrpt = 0x0b;	//POSIX triple \0377 \0 \0
2856     				} else {
2857     					brkrpt = 0x01;	// Null only
2858     				}
2859     			}
2860     			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
2861     		} 
2862     
2863     		if (iflag & IGNPAR) {
2864     			parrpt = 0x20;
2865     													/* would be 2 for not cirrus bug */
2866     													/* would be 0x20 cept for cirrus bug */
2867     		} else {
2868     			if ( iflag & PARMRK ) {
2869     				/*
2870     				 * Replace error characters with 3-byte sequence (\0377,\0,char)
2871     				 */
2872     				parrpt = 0x04 ;
2873     				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
2874     			} else {
2875     				parrpt = 0x03;
2876     			} 
2877     		}
2878     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
2879     	}
2880     	if (cflag & CLOCAL) {
2881     		// Status reporting fails for DCD if this is off
2882     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
2883     		pCh->flags &= ~ASYNC_CHECK_CD;
2884     	} else {
2885     		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
2886     		pCh->flags	|= ASYNC_CHECK_CD;
2887     	}
2888     
2889     #ifdef XXX
2890     do_flags_thing:	// This is a test, we don't do the flags thing
2891     	
2892     	if ( (cflag & CRTSCTS) ) {
2893     		cflag |= 014000000000;
2894     	}
2895     	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, 
2896     				CMD_UNIX_FLAGS(iflag,cflag,lflag));
2897     #endif
2898     		
2899     service_it:
2900     	i2DrainOutput( pCh, 100 );		
2901     }
2902     
2903     /******************************************************************************/
2904     /* IPL Device Section                                                         */
2905     /******************************************************************************/
2906     
2907     /******************************************************************************/
2908     /* Function:   ip2_ipl_read()                                                  */
2909     /* Parameters: Pointer to device inode                                        */
2910     /*             Pointer to file structure                                      */
2911     /*             Pointer to data                                                */
2912     /*             Number of bytes to read                                        */
2913     /* Returns:    Success or failure                                             */
2914     /*                                                                            */
2915     /* Description:   Ugly                                                        */
2916     /*                                                                            */
2917     /*                                                                            */
2918     /******************************************************************************/
2919     
2920     static 
2921     #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
2922     int
2923     ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off )
2924     	unsigned int minor = MINOR( pInode->i_rdev );
2925     #else
2926     ssize_t
2927     ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off )
2928     {
2929     	unsigned int minor = MINOR( pFile->f_dentry->d_inode->i_rdev );
2930     #endif
2931     	int rc = 0;
2932     
2933     #ifdef IP2DEBUG_IPL
2934     	printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
2935     #endif
2936     
2937     	switch( minor ) {
2938     	case 0:	    // IPL device
2939     		rc = -EINVAL;
2940     		break;
2941     	case 1:	    // Status dump
2942     		rc = -EINVAL;
2943     		break;
2944     	case 2:	    // Ping device
2945     		rc = -EINVAL;
2946     		break;
2947     	case 3:	    // Trace device
2948     		rc = DumpTraceBuffer ( pData, count );
2949     		break;
2950     	case 4:	    // Trace device
2951     		rc = DumpFifoBuffer ( pData, count );
2952     		break;
2953     	default:
2954     		rc = -ENODEV;
2955     		break;
2956     	}
2957     	return rc;
2958     }
2959     
2960     static int
2961     DumpFifoBuffer ( char *pData, int count )
2962     {
2963     #ifdef DEBUG_FIFO
2964     	int rc;
2965     	COPY_TO_USER(rc, pData, DBGBuf, count);
2966     
2967     	printk(KERN_DEBUG "Last index %d\n", I );
2968     
2969     	return count;
2970     #endif	/* DEBUG_FIFO */
2971     	return 0;
2972     }
2973     
2974     static int
2975     DumpTraceBuffer ( char *pData, int count )
2976     {
2977     #ifdef IP2DEBUG_TRACE
2978     	int rc;
2979     	int dumpcount;
2980     	int chunk;
2981     	int *pIndex = (int*)pData;
2982     
2983     	if ( count < (sizeof(int) * 6) ) {
2984     		return -EIO;
2985     	}
2986     	PUT_USER(rc, tracewrap, pIndex );
2987     	PUT_USER(rc, TRACEMAX, ++pIndex );
2988     	PUT_USER(rc, tracestrip, ++pIndex );
2989     	PUT_USER(rc, tracestuff, ++pIndex );
2990     	pData += sizeof(int) * 6;
2991     	count -= sizeof(int) * 6;
2992     
2993     	dumpcount = tracestuff - tracestrip;
2994     	if ( dumpcount < 0 ) {
2995     		dumpcount += TRACEMAX;
2996     	}
2997     	if ( dumpcount > count ) {
2998     		dumpcount = count;
2999     	}
3000     	chunk = TRACEMAX - tracestrip;
3001     	if ( dumpcount > chunk ) {
3002     		COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
3003     			      chunk * sizeof(tracebuf[0]) );
3004     		pData += chunk * sizeof(tracebuf[0]);
3005     		tracestrip = 0;
3006     		chunk = dumpcount - chunk;
3007     	} else {
3008     		chunk = dumpcount;
3009     	}
3010     	COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
3011     		      chunk * sizeof(tracebuf[0]) );
3012     	tracestrip += chunk;
3013     	tracewrap = 0;
3014     
3015     	PUT_USER(rc, tracestrip, ++pIndex );
3016     	PUT_USER(rc, tracestuff, ++pIndex );
3017     
3018     	return dumpcount;
3019     #else
3020     	return 0;
3021     #endif
3022     }
3023     
3024     /******************************************************************************/
3025     /* Function:   ip2_ipl_write()                                                 */
3026     /* Parameters:                                                                */
3027     /*             Pointer to file structure                                      */
3028     /*             Pointer to data                                                */
3029     /*             Number of bytes to write                                       */
3030     /* Returns:    Success or failure                                             */
3031     /*                                                                            */
3032     /* Description:                                                               */
3033     /*                                                                            */
3034     /*                                                                            */
3035     /******************************************************************************/
3036     static ssize_t
3037     ip2_ipl_write(struct file *pFile, const char *pData, size_t count, loff_t *off)
3038     {
3039     #ifdef IP2DEBUG_IPL
3040     	printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
3041     #endif
3042     	return 0;
3043     }
3044     
3045     /******************************************************************************/
3046     /* Function:   ip2_ipl_ioctl()                                                */
3047     /* Parameters: Pointer to device inode                                        */
3048     /*             Pointer to file structure                                      */
3049     /*             Command                                                        */
3050     /*             Argument                                                       */
3051     /* Returns:    Success or failure                                             */
3052     /*                                                                            */
3053     /* Description:                                                               */
3054     /*                                                                            */
3055     /*                                                                            */
3056     /******************************************************************************/
3057     static int
3058     ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
3059     {
3060     	unsigned int iplminor = MINOR(pInode->i_rdev);
3061     	int rc = 0;
3062     	ULONG *pIndex = (ULONG*)arg;
3063     	i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
3064     	i2ChanStrPtr pCh;
3065     
3066     #ifdef IP2DEBUG_IPL
3067     	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
3068     #endif
3069     
3070     	switch ( iplminor ) {
3071     	case 0:	    // IPL device
3072     		rc = -EINVAL;
3073     		break;
3074     	case 1:	    // Status dump
3075     	case 5:
3076     	case 9:
3077     	case 13:
3078     		switch ( cmd ) {
3079     		case 64:	/* Driver - ip2stat */
3080     			PUT_USER(rc, ref_count, pIndex++ );
3081     			PUT_USER(rc, irq_counter, pIndex++  );
3082     			PUT_USER(rc, bh_counter, pIndex++  );
3083     			break;
3084     
3085     		case 65:	/* Board  - ip2stat */
3086     			if ( pB ) {
3087     				COPY_TO_USER(rc, (char*)arg, (char*)pB, sizeof(i2eBordStr) );
3088     				PUT_USER(rc, INB(pB->i2eStatus),
3089     					(ULONG*)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
3090     			} else {
3091     				rc = -ENODEV;
3092     			}
3093     			break;
3094     
3095     		default:
3096     			pCh = DevTable[cmd];
3097     			if ( pCh )
3098     			{
3099     				COPY_TO_USER(rc, (char*)arg, (char*)pCh, sizeof(i2ChanStr) );
3100     			} else {
3101     				rc = cmd < 64 ? -ENODEV : -EINVAL;
3102     			}
3103     		}
3104     		break;
3105     
3106     	case 2:	    // Ping device
3107     		rc = -EINVAL;
3108     		break;
3109     	case 3:	    // Trace device
3110     		if ( cmd == 1 ) {
3111     			PUT_USER(rc, iiSendPendingMail, pIndex++ );
3112     			PUT_USER(rc, i2InitChannels, pIndex++ );
3113     			PUT_USER(rc, i2QueueNeeds, pIndex++ );
3114     			PUT_USER(rc, i2QueueCommands, pIndex++ );
3115     			PUT_USER(rc, i2GetStatus, pIndex++ );
3116     			PUT_USER(rc, i2Input, pIndex++ );
3117     			PUT_USER(rc, i2InputFlush, pIndex++ );
3118     			PUT_USER(rc, i2Output, pIndex++ );
3119     			PUT_USER(rc, i2FlushOutput, pIndex++ );
3120     			PUT_USER(rc, i2DrainWakeup, pIndex++ );
3121     			PUT_USER(rc, i2DrainOutput, pIndex++ );
3122     			PUT_USER(rc, i2OutputFree, pIndex++ );
3123     			PUT_USER(rc, i2StripFifo, pIndex++ );
3124     			PUT_USER(rc, i2StuffFifoBypass, pIndex++ );
3125     			PUT_USER(rc, i2StuffFifoFlow, pIndex++ );
3126     			PUT_USER(rc, i2StuffFifoInline, pIndex++ );
3127     			PUT_USER(rc, i2ServiceBoard, pIndex++ );
3128     			PUT_USER(rc, serviceOutgoingFifo, pIndex++ );
3129     			// PUT_USER(rc, ip2_init, pIndex++ );
3130     			PUT_USER(rc, ip2_init_board, pIndex++ );
3131     			PUT_USER(rc, find_eisa_board, pIndex++ );
3132     			PUT_USER(rc, set_irq, pIndex++ );
3133     			PUT_USER(rc, ip2_interrupt, pIndex++ );
3134     			PUT_USER(rc, ip2_poll, pIndex++ );
3135     			PUT_USER(rc, service_all_boards, pIndex++ );
3136     			PUT_USER(rc, do_input, pIndex++ );
3137     			PUT_USER(rc, do_status, pIndex++ );
3138     #ifndef IP2DEBUG_OPEN
3139     			PUT_USER(rc, 0, pIndex++ );
3140     #else
3141     			PUT_USER(rc, open_sanity_check, pIndex++ );
3142     #endif
3143     			PUT_USER(rc, ip2_open, pIndex++ );
3144     			PUT_USER(rc, ip2_close, pIndex++ );
3145     			PUT_USER(rc, ip2_hangup, pIndex++ );
3146     			PUT_USER(rc, ip2_write, pIndex++ );
3147     			PUT_USER(rc, ip2_putchar, pIndex++ );
3148     			PUT_USER(rc, ip2_flush_chars, pIndex++ );
3149     			PUT_USER(rc, ip2_write_room, pIndex++ );
3150     			PUT_USER(rc, ip2_chars_in_buf, pIndex++ );
3151     			PUT_USER(rc, ip2_flush_buffer, pIndex++ );
3152     
3153     			//PUT_USER(rc, ip2_wait_until_sent, pIndex++ );
3154     			PUT_USER(rc, 0, pIndex++ );
3155     
3156     			PUT_USER(rc, ip2_throttle, pIndex++ );
3157     			PUT_USER(rc, ip2_unthrottle, pIndex++ );
3158     			PUT_USER(rc, ip2_ioctl, pIndex++ );
3159     			PUT_USER(rc, set_modem_info, pIndex++ );
3160     			PUT_USER(rc, get_serial_info, pIndex++ );
3161     			PUT_USER(rc, set_serial_info, pIndex++ );
3162     			PUT_USER(rc, ip2_set_termios, pIndex++ );
3163     			PUT_USER(rc, ip2_set_line_discipline, pIndex++ );
3164     			PUT_USER(rc, set_params, pIndex++ );
3165     		} else {
3166     			rc = -EINVAL;
3167     		}
3168     
3169     		break;
3170     
3171     	default:
3172     		rc = -ENODEV;
3173     		break;
3174     	}
3175     	return rc;
3176     }
3177     
3178     /******************************************************************************/
3179     /* Function:   ip2_ipl_open()                                                 */
3180     /* Parameters: Pointer to device inode                                        */
3181     /*             Pointer to file structure                                      */
3182     /* Returns:    Success or failure                                             */
3183     /*                                                                            */
3184     /* Description:                                                               */
3185     /*                                                                            */
3186     /*                                                                            */
3187     /******************************************************************************/
3188     static int
3189     ip2_ipl_open( struct inode *pInode, struct file *pFile )
3190     {
3191     	unsigned int iplminor = MINOR(pInode->i_rdev);
3192     	i2eBordStrPtr pB;
3193     	i2ChanStrPtr  pCh;
3194     
3195     #ifdef IP2DEBUG_IPL
3196     	printk (KERN_DEBUG "IP2IPL: open\n" );
3197     #endif
3198     
3199     	switch(iplminor) {
3200     	// These are the IPL devices
3201     	case 0:
3202     	case 4:
3203     	case 8:
3204     	case 12:
3205     		break;
3206     
3207     	// These are the status devices
3208     	case 1:
3209     	case 5:
3210     	case 9:
3211     	case 13:
3212     		break;
3213     
3214     	// These are the debug devices
3215     	case 2:
3216     	case 6:
3217     	case 10:
3218     	case 14:
3219     		pB = i2BoardPtrTable[iplminor / 4];
3220     		pCh = (i2ChanStrPtr) pB->i2eChannelPtr;
3221     		break;
3222     
3223     	// This is the trace device
3224     	case 3:
3225     		break;
3226     	}
3227     	return 0;
3228     }
3229     /******************************************************************************/
3230     /* Function:   ip2_read_procmem                                               */
3231     /* Parameters:                                                                */
3232     /*                                                                            */
3233     /* Returns: Length of output                                                  */
3234     /*                                                                            */
3235     /* Description:                                                               */
3236     /*   Supplies some driver operating parameters                                */
3237     /*	Not real useful unless your debugging the fifo							  */
3238     /*                                                                            */
3239     /******************************************************************************/
3240     
3241     #define LIMIT  (PAGE_SIZE - 120)
3242     
3243     static int
3244     ip2_read_procmem(char *buf, char **start, off_t offset, int len)
3245     {
3246     	i2eBordStrPtr  pB;
3247     	i2ChanStrPtr  pCh;
3248     	PTTY tty;
3249     	int i;
3250     
3251     	len = 0;
3252     
3253     #define FMTLINE	"%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
3254     #define FMTLIN2	"     0x%04x 0x%04x tx flow 0x%x\n"
3255     #define FMTLIN3	"     0x%04x 0x%04x rc flow\n"
3256     
3257     	len += sprintf(buf+len,"\n");
3258     
3259     	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3260     		pB = i2BoardPtrTable[i];
3261     		if ( pB ) {
3262     			len += sprintf(buf+len,"board %d:\n",i);
3263     			len += sprintf(buf+len,"\tFifo rem: %d mty: %x outM %x\n",
3264     				pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
3265     		}
3266     	}
3267     
3268     	len += sprintf(buf+len,"#: tty flags, port flags,     cflags,     iflags\n");
3269     	for (i=0; i < IP2_MAX_PORTS; i++) {
3270     		if (len > LIMIT)
3271     			break;
3272     		pCh = DevTable[i];
3273     		if (pCh) {
3274     			tty = pCh->pTTY;
3275     			if (tty && tty->count) {
3276     				len += sprintf(buf+len,FMTLINE,i,(int)tty->flags,pCh->flags,
3277     									tty->termios->c_cflag,tty->termios->c_iflag);
3278     
3279     				len += sprintf(buf+len,FMTLIN2,
3280     						pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
3281     				len += sprintf(buf+len,FMTLIN3,pCh->infl.asof,pCh->infl.room);
3282     			}
3283     		}
3284     	}
3285     	return len;
3286     }
3287     
3288     /*
3289      * This is the handler for /proc/tty/driver/ip2
3290      *
3291      * This stretch of code has been largely plagerized from at least three
3292      * different sources including ip2mkdev.c and a couple of other drivers.
3293      * The bugs are all mine.  :-)	=mhw=
3294      */
3295     int ip2_read_proc(char *page, char **start, off_t off,
3296     				int count, int *eof, void *data)
3297     {
3298     	int	i, j, box;
3299     	int	len = 0;
3300     	int	boxes = 0;
3301     	int	ports = 0;
3302     	int	tports = 0;
3303     	off_t	begin = 0;
3304     	i2eBordStrPtr  pB;
3305     
3306     	len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion );
3307     	len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
3308     			IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
3309     			IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
3310     
3311     	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3312     		/* This need to be reset for a board by board count... */
3313     		boxes = 0;
3314     		pB = i2BoardPtrTable[i];
3315     		if( pB ) {
3316     			switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
3317     			{
3318     			case POR_ID_FIIEX:
3319     				len += sprintf( page+len, "Board %d: EX ports=", i );
3320     				for( box = 0; box < ABS_MAX_BOXES; ++box )
3321     				{
3322     					ports = 0;
3323     
3324     					if( pB->i2eChannelMap[box] != 0 ) ++boxes;
3325     					for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
3326     					{
3327     						if( pB->i2eChannelMap[box] & 1<< j ) {
3328     							++ports;
3329     						}
3330     					}
3331     					len += sprintf( page+len, "%d,", ports );
3332     					tports += ports;
3333     				}
3334     
3335     				--len;	/* Backup over that last comma */
3336     
3337     				len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 );
3338     				break;
3339     
3340     			case POR_ID_II_4:
3341     				len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i );
3342     				tports = ports = 4;
3343     				break;
3344     
3345     			case POR_ID_II_8:
3346     				len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i );
3347     				tports = ports = 8;
3348     				break;
3349     
3350     			case POR_ID_II_8R:
3351     				len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i );
3352     				tports = ports = 8;
3353     				break;
3354     
3355     			default:
3356     				len += sprintf(page+len, "Board %d: unknown", i );
3357     				/* Don't try and probe for minor numbers */
3358     				tports = ports = 0;
3359     			}
3360     
3361     		} else {
3362     			/* Don't try and probe for minor numbers */
3363     			len += sprintf(page+len, "Board %d: vacant", i );
3364     			tports = ports = 0;
3365     		}
3366     
3367     		if( tports ) {
3368     			len += sprintf(page+len, " minors=" );
3369     
3370     			for ( box = 0; box < ABS_MAX_BOXES; ++box )
3371     			{
3372     				for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
3373     				{
3374     					if ( pB->i2eChannelMap[box] & (1 << j) )
3375     					{
3376     						len += sprintf (page+len,"%d,",
3377     							j + ABS_BIGGEST_BOX *
3378     							(box+i*ABS_MAX_BOXES));
3379     					}
3380     				}
3381     			}
3382     
3383     			page[ len - 1 ] = '\n';	/* Overwrite that last comma */
3384     		} else {
3385     			len += sprintf (page+len,"\n" );
3386     		}
3387     
3388     		if (len+begin > off+count)
3389     			break;
3390     		if (len+begin < off) {
3391     			begin += len;
3392     			len = 0;
3393     		}
3394     	}
3395     
3396     	if (i >= IP2_MAX_BOARDS)
3397     		*eof = 1;
3398     	if (off >= len+begin)
3399     		return 0;
3400     
3401     	*start = page + (off-begin);
3402     	return ((count < begin+len-off) ? count : begin+len-off);
3403      }
3404      
3405     /******************************************************************************/
3406     /* Function:   ip2trace()                                                     */
3407     /* Parameters: Value to add to trace buffer                                   */
3408     /* Returns:    Nothing                                                        */
3409     /*                                                                            */
3410     /* Description:                                                               */
3411     /*                                                                            */
3412     /*                                                                            */
3413     /******************************************************************************/
3414     void
3415     ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
3416     {
3417     #ifdef IP2DEBUG_TRACE
3418     	long flags;
3419     	unsigned long *pCode = &codes;
3420     	union ip2breadcrumb bc;
3421     	i2ChanStrPtr  pCh;
3422     
3423     
3424     	tracebuf[tracestuff++] = jiffies;
3425     	if ( tracestuff == TRACEMAX ) {
3426     		tracestuff = 0;
3427     	}
3428     	if ( tracestuff == tracestrip ) {
3429     		if ( ++tracestrip == TRACEMAX ) {
3430     			tracestrip = 0;
3431     		}
3432     		++tracewrap;
3433     	}
3434     
3435     	bc.hdr.port  = 0xff & pn;
3436     	bc.hdr.cat   = cat;
3437     	bc.hdr.codes = (unsigned char)( codes & 0xff );
3438     	bc.hdr.label = label;
3439     	tracebuf[tracestuff++] = bc.value;
3440     
3441     	for (;;) {
3442     		if ( tracestuff == TRACEMAX ) {
3443     			tracestuff = 0;
3444     		}
3445     		if ( tracestuff == tracestrip ) {
3446     			if ( ++tracestrip == TRACEMAX ) {
3447     				tracestrip = 0;
3448     			}
3449     			++tracewrap;
3450     		}
3451     
3452     		if ( !codes-- )
3453     			break;
3454     
3455     		tracebuf[tracestuff++] = *++pCode;
3456     	}
3457     #endif
3458     }
3459     
3460     
3461