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