forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcyclades.c
5421 lines (4880 loc) · 155 KB
/
cyclades.c
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#undef BLOCKMOVE
#define Z_WAKE
#undef Z_EXT_CHARS_IN_BUFFER
/*
* linux/drivers/char/cyclades.c
*
* This file contains the driver for the Cyclades async multiport
* serial boards.
*
* Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
* Modified and maintained by Marcio Saito <marcio@cyclades.com>.
*
* Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com>
*
* Much of the design and some of the code came from serial.c
* which was copyright (C) 1991, 1992 Linus Torvalds. It was
* extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
* and then fixed as suggested by Michael K. Johnson 12/12/92.
* Converted to pci probing and cleaned up by Jiri Slaby.
*
* This version supports shared IRQ's (only for PCI boards).
*
* $Log: cyclades.c,v $
* Prevent users from opening non-existing Z ports.
*
* Revision 2.3.2.8 2000/07/06 18:14:16 ivan
* Fixed the PCI detection function to work properly on Alpha systems.
* Implemented support for TIOCSERGETLSR ioctl.
* Implemented full support for non-standard baud rates.
*
* Revision 2.3.2.7 2000/06/01 18:26:34 ivan
* Request PLX I/O region, although driver doesn't use it, to avoid
* problems with other drivers accessing it.
* Removed count for on-board buffer characters in cy_chars_in_buffer
* (Cyclades-Z only).
*
* Revision 2.3.2.6 2000/05/05 13:56:05 ivan
* Driver now reports physical instead of virtual memory addresses.
* Masks were added to some Cyclades-Z read accesses.
* Implemented workaround for PLX9050 bug that would cause a system lockup
* in certain systems, depending on the MMIO addresses allocated to the
* board.
* Changed the Tx interrupt programming in the CD1400 chips to boost up
* performance (Cyclom-Y only).
* Code is now compliant with the new module interface (module_[init|exit]).
* Make use of the PCI helper functions to access PCI resources.
* Did some code "housekeeping".
*
* Revision 2.3.2.5 2000/01/19 14:35:33 ivan
* Fixed bug in cy_set_termios on CRTSCTS flag turnoff.
*
* Revision 2.3.2.4 2000/01/17 09:19:40 ivan
* Fixed SMP locking in Cyclom-Y interrupt handler.
*
* Revision 2.3.2.3 1999/12/28 12:11:39 ivan
* Added a new cyclades_card field called nports to allow the driver to
* know the exact number of ports found by the Z firmware after its load;
* RX buffer contention prevention logic on interrupt op mode revisited
* (Cyclades-Z only);
* Revisited printk's for Z debug;
* Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
*
* Revision 2.3.2.2 1999/10/01 11:27:43 ivan
* Fixed bug in cyz_poll that would make all ports but port 0
* unable to transmit/receive data (Cyclades-Z only);
* Implemented logic to prevent the RX buffer from being stuck with data
* due to a driver / firmware race condition in interrupt op mode
* (Cyclades-Z only);
* Fixed bug in block_til_ready logic that would lead to a system crash;
* Revisited cy_close spinlock usage;
*
* Revision 2.3.2.1 1999/09/28 11:01:22 ivan
* Revisited CONFIG_PCI conditional compilation for PCI board support;
* Implemented TIOCGICOUNT and TIOCMIWAIT ioctl support;
* _Major_ cleanup on the Cyclades-Z interrupt support code / logic;
* Removed CTS handling from the driver -- this is now completely handled
* by the firmware (Cyclades-Z only);
* Flush RX on-board buffers on a port open (Cyclades-Z only);
* Fixed handling of ASYNC_SPD_* TTY flags;
* Module unload now unmaps all memory area allocated by ioremap;
*
* Revision 2.3.1.1 1999/07/15 16:45:53 ivan
* Removed CY_PROC conditional compilation;
* Implemented SMP-awareness for the driver;
* Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
* functions;
* The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
* (irq=NN) as parameters (only for ISA boards);
* Fixed bug in set_line_char that would prevent the Cyclades-Z
* ports from being configured at speeds above 115.2Kbps;
* Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
* switching from working properly;
* The driver now only prints IRQ info for the Cyclades-Z if it's
* configured to work in interrupt mode;
*
* Revision 2.2.2.3 1999/06/28 11:13:29 ivan
* Added support for interrupt mode operation for the Z cards;
* Removed the driver inactivity control for the Z;
* Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
* the Z firmware is not loaded yet;
* Replaced the "manual" Z Tx flush buffer by a call to a FW command of
* same functionality;
* Implemented workaround for IRQ setting loss on the PCI configuration
* registers after a PCI bridge EEPROM reload (affects PLX9060 only);
*
* Revision 2.2.2.2 1999/05/14 17:18:15 ivan
* /proc entry location changed to /proc/tty/driver/cyclades;
* Added support to shared IRQ's (only for PCI boards);
* Added support for Cobalt Qube2 systems;
* IRQ [de]allocation scheme revisited;
* BREAK implementation changed in order to make use of the 'break_ctl'
* TTY facility;
* Fixed typo in TTY structure field 'driver_name';
* Included a PCI bridge reset and EEPROM reload in the board
* initialization code (for both Y and Z series).
*
* Revision 2.2.2.1 1999/04/08 16:17:43 ivan
* Fixed a bug in cy_wait_until_sent that was preventing the port to be
* closed properly after a SIGINT;
* Module usage counter scheme revisited;
* Added support to the upcoming Y PCI boards (i.e., support to additional
* PCI Device ID's).
*
* Revision 2.2.1.10 1999/01/20 16:14:29 ivan
* Removed all unnecessary page-alignement operations in ioremap calls
* (ioremap is currently safe for these operations).
*
* Revision 2.2.1.9 1998/12/30 18:18:30 ivan
* Changed access to PLX PCI bridge registers from I/O to MMIO, in
* order to make PLX9050-based boards work with certain motherboards.
*
* Revision 2.2.1.8 1998/11/13 12:46:20 ivan
* cy_close function now resets (correctly) the tty->closing flag;
* JIFFIES_DIFF macro fixed.
*
* Revision 2.2.1.7 1998/09/03 12:07:28 ivan
* Fixed bug in cy_close function, which was not informing HW of
* which port should have the reception disabled before doing so;
* fixed Cyclom-8YoP hardware detection bug.
*
* Revision 2.2.1.6 1998/08/20 17:15:39 ivan
* Fixed bug in cy_close function, which causes malfunction
* of one of the first 4 ports when a higher port is closed
* (Cyclom-Y only).
*
* Revision 2.2.1.5 1998/08/10 18:10:28 ivan
* Fixed Cyclom-4Yo hardware detection bug.
*
* Revision 2.2.1.4 1998/08/04 11:02:50 ivan
* /proc/cyclades implementation with great collaboration of
* Marc Lewis <marc@blarg.net>;
* cyy_interrupt was changed to avoid occurrence of kernel oopses
* during PPP operation.
*
* Revision 2.2.1.3 1998/06/01 12:09:10 ivan
* General code review in order to comply with 2.1 kernel standards;
* data loss prevention for slow devices revisited (cy_wait_until_sent
* was created);
* removed conditional compilation for new/old PCI structure support
* (now the driver only supports the new PCI structure).
*
* Revision 2.2.1.1 1998/03/19 16:43:12 ivan
* added conditional compilation for new/old PCI structure support;
* removed kernel series (2.0.x / 2.1.x) conditional compilation.
*
* Revision 2.1.1.3 1998/03/16 18:01:12 ivan
* cleaned up the data loss fix;
* fixed XON/XOFF handling once more (Cyclades-Z);
* general review of the driver routines;
* introduction of a mechanism to prevent data loss with slow
* printers, by forcing a delay before closing the port.
*
* Revision 2.1.1.2 1998/02/17 16:50:00 ivan
* fixed detection/handling of new CD1400 in Ye boards;
* fixed XON/XOFF handling (Cyclades-Z);
* fixed data loss caused by a premature port close;
* introduction of a flag that holds the CD1400 version ID per port
* (used by the CYGETCD1400VER new ioctl).
*
* Revision 2.1.1.1 1997/12/03 17:31:19 ivan
* Code review for the module cleanup routine;
* fixed RTS and DTR status report for new CD1400's in get_modem_info;
* includes anonymous changes regarding signal_pending.
*
* Revision 2.1 1997/11/01 17:42:41 ivan
* Changes in the driver to support Alpha systems (except 8Zo V_1);
* BREAK fix for the Cyclades-Z boards;
* driver inactivity control by FW implemented;
* introduction of flag that allows driver to take advantage of
* a special CD1400 feature related to HW flow control;
* added support for the CD1400 rev. J (Cyclom-Y boards);
* introduction of ioctls to:
* - control the rtsdtr_inv flag (Cyclom-Y);
* - control the rflow flag (Cyclom-Y);
* - adjust the polling interval (Cyclades-Z);
*
* Revision 1.36.4.33 1997/06/27 19:00:00 ivan
* Fixes related to kernel version conditional
* compilation.
*
* Revision 1.36.4.32 1997/06/14 19:30:00 ivan
* Compatibility issues between kernels 2.0.x and
* 2.1.x (mainly related to clear_bit function).
*
* Revision 1.36.4.31 1997/06/03 15:30:00 ivan
* Changes to define the memory window according to the
* board type.
*
* Revision 1.36.4.30 1997/05/16 15:30:00 daniel
* Changes to support new cycladesZ boards.
*
* Revision 1.36.4.29 1997/05/12 11:30:00 daniel
* Merge of Bentson's and Daniel's version 1.36.4.28.
* Corrects bug in cy_detect_pci: check if there are more
* ports than the number of static structs allocated.
* Warning message during initialization if this driver is
* used with the new generation of cycladesZ boards. Those
* will be supported only in next release of the driver.
* Corrects bug in cy_detect_pci and cy_detect_isa that
* returned wrong number of VALID boards, when a cyclomY
* was found with no serial modules connected.
* Changes to use current (2.1.x) kernel subroutine names
* and created macros for compilation with 2.0.x kernel,
* instead of the other way around.
*
* Revision 1.36.4.28 1997/05/?? ??:00:00 bentson
* Change queue_task_irq_off to queue_task_irq.
* The inline function queue_task_irq_off (tqueue.h)
* was removed from latest releases of 2.1.x kernel.
* Use of macro __init to mark the initialization
* routines, so memory can be reused.
* Also incorporate implementation of critical region
* in function cleanup_module() created by anonymous
* linuxer.
*
* Revision 1.36.4.28 1997/04/25 16:00:00 daniel
* Change to support new firmware that solves DCD problem:
* application could fail to receive SIGHUP signal when DCD
* varying too fast.
*
* Revision 1.36.4.27 1997/03/26 10:30:00 daniel
* Changed for support linux versions 2.1.X.
* Backward compatible with linux versions 2.0.X.
* Corrected illegal use of filler field in
* CH_CTRL struct.
* Deleted some debug messages.
*
* Revision 1.36.4.26 1997/02/27 12:00:00 daniel
* Included check for NULL tty pointer in cyz_poll.
*
* Revision 1.36.4.25 1997/02/26 16:28:30 bentson
* Bill Foster at Blarg! Online services noticed that
* some of the switch elements of -Z modem control
* lacked a closing "break;"
*
* Revision 1.36.4.24 1997/02/24 11:00:00 daniel
* Changed low water threshold for buffer xmit_buf
*
* Revision 1.36.4.23 1996/12/02 21:50:16 bentson
* Marcio provided fix to modem status fetch for -Z
*
* Revision 1.36.4.22 1996/10/28 22:41:17 bentson
* improve mapping of -Z control page (thanks to Steve
* Price <stevep@fa.tdktca.com> for help on this)
*
* Revision 1.36.4.21 1996/09/10 17:00:10 bentson
* shift from CPU-bound to memcopy in cyz_polling operation
*
* Revision 1.36.4.20 1996/09/09 18:30:32 Bentson
* Added support to set and report higher speeds.
*
* Revision 1.36.4.19c 1996/08/09 10:00:00 Marcio Saito
* Some fixes in the HW flow control for the BETA release.
* Don't try to register the IRQ.
*
* Revision 1.36.4.19 1996/08/08 16:23:18 Bentson
* make sure "cyc" appears in all kernel messages; all soft interrupts
* handled by same routine; recognize out-of-band reception; comment
* out some diagnostic messages; leave RTS/CTS flow control to hardware;
* fix race condition in -Z buffer management; only -Y needs to explicitly
* flush chars; tidy up some startup messages;
*
* Revision 1.36.4.18 1996/07/25 18:57:31 bentson
* shift MOD_INC_USE_COUNT location to match
* serial.c; purge some diagnostic messages;
*
* Revision 1.36.4.17 1996/07/25 18:01:08 bentson
* enable modem status messages and fetch & process them; note
* time of last activity type for each port; set_line_char now
* supports more than line 0 and treats 0 baud correctly;
* get_modem_info senses rs_status;
*
* Revision 1.36.4.16 1996/07/20 08:43:15 bentson
* barely works--now's time to turn on
* more features 'til it breaks
*
* Revision 1.36.4.15 1996/07/19 22:30:06 bentson
* check more -Z board status; shorten boot message
*
* Revision 1.36.4.14 1996/07/19 22:20:37 bentson
* fix reference to ch_ctrl in startup; verify return
* values from cyz_issue_cmd and cyz_update_channel;
* more stuff to get modem control correct;
*
* Revision 1.36.4.13 1996/07/11 19:53:33 bentson
* more -Z stuff folded in; re-order changes to put -Z stuff
* after -Y stuff (to make changes clearer)
*
* Revision 1.36.4.12 1996/07/11 15:40:55 bentson
* Add code to poll Cyclades-Z. Add code to get & set RS-232 control.
* Add code to send break. Clear firmware ID word at startup (so
* that other code won't talk to inactive board).
*
* Revision 1.36.4.11 1996/07/09 05:28:29 bentson
* add code for -Z in set_line_char
*
* Revision 1.36.4.10 1996/07/08 19:28:37 bentson
* fold more -Z stuff (or in some cases, error messages)
* into driver; add text to "don't know what to do" messages.
*
* Revision 1.36.4.9 1996/07/08 18:38:38 bentson
* moved compile-time flags near top of file; cosmetic changes
* to narrow text (to allow 2-up printing); changed many declarations
* to "static" to limit external symbols; shuffled code order to
* coalesce -Y and -Z specific code, also to put internal functions
* in order of tty_driver structure; added code to recognize -Z
* ports (and for moment, do nothing or report error); add cy_startup
* to parse boot command line for extra base addresses for ISA probes;
*
* Revision 1.36.4.8 1996/06/25 17:40:19 bentson
* reorder some code, fix types of some vars (int vs. long),
* add cy_setup to support user declared ISA addresses
*
* Revision 1.36.4.7 1996/06/21 23:06:18 bentson
* dump ioctl based firmware load (it's now a user level
* program); ensure uninitialzed ports cannot be used
*
* Revision 1.36.4.6 1996/06/20 23:17:19 bentson
* rename vars and restructure some code
*
* Revision 1.36.4.5 1996/06/14 15:09:44 bentson
* get right status back after boot load
*
* Revision 1.36.4.4 1996/06/13 19:51:44 bentson
* successfully loads firmware
*
* Revision 1.36.4.3 1996/06/13 06:08:33 bentson
* add more of the code for the boot/load ioctls
*
* Revision 1.36.4.2 1996/06/11 21:00:51 bentson
* start to add Z functionality--starting with ioctl
* for loading firmware
*
* Revision 1.36.4.1 1996/06/10 18:03:02 bentson
* added code to recognize Z/PCI card at initialization; report
* presence, but card is not initialized (because firmware needs
* to be loaded)
*
* Revision 1.36.3.8 1996/06/07 16:29:00 bentson
* starting minor number at zero; added missing verify_area
* as noted by Heiko Eißfeldt <heiko@colossus.escape.de>
*
* Revision 1.36.3.7 1996/04/19 21:06:18 bentson
* remove unneeded boot message & fix CLOCAL hardware flow
* control (Miquel van Smoorenburg <miquels@Q.cistron.nl>);
* remove unused diagnostic statements; minor 0 is first;
*
* Revision 1.36.3.6 1996/03/13 13:21:17 marcio
* The kernel function vremap (available only in later 1.3.xx kernels)
* allows the access to memory addresses above the RAM. This revision
* of the driver supports PCI boards below 1Mb (device id 0x100) and
* above 1Mb (device id 0x101).
*
* Revision 1.36.3.5 1996/03/07 15:20:17 bentson
* Some global changes to interrupt handling spilled into
* this driver--mostly unused arguments in system function
* calls. Also added change by Marcio Saito which should
* reduce lost interrupts at startup by fast processors.
*
* Revision 1.36.3.4 1995/11/13 20:45:10 bentson
* Changes by Corey Minyard <minyard@wf-rch.cirr.com> distributed
* in 1.3.41 kernel to remove a possible race condition, extend
* some error messages, and let the driver run as a loadable module
* Change by Alan Wendt <alan@ez0.ezlink.com> to remove a
* possible race condition.
* Change by Marcio Saito <marcio@cyclades.com> to fix PCI addressing.
*
* Revision 1.36.3.3 1995/11/13 19:44:48 bentson
* Changes by Linus Torvalds in 1.3.33 kernel distribution
* required due to reordering of driver initialization.
* Drivers are now initialized *after* memory management.
*
* Revision 1.36.3.2 1995/09/08 22:07:14 bentson
* remove printk from ISR; fix typo
*
* Revision 1.36.3.1 1995/09/01 12:00:42 marcio
* Minor fixes in the PCI board support. PCI function calls in
* conditional compilation (CONFIG_PCI). Thanks to Jim Duncan
* <duncan@okay.com>. "bad serial count" message removed.
*
* Revision 1.36.3 1995/08/22 09:19:42 marcio
* Cyclom-Y/PCI support added. Changes in the cy_init routine and
* board initialization. Changes in the boot messages. The driver
* supports up to 4 boards and 64 ports by default.
*
* Revision 1.36.1.4 1995/03/29 06:14:14 bentson
* disambiguate between Cyclom-16Y and Cyclom-32Ye;
*
* Revision 1.36.1.3 1995/03/23 22:15:35 bentson
* add missing break in modem control block in ioctl switch statement
* (discovered by Michael Edward Chastain <mec@jobe.shell.portal.com>);
*
* Revision 1.36.1.2 1995/03/22 19:16:22 bentson
* make sure CTS flow control is set as soon as possible (thanks
* to note from David Lambert <lambert@chesapeake.rps.slb.com>);
*
* Revision 1.36.1.1 1995/03/13 15:44:43 bentson
* initialize defaults for receive threshold and stale data timeout;
* cosmetic changes;
*
* Revision 1.36 1995/03/10 23:33:53 bentson
* added support of chips 4-7 in 32 port Cyclom-Ye;
* fix cy_interrupt pointer dereference problem
* (Joe Portman <baron@aa.net>);
* give better error response if open is attempted on non-existent port
* (Zachariah Vaum <jchryslr@netcom.com>);
* correct command timeout (Kenneth Lerman <lerman@@seltd.newnet.com>);
* conditional compilation for -16Y on systems with fast, noisy bus;
* comment out diagnostic print function;
* cleaned up table of base addresses;
* set receiver time-out period register to correct value,
* set receive threshold to better default values,
* set chip timer to more accurate 200 Hz ticking,
* add code to monitor and modify receive parameters
* (Rik Faith <faith@cs.unc.edu> Nick Simicich
* <njs@scifi.emi.net>);
*
* Revision 1.35 1994/12/16 13:54:18 steffen
* additional patch by Marcio Saito for board detection
* Accidently left out in 1.34
*
* Revision 1.34 1994/12/10 12:37:12 steffen
* This is the corrected version as suggested by Marcio Saito
*
* Revision 1.33 1994/12/01 22:41:18 bentson
* add hooks to support more high speeds directly; add tytso
* patch regarding CLOCAL wakeups
*
* Revision 1.32 1994/11/23 19:50:04 bentson
* allow direct kernel control of higher signalling rates;
* look for cards at additional locations
*
* Revision 1.31 1994/11/16 04:33:28 bentson
* ANOTHER fix from Corey Minyard, minyard@wf-rch.cirr.com--
* a problem in chars_in_buffer has been resolved by some
* small changes; this should yield smoother output
*
* Revision 1.30 1994/11/16 04:28:05 bentson
* Fix from Corey Minyard, Internet: minyard@metronet.com,
* UUCP: minyard@wf-rch.cirr.com, WORK: minyardbnr.ca, to
* cy_hangup that appears to clear up much (all?) of the
* DTR glitches; also he's added/cleaned-up diagnostic messages
*
* Revision 1.29 1994/11/16 04:16:07 bentson
* add change proposed by Ralph Sims, ralphs@halcyon.com, to
* operate higher speeds in same way as other serial ports;
* add more serial ports (for up to two 16-port muxes).
*
* Revision 1.28 1994/11/04 00:13:16 root
* turn off diagnostic messages
*
* Revision 1.27 1994/11/03 23:46:37 root
* bunch of changes to bring driver into greater conformance
* with the serial.c driver (looking for missed fixes)
*
* Revision 1.26 1994/11/03 22:40:36 root
* automatic interrupt probing fixed.
*
* Revision 1.25 1994/11/03 20:17:02 root
* start to implement auto-irq
*
* Revision 1.24 1994/11/03 18:01:55 root
* still working on modem signals--trying not to drop DTR
* during the getty/login processes
*
* Revision 1.23 1994/11/03 17:51:36 root
* extend baud rate support; set receive threshold as function
* of baud rate; fix some problems with RTS/CTS;
*
* Revision 1.22 1994/11/02 18:05:35 root
* changed arguments to udelay to type long to get
* delays to be of correct duration
*
* Revision 1.21 1994/11/02 17:37:30 root
* employ udelay (after calibrating loops_per_second earlier
* in init/main.c) instead of using home-grown delay routines
*
* Revision 1.20 1994/11/02 03:11:38 root
* cy_chars_in_buffer forces a return value of 0 to let
* login work (don't know why it does); some functions
* that were returning EFAULT, now executes the code;
* more work on deciding when to disable xmit interrupts;
*
* Revision 1.19 1994/11/01 20:10:14 root
* define routine to start transmission interrupts (by enabling
* transmit interrupts); directly enable/disable modem interrupts;
*
* Revision 1.18 1994/11/01 18:40:45 bentson
* Don't always enable transmit interrupts in startup; interrupt on
* TxMpty instead of TxRdy to help characters get out before shutdown;
* restructure xmit interrupt to check for chars first and quit if
* none are ready to go; modem status (MXVRx) is upright, _not_ inverted
* (to my view);
*
* Revision 1.17 1994/10/30 04:39:45 bentson
* rename serial_driver and callout_driver to cy_serial_driver and
* cy_callout_driver to avoid linkage interference; initialize
* info->type to PORT_CIRRUS; ruggedize paranoia test; elide ->port
* from cyclades_port structure; add paranoia check to cy_close;
*
* Revision 1.16 1994/10/30 01:14:33 bentson
* change major numbers; add some _early_ return statements;
*
* Revision 1.15 1994/10/29 06:43:15 bentson
* final tidying up for clean compile; enable some error reporting
*
* Revision 1.14 1994/10/28 20:30:22 Bentson
* lots of changes to drag the driver towards the new tty_io
* structures and operation. not expected to work, but may
* compile cleanly.
*
* Revision 1.13 1994/07/21 23:08:57 Bentson
* add some diagnostic cruft; support 24 lines (for testing
* both -8Y and -16Y cards; be more thorough in servicing all
* chips during interrupt; add "volatile" a few places to
* circumvent compiler optimizations; fix base & offset
* computations in block_til_ready (was causing chip 0 to
* stop operation)
*
* Revision 1.12 1994/07/19 16:42:11 Bentson
* add some hackery for kernel version 1.1.8; expand
* error messages; refine timing for delay loops and
* declare loop params volatile
*
* Revision 1.11 1994/06/11 21:53:10 bentson
* get use of save_car right in transmit interrupt service
*
* Revision 1.10.1.1 1994/06/11 21:31:18 bentson
* add some diagnostic printing; try to fix save_car stuff
*
* Revision 1.10 1994/06/11 20:36:08 bentson
* clean up compiler warnings
*
* Revision 1.9 1994/06/11 19:42:46 bentson
* added a bunch of code to support modem signalling
*
* Revision 1.8 1994/06/11 17:57:07 bentson
* recognize break & parity error
*
* Revision 1.7 1994/06/05 05:51:34 bentson
* Reorder baud table to be monotonic; add cli to CP; discard
* incoming characters and status if the line isn't open; start to
* fold code into cy_throttle; start to port get_serial_info,
* set_serial_info, get_modem_info, set_modem_info, and send_break
* from serial.c; expand cy_ioctl; relocate and expand config_setup;
* get flow control characters from tty struct; invalidate ports w/o
* hardware;
*
* Revision 1.6 1994/05/31 18:42:21 bentson
* add a loop-breaker in the interrupt service routine;
* note when port is initialized so that it can be shut
* down under the right conditions; receive works without
* any obvious errors
*
* Revision 1.5 1994/05/30 00:55:02 bentson
* transmit works without obvious errors
*
* Revision 1.4 1994/05/27 18:46:27 bentson
* incorporated more code from lib_y.c; can now print short
* strings under interrupt control to port zero; seems to
* select ports/channels/lines correctly
*
* Revision 1.3 1994/05/25 22:12:44 bentson
* shifting from multi-port on a card to proper multiplexor
* data structures; added skeletons of most routines
*
* Revision 1.2 1994/05/19 13:21:43 bentson
* start to crib from other sources
*
*/
#define CY_VERSION "2.5"
/* If you need to install more boards than NR_CARDS, change the constant
in the definition below. No other change is necessary to support up to
eight boards. Beyond that you'll have to extend cy_isa_addresses. */
#define NR_CARDS 4
/*
If the total number of ports is larger than NR_PORTS, change this
constant in the definition below. No other change is necessary to
support more boards/ports. */
#define NR_PORTS 256
#define ZE_V1_NPORTS 64
#define ZO_V1 0
#define ZO_V2 1
#define ZE_V1 2
#define SERIAL_PARANOIA_CHECK
#undef CY_DEBUG_OPEN
#undef CY_DEBUG_THROTTLE
#undef CY_DEBUG_OTHER
#undef CY_DEBUG_IO
#undef CY_DEBUG_COUNT
#undef CY_DEBUG_DTR
#undef CY_DEBUG_WAIT_UNTIL_SENT
#undef CY_DEBUG_INTERRUPTS
#undef CY_16Y_HACK
#undef CY_ENABLE_MONITORING
#undef CY_PCI_DEBUG
/*
* Include section
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/cyclades.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
#include <linux/firmware.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
static void cy_throttle(struct tty_struct *tty);
static void cy_send_xchar(struct tty_struct *tty, char ch);
#define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1)
#define Z_FPGA_CHECK(card) \
((readl(&((struct RUNTIME_9060 __iomem *) \
((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
#define ISZLOADED(card) (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \
((card).ctl_addr))->mail_box_0)) || \
Z_FPGA_CHECK(card)) && \
(ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \
((card).base_addr+ID_ADDRESS))->signature)))
#ifndef SERIAL_XMIT_SIZE
#define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096))
#endif
#define WAKEUP_CHARS 256
#define STD_COM_FLAGS (0)
/* firmware stuff */
#define ZL_MAX_BLOCKS 16
#define DRIVER_VERSION 0x02010203
#define RAM_SIZE 0x80000
#define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0)
enum zblock_type {
ZBLOCK_PRG = 0,
ZBLOCK_FPGA = 1
};
struct zfile_header {
char name[64];
char date[32];
char aux[32];
u32 n_config;
u32 config_offset;
u32 n_blocks;
u32 block_offset;
u32 reserved[9];
} __attribute__ ((packed));
struct zfile_config {
char name[64];
u32 mailbox;
u32 function;
u32 n_blocks;
u32 block_list[ZL_MAX_BLOCKS];
} __attribute__ ((packed));
struct zfile_block {
u32 type;
u32 file_offset;
u32 ram_offset;
u32 size;
} __attribute__ ((packed));
static struct tty_driver *cy_serial_driver;
#ifdef CONFIG_ISA
/* This is the address lookup table. The driver will probe for
Cyclom-Y/ISA boards at all addresses in here. If you want the
driver to probe addresses at a different address, add it to
this table. If the driver is probing some other board and
causing problems, remove the offending address from this table.
*/
static unsigned int cy_isa_addresses[] = {
0xD0000,
0xD2000,
0xD4000,
0xD6000,
0xD8000,
0xDA000,
0xDC000,
0xDE000,
0, 0, 0, 0, 0, 0, 0, 0
};
#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
#ifdef MODULE
static long maddr[NR_CARDS];
static int irq[NR_CARDS];
module_param_array(maddr, long, NULL, 0);
module_param_array(irq, int, NULL, 0);
#endif
#endif /* CONFIG_ISA */
/* This is the per-card data structure containing address, irq, number of
channels, etc. This driver supports a maximum of NR_CARDS cards.
*/
static struct cyclades_card cy_card[NR_CARDS];
static int cy_next_channel; /* next minor available */
/*
* This is used to look up the divisor speeds and the timeouts
* We're normally limited to 15 distinct baud rates. The extra
* are accessed via settings in info->flags.
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
* 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
* HI VHI
* 20
*/
static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
230400, 0
};
static char baud_co_25[] = { /* 25 MHz clock option table */
/* value => 00 01 02 03 04 */
/* divide by 8 32 128 512 2048 */
0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static char baud_bpr_25[] = { /* 25 MHz baud rate period table */
0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
};
static char baud_co_60[] = { /* 60 MHz clock option table (CD1400 J) */
/* value => 00 01 02 03 04 */
/* divide by 8 32 128 512 2048 */
0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00
};
static char baud_bpr_60[] = { /* 60 MHz baud rate period table (CD1400 J) */
0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
0x21
};
static char baud_cor3[] = { /* receive threshold */
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
0x07
};
/*
* The Cyclades driver implements HW flow control as any serial driver.
* The cyclades_port structure member rflow and the vector rflow_thr
* allows us to take advantage of a special feature in the CD1400 to avoid
* data loss even when the system interrupt latency is too high. These flags
* are to be used only with very special applications. Setting these flags
* requires the use of a special cable (DTR and RTS reversed). In the new
* CD1400-based boards (rev. 6.00 or later), there is no need for special
* cables.
*/
static char rflow_thr[] = { /* rflow threshold */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a
};
/* The Cyclom-Ye has placed the sequential chips in non-sequential
* address order. This look-up table overcomes that problem.
*/
static int cy_chip_offset[] = { 0x0000,
0x0400,
0x0800,
0x0C00,
0x0200,
0x0600,
0x0A00,
0x0E00
};
/* PCI related definitions */
#ifdef CONFIG_PCI
static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) }, /* PCI > 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) }, /* 4Y PCI < 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) }, /* 4Y PCI > 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) }, /* 8Y PCI < 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) }, /* 8Y PCI > 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) }, /* Z PCI < 1Mb */
{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) }, /* Z PCI > 1Mb */
{ } /* end of table */
};
MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
#endif
static void cy_start(struct tty_struct *);
static void set_line_char(struct cyclades_port *);
static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
#ifdef CONFIG_ISA
static unsigned detect_isa_irq(void __iomem *);
#endif /* CONFIG_ISA */
static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *);
#ifndef CONFIG_CYZ_INTR
static void cyz_poll(unsigned long);
/* The Cyclades-Z polling cycle is defined by this variable */
static long cyz_polling_cycle = CZ_DEF_POLL;
static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
#else /* CONFIG_CYZ_INTR */
static void cyz_rx_restart(unsigned long);
static struct timer_list cyz_rx_full_timer[NR_PORTS];
#endif /* CONFIG_CYZ_INTR */
static inline int serial_paranoia_check(struct cyclades_port *info,
char *name, const char *routine)
{
#ifdef SERIAL_PARANOIA_CHECK
if (!info) {
printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
"in %s\n", name, routine);
return 1;
}
if (info->magic != CYCLADES_MAGIC) {
printk(KERN_WARNING "cyc Warning: bad magic number for serial "
"struct (%s) in %s\n", name, routine);
return 1;
}
#endif
return 0;
} /* serial_paranoia_check */
/***********************************************************/
/********* Start of block of Cyclom-Y specific code ********/
/* This routine waits up to 1000 micro-seconds for the previous
command to the Cirrus chip to complete and then issues the
new command. An error is returned if the previous command
didn't finish within the time limit.
This function is only called from inside spinlock-protected code.
*/
static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
{
unsigned int i;
/* Check to see that the previous command has completed */
for (i = 0; i < 100; i++) {
if (readb(base_addr + (CyCCR << index)) == 0) {
break;
}
udelay(10L);
}
/* if the CCR never cleared, the previous command
didn't finish within the "reasonable time" */
if (i == 100)
return -1;
/* Issue the new command */
cy_writeb(base_addr + (CyCCR << index), cmd);
return 0;
} /* cyy_issue_cmd */
#ifdef CONFIG_ISA
/* ISA interrupt detection code */
static unsigned detect_isa_irq(void __iomem * address)
{
int irq;
unsigned long irqs, flags;
int save_xir, save_car;
int index = 0; /* IRQ probing is only for ISA */
/* forget possible initially masked and pending IRQ */
irq = probe_irq_off(probe_irq_on());
/* Clear interrupts on the board first */
cy_writeb(address + (Cy_ClrIntr << index), 0);
/* Cy_ClrIntr is 0x1800 */
irqs = probe_irq_on();
/* Wait ... */
udelay(5000L);
/* Enable the Tx interrupts on the CD1400 */
local_irq_save(flags);
cy_writeb(address + (CyCAR << index), 0);
cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
cy_writeb(address + (CyCAR << index), 0);
cy_writeb(address + (CySRER << index),
readb(address + (CySRER << index)) | CyTxRdy);
local_irq_restore(flags);
/* Wait ... */
udelay(5000L);
/* Check which interrupt is in use */
irq = probe_irq_off(irqs);
/* Clean up */
save_xir = (u_char) readb(address + (CyTIR << index));
save_car = readb(address + (CyCAR << index));
cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
cy_writeb(address + (CySRER << index),
readb(address + (CySRER << index)) & ~CyTxRdy);
cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
cy_writeb(address + (CyCAR << index), (save_car));
cy_writeb(address + (Cy_ClrIntr << index), 0);
/* Cy_ClrIntr is 0x1800 */
return (irq > 0) ? irq : 0;
}
#endif /* CONFIG_ISA */
static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
void __iomem *base_addr)
{
struct cyclades_port *info;
struct tty_struct *tty;
int len, index = cinfo->bus_index;
u8 save_xir, channel, save_car, data, char_count;
#ifdef CY_DEBUG_INTERRUPTS
printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
#endif
/* determine the channel & change to that context */
save_xir = readb(base_addr + (CyRIR << index));
channel = save_xir & CyIRChannel;
info = &cinfo->ports[channel + chip * 4];
save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir);
/* if there is nowhere to put the data, discard it */
if (info->tty == NULL) {