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