Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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