This source file includes following definitions.
- serial_paranoia_check
- SP
- CP
- CP1
- CP2
- CP4
- CP8
- write_cy_cmd
- cy_stop
- cy_start
- cy_sched_event
- cy_probe
- cy_interrupt
- do_cyclades_bh
- do_softint
- grab_all_interrupts
- free_all_interrupts
- check_wild_interrupts
- get_auto_irq
- do_auto_irq
- startup
- start_xmit
- shutdown
- config_setup
- cy_put_char
- cy_flush_chars
- cy_write
- cy_write_room
- cy_chars_in_buffer
- cy_flush_buffer
- cy_throttle
- cy_unthrottle
- get_serial_info
- set_serial_info
- get_modem_info
- set_modem_info
- send_break
- get_mon_info
- set_threshold
- get_threshold
- set_default_threshold
- get_default_threshold
- set_timeout
- get_timeout
- set_default_timeout
- get_default_timeout
- cy_ioctl
- cy_set_termios
- cy_close
- cy_hangup
- block_til_ready
- cy_open
- show_version
- cy_init_card
- cy_init
- cy_detect_isa
- cy_detect_pci
- show_status
1 static char rcsid[] =
2 "$Revision: 1.36.3.2 $$Date: 1995/09/08 22:07:14 $";
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 #include <linux/errno.h>
227 #include <linux/signal.h>
228 #include <linux/sched.h>
229 #include <linux/timer.h>
230 #include <linux/tty.h>
231 #include <linux/serial.h>
232 #include <linux/interrupt.h>
233 #include <linux/string.h>
234 #include <linux/fcntl.h>
235 #include <linux/ptrace.h>
236 #include <linux/cyclades.h>
237 #include <linux/delay.h>
238 #include <linux/major.h>
239 #include <linux/mm.h>
240
241 #include <asm/system.h>
242 #include <asm/io.h>
243 #include <asm/segment.h>
244 #include <asm/bitops.h>
245
246 #include <linux/config.h>
247 #include <linux/types.h>
248 #include <linux/kernel.h>
249 #include <linux/bios32.h>
250 #include <linux/pci.h>
251
252 #define small_delay(x) for(j=0;j<x;j++)k++;
253
254
255 #define SERIAL_PARANOIA_CHECK
256 #undef SERIAL_DEBUG_OPEN
257 #undef SERIAL_DEBUG_THROTTLE
258 #undef SERIAL_DEBUG_OTHER
259 #undef SERIAL_DEBUG_IO
260 #undef SERIAL_DEBUG_COUNT
261 #undef SERIAL_DEBUG_DTR
262 #undef CYCLOM_16Y_HACK
263 #undef CYCLOM_ENABLE_MONITORING
264
265 #ifndef MIN
266 #define MIN(a,b) ((a) < (b) ? (a) : (b))
267 #endif
268
269 #define WAKEUP_CHARS 256
270
271 #define STD_COM_FLAGS (0)
272
273 #define SERIAL_TYPE_NORMAL 1
274 #define SERIAL_TYPE_CALLOUT 2
275
276
277 DECLARE_TASK_QUEUE(tq_cyclades);
278
279 struct tty_driver cy_serial_driver, cy_callout_driver;
280
281 static volatile int cy_irq_triggered;
282 static volatile int cy_triggered;
283 static int cy_wild_int_mask;
284 static unsigned char *intr_base_addr;
285
286
287
288
289
290
291
292
293 static unsigned char *cy_isa_addresses[] = {
294 (unsigned char *) 0xD0000,
295 (unsigned char *) 0xD2000,
296 (unsigned char *) 0xD4000,
297 (unsigned char *) 0xD6000,
298 (unsigned char *) 0xD8000,
299 (unsigned char *) 0xDA000,
300 (unsigned char *) 0xDC000,
301 (unsigned char *) 0xDE000,
302 };
303 #define NR_ISA_ADDRESSES (sizeof(cy_isa_addresses)/sizeof(unsigned char *))
304
305
306
307
308
309
310 #define NR_CARDS 4
311
312 static struct cyclades_card cy_card[NR_CARDS];
313
314
315
316
317
318
319
320 #define NR_PORTS 64
321
322 static struct cyclades_port cy_port[NR_PORTS];
323
324
325
326
327 static int cy_chip_offset [] =
328 { 0x0000,
329 0x0400,
330 0x0800,
331 0x0C00,
332 0x0200,
333 0x0600,
334 0x0A00,
335 0x0E00
336 };
337
338
339
340 static unsigned short cy_pci_nboard = 0;
341 static unsigned short cy_isa_nboard = 0;
342 static unsigned short cy_nboard = 0;
343
344 int cy_detect_isa(void);
345 int cy_detect_pci(void);
346
347 static int cy_next_channel = 0;
348
349 static int serial_refcount;
350
351 static struct tty_struct *serial_table[NR_PORTS];
352 static struct termios *serial_termios[NR_PORTS];
353 static struct termios *serial_termios_locked[NR_PORTS];
354
355
356
357
358 struct cyclades_card *IRQ_cards[16];
359
360
361
362
363
364
365
366
367
368
369
370 static unsigned char *tmp_buf = 0;
371 static struct semaphore tmp_buf_sem = MUTEX;
372
373
374
375
376
377
378
379
380
381 static int baud_table[] = {
382 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
383 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800,115200,150000,
384 0};
385
386 static char baud_co[] = {
387
388
389 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
390 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
391
392 static char baud_bpr[] = {
393 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
394 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15};
395
396 static char baud_cor3[] = {
397 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
398 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07};
399
400
401
402 static void shutdown(struct cyclades_port *);
403 static int startup (struct cyclades_port *);
404 static void cy_throttle(struct tty_struct *);
405 static void cy_unthrottle(struct tty_struct *);
406 static void config_setup(struct cyclades_port *);
407 extern void console_print(const char *);
408 #ifdef CYCLOM_SHOW_STATUS
409 static void show_status(int);
410 #endif
411
412
413 static inline int
414 serial_paranoia_check(struct cyclades_port *info,
415 kdev_t device, const char *routine)
416 {
417 #ifdef SERIAL_PARANOIA_CHECK
418 static const char *badmagic =
419 "Warning: bad magic number for serial struct (%s) in %s\n";
420 static const char *badinfo =
421 "Warning: null cyclades_port for (%s) in %s\n";
422 static const char *badrange =
423 "Warning: cyclades_port out of range for (%s) in %s\n";
424
425 if (!info) {
426 printk(badinfo, kdevname(device), routine);
427 return 1;
428 }
429
430 if( (long)info < (long)(&cy_port[0])
431 || (long)(&cy_port[NR_PORTS]) < (long)info ){
432 printk(badrange, kdevname(device), routine);
433 return 1;
434 }
435
436 if (info->magic != CYCLADES_MAGIC) {
437 printk(badmagic, kdevname(device), routine);
438 return 1;
439 }
440 #endif
441 return 0;
442 }
443
444
445
446
447 void
448 SP(char *data){
449 unsigned long flags;
450 save_flags(flags); cli();
451 console_print(data);
452 restore_flags(flags);
453 }
454 char scrn[2];
455 void
456 CP(char data){
457 unsigned long flags;
458 save_flags(flags); cli();
459 scrn[0] = data;
460 console_print(scrn);
461 restore_flags(flags);
462 }
463
464 void CP1(int data) { (data<10)? CP(data+'0'): CP(data+'A'-10); }
465 void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }
466 void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }
467 void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }
468
469
470
471
472
473
474
475 u_short
476 write_cy_cmd(u_char *base_addr, u_char cmd, int index)
477 {
478 unsigned long flags;
479 volatile int i;
480
481 save_flags(flags); cli();
482
483 for(i = 0 ; i < 100 ; i++){
484 if (base_addr[CyCCR<<index] == 0){
485 break;
486 }
487 udelay(10L);
488 }
489
490
491 if ( i == 100 ) {
492 restore_flags(flags);
493 return (-1);
494 }
495
496
497 base_addr[CyCCR<<index] = cmd;
498 restore_flags(flags);
499 return(0);
500 }
501
502
503
504
505
506 static void
507 cy_stop(struct tty_struct *tty)
508 {
509 struct cyclades_card *cinfo;
510 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
511 unsigned char *base_addr;
512 int chip,channel,index;
513 unsigned long flags;
514
515 #ifdef SERIAL_DEBUG_OTHER
516 printk("cy_stop ttyC%d\n", info->line);
517 #endif
518
519 if (serial_paranoia_check(info, tty->device, "cy_stop"))
520 return;
521
522 cinfo = &cy_card[info->card];
523 index = cinfo->bus_index;
524 channel = info->line - cinfo->first_line;
525 chip = channel>>2;
526 channel &= 0x03;
527 base_addr = (unsigned char*)
528 (cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index));
529
530 save_flags(flags); cli();
531 base_addr[CyCAR<<index] = (u_char)(channel & 0x0003);
532 base_addr[CySRER<<index] &= ~CyTxMpty;
533 restore_flags(flags);
534
535 return;
536 }
537
538 static void
539 cy_start(struct tty_struct *tty)
540 {
541 struct cyclades_card *cinfo;
542 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
543 unsigned char *base_addr;
544 int chip,channel,index;
545 unsigned long flags;
546
547 #ifdef SERIAL_DEBUG_OTHER
548 printk("cy_start ttyC%d\n", info->line);
549 #endif
550
551 if (serial_paranoia_check(info, tty->device, "cy_start"))
552 return;
553
554 cinfo = &cy_card[info->card];
555 index = cinfo->bus_index;
556 channel = info->line - cinfo->first_line;
557 chip = channel>>2;
558 channel &= 0x03;
559 base_addr = (unsigned char*)
560 (cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index));
561
562 save_flags(flags); cli();
563 base_addr[CyCAR<<index] = (u_char)(channel & 0x0003);
564 base_addr[CySRER<<index] |= CyTxMpty;
565 restore_flags(flags);
566
567 return;
568 }
569
570
571
572
573
574
575
576
577 static inline void
578 cy_sched_event(struct cyclades_port *info, int event)
579 {
580 info->event |= 1 << event;
581 queue_task_irq_off(&info->tqueue, &tq_cyclades);
582 mark_bh(CYCLADES_BH);
583 }
584
585
586
587
588
589
590
591 static void
592 cy_probe(int irq, struct pt_regs *regs)
593 {
594 int save_xir, save_car;
595 int index = 0;
596
597 cy_irq_triggered = irq;
598 cy_triggered |= 1 << irq;
599
600 if(intr_base_addr[CySVRR<<index] != 0) {
601 save_xir = (u_char) intr_base_addr[CyTIR<<index];
602 save_car = intr_base_addr[CyCAR<<index];
603 if ((save_xir & 0x3) != 0){
604 SP("channel ");
605 CP2(save_xir);
606 SP(" requesting unexpected interrupt\n");
607 }
608 intr_base_addr[CyCAR<<index] = (save_xir & 0x3);
609 intr_base_addr[CySRER<<index] &= ~CyTxMpty;
610 intr_base_addr[CyTIR<<index] = (save_xir & 0x3f);
611 intr_base_addr[CyCAR<<index] = (save_car);
612 *(intr_base_addr + (Cy_ClrIntr<<index)) = 0;
613 }
614 return;
615 }
616
617
618
619
620
621 static void
622 cy_interrupt(int irq, struct pt_regs *regs)
623 {
624 struct tty_struct *tty;
625 int status;
626 struct cyclades_card *cinfo;
627 struct cyclades_port *info;
628 volatile unsigned char *base_addr, *card_base_addr;
629 int chip;
630 int save_xir, channel, save_car;
631 char data;
632 int char_count;
633 int outch;
634 int i,j,index;
635 int too_many;
636 int had_work;
637 int mdm_change;
638 int mdm_status;
639
640 if((cinfo = IRQ_cards[irq]) == 0){
641 return;
642 }
643
644 card_base_addr = (unsigned char *)cinfo->base_addr;
645 index = cinfo->bus_index;
646
647
648
649
650
651
652 do{
653 had_work = 0;
654 for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
655 base_addr = (unsigned char *)
656 (cinfo->base_addr + (cy_chip_offset[chip]<<index));
657 too_many = 0;
658 while ( (status = base_addr[CySVRR<<index]) != 0x00) {
659 had_work++;
660
661
662
663
664
665 if(1000<too_many++){
666 break;
667 }
668 if (status & CySRReceive) {
669
670 save_xir = (u_char) base_addr[CyRIR<<index];
671 channel = (u_short ) (save_xir & CyIRChannel);
672 i = channel + chip * 4 + cinfo->first_line;
673 info = &cy_port[i];
674 info->last_active = jiffies;
675 save_car = base_addr[CyCAR<<index];
676 base_addr[CyCAR<<index] = save_xir;
677
678
679 if(info->tty == 0){
680 j = (base_addr[CyRIVR<<index] & CyIVRMask);
681 if ( j == CyIVRRxEx ) {
682 data = base_addr[CyRDSR<<index];
683 } else {
684 char_count = base_addr[CyRDCR<<index];
685 while(char_count--){
686 data = base_addr[CyRDSR<<index];
687 }
688 }
689 }else{
690 tty = info->tty;
691 j = (base_addr[CyRIVR<<index] & CyIVRMask);
692 if ( j == CyIVRRxEx ) {
693 data = base_addr[CyRDSR<<index];
694 if(data & info->ignore_status_mask){
695 continue;
696 }
697 if (tty->flip.count < TTY_FLIPBUF_SIZE){
698 tty->flip.count++;
699 if (data & info->read_status_mask){
700 if(data & CyBREAK){
701 *tty->flip.flag_buf_ptr++ =
702 TTY_BREAK;
703 *tty->flip.char_buf_ptr++ =
704 base_addr[CyRDSR<<index];
705 if (info->flags & ASYNC_SAK){
706 do_SAK(tty);
707 }
708 }else if(data & CyFRAME){
709 *tty->flip.flag_buf_ptr++ =
710 TTY_FRAME;
711 *tty->flip.char_buf_ptr++ =
712 base_addr[CyRDSR<<index];
713 }else if(data & CyPARITY){
714 *tty->flip.flag_buf_ptr++ =
715 TTY_PARITY;
716 *tty->flip.char_buf_ptr++ =
717 base_addr[CyRDSR<<index];
718 }else if(data & CyOVERRUN){
719 *tty->flip.flag_buf_ptr++ =
720 TTY_OVERRUN;
721 *tty->flip.char_buf_ptr++ = 0;
722
723
724
725
726 if(tty->flip.count < TTY_FLIPBUF_SIZE){
727 tty->flip.count++;
728 *tty->flip.flag_buf_ptr++ =
729 TTY_NORMAL;
730 *tty->flip.char_buf_ptr++ =
731 base_addr[CyRDSR<<index];
732 }
733
734
735
736
737 }else{
738 *tty->flip.flag_buf_ptr++ = 0;
739 *tty->flip.char_buf_ptr++ = 0;
740 }
741 }else{
742 *tty->flip.flag_buf_ptr++ = 0;
743 *tty->flip.char_buf_ptr++ = 0;
744 }
745 }else{
746
747
748 }
749 } else {
750
751 char_count = base_addr[CyRDCR<<index];
752
753 #ifdef CYCLOM_ENABLE_MONITORING
754 ++info->mon.int_count;
755 info->mon.char_count += char_count;
756 if (char_count > info->mon.char_max)
757 info->mon.char_max = char_count;
758 info->mon.char_last = char_count;
759 #endif
760 while(char_count--){
761 if (tty->flip.count >= TTY_FLIPBUF_SIZE){
762 break;
763 }
764 tty->flip.count++;
765 data = base_addr[CyRDSR<<index];
766 *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
767 *tty->flip.char_buf_ptr++ = data;
768 #ifdef CYCLOM_16Y_HACK
769 udelay(10L);
770 #endif
771 }
772 }
773 queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
774 }
775
776 base_addr[CyRIR<<index] = (save_xir & 0x3f);
777 base_addr[CyCAR<<index] = (save_car);
778 }
779
780
781 if (status & CySRTransmit) {
782
783
784
785
786 save_xir = (u_char) base_addr[CyTIR<<index];
787 channel = (u_short ) (save_xir & CyIRChannel);
788 i = channel + chip * 4 + cinfo->first_line;
789 save_car = base_addr[CyCAR<<index];
790 base_addr[CyCAR<<index] = save_xir;
791
792
793 if( (i < 0) || (NR_PORTS <= i) ){
794 base_addr[CySRER<<index] &= ~CyTxMpty;
795 goto txend;
796 }
797 info = &cy_port[i];
798 info->last_active = jiffies;
799 if(info->tty == 0){
800 base_addr[CySRER<<index] &= ~CyTxMpty;
801 goto txdone;
802 }
803
804
805 char_count = info->xmit_fifo_size;
806
807
808 if(info->x_char) {
809 outch = info->x_char;
810 base_addr[CyTDR<<index] = outch;
811 char_count--;
812 info->x_char = 0;
813 }
814
815 if (info->x_break){
816
817
818
819
820
821
822
823
824 base_addr[CyTDR<<index] = 0;
825 base_addr[CyTDR<<index] = 0x81;
826 base_addr[CyTDR<<index] = 0;
827 base_addr[CyTDR<<index] = 0x82;
828 base_addr[CyTDR<<index] = info->x_break*200/HZ;
829 base_addr[CyTDR<<index] = 0;
830 base_addr[CyTDR<<index] = 0x83;
831 char_count -= 7;
832 info->x_break = 0;
833 }
834
835 while (char_count-- > 0){
836 if (!info->xmit_cnt){
837 base_addr[CySRER<<index] &= ~CyTxMpty;
838 goto txdone;
839 }
840 if (info->xmit_buf == 0){
841 base_addr[CySRER<<index] &= ~CyTxMpty;
842 goto txdone;
843 }
844 if (info->tty->stopped || info->tty->hw_stopped){
845 base_addr[CySRER<<index] &= ~CyTxMpty;
846 goto txdone;
847 }
848
849
850
851
852
853
854
855
856
857
858
859 outch = info->xmit_buf[info->xmit_tail];
860 if( outch ){
861 info->xmit_cnt--;
862 info->xmit_tail = (info->xmit_tail + 1)
863 & (PAGE_SIZE - 1);
864 base_addr[CyTDR<<index] = outch;
865 }else{
866 if(char_count > 1){
867 info->xmit_cnt--;
868 info->xmit_tail = (info->xmit_tail + 1)
869 & (PAGE_SIZE - 1);
870 base_addr[CyTDR<<index] = outch;
871 base_addr[CyTDR<<index] = 0;
872 char_count--;
873 }else{
874 }
875 }
876 }
877
878 txdone:
879 if (info->xmit_cnt < WAKEUP_CHARS) {
880 cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
881 }
882
883 txend:
884
885 base_addr[CyTIR<<index] = (save_xir & 0x3f);
886 base_addr[CyCAR<<index] = (save_car);
887 }
888
889 if (status & CySRModem) {
890
891
892 save_xir = (u_char) base_addr[CyMIR<<index];
893 channel = (u_short ) (save_xir & CyIRChannel);
894 info = &cy_port[channel + chip * 4 + cinfo->first_line];
895 info->last_active = jiffies;
896 save_car = base_addr[CyCAR<<index];
897 base_addr[CyCAR<<index] = save_xir;
898
899 mdm_change = base_addr[CyMISR<<index];
900 mdm_status = base_addr[CyMSVR1<<index];
901
902 if(info->tty == 0){
903 ;
904 }else{
905 if((mdm_change & CyDCD)
906 && (info->flags & ASYNC_CHECK_CD)){
907 if(mdm_status & CyDCD){
908
909 cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
910 }else if(!((info->flags & ASYNC_CALLOUT_ACTIVE)
911 &&(info->flags & ASYNC_CALLOUT_NOHUP))){
912
913 cy_sched_event(info, Cy_EVENT_HANGUP);
914 }
915 }
916 if((mdm_change & CyCTS)
917 && (info->flags & ASYNC_CTS_FLOW)){
918 if(info->tty->stopped){
919 if(mdm_status & CyCTS){
920
921 info->tty->stopped = 0;
922 base_addr[CySRER<<index] |= CyTxMpty;
923 cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
924 }
925 }else{
926 if(!(mdm_status & CyCTS)){
927
928 info->tty->stopped = 1;
929 base_addr[CySRER<<index] &= ~CyTxMpty;
930 }
931 }
932 }
933 if(mdm_status & CyDSR){
934 }
935 if(mdm_status & CyRI){
936 }
937 }
938
939 base_addr[CyMIR<<index] = (save_xir & 0x3f);
940 base_addr[CyCAR<<index] = save_car;
941 }
942 }
943 }
944 } while(had_work);
945
946
947 *(card_base_addr + (Cy_ClrIntr<<index)) = 0;
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 static void
974 do_cyclades_bh(void *unused)
975 {
976 run_task_queue(&tq_cyclades);
977 }
978
979 static void
980 do_softint(void *private_)
981 {
982 struct cyclades_port *info = (struct cyclades_port *) private_;
983 struct tty_struct *tty;
984
985 tty = info->tty;
986 if (!tty)
987 return;
988
989 if (clear_bit(Cy_EVENT_HANGUP, &info->event)) {
990 tty_hangup(info->tty);
991 wake_up_interruptible(&info->open_wait);
992 info->flags &= ~(ASYNC_NORMAL_ACTIVE|
993 ASYNC_CALLOUT_ACTIVE);
994 }
995 if (clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
996 wake_up_interruptible(&info->open_wait);
997 }
998 if (clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
999 if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
1000 && tty->ldisc.write_wakeup){
1001 (tty->ldisc.write_wakeup)(tty);
1002 }
1003 wake_up_interruptible(&tty->write_wait);
1004 }
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014 static int
1015 grab_all_interrupts(int dontgrab)
1016 {
1017 int irq_lines = 0;
1018 int i, mask;
1019
1020 for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
1021 if (!(mask & dontgrab)
1022 && !request_irq(i, cy_probe, SA_INTERRUPT, "serial probe")) {
1023 irq_lines |= mask;
1024 }
1025 }
1026 return irq_lines;
1027 }
1028
1029
1030
1031
1032 static void
1033 free_all_interrupts(int irq_lines)
1034 {
1035 int i;
1036
1037 for (i = 0; i < 16; i++) {
1038 if (irq_lines & (1 << i))
1039 free_irq(i);
1040 }
1041 }
1042
1043
1044
1045
1046
1047 static int
1048 check_wild_interrupts(void)
1049 {
1050 int i, mask;
1051 int wild_interrupts = 0;
1052 int irq_lines;
1053 unsigned long timeout;
1054 unsigned long flags;
1055
1056
1057 save_flags(flags); sti();
1058
1059 irq_lines = grab_all_interrupts(0);
1060
1061
1062
1063
1064
1065 timeout = jiffies+10;
1066 while (timeout >= jiffies)
1067 ;
1068
1069 cy_triggered = 0;
1070
1071 timeout = jiffies+10;
1072 while (timeout >= jiffies)
1073 ;
1074
1075 for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
1076 if ((cy_triggered & (1 << i)) &&
1077 (irq_lines & (1 << i))) {
1078 wild_interrupts |= mask;
1079 }
1080 }
1081 free_all_interrupts(irq_lines);
1082 restore_flags(flags);
1083 return wild_interrupts;
1084 }
1085
1086
1087
1088
1089
1090
1091 static int
1092 get_auto_irq(unsigned char *address)
1093 {
1094 unsigned long timeout;
1095 unsigned char *base_addr;
1096 int index;
1097
1098 index = 0;
1099 base_addr = address;
1100 intr_base_addr = address;
1101
1102
1103
1104
1105 cy_irq_triggered = 0;
1106 cli();
1107 base_addr[CyCAR<<index] = 0;
1108 write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_XMTR,index);
1109 base_addr[CySRER<<index] |= CyTxMpty;
1110 sti();
1111
1112 timeout = jiffies+2;
1113 while (timeout >= jiffies) {
1114 if (cy_irq_triggered)
1115 break;
1116 }
1117 return(cy_irq_triggered);
1118 }
1119
1120
1121
1122
1123
1124 static int
1125 do_auto_irq(unsigned char *address)
1126 {
1127 int irq_lines = 0;
1128 int irq_try_1 = 0, irq_try_2 = 0;
1129 int retries;
1130 unsigned long flags;
1131
1132
1133 save_flags(flags); sti();
1134
1135 cy_wild_int_mask = check_wild_interrupts();
1136
1137 irq_lines = grab_all_interrupts(cy_wild_int_mask);
1138
1139 for (retries = 0; retries < 5; retries++) {
1140 if (!irq_try_1)
1141 irq_try_1 = get_auto_irq(address);
1142 if (!irq_try_2)
1143 irq_try_2 = get_auto_irq(address);
1144 if (irq_try_1 && irq_try_2) {
1145 if (irq_try_1 == irq_try_2)
1146 break;
1147 irq_try_1 = irq_try_2 = 0;
1148 }
1149 }
1150 restore_flags(flags);
1151 free_all_interrupts(irq_lines);
1152 return (irq_try_1 == irq_try_2) ? irq_try_1 : 0;
1153 }
1154
1155
1156
1157
1158
1159 static int
1160 startup(struct cyclades_port * info)
1161 {
1162 unsigned long flags;
1163 unsigned char *base_addr;
1164 int card,chip,channel,index;
1165
1166 if (info->flags & ASYNC_INITIALIZED){
1167 return 0;
1168 }
1169
1170 if (!info->type){
1171 if (info->tty){
1172 set_bit(TTY_IO_ERROR, &info->tty->flags);
1173 }
1174 return 0;
1175 }
1176 if (!info->xmit_buf){
1177 info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL);
1178 if (!info->xmit_buf){
1179 return -ENOMEM;
1180 }
1181 }
1182
1183 config_setup(info);
1184
1185 card = info->card;
1186 channel = (info->line) - (cy_card[card].first_line);
1187 chip = channel>>2;
1188 channel &= 0x03;
1189 index = cy_card[card].bus_index;
1190 base_addr = (unsigned char*)
1191 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1192
1193 #ifdef SERIAL_DEBUG_OPEN
1194 printk("startup card %d, chip %d, channel %d, base_addr %lx",
1195 card, chip, channel, (long)base_addr);
1196 #endif
1197
1198 save_flags(flags); cli();
1199 base_addr[CyCAR<<index] = (u_char)channel;
1200
1201 base_addr[CyRTPR<<index] = (info->default_timeout
1202 ? info->default_timeout
1203 : 0x02);
1204
1205 write_cy_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
1206
1207 base_addr[CyCAR<<index] = (u_char)channel;
1208 base_addr[CyMSVR1<<index] = CyRTS;
1209
1210 base_addr[CyMSVR2<<index] = CyDTR;
1211
1212 #ifdef SERIAL_DEBUG_DTR
1213 printk("cyc: %d: raising DTR\n", __LINE__);
1214 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1215 #endif
1216
1217 base_addr[CySRER<<index] |= CyRxData;
1218 info->flags |= ASYNC_INITIALIZED;
1219
1220 if (info->tty){
1221 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1222 }
1223 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1224
1225 restore_flags(flags);
1226
1227 #ifdef SERIAL_DEBUG_OPEN
1228 printk(" done\n");
1229 #endif
1230 return 0;
1231 }
1232
1233 void
1234 start_xmit( struct cyclades_port *info )
1235 {
1236 unsigned long flags;
1237 unsigned char *base_addr;
1238 int card,chip,channel,index;
1239
1240 card = info->card;
1241 channel = (info->line) - (cy_card[card].first_line);
1242 chip = channel>>2;
1243 channel &= 0x03;
1244 index = cy_card[card].bus_index;
1245 base_addr = (unsigned char*)
1246 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1247
1248 save_flags(flags); cli();
1249 base_addr[CyCAR<<index] = channel;
1250 base_addr[CySRER<<index] |= CyTxMpty;
1251 restore_flags(flags);
1252 }
1253
1254
1255
1256
1257
1258 static void
1259 shutdown(struct cyclades_port * info)
1260 {
1261 unsigned long flags;
1262 unsigned char *base_addr;
1263 int card,chip,channel,index;
1264
1265 if (!(info->flags & ASYNC_INITIALIZED)){
1266
1267 return;
1268 }
1269
1270 card = info->card;
1271 channel = info->line - cy_card[card].first_line;
1272 chip = channel>>2;
1273 channel &= 0x03;
1274 index = cy_card[card].bus_index;
1275 base_addr = (unsigned char*)
1276 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1277
1278 #ifdef SERIAL_DEBUG_OPEN
1279 printk("shutdown card %d, chip %d, channel %d, base_addr %lx\n",
1280 card, chip, channel, (long)base_addr);
1281 #endif
1282
1283
1284
1285
1286
1287
1288
1289 save_flags(flags); cli();
1290 if (info->xmit_buf){
1291 free_page((unsigned long) info->xmit_buf);
1292 info->xmit_buf = 0;
1293 }
1294
1295 base_addr[CyCAR<<index] = (u_char)channel;
1296 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
1297 base_addr[CyMSVR1<<index] = ~CyRTS;
1298 base_addr[CyMSVR2<<index] = ~CyDTR;
1299 #ifdef SERIAL_DEBUG_DTR
1300 printk("cyc: %d: dropping DTR\n", __LINE__);
1301 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1302 #endif
1303 }
1304 write_cy_cmd(base_addr,CyCHAN_CTL|CyDIS_RCVR,index);
1305
1306
1307
1308 if (info->tty){
1309 set_bit(TTY_IO_ERROR, &info->tty->flags);
1310 }
1311 info->flags &= ~ASYNC_INITIALIZED;
1312 restore_flags(flags);
1313
1314 #ifdef SERIAL_DEBUG_OPEN
1315 printk(" done\n");
1316 #endif
1317 return;
1318 }
1319
1320
1321
1322
1323 static void
1324 config_setup(struct cyclades_port * info)
1325 {
1326 unsigned long flags;
1327 unsigned char *base_addr;
1328 int card,chip,channel,index;
1329 unsigned cflag;
1330 int i;
1331
1332 if (!info->tty || !info->tty->termios){
1333 return;
1334 }
1335 if (info->line == -1){
1336 return;
1337 }
1338 cflag = info->tty->termios->c_cflag;
1339
1340
1341 i = cflag & CBAUD;
1342 #ifdef CBAUDEX
1343
1344
1345
1346
1347
1348
1349
1350
1351 if (i & CBAUDEX) {
1352 if (i == B57600)
1353 i = 16;
1354 else if(i == B115200)
1355 i = 18;
1356 #ifdef B78600
1357 else if(i == B78600)
1358 i = 17;
1359 #endif
1360 else
1361 info->tty->termios->c_cflag &= ~CBAUDEX;
1362 }
1363 #endif
1364 if (i == 15) {
1365 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
1366 i += 1;
1367 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
1368 i += 3;
1369 }
1370 info->tbpr = baud_bpr[i];
1371 info->tco = baud_co[i];
1372 info->rbpr = baud_bpr[i];
1373 info->rco = baud_co[i];
1374 if (baud_table[i] == 134) {
1375 info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
1376
1377 } else if (baud_table[i]) {
1378 info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
1379
1380 } else {
1381 info->timeout = 0;
1382 }
1383
1384
1385
1386
1387
1388 info->cor5 = 0;
1389 info->cor4 = 0;
1390 info->cor3 = (info->default_threshold
1391 ? info->default_threshold
1392 : baud_cor3[i]);
1393 info->cor2 = CyETC;
1394 switch(cflag & CSIZE){
1395 case CS5:
1396 info->cor1 = Cy_5_BITS;
1397 break;
1398 case CS6:
1399 info->cor1 = Cy_6_BITS;
1400 break;
1401 case CS7:
1402 info->cor1 = Cy_7_BITS;
1403 break;
1404 case CS8:
1405 info->cor1 = Cy_8_BITS;
1406 break;
1407 }
1408 if(cflag & CSTOPB){
1409 info->cor1 |= Cy_2_STOP;
1410 }
1411 if (cflag & PARENB){
1412 if (cflag & PARODD){
1413 info->cor1 |= CyPARITY_O;
1414 }else{
1415 info->cor1 |= CyPARITY_E;
1416 }
1417 }else{
1418 info->cor1 |= CyPARITY_NONE;
1419 }
1420
1421
1422 if (cflag & CRTSCTS){
1423 info->flags |= ASYNC_CTS_FLOW;
1424 info->cor2 |= CyCtsAE;
1425 }else{
1426 info->flags &= ~ASYNC_CTS_FLOW;
1427 info->cor2 &= ~CyCtsAE;
1428 }
1429 if (cflag & CLOCAL)
1430 info->flags &= ~ASYNC_CHECK_CD;
1431 else
1432 info->flags |= ASYNC_CHECK_CD;
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 card = info->card;
1445 channel = (info->line) - (cy_card[card].first_line);
1446 chip = channel>>2;
1447 channel &= 0x03;
1448 index = cy_card[card].bus_index;
1449 base_addr = (unsigned char*)
1450 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1451
1452 save_flags(flags); cli();
1453 base_addr[CyCAR<<index] = (u_char)channel;
1454
1455
1456
1457 base_addr[CyTCOR<<index] = info->tco;
1458 base_addr[CyTBPR<<index] = info->tbpr;
1459 base_addr[CyRCOR<<index] = info->rco;
1460 base_addr[CyRBPR<<index] = info->rbpr;
1461
1462
1463
1464 base_addr[CySCHR1<<index] = START_CHAR(info->tty);
1465 base_addr[CySCHR2<<index] = STOP_CHAR(info->tty);
1466 base_addr[CyCOR1<<index] = info->cor1;
1467 base_addr[CyCOR2<<index] = info->cor2;
1468 base_addr[CyCOR3<<index] = info->cor3;
1469 base_addr[CyCOR4<<index] = info->cor4;
1470 base_addr[CyCOR5<<index] = info->cor5;
1471
1472 write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
1473
1474 base_addr[CyCAR<<index] = (u_char)channel;
1475
1476 base_addr[CyRTPR<<index] = (info->default_timeout
1477 ? info->default_timeout
1478 : 0x02);
1479
1480 if (C_CLOCAL(info->tty)) {
1481 base_addr[CySRER<<index] |= 0;
1482
1483 base_addr[CyMCOR1<<index] = 0x0;
1484
1485 base_addr[CyMCOR2<<index] = 0x0;
1486 } else {
1487 base_addr[CySRER<<index] |= CyMdmCh;
1488
1489 base_addr[CyMCOR1<<index] = CyDSR|CyCTS|CyRI|CyDCD;
1490
1491 base_addr[CyMCOR2<<index] = CyDSR|CyCTS|CyRI|CyDCD;
1492 }
1493
1494 if(i == 0){
1495 base_addr[CyMSVR2<<index] = ~CyDTR;
1496 #ifdef SERIAL_DEBUG_DTR
1497 printk("cyc: %d: dropping DTR\n", __LINE__);
1498 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1499 #endif
1500 }else{
1501 base_addr[CyMSVR2<<index] = CyDTR;
1502 #ifdef SERIAL_DEBUG_DTR
1503 printk("cyc: %d: raising DTR\n", __LINE__);
1504 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1505 #endif
1506 }
1507
1508 if (info->tty){
1509 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1510 }
1511
1512 restore_flags(flags);
1513
1514 }
1515
1516
1517 static void
1518 cy_put_char(struct tty_struct *tty, unsigned char ch)
1519 {
1520 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1521 unsigned long flags;
1522
1523 #ifdef SERIAL_DEBUG_IO
1524 printk("cy_put_char ttyC%d\n", info->line);
1525 #endif
1526
1527 if (serial_paranoia_check(info, tty->device, "cy_put_char"))
1528 return;
1529
1530 if (!tty || !info->xmit_buf)
1531 return;
1532
1533 save_flags(flags); cli();
1534 if (info->xmit_cnt >= PAGE_SIZE - 1) {
1535 restore_flags(flags);
1536 return;
1537 }
1538
1539 info->xmit_buf[info->xmit_head++] = ch;
1540 info->xmit_head &= PAGE_SIZE - 1;
1541 info->xmit_cnt++;
1542 restore_flags(flags);
1543 }
1544
1545
1546 static void
1547 cy_flush_chars(struct tty_struct *tty)
1548 {
1549 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1550 unsigned long flags;
1551 unsigned char *base_addr;
1552 int card,chip,channel,index;
1553
1554 #ifdef SERIAL_DEBUG_IO
1555 printk("cy_flush_chars ttyC%d\n", info->line);
1556 #endif
1557
1558 if (serial_paranoia_check(info, tty->device, "cy_flush_chars"))
1559 return;
1560
1561 if (info->xmit_cnt <= 0 || tty->stopped
1562 || tty->hw_stopped || !info->xmit_buf)
1563 return;
1564
1565 card = info->card;
1566 channel = info->line - cy_card[card].first_line;
1567 chip = channel>>2;
1568 channel &= 0x03;
1569 index = cy_card[card].bus_index;
1570 base_addr = (unsigned char*)
1571 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1572
1573 save_flags(flags); cli();
1574 base_addr[CyCAR<<index] = channel;
1575 base_addr[CySRER<<index] |= CyTxMpty;
1576 restore_flags(flags);
1577 }
1578
1579
1580
1581
1582
1583
1584
1585
1586 static int
1587 cy_write(struct tty_struct * tty, int from_user,
1588 const unsigned char *buf, int count)
1589 {
1590 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1591 unsigned long flags;
1592 int c, total = 0;
1593
1594 #ifdef SERIAL_DEBUG_IO
1595 printk("cy_write ttyC%d\n", info->line);
1596 #endif
1597
1598 if (serial_paranoia_check(info, tty->device, "cy_write")){
1599 return 0;
1600 }
1601
1602 if (!tty || !info->xmit_buf || !tmp_buf){
1603 return 0;
1604 }
1605
1606 while (1) {
1607 save_flags(flags); cli();
1608 c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1609 SERIAL_XMIT_SIZE - info->xmit_head));
1610 if (c <= 0){
1611 restore_flags(flags);
1612 break;
1613 }
1614
1615 if (from_user) {
1616 down(&tmp_buf_sem);
1617 memcpy_fromfs(tmp_buf, buf, c);
1618 c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1619 SERIAL_XMIT_SIZE - info->xmit_head));
1620 memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
1621 up(&tmp_buf_sem);
1622 } else
1623 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1624 info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1625 info->xmit_cnt += c;
1626 restore_flags(flags);
1627 buf += c;
1628 count -= c;
1629 total += c;
1630 }
1631
1632
1633 if (info->xmit_cnt
1634 && !tty->stopped
1635 && !tty->hw_stopped ) {
1636 start_xmit(info);
1637 }
1638 return total;
1639 }
1640
1641
1642 static int
1643 cy_write_room(struct tty_struct *tty)
1644 {
1645 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1646 int ret;
1647
1648 #ifdef SERIAL_DEBUG_IO
1649 printk("cy_write_room ttyC%d\n", info->line);
1650 #endif
1651
1652 if (serial_paranoia_check(info, tty->device, "cy_write_room"))
1653 return 0;
1654 ret = PAGE_SIZE - info->xmit_cnt - 1;
1655 if (ret < 0)
1656 ret = 0;
1657 return ret;
1658 }
1659
1660
1661 static int
1662 cy_chars_in_buffer(struct tty_struct *tty)
1663 {
1664 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1665
1666 #ifdef SERIAL_DEBUG_IO
1667 printk("cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt);
1668 #endif
1669
1670 if (serial_paranoia_check(info, tty->device, "cy_chars_in_buffer"))
1671 return 0;
1672
1673 return info->xmit_cnt;
1674 }
1675
1676
1677 static void
1678 cy_flush_buffer(struct tty_struct *tty)
1679 {
1680 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1681 unsigned long flags;
1682
1683 #ifdef SERIAL_DEBUG_IO
1684 printk("cy_flush_buffer ttyC%d\n", info->line);
1685 #endif
1686
1687 if (serial_paranoia_check(info, tty->device, "cy_flush_buffer"))
1688 return;
1689 save_flags(flags); cli();
1690 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1691 restore_flags(flags);
1692 wake_up_interruptible(&tty->write_wait);
1693 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
1694 && tty->ldisc.write_wakeup)
1695 (tty->ldisc.write_wakeup)(tty);
1696 }
1697
1698
1699
1700
1701
1702
1703 static void
1704 cy_throttle(struct tty_struct * tty)
1705 {
1706 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1707 unsigned long flags;
1708 unsigned char *base_addr;
1709 int card,chip,channel,index;
1710
1711 #ifdef SERIAL_DEBUG_THROTTLE
1712 char buf[64];
1713
1714 printk("throttle %s: %d....\n", _tty_name(tty, buf),
1715 tty->ldisc.chars_in_buffer(tty));
1716 printk("cy_throttle ttyC%d\n", info->line);
1717 #endif
1718
1719 if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){
1720 return;
1721 }
1722
1723 if (I_IXOFF(tty)) {
1724 info->x_char = STOP_CHAR(tty);
1725
1726 }
1727
1728 card = info->card;
1729 channel = info->line - cy_card[card].first_line;
1730 chip = channel>>2;
1731 channel &= 0x03;
1732 index = cy_card[card].bus_index;
1733 base_addr = (unsigned char*)
1734 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1735
1736 save_flags(flags); cli();
1737 base_addr[CyCAR<<index] = (u_char)channel;
1738 base_addr[CyMSVR1<<index] = ~CyRTS;
1739 restore_flags(flags);
1740
1741 return;
1742 }
1743
1744
1745 static void
1746 cy_unthrottle(struct tty_struct * tty)
1747 {
1748 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1749 unsigned long flags;
1750 unsigned char *base_addr;
1751 int card,chip,channel,index;
1752
1753 #ifdef SERIAL_DEBUG_THROTTLE
1754 char buf[64];
1755
1756 printk("throttle %s: %d....\n", _tty_name(tty, buf),
1757 tty->ldisc.chars_in_buffer(tty));
1758 printk("cy_unthrottle ttyC%d\n", info->line);
1759 #endif
1760
1761 if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){
1762 return;
1763 }
1764
1765 if (I_IXOFF(tty)) {
1766 info->x_char = START_CHAR(tty);
1767
1768 }
1769
1770 card = info->card;
1771 channel = info->line - cy_card[card].first_line;
1772 chip = channel>>2;
1773 channel &= 0x03;
1774 index = cy_card[card].bus_index;
1775 base_addr = (unsigned char*)
1776 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1777
1778 save_flags(flags); cli();
1779 base_addr[CyCAR<<index] = (u_char)channel;
1780 base_addr[CyMSVR1<<index] = CyRTS;
1781 restore_flags(flags);
1782
1783 return;
1784 }
1785
1786 static int
1787 get_serial_info(struct cyclades_port * info,
1788 struct serial_struct * retinfo)
1789 {
1790 struct serial_struct tmp;
1791 struct cyclades_card *cinfo = &cy_card[info->card];
1792
1793
1794 if (!retinfo)
1795 return -EFAULT;
1796 memset(&tmp, 0, sizeof(tmp));
1797 tmp.type = info->type;
1798 tmp.line = info->line;
1799 tmp.port = info->card * 0x100 + info->line - cinfo->first_line;
1800 tmp.irq = cinfo->irq;
1801 tmp.flags = info->flags;
1802 tmp.baud_base = 0;
1803 tmp.close_delay = info->close_delay;
1804 tmp.custom_divisor = 0;
1805 tmp.hub6 = 0;
1806 memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
1807 return 0;
1808 }
1809
1810 static int
1811 set_serial_info(struct cyclades_port * info,
1812 struct serial_struct * new_info)
1813 {
1814 struct serial_struct new_serial;
1815 struct cyclades_port old_info;
1816
1817
1818 if (!new_info)
1819 return -EFAULT;
1820 memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
1821 old_info = *info;
1822
1823 if (!suser()) {
1824 if ((new_serial.close_delay != info->close_delay) ||
1825 ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
1826 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
1827 return -EPERM;
1828 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1829 (new_serial.flags & ASYNC_USR_MASK));
1830 goto check_and_exit;
1831 }
1832
1833
1834
1835
1836
1837
1838
1839 info->flags = ((info->flags & ~ASYNC_FLAGS) |
1840 (new_serial.flags & ASYNC_FLAGS));
1841 info->close_delay = new_serial.close_delay;
1842
1843
1844 check_and_exit:
1845 if (info->flags & ASYNC_INITIALIZED){
1846 config_setup(info);
1847 return 0;
1848 }else{
1849 return startup(info);
1850 }
1851 }
1852
1853 static int
1854 get_modem_info(struct cyclades_port * info, unsigned int *value)
1855 {
1856 int card,chip,channel,index;
1857 unsigned char *base_addr;
1858 unsigned long flags;
1859 unsigned char status;
1860 unsigned int result;
1861
1862 card = info->card;
1863 channel = (info->line) - (cy_card[card].first_line);
1864 chip = channel>>2;
1865 channel &= 0x03;
1866 index = cy_card[card].bus_index;
1867 base_addr = (unsigned char*)
1868 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1869
1870 save_flags(flags); cli();
1871 base_addr[CyCAR<<index] = (u_char)channel;
1872 status = base_addr[CyMSVR1<<index];
1873 status |= base_addr[CyMSVR2<<index];
1874 restore_flags(flags);
1875
1876 result = ((status & CyRTS) ? TIOCM_RTS : 0)
1877 | ((status & CyDTR) ? TIOCM_DTR : 0)
1878 | ((status & CyDCD) ? TIOCM_CAR : 0)
1879 | ((status & CyRI) ? TIOCM_RNG : 0)
1880 | ((status & CyDSR) ? TIOCM_DSR : 0)
1881 | ((status & CyCTS) ? TIOCM_CTS : 0);
1882 put_fs_long(result,(unsigned long *) value);
1883 return 0;
1884 }
1885
1886 static int
1887 set_modem_info(struct cyclades_port * info, unsigned int cmd,
1888 unsigned int *value)
1889 {
1890 int card,chip,channel,index;
1891 unsigned char *base_addr;
1892 unsigned long flags;
1893 unsigned int arg = get_fs_long((unsigned long *) value);
1894
1895 card = info->card;
1896 channel = (info->line) - (cy_card[card].first_line);
1897 chip = channel>>2;
1898 channel &= 0x03;
1899 index = cy_card[card].bus_index;
1900 base_addr = (unsigned char*)
1901 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
1902
1903 switch (cmd) {
1904 case TIOCMBIS:
1905 if (arg & TIOCM_RTS){
1906 save_flags(flags); cli();
1907 base_addr[CyCAR<<index] = (u_char)channel;
1908 base_addr[CyMSVR1<<index] = CyRTS;
1909 restore_flags(flags);
1910 }
1911 if (arg & TIOCM_DTR){
1912 save_flags(flags); cli();
1913 base_addr[CyCAR<<index] = (u_char)channel;
1914
1915 base_addr[CyMSVR2<<index] = CyDTR;
1916 #ifdef SERIAL_DEBUG_DTR
1917 printk("cyc: %d: raising DTR\n", __LINE__);
1918 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1919 #endif
1920 restore_flags(flags);
1921 }
1922 break;
1923 case TIOCMBIC:
1924 if (arg & TIOCM_RTS){
1925 save_flags(flags); cli();
1926 base_addr[CyCAR<<index] = (u_char)channel;
1927 base_addr[CyMSVR1<<index] = ~CyRTS;
1928 restore_flags(flags);
1929 }
1930 if (arg & TIOCM_DTR){
1931 save_flags(flags); cli();
1932 base_addr[CyCAR<<index] = (u_char)channel;
1933
1934 base_addr[CyMSVR2<<index] = ~CyDTR;
1935 #ifdef SERIAL_DEBUG_DTR
1936 printk("cyc: %d: dropping DTR\n", __LINE__);
1937 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1938 #endif
1939 restore_flags(flags);
1940 }
1941 break;
1942 case TIOCMSET:
1943 if (arg & TIOCM_RTS){
1944 save_flags(flags); cli();
1945 base_addr[CyCAR<<index] = (u_char)channel;
1946 base_addr[CyMSVR1<<index] = CyRTS;
1947 restore_flags(flags);
1948 }else{
1949 save_flags(flags); cli();
1950 base_addr[CyCAR<<index] = (u_char)channel;
1951 base_addr[CyMSVR1<<index] = ~CyRTS;
1952 restore_flags(flags);
1953 }
1954 if (arg & TIOCM_DTR){
1955 save_flags(flags); cli();
1956 base_addr[CyCAR<<index] = (u_char)channel;
1957
1958 base_addr[CyMSVR2<<index] = CyDTR;
1959 #ifdef SERIAL_DEBUG_DTR
1960 printk("cyc: %d: raising DTR\n", __LINE__);
1961 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1962 #endif
1963 restore_flags(flags);
1964 }else{
1965 save_flags(flags); cli();
1966 base_addr[CyCAR<<index] = (u_char)channel;
1967
1968 base_addr[CyMSVR2<<index] = ~CyDTR;
1969 #ifdef SERIAL_DEBUG_DTR
1970 printk("cyc: %d: dropping DTR\n", __LINE__);
1971 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
1972 #endif
1973 restore_flags(flags);
1974 }
1975 break;
1976 default:
1977 return -EINVAL;
1978 }
1979 return 0;
1980 }
1981
1982 static void
1983 send_break( struct cyclades_port * info, int duration)
1984 {
1985
1986
1987 info->x_break = duration;
1988 if (!info->xmit_cnt ) {
1989 start_xmit(info);
1990 }
1991 }
1992
1993 static int
1994 get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
1995 {
1996
1997 memcpy_tofs(mon, &info->mon, sizeof(struct cyclades_monitor));
1998 info->mon.int_count = 0;
1999 info->mon.char_count = 0;
2000 info->mon.char_max = 0;
2001 info->mon.char_last = 0;
2002 return 0;
2003 }
2004
2005 static int
2006 set_threshold(struct cyclades_port * info, unsigned long value)
2007 {
2008 unsigned char *base_addr;
2009 int card,channel,chip,index;
2010
2011 card = info->card;
2012 channel = info->line - cy_card[card].first_line;
2013 chip = channel>>2;
2014 channel &= 0x03;
2015 index = cy_card[card].bus_index;
2016 base_addr = (unsigned char*)
2017 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
2018
2019 info->cor3 &= ~CyREC_FIFO;
2020 info->cor3 |= value & CyREC_FIFO;
2021 base_addr[CyCOR3<<index] = info->cor3;
2022 write_cy_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
2023 return 0;
2024 }
2025
2026 static int
2027 get_threshold(struct cyclades_port * info, unsigned long *value)
2028 {
2029 unsigned char *base_addr;
2030 int card,channel,chip,index;
2031 unsigned long tmp;
2032
2033 card = info->card;
2034 channel = info->line - cy_card[card].first_line;
2035 chip = channel>>2;
2036 channel &= 0x03;
2037 index = cy_card[card].bus_index;
2038 base_addr = (unsigned char*)
2039 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
2040
2041 tmp = base_addr[CyCOR3<<index] & CyREC_FIFO;
2042 put_fs_long(tmp,value);
2043 return 0;
2044 }
2045
2046 static int
2047 set_default_threshold(struct cyclades_port * info, unsigned long value)
2048 {
2049 info->default_threshold = value & 0x0f;
2050 return 0;
2051 }
2052
2053 static int
2054 get_default_threshold(struct cyclades_port * info, unsigned long *value)
2055 {
2056 put_fs_long(info->default_threshold,value);
2057 return 0;
2058 }
2059
2060 static int
2061 set_timeout(struct cyclades_port * info, unsigned long value)
2062 {
2063 unsigned char *base_addr;
2064 int card,channel,chip,index;
2065
2066 card = info->card;
2067 channel = info->line - cy_card[card].first_line;
2068 chip = channel>>2;
2069 channel &= 0x03;
2070 index = cy_card[card].bus_index;
2071 base_addr = (unsigned char*)
2072 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
2073
2074 base_addr[CyRTPR<<index] = value & 0xff;
2075 return 0;
2076 }
2077
2078 static int
2079 get_timeout(struct cyclades_port * info, unsigned long *value)
2080 {
2081 unsigned char *base_addr;
2082 int card,channel,chip,index;
2083 unsigned long tmp;
2084
2085 card = info->card;
2086 channel = info->line - cy_card[card].first_line;
2087 chip = channel>>2;
2088 channel &= 0x03;
2089 index = cy_card[card].bus_index;
2090 base_addr = (unsigned char*)
2091 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
2092
2093 tmp = base_addr[CyRTPR<<index];
2094 put_fs_long(tmp,value);
2095 return 0;
2096 }
2097
2098 static int
2099 set_default_timeout(struct cyclades_port * info, unsigned long value)
2100 {
2101 info->default_timeout = value & 0xff;
2102 return 0;
2103 }
2104
2105 static int
2106 get_default_timeout(struct cyclades_port * info, unsigned long *value)
2107 {
2108 put_fs_long(info->default_timeout,value);
2109 return 0;
2110 }
2111
2112 static int
2113 cy_ioctl(struct tty_struct *tty, struct file * file,
2114 unsigned int cmd, unsigned long arg)
2115 {
2116 int error;
2117 struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
2118 int ret_val = 0;
2119
2120 #ifdef SERIAL_DEBUG_OTHER
2121 printk("cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg);
2122 #endif
2123
2124 switch (cmd) {
2125 case CYGETMON:
2126 error = verify_area(VERIFY_WRITE, (void *) arg
2127 ,sizeof(struct cyclades_monitor));
2128 if (error){
2129 ret_val = error;
2130 break;
2131 }
2132 ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
2133 break;
2134 case CYGETTHRESH:
2135 error = verify_area(VERIFY_WRITE, (void *) arg
2136 ,sizeof(unsigned long));
2137 if (error){
2138 ret_val = error;
2139 break;
2140 }
2141 ret_val = get_threshold(info, (unsigned long *)arg);
2142 break;
2143 case CYSETTHRESH:
2144 ret_val = set_threshold(info, (unsigned long)arg);
2145 break;
2146 case CYGETDEFTHRESH:
2147 error = verify_area(VERIFY_WRITE, (void *) arg
2148 ,sizeof(unsigned long));
2149 if (error){
2150 ret_val = error;
2151 break;
2152 }
2153 ret_val = get_default_threshold(info, (unsigned long *)arg);
2154 break;
2155 case CYSETDEFTHRESH:
2156 ret_val = set_default_threshold(info, (unsigned long)arg);
2157 break;
2158 case CYGETTIMEOUT:
2159 error = verify_area(VERIFY_WRITE, (void *) arg
2160 ,sizeof(unsigned long));
2161 if (error){
2162 ret_val = error;
2163 break;
2164 }
2165 ret_val = get_timeout(info, (unsigned long *)arg);
2166 break;
2167 case CYSETTIMEOUT:
2168 ret_val = set_timeout(info, (unsigned long)arg);
2169 break;
2170 case CYGETDEFTIMEOUT:
2171 error = verify_area(VERIFY_WRITE, (void *) arg
2172 ,sizeof(unsigned long));
2173 if (error){
2174 ret_val = error;
2175 break;
2176 }
2177 ret_val = get_default_timeout(info, (unsigned long *)arg);
2178 break;
2179 case CYSETDEFTIMEOUT:
2180 ret_val = set_default_timeout(info, (unsigned long)arg);
2181 break;
2182 case TCSBRK:
2183 ret_val = tty_check_change(tty);
2184 if (ret_val)
2185 return ret_val;
2186 tty_wait_until_sent(tty,0);
2187 if (!arg)
2188 send_break(info, HZ/4);
2189 break;
2190 case TCSBRKP:
2191 ret_val = tty_check_change(tty);
2192 if (ret_val)
2193 return ret_val;
2194 tty_wait_until_sent(tty,0);
2195 send_break(info, arg ? arg*(HZ/10) : HZ/4);
2196 break;
2197 case TIOCMBIS:
2198 case TIOCMBIC:
2199 case TIOCMSET:
2200 ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
2201 break;
2202
2203
2204 case TIOCGSOFTCAR:
2205 error = verify_area(VERIFY_WRITE, (void *) arg
2206 ,sizeof(unsigned int *));
2207 if (error){
2208 ret_val = error;
2209 break;
2210 }
2211 put_fs_long(C_CLOCAL(tty) ? 1 : 0,
2212 (unsigned long *) arg);
2213 break;
2214 case TIOCSSOFTCAR:
2215 arg = get_fs_long((unsigned long *) arg);
2216 tty->termios->c_cflag =
2217 ((tty->termios->c_cflag & ~CLOCAL) |
2218 (arg ? CLOCAL : 0));
2219 break;
2220 case TIOCMGET:
2221 error = verify_area(VERIFY_WRITE, (void *) arg
2222 ,sizeof(unsigned int *));
2223 if (error){
2224 ret_val = error;
2225 break;
2226 }
2227 ret_val = get_modem_info(info, (unsigned int *) arg);
2228 break;
2229 case TIOCGSERIAL:
2230 error = verify_area(VERIFY_WRITE, (void *) arg
2231 ,sizeof(struct serial_struct));
2232 if (error){
2233 ret_val = error;
2234 break;
2235 }
2236 ret_val = get_serial_info(info,
2237 (struct serial_struct *) arg);
2238 break;
2239 case TIOCSSERIAL:
2240 ret_val = set_serial_info(info,
2241 (struct serial_struct *) arg);
2242 break;
2243 default:
2244 ret_val = -ENOIOCTLCMD;
2245 }
2246
2247 #ifdef SERIAL_DEBUG_OTHER
2248 printk("cy_ioctl done\n");
2249 #endif
2250
2251 return ret_val;
2252 }
2253
2254
2255
2256
2257 static void
2258 cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
2259 {
2260 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
2261
2262 #ifdef SERIAL_DEBUG_OTHER
2263 printk("cy_set_termios ttyC%d\n", info->line);
2264 #endif
2265
2266 if (tty->termios->c_cflag == old_termios->c_cflag)
2267 return;
2268 config_setup(info);
2269
2270 if ((old_termios->c_cflag & CRTSCTS) &&
2271 !(tty->termios->c_cflag & CRTSCTS)) {
2272 tty->stopped = 0;
2273 cy_start(tty);
2274 }
2275 #ifdef tytso_patch_94Nov25_1726
2276 if (!(old_termios->c_cflag & CLOCAL) &&
2277 (tty->termios->c_cflag & CLOCAL))
2278 wake_up_interruptible(&info->open_wait);
2279 #endif
2280
2281 return;
2282 }
2283
2284
2285 static void
2286 cy_close(struct tty_struct * tty, struct file * filp)
2287 {
2288 struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
2289
2290
2291 #ifdef SERIAL_DEBUG_OTHER
2292 printk("cy_close ttyC%d\n", info->line);
2293 #endif
2294
2295 if (!info
2296 || serial_paranoia_check(info, tty->device, "cy_close")){
2297 return;
2298 }
2299 #ifdef SERIAL_DEBUG_OPEN
2300 printk("cy_close ttyC%d, count = %d\n", info->line, info->count);
2301 #endif
2302
2303 if ((tty->count == 1) && (info->count != 1)) {
2304
2305
2306
2307
2308
2309
2310
2311 printk("cy_close: bad serial port count; tty->count is 1, "
2312 "info->count is %d\n", info->count);
2313 info->count = 1;
2314 }
2315 #ifdef SERIAL_DEBUG_COUNT
2316 printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);
2317 #endif
2318 if (--info->count < 0) {
2319 #ifdef SERIAL_DEBUG_COUNT
2320 printk("cyc: %d: setting count to 0\n", __LINE__);
2321 #endif
2322 info->count = 0;
2323 }
2324 if (info->count)
2325 return;
2326 info->flags |= ASYNC_CLOSING;
2327
2328
2329
2330
2331 if (info->flags & ASYNC_NORMAL_ACTIVE)
2332 info->normal_termios = *tty->termios;
2333 if (info->flags & ASYNC_CALLOUT_ACTIVE)
2334 info->callout_termios = *tty->termios;
2335 if (info->flags & ASYNC_INITIALIZED)
2336 tty_wait_until_sent(tty, 3000);
2337 shutdown(info);
2338 if (tty->driver.flush_buffer)
2339 tty->driver.flush_buffer(tty);
2340 if (tty->ldisc.flush_buffer)
2341 tty->ldisc.flush_buffer(tty);
2342 info->event = 0;
2343 info->tty = 0;
2344 if (tty->ldisc.num != ldiscs[N_TTY].num) {
2345 if (tty->ldisc.close)
2346 (tty->ldisc.close)(tty);
2347 tty->ldisc = ldiscs[N_TTY];
2348 tty->termios->c_line = N_TTY;
2349 if (tty->ldisc.open)
2350 (tty->ldisc.open)(tty);
2351 }
2352 if (info->blocked_open) {
2353 if (info->close_delay) {
2354 current->state = TASK_INTERRUPTIBLE;
2355 current->timeout = jiffies + info->close_delay;
2356 schedule();
2357 }
2358 wake_up_interruptible(&info->open_wait);
2359 }
2360 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
2361 ASYNC_CLOSING);
2362 wake_up_interruptible(&info->close_wait);
2363
2364 #ifdef SERIAL_DEBUG_OTHER
2365 printk("cy_close done\n");
2366 #endif
2367
2368 return;
2369 }
2370
2371
2372
2373
2374 void
2375 cy_hangup(struct tty_struct *tty)
2376 {
2377 struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
2378
2379 #ifdef SERIAL_DEBUG_OTHER
2380 printk("cy_hangup ttyC%d\n", info->line);
2381 #endif
2382
2383 if (serial_paranoia_check(info, tty->device, "cy_hangup"))
2384 return;
2385
2386 shutdown(info);
2387 #if 0
2388 info->event = 0;
2389 info->count = 0;
2390 #ifdef SERIAL_DEBUG_COUNT
2391 printk("cyc: %d: setting count to 0\n", __LINE__);
2392 #endif
2393 info->tty = 0;
2394 #endif
2395 info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
2396 wake_up_interruptible(&info->open_wait);
2397 }
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407 static int
2408 block_til_ready(struct tty_struct *tty, struct file * filp,
2409 struct cyclades_port *info)
2410 {
2411 struct wait_queue wait = { current, NULL };
2412 struct cyclades_card *cinfo;
2413 unsigned long flags;
2414 int chip, channel,index;
2415 int retval;
2416 char *base_addr;
2417
2418
2419
2420
2421
2422 if (info->flags & ASYNC_CLOSING) {
2423 interruptible_sleep_on(&info->close_wait);
2424 if (info->flags & ASYNC_HUP_NOTIFY){
2425 return -EAGAIN;
2426 }else{
2427 return -ERESTARTSYS;
2428 }
2429 }
2430
2431
2432
2433
2434
2435 if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
2436 if (info->flags & ASYNC_NORMAL_ACTIVE){
2437 return -EBUSY;
2438 }
2439 if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2440 (info->flags & ASYNC_SESSION_LOCKOUT) &&
2441 (info->session != current->session)){
2442 return -EBUSY;
2443 }
2444 if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2445 (info->flags & ASYNC_PGRP_LOCKOUT) &&
2446 (info->pgrp != current->pgrp)){
2447 return -EBUSY;
2448 }
2449 info->flags |= ASYNC_CALLOUT_ACTIVE;
2450 return 0;
2451 }
2452
2453
2454
2455
2456
2457 if (filp->f_flags & O_NONBLOCK) {
2458 if (info->flags & ASYNC_CALLOUT_ACTIVE){
2459 return -EBUSY;
2460 }
2461 info->flags |= ASYNC_NORMAL_ACTIVE;
2462 return 0;
2463 }
2464
2465
2466
2467
2468
2469
2470
2471
2472 retval = 0;
2473 add_wait_queue(&info->open_wait, &wait);
2474 #ifdef SERIAL_DEBUG_OPEN
2475 printk("block_til_ready before block: ttyC%d, count = %d\n",
2476 info->line, info->count);
2477 #endif
2478 info->count--;
2479 #ifdef SERIAL_DEBUG_COUNT
2480 printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
2481 #endif
2482 info->blocked_open++;
2483
2484 cinfo = &cy_card[info->card];
2485 channel = info->line - cinfo->first_line;
2486 chip = channel>>2;
2487 channel &= 0x03;
2488 index = cinfo->bus_index;
2489 base_addr = (char *) (cinfo->base_addr + (cy_chip_offset[chip]<<index));
2490
2491 while (1) {
2492 save_flags(flags); cli();
2493 if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
2494 base_addr[CyCAR<<index] = (u_char)channel;
2495 base_addr[CyMSVR1<<index] = CyRTS;
2496
2497 base_addr[CyMSVR2<<index] = CyDTR;
2498 #ifdef SERIAL_DEBUG_DTR
2499 printk("cyc: %d: raising DTR\n", __LINE__);
2500 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1<<index], base_addr[CyMSVR2<<index]);
2501 #endif
2502 }
2503 restore_flags(flags);
2504 current->state = TASK_INTERRUPTIBLE;
2505 if (tty_hung_up_p(filp)
2506 || !(info->flags & ASYNC_INITIALIZED) ){
2507 if (info->flags & ASYNC_HUP_NOTIFY) {
2508 retval = -EAGAIN;
2509 }else{
2510 retval = -ERESTARTSYS;
2511 }
2512 break;
2513 }
2514 save_flags(flags); cli();
2515 base_addr[CyCAR<<index] = (u_char)channel;
2516
2517 if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
2518 && !(info->flags & ASYNC_CLOSING)
2519 && (C_CLOCAL(tty)
2520 || (base_addr[CyMSVR1<<index] & CyDCD))) {
2521 restore_flags(flags);
2522 break;
2523 }
2524 restore_flags(flags);
2525 if (current->signal & ~current->blocked) {
2526 retval = -ERESTARTSYS;
2527 break;
2528 }
2529 #ifdef SERIAL_DEBUG_OPEN
2530 printk("block_til_ready blocking: ttyC%d, count = %d\n",
2531 info->line, info->count);
2532 #endif
2533 schedule();
2534 }
2535 current->state = TASK_RUNNING;
2536 remove_wait_queue(&info->open_wait, &wait);
2537 if (!tty_hung_up_p(filp)){
2538 info->count++;
2539 #ifdef SERIAL_DEBUG_COUNT
2540 printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
2541 #endif
2542 }
2543 info->blocked_open--;
2544 #ifdef SERIAL_DEBUG_OPEN
2545 printk("block_til_ready after blocking: ttyC%d, count = %d\n",
2546 info->line, info->count);
2547 #endif
2548 if (retval)
2549 return retval;
2550 info->flags |= ASYNC_NORMAL_ACTIVE;
2551 return 0;
2552 }
2553
2554
2555
2556
2557
2558 int
2559 cy_open(struct tty_struct *tty, struct file * filp)
2560 {
2561 struct cyclades_port *info;
2562 int retval, line;
2563
2564
2565 line = MINOR(tty->device) - tty->driver.minor_start;
2566 if ((line < 0) || (NR_PORTS <= line)){
2567 return -ENODEV;
2568 }
2569 info = &cy_port[line];
2570 if (info->line < 0){
2571 return -ENODEV;
2572 }
2573 #ifdef SERIAL_DEBUG_OTHER
2574 printk("cy_open ttyC%d\n", info->line);
2575 #endif
2576 if (serial_paranoia_check(info, tty->device, "cy_open")){
2577 return -ENODEV;
2578 }
2579 #ifdef SERIAL_DEBUG_OPEN
2580 printk("cy_open ttyC%d, count = %d\n", info->line, info->count);
2581 #endif
2582 info->count++;
2583 #ifdef SERIAL_DEBUG_COUNT
2584 printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
2585 #endif
2586 tty->driver_data = info;
2587 info->tty = tty;
2588
2589 if (!tmp_buf) {
2590 tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
2591 if (!tmp_buf){
2592 return -ENOMEM;
2593 }
2594 }
2595
2596 if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
2597 if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
2598 *tty->termios = info->normal_termios;
2599 else
2600 *tty->termios = info->callout_termios;
2601 }
2602
2603
2604
2605 retval = startup(info);
2606 if (retval){
2607 return retval;
2608 }
2609
2610 retval = block_til_ready(tty, filp, info);
2611 if (retval) {
2612 #ifdef SERIAL_DEBUG_OPEN
2613 printk("cy_open returning after block_til_ready with %d\n",
2614 retval);
2615 #endif
2616 return retval;
2617 }
2618
2619 info->session = current->session;
2620 info->pgrp = current->pgrp;
2621
2622 #ifdef SERIAL_DEBUG_OPEN
2623 printk("cy_open done\n");
2624 #endif
2625 return 0;
2626 }
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643 static void
2644 show_version(void)
2645 {
2646 printk("Cyclom driver %s\n",rcsid);
2647 }
2648
2649
2650
2651 int
2652 cy_init_card(unsigned char *true_base_addr,int index)
2653 {
2654 unsigned int chip_number;
2655 unsigned char* base_addr;
2656
2657 true_base_addr[Cy_HwReset<<index] = 0;
2658 true_base_addr[Cy_ClrIntr<<index] = 0;
2659 udelay(500L);
2660
2661 for(chip_number=0; chip_number<CyMaxChipsPerCard; chip_number++){
2662 base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
2663 udelay(1000L);
2664 if(base_addr[CyCCR<<index] != 0x00){
2665
2666
2667
2668
2669 return chip_number;
2670 }
2671
2672 base_addr[CyGFRCR<<index] = 0;
2673 udelay(10L);
2674
2675
2676
2677
2678
2679
2680
2681 if (chip_number == 4
2682 && *(true_base_addr + cy_chip_offset[0] + CyGFRCR) == 0){
2683 return chip_number;
2684 }
2685
2686 base_addr[CyCCR<<index] = CyCHIP_RESET;
2687 udelay(1000L);
2688
2689 if(base_addr[CyGFRCR<<index] == 0x00){
2690
2691
2692
2693
2694 return chip_number;
2695 }
2696 if((0xf0 & base_addr[CyGFRCR<<index]) != 0x40){
2697
2698
2699
2700
2701 return chip_number;
2702 }
2703 base_addr[CyGCR<<index] = CyCH0_SERIAL;
2704 base_addr[CyPPR<<index] = 244;
2705
2706
2707
2708
2709
2710
2711 }
2712
2713 return chip_number;
2714 }
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732 int
2733 cy_init(void)
2734 {
2735 struct cyclades_port *info;
2736 struct cyclades_card *cinfo;
2737 int board,port,i;
2738
2739 scrn[1] = '\0';
2740 show_version();
2741
2742
2743
2744 memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
2745 cy_serial_driver.magic = TTY_DRIVER_MAGIC;
2746 cy_serial_driver.name = "ttyC";
2747 cy_serial_driver.major = CYCLADES_MAJOR;
2748 cy_serial_driver.minor_start = 32;
2749 cy_serial_driver.num = NR_PORTS;
2750 cy_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
2751 cy_serial_driver.subtype = SERIAL_TYPE_NORMAL;
2752 cy_serial_driver.init_termios = tty_std_termios;
2753 cy_serial_driver.init_termios.c_cflag =
2754 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2755 cy_serial_driver.flags = TTY_DRIVER_REAL_RAW;
2756 cy_serial_driver.refcount = &serial_refcount;
2757 cy_serial_driver.table = serial_table;
2758 cy_serial_driver.termios = serial_termios;
2759 cy_serial_driver.termios_locked = serial_termios_locked;
2760 cy_serial_driver.open = cy_open;
2761 cy_serial_driver.close = cy_close;
2762 cy_serial_driver.write = cy_write;
2763 cy_serial_driver.put_char = cy_put_char;
2764 cy_serial_driver.flush_chars = cy_flush_chars;
2765 cy_serial_driver.write_room = cy_write_room;
2766 cy_serial_driver.chars_in_buffer = cy_chars_in_buffer;
2767 cy_serial_driver.flush_buffer = cy_flush_buffer;
2768 cy_serial_driver.ioctl = cy_ioctl;
2769 cy_serial_driver.throttle = cy_throttle;
2770 cy_serial_driver.unthrottle = cy_unthrottle;
2771 cy_serial_driver.set_termios = cy_set_termios;
2772 cy_serial_driver.stop = cy_stop;
2773 cy_serial_driver.start = cy_start;
2774 cy_serial_driver.hangup = cy_hangup;
2775
2776
2777
2778
2779
2780 cy_callout_driver = cy_serial_driver;
2781 cy_callout_driver.name = "cub";
2782 cy_callout_driver.major = CYCLADESAUX_MAJOR;
2783 cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
2784
2785 if (tty_register_driver(&cy_serial_driver))
2786 panic("Couldn't register Cyclom serial driver\n");
2787 if (tty_register_driver(&cy_callout_driver))
2788 panic("Couldn't register Cyclom callout driver\n");
2789
2790 bh_base[CYCLADES_BH].routine = do_cyclades_bh;
2791 enable_bh(CYCLADES_BH);
2792
2793 for (i = 0; i < 16; i++) {
2794 IRQ_cards[i] = 0;
2795 }
2796
2797 for (i = 0; i < NR_CARDS; i++) {
2798
2799 cy_card[i].base_addr = 0;
2800 }
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810 cy_isa_nboard = cy_detect_isa();
2811
2812
2813 cy_pci_nboard = cy_detect_pci();
2814
2815 cy_nboard = cy_isa_nboard + cy_pci_nboard;
2816
2817
2818 for (i = 0 ; i < NR_CARDS ; i++) {
2819 if (cy_card[i].base_addr == 0) {
2820 cy_card[i].first_line = -1;
2821 }
2822 }
2823
2824 for (i = cy_next_channel ; i < NR_PORTS ; i++) {
2825 cy_port[i].line = -1;
2826 cy_port[i].magic = -1;
2827 }
2828
2829
2830 for (board = 0 ; board < cy_nboard ; board++) {
2831 cinfo = &cy_card[board];
2832 for (port = cinfo->first_line ;
2833 port < cinfo->first_line + 4*cinfo->num_chips ;
2834 port++)
2835 {
2836 info = &cy_port[port];
2837 info->magic = CYCLADES_MAGIC;
2838 info->type = PORT_CIRRUS;
2839 info->card = board;
2840 info->line = port;
2841 info->flags = STD_COM_FLAGS;
2842 info->tty = 0;
2843 info->xmit_fifo_size = 12;
2844 info->cor1 = CyPARITY_NONE|Cy_1_STOP|Cy_8_BITS;
2845 info->cor2 = CyETC;
2846 info->cor3 = 0x08;
2847 info->cor4 = 0;
2848 info->cor5 = 0;
2849 info->tbpr = baud_bpr[13];
2850 info->tco = baud_co[13];
2851 info->rbpr = baud_bpr[13];
2852 info->rco = baud_co[13];
2853 info->close_delay = 0;
2854 info->x_char = 0;
2855 info->event = 0;
2856 info->count = 0;
2857 #ifdef SERIAL_DEBUG_COUNT
2858 printk("cyc: %d: setting count to 0\n", __LINE__);
2859 #endif
2860 info->blocked_open = 0;
2861 info->default_threshold = 0;
2862 info->default_timeout = 0;
2863 info->tqueue.routine = do_softint;
2864 info->tqueue.data = info;
2865 info->callout_termios =cy_callout_driver.init_termios;
2866 info->normal_termios = cy_serial_driver.init_termios;
2867 info->open_wait = 0;
2868 info->close_wait = 0;
2869
2870
2871 info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK
2872 | CyPARITY| CyFRAME| CyOVERRUN;
2873
2874 }
2875 }
2876 return 0;
2877
2878 }
2879
2880
2881
2882
2883
2884
2885
2886 int
2887 cy_detect_isa()
2888 {
2889 unsigned int cy_isa_irq,nboard;
2890 unsigned char *cy_isa_address;
2891 unsigned short i,j,cy_isa_nchan;
2892
2893 nboard = 0;
2894
2895
2896 for (i = 0 ; i < NR_ISA_ADDRESSES ; i++) {
2897 cy_isa_address = cy_isa_addresses[i];
2898 if (cy_isa_address == 0x0000) {
2899 return(nboard);
2900 }
2901
2902
2903 cy_isa_nchan = 4 * cy_init_card(cy_isa_address,0);
2904 if (cy_isa_nchan == 0) {
2905 continue;
2906 }
2907
2908
2909 cy_isa_irq = do_auto_irq(cy_isa_address);
2910 if (cy_isa_irq == 0) {
2911 printk("Cyclom-Y/ISA found at 0x%x but the IRQ could not be detected.\n",
2912 (unsigned int) cy_isa_address);
2913 continue;
2914 }
2915
2916 if((cy_next_channel+cy_isa_nchan) > NR_PORTS) {
2917 printk("Cyclom-Y/ISA found at 0x%x but no more channel structures are available.\n",
2918 (unsigned int) cy_isa_address);
2919 return(nboard);
2920 }
2921
2922 for (j = 0 ; j < NR_CARDS ; j++) {
2923 if (cy_card[j].base_addr == 0) break;
2924 }
2925 if (j == NR_CARDS) {
2926 printk("Cyclom-Y/ISA found at 0x%x but no more card structures are available.\n",
2927 (unsigned int) cy_isa_address);
2928 return(nboard);
2929 }
2930
2931
2932 if(request_irq(cy_isa_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
2933 {
2934 printk("Cyclom-Y/ISA found at 0x%x but could not allocate interrupt IRQ#%d.\n",
2935 (unsigned int) cy_isa_address,cy_isa_irq);
2936 return(nboard);
2937 }
2938
2939
2940 cy_card[j].base_addr = (int) cy_isa_address;
2941 cy_card[j].irq = (int) cy_isa_irq;
2942 cy_card[j].bus_index = 0;
2943 cy_card[j].first_line = cy_next_channel;
2944 cy_card[j].num_chips = cy_isa_nchan/4;
2945 IRQ_cards[cy_isa_irq] = &cy_card[j];
2946 nboard++;
2947
2948
2949 printk("Cyclom-Y/ISA #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n",
2950 j+1,(unsigned int) cy_isa_address,
2951 (unsigned int)(cy_isa_address + 0x1fff),
2952 cy_isa_irq,cy_isa_nchan,cy_next_channel);
2953 cy_next_channel += cy_isa_nchan;
2954 }
2955 return(nboard);
2956
2957 }
2958
2959
2960
2961
2962
2963
2964
2965 int
2966 cy_detect_pci()
2967 {
2968 unsigned char cyy_bus, cyy_dev_fn, cyy_rev_id;
2969 unsigned long pci_intr_ctrl;
2970 unsigned char cy_pci_irq;
2971 unsigned int cy_pci_address, cy_pci_io;
2972 unsigned short i,j,cy_pci_nchan;
2973
2974 #ifndef CONFIG_PCI
2975 printk ("Kernel without PCI support.\n");
2976 return(0);
2977 #else
2978 if(pcibios_present() == 0) {
2979 return(0);
2980 }
2981 for (i = 0; i < NR_CARDS; i++) {
2982
2983 if(pcibios_find_device (PCI_VENDOR_ID_CYCLADES,
2984 PCI_DEVICE_ID_CYCLOMY,i,
2985 &cyy_bus, &cyy_dev_fn) != 0)
2986 {
2987 break;
2988 }
2989
2990 pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
2991 PCI_INTERRUPT_LINE, &cy_pci_irq);
2992 pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
2993 PCI_BASE_ADDRESS_1, &cy_pci_io);
2994 pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
2995 PCI_BASE_ADDRESS_2, &cy_pci_address);
2996 pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
2997 PCI_REVISION_ID, &cyy_rev_id);
2998 cy_pci_address &= 0xfffffff0;
2999 cy_pci_io &= 0xfffffffc;
3000 cy_pci_nchan = 4 * cy_init_card((unsigned char *)
3001 cy_pci_address,1);
3002 if(cy_pci_nchan == 0) {
3003 printk("Cyclom-Y PCI host card with no Serial-Modules at 0x%x.\n",
3004 (unsigned int) cy_pci_address);
3005 continue;
3006 }
3007 if((cy_next_channel+cy_pci_nchan) > NR_PORTS) {
3008 printk("Cyclom-Y/PCI found at 0x%x but no more channel structures are available.\n",
3009 (unsigned int) cy_pci_address);
3010 return(i);
3011 }
3012 #ifdef CY_PCI_DEBUG
3013 printk("Cyclom-Ye/PCI #%d (bus=0x0%x, pci_id=0x%x, rev_id=%d).\n",
3014 i+1,cyy_bus,cyy_dev_fn,cyy_rev_id);
3015 printk("Cyclom-Ye/PCI: found at 0x%x, IRQ%d, ioaddr = 0x%lx.\n",
3016 cy_pci_address,(int)cy_pci_irq,cy_pci_io);
3017 #endif
3018
3019 for (j = 0 ; j < NR_CARDS ; j++) {
3020 if (cy_card[j].base_addr == 0) break;
3021 }
3022 if (j == NR_CARDS) {
3023 printk("Cyclom-Y/PCI found at 0x%x but no more card structures are available.\n",
3024 (unsigned int) cy_pci_address);
3025 return(i);
3026 }
3027
3028
3029 if(request_irq(cy_pci_irq,cy_interrupt,SA_INTERRUPT,"cyclades"))
3030 {
3031 printk("Cyclom-Y/PCI found at 0x%x but could not allocate interrupt IRQ%d.\n",
3032 (unsigned int) cy_pci_address,cy_pci_irq);
3033 return(i);
3034 }
3035
3036
3037 cy_card[j].base_addr = (int) cy_pci_address;
3038 cy_card[j].irq = (int) cy_pci_irq;
3039 cy_card[j].bus_index = 1;
3040 cy_card[j].first_line = cy_next_channel;
3041 cy_card[j].num_chips = cy_pci_nchan/4;
3042 IRQ_cards[cy_pci_irq] = &cy_card[j];
3043
3044
3045 outw(inw(cy_pci_io+0x68)|0x0900,cy_pci_io+0x68);
3046 pci_intr_ctrl = (unsigned long)(inw(cy_pci_io+0x68) | inw(cy_pci_io+0x6a)<<16);
3047
3048
3049 printk("Cyclom-Y/PCI #%d: 0x%x-0x%x, IRQ%d, %d channels starting from port %d.\n",
3050 j+1,(unsigned int) cy_pci_address,
3051 (unsigned int)(cy_pci_address + 0x3fff),
3052 (int)cy_pci_irq,cy_pci_nchan,cy_next_channel);
3053
3054 cy_next_channel += cy_pci_nchan;
3055 }
3056 return(i);
3057 #endif
3058 }
3059
3060
3061 #ifdef CYCLOM_SHOW_STATUS
3062 static void
3063 show_status(int line_num)
3064 {
3065 unsigned char *base_addr;
3066 int card,chip,channel,index;
3067 struct cyclades_port * info;
3068 unsigned long flags;
3069
3070 info = &cy_port[line_num];
3071 card = info->card;
3072 index = cy_card[card].bus_index;
3073 channel = (info->line) - (cy_card[card].first_line);
3074 chip = channel>>2;
3075 channel &= 0x03;
3076 printk(" card %d, chip %d, channel %d\n", card, chip, channel);
3077
3078 printk(" cy_card\n");
3079 printk(" irq base_addr num_chips first_line = %d %lx %d %d\n",
3080 cy_card[card].irq, (long)cy_card[card].base_addr,
3081 cy_card[card].num_chips, cy_card[card].first_line);
3082
3083 printk(" cy_port\n");
3084 printk(" card line flags = %d %d %x\n",
3085 info->card, info->line, info->flags);
3086 printk(" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
3087 (long)info->tty, info->read_status_mask,
3088 info->timeout, info->xmit_fifo_size);
3089 printk(" cor1,cor2,cor3,cor4,cor5 = %x %x %x %x %x\n",
3090 info->cor1, info->cor2, info->cor3, info->cor4, info->cor5);
3091 printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n",
3092 info->tbpr, info->tco, info->rbpr, info->rco);
3093 printk(" close_delay event count = %d %d %d\n",
3094 info->close_delay, info->event, info->count);
3095 printk(" x_char blocked_open = %x %x\n",
3096 info->x_char, info->blocked_open);
3097 printk(" session pgrp open_wait = %lx %lx %lx\n",
3098 info->session, info->pgrp, (long)info->open_wait);
3099
3100
3101 save_flags(flags); cli();
3102
3103 base_addr = (unsigned char*)
3104 (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
3105
3106
3107
3108 printk(" CyGFRCR %x\n", base_addr[CyGFRCR<<index]);
3109 printk(" CyCAR %x\n", base_addr[CyCAR<<index]);
3110 printk(" CyGCR %x\n", base_addr[CyGCR<<index]);
3111 printk(" CySVRR %x\n", base_addr[CySVRR<<index]);
3112 printk(" CyRICR %x\n", base_addr[CyRICR<<index]);
3113 printk(" CyTICR %x\n", base_addr[CyTICR<<index]);
3114 printk(" CyMICR %x\n", base_addr[CyMICR<<index]);
3115 printk(" CyRIR %x\n", base_addr[CyRIR<<index]);
3116 printk(" CyTIR %x\n", base_addr[CyTIR<<index]);
3117 printk(" CyMIR %x\n", base_addr[CyMIR<<index]);
3118 printk(" CyPPR %x\n", base_addr[CyPPR<<index]);
3119
3120 base_addr[CyCAR<<index] = (u_char)channel;
3121
3122
3123
3124 printk(" CyRIVR %x\n", base_addr[CyRIVR<<index]);
3125 printk(" CyTIVR %x\n", base_addr[CyTIVR<<index]);
3126 printk(" CyMIVR %x\n", base_addr[CyMIVR<<index]);
3127 printk(" CyMISR %x\n", base_addr[CyMISR<<index]);
3128
3129
3130
3131 printk(" CyCCR %x\n", base_addr[CyCCR<<index]);
3132 printk(" CySRER %x\n", base_addr[CySRER<<index]);
3133 printk(" CyCOR1 %x\n", base_addr[CyCOR1<<index]);
3134 printk(" CyCOR2 %x\n", base_addr[CyCOR2<<index]);
3135 printk(" CyCOR3 %x\n", base_addr[CyCOR3<<index]);
3136 printk(" CyCOR4 %x\n", base_addr[CyCOR4<<index]);
3137 printk(" CyCOR5 %x\n", base_addr[CyCOR5<<index]);
3138 printk(" CyCCSR %x\n", base_addr[CyCCSR<<index]);
3139 printk(" CyRDCR %x\n", base_addr[CyRDCR<<index]);
3140 printk(" CySCHR1 %x\n", base_addr[CySCHR1<<index]);
3141 printk(" CySCHR2 %x\n", base_addr[CySCHR2<<index]);
3142 printk(" CySCHR3 %x\n", base_addr[CySCHR3<<index]);
3143 printk(" CySCHR4 %x\n", base_addr[CySCHR4<<index]);
3144 printk(" CySCRL %x\n", base_addr[CySCRL<<index]);
3145 printk(" CySCRH %x\n", base_addr[CySCRH<<index]);
3146 printk(" CyLNC %x\n", base_addr[CyLNC<<index]);
3147 printk(" CyMCOR1 %x\n", base_addr[CyMCOR1<<index]);
3148 printk(" CyMCOR2 %x\n", base_addr[CyMCOR2<<index]);
3149 printk(" CyRTPR %x\n", base_addr[CyRTPR<<index]);
3150 printk(" CyMSVR1 %x\n", base_addr[CyMSVR1<<index]);
3151 printk(" CyMSVR2 %x\n", base_addr[CyMSVR2<<index]);
3152 printk(" CyRBPR %x\n", base_addr[CyRBPR<<index]);
3153 printk(" CyRCOR %x\n", base_addr[CyRCOR<<index]);
3154 printk(" CyTBPR %x\n", base_addr[CyTBPR<<index]);
3155 printk(" CyTCOR %x\n", base_addr[CyTCOR<<index]);
3156
3157 restore_flags(flags);
3158 }
3159 #endif
3160