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