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