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