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