- Kai Germaschewski: ymfpci cleanups and resource leak fixes
[davej-history.git] / drivers / char / ip2main.c
bloba5e3adca6f0666a7bd9f48b8c5ceee9358f3815b
1 /*
3 * (c) 1999 by Computone Corporation
5 ********************************************************************************
7 * PACKAGE: Linux tty Device Driver for IntelliPort family of multiport
8 * serial I/O controllers.
10 * DESCRIPTION: Mainline code for the device driver
12 *******************************************************************************/
13 // ToDo:
15 // Done:
17 // 1.2.9
18 // Four box EX was barfing on >128k kmalloc, made structure smaller by
19 // reducing output buffer size
21 // 1.2.8
22 // Device file system support (MHW)
24 // 1.2.7
25 // Fixed
26 // Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
28 // 1.2.6
29 //Fixes DCD problems
30 // DCD was not reported when CLOCAL was set on call to TIOCMGET
32 //Enhancements:
33 // TIOCMGET requests and waits for status return
34 // No DSS interrupts enabled except for DCD when needed
36 // For internal use only
38 //#define IP2DEBUG_INIT
39 //#define IP2DEBUG_OPEN
40 //#define IP2DEBUG_WRITE
41 //#define IP2DEBUG_READ
42 //#define IP2DEBUG_IOCTL
43 //#define IP2DEBUG_IPL
45 //#define IP2DEBUG_TRACE
46 //#define DEBUG_FIFO
48 /************/
49 /* Includes */
50 /************/
51 #include <linux/config.h>
52 // Uncomment the following if you want it compiled with modversions
53 #ifdef MODULE
54 # if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
55 # define MODVERSIONS
56 # endif
57 # ifdef MODVERSIONS
58 # include <linux/modversions.h>
59 # endif
60 #endif
62 #include <linux/version.h>
64 #include <linux/ctype.h>
65 #include <linux/string.h>
66 #include <linux/fcntl.h>
67 #include <linux/errno.h>
68 #include <linux/module.h>
69 #include <linux/signal.h>
70 #include <linux/sched.h>
71 #ifdef CONFIG_DEVFS_FS
72 #include <linux/devfs_fs_kernel.h>
73 #endif
74 #include <linux/timer.h>
75 #include <linux/interrupt.h>
76 #include <linux/pci.h>
77 #include <linux/mm.h>
78 #include <linux/malloc.h>
79 #include <linux/major.h>
80 #include <linux/wait.h>
82 #include <linux/tty.h>
83 #include <linux/tty_flip.h>
84 #include <linux/termios.h>
85 #include <linux/tty_driver.h>
86 #include <linux/serial.h>
87 #include <linux/ptrace.h>
88 #include <linux/ioport.h>
90 #include <linux/cdk.h>
91 #include <linux/comstats.h>
92 #include <linux/delay.h>
94 #include <asm/system.h>
95 #include <asm/io.h>
96 #include <asm/irq.h>
97 #include <asm/bitops.h>
99 #ifndef KERNEL_VERSION
100 #define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
101 #endif
103 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
104 # include <linux/vmalloc.h>
105 # include <linux/init.h>
106 # include <asm/serial.h>
107 #else
108 # include <linux/bios32.h>
109 #endif
111 // These VERSION switches maybe inexact because I simply don't know
112 // when the various features appeared in the 2.1.XX kernels.
113 // They are good enough for 2.0 vs 2.2 and if you are fooling with
114 // the 2.1.XX stuff then it would be trivial for you to fix.
115 // Most of these macros were stolen from some other drivers
116 // so blame them.
118 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4)
119 # include <asm/segment.h>
120 # define GET_USER(error,value,addr) error = get_user(value,addr)
121 # define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
122 # define PUT_USER(error,value,addr) error = put_user(value,addr)
123 # define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
125 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)
126 # include <asm/uaccess.h>
127 # define pcibios_strerror(status) \
128 printk( KERN_ERR "IP2: PCI error 0x%x \n", status );
129 # endif
131 #else /* 2.0.x and 2.1.x before 2.1.4 */
133 # define proc_register_dynamic(a,b) proc_register(a,b)
135 # define GET_USER(error,value,addr) \
136 do { \
137 error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \
138 if (error == 0) \
139 value = get_user(addr); \
140 } while (0)
142 # define COPY_FROM_USER(error,dest,src,size) \
143 do { \
144 error = verify_area (VERIFY_READ, (void *) src, size); \
145 if (error == 0) \
146 memcpy_fromfs (dest, src, size); \
147 } while (0)
149 # define PUT_USER(error,value,addr) \
150 do { \
151 error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \
152 if (error == 0) \
153 put_user (value, addr); \
154 } while (0)
156 # define COPY_TO_USER(error,dest,src,size) \
157 do { \
158 error = verify_area (VERIFY_WRITE, (void *) dest, size); \
159 if (error == 0) \
160 memcpy_tofs (dest, src, size); \
161 } while (0)
163 #endif
165 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
166 #define __init
167 #define __initfunc(a) a
168 #define __initdata
169 #define ioremap(a,b) vremap((a),(b))
170 #define iounmap(a) vfree((a))
171 #define SERIAL_TYPE_NORMAL 1
172 #define SERIAL_TYPE_CALLOUT 2
173 #define schedule_timeout(a){current->timeout = jiffies + (a); schedule();}
174 #define signal_pending(a) ((a)->signal & ~(a)->blocked)
175 #define in_interrupt() intr_count
176 #endif
178 #include "./ip2/ip2types.h"
179 #include "./ip2/ip2trace.h"
180 #include "./ip2/ip2ioctl.h"
181 #include "./ip2/ip2.h"
182 #include "./ip2/i2ellis.h"
183 #include "./ip2/i2lib.h"
185 /*****************
186 * /proc/ip2mem *
187 *****************/
189 #include <linux/proc_fs.h>
191 static int ip2_read_procmem(char *, char **, off_t, int);
192 int ip2_read_proc(char *, char **, off_t, int, int *, void * );
194 /********************/
195 /* Type Definitions */
196 /********************/
198 /*************/
199 /* Constants */
200 /*************/
202 /* String constants to identify ourselves */
203 static char *pcName = "Computone IntelliPort Plus multiport driver";
204 static char *pcVersion = "1.2.9";
206 /* String constants for port names */
207 static char *pcDriver_name = "ip2";
208 #ifdef CONFIG_DEVFS_FS
209 static char *pcTty = "ttf/%d";
210 static char *pcCallout = "cuf/%d";
211 #else
212 static char *pcTty = "ttyF";
213 static char *pcCallout = "cuf";
214 #endif
215 static char *pcIpl = "ip2ipl";
217 /* Serial subtype definitions */
218 #define SERIAL_TYPE_NORMAL 1
219 #define SERIAL_TYPE_CALLOUT 2
221 // cheezy kludge or genius - you decide?
222 int ip2_loadmain(int *, int *, unsigned char *, int);
223 static unsigned char *Fip_firmware;
224 static int Fip_firmware_size;
226 /***********************/
227 /* Function Prototypes */
228 /***********************/
230 /* Global module entry functions */
231 #ifdef MODULE
232 int init_module(void);
233 void cleanup_module(void);
234 #endif
236 int old_ip2_init(void);
238 /* Private (static) functions */
239 static int ip2_open(PTTY, struct file *);
240 static void ip2_close(PTTY, struct file *);
241 static int ip2_write(PTTY, int, const unsigned char *, int);
242 static void ip2_putchar(PTTY, unsigned char);
243 static void ip2_flush_chars(PTTY);
244 static int ip2_write_room(PTTY);
245 static int ip2_chars_in_buf(PTTY);
246 static void ip2_flush_buffer(PTTY);
247 static int ip2_ioctl(PTTY, struct file *, UINT, ULONG);
248 static void ip2_set_termios(PTTY, struct termios *);
249 static void ip2_set_line_discipline(PTTY);
250 static void ip2_throttle(PTTY);
251 static void ip2_unthrottle(PTTY);
252 static void ip2_stop(PTTY);
253 static void ip2_start(PTTY);
254 static void ip2_hangup(PTTY);
256 static void set_irq(int, int);
257 static void ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs);
258 static void ip2_poll(unsigned long arg);
259 static inline void service_all_boards(void);
260 static inline void do_input(i2ChanStrPtr pCh);
261 static inline void do_status(i2ChanStrPtr pCh);
263 static void ip2_wait_until_sent(PTTY,int);
265 static void set_params (i2ChanStrPtr, struct termios *);
266 static int set_modem_info(i2ChanStrPtr, unsigned int, unsigned int *);
267 static int get_serial_info(i2ChanStrPtr, struct serial_struct *);
268 static int set_serial_info(i2ChanStrPtr, struct serial_struct *);
270 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
271 static int ip2_ipl_read(struct inode *, char *, size_t , loff_t *);
272 #else
273 static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ;
274 #endif
275 static ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *);
276 static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG);
277 static int ip2_ipl_open(struct inode *, struct file *);
279 void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
280 static int DumpTraceBuffer(char *, int);
281 static int DumpFifoBuffer( char *, int);
283 static void ip2_init_board(int);
284 static unsigned short find_eisa_board(int);
286 /***************/
287 /* Static Data */
288 /***************/
290 static struct tty_driver ip2_tty_driver;
291 static struct tty_driver ip2_callout_driver;
293 static int ref_count;
295 /* Here, then is a table of board pointers which the interrupt routine should
296 * scan through to determine who it must service.
298 static unsigned short i2nBoards; // Number of boards here
300 static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
302 static i2ChanStrPtr DevTable[IP2_MAX_PORTS];
303 //DevTableMem just used to save addresses for kfree
304 static void *DevTableMem[IP2_MAX_BOARDS];
306 static struct tty_struct * TtyTable[IP2_MAX_PORTS];
307 static struct termios * Termios[IP2_MAX_PORTS];
308 static struct termios * TermiosLocked[IP2_MAX_PORTS];
310 /* This is the driver descriptor for the ip2ipl device, which is used to
311 * download the loadware to the boards.
313 static struct file_operations ip2_ipl = {
314 owner: THIS_MODULE,
315 read: ip2_ipl_read,
316 write: ip2_ipl_write,
317 ioctl: ip2_ipl_ioctl,
318 open: ip2_ipl_open,
321 static long irq_counter;
322 static long bh_counter;
324 // Use immediate queue to service interrupts
325 //#define USE_IQI // PCI&2.2 needs work
326 //#define USE_IQ // PCI&2.2 needs work
328 /* The timer_list entry for our poll routine. If interrupt operation is not
329 * selected, the board is serviced periodically to see if anything needs doing.
331 #define POLL_TIMEOUT (jiffies + 1)
332 static struct timer_list PollTimer = { function: ip2_poll };
333 static char TimerOn;
335 #ifdef IP2DEBUG_TRACE
336 /* Trace (debug) buffer data */
337 #define TRACEMAX 1000
338 static unsigned long tracebuf[TRACEMAX];
339 static int tracestuff;
340 static int tracestrip;
341 static int tracewrap;
342 #endif
344 /**********/
345 /* Macros */
346 /**********/
348 #if defined(MODULE) && defined(IP2DEBUG_OPEN)
349 #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
350 kdevname(tty->device),(pCh->flags),ref_count, \
351 tty->count,/*GET_USE_COUNT(module)*/0,s)
352 #else
353 #define DBG_CNT(s)
354 #endif
356 #define MIN(a,b) ( ( (a) < (b) ) ? (a) : (b) )
357 #define MAX(a,b) ( ( (a) > (b) ) ? (a) : (b) )
359 /********/
360 /* Code */
361 /********/
363 #include "./ip2/i2ellis.c" /* Extremely low-level interface services */
364 #include "./ip2/i2cmd.c" /* Standard loadware command definitions */
365 #include "./ip2/i2lib.c" /* High level interface services */
367 /* Configuration area for modprobe */
368 #ifdef MODULE
369 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
370 MODULE_AUTHOR("Doug McNash");
371 MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
372 # endif /* LINUX_VERSION */
373 #endif /* MODULE */
375 static int poll_only;
377 static int Eisa_irq;
378 static int Eisa_slot;
380 static int iindx;
381 static char rirqs[IP2_MAX_BOARDS];
382 static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
384 /******************************************************************************/
385 /* Initialisation Section */
386 /******************************************************************************/
387 int
388 ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
390 int i;
391 /* process command line arguments to modprobe or insmod i.e. iop & irqp */
392 /* otherwise ip2config is initialized by what's in ip2/ip2.h */
393 /* command line trumps initialization in ip2.h */
394 /* first two args are null if builtin to kernel */
395 if ((irqp != NULL) || (iop != NULL)) {
396 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
397 if (irqp && irqp[i]) {
398 ip2config.irq[i] = irqp[i];
400 if (iop && iop[i]) {
401 ip2config.addr[i] = iop[i];
405 Fip_firmware = firmware;
406 Fip_firmware_size = firmsize;
407 return old_ip2_init();
410 // Some functions to keep track of what irq's we have
412 static int __init
413 is_valid_irq(int irq)
415 int *i = Valid_Irqs;
417 while ((*i != 0) && (*i != irq)) {
418 i++;
420 return (*i);
423 static void __init
424 mark_requested_irq( char irq )
426 rirqs[iindx++] = irq;
429 static int __init
430 clear_requested_irq( char irq )
432 int i;
433 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
434 if (rirqs[i] == irq) {
435 rirqs[i] = 0;
436 return 1;
439 return 0;
442 static int __init
443 have_requested_irq( char irq )
445 // array init to zeros so 0 irq will not be requested as a side effect
446 int i;
447 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
448 if (rirqs[i] == irq)
449 return 1;
451 return 0;
454 /******************************************************************************/
455 /* Function: init_module() */
456 /* Parameters: None */
457 /* Returns: Success (0) */
458 /* */
459 /* Description: */
460 /* This is a required entry point for an installable module. It simply calls */
461 /* the driver initialisation function and returns what it returns. */
462 /******************************************************************************/
463 #ifdef MODULE
465 init_module(void)
467 #ifdef IP2DEBUG_INIT
468 printk (KERN_DEBUG "Loading module ...\n" );
469 #endif
470 //was return old_ip2_init();
471 return 0;
473 #endif /* MODULE */
475 /******************************************************************************/
476 /* Function: cleanup_module() */
477 /* Parameters: None */
478 /* Returns: Nothing */
479 /* */
480 /* Description: */
481 /* This is a required entry point for an installable module. It has to return */
482 /* the device and the driver to a passive state. It should not be necessary */
483 /* to reset the board fully, especially as the loadware is downloaded */
484 /* externally rather than in the driver. We just want to disable the board */
485 /* and clear the loadware to a reset state. To allow this there has to be a */
486 /* way to detect whether the board has the loadware running at init time to */
487 /* handle subsequent installations of the driver. All memory allocated by the */
488 /* driver should be returned since it may be unloaded from memory. */
489 /******************************************************************************/
490 #ifdef MODULE
491 void
492 cleanup_module(void)
494 int err;
495 int i;
497 #ifdef IP2DEBUG_INIT
498 printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion );
499 #endif
500 /* Stop poll timer if we had one. */
501 if ( TimerOn ) {
502 del_timer ( &PollTimer );
503 TimerOn = 0;
506 /* Reset the boards we have. */
507 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
508 if ( i2BoardPtrTable[i] ) {
509 iiReset( i2BoardPtrTable[i] );
513 /* The following is done at most once, if any boards were installed. */
514 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
515 if ( i2BoardPtrTable[i] ) {
516 iiResetDelay( i2BoardPtrTable[i] );
517 /* free io addresses and Tibet */
518 release_region( ip2config.addr[i], 8 );
519 #ifdef CONFIG_DEVFS_FS
520 devfs_unregister (i2BoardPtrTable[i]->devfs_ipl_handle);
521 devfs_unregister (i2BoardPtrTable[i]->devfs_stat_handle);
522 #endif
524 /* Disable and remove interrupt handler. */
525 if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) {
526 free_irq ( ip2config.irq[i], (void *)&pcName);
527 clear_requested_irq( ip2config.irq[i]);
530 if ( ( err = tty_unregister_driver ( &ip2_tty_driver ) ) ) {
531 printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
533 if ( ( err = tty_unregister_driver ( &ip2_callout_driver ) ) ) {
534 printk(KERN_ERR "IP2: failed to unregister callout driver (%d)\n", err);
536 #ifdef CONFIG_DEVFS_FS
537 if ( ( err = devfs_unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
538 #else
539 if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
540 #endif
542 printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
544 remove_proc_entry("ip2mem", &proc_root);
546 // free memory
547 for (i = 0; i < IP2_MAX_BOARDS; i++) {
548 void *pB;
549 if ((pB = i2BoardPtrTable[i]) != 0 ) {
550 kfree ( pB );
551 i2BoardPtrTable[i] = NULL;
553 if ((DevTableMem[i]) != NULL ) {
554 kfree ( DevTableMem[i] );
555 DevTableMem[i] = NULL;
559 /* Cleanup the iiEllis subsystem. */
560 iiEllisCleanup();
561 #ifdef IP2DEBUG_INIT
562 printk (KERN_DEBUG "IP2 Unloaded\n" );
563 #endif
565 #endif /* MODULE */
567 /******************************************************************************/
568 /* Function: old_ip2_init() */
569 /* Parameters: irq, io from command line of insmod et. al. */
570 /* Returns: Success (0) */
571 /* */
572 /* Description: */
573 /* This was the required entry point for all drivers (now in ip2.c) */
574 /* It performs all */
575 /* initialisation of the devices and driver structures, and registers itself */
576 /* with the relevant kernel modules. */
577 /******************************************************************************/
578 /* SA_INTERRUPT- if set blocks all interrupts else only this line */
579 /* SA_SHIRQ - for shared irq PCI or maybe EISA only */
580 /* SA_RANDOM - can be source for cert. random number generators */
581 #define IP2_SA_FLAGS 0
583 int __init
584 old_ip2_init(void)
586 #ifdef CONFIG_DEVFS_FS
587 static devfs_handle_t devfs_handle;
588 int j, box;
589 #endif
590 int i;
591 int err;
592 int status = 0;
593 static int loaded;
594 i2eBordStrPtr pB = NULL;
595 int rc = -1;
597 #ifdef IP2DEBUG_TRACE
598 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 );
599 #endif
601 /* Announce our presence */
602 printk( KERN_INFO "%s version %s\n", pcName, pcVersion );
604 // ip2 can be unloaded and reloaded for no good reason
605 // we can't let that happen here or bad things happen
606 // second load hoses board but not system - fixme later
607 if (loaded) {
608 printk( KERN_INFO "Still loaded\n" );
609 return 0;
611 loaded++;
613 /* if all irq config is zero we shall poll_only */
614 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
615 poll_only |= ip2config.irq[i];
617 poll_only = !poll_only;
619 /* Initialise the iiEllis subsystem. */
620 iiEllisInit();
622 /* Initialize arrays. */
623 memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable );
624 memset( DevTable, 0, sizeof DevTable );
625 memset( TtyTable, 0, sizeof TtyTable );
626 memset( Termios, 0, sizeof Termios );
627 memset( TermiosLocked, 0, sizeof TermiosLocked );
629 /* Initialise all the boards we can find (up to the maximum). */
630 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
631 switch ( ip2config.addr[i] ) {
632 case 0: /* skip this slot even if card is present */
633 break;
634 default: /* ISA */
635 /* ISA address must be specified */
636 if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) {
637 printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n",
638 i, ip2config.addr[i] );
639 ip2config.addr[i] = 0;
640 } else {
641 ip2config.type[i] = ISA;
643 /* Check for valid irq argument, set for polling if invalid */
644 if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) {
645 printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]);
646 ip2config.irq[i] = 0;// 0 is polling and is valid in that sense
649 break;
650 case PCI:
651 #ifdef CONFIG_PCI
652 #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
653 if (pcibios_present()) {
654 unsigned char pci_bus, pci_devfn;
655 int Pci_index = 0;
656 status = pcibios_find_device(PCI_VENDOR_ID_COMPUTONE,
657 PCI_DEVICE_ID_COMPUTONE_IP2EX, Pci_index,
658 &pci_bus, &pci_devfn);
659 if (status == 0) {
660 unsigned int addr;
661 unsigned char pci_irq;
663 ip2config.type[i] = PCI;
665 * Update Pci_index, so that the next time we go
666 * searching for a PCI board we find a different
667 * one.
669 ++Pci_index;
671 pcibios_read_config_dword(pci_bus, pci_devfn,
672 PCI_BASE_ADDRESS_1, &addr);
673 if ( addr & 1 ) {
674 ip2config.addr[i]=(USHORT)(addr&0xfffe);
675 } else {
676 printk( KERN_ERR "IP2: PCI I/O address error\n");
678 pcibios_read_config_byte(pci_bus, pci_devfn,
679 PCI_INTERRUPT_LINE, &pci_irq);
681 if (!is_valid_irq(pci_irq)) {
682 printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
683 pci_irq = 0;
685 ip2config.irq[i] = pci_irq;
686 } else { // ann error
687 ip2config.addr[i] = 0;
688 if (status == PCIBIOS_DEVICE_NOT_FOUND) {
689 printk( KERN_ERR "IP2: PCI board %d not found\n", i );
690 } else {
691 pcibios_strerror(status);
695 #else /* LINUX_VERSION_CODE > 2.1.99 */
696 if (pci_present()) {
697 struct pci_dev *pci_dev_i = NULL;
698 pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE,
699 PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
700 if (pci_dev_i != NULL) {
701 unsigned int addr;
702 unsigned char pci_irq;
704 ip2config.type[i] = PCI;
705 status =
706 pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
707 if ( addr & 1 ) {
708 ip2config.addr[i]=(USHORT)(addr&0xfffe);
709 } else {
710 printk( KERN_ERR "IP2: PCI I/O address error\n");
712 status =
713 pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
715 if (!is_valid_irq(pci_irq)) {
716 printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
717 pci_irq = 0;
719 ip2config.irq[i] = pci_irq;
720 } else { // ann error
721 ip2config.addr[i] = 0;
722 if (status == PCIBIOS_DEVICE_NOT_FOUND) {
723 printk( KERN_ERR "IP2: PCI board %d not found\n", i );
724 } else {
725 pcibios_strerror(status);
729 #endif /* ! 2_0_X */
730 #else
731 printk( KERN_ERR "IP2: PCI card specified but PCI support not\n");
732 printk( KERN_ERR "IP2: configured in this kernel.\n");
733 printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n");
734 #endif /* CONFIG_PCI */
735 break;
736 case EISA:
737 if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) {
738 /* Eisa_irq set as side effect, boo */
739 ip2config.type[i] = EISA;
741 ip2config.irq[i] = Eisa_irq;
742 break;
743 } /* switch */
744 } /* for */
745 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
746 if ( ip2config.addr[i] ) {
747 pB = kmalloc( sizeof(i2eBordStr), GFP_KERNEL);
748 if ( pB != NULL ) {
749 i2BoardPtrTable[i] = pB;
750 memset( pB, 0, sizeof(i2eBordStr) );
751 iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer );
752 iiReset( pB );
753 } else {
754 printk(KERN_ERR "IP2: board memory allocation error\n");
758 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
759 if ( ( pB = i2BoardPtrTable[i] ) != NULL ) {
760 iiResetDelay( pB );
761 break;
764 for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
765 if ( i2BoardPtrTable[i] != NULL ) {
766 ip2_init_board( i );
770 #ifdef IP2DEBUG_TRACE
771 ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 );
772 #endif
774 /* Zero out the normal tty device structure. */
775 memset ( &ip2_tty_driver, 0, sizeof ip2_tty_driver );
777 /* Initialise the relevant fields. */
778 ip2_tty_driver.magic = TTY_DRIVER_MAGIC;
779 ip2_tty_driver.name = pcTty;
780 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
781 ip2_tty_driver.driver_name = pcDriver_name;
782 ip2_tty_driver.read_proc = ip2_read_proc;
783 #endif
784 ip2_tty_driver.major = IP2_TTY_MAJOR;
785 ip2_tty_driver.minor_start = 0;
786 ip2_tty_driver.num = IP2_MAX_PORTS;
787 ip2_tty_driver.type = TTY_DRIVER_TYPE_SERIAL;
788 ip2_tty_driver.subtype = SERIAL_TYPE_NORMAL;
789 ip2_tty_driver.init_termios = tty_std_termios;
790 ip2_tty_driver.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
791 #ifdef CONFIG_DEVFS_FS
792 ip2_tty_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
793 #else
794 ip2_tty_driver.flags = TTY_DRIVER_REAL_RAW;
795 #endif
796 ip2_tty_driver.refcount = &ref_count;
797 ip2_tty_driver.table = TtyTable;
798 ip2_tty_driver.termios = Termios;
799 ip2_tty_driver.termios_locked = TermiosLocked;
801 /* Setup the pointers to the implemented functions. */
802 ip2_tty_driver.open = ip2_open;
803 ip2_tty_driver.close = ip2_close;
804 ip2_tty_driver.write = ip2_write;
805 ip2_tty_driver.put_char = ip2_putchar;
806 ip2_tty_driver.flush_chars = ip2_flush_chars;
807 ip2_tty_driver.write_room = ip2_write_room;
808 ip2_tty_driver.chars_in_buffer = ip2_chars_in_buf;
809 ip2_tty_driver.flush_buffer = ip2_flush_buffer;
810 ip2_tty_driver.ioctl = ip2_ioctl;
811 ip2_tty_driver.throttle = ip2_throttle;
812 ip2_tty_driver.unthrottle = ip2_unthrottle;
813 ip2_tty_driver.set_termios = ip2_set_termios;
814 ip2_tty_driver.set_ldisc = ip2_set_line_discipline;
815 ip2_tty_driver.stop = ip2_stop;
816 ip2_tty_driver.start = ip2_start;
817 ip2_tty_driver.hangup = ip2_hangup;
819 /* Initialise the callout driver structure from the tty driver, and
820 * make the needed adjustments.
822 ip2_callout_driver = ip2_tty_driver;
823 ip2_callout_driver.name = pcCallout;
824 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
825 ip2_callout_driver.driver_name = pcDriver_name;
826 ip2_callout_driver.read_proc = NULL;
827 #endif
828 ip2_callout_driver.major = IP2_CALLOUT_MAJOR;
829 ip2_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
831 #ifdef IP2DEBUG_TRACE
832 ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 );
833 #endif
835 /* Register the tty devices. */
836 if ( ( err = tty_register_driver ( &ip2_tty_driver ) ) ) {
837 printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err);
838 } else
839 if ( ( err = tty_register_driver ( &ip2_callout_driver ) ) ) {
840 printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err);
841 } else
842 /* Register the IPL driver. */
843 #ifdef CONFIG_DEVFS_FS
844 if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl )))
845 #else
846 if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) )
847 #endif
849 printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
850 } else
851 /* Register the read_procmem thing */
852 if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) {
853 printk(KERN_ERR "IP2: failed to register read_procmem\n");
854 } else {
856 #ifdef IP2DEBUG_TRACE
857 ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 );
858 #endif
859 /* Register the interrupt handler or poll handler, depending upon the
860 * specified interrupt.
862 #ifdef CONFIG_DEVFS_FS
863 if (!devfs_handle)
864 devfs_handle = devfs_mk_dir (NULL, "ip2", NULL);
865 #endif
867 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
868 #ifdef CONFIG_DEVFS_FS
869 char name[16];
870 #endif
872 if ( 0 == ip2config.addr[i] ) {
873 continue;
876 #ifdef CONFIG_DEVFS_FS
877 sprintf( name, "ipl%d", i );
878 i2BoardPtrTable[i]->devfs_ipl_handle =
879 devfs_register (devfs_handle, name,
880 DEVFS_FL_DEFAULT,
881 IP2_IPL_MAJOR, 4 * i,
882 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
883 &ip2_ipl, NULL);
885 sprintf( name, "stat%d", i );
886 i2BoardPtrTable[i]->devfs_stat_handle =
887 devfs_register (devfs_handle, name,
888 DEVFS_FL_DEFAULT,
889 IP2_IPL_MAJOR, 4 * i + 1,
890 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
891 &ip2_ipl, NULL);
893 for ( box = 0; box < ABS_MAX_BOXES; ++box )
895 for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
897 if ( pB->i2eChannelMap[box] & (1 << j) )
899 tty_register_devfs(&ip2_tty_driver,
900 0, j + ABS_BIGGEST_BOX *
901 (box+i*ABS_MAX_BOXES));
902 tty_register_devfs(&ip2_callout_driver,
903 0, j + ABS_BIGGEST_BOX *
904 (box+i*ABS_MAX_BOXES));
908 #endif
910 if (poll_only) {
911 ip2config.irq[i] = CIR_POLL;
913 if ( ip2config.irq[i] == CIR_POLL ) {
914 retry:
915 if (!TimerOn) {
916 PollTimer.expires = POLL_TIMEOUT;
917 add_timer ( &PollTimer );
918 TimerOn = 1;
919 printk( KERN_INFO "IP2: polling\n");
921 } else {
922 if (have_requested_irq(ip2config.irq[i]))
923 continue;
924 rc = request_irq( ip2config.irq[i], ip2_interrupt,
925 IP2_SA_FLAGS | (ip2config.type[i] == PCI ? SA_SHIRQ : 0),
926 pcName, (void *)&pcName);
927 if (rc) {
928 printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc);
929 ip2config.irq[i] = CIR_POLL;
930 printk( KERN_INFO "IP2: Polling %ld/sec.\n",
931 (POLL_TIMEOUT - jiffies));
932 goto retry;
934 mark_requested_irq(ip2config.irq[i]);
935 /* Initialise the interrupt handler bottom half (aka slih). */
938 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
939 if ( i2BoardPtrTable[i] ) {
940 set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */
944 #ifdef IP2DEBUG_TRACE
945 ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 );
946 #endif
948 return 0;
951 /******************************************************************************/
952 /* Function: ip2_init_board() */
953 /* Parameters: Index of board in configuration structure */
954 /* Returns: Success (0) */
955 /* */
956 /* Description: */
957 /* This function initializes the specified board. The loadware is copied to */
958 /* the board, the channel structures are initialized, and the board details */
959 /* are reported on the console. */
960 /******************************************************************************/
961 static void __init
962 ip2_init_board( int boardnum )
964 int i,rc;
965 int nports = 0, nboxes = 0;
966 i2ChanStrPtr pCh;
967 i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
969 if ( !iiInitialize ( pB ) ) {
970 printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
971 pB->i2eBase, pB->i2eError );
972 kfree ( pB );
973 i2BoardPtrTable[boardnum] = NULL;
974 return;
976 printk(KERN_INFO "Board %d: addr=0x%x irq=%d ", boardnum + 1,
977 ip2config.addr[boardnum], ip2config.irq[boardnum] );
979 if (0 != ( rc = check_region( ip2config.addr[boardnum], 8))) {
980 i2BoardPtrTable[boardnum] = NULL;
981 printk(KERN_ERR "bad addr=0x%x rc = %d\n",
982 ip2config.addr[boardnum], rc );
983 return;
985 request_region( ip2config.addr[boardnum], 8, pcName );
987 if ( iiDownloadAll ( pB, (loadHdrStrPtr)Fip_firmware, 1, Fip_firmware_size )
988 != II_DOWN_GOOD ) {
989 printk ( KERN_ERR "IP2:failed to download loadware " );
990 } else {
991 printk ( KERN_INFO "fv=%d.%d.%d lv=%d.%d.%d\n",
992 pB->i2ePom.e.porVersion,
993 pB->i2ePom.e.porRevision,
994 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
995 pB->i2eLRevision, pB->i2eLSub );
998 switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
1000 default:
1001 printk( KERN_ERR "IP2: Unknown board type, ID = %x",
1002 pB->i2ePom.e.porID );
1003 nports = 0;
1004 goto ex_exit;
1005 break;
1007 case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
1008 printk ( KERN_INFO "ISA-4" );
1009 nports = 4;
1010 break;
1012 case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
1013 printk ( KERN_INFO "ISA-8 std" );
1014 nports = 8;
1015 break;
1017 case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
1018 printk ( KERN_INFO "ISA-8 RJ11" );
1019 nports = 8;
1020 break;
1022 case POR_ID_FIIEX: /* IntelliPort IIEX */
1024 int portnum = IP2_PORTS_PER_BOARD * boardnum;
1025 int box;
1027 for( box = 0; box < ABS_MAX_BOXES; ++box ) {
1028 if ( pB->i2eChannelMap[box] != 0 ) {
1029 ++nboxes;
1031 for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
1032 if ( pB->i2eChannelMap[box] & 1<< i ) {
1033 ++nports;
1037 DevTableMem[boardnum] = pCh =
1038 kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
1039 if ( !i2InitChannels( pB, nports, pCh ) ) {
1040 printk(KERN_ERR "i2InitChannels failed: %d\n",pB->i2eError);
1042 pB->i2eChannelPtr = &DevTable[portnum];
1043 pB->i2eChannelCnt = ABS_MOST_PORTS;
1045 for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
1046 for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
1047 if ( pB->i2eChannelMap[box] & (1 << i) ) {
1048 DevTable[portnum + i] = pCh;
1049 pCh->port_index = portnum + i;
1050 pCh++;
1054 printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit",
1055 nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
1057 goto ex_exit;
1058 break;
1060 DevTableMem[boardnum] = pCh =
1061 kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
1062 pB->i2eChannelPtr = pCh;
1063 pB->i2eChannelCnt = nports;
1064 i2InitChannels ( pB, pB->i2eChannelCnt, pCh );
1065 pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
1067 for( i = 0; i < pB->i2eChannelCnt; ++i ) {
1068 DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
1069 pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
1070 pCh++;
1072 ex_exit:
1073 printk ( KERN_INFO "\n" );
1076 /******************************************************************************/
1077 /* Function: find_eisa_board ( int start_slot ) */
1078 /* Parameters: First slot to check */
1079 /* Returns: Address of EISA IntelliPort II controller */
1080 /* */
1081 /* Description: */
1082 /* This function searches for an EISA IntelliPort controller, starting */
1083 /* from the specified slot number. If the motherboard is not identified as an */
1084 /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
1085 /* it returns the base address of the controller. */
1086 /******************************************************************************/
1087 static unsigned short __init
1088 find_eisa_board( int start_slot )
1090 int i, j;
1091 unsigned int idm = 0;
1092 unsigned int idp = 0;
1093 unsigned int base = 0;
1094 unsigned int value;
1095 int setup_address;
1096 int setup_irq;
1097 int ismine = 0;
1100 * First a check for an EISA motherboard, which we do by comparing the
1101 * EISA ID registers for the system board and the first couple of slots.
1102 * No slot ID should match the system board ID, but on an ISA or PCI
1103 * machine the odds are that an empty bus will return similar values for
1104 * each slot.
1106 i = 0x0c80;
1107 value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
1108 for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
1109 j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
1110 if ( value == j )
1111 return 0;
1115 * OK, so we are inclined to believe that this is an EISA machine. Find
1116 * an IntelliPort controller.
1118 for( i = start_slot; i < 16; i++ ) {
1119 base = i << 12;
1120 idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
1121 idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
1122 ismine = 0;
1123 if ( idm == 0x0e8e ) {
1124 if ( idp == 0x0281 || idp == 0x0218 ) {
1125 ismine = 1;
1126 } else if ( idp == 0x0282 || idp == 0x0283 ) {
1127 ismine = 3; /* Can do edge-trigger */
1129 if ( ismine ) {
1130 Eisa_slot = i;
1131 break;
1135 if ( !ismine )
1136 return 0;
1138 /* It's some sort of EISA card, but at what address is it configured? */
1140 setup_address = base + 0xc88;
1141 value = inb(base + 0xc86);
1142 setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
1144 if ( (ismine & 2) && !(value & 0x10) ) {
1145 ismine = 1; /* Could be edging, but not */
1148 if ( Eisa_irq == 0 ) {
1149 Eisa_irq = setup_irq;
1150 } else if ( Eisa_irq != setup_irq ) {
1151 printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
1154 #ifdef IP2DEBUG_INIT
1155 printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
1156 base >> 12, idm, idp, setup_address);
1157 if ( Eisa_irq ) {
1158 printk(KERN_DEBUG ", Interrupt %d %s\n",
1159 setup_irq, (ismine & 2) ? "(edge)" : "(level)");
1160 } else {
1161 printk(KERN_DEBUG ", (polled)\n");
1163 #endif
1164 return setup_address;
1167 /******************************************************************************/
1168 /* Function: set_irq() */
1169 /* Parameters: index to board in board table */
1170 /* IRQ to use */
1171 /* Returns: Success (0) */
1172 /* */
1173 /* Description: */
1174 /******************************************************************************/
1175 static void
1176 set_irq( int boardnum, int boardIrq )
1178 unsigned char tempCommand[16];
1179 i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
1180 unsigned long flags;
1183 * Notify the boards they may generate interrupts. This is done by
1184 * sending an in-line command to channel 0 on each board. This is why
1185 * the channels have to be defined already. For each board, if the
1186 * interrupt has never been defined, we must do so NOW, directly, since
1187 * board will not send flow control or even give an interrupt until this
1188 * is done. If polling we must send 0 as the interrupt parameter.
1191 // We will get an interrupt here at the end of this function
1193 iiDisableMailIrq(pB);
1195 /* We build up the entire packet header. */
1196 CHANNEL_OF(tempCommand) = 0;
1197 PTYPE_OF(tempCommand) = PTYPE_INLINE;
1198 CMD_COUNT_OF(tempCommand) = 2;
1199 (CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
1200 (CMD_OF(tempCommand))[1] = boardIrq;
1202 * Write to FIFO; don't bother to adjust fifo capacity for this, since
1203 * board will respond almost immediately after SendMail hit.
1205 WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1206 iiWriteBuf(pB, tempCommand, 4);
1207 WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1208 pB->i2eUsingIrq = boardIrq;
1209 pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
1211 /* Need to update number of boards before you enable mailbox int */
1212 ++i2nBoards;
1214 CHANNEL_OF(tempCommand) = 0;
1215 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1216 CMD_COUNT_OF(tempCommand) = 6;
1217 (CMD_OF(tempCommand))[0] = 88; // SILO
1218 (CMD_OF(tempCommand))[1] = 64; // chars
1219 (CMD_OF(tempCommand))[2] = 32; // ms
1221 (CMD_OF(tempCommand))[3] = 28; // MAX_BLOCK
1222 (CMD_OF(tempCommand))[4] = 64; // chars
1224 (CMD_OF(tempCommand))[5] = 87; // HW_TEST
1225 WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1226 iiWriteBuf(pB, tempCommand, 8);
1227 WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1229 CHANNEL_OF(tempCommand) = 0;
1230 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1231 CMD_COUNT_OF(tempCommand) = 1;
1232 (CMD_OF(tempCommand))[0] = 84; /* get BOX_IDS */
1233 iiWriteBuf(pB, tempCommand, 3);
1235 #ifdef XXX
1236 // enable heartbeat for test porpoises
1237 CHANNEL_OF(tempCommand) = 0;
1238 PTYPE_OF(tempCommand) = PTYPE_BYPASS;
1239 CMD_COUNT_OF(tempCommand) = 2;
1240 (CMD_OF(tempCommand))[0] = 44; /* get ping */
1241 (CMD_OF(tempCommand))[1] = 200; /* 200 ms */
1242 WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
1243 iiWriteBuf(pB, tempCommand, 4);
1244 WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
1245 #endif
1247 iiEnableMailIrq(pB);
1248 iiSendPendingMail(pB);
1251 /******************************************************************************/
1252 /* Interrupt Handler Section */
1253 /******************************************************************************/
1255 static inline void
1256 service_all_boards()
1258 int i;
1259 i2eBordStrPtr pB;
1261 /* Service every board on the list */
1262 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
1263 pB = i2BoardPtrTable[i];
1264 if ( pB ) {
1265 i2ServiceBoard( pB );
1271 #ifdef USE_IQI
1272 static struct tq_struct
1273 senior_service =
1274 { // it's the death that worse than fate
1275 NULL,
1277 (void(*)(void*)) service_all_boards,
1278 NULL, //later - board address XXX
1280 #endif
1282 /******************************************************************************/
1283 /* Function: ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs) */
1284 /* Parameters: irq - interrupt number */
1285 /* pointer to optional device ID structure */
1286 /* pointer to register structure */
1287 /* Returns: Nothing */
1288 /* */
1289 /* Description: */
1290 /* */
1291 /* */
1292 /******************************************************************************/
1293 static void
1294 ip2_interrupt(int irq, void *dev_id, struct pt_regs * regs)
1296 int i;
1297 i2eBordStrPtr pB;
1299 #ifdef IP2DEBUG_TRACE
1300 ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq );
1301 #endif
1303 #ifdef USE_IQI
1305 queue_task(&senior_service, &tq_immediate);
1306 mark_bh(IMMEDIATE_BH);
1308 #else
1309 /* Service just the boards on the list using this irq */
1310 for( i = 0; i < i2nBoards; ++i ) {
1311 pB = i2BoardPtrTable[i];
1312 if ( pB && (pB->i2eUsingIrq == irq) ) {
1313 i2ServiceBoard( pB );
1317 #endif /* USE_IQI */
1319 ++irq_counter;
1321 #ifdef IP2DEBUG_TRACE
1322 ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1323 #endif
1326 /******************************************************************************/
1327 /* Function: ip2_poll(unsigned long arg) */
1328 /* Parameters: ? */
1329 /* Returns: Nothing */
1330 /* */
1331 /* Description: */
1332 /* This function calls the library routine i2ServiceBoard for each board in */
1333 /* the board table. This is used instead of the interrupt routine when polled */
1334 /* mode is specified. */
1335 /******************************************************************************/
1336 static void
1337 ip2_poll(unsigned long arg)
1339 #ifdef IP2DEBUG_TRACE
1340 ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
1341 #endif
1342 TimerOn = 0; // it's the truth but not checked in service
1344 bh_counter++;
1346 #ifdef USE_IQI
1348 queue_task(&senior_service, &tq_immediate);
1349 mark_bh(IMMEDIATE_BH);
1351 #else
1352 // Just polled boards, service_all might be better
1353 ip2_interrupt(0, NULL, NULL);
1355 #endif /* USE_IQI */
1357 PollTimer.expires = POLL_TIMEOUT;
1358 add_timer( &PollTimer );
1359 TimerOn = 1;
1361 #ifdef IP2DEBUG_TRACE
1362 ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
1363 #endif
1366 static inline void
1367 do_input( i2ChanStrPtr pCh )
1369 unsigned long flags;
1371 #ifdef IP2DEBUG_TRACE
1372 ip2trace(CHANN, ITRC_INPUT, 21, 0 );
1373 #endif
1374 // Data input
1375 if ( pCh->pTTY != NULL ) {
1376 READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
1377 if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
1378 READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
1379 i2Input( pCh );
1380 } else
1381 READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
1382 } else {
1383 #ifdef IP2DEBUG_TRACE
1384 ip2trace(CHANN, ITRC_INPUT, 22, 0 );
1385 #endif
1386 i2InputFlush( pCh );
1390 // code duplicated from n_tty (ldisc)
1391 static inline void
1392 isig(int sig, struct tty_struct *tty, int flush)
1394 if (tty->pgrp > 0)
1395 kill_pg(tty->pgrp, sig, 1);
1396 if (flush || !L_NOFLSH(tty)) {
1397 if ( tty->ldisc.flush_buffer )
1398 tty->ldisc.flush_buffer(tty);
1399 i2InputFlush( tty->driver_data );
1403 static inline void
1404 do_status( i2ChanStrPtr pCh )
1406 int status;
1408 status = i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
1410 #ifdef IP2DEBUG_TRACE
1411 ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
1412 #endif
1414 if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
1415 if ( (status & I2_BRK) ) {
1416 // code duplicated from n_tty (ldisc)
1417 if (I_IGNBRK(pCh->pTTY))
1418 goto skip_this;
1419 if (I_BRKINT(pCh->pTTY)) {
1420 isig(SIGINT, pCh->pTTY, 1);
1421 goto skip_this;
1423 wake_up_interruptible(&pCh->pTTY->read_wait);
1425 #ifdef NEVER_HAPPENS_AS_SETUP_XXX
1426 // and can't work because we don't know the_char
1427 // as the_char is reported on a seperate path
1428 // The intelligent board does this stuff as setup
1430 char brkf = TTY_NORMAL;
1431 unsigned char brkc = '\0';
1432 unsigned char tmp;
1433 if ( (status & I2_BRK) ) {
1434 brkf = TTY_BREAK;
1435 brkc = '\0';
1437 else if (status & I2_PAR) {
1438 brkf = TTY_PARITY;
1439 brkc = the_char;
1440 } else if (status & I2_FRA) {
1441 brkf = TTY_FRAME;
1442 brkc = the_char;
1443 } else if (status & I2_OVR) {
1444 brkf = TTY_OVERRUN;
1445 brkc = the_char;
1447 tmp = pCh->pTTY->real_raw;
1448 pCh->pTTY->real_raw = 0;
1449 pCh->pTTY->ldisc.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
1450 pCh->pTTY->real_raw = tmp;
1452 #endif /* NEVER_HAPPENS_AS_SETUP_XXX */
1454 skip_this:
1456 if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
1457 wake_up_interruptible(&pCh->delta_msr_wait);
1459 if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
1460 if ( status & I2_DCD ) {
1461 if ( pCh->wopen ) {
1462 wake_up_interruptible ( &pCh->open_wait );
1464 } else if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) ) {
1465 if (pCh->pTTY && (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
1466 tty_hangup( pCh->pTTY );
1472 #ifdef IP2DEBUG_TRACE
1473 ip2trace (CHANN, ITRC_STATUS, 26, 0 );
1474 #endif
1477 /******************************************************************************/
1478 /* Device Open/Close/Ioctl Entry Point Section */
1479 /******************************************************************************/
1481 /******************************************************************************/
1482 /* Function: open_sanity_check() */
1483 /* Parameters: Pointer to tty structure */
1484 /* Pointer to file structure */
1485 /* Returns: Success or failure */
1486 /* */
1487 /* Description: */
1488 /* Verifies the structure magic numbers and cross links. */
1489 /******************************************************************************/
1490 #ifdef IP2DEBUG_OPEN
1491 static void
1492 open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
1494 if ( pBrd->i2eValid != I2E_MAGIC ) {
1495 printk(KERN_ERR "IP2: invalid board structure\n" );
1496 } else if ( pBrd != pCh->pMyBord ) {
1497 printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
1498 pCh->pMyBord );
1499 } else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
1500 printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
1501 } else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
1502 } else {
1503 printk(KERN_INFO "IP2: all pointers check out!\n" );
1506 #endif
1509 /******************************************************************************/
1510 /* Function: ip2_open() */
1511 /* Parameters: Pointer to tty structure */
1512 /* Pointer to file structure */
1513 /* Returns: Success or failure */
1514 /* */
1515 /* Description: (MANDATORY) */
1516 /* A successful device open has to run a gauntlet of checks before it */
1517 /* completes. After some sanity checking and pointer setup, the function */
1518 /* blocks until all conditions are satisfied. It then initialises the port to */
1519 /* the default characteristics and returns. */
1520 /******************************************************************************/
1521 static int
1522 ip2_open( PTTY tty, struct file *pFile )
1524 int rc = 0;
1525 int do_clocal = 0;
1526 i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
1528 #ifdef IP2DEBUG_TRACE
1529 ip2trace (MINOR(tty->device), ITRC_OPEN, ITRC_ENTER, 0 );
1530 #endif
1532 if ( pCh == NULL ) {
1533 return -ENODEV;
1535 /* Setup pointer links in device and tty structures */
1536 pCh->pTTY = tty;
1537 tty->driver_data = pCh;
1538 MOD_INC_USE_COUNT;
1540 #ifdef IP2DEBUG_OPEN
1541 printk(KERN_DEBUG \
1542 "IP2:open(tty=%p,pFile=%p):dev=%x,maj=%d,min=%d,ch=%d,idx=%d\n",
1543 tty, pFile, tty->device, MAJOR(tty->device), MINOR(tty->device),
1544 pCh->infl.hd.i2sChannel, pCh->port_index);
1545 open_sanity_check ( pCh, pCh->pMyBord );
1546 #endif
1548 i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
1549 pCh->dataSetOut |= (I2_DTR | I2_RTS);
1550 serviceOutgoingFifo( pCh->pMyBord );
1552 /* Block here until the port is ready (per serial and istallion) */
1554 * 1. If the port is in the middle of closing wait for the completion
1555 * and then return the appropriate error.
1557 if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
1558 if ( pCh->flags & ASYNC_CLOSING ) {
1559 interruptible_sleep_on( &pCh->close_wait);
1561 if ( tty_hung_up_p(pFile) ) {
1562 return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
1566 * 2. If this is a callout device, make sure the normal port is not in
1567 * use, and that someone else doesn't have the callout device locked.
1568 * (These are the only tests the standard serial driver makes for
1569 * callout devices.)
1571 if ( tty->driver.subtype == SERIAL_TYPE_CALLOUT ) {
1572 if ( pCh->flags & ASYNC_NORMAL_ACTIVE ) {
1573 return -EBUSY;
1575 if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) &&
1576 ( pCh->flags & ASYNC_SESSION_LOCKOUT ) &&
1577 ( pCh->session != current->session ) ) {
1578 return -EBUSY;
1580 if ( ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) &&
1581 ( pCh->flags & ASYNC_PGRP_LOCKOUT ) &&
1582 ( pCh->pgrp != current->pgrp ) ) {
1583 return -EBUSY;
1585 pCh->flags |= ASYNC_CALLOUT_ACTIVE;
1586 goto noblock;
1589 * 3. Handle a non-blocking open of a normal port.
1591 if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
1592 if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) {
1593 return -EBUSY;
1595 pCh->flags |= ASYNC_NORMAL_ACTIVE;
1596 goto noblock;
1599 * 4. Now loop waiting for the port to be free and carrier present
1600 * (if required).
1602 if ( pCh->flags & ASYNC_CALLOUT_ACTIVE ) {
1603 if ( pCh->NormalTermios.c_cflag & CLOCAL ) {
1604 do_clocal = 1;
1606 } else {
1607 if ( tty->termios->c_cflag & CLOCAL ) {
1608 do_clocal = 1;
1612 #ifdef IP2DEBUG_OPEN
1613 printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
1614 #endif
1616 ++pCh->wopen;
1617 for(;;) {
1618 if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE)) {
1619 i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
1620 pCh->dataSetOut |= (I2_DTR | I2_RTS);
1621 serviceOutgoingFifo( pCh->pMyBord );
1623 if ( tty_hung_up_p(pFile) ) {
1624 return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
1626 if ( !(pCh->flags & ASYNC_CALLOUT_ACTIVE) &&
1627 !(pCh->flags & ASYNC_CLOSING) &&
1628 (do_clocal || (pCh->dataSetIn & I2_DCD) )) {
1629 rc = 0;
1630 break;
1633 #ifdef IP2DEBUG_OPEN
1634 printk(KERN_DEBUG "ASYNC_CALLOUT_ACTIVE = %s\n",
1635 (pCh->flags & ASYNC_CALLOUT_ACTIVE)?"True":"False");
1636 printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
1637 (pCh->flags & ASYNC_CLOSING)?"True":"False");
1638 printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
1639 #endif
1640 #ifdef IP2DEBUG_TRACE
1641 ip2trace (CHANN, ITRC_OPEN, 3, 2, (pCh->flags & ASYNC_CALLOUT_ACTIVE),
1642 (pCh->flags & ASYNC_CLOSING) );
1643 #endif
1644 /* check for signal */
1645 if (signal_pending(current)) {
1646 rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
1647 break;
1649 interruptible_sleep_on(&pCh->open_wait);
1651 --pCh->wopen; //why count?
1652 #ifdef IP2DEBUG_TRACE
1653 ip2trace (CHANN, ITRC_OPEN, 4, 0 );
1654 #endif
1655 if (rc != 0 ) {
1656 return rc;
1658 pCh->flags |= ASYNC_NORMAL_ACTIVE;
1660 noblock:
1662 /* first open - Assign termios structure to port */
1663 if ( tty->count == 1 ) {
1664 i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1665 if ( pCh->flags & ASYNC_SPLIT_TERMIOS ) {
1666 if ( tty->driver.subtype == SERIAL_TYPE_NORMAL ) {
1667 *tty->termios = pCh->NormalTermios;
1668 } else {
1669 *tty->termios = pCh->CalloutTermios;
1672 /* Now we must send the termios settings to the loadware */
1673 set_params( pCh, NULL );
1676 /* override previous and never reset ??? */
1677 pCh->session = current->session;
1678 pCh->pgrp = current->pgrp;
1681 * Now set any i2lib options. These may go away if the i2lib code ends
1682 * up rolled into the mainline.
1684 pCh->channelOptions |= CO_NBLOCK_WRITE;
1686 #ifdef IP2DEBUG_OPEN
1687 printk (KERN_DEBUG "IP2: open completed\n" );
1688 #endif
1689 serviceOutgoingFifo( pCh->pMyBord );
1691 #ifdef IP2DEBUG_TRACE
1692 ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
1693 #endif
1694 return 0;
1697 /******************************************************************************/
1698 /* Function: ip2_close() */
1699 /* Parameters: Pointer to tty structure */
1700 /* Pointer to file structure */
1701 /* Returns: Nothing */
1702 /* */
1703 /* Description: */
1704 /* */
1705 /* */
1706 /******************************************************************************/
1707 static void
1708 ip2_close( PTTY tty, struct file *pFile )
1710 i2ChanStrPtr pCh = tty->driver_data;
1712 if ( !pCh ) {
1713 return;
1716 #ifdef IP2DEBUG_TRACE
1717 ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
1718 #endif
1720 #ifdef IP2DEBUG_OPEN
1721 printk(KERN_DEBUG "IP2:close ttyF%02X:\n",MINOR(tty->device));
1722 #endif
1724 if ( tty_hung_up_p ( pFile ) ) {
1725 MOD_DEC_USE_COUNT;
1727 #ifdef IP2DEBUG_TRACE
1728 ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
1729 #endif
1730 return;
1732 if ( tty->count > 1 ) { /* not the last close */
1733 MOD_DEC_USE_COUNT;
1734 #ifdef IP2DEBUG_TRACE
1735 ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
1736 #endif
1737 return;
1739 pCh->flags |= ASYNC_CLOSING; // last close actually
1742 * Save the termios structure, since this port may have separate termios
1743 * for callout and dialin.
1745 if (pCh->flags & ASYNC_NORMAL_ACTIVE)
1746 pCh->NormalTermios = *tty->termios;
1747 if (pCh->flags & ASYNC_CALLOUT_ACTIVE)
1748 pCh->CalloutTermios = *tty->termios;
1750 tty->closing = 1;
1752 if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
1754 * Before we drop DTR, make sure the transmitter has completely drained.
1755 * This uses an timeout, after which the close
1756 * completes.
1758 ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
1761 * At this point we stop accepting input. Here we flush the channel
1762 * input buffer which will allow the board to send up more data. Any
1763 * additional input is tossed at interrupt/poll time.
1765 i2InputFlush( pCh );
1767 /* disable DSS reporting */
1768 i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
1769 CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1770 if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
1771 i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
1772 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1773 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1776 serviceOutgoingFifo ( pCh->pMyBord );
1778 if ( tty->driver.flush_buffer )
1779 tty->driver.flush_buffer(tty);
1780 if ( tty->ldisc.flush_buffer )
1781 tty->ldisc.flush_buffer(tty);
1782 tty->closing = 0;
1784 pCh->pTTY = NULL;
1786 if (pCh->wopen) {
1787 if (pCh->ClosingDelay) {
1788 current->state = TASK_INTERRUPTIBLE;
1789 schedule_timeout(pCh->ClosingDelay);
1791 wake_up_interruptible(&pCh->open_wait);
1794 pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING);
1795 wake_up_interruptible(&pCh->close_wait);
1797 #ifdef IP2DEBUG_OPEN
1798 DBG_CNT("ip2_close: after wakeups--");
1799 #endif
1801 MOD_DEC_USE_COUNT;
1803 #ifdef IP2DEBUG_TRACE
1804 ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
1805 #endif
1806 return;
1809 /******************************************************************************/
1810 /* Function: ip2_hangup() */
1811 /* Parameters: Pointer to tty structure */
1812 /* Returns: Nothing */
1813 /* */
1814 /* Description: */
1815 /* */
1816 /* */
1817 /******************************************************************************/
1818 static void
1819 ip2_hangup ( PTTY tty )
1821 i2ChanStrPtr pCh = tty->driver_data;
1823 #ifdef IP2DEBUG_TRACE
1824 ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
1825 #endif
1827 ip2_flush_buffer(tty);
1829 /* disable DSS reporting */
1831 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
1832 i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
1833 if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
1834 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
1835 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
1836 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
1838 i2QueueCommands(PTYPE_INLINE, pCh, 1, 3,
1839 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
1840 serviceOutgoingFifo ( pCh->pMyBord );
1842 wake_up_interruptible ( &pCh->delta_msr_wait );
1844 pCh->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1845 pCh->pTTY = NULL;
1846 wake_up_interruptible ( &pCh->open_wait );
1848 #ifdef IP2DEBUG_TRACE
1849 ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
1850 #endif
1853 /******************************************************************************/
1854 /******************************************************************************/
1855 /* Device Output Section */
1856 /******************************************************************************/
1857 /******************************************************************************/
1859 /******************************************************************************/
1860 /* Function: ip2_write() */
1861 /* Parameters: Pointer to tty structure */
1862 /* Flag denoting data is in user (1) or kernel (0) space */
1863 /* Pointer to data */
1864 /* Number of bytes to write */
1865 /* Returns: Number of bytes actually written */
1866 /* */
1867 /* Description: (MANDATORY) */
1868 /* */
1869 /* */
1870 /******************************************************************************/
1871 static int
1872 ip2_write( PTTY tty, int user, const unsigned char *pData, int count)
1874 i2ChanStrPtr pCh = tty->driver_data;
1875 int bytesSent = 0;
1876 unsigned long flags;
1878 #ifdef IP2DEBUG_TRACE
1879 ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
1880 #endif
1882 /* Flush out any buffered data left over from ip2_putchar() calls. */
1883 ip2_flush_chars( tty );
1885 /* This is the actual move bit. Make sure it does what we need!!!!! */
1886 WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1887 bytesSent = i2Output( pCh, pData, count, user );
1888 WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1890 #ifdef IP2DEBUG_TRACE
1891 ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
1892 #endif
1893 return bytesSent > 0 ? bytesSent : 0;
1896 /******************************************************************************/
1897 /* Function: ip2_putchar() */
1898 /* Parameters: Pointer to tty structure */
1899 /* Character to write */
1900 /* Returns: Nothing */
1901 /* */
1902 /* Description: */
1903 /* */
1904 /* */
1905 /******************************************************************************/
1906 static void
1907 ip2_putchar( PTTY tty, unsigned char ch )
1909 i2ChanStrPtr pCh = tty->driver_data;
1910 unsigned long flags;
1912 #ifdef IP2DEBUG_TRACE
1913 // ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
1914 #endif
1916 WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1917 pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
1918 if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
1919 WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1920 ip2_flush_chars( tty );
1921 } else
1922 WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1924 #ifdef IP2DEBUG_TRACE
1925 // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
1926 #endif
1929 /******************************************************************************/
1930 /* Function: ip2_flush_chars() */
1931 /* Parameters: Pointer to tty structure */
1932 /* Returns: Nothing */
1933 /* */
1934 /* Description: */
1935 /* */
1936 /******************************************************************************/
1937 static void
1938 ip2_flush_chars( PTTY tty )
1940 int strip;
1941 i2ChanStrPtr pCh = tty->driver_data;
1942 unsigned long flags;
1944 WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1945 if ( pCh->Pbuf_stuff ) {
1946 #ifdef IP2DEBUG_TRACE
1947 // ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
1948 #endif
1950 // We may need to restart i2Output if it does not fullfill this request
1952 strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff, 0 );
1953 if ( strip != pCh->Pbuf_stuff ) {
1954 memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
1956 pCh->Pbuf_stuff -= strip;
1958 WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1961 /******************************************************************************/
1962 /* Function: ip2_write_room() */
1963 /* Parameters: Pointer to tty structure */
1964 /* Returns: Number of bytes that the driver can accept */
1965 /* */
1966 /* Description: */
1967 /* */
1968 /******************************************************************************/
1969 static int
1970 ip2_write_room ( PTTY tty )
1972 int bytesFree;
1973 i2ChanStrPtr pCh = tty->driver_data;
1974 unsigned long flags;
1976 READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
1977 bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
1978 READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
1980 #ifdef IP2DEBUG_TRACE
1981 ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
1982 #endif
1984 return ((bytesFree > 0) ? bytesFree : 0);
1987 /******************************************************************************/
1988 /* Function: ip2_chars_in_buf() */
1989 /* Parameters: Pointer to tty structure */
1990 /* Returns: Number of bytes queued for transmission */
1991 /* */
1992 /* Description: */
1993 /* */
1994 /* */
1995 /******************************************************************************/
1996 static int
1997 ip2_chars_in_buf ( PTTY tty )
1999 i2ChanStrPtr pCh = tty->driver_data;
2000 int rc;
2001 unsigned long flags;
2002 #ifdef IP2DEBUG_TRACE
2003 ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
2004 #endif
2005 #ifdef IP2DEBUG_WRITE
2006 printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
2007 pCh->Obuf_char_count + pCh->Pbuf_stuff,
2008 pCh->Obuf_char_count, pCh->Pbuf_stuff );
2009 #endif
2010 READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
2011 rc = pCh->Obuf_char_count;
2012 READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
2013 READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
2014 rc += pCh->Pbuf_stuff;
2015 READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
2016 return rc;
2019 /******************************************************************************/
2020 /* Function: ip2_flush_buffer() */
2021 /* Parameters: Pointer to tty structure */
2022 /* Returns: Nothing */
2023 /* */
2024 /* Description: */
2025 /* */
2026 /* */
2027 /******************************************************************************/
2028 static void
2029 ip2_flush_buffer( PTTY tty )
2031 i2ChanStrPtr pCh = tty->driver_data;
2032 unsigned long flags;
2034 #ifdef IP2DEBUG_TRACE
2035 ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
2036 #endif
2037 #ifdef IP2DEBUG_WRITE
2038 printk (KERN_DEBUG "IP2: flush buffer\n" );
2039 #endif
2040 WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
2041 pCh->Pbuf_stuff = 0;
2042 WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
2043 i2FlushOutput( pCh );
2044 ip2_owake(tty);
2045 #ifdef IP2DEBUG_TRACE
2046 ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
2047 #endif
2050 /******************************************************************************/
2051 /* Function: ip2_wait_until_sent() */
2052 /* Parameters: Pointer to tty structure */
2053 /* Timeout for wait. */
2054 /* Returns: Nothing */
2055 /* */
2056 /* Description: */
2057 /* This function is used in place of the normal tty_wait_until_sent, which */
2058 /* only waits for the driver buffers to be empty (or rather, those buffers */
2059 /* reported by chars_in_buffer) which doesn't work for IP2 due to the */
2060 /* indeterminate number of bytes buffered on the board. */
2061 /******************************************************************************/
2062 static void
2063 ip2_wait_until_sent ( PTTY tty, int timeout )
2065 int i = jiffies;
2066 i2ChanStrPtr pCh = tty->driver_data;
2068 tty_wait_until_sent(tty, timeout );
2069 if ( (i = timeout - (jiffies -i)) > 0)
2070 i2DrainOutput( pCh, i );
2073 /******************************************************************************/
2074 /******************************************************************************/
2075 /* Device Input Section */
2076 /******************************************************************************/
2077 /******************************************************************************/
2079 /******************************************************************************/
2080 /* Function: ip2_throttle() */
2081 /* Parameters: Pointer to tty structure */
2082 /* Returns: Nothing */
2083 /* */
2084 /* Description: */
2085 /* */
2086 /* */
2087 /******************************************************************************/
2088 static void
2089 ip2_throttle ( PTTY tty )
2091 i2ChanStrPtr pCh = tty->driver_data;
2093 #ifdef IP2DEBUG_READ
2094 printk (KERN_DEBUG "IP2: throttle\n" );
2095 #endif
2097 * Signal the poll/interrupt handlers not to forward incoming data to
2098 * the line discipline. This will cause the buffers to fill up in the
2099 * library and thus cause the library routines to send the flow control
2100 * stuff.
2102 pCh->throttled = 1;
2105 /******************************************************************************/
2106 /* Function: ip2_unthrottle() */
2107 /* Parameters: Pointer to tty structure */
2108 /* Returns: Nothing */
2109 /* */
2110 /* Description: */
2111 /* */
2112 /* */
2113 /******************************************************************************/
2114 static void
2115 ip2_unthrottle ( PTTY tty )
2117 i2ChanStrPtr pCh = tty->driver_data;
2118 unsigned long flags;
2120 #ifdef IP2DEBUG_READ
2121 printk (KERN_DEBUG "IP2: unthrottle\n" );
2122 #endif
2124 /* Pass incoming data up to the line discipline again. */
2125 pCh->throttled = 0;
2126 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2127 serviceOutgoingFifo( pCh->pMyBord );
2128 READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
2129 if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
2130 READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
2131 #ifdef IP2DEBUG_READ
2132 printk (KERN_DEBUG "i2Input called from unthrottle\n" );
2133 #endif
2134 i2Input( pCh );
2135 } else
2136 READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
2139 static void
2140 ip2_start ( PTTY tty )
2142 i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
2144 i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
2145 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
2146 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
2147 #ifdef IP2DEBUG_WRITE
2148 printk (KERN_DEBUG "IP2: start tx\n" );
2149 #endif
2152 static void
2153 ip2_stop ( PTTY tty )
2155 i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
2157 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
2158 #ifdef IP2DEBUG_WRITE
2159 printk (KERN_DEBUG "IP2: stop tx\n" );
2160 #endif
2163 /******************************************************************************/
2164 /* Device Ioctl Section */
2165 /******************************************************************************/
2167 /******************************************************************************/
2168 /* Function: ip2_ioctl() */
2169 /* Parameters: Pointer to tty structure */
2170 /* Pointer to file structure */
2171 /* Command */
2172 /* Argument */
2173 /* Returns: Success or failure */
2174 /* */
2175 /* Description: */
2176 /* */
2177 /* */
2178 /******************************************************************************/
2179 static int
2180 ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2182 i2ChanStrPtr pCh = DevTable[MINOR(tty->device)];
2183 struct async_icount cprev, cnow; /* kernel counter temps */
2184 struct serial_icounter_struct *p_cuser; /* user space */
2185 int rc = 0;
2186 unsigned long flags;
2188 if ( pCh == NULL ) {
2189 return -ENODEV;
2192 #ifdef IP2DEBUG_TRACE
2193 ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
2194 #endif
2196 #ifdef IP2DEBUG_IOCTL
2197 printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
2198 #endif
2200 switch(cmd) {
2201 case TIOCGSERIAL:
2202 #ifdef IP2DEBUG_TRACE
2203 ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
2204 #endif
2205 rc = get_serial_info(pCh, (struct serial_struct *) arg);
2206 if (rc)
2207 return rc;
2208 break;
2210 case TIOCSSERIAL:
2211 #ifdef IP2DEBUG_TRACE
2212 ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
2213 #endif
2214 rc = set_serial_info(pCh, (struct serial_struct *) arg);
2215 if (rc)
2216 return rc;
2217 break;
2219 case TCXONC:
2220 rc = tty_check_change(tty);
2221 if (rc)
2222 return rc;
2223 switch (arg) {
2224 case TCOOFF:
2225 //return -ENOIOCTLCMD;
2226 break;
2227 case TCOON:
2228 //return -ENOIOCTLCMD;
2229 break;
2230 case TCIOFF:
2231 if (STOP_CHAR(tty) != __DISABLED_CHAR) {
2232 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2233 CMD_XMIT_NOW(STOP_CHAR(tty)));
2235 break;
2236 case TCION:
2237 if (START_CHAR(tty) != __DISABLED_CHAR) {
2238 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
2239 CMD_XMIT_NOW(START_CHAR(tty)));
2241 break;
2242 default:
2243 return -EINVAL;
2245 return 0;
2247 case TCSBRK: /* SVID version: non-zero arg --> no break */
2248 rc = tty_check_change(tty);
2249 #ifdef IP2DEBUG_TRACE
2250 ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
2251 #endif
2252 if (!rc) {
2253 ip2_wait_until_sent(tty,0);
2254 if (!arg) {
2255 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
2256 serviceOutgoingFifo( pCh->pMyBord );
2259 break;
2261 case TCSBRKP: /* support for POSIX tcsendbreak() */
2262 rc = tty_check_change(tty);
2263 #ifdef IP2DEBUG_TRACE
2264 ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
2265 #endif
2266 if (!rc) {
2267 ip2_wait_until_sent(tty,0);
2268 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2269 CMD_SEND_BRK(arg ? arg*100 : 250));
2270 serviceOutgoingFifo ( pCh->pMyBord );
2272 break;
2274 case TIOCGSOFTCAR:
2275 #ifdef IP2DEBUG_TRACE
2276 ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
2277 #endif
2278 PUT_USER(rc,C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
2279 if (rc)
2280 return rc;
2281 break;
2283 case TIOCSSOFTCAR:
2284 #ifdef IP2DEBUG_TRACE
2285 ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
2286 #endif
2287 GET_USER(rc,arg,(unsigned long *) arg);
2288 if (rc)
2289 return rc;
2290 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
2291 | (arg ? CLOCAL : 0));
2293 break;
2295 case TIOCMGET:
2296 #ifdef IP2DEBUG_TRACE
2297 ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc );
2298 #endif
2300 FIXME - the following code is causing a NULL pointer dereference in
2301 2.3.51 in an interrupt handler. It's suppose to prompt the board
2302 to return the DSS signal status immediately. Why doesn't it do
2303 the same thing in 2.2.14?
2306 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
2307 serviceOutgoingFifo( pCh->pMyBord );
2308 interruptible_sleep_on(&pCh->dss_now_wait);
2309 if (signal_pending(current)) {
2310 return -EINTR;
2313 PUT_USER(rc,
2314 ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
2315 | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
2316 | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0)
2317 | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0)
2318 | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0)
2319 | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0),
2320 (unsigned int *) arg);
2321 break;
2323 case TIOCMBIS:
2324 case TIOCMBIC:
2325 case TIOCMSET:
2326 #ifdef IP2DEBUG_TRACE
2327 ip2trace (CHANN, ITRC_IOCTL, 9, 0 );
2328 #endif
2329 rc = set_modem_info(pCh, cmd, (unsigned int *) arg);
2330 break;
2333 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
2334 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
2335 * for masking). Caller should use TIOCGICOUNT to see which one it was
2337 case TIOCMIWAIT:
2338 save_flags(flags);cli();
2339 cprev = pCh->icount; /* note the counters on entry */
2340 restore_flags(flags);
2341 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4,
2342 CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
2343 serviceOutgoingFifo( pCh->pMyBord );
2344 for(;;) {
2345 #ifdef IP2DEBUG_TRACE
2346 ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
2347 #endif
2348 interruptible_sleep_on(&pCh->delta_msr_wait);
2349 #ifdef IP2DEBUG_TRACE
2350 ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
2351 #endif
2352 /* see if a signal did it */
2353 if (signal_pending(current)) {
2354 rc = -ERESTARTSYS;
2355 break;
2357 save_flags(flags);cli();
2358 cnow = pCh->icount; /* atomic copy */
2359 restore_flags(flags);
2360 if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
2361 cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
2362 rc = -EIO; /* no change => rc */
2363 break;
2365 if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
2366 ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
2367 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
2368 ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
2369 rc = 0;
2370 break;
2372 cprev = cnow;
2374 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3,
2375 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
2376 if ( ! (pCh->flags & ASYNC_CHECK_CD)) {
2377 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
2379 serviceOutgoingFifo( pCh->pMyBord );
2380 return rc;
2381 break;
2384 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2385 * Return: write counters to the user passed counter struct
2386 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2387 * only 0->1 is counted. The controller is quite capable of counting
2388 * both, but this done to preserve compatibility with the standard
2389 * serial driver.
2391 case TIOCGICOUNT:
2392 #ifdef IP2DEBUG_TRACE
2393 ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
2394 #endif
2395 save_flags(flags);cli();
2396 cnow = pCh->icount;
2397 restore_flags(flags);
2398 p_cuser = (struct serial_icounter_struct *) arg;
2399 PUT_USER(rc,cnow.cts, &p_cuser->cts);
2400 PUT_USER(rc,cnow.dsr, &p_cuser->dsr);
2401 PUT_USER(rc,cnow.rng, &p_cuser->rng);
2402 PUT_USER(rc,cnow.dcd, &p_cuser->dcd);
2403 PUT_USER(rc,cnow.rx, &p_cuser->rx);
2404 PUT_USER(rc,cnow.tx, &p_cuser->tx);
2405 PUT_USER(rc,cnow.frame, &p_cuser->frame);
2406 PUT_USER(rc,cnow.overrun, &p_cuser->overrun);
2407 PUT_USER(rc,cnow.parity, &p_cuser->parity);
2408 PUT_USER(rc,cnow.brk, &p_cuser->brk);
2409 PUT_USER(rc,cnow.buf_overrun, &p_cuser->buf_overrun);
2410 break;
2413 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2414 * will be passed to the line discipline for it to handle.
2416 case TIOCSERCONFIG:
2417 case TIOCSERGWILD:
2418 case TIOCSERGETLSR:
2419 case TIOCSERSWILD:
2420 case TIOCSERGSTRUCT:
2421 case TIOCSERGETMULTI:
2422 case TIOCSERSETMULTI:
2424 default:
2425 #ifdef IP2DEBUG_TRACE
2426 ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
2427 #endif
2428 rc = -ENOIOCTLCMD;
2429 break;
2431 #ifdef IP2DEBUG_TRACE
2432 ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
2433 #endif
2434 return rc;
2437 /******************************************************************************/
2438 /* Function: set_modem_info() */
2439 /* Parameters: Pointer to channel structure */
2440 /* Specific ioctl command */
2441 /* Pointer to source for new settings */
2442 /* Returns: Nothing */
2443 /* */
2444 /* Description: */
2445 /* This returns the current settings of the dataset signal inputs to the user */
2446 /* program. */
2447 /******************************************************************************/
2448 static int
2449 set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value)
2451 int rc;
2452 unsigned int arg;
2454 GET_USER(rc,arg,value);
2455 if (rc)
2456 return rc;
2457 switch(cmd) {
2458 case TIOCMBIS:
2459 if (arg & TIOCM_RTS) {
2460 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2461 pCh->dataSetOut |= I2_RTS;
2463 if (arg & TIOCM_DTR) {
2464 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2465 pCh->dataSetOut |= I2_DTR;
2467 break;
2468 case TIOCMBIC:
2469 if (arg & TIOCM_RTS) {
2470 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2471 pCh->dataSetOut &= ~I2_RTS;
2473 if (arg & TIOCM_DTR) {
2474 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2475 pCh->dataSetOut &= ~I2_DTR;
2477 break;
2478 case TIOCMSET:
2479 if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) {
2480 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
2481 pCh->dataSetOut |= I2_RTS;
2482 } else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) {
2483 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
2484 pCh->dataSetOut &= ~I2_RTS;
2486 if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) {
2487 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
2488 pCh->dataSetOut |= I2_DTR;
2489 } else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) {
2490 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
2491 pCh->dataSetOut &= ~I2_DTR;
2493 break;
2494 default:
2495 return -EINVAL;
2497 serviceOutgoingFifo( pCh->pMyBord );
2498 return 0;
2501 /******************************************************************************/
2502 /* Function: GetSerialInfo() */
2503 /* Parameters: Pointer to channel structure */
2504 /* Pointer to old termios structure */
2505 /* Returns: Nothing */
2506 /* */
2507 /* Description: */
2508 /* This is to support the setserial command, and requires processing of the */
2509 /* standard Linux serial structure. */
2510 /******************************************************************************/
2511 static int
2512 get_serial_info ( i2ChanStrPtr pCh, struct serial_struct *retinfo )
2514 struct serial_struct tmp;
2515 int rc;
2517 if ( !retinfo ) {
2518 return -EFAULT;
2521 memset ( &tmp, 0, sizeof(tmp) );
2522 tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
2523 if (BID_HAS_654(tmp.type)) {
2524 tmp.type = PORT_16650;
2525 } else {
2526 tmp.type = PORT_CIRRUS;
2528 tmp.line = pCh->port_index;
2529 tmp.port = pCh->pMyBord->i2eBase;
2530 tmp.irq = ip2config.irq[pCh->port_index/64];
2531 tmp.flags = pCh->flags;
2532 tmp.baud_base = pCh->BaudBase;
2533 tmp.close_delay = pCh->ClosingDelay;
2534 tmp.closing_wait = pCh->ClosingWaitTime;
2535 tmp.custom_divisor = pCh->BaudDivisor;
2536 COPY_TO_USER(rc,retinfo,&tmp,sizeof(*retinfo));
2537 return rc;
2540 /******************************************************************************/
2541 /* Function: SetSerialInfo() */
2542 /* Parameters: Pointer to channel structure */
2543 /* Pointer to old termios structure */
2544 /* Returns: Nothing */
2545 /* */
2546 /* Description: */
2547 /* This function provides support for setserial, which uses the TIOCSSERIAL */
2548 /* ioctl. Not all setserial parameters are relevant. If the user attempts to */
2549 /* change the IRQ, address or type of the port the ioctl fails. */
2550 /******************************************************************************/
2551 static int
2552 set_serial_info( i2ChanStrPtr pCh, struct serial_struct *new_info )
2554 struct serial_struct ns;
2555 int old_flags, old_baud_divisor;
2556 int rc = 0;
2558 if ( !new_info ) {
2559 return -EFAULT;
2561 COPY_FROM_USER(rc, &ns, new_info, sizeof (ns) );
2562 if (rc) {
2563 return rc;
2566 * We don't allow setserial to change IRQ, board address, type or baud
2567 * base. Also line nunber as such is meaningless but we use it for our
2568 * array index so it is fixed also.
2570 if ( (ns.irq != ip2config.irq[pCh->port_index])
2571 || ((int) ns.port != ((int) (pCh->pMyBord->i2eBase)))
2572 || (ns.baud_base != pCh->BaudBase)
2573 || (ns.line != pCh->port_index) ) {
2574 return -EINVAL;
2577 old_flags = pCh->flags;
2578 old_baud_divisor = pCh->BaudDivisor;
2580 if ( !suser() ) {
2581 if ( ( ns.close_delay != pCh->ClosingDelay ) ||
2582 ( (ns.flags & ~ASYNC_USR_MASK) !=
2583 (pCh->flags & ~ASYNC_USR_MASK) ) ) {
2584 return -EPERM;
2587 pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
2588 (ns.flags & ASYNC_USR_MASK);
2589 pCh->BaudDivisor = ns.custom_divisor;
2590 } else {
2591 pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
2592 (ns.flags & ASYNC_FLAGS);
2593 pCh->BaudDivisor = ns.custom_divisor;
2594 pCh->ClosingDelay = ns.close_delay * HZ/100;
2595 pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
2598 if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
2599 || (old_baud_divisor != pCh->BaudDivisor) ) {
2600 // Invalidate speed and reset parameters
2601 set_params( pCh, NULL );
2604 return rc;
2607 /******************************************************************************/
2608 /* Function: ip2_set_termios() */
2609 /* Parameters: Pointer to tty structure */
2610 /* Pointer to old termios structure */
2611 /* Returns: Nothing */
2612 /* */
2613 /* Description: */
2614 /* */
2615 /* */
2616 /******************************************************************************/
2617 static void
2618 ip2_set_termios( PTTY tty, struct termios *old_termios )
2620 i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
2622 #ifdef IP2DEBUG_IOCTL
2623 printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
2624 #endif
2626 set_params( pCh, old_termios );
2629 /******************************************************************************/
2630 /* Function: ip2_set_line_discipline() */
2631 /* Parameters: Pointer to tty structure */
2632 /* Returns: Nothing */
2633 /* */
2634 /* Description: Does nothing */
2635 /* */
2636 /* */
2637 /******************************************************************************/
2638 static void
2639 ip2_set_line_discipline ( PTTY tty )
2641 #ifdef IP2DEBUG_IOCTL
2642 printk (KERN_DEBUG "IP2: set line discipline\n" );
2643 #endif
2644 #ifdef IP2DEBUG_TRACE
2645 ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
2646 #endif
2649 /******************************************************************************/
2650 /* Function: SetLine Characteristics() */
2651 /* Parameters: Pointer to channel structure */
2652 /* Returns: Nothing */
2653 /* */
2654 /* Description: */
2655 /* This routine is called to update the channel structure with the new line */
2656 /* characteristics, and send the appropriate commands to the board when they */
2657 /* change. */
2658 /******************************************************************************/
2659 static void
2660 set_params( i2ChanStrPtr pCh, struct termios *o_tios )
2662 tcflag_t cflag, iflag, lflag;
2663 char stop_char, start_char;
2664 struct termios dummy;
2666 lflag = pCh->pTTY->termios->c_lflag;
2667 cflag = pCh->pTTY->termios->c_cflag;
2668 iflag = pCh->pTTY->termios->c_iflag;
2670 if (o_tios == NULL) {
2671 dummy.c_lflag = ~lflag;
2672 dummy.c_cflag = ~cflag;
2673 dummy.c_iflag = ~iflag;
2674 o_tios = &dummy;
2678 switch ( cflag & CBAUD ) {
2679 case B0:
2680 i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
2681 pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
2682 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
2683 pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
2684 goto service_it;
2685 break;
2686 case B38400:
2688 * This is the speed that is overloaded with all the other high
2689 * speeds, depending upon the flag settings.
2691 if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
2692 pCh->speed = CBR_57600;
2693 } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
2694 pCh->speed = CBR_115200;
2695 } else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
2696 pCh->speed = CBR_C1;
2697 } else {
2698 pCh->speed = CBR_38400;
2700 break;
2701 case B50: pCh->speed = CBR_50; break;
2702 case B75: pCh->speed = CBR_75; break;
2703 case B110: pCh->speed = CBR_110; break;
2704 case B134: pCh->speed = CBR_134; break;
2705 case B150: pCh->speed = CBR_150; break;
2706 case B200: pCh->speed = CBR_200; break;
2707 case B300: pCh->speed = CBR_300; break;
2708 case B600: pCh->speed = CBR_600; break;
2709 case B1200: pCh->speed = CBR_1200; break;
2710 case B1800: pCh->speed = CBR_1800; break;
2711 case B2400: pCh->speed = CBR_2400; break;
2712 case B4800: pCh->speed = CBR_4800; break;
2713 case B9600: pCh->speed = CBR_9600; break;
2714 case B19200: pCh->speed = CBR_19200; break;
2715 case B57600: pCh->speed = CBR_57600; break;
2716 case B115200: pCh->speed = CBR_115200; break;
2717 case B153600: pCh->speed = CBR_153600; break;
2718 case B230400: pCh->speed = CBR_230400; break;
2719 case B307200: pCh->speed = CBR_307200; break;
2720 case B460800: pCh->speed = CBR_460800; break;
2721 case B921600: pCh->speed = CBR_921600; break;
2722 default: pCh->speed = CBR_9600; break;
2724 if ( pCh->speed == CBR_C1 ) {
2725 // Process the custom speed parameters.
2726 int bps = pCh->BaudBase / pCh->BaudDivisor;
2727 if ( bps == 921600 ) {
2728 pCh->speed = CBR_921600;
2729 } else {
2730 bps = bps/10;
2731 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
2734 i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
2736 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
2737 pCh->dataSetOut |= (I2_DTR | I2_RTS);
2739 if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag))
2741 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2742 CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
2744 if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag))
2746 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
2747 CMD_SETPAR(
2748 (cflag & PARENB ? (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
2752 /* byte size and parity */
2753 if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag))
2755 int datasize;
2756 switch ( cflag & CSIZE ) {
2757 case CS5: datasize = CSZ_5; break;
2758 case CS6: datasize = CSZ_6; break;
2759 case CS7: datasize = CSZ_7; break;
2760 case CS8: datasize = CSZ_8; break;
2761 default: datasize = CSZ_5; break; /* as per serial.c */
2763 i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
2765 /* Process CTS flow control flag setting */
2766 if ( (cflag & CRTSCTS) ) {
2767 i2QueueCommands(PTYPE_INLINE, pCh, 100,
2768 2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
2769 } else {
2770 i2QueueCommands(PTYPE_INLINE, pCh, 100,
2771 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
2774 // Process XON/XOFF flow control flags settings
2776 stop_char = STOP_CHAR(pCh->pTTY);
2777 start_char = START_CHAR(pCh->pTTY);
2779 //////////// can't be \000
2780 if (stop_char == __DISABLED_CHAR )
2782 stop_char = ~__DISABLED_CHAR;
2784 if (start_char == __DISABLED_CHAR )
2786 start_char = ~__DISABLED_CHAR;
2788 /////////////////////////////////
2790 if ( o_tios->c_cc[VSTART] != start_char )
2792 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
2793 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
2795 if ( o_tios->c_cc[VSTOP] != stop_char )
2797 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
2798 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
2800 if (stop_char == __DISABLED_CHAR )
2802 stop_char = ~__DISABLED_CHAR; //TEST123
2803 goto no_xoff;
2805 if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF)))
2807 if ( iflag & IXOFF ) { // Enable XOFF output flow control
2808 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
2809 } else { // Disable XOFF output flow control
2810 no_xoff:
2811 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
2814 if (start_char == __DISABLED_CHAR )
2816 goto no_xon;
2818 if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY)))
2820 if ( iflag & IXON ) {
2821 if ( iflag & IXANY ) { // Enable XON/XANY output flow control
2822 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
2823 } else { // Enable XON output flow control
2824 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
2826 } else { // Disable XON output flow control
2827 no_xon:
2828 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
2831 if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) )
2833 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2834 CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
2836 if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) )
2838 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
2839 CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
2842 if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR))
2843 ^ ( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) )
2845 char brkrpt = 0;
2846 char parrpt = 0;
2848 if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
2849 /* Ignore breaks altogether */
2850 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
2851 } else {
2852 if ( iflag & BRKINT ) {
2853 if ( iflag & PARMRK ) {
2854 brkrpt = 0x0a; // exception an inline triple
2855 } else {
2856 brkrpt = 0x1a; // exception and NULL
2858 brkrpt |= 0x04; // flush input
2859 } else {
2860 if ( iflag & PARMRK ) {
2861 brkrpt = 0x0b; //POSIX triple \0377 \0 \0
2862 } else {
2863 brkrpt = 0x01; // Null only
2866 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
2869 if (iflag & IGNPAR) {
2870 parrpt = 0x20;
2871 /* would be 2 for not cirrus bug */
2872 /* would be 0x20 cept for cirrus bug */
2873 } else {
2874 if ( iflag & PARMRK ) {
2876 * Replace error characters with 3-byte sequence (\0377,\0,char)
2878 parrpt = 0x04 ;
2879 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
2880 } else {
2881 parrpt = 0x03;
2884 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
2886 if (cflag & CLOCAL) {
2887 // Status reporting fails for DCD if this is off
2888 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
2889 pCh->flags &= ~ASYNC_CHECK_CD;
2890 } else {
2891 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
2892 pCh->flags |= ASYNC_CHECK_CD;
2895 #ifdef XXX
2896 do_flags_thing: // This is a test, we don't do the flags thing
2898 if ( (cflag & CRTSCTS) ) {
2899 cflag |= 014000000000;
2901 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1,
2902 CMD_UNIX_FLAGS(iflag,cflag,lflag));
2903 #endif
2905 service_it:
2906 i2DrainOutput( pCh, 100 );
2909 /******************************************************************************/
2910 /* IPL Device Section */
2911 /******************************************************************************/
2913 /******************************************************************************/
2914 /* Function: ip2_ipl_read() */
2915 /* Parameters: Pointer to device inode */
2916 /* Pointer to file structure */
2917 /* Pointer to data */
2918 /* Number of bytes to read */
2919 /* Returns: Success or failure */
2920 /* */
2921 /* Description: Ugly */
2922 /* */
2923 /* */
2924 /******************************************************************************/
2926 static
2927 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
2929 ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off )
2930 unsigned int minor = MINOR( pInode->i_rdev );
2931 #else
2932 ssize_t
2933 ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off )
2935 unsigned int minor = MINOR( pFile->f_dentry->d_inode->i_rdev );
2936 #endif
2937 int rc = 0;
2939 #ifdef IP2DEBUG_IPL
2940 printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
2941 #endif
2943 switch( minor ) {
2944 case 0: // IPL device
2945 rc = -EINVAL;
2946 break;
2947 case 1: // Status dump
2948 rc = -EINVAL;
2949 break;
2950 case 2: // Ping device
2951 rc = -EINVAL;
2952 break;
2953 case 3: // Trace device
2954 rc = DumpTraceBuffer ( pData, count );
2955 break;
2956 case 4: // Trace device
2957 rc = DumpFifoBuffer ( pData, count );
2958 break;
2959 default:
2960 rc = -ENODEV;
2961 break;
2963 return rc;
2966 static int
2967 DumpFifoBuffer ( char *pData, int count )
2969 #ifdef DEBUG_FIFO
2970 int rc;
2971 COPY_TO_USER(rc, pData, DBGBuf, count);
2973 printk(KERN_DEBUG "Last index %d\n", I );
2975 return count;
2976 #endif /* DEBUG_FIFO */
2977 return 0;
2980 static int
2981 DumpTraceBuffer ( char *pData, int count )
2983 #ifdef IP2DEBUG_TRACE
2984 int rc;
2985 int dumpcount;
2986 int chunk;
2987 int *pIndex = (int*)pData;
2989 if ( count < (sizeof(int) * 6) ) {
2990 return -EIO;
2992 PUT_USER(rc, tracewrap, pIndex );
2993 PUT_USER(rc, TRACEMAX, ++pIndex );
2994 PUT_USER(rc, tracestrip, ++pIndex );
2995 PUT_USER(rc, tracestuff, ++pIndex );
2996 pData += sizeof(int) * 6;
2997 count -= sizeof(int) * 6;
2999 dumpcount = tracestuff - tracestrip;
3000 if ( dumpcount < 0 ) {
3001 dumpcount += TRACEMAX;
3003 if ( dumpcount > count ) {
3004 dumpcount = count;
3006 chunk = TRACEMAX - tracestrip;
3007 if ( dumpcount > chunk ) {
3008 COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
3009 chunk * sizeof(tracebuf[0]) );
3010 pData += chunk * sizeof(tracebuf[0]);
3011 tracestrip = 0;
3012 chunk = dumpcount - chunk;
3013 } else {
3014 chunk = dumpcount;
3016 COPY_TO_USER(rc, pData, &tracebuf[tracestrip],
3017 chunk * sizeof(tracebuf[0]) );
3018 tracestrip += chunk;
3019 tracewrap = 0;
3021 PUT_USER(rc, tracestrip, ++pIndex );
3022 PUT_USER(rc, tracestuff, ++pIndex );
3024 return dumpcount;
3025 #else
3026 return 0;
3027 #endif
3030 /******************************************************************************/
3031 /* Function: ip2_ipl_write() */
3032 /* Parameters: */
3033 /* Pointer to file structure */
3034 /* Pointer to data */
3035 /* Number of bytes to write */
3036 /* Returns: Success or failure */
3037 /* */
3038 /* Description: */
3039 /* */
3040 /* */
3041 /******************************************************************************/
3042 static ssize_t
3043 ip2_ipl_write(struct file *pFile, const char *pData, size_t count, loff_t *off)
3045 #ifdef IP2DEBUG_IPL
3046 printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
3047 #endif
3048 return 0;
3051 /******************************************************************************/
3052 /* Function: ip2_ipl_ioctl() */
3053 /* Parameters: Pointer to device inode */
3054 /* Pointer to file structure */
3055 /* Command */
3056 /* Argument */
3057 /* Returns: Success or failure */
3058 /* */
3059 /* Description: */
3060 /* */
3061 /* */
3062 /******************************************************************************/
3063 static int
3064 ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
3066 unsigned int iplminor = MINOR(pInode->i_rdev);
3067 int rc = 0;
3068 ULONG *pIndex = (ULONG*)arg;
3069 i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
3070 i2ChanStrPtr pCh;
3072 #ifdef IP2DEBUG_IPL
3073 printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
3074 #endif
3076 switch ( iplminor ) {
3077 case 0: // IPL device
3078 rc = -EINVAL;
3079 break;
3080 case 1: // Status dump
3081 case 5:
3082 case 9:
3083 case 13:
3084 switch ( cmd ) {
3085 case 64: /* Driver - ip2stat */
3086 PUT_USER(rc, ref_count, pIndex++ );
3087 PUT_USER(rc, irq_counter, pIndex++ );
3088 PUT_USER(rc, bh_counter, pIndex++ );
3089 break;
3091 case 65: /* Board - ip2stat */
3092 if ( pB ) {
3093 COPY_TO_USER(rc, (char*)arg, (char*)pB, sizeof(i2eBordStr) );
3094 PUT_USER(rc, INB(pB->i2eStatus),
3095 (ULONG*)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
3096 } else {
3097 rc = -ENODEV;
3099 break;
3101 default:
3102 pCh = DevTable[cmd];
3103 if ( pCh )
3105 COPY_TO_USER(rc, (char*)arg, (char*)pCh, sizeof(i2ChanStr) );
3106 } else {
3107 rc = cmd < 64 ? -ENODEV : -EINVAL;
3110 break;
3112 case 2: // Ping device
3113 rc = -EINVAL;
3114 break;
3115 case 3: // Trace device
3116 if ( cmd == 1 ) {
3117 PUT_USER(rc, iiSendPendingMail, pIndex++ );
3118 PUT_USER(rc, i2InitChannels, pIndex++ );
3119 PUT_USER(rc, i2QueueNeeds, pIndex++ );
3120 PUT_USER(rc, i2QueueCommands, pIndex++ );
3121 PUT_USER(rc, i2GetStatus, pIndex++ );
3122 PUT_USER(rc, i2Input, pIndex++ );
3123 PUT_USER(rc, i2InputFlush, pIndex++ );
3124 PUT_USER(rc, i2Output, pIndex++ );
3125 PUT_USER(rc, i2FlushOutput, pIndex++ );
3126 PUT_USER(rc, i2DrainWakeup, pIndex++ );
3127 PUT_USER(rc, i2DrainOutput, pIndex++ );
3128 PUT_USER(rc, i2OutputFree, pIndex++ );
3129 PUT_USER(rc, i2StripFifo, pIndex++ );
3130 PUT_USER(rc, i2StuffFifoBypass, pIndex++ );
3131 PUT_USER(rc, i2StuffFifoFlow, pIndex++ );
3132 PUT_USER(rc, i2StuffFifoInline, pIndex++ );
3133 PUT_USER(rc, i2ServiceBoard, pIndex++ );
3134 PUT_USER(rc, serviceOutgoingFifo, pIndex++ );
3135 // PUT_USER(rc, ip2_init, pIndex++ );
3136 PUT_USER(rc, ip2_init_board, pIndex++ );
3137 PUT_USER(rc, find_eisa_board, pIndex++ );
3138 PUT_USER(rc, set_irq, pIndex++ );
3139 PUT_USER(rc, ip2_interrupt, pIndex++ );
3140 PUT_USER(rc, ip2_poll, pIndex++ );
3141 PUT_USER(rc, service_all_boards, pIndex++ );
3142 PUT_USER(rc, do_input, pIndex++ );
3143 PUT_USER(rc, do_status, pIndex++ );
3144 #ifndef IP2DEBUG_OPEN
3145 PUT_USER(rc, 0, pIndex++ );
3146 #else
3147 PUT_USER(rc, open_sanity_check, pIndex++ );
3148 #endif
3149 PUT_USER(rc, ip2_open, pIndex++ );
3150 PUT_USER(rc, ip2_close, pIndex++ );
3151 PUT_USER(rc, ip2_hangup, pIndex++ );
3152 PUT_USER(rc, ip2_write, pIndex++ );
3153 PUT_USER(rc, ip2_putchar, pIndex++ );
3154 PUT_USER(rc, ip2_flush_chars, pIndex++ );
3155 PUT_USER(rc, ip2_write_room, pIndex++ );
3156 PUT_USER(rc, ip2_chars_in_buf, pIndex++ );
3157 PUT_USER(rc, ip2_flush_buffer, pIndex++ );
3159 //PUT_USER(rc, ip2_wait_until_sent, pIndex++ );
3160 PUT_USER(rc, 0, pIndex++ );
3162 PUT_USER(rc, ip2_throttle, pIndex++ );
3163 PUT_USER(rc, ip2_unthrottle, pIndex++ );
3164 PUT_USER(rc, ip2_ioctl, pIndex++ );
3165 PUT_USER(rc, set_modem_info, pIndex++ );
3166 PUT_USER(rc, get_serial_info, pIndex++ );
3167 PUT_USER(rc, set_serial_info, pIndex++ );
3168 PUT_USER(rc, ip2_set_termios, pIndex++ );
3169 PUT_USER(rc, ip2_set_line_discipline, pIndex++ );
3170 PUT_USER(rc, set_params, pIndex++ );
3171 } else {
3172 rc = -EINVAL;
3175 break;
3177 default:
3178 rc = -ENODEV;
3179 break;
3181 return rc;
3184 /******************************************************************************/
3185 /* Function: ip2_ipl_open() */
3186 /* Parameters: Pointer to device inode */
3187 /* Pointer to file structure */
3188 /* Returns: Success or failure */
3189 /* */
3190 /* Description: */
3191 /* */
3192 /* */
3193 /******************************************************************************/
3194 static int
3195 ip2_ipl_open( struct inode *pInode, struct file *pFile )
3197 unsigned int iplminor = MINOR(pInode->i_rdev);
3198 i2eBordStrPtr pB;
3199 i2ChanStrPtr pCh;
3201 #ifdef IP2DEBUG_IPL
3202 printk (KERN_DEBUG "IP2IPL: open\n" );
3203 #endif
3205 switch(iplminor) {
3206 // These are the IPL devices
3207 case 0:
3208 case 4:
3209 case 8:
3210 case 12:
3211 break;
3213 // These are the status devices
3214 case 1:
3215 case 5:
3216 case 9:
3217 case 13:
3218 break;
3220 // These are the debug devices
3221 case 2:
3222 case 6:
3223 case 10:
3224 case 14:
3225 pB = i2BoardPtrTable[iplminor / 4];
3226 pCh = (i2ChanStrPtr) pB->i2eChannelPtr;
3227 break;
3229 // This is the trace device
3230 case 3:
3231 break;
3233 return 0;
3235 /******************************************************************************/
3236 /* Function: ip2_read_procmem */
3237 /* Parameters: */
3238 /* */
3239 /* Returns: Length of output */
3240 /* */
3241 /* Description: */
3242 /* Supplies some driver operating parameters */
3243 /* Not real useful unless your debugging the fifo */
3244 /* */
3245 /******************************************************************************/
3247 #define LIMIT (PAGE_SIZE - 120)
3249 static int
3250 ip2_read_procmem(char *buf, char **start, off_t offset, int len)
3252 i2eBordStrPtr pB;
3253 i2ChanStrPtr pCh;
3254 PTTY tty;
3255 int i;
3257 len = 0;
3259 #define FMTLINE "%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
3260 #define FMTLIN2 " 0x%04x 0x%04x tx flow 0x%x\n"
3261 #define FMTLIN3 " 0x%04x 0x%04x rc flow\n"
3263 len += sprintf(buf+len,"\n");
3265 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3266 pB = i2BoardPtrTable[i];
3267 if ( pB ) {
3268 len += sprintf(buf+len,"board %d:\n",i);
3269 len += sprintf(buf+len,"\tFifo rem: %d mty: %x outM %x\n",
3270 pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
3274 len += sprintf(buf+len,"#: tty flags, port flags, cflags, iflags\n");
3275 for (i=0; i < IP2_MAX_PORTS; i++) {
3276 if (len > LIMIT)
3277 break;
3278 pCh = DevTable[i];
3279 if (pCh) {
3280 tty = pCh->pTTY;
3281 if (tty && tty->count) {
3282 len += sprintf(buf+len,FMTLINE,i,(int)tty->flags,pCh->flags,
3283 tty->termios->c_cflag,tty->termios->c_iflag);
3285 len += sprintf(buf+len,FMTLIN2,
3286 pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
3287 len += sprintf(buf+len,FMTLIN3,pCh->infl.asof,pCh->infl.room);
3291 return len;
3295 * This is the handler for /proc/tty/driver/ip2
3297 * This stretch of code has been largely plagerized from at least three
3298 * different sources including ip2mkdev.c and a couple of other drivers.
3299 * The bugs are all mine. :-) =mhw=
3301 int ip2_read_proc(char *page, char **start, off_t off,
3302 int count, int *eof, void *data)
3304 int i, j, box;
3305 int len = 0;
3306 int boxes = 0;
3307 int ports = 0;
3308 int tports = 0;
3309 off_t begin = 0;
3310 i2eBordStrPtr pB;
3312 len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion );
3313 len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
3314 IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
3315 IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
3317 for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
3318 /* This need to be reset for a board by board count... */
3319 boxes = 0;
3320 pB = i2BoardPtrTable[i];
3321 if( pB ) {
3322 switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED )
3324 case POR_ID_FIIEX:
3325 len += sprintf( page+len, "Board %d: EX ports=", i );
3326 for( box = 0; box < ABS_MAX_BOXES; ++box )
3328 ports = 0;
3330 if( pB->i2eChannelMap[box] != 0 ) ++boxes;
3331 for( j = 0; j < ABS_BIGGEST_BOX; ++j )
3333 if( pB->i2eChannelMap[box] & 1<< j ) {
3334 ++ports;
3337 len += sprintf( page+len, "%d,", ports );
3338 tports += ports;
3341 --len; /* Backup over that last comma */
3343 len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 );
3344 break;
3346 case POR_ID_II_4:
3347 len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i );
3348 tports = ports = 4;
3349 break;
3351 case POR_ID_II_8:
3352 len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i );
3353 tports = ports = 8;
3354 break;
3356 case POR_ID_II_8R:
3357 len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i );
3358 tports = ports = 8;
3359 break;
3361 default:
3362 len += sprintf(page+len, "Board %d: unknown", i );
3363 /* Don't try and probe for minor numbers */
3364 tports = ports = 0;
3367 } else {
3368 /* Don't try and probe for minor numbers */
3369 len += sprintf(page+len, "Board %d: vacant", i );
3370 tports = ports = 0;
3373 if( tports ) {
3374 len += sprintf(page+len, " minors=" );
3376 for ( box = 0; box < ABS_MAX_BOXES; ++box )
3378 for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
3380 if ( pB->i2eChannelMap[box] & (1 << j) )
3382 len += sprintf (page+len,"%d,",
3383 j + ABS_BIGGEST_BOX *
3384 (box+i*ABS_MAX_BOXES));
3389 page[ len - 1 ] = '\n'; /* Overwrite that last comma */
3390 } else {
3391 len += sprintf (page+len,"\n" );
3394 if (len+begin > off+count)
3395 break;
3396 if (len+begin < off) {
3397 begin += len;
3398 len = 0;
3402 if (i >= IP2_MAX_BOARDS)
3403 *eof = 1;
3404 if (off >= len+begin)
3405 return 0;
3407 *start = page + (off-begin);
3408 return ((count < begin+len-off) ? count : begin+len-off);
3411 /******************************************************************************/
3412 /* Function: ip2trace() */
3413 /* Parameters: Value to add to trace buffer */
3414 /* Returns: Nothing */
3415 /* */
3416 /* Description: */
3417 /* */
3418 /* */
3419 /******************************************************************************/
3420 void
3421 ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
3423 #ifdef IP2DEBUG_TRACE
3424 long flags;
3425 unsigned long *pCode = &codes;
3426 union ip2breadcrumb bc;
3427 i2ChanStrPtr pCh;
3430 tracebuf[tracestuff++] = jiffies;
3431 if ( tracestuff == TRACEMAX ) {
3432 tracestuff = 0;
3434 if ( tracestuff == tracestrip ) {
3435 if ( ++tracestrip == TRACEMAX ) {
3436 tracestrip = 0;
3438 ++tracewrap;
3441 bc.hdr.port = 0xff & pn;
3442 bc.hdr.cat = cat;
3443 bc.hdr.codes = (unsigned char)( codes & 0xff );
3444 bc.hdr.label = label;
3445 tracebuf[tracestuff++] = bc.value;
3447 for (;;) {
3448 if ( tracestuff == TRACEMAX ) {
3449 tracestuff = 0;
3451 if ( tracestuff == tracestrip ) {
3452 if ( ++tracestrip == TRACEMAX ) {
3453 tracestrip = 0;
3455 ++tracewrap;
3458 if ( !codes-- )
3459 break;
3461 tracebuf[tracestuff++] = *++pCode;
3463 #endif