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