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