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