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