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