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#include <linux/errno.h>
48#include <linux/signal.h>
49#include <linux/sched.h>
50#include <linux/timer.h>
51#include <linux/tty.h>
52#include <linux/interrupt.h>
53#include <linux/serial.h>
54#include <linux/serialP.h>
55#include <linux/string.h>
56#include <linux/fcntl.h>
57#include <linux/ptrace.h>
58#include <linux/serial167.h>
59#include <linux/delay.h>
60#include <linux/major.h>
61#include <linux/mm.h>
62#include <linux/console.h>
63#include <linux/module.h>
64#include <linux/bitops.h>
65#include <linux/tty_flip.h>
66
67#include <asm/system.h>
68#include <asm/io.h>
69#include <asm/mvme16xhw.h>
70#include <asm/bootinfo.h>
71#include <asm/setup.h>
72
73#include <linux/types.h>
74#include <linux/kernel.h>
75
76#include <asm/uaccess.h>
77#include <linux/init.h>
78
79#define SERIAL_PARANOIA_CHECK
80#undef SERIAL_DEBUG_OPEN
81#undef SERIAL_DEBUG_THROTTLE
82#undef SERIAL_DEBUG_OTHER
83#undef SERIAL_DEBUG_IO
84#undef SERIAL_DEBUG_COUNT
85#undef SERIAL_DEBUG_DTR
86#undef CYCLOM_16Y_HACK
87#define CYCLOM_ENABLE_MONITORING
88
89#define WAKEUP_CHARS 256
90
91#define STD_COM_FLAGS (0)
92
93static struct tty_driver *cy_serial_driver;
94extern int serial_console;
95static struct cyclades_port *serial_console_info = NULL;
96static unsigned int serial_console_cflag = 0;
97u_char initial_console_speed;
98
99
100
101#define BASE_ADDR (0xfff45000)
102#define pcc2chip ((volatile u_char *)0xfff42000)
103#define PccSCCMICR 0x1d
104#define PccSCCTICR 0x1e
105#define PccSCCRICR 0x1f
106#define PccTPIACKR 0x25
107#define PccRPIACKR 0x27
108#define PccIMLR 0x3f
109
110
111struct cyclades_port cy_port[] = {
112
113 {-1},
114 {-1},
115 {-1},
116 {-1},
117};
118
119#define NR_PORTS ARRAY_SIZE(cy_port)
120
121
122
123
124
125
126
127
128
129static int baud_table[] = {
130 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
131 1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
132 0
133};
134
135#if 0
136static char baud_co[] = {
137
138
139 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
140 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
141};
142
143static char baud_bpr[] = {
144 0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
145 0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
146};
147#endif
148
149
150
151
152static u_char baud_co[] = {
153 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
154 0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
155};
156
157
158static u_char baud_bpr[] = {
159 0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
160 0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
161};
162
163static u_char baud_cor4[] = {
164 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
165 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
166};
167
168static void shutdown(struct cyclades_port *);
169static int startup(struct cyclades_port *);
170static void cy_throttle(struct tty_struct *);
171static void cy_unthrottle(struct tty_struct *);
172static void config_setup(struct cyclades_port *);
173extern void console_print(const char *);
174#ifdef CYCLOM_SHOW_STATUS
175static void show_status(int);
176#endif
177
178#ifdef CONFIG_REMOTE_DEBUG
179static void debug_setup(void);
180void queueDebugChar(int c);
181int getDebugChar(void);
182
183#define DEBUG_PORT 1
184#define DEBUG_LEN 256
185
186typedef struct {
187 int in;
188 int out;
189 unsigned char buf[DEBUG_LEN];
190} debugq;
191
192debugq debugiq;
193#endif
194
195
196
197
198
199
200
201
202void my_udelay(long us)
203{
204 u_char x;
205 volatile u_char *p = &x;
206 int i;
207
208 while (us--)
209 for (i = 100; i; i--)
210 x |= *p;
211}
212
213static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
214 const char *routine)
215{
216#ifdef SERIAL_PARANOIA_CHECK
217 if (!info) {
218 printk("Warning: null cyclades_port for (%s) in %s\n", name,
219 routine);
220 return 1;
221 }
222
223 if ((long)info < (long)(&cy_port[0])
224 || (long)(&cy_port[NR_PORTS]) < (long)info) {
225 printk("Warning: cyclades_port out of range for (%s) in %s\n",
226 name, routine);
227 return 1;
228 }
229
230 if (info->magic != CYCLADES_MAGIC) {
231 printk("Warning: bad magic number for serial struct (%s) in "
232 "%s\n", name, routine);
233 return 1;
234 }
235#endif
236 return 0;
237}
238
239#if 0
240
241
242
243void SP(char *data)
244{
245 unsigned long flags;
246 local_irq_save(flags);
247 console_print(data);
248 local_irq_restore(flags);
249}
250
251char scrn[2];
252void CP(char data)
253{
254 unsigned long flags;
255 local_irq_save(flags);
256 scrn[0] = data;
257 console_print(scrn);
258 local_irq_restore(flags);
259}
260
261void CP1(int data)
262{
263 (data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
264}
265void CP2(int data)
266{
267 CP1((data >> 4) & 0x0f);
268 CP1(data & 0x0f);
269}
270void CP4(int data)
271{
272 CP2((data >> 8) & 0xff);
273 CP2(data & 0xff);
274}
275void CP8(long data)
276{
277 CP4((data >> 16) & 0xffff);
278 CP4(data & 0xffff);
279}
280#endif
281
282
283
284
285
286
287u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
288{
289 unsigned long flags;
290 volatile int i;
291
292 local_irq_save(flags);
293
294 for (i = 0; i < 100; i++) {
295 if (base_addr[CyCCR] == 0) {
296 break;
297 }
298 my_udelay(10L);
299 }
300
301
302 if (i == 10) {
303 local_irq_restore(flags);
304 return (-1);
305 }
306
307
308 base_addr[CyCCR] = cmd;
309 local_irq_restore(flags);
310 return (0);
311}
312
313
314
315
316static void cy_stop(struct tty_struct *tty)
317{
318 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
319 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
320 int channel;
321 unsigned long flags;
322
323#ifdef SERIAL_DEBUG_OTHER
324 printk("cy_stop %s\n", tty->name);
325#endif
326
327 if (serial_paranoia_check(info, tty->name, "cy_stop"))
328 return;
329
330 channel = info->line;
331
332 local_irq_save(flags);
333 base_addr[CyCAR] = (u_char) (channel);
334 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
335 local_irq_restore(flags);
336}
337
338static void cy_start(struct tty_struct *tty)
339{
340 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
341 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
342 int channel;
343 unsigned long flags;
344
345#ifdef SERIAL_DEBUG_OTHER
346 printk("cy_start %s\n", tty->name);
347#endif
348
349 if (serial_paranoia_check(info, tty->name, "cy_start"))
350 return;
351
352 channel = info->line;
353
354 local_irq_save(flags);
355 base_addr[CyCAR] = (u_char) (channel);
356 base_addr[CyIER] |= CyTxMpty;
357 local_irq_restore(flags);
358}
359
360
361
362
363
364static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
365{
366 struct tty_struct *tty;
367 struct cyclades_port *info;
368 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
369 unsigned char err, rfoc;
370 int channel;
371 char data;
372
373
374 channel = (u_short) (base_addr[CyLICR] >> 2);
375 info = &cy_port[channel];
376 info->last_active = jiffies;
377
378 if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
379
380 base_addr[CyREOIR] = CyNOTRANS;
381 return IRQ_HANDLED;
382 }
383
384
385
386
387 if ((rfoc = base_addr[CyRFOC]) != 0)
388 data = base_addr[CyRDR];
389 else
390 data = 0;
391
392
393 if (info->tty == 0) {
394 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
395 return IRQ_HANDLED;
396 } else {
397 tty = info->tty;
398 if (err & info->ignore_status_mask) {
399 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
400 return IRQ_HANDLED;
401 }
402 if (tty_buffer_request_room(tty, 1) != 0) {
403 if (err & info->read_status_mask) {
404 if (err & CyBREAK) {
405 tty_insert_flip_char(tty, data,
406 TTY_BREAK);
407 if (info->flags & ASYNC_SAK) {
408 do_SAK(tty);
409 }
410 } else if (err & CyFRAME) {
411 tty_insert_flip_char(tty, data,
412 TTY_FRAME);
413 } else if (err & CyPARITY) {
414 tty_insert_flip_char(tty, data,
415 TTY_PARITY);
416 } else if (err & CyOVERRUN) {
417 tty_insert_flip_char(tty, 0,
418 TTY_OVERRUN);
419
420
421
422
423
424 if (tty_buffer_request_room(tty, 1) !=
425 0) {
426 tty_insert_flip_char(tty, data,
427 TTY_FRAME);
428 }
429
430
431
432
433 } else {
434 tty_insert_flip_char(tty, 0,
435 TTY_NORMAL);
436 }
437 } else {
438 tty_insert_flip_char(tty, data, TTY_NORMAL);
439 }
440 } else {
441
442
443 }
444 }
445 tty_schedule_flip(tty);
446
447 base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
448 return IRQ_HANDLED;
449}
450
451static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
452{
453 struct cyclades_port *info;
454 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
455 int channel;
456 int mdm_change;
457 int mdm_status;
458
459
460 channel = (u_short) (base_addr[CyLICR] >> 2);
461 info = &cy_port[channel];
462 info->last_active = jiffies;
463
464 mdm_change = base_addr[CyMISR];
465 mdm_status = base_addr[CyMSVR1];
466
467 if (info->tty == 0) {
468 ;
469 } else {
470 if ((mdm_change & CyDCD)
471 && (info->flags & ASYNC_CHECK_CD)) {
472 if (mdm_status & CyDCD) {
473
474 wake_up_interruptible(&info->open_wait);
475 } else {
476
477 tty_hangup(info->tty);
478 wake_up_interruptible(&info->open_wait);
479 info->flags &= ~ASYNC_NORMAL_ACTIVE;
480 }
481 }
482 if ((mdm_change & CyCTS)
483 && (info->flags & ASYNC_CTS_FLOW)) {
484 if (info->tty->stopped) {
485 if (mdm_status & CyCTS) {
486
487 info->tty->stopped = 0;
488 base_addr[CyIER] |= CyTxMpty;
489 tty_wakeup(info->tty);
490 }
491 } else {
492 if (!(mdm_status & CyCTS)) {
493
494 info->tty->stopped = 1;
495 base_addr[CyIER] &=
496 ~(CyTxMpty | CyTxRdy);
497 }
498 }
499 }
500 if (mdm_status & CyDSR) {
501 }
502 }
503 base_addr[CyMEOIR] = 0;
504 return IRQ_HANDLED;
505}
506
507static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
508{
509 struct cyclades_port *info;
510 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
511 int channel;
512 int char_count, saved_cnt;
513 int outch;
514
515
516 channel = (u_short) (base_addr[CyLICR] >> 2);
517
518#ifdef CONFIG_REMOTE_DEBUG
519 if (channel == DEBUG_PORT) {
520 panic("TxInt on debug port!!!");
521 }
522#endif
523
524 info = &cy_port[channel];
525
526
527 if ((channel < 0) || (NR_PORTS <= channel)) {
528 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
529 base_addr[CyTEOIR] = CyNOTRANS;
530 return IRQ_HANDLED;
531 }
532 info->last_active = jiffies;
533 if (info->tty == 0) {
534 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
535 base_addr[CyTEOIR] = CyNOTRANS;
536 return IRQ_HANDLED;
537 }
538
539
540 saved_cnt = char_count = base_addr[CyTFTC];
541
542 if (info->x_char) {
543 outch = info->x_char;
544 base_addr[CyTDR] = outch;
545 char_count--;
546 info->x_char = 0;
547 }
548
549 if (info->x_break) {
550
551
552
553
554
555
556
557
558
559 base_addr[CyTDR] = 0;
560 base_addr[CyTDR] = 0x81;
561 base_addr[CyTDR] = 0;
562 base_addr[CyTDR] = 0x82;
563 base_addr[CyTDR] = info->x_break * 200 / HZ;
564 base_addr[CyTDR] = 0;
565 base_addr[CyTDR] = 0x83;
566 char_count -= 7;
567 info->x_break = 0;
568 }
569
570 while (char_count > 0) {
571 if (!info->xmit_cnt) {
572 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
573 break;
574 }
575 if (info->xmit_buf == 0) {
576 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
577 break;
578 }
579 if (info->tty->stopped || info->tty->hw_stopped) {
580 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
581 break;
582 }
583
584
585
586
587
588
589
590
591
592
593
594 outch = info->xmit_buf[info->xmit_tail];
595 if (outch) {
596 info->xmit_cnt--;
597 info->xmit_tail = (info->xmit_tail + 1)
598 & (PAGE_SIZE - 1);
599 base_addr[CyTDR] = outch;
600 char_count--;
601 } else {
602 if (char_count > 1) {
603 info->xmit_cnt--;
604 info->xmit_tail = (info->xmit_tail + 1)
605 & (PAGE_SIZE - 1);
606 base_addr[CyTDR] = outch;
607 base_addr[CyTDR] = 0;
608 char_count--;
609 char_count--;
610 } else {
611 break;
612 }
613 }
614 }
615
616 if (info->xmit_cnt < WAKEUP_CHARS)
617 tty_wakeup(info->tty);
618
619 base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
620 return IRQ_HANDLED;
621}
622
623static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
624{
625 struct tty_struct *tty;
626 struct cyclades_port *info;
627 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
628 int channel;
629 char data;
630 int char_count;
631 int save_cnt;
632 int len;
633
634
635 channel = (u_short) (base_addr[CyLICR] >> 2);
636 info = &cy_port[channel];
637 info->last_active = jiffies;
638 save_cnt = char_count = base_addr[CyRFOC];
639
640#ifdef CONFIG_REMOTE_DEBUG
641 if (channel == DEBUG_PORT) {
642 while (char_count--) {
643 data = base_addr[CyRDR];
644 queueDebugChar(data);
645 }
646 } else
647#endif
648
649 if (info->tty == 0) {
650 while (char_count--) {
651 data = base_addr[CyRDR];
652 }
653 } else {
654 tty = info->tty;
655
656
657#ifdef CYCLOM_ENABLE_MONITORING
658 ++info->mon.int_count;
659 info->mon.char_count += char_count;
660 if (char_count > info->mon.char_max)
661 info->mon.char_max = char_count;
662 info->mon.char_last = char_count;
663#endif
664 len = tty_buffer_request_room(tty, char_count);
665 while (len--) {
666 data = base_addr[CyRDR];
667 tty_insert_flip_char(tty, data, TTY_NORMAL);
668#ifdef CYCLOM_16Y_HACK
669 udelay(10L);
670#endif
671 }
672 tty_schedule_flip(tty);
673 }
674
675 base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
676 return IRQ_HANDLED;
677}
678
679
680
681
682static int startup(struct cyclades_port *info)
683{
684 unsigned long flags;
685 volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
686 int channel;
687
688 if (info->flags & ASYNC_INITIALIZED) {
689 return 0;
690 }
691
692 if (!info->type) {
693 if (info->tty) {
694 set_bit(TTY_IO_ERROR, &info->tty->flags);
695 }
696 return 0;
697 }
698 if (!info->xmit_buf) {
699 info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
700 if (!info->xmit_buf) {
701 return -ENOMEM;
702 }
703 }
704
705 config_setup(info);
706
707 channel = info->line;
708
709#ifdef SERIAL_DEBUG_OPEN
710 printk("startup channel %d\n", channel);
711#endif
712
713 local_irq_save(flags);
714 base_addr[CyCAR] = (u_char) channel;
715 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
716
717 base_addr[CyCAR] = (u_char) channel;
718 base_addr[CyMSVR1] = CyRTS;
719
720 base_addr[CyMSVR2] = CyDTR;
721
722#ifdef SERIAL_DEBUG_DTR
723 printk("cyc: %d: raising DTR\n", __LINE__);
724 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
725 base_addr[CyMSVR2]);
726#endif
727
728 base_addr[CyIER] |= CyRxData;
729 info->flags |= ASYNC_INITIALIZED;
730
731 if (info->tty) {
732 clear_bit(TTY_IO_ERROR, &info->tty->flags);
733 }
734 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
735
736 local_irq_restore(flags);
737
738#ifdef SERIAL_DEBUG_OPEN
739 printk(" done\n");
740#endif
741 return 0;
742}
743
744void start_xmit(struct cyclades_port *info)
745{
746 unsigned long flags;
747 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
748 int channel;
749
750 channel = info->line;
751 local_irq_save(flags);
752 base_addr[CyCAR] = channel;
753 base_addr[CyIER] |= CyTxMpty;
754 local_irq_restore(flags);
755}
756
757
758
759
760
761static void shutdown(struct cyclades_port *info)
762{
763 unsigned long flags;
764 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
765 int channel;
766
767 if (!(info->flags & ASYNC_INITIALIZED)) {
768
769 return;
770 }
771
772 channel = info->line;
773
774#ifdef SERIAL_DEBUG_OPEN
775 printk("shutdown channel %d\n", channel);
776#endif
777
778
779
780
781
782
783
784 local_irq_save(flags);
785 if (info->xmit_buf) {
786 free_page((unsigned long)info->xmit_buf);
787 info->xmit_buf = NULL;
788 }
789
790 base_addr[CyCAR] = (u_char) channel;
791 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
792 base_addr[CyMSVR1] = 0;
793
794 base_addr[CyMSVR2] = 0;
795#ifdef SERIAL_DEBUG_DTR
796 printk("cyc: %d: dropping DTR\n", __LINE__);
797 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
798 base_addr[CyMSVR2]);
799#endif
800 }
801 write_cy_cmd(base_addr, CyDIS_RCVR);
802
803
804
805 if (info->tty) {
806 set_bit(TTY_IO_ERROR, &info->tty->flags);
807 }
808 info->flags &= ~ASYNC_INITIALIZED;
809 local_irq_restore(flags);
810
811#ifdef SERIAL_DEBUG_OPEN
812 printk(" done\n");
813#endif
814}
815
816
817
818
819static void config_setup(struct cyclades_port *info)
820{
821 unsigned long flags;
822 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
823 int channel;
824 unsigned cflag;
825 int i;
826 unsigned char ti, need_init_chan = 0;
827
828 if (!info->tty || !info->tty->termios) {
829 return;
830 }
831 if (info->line == -1) {
832 return;
833 }
834 cflag = info->tty->termios->c_cflag;
835
836
837 i = cflag & CBAUD;
838#ifdef CBAUDEX
839
840
841
842
843
844
845
846
847 if (i & CBAUDEX) {
848 if (i == B57600)
849 i = 16;
850 else if (i == B115200)
851 i = 18;
852#ifdef B78600
853 else if (i == B78600)
854 i = 17;
855#endif
856 else
857 info->tty->termios->c_cflag &= ~CBAUDEX;
858 }
859#endif
860 if (i == 15) {
861 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
862 i += 1;
863 if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
864 i += 3;
865 }
866
867
868
869
870 if (info != serial_console_info) {
871 info->tbpr = baud_bpr[i];
872 info->tco = baud_co[i];
873 info->rbpr = baud_bpr[i];
874 info->rco = baud_co[i] >> 5;
875 if (baud_table[i] == 134) {
876 info->timeout =
877 (info->xmit_fifo_size * HZ * 30 / 269) + 2;
878
879 } else if (baud_table[i]) {
880 info->timeout =
881 (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
882 2;
883
884 } else {
885 info->timeout = 0;
886 }
887 }
888
889
890
891
892
893 info->cor7 = 0;
894 info->cor6 = 0;
895 info->cor5 = 0;
896 info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);
897
898
899
900 channel = info->line;
901 base_addr[CyCAR] = (u_char) channel;
902 if (C_CLOCAL(info->tty)) {
903 if (base_addr[CyIER] & CyMdmCh)
904 base_addr[CyIER] &= ~CyMdmCh;
905
906 if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
907 base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
908
909 if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
910 base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
911 } else {
912 if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
913 base_addr[CyIER] |= CyMdmCh;
914
915 if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
916 (CyDSR | CyCTS | CyDCD))
917 base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
918
919 if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
920 (CyDSR | CyCTS | CyDCD))
921 base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
922 }
923 info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
924 info->cor2 = CyETC;
925 switch (cflag & CSIZE) {
926 case CS5:
927 info->cor1 = Cy_5_BITS;
928 break;
929 case CS6:
930 info->cor1 = Cy_6_BITS;
931 break;
932 case CS7:
933 info->cor1 = Cy_7_BITS;
934 break;
935 case CS8:
936 info->cor1 = Cy_8_BITS;
937 break;
938 }
939 if (cflag & PARENB) {
940 if (cflag & PARODD) {
941 info->cor1 |= CyPARITY_O;
942 } else {
943 info->cor1 |= CyPARITY_E;
944 }
945 } else {
946 info->cor1 |= CyPARITY_NONE;
947 }
948
949
950#if 0
951
952 if (cflag & CRTSCTS) {
953 info->flags |= ASYNC_CTS_FLOW;
954 info->cor2 |= CyCtsAE;
955 } else {
956 info->flags &= ~ASYNC_CTS_FLOW;
957 info->cor2 &= ~CyCtsAE;
958 }
959#endif
960 if (cflag & CLOCAL)
961 info->flags &= ~ASYNC_CHECK_CD;
962 else
963 info->flags |= ASYNC_CHECK_CD;
964
965
966
967
968
969
970
971
972
973
974
975 channel = info->line;
976
977 local_irq_save(flags);
978 base_addr[CyCAR] = (u_char) channel;
979
980
981 if (base_addr[CyLICR] != channel << 2)
982 base_addr[CyLICR] = channel << 2;
983 if (base_addr[CyLIVR] != 0x5c)
984 base_addr[CyLIVR] = 0x5c;
985
986
987
988 if (base_addr[CyCOR1] != info->cor1)
989 need_init_chan = 1;
990 if (base_addr[CyTCOR] != info->tco)
991 base_addr[CyTCOR] = info->tco;
992 if (base_addr[CyTBPR] != info->tbpr)
993 base_addr[CyTBPR] = info->tbpr;
994 if (base_addr[CyRCOR] != info->rco)
995 base_addr[CyRCOR] = info->rco;
996 if (base_addr[CyRBPR] != info->rbpr)
997 base_addr[CyRBPR] = info->rbpr;
998
999
1000
1001 if (base_addr[CySCHR1] != START_CHAR(info->tty))
1002 base_addr[CySCHR1] = START_CHAR(info->tty);
1003 if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
1004 base_addr[CySCHR2] = STOP_CHAR(info->tty);
1005 if (base_addr[CySCRL] != START_CHAR(info->tty))
1006 base_addr[CySCRL] = START_CHAR(info->tty);
1007 if (base_addr[CySCRH] != START_CHAR(info->tty))
1008 base_addr[CySCRH] = START_CHAR(info->tty);
1009 if (base_addr[CyCOR1] != info->cor1)
1010 base_addr[CyCOR1] = info->cor1;
1011 if (base_addr[CyCOR2] != info->cor2)
1012 base_addr[CyCOR2] = info->cor2;
1013 if (base_addr[CyCOR3] != info->cor3)
1014 base_addr[CyCOR3] = info->cor3;
1015 if (base_addr[CyCOR4] != info->cor4)
1016 base_addr[CyCOR4] = info->cor4;
1017 if (base_addr[CyCOR5] != info->cor5)
1018 base_addr[CyCOR5] = info->cor5;
1019 if (base_addr[CyCOR6] != info->cor6)
1020 base_addr[CyCOR6] = info->cor6;
1021 if (base_addr[CyCOR7] != info->cor7)
1022 base_addr[CyCOR7] = info->cor7;
1023
1024 if (need_init_chan)
1025 write_cy_cmd(base_addr, CyINIT_CHAN);
1026
1027 base_addr[CyCAR] = (u_char) channel;
1028
1029
1030 ti = info->default_timeout ? info->default_timeout : 0x02;
1031 if (base_addr[CyRTPRL] != ti)
1032 base_addr[CyRTPRL] = ti;
1033 if (base_addr[CyRTPRH] != 0)
1034 base_addr[CyRTPRH] = 0;
1035
1036
1037 if (i == 0) {
1038 if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
1039 base_addr[CyMSVR2] = 0;
1040#ifdef SERIAL_DEBUG_DTR
1041 printk("cyc: %d: dropping DTR\n", __LINE__);
1042 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1043 base_addr[CyMSVR2]);
1044#endif
1045 } else {
1046 if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
1047 base_addr[CyMSVR2] = CyDTR;
1048#ifdef SERIAL_DEBUG_DTR
1049 printk("cyc: %d: raising DTR\n", __LINE__);
1050 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1051 base_addr[CyMSVR2]);
1052#endif
1053 }
1054
1055 if (info->tty) {
1056 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1057 }
1058
1059 local_irq_restore(flags);
1060
1061}
1062
1063static int cy_put_char(struct tty_struct *tty, unsigned char ch)
1064{
1065 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1066 unsigned long flags;
1067
1068#ifdef SERIAL_DEBUG_IO
1069 printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
1070#endif
1071
1072 if (serial_paranoia_check(info, tty->name, "cy_put_char"))
1073 return 0;
1074
1075 if (!info->xmit_buf)
1076 return 0;
1077
1078 local_irq_save(flags);
1079 if (info->xmit_cnt >= PAGE_SIZE - 1) {
1080 local_irq_restore(flags);
1081 return 0;
1082 }
1083
1084 info->xmit_buf[info->xmit_head++] = ch;
1085 info->xmit_head &= PAGE_SIZE - 1;
1086 info->xmit_cnt++;
1087 local_irq_restore(flags);
1088 return 1;
1089}
1090
1091static void cy_flush_chars(struct tty_struct *tty)
1092{
1093 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1094 unsigned long flags;
1095 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1096 int channel;
1097
1098#ifdef SERIAL_DEBUG_IO
1099 printk("cy_flush_chars %s\n", tty->name);
1100#endif
1101
1102 if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
1103 return;
1104
1105 if (info->xmit_cnt <= 0 || tty->stopped
1106 || tty->hw_stopped || !info->xmit_buf)
1107 return;
1108
1109 channel = info->line;
1110
1111 local_irq_save(flags);
1112 base_addr[CyCAR] = channel;
1113 base_addr[CyIER] |= CyTxMpty;
1114 local_irq_restore(flags);
1115}
1116
1117
1118
1119
1120
1121
1122
1123static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
1124{
1125 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1126 unsigned long flags;
1127 int c, total = 0;
1128
1129#ifdef SERIAL_DEBUG_IO
1130 printk("cy_write %s\n", tty->name);
1131#endif
1132
1133 if (serial_paranoia_check(info, tty->name, "cy_write")) {
1134 return 0;
1135 }
1136
1137 if (!info->xmit_buf) {
1138 return 0;
1139 }
1140
1141 while (1) {
1142 local_irq_save(flags);
1143 c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1144 SERIAL_XMIT_SIZE - info->xmit_head));
1145 if (c <= 0) {
1146 local_irq_restore(flags);
1147 break;
1148 }
1149
1150 memcpy(info->xmit_buf + info->xmit_head, buf, c);
1151 info->xmit_head =
1152 (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
1153 info->xmit_cnt += c;
1154 local_irq_restore(flags);
1155
1156 buf += c;
1157 count -= c;
1158 total += c;
1159 }
1160
1161 if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
1162 start_xmit(info);
1163 }
1164 return total;
1165}
1166
1167static int cy_write_room(struct tty_struct *tty)
1168{
1169 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1170 int ret;
1171
1172#ifdef SERIAL_DEBUG_IO
1173 printk("cy_write_room %s\n", tty->name);
1174#endif
1175
1176 if (serial_paranoia_check(info, tty->name, "cy_write_room"))
1177 return 0;
1178 ret = PAGE_SIZE - info->xmit_cnt - 1;
1179 if (ret < 0)
1180 ret = 0;
1181 return ret;
1182}
1183
1184static int cy_chars_in_buffer(struct tty_struct *tty)
1185{
1186 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1187
1188#ifdef SERIAL_DEBUG_IO
1189 printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);
1190#endif
1191
1192 if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
1193 return 0;
1194
1195 return info->xmit_cnt;
1196}
1197
1198static void cy_flush_buffer(struct tty_struct *tty)
1199{
1200 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1201 unsigned long flags;
1202
1203#ifdef SERIAL_DEBUG_IO
1204 printk("cy_flush_buffer %s\n", tty->name);
1205#endif
1206
1207 if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
1208 return;
1209 local_irq_save(flags);
1210 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1211 local_irq_restore(flags);
1212 tty_wakeup(tty);
1213}
1214
1215
1216
1217
1218
1219static void cy_throttle(struct tty_struct *tty)
1220{
1221 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1222 unsigned long flags;
1223 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1224 int channel;
1225
1226#ifdef SERIAL_DEBUG_THROTTLE
1227 char buf[64];
1228
1229 printk("throttle %s: %d....\n", tty_name(tty, buf),
1230 tty->ldisc.chars_in_buffer(tty));
1231 printk("cy_throttle %s\n", tty->name);
1232#endif
1233
1234 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1235 return;
1236 }
1237
1238 if (I_IXOFF(tty)) {
1239 info->x_char = STOP_CHAR(tty);
1240
1241 }
1242
1243 channel = info->line;
1244
1245 local_irq_save(flags);
1246 base_addr[CyCAR] = (u_char) channel;
1247 base_addr[CyMSVR1] = 0;
1248 local_irq_restore(flags);
1249}
1250
1251static void cy_unthrottle(struct tty_struct *tty)
1252{
1253 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1254 unsigned long flags;
1255 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1256 int channel;
1257
1258#ifdef SERIAL_DEBUG_THROTTLE
1259 char buf[64];
1260
1261 printk("throttle %s: %d....\n", tty_name(tty, buf),
1262 tty->ldisc.chars_in_buffer(tty));
1263 printk("cy_unthrottle %s\n", tty->name);
1264#endif
1265
1266 if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
1267 return;
1268 }
1269
1270 if (I_IXOFF(tty)) {
1271 info->x_char = START_CHAR(tty);
1272
1273 }
1274
1275 channel = info->line;
1276
1277 local_irq_save(flags);
1278 base_addr[CyCAR] = (u_char) channel;
1279 base_addr[CyMSVR1] = CyRTS;
1280 local_irq_restore(flags);
1281}
1282
1283static int
1284get_serial_info(struct cyclades_port *info,
1285 struct serial_struct __user * retinfo)
1286{
1287 struct serial_struct tmp;
1288
1289
1290 if (!retinfo)
1291 return -EFAULT;
1292 memset(&tmp, 0, sizeof(tmp));
1293 tmp.type = info->type;
1294 tmp.line = info->line;
1295 tmp.port = info->line;
1296 tmp.irq = 0;
1297 tmp.flags = info->flags;
1298 tmp.baud_base = 0;
1299 tmp.close_delay = info->close_delay;
1300 tmp.custom_divisor = 0;
1301 tmp.hub6 = 0;
1302 return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
1303}
1304
1305static int
1306set_serial_info(struct cyclades_port *info,
1307 struct serial_struct __user * new_info)
1308{
1309 struct serial_struct new_serial;
1310 struct cyclades_port old_info;
1311
1312
1313 if (!new_info)
1314 return -EFAULT;
1315 if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
1316 return -EFAULT;
1317 old_info = *info;
1318
1319 if (!capable(CAP_SYS_ADMIN)) {
1320 if ((new_serial.close_delay != info->close_delay) ||
1321 ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
1322 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
1323 return -EPERM;
1324 info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1325 (new_serial.flags & ASYNC_USR_MASK));
1326 goto check_and_exit;
1327 }
1328
1329
1330
1331
1332
1333
1334 info->flags = ((info->flags & ~ASYNC_FLAGS) |
1335 (new_serial.flags & ASYNC_FLAGS));
1336 info->close_delay = new_serial.close_delay;
1337
1338check_and_exit:
1339 if (info->flags & ASYNC_INITIALIZED) {
1340 config_setup(info);
1341 return 0;
1342 }
1343 return startup(info);
1344}
1345
1346static int cy_tiocmget(struct tty_struct *tty, struct file *file)
1347{
1348 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1349 int channel;
1350 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1351 unsigned long flags;
1352 unsigned char status;
1353
1354 channel = info->line;
1355
1356 local_irq_save(flags);
1357 base_addr[CyCAR] = (u_char) channel;
1358 status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
1359 local_irq_restore(flags);
1360
1361 return ((status & CyRTS) ? TIOCM_RTS : 0)
1362 | ((status & CyDTR) ? TIOCM_DTR : 0)
1363 | ((status & CyDCD) ? TIOCM_CAR : 0)
1364 | ((status & CyDSR) ? TIOCM_DSR : 0)
1365 | ((status & CyCTS) ? TIOCM_CTS : 0);
1366}
1367
1368static int
1369cy_tiocmset(struct tty_struct *tty, struct file *file,
1370 unsigned int set, unsigned int clear)
1371{
1372 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1373 int channel;
1374 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1375 unsigned long flags;
1376
1377 channel = info->line;
1378
1379 if (set & TIOCM_RTS) {
1380 local_irq_save(flags);
1381 base_addr[CyCAR] = (u_char) channel;
1382 base_addr[CyMSVR1] = CyRTS;
1383 local_irq_restore(flags);
1384 }
1385 if (set & TIOCM_DTR) {
1386 local_irq_save(flags);
1387 base_addr[CyCAR] = (u_char) channel;
1388
1389 base_addr[CyMSVR2] = CyDTR;
1390#ifdef SERIAL_DEBUG_DTR
1391 printk("cyc: %d: raising DTR\n", __LINE__);
1392 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1393 base_addr[CyMSVR2]);
1394#endif
1395 local_irq_restore(flags);
1396 }
1397
1398 if (clear & TIOCM_RTS) {
1399 local_irq_save(flags);
1400 base_addr[CyCAR] = (u_char) channel;
1401 base_addr[CyMSVR1] = 0;
1402 local_irq_restore(flags);
1403 }
1404 if (clear & TIOCM_DTR) {
1405 local_irq_save(flags);
1406 base_addr[CyCAR] = (u_char) channel;
1407
1408 base_addr[CyMSVR2] = 0;
1409#ifdef SERIAL_DEBUG_DTR
1410 printk("cyc: %d: dropping DTR\n", __LINE__);
1411 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1412 base_addr[CyMSVR2]);
1413#endif
1414 local_irq_restore(flags);
1415 }
1416
1417 return 0;
1418}
1419
1420static void send_break(struct cyclades_port *info, int duration)
1421{
1422
1423
1424 info->x_break = duration;
1425 if (!info->xmit_cnt) {
1426 start_xmit(info);
1427 }
1428}
1429
1430static int
1431get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
1432{
1433
1434 if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
1435 return -EFAULT;
1436 info->mon.int_count = 0;
1437 info->mon.char_count = 0;
1438 info->mon.char_max = 0;
1439 info->mon.char_last = 0;
1440 return 0;
1441}
1442
1443static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
1444{
1445 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1446 unsigned long value;
1447 int channel;
1448
1449 if (get_user(value, arg))
1450 return -EFAULT;
1451
1452 channel = info->line;
1453 info->cor4 &= ~CyREC_FIFO;
1454 info->cor4 |= value & CyREC_FIFO;
1455 base_addr[CyCOR4] = info->cor4;
1456 return 0;
1457}
1458
1459static int
1460get_threshold(struct cyclades_port *info, unsigned long __user * value)
1461{
1462 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1463 int channel;
1464 unsigned long tmp;
1465
1466 channel = info->line;
1467
1468 tmp = base_addr[CyCOR4] & CyREC_FIFO;
1469 return put_user(tmp, value);
1470}
1471
1472static int
1473set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
1474{
1475 unsigned long value;
1476
1477 if (get_user(value, arg))
1478 return -EFAULT;
1479
1480 info->default_threshold = value & 0x0f;
1481 return 0;
1482}
1483
1484static int
1485get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
1486{
1487 return put_user(info->default_threshold, value);
1488}
1489
1490static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
1491{
1492 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1493 int channel;
1494 unsigned long value;
1495
1496 if (get_user(value, arg))
1497 return -EFAULT;
1498
1499 channel = info->line;
1500
1501 base_addr[CyRTPRL] = value & 0xff;
1502 base_addr[CyRTPRH] = (value >> 8) & 0xff;
1503 return 0;
1504}
1505
1506static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
1507{
1508 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1509 int channel;
1510 unsigned long tmp;
1511
1512 channel = info->line;
1513
1514 tmp = base_addr[CyRTPRL];
1515 return put_user(tmp, value);
1516}
1517
1518static int set_default_timeout(struct cyclades_port *info, unsigned long value)
1519{
1520 info->default_timeout = value & 0xff;
1521 return 0;
1522}
1523
1524static int
1525get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
1526{
1527 return put_user(info->default_timeout, value);
1528}
1529
1530static int
1531cy_ioctl(struct tty_struct *tty, struct file *file,
1532 unsigned int cmd, unsigned long arg)
1533{
1534 unsigned long val;
1535 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1536 int ret_val = 0;
1537 void __user *argp = (void __user *)arg;
1538
1539#ifdef SERIAL_DEBUG_OTHER
1540 printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);
1541#endif
1542
1543 lock_kernel();
1544
1545 switch (cmd) {
1546 case CYGETMON:
1547 ret_val = get_mon_info(info, argp);
1548 break;
1549 case CYGETTHRESH:
1550 ret_val = get_threshold(info, argp);
1551 break;
1552 case CYSETTHRESH:
1553 ret_val = set_threshold(info, argp);
1554 break;
1555 case CYGETDEFTHRESH:
1556 ret_val = get_default_threshold(info, argp);
1557 break;
1558 case CYSETDEFTHRESH:
1559 ret_val = set_default_threshold(info, argp);
1560 break;
1561 case CYGETTIMEOUT:
1562 ret_val = get_timeout(info, argp);
1563 break;
1564 case CYSETTIMEOUT:
1565 ret_val = set_timeout(info, argp);
1566 break;
1567 case CYGETDEFTIMEOUT:
1568 ret_val = get_default_timeout(info, argp);
1569 break;
1570 case CYSETDEFTIMEOUT:
1571 ret_val = set_default_timeout(info, (unsigned long)arg);
1572 break;
1573 case TCSBRK:
1574 ret_val = tty_check_change(tty);
1575 if (ret_val)
1576 break;
1577 tty_wait_until_sent(tty, 0);
1578 if (!arg)
1579 send_break(info, HZ / 4);
1580 break;
1581 case TCSBRKP:
1582 ret_val = tty_check_change(tty);
1583 if (ret_val)
1584 break;
1585 tty_wait_until_sent(tty, 0);
1586 send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
1587 break;
1588
1589
1590 case TIOCGSERIAL:
1591 ret_val = get_serial_info(info, argp);
1592 break;
1593 case TIOCSSERIAL:
1594 ret_val = set_serial_info(info, argp);
1595 break;
1596 default:
1597 ret_val = -ENOIOCTLCMD;
1598 }
1599 unlock_kernel();
1600
1601#ifdef SERIAL_DEBUG_OTHER
1602 printk("cy_ioctl done\n");
1603#endif
1604
1605 return ret_val;
1606}
1607
1608static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
1609{
1610 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1611
1612#ifdef SERIAL_DEBUG_OTHER
1613 printk("cy_set_termios %s\n", tty->name);
1614#endif
1615
1616 if (tty->termios->c_cflag == old_termios->c_cflag)
1617 return;
1618 config_setup(info);
1619
1620 if ((old_termios->c_cflag & CRTSCTS) &&
1621 !(tty->termios->c_cflag & CRTSCTS)) {
1622 tty->stopped = 0;
1623 cy_start(tty);
1624 }
1625#ifdef tytso_patch_94Nov25_1726
1626 if (!(old_termios->c_cflag & CLOCAL) &&
1627 (tty->termios->c_cflag & CLOCAL))
1628 wake_up_interruptible(&info->open_wait);
1629#endif
1630}
1631
1632static void cy_close(struct tty_struct *tty, struct file *filp)
1633{
1634 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1635
1636
1637#ifdef SERIAL_DEBUG_OTHER
1638 printk("cy_close %s\n", tty->name);
1639#endif
1640
1641 if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
1642 return;
1643 }
1644#ifdef SERIAL_DEBUG_OPEN
1645 printk("cy_close %s, count = %d\n", tty->name, info->count);
1646#endif
1647
1648 if ((tty->count == 1) && (info->count != 1)) {
1649
1650
1651
1652
1653
1654
1655
1656 printk("cy_close: bad serial port count; tty->count is 1, "
1657 "info->count is %d\n", info->count);
1658 info->count = 1;
1659 }
1660#ifdef SERIAL_DEBUG_COUNT
1661 printk("cyc: %d: decrementing count to %d\n", __LINE__,
1662 info->count - 1);
1663#endif
1664 if (--info->count < 0) {
1665 printk("cy_close: bad serial port count for ttys%d: %d\n",
1666 info->line, info->count);
1667#ifdef SERIAL_DEBUG_COUNT
1668 printk("cyc: %d: setting count to 0\n", __LINE__);
1669#endif
1670 info->count = 0;
1671 }
1672 if (info->count)
1673 return;
1674 info->flags |= ASYNC_CLOSING;
1675 if (info->flags & ASYNC_INITIALIZED)
1676 tty_wait_until_sent(tty, 3000);
1677 shutdown(info);
1678 cy_flush_buffer(tty);
1679 tty_ldisc_flush(tty);
1680 info->tty = NULL;
1681 if (info->blocked_open) {
1682 if (info->close_delay) {
1683 msleep_interruptible(jiffies_to_msecs
1684 (info->close_delay));
1685 }
1686 wake_up_interruptible(&info->open_wait);
1687 }
1688 info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
1689 wake_up_interruptible(&info->close_wait);
1690
1691#ifdef SERIAL_DEBUG_OTHER
1692 printk("cy_close done\n");
1693#endif
1694}
1695
1696
1697
1698
1699void cy_hangup(struct tty_struct *tty)
1700{
1701 struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1702
1703#ifdef SERIAL_DEBUG_OTHER
1704 printk("cy_hangup %s\n", tty->name);
1705#endif
1706
1707 if (serial_paranoia_check(info, tty->name, "cy_hangup"))
1708 return;
1709
1710 shutdown(info);
1711#if 0
1712 info->event = 0;
1713 info->count = 0;
1714#ifdef SERIAL_DEBUG_COUNT
1715 printk("cyc: %d: setting count to 0\n", __LINE__);
1716#endif
1717 info->tty = 0;
1718#endif
1719 info->flags &= ~ASYNC_NORMAL_ACTIVE;
1720 wake_up_interruptible(&info->open_wait);
1721}
1722
1723
1724
1725
1726
1727
1728
1729static int
1730block_til_ready(struct tty_struct *tty, struct file *filp,
1731 struct cyclades_port *info)
1732{
1733 DECLARE_WAITQUEUE(wait, current);
1734 unsigned long flags;
1735 int channel;
1736 int retval;
1737 volatile u_char *base_addr = (u_char *) BASE_ADDR;
1738
1739
1740
1741
1742
1743 if (info->flags & ASYNC_CLOSING) {
1744 interruptible_sleep_on(&info->close_wait);
1745 if (info->flags & ASYNC_HUP_NOTIFY) {
1746 return -EAGAIN;
1747 } else {
1748 return -ERESTARTSYS;
1749 }
1750 }
1751
1752
1753
1754
1755
1756 if (filp->f_flags & O_NONBLOCK) {
1757 info->flags |= ASYNC_NORMAL_ACTIVE;
1758 return 0;
1759 }
1760
1761
1762
1763
1764
1765
1766
1767
1768 retval = 0;
1769 add_wait_queue(&info->open_wait, &wait);
1770#ifdef SERIAL_DEBUG_OPEN
1771 printk("block_til_ready before block: %s, count = %d\n",
1772 tty->name, info->count);
1773
1774#endif
1775 info->count--;
1776#ifdef SERIAL_DEBUG_COUNT
1777 printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
1778#endif
1779 info->blocked_open++;
1780
1781 channel = info->line;
1782
1783 while (1) {
1784 local_irq_save(flags);
1785 base_addr[CyCAR] = (u_char) channel;
1786 base_addr[CyMSVR1] = CyRTS;
1787
1788 base_addr[CyMSVR2] = CyDTR;
1789#ifdef SERIAL_DEBUG_DTR
1790 printk("cyc: %d: raising DTR\n", __LINE__);
1791 printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
1792 base_addr[CyMSVR2]);
1793#endif
1794 local_irq_restore(flags);
1795 set_current_state(TASK_INTERRUPTIBLE);
1796 if (tty_hung_up_p(filp)
1797 || !(info->flags & ASYNC_INITIALIZED)) {
1798 if (info->flags & ASYNC_HUP_NOTIFY) {
1799 retval = -EAGAIN;
1800 } else {
1801 retval = -ERESTARTSYS;
1802 }
1803 break;
1804 }
1805 local_irq_save(flags);
1806 base_addr[CyCAR] = (u_char) channel;
1807
1808 if (!(info->flags & ASYNC_CLOSING)
1809 && (C_CLOCAL(tty)
1810 || (base_addr[CyMSVR1] & CyDCD))) {
1811 local_irq_restore(flags);
1812 break;
1813 }
1814 local_irq_restore(flags);
1815 if (signal_pending(current)) {
1816 retval = -ERESTARTSYS;
1817 break;
1818 }
1819#ifdef SERIAL_DEBUG_OPEN
1820 printk("block_til_ready blocking: %s, count = %d\n",
1821 tty->name, info->count);
1822
1823#endif
1824 schedule();
1825 }
1826 __set_current_state(TASK_RUNNING);
1827 remove_wait_queue(&info->open_wait, &wait);
1828 if (!tty_hung_up_p(filp)) {
1829 info->count++;
1830#ifdef SERIAL_DEBUG_COUNT
1831 printk("cyc: %d: incrementing count to %d\n", __LINE__,
1832 info->count);
1833#endif
1834 }
1835 info->blocked_open--;
1836#ifdef SERIAL_DEBUG_OPEN
1837 printk("block_til_ready after blocking: %s, count = %d\n",
1838 tty->name, info->count);
1839
1840#endif
1841 if (retval)
1842 return retval;
1843 info->flags |= ASYNC_NORMAL_ACTIVE;
1844 return 0;
1845}
1846
1847
1848
1849
1850
1851int cy_open(struct tty_struct *tty, struct file *filp)
1852{
1853 struct cyclades_port *info;
1854 int retval, line;
1855
1856
1857 line = tty->index;
1858 if ((line < 0) || (NR_PORTS <= line)) {
1859 return -ENODEV;
1860 }
1861 info = &cy_port[line];
1862 if (info->line < 0) {
1863 return -ENODEV;
1864 }
1865#ifdef SERIAL_DEBUG_OTHER
1866 printk("cy_open %s\n", tty->name);
1867#endif
1868 if (serial_paranoia_check(info, tty->name, "cy_open")) {
1869 return -ENODEV;
1870 }
1871#ifdef SERIAL_DEBUG_OPEN
1872 printk("cy_open %s, count = %d\n", tty->name, info->count);
1873
1874#endif
1875 info->count++;
1876#ifdef SERIAL_DEBUG_COUNT
1877 printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
1878#endif
1879 tty->driver_data = info;
1880 info->tty = tty;
1881
1882
1883
1884
1885 retval = startup(info);
1886 if (retval) {
1887 return retval;
1888 }
1889
1890 retval = block_til_ready(tty, filp, info);
1891 if (retval) {
1892#ifdef SERIAL_DEBUG_OPEN
1893 printk("cy_open returning after block_til_ready with %d\n",
1894 retval);
1895#endif
1896 return retval;
1897 }
1898#ifdef SERIAL_DEBUG_OPEN
1899 printk("cy_open done\n");
1900
1901#endif
1902 return 0;
1903}
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918static void show_version(void)
1919{
1920 printk("MVME166/167 cd2401 driver\n");
1921}
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935void mvme167_serial_console_setup(int cflag)
1936{
1937 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
1938 int ch;
1939 u_char spd;
1940 u_char rcor, rbpr, badspeed = 0;
1941 unsigned long flags;
1942
1943 local_irq_save(flags);
1944
1945
1946
1947
1948
1949
1950 base_addr[CyCAR] = 0;
1951
1952 rcor = base_addr[CyRCOR] << 5;
1953 rbpr = base_addr[CyRBPR];
1954
1955 for (spd = 0; spd < sizeof(baud_bpr); spd++)
1956 if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
1957 break;
1958 if (spd >= sizeof(baud_bpr)) {
1959 spd = 14;
1960 badspeed = 1;
1961 }
1962 initial_console_speed = spd;
1963
1964
1965
1966 my_udelay(20000L);
1967 if (base_addr[CyCCR] != 0x00) {
1968 local_irq_restore(flags);
1969
1970 return;
1971 }
1972
1973 base_addr[CyCCR] = CyCHIP_RESET;
1974 my_udelay(1000L);
1975
1976 if (base_addr[CyGFRCR] == 0x00) {
1977 local_irq_restore(flags);
1978
1979 return;
1980 }
1981
1982
1983
1984
1985
1986
1987 base_addr[CyTPR] = 10;
1988
1989 base_addr[CyPILR1] = 0x01;
1990 base_addr[CyPILR2] = 0x02;
1991 base_addr[CyPILR3] = 0x03;
1992
1993
1994
1995
1996
1997
1998
1999 for (ch = 3; ch >= 0; ch--) {
2000 base_addr[CyCAR] = (u_char) ch;
2001 base_addr[CyIER] = 0;
2002 base_addr[CyCMR] = CyASYNC;
2003 base_addr[CyLICR] = (u_char) ch << 2;
2004 base_addr[CyLIVR] = 0x5c;
2005 base_addr[CyTCOR] = baud_co[spd];
2006 base_addr[CyTBPR] = baud_bpr[spd];
2007 base_addr[CyRCOR] = baud_co[spd] >> 5;
2008 base_addr[CyRBPR] = baud_bpr[spd];
2009 base_addr[CySCHR1] = 'Q' & 0x1f;
2010 base_addr[CySCHR2] = 'X' & 0x1f;
2011 base_addr[CySCRL] = 0;
2012 base_addr[CySCRH] = 0;
2013 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2014 base_addr[CyCOR2] = 0;
2015 base_addr[CyCOR3] = Cy_1_STOP;
2016 base_addr[CyCOR4] = baud_cor4[spd];
2017 base_addr[CyCOR5] = 0;
2018 base_addr[CyCOR6] = 0;
2019 base_addr[CyCOR7] = 0;
2020 base_addr[CyRTPRL] = 2;
2021 base_addr[CyRTPRH] = 0;
2022 base_addr[CyMSVR1] = 0;
2023 base_addr[CyMSVR2] = 0;
2024 write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
2025 }
2026
2027
2028
2029
2030
2031 base_addr[CyMSVR1] = CyRTS;
2032 base_addr[CyMSVR2] = CyDTR;
2033 base_addr[CyIER] = CyRxData;
2034 write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
2035
2036 local_irq_restore(flags);
2037
2038 my_udelay(20000L);
2039
2040 printk("CD2401 initialised, chip is rev 0x%02x\n", base_addr[CyGFRCR]);
2041 if (badspeed)
2042 printk
2043 (" WARNING: Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
2044 rcor >> 5, rbpr);
2045}
2046
2047static const struct tty_operations cy_ops = {
2048 .open = cy_open,
2049 .close = cy_close,
2050 .write = cy_write,
2051 .put_char = cy_put_char,
2052 .flush_chars = cy_flush_chars,
2053 .write_room = cy_write_room,
2054 .chars_in_buffer = cy_chars_in_buffer,
2055 .flush_buffer = cy_flush_buffer,
2056 .ioctl = cy_ioctl,
2057 .throttle = cy_throttle,
2058 .unthrottle = cy_unthrottle,
2059 .set_termios = cy_set_termios,
2060 .stop = cy_stop,
2061 .start = cy_start,
2062 .hangup = cy_hangup,
2063 .tiocmget = cy_tiocmget,
2064 .tiocmset = cy_tiocmset,
2065};
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083static int __init serial167_init(void)
2084{
2085 struct cyclades_port *info;
2086 int ret = 0;
2087 int good_ports = 0;
2088 int port_num = 0;
2089 int index;
2090 int DefSpeed;
2091#ifdef notyet
2092 struct sigaction sa;
2093#endif
2094
2095 if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
2096 return 0;
2097
2098 cy_serial_driver = alloc_tty_driver(NR_PORTS);
2099 if (!cy_serial_driver)
2100 return -ENOMEM;
2101
2102#if 0
2103 scrn[1] = '\0';
2104#endif
2105
2106 show_version();
2107
2108
2109 if (serial_console_cflag)
2110 DefSpeed = serial_console_cflag & 0017;
2111 else {
2112 DefSpeed = initial_console_speed;
2113 serial_console_info = &cy_port[0];
2114 serial_console_cflag = DefSpeed | CS8;
2115#if 0
2116 serial_console = 64;
2117#endif
2118 }
2119
2120
2121
2122 cy_serial_driver->owner = THIS_MODULE;
2123 cy_serial_driver->name = "ttyS";
2124 cy_serial_driver->major = TTY_MAJOR;
2125 cy_serial_driver->minor_start = 64;
2126 cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
2127 cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
2128 cy_serial_driver->init_termios = tty_std_termios;
2129 cy_serial_driver->init_termios.c_cflag =
2130 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2131 cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
2132 tty_set_operations(cy_serial_driver, &cy_ops);
2133
2134 ret = tty_register_driver(cy_serial_driver);
2135 if (ret) {
2136 printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
2137 put_tty_driver(cy_serial_driver);
2138 return ret;
2139 }
2140
2141 port_num = 0;
2142 info = cy_port;
2143 for (index = 0; index < 1; index++) {
2144
2145 good_ports = 4;
2146
2147 if (port_num < NR_PORTS) {
2148 while (good_ports-- && port_num < NR_PORTS) {
2149
2150 info->magic = CYCLADES_MAGIC;
2151 info->type = PORT_CIRRUS;
2152 info->card = index;
2153 info->line = port_num;
2154 info->flags = STD_COM_FLAGS;
2155 info->tty = NULL;
2156 info->xmit_fifo_size = 12;
2157 info->cor1 = CyPARITY_NONE | Cy_8_BITS;
2158 info->cor2 = CyETC;
2159 info->cor3 = Cy_1_STOP;
2160 info->cor4 = 0x08;
2161 info->cor5 = 0;
2162 info->cor6 = 0;
2163 info->cor7 = 0;
2164 info->tbpr = baud_bpr[DefSpeed];
2165 info->tco = baud_co[DefSpeed];
2166 info->rbpr = baud_bpr[DefSpeed];
2167 info->rco = baud_co[DefSpeed] >> 5;
2168 info->close_delay = 0;
2169 info->x_char = 0;
2170 info->count = 0;
2171#ifdef SERIAL_DEBUG_COUNT
2172 printk("cyc: %d: setting count to 0\n",
2173 __LINE__);
2174#endif
2175 info->blocked_open = 0;
2176 info->default_threshold = 0;
2177 info->default_timeout = 0;
2178 init_waitqueue_head(&info->open_wait);
2179 init_waitqueue_head(&info->close_wait);
2180
2181
2182
2183 info->read_status_mask =
2184 CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
2185 CyFRAME | CyOVERRUN;
2186
2187
2188 printk("ttyS%d ", info->line);
2189 port_num++;
2190 info++;
2191 if (!(port_num & 7)) {
2192 printk("\n ");
2193 }
2194 }
2195 }
2196 printk("\n");
2197 }
2198 while (port_num < NR_PORTS) {
2199 info->line = -1;
2200 port_num++;
2201 info++;
2202 }
2203#ifdef CONFIG_REMOTE_DEBUG
2204 debug_setup();
2205#endif
2206 ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
2207 "cd2401_errors", cd2401_rxerr_interrupt);
2208 if (ret) {
2209 printk(KERN_ERR "Could't get cd2401_errors IRQ");
2210 goto cleanup_serial_driver;
2211 }
2212
2213 ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
2214 "cd2401_modem", cd2401_modem_interrupt);
2215 if (ret) {
2216 printk(KERN_ERR "Could't get cd2401_modem IRQ");
2217 goto cleanup_irq_cd2401_errors;
2218 }
2219
2220 ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
2221 "cd2401_txints", cd2401_tx_interrupt);
2222 if (ret) {
2223 printk(KERN_ERR "Could't get cd2401_txints IRQ");
2224 goto cleanup_irq_cd2401_modem;
2225 }
2226
2227 ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
2228 "cd2401_rxints", cd2401_rx_interrupt);
2229 if (ret) {
2230 printk(KERN_ERR "Could't get cd2401_rxints IRQ");
2231 goto cleanup_irq_cd2401_txints;
2232 }
2233
2234
2235
2236 pcc2chip[PccSCCMICR] = 0x15;
2237 pcc2chip[PccSCCTICR] = 0x15;
2238 pcc2chip[PccSCCRICR] = 0x15;
2239
2240 pcc2chip[PccIMLR] = 3;
2241
2242 return 0;
2243cleanup_irq_cd2401_txints:
2244 free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
2245cleanup_irq_cd2401_modem:
2246 free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
2247cleanup_irq_cd2401_errors:
2248 free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
2249cleanup_serial_driver:
2250 if (tty_unregister_driver(cy_serial_driver))
2251 printk(KERN_ERR
2252 "Couldn't unregister MVME166/7 serial driver\n");
2253 put_tty_driver(cy_serial_driver);
2254 return ret;
2255}
2256
2257module_init(serial167_init);
2258
2259#ifdef CYCLOM_SHOW_STATUS
2260static void show_status(int line_num)
2261{
2262 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2263 int channel;
2264 struct cyclades_port *info;
2265 unsigned long flags;
2266
2267 info = &cy_port[line_num];
2268 channel = info->line;
2269 printk(" channel %d\n", channel);
2270 printk(" cy_port\n");
2271 printk(" card line flags = %d %d %x\n",
2272 info->card, info->line, info->flags);
2273 printk
2274 (" *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
2275 (long)info->tty, info->read_status_mask, info->timeout,
2276 info->xmit_fifo_size);
2277 printk(" cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
2278 info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
2279 info->cor6, info->cor7);
2280 printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
2281 info->rbpr, info->rco);
2282 printk(" close_delay event count = %d %d %d\n", info->close_delay,
2283 info->event, info->count);
2284 printk(" x_char blocked_open = %x %x\n", info->x_char,
2285 info->blocked_open);
2286 printk(" open_wait = %lx %lx %lx\n", (long)info->open_wait);
2287
2288 local_irq_save(flags);
2289
2290
2291
2292 printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
2293 printk(" CyCAR %x\n", base_addr[CyCAR]);
2294 printk(" CyRISR %x\n", base_addr[CyRISR]);
2295 printk(" CyTISR %x\n", base_addr[CyTISR]);
2296 printk(" CyMISR %x\n", base_addr[CyMISR]);
2297 printk(" CyRIR %x\n", base_addr[CyRIR]);
2298 printk(" CyTIR %x\n", base_addr[CyTIR]);
2299 printk(" CyMIR %x\n", base_addr[CyMIR]);
2300 printk(" CyTPR %x\n", base_addr[CyTPR]);
2301
2302 base_addr[CyCAR] = (u_char) channel;
2303
2304
2305
2306#if 0
2307 printk(" CyRIVR %x\n", base_addr[CyRIVR]);
2308 printk(" CyTIVR %x\n", base_addr[CyTIVR]);
2309 printk(" CyMIVR %x\n", base_addr[CyMIVR]);
2310 printk(" CyMISR %x\n", base_addr[CyMISR]);
2311#endif
2312
2313
2314
2315 printk(" CyCCR %x\n", base_addr[CyCCR]);
2316 printk(" CyIER %x\n", base_addr[CyIER]);
2317 printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
2318 printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
2319 printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
2320 printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
2321 printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
2322#if 0
2323 printk(" CyCCSR %x\n", base_addr[CyCCSR]);
2324 printk(" CyRDCR %x\n", base_addr[CyRDCR]);
2325#endif
2326 printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
2327 printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
2328#if 0
2329 printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
2330 printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
2331 printk(" CySCRL %x\n", base_addr[CySCRL]);
2332 printk(" CySCRH %x\n", base_addr[CySCRH]);
2333 printk(" CyLNC %x\n", base_addr[CyLNC]);
2334 printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
2335 printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
2336#endif
2337 printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
2338 printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
2339 printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
2340 printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
2341 printk(" CyRBPR %x\n", base_addr[CyRBPR]);
2342 printk(" CyRCOR %x\n", base_addr[CyRCOR]);
2343 printk(" CyTBPR %x\n", base_addr[CyTBPR]);
2344 printk(" CyTCOR %x\n", base_addr[CyTCOR]);
2345
2346 local_irq_restore(flags);
2347}
2348#endif
2349
2350#if 0
2351
2352
2353
2354
2355void console_setup(char *str, int *ints)
2356{
2357 char *s;
2358 int baud, bits, parity;
2359 int cflag = 0;
2360
2361
2362 if (ints[0] > 3 || ints[1] > 3)
2363 return;
2364
2365
2366 baud = 2400;
2367 bits = 8;
2368 parity = 'n';
2369 if (ints[2])
2370 baud = ints[2];
2371 if ((s = strchr(str, ','))) {
2372 do {
2373 s++;
2374 } while (*s >= '0' && *s <= '9');
2375 if (*s)
2376 parity = *s++;
2377 if (*s)
2378 bits = *s - '0';
2379 }
2380
2381
2382 switch (baud) {
2383 case 1200:
2384 cflag |= B1200;
2385 break;
2386 case 9600:
2387 cflag |= B9600;
2388 break;
2389 case 19200:
2390 cflag |= B19200;
2391 break;
2392 case 38400:
2393 cflag |= B38400;
2394 break;
2395 case 2400:
2396 default:
2397 cflag |= B2400;
2398 break;
2399 }
2400 switch (bits) {
2401 case 7:
2402 cflag |= CS7;
2403 break;
2404 default:
2405 case 8:
2406 cflag |= CS8;
2407 break;
2408 }
2409 switch (parity) {
2410 case 'o':
2411 case 'O':
2412 cflag |= PARODD;
2413 break;
2414 case 'e':
2415 case 'E':
2416 cflag |= PARENB;
2417 break;
2418 }
2419
2420 serial_console_info = &cy_port[ints[1]];
2421 serial_console_cflag = cflag;
2422 serial_console = ints[1] + 64;
2423}
2424#endif
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441void serial167_console_write(struct console *co, const char *str,
2442 unsigned count)
2443{
2444 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2445 unsigned long flags;
2446 volatile u_char sink;
2447 u_char ier;
2448 int port;
2449 u_char do_lf = 0;
2450 int i = 0;
2451
2452 local_irq_save(flags);
2453
2454
2455
2456 port = 0;
2457 base_addr[CyCAR] = (u_char) port;
2458 while (base_addr[CyCCR])
2459 ;
2460 base_addr[CyCCR] = CyENB_XMTR;
2461
2462 ier = base_addr[CyIER];
2463 base_addr[CyIER] = CyTxMpty;
2464
2465 while (1) {
2466 if (pcc2chip[PccSCCTICR] & 0x20) {
2467
2468 sink = pcc2chip[PccTPIACKR];
2469 if ((base_addr[CyLICR] >> 2) == port) {
2470 if (i == count) {
2471
2472 base_addr[CyTEOIR] = CyNOTRANS;
2473 break;
2474 }
2475 if (do_lf) {
2476 base_addr[CyTDR] = '\n';
2477 str++;
2478 i++;
2479 do_lf = 0;
2480 } else if (*str == '\n') {
2481 base_addr[CyTDR] = '\r';
2482 do_lf = 1;
2483 } else {
2484 base_addr[CyTDR] = *str++;
2485 i++;
2486 }
2487 base_addr[CyTEOIR] = 0;
2488 } else
2489 base_addr[CyTEOIR] = CyNOTRANS;
2490 }
2491 }
2492
2493 base_addr[CyIER] = ier;
2494
2495 local_irq_restore(flags);
2496}
2497
2498static struct tty_driver *serial167_console_device(struct console *c,
2499 int *index)
2500{
2501 *index = c->index;
2502 return cy_serial_driver;
2503}
2504
2505static struct console sercons = {
2506 .name = "ttyS",
2507 .write = serial167_console_write,
2508 .device = serial167_console_device,
2509 .flags = CON_PRINTBUFFER,
2510 .index = -1,
2511};
2512
2513static int __init serial167_console_init(void)
2514{
2515 if (vme_brdtype == VME_TYPE_MVME166 ||
2516 vme_brdtype == VME_TYPE_MVME167 ||
2517 vme_brdtype == VME_TYPE_MVME177) {
2518 mvme167_serial_console_setup(0);
2519 register_console(&sercons);
2520 }
2521 return 0;
2522}
2523
2524console_initcall(serial167_console_init);
2525
2526#ifdef CONFIG_REMOTE_DEBUG
2527void putDebugChar(int c)
2528{
2529 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2530 unsigned long flags;
2531 volatile u_char sink;
2532 u_char ier;
2533 int port;
2534
2535 local_irq_save(flags);
2536
2537
2538
2539 port = DEBUG_PORT;
2540 base_addr[CyCAR] = (u_char) port;
2541 while (base_addr[CyCCR])
2542 ;
2543 base_addr[CyCCR] = CyENB_XMTR;
2544
2545 ier = base_addr[CyIER];
2546 base_addr[CyIER] = CyTxMpty;
2547
2548 while (1) {
2549 if (pcc2chip[PccSCCTICR] & 0x20) {
2550
2551 sink = pcc2chip[PccTPIACKR];
2552 if ((base_addr[CyLICR] >> 2) == port) {
2553 base_addr[CyTDR] = c;
2554 base_addr[CyTEOIR] = 0;
2555 break;
2556 } else
2557 base_addr[CyTEOIR] = CyNOTRANS;
2558 }
2559 }
2560
2561 base_addr[CyIER] = ier;
2562
2563 local_irq_restore(flags);
2564}
2565
2566int getDebugChar()
2567{
2568 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2569 unsigned long flags;
2570 volatile u_char sink;
2571 u_char ier;
2572 int port;
2573 int i, c;
2574
2575 i = debugiq.out;
2576 if (i != debugiq.in) {
2577 c = debugiq.buf[i];
2578 if (++i == DEBUG_LEN)
2579 i = 0;
2580 debugiq.out = i;
2581 return c;
2582 }
2583
2584
2585 local_irq_save(flags);
2586
2587
2588
2589 port = DEBUG_PORT;
2590 base_addr[CyCAR] = (u_char) port;
2591#if 0
2592 while (base_addr[CyCCR])
2593 ;
2594 base_addr[CyCCR] = CyENB_RCVR;
2595#endif
2596 ier = base_addr[CyIER];
2597 base_addr[CyIER] = CyRxData;
2598
2599 while (1) {
2600 if (pcc2chip[PccSCCRICR] & 0x20) {
2601
2602 sink = pcc2chip[PccRPIACKR];
2603 if ((base_addr[CyLICR] >> 2) == port) {
2604 int cnt = base_addr[CyRFOC];
2605 while (cnt-- > 0) {
2606 c = base_addr[CyRDR];
2607 if (c == 0)
2608 printk
2609 ("!! debug char is null (cnt=%d) !!",
2610 cnt);
2611 else
2612 queueDebugChar(c);
2613 }
2614 base_addr[CyREOIR] = 0;
2615 i = debugiq.out;
2616 if (i == debugiq.in)
2617 panic("Debug input queue empty!");
2618 c = debugiq.buf[i];
2619 if (++i == DEBUG_LEN)
2620 i = 0;
2621 debugiq.out = i;
2622 break;
2623 } else
2624 base_addr[CyREOIR] = CyNOTRANS;
2625 }
2626 }
2627
2628 base_addr[CyIER] = ier;
2629
2630 local_irq_restore(flags);
2631
2632 return (c);
2633}
2634
2635void queueDebugChar(int c)
2636{
2637 int i;
2638
2639 i = debugiq.in;
2640 debugiq.buf[i] = c;
2641 if (++i == DEBUG_LEN)
2642 i = 0;
2643 if (i != debugiq.out)
2644 debugiq.in = i;
2645}
2646
2647static void debug_setup()
2648{
2649 unsigned long flags;
2650 volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
2651 int i, cflag;
2652
2653 cflag = B19200;
2654
2655 local_irq_save(flags);
2656
2657 for (i = 0; i < 4; i++) {
2658 base_addr[CyCAR] = i;
2659 base_addr[CyLICR] = i << 2;
2660 }
2661
2662 debugiq.in = debugiq.out = 0;
2663
2664 base_addr[CyCAR] = DEBUG_PORT;
2665
2666
2667 i = cflag & CBAUD;
2668
2669 base_addr[CyIER] = 0;
2670
2671 base_addr[CyCMR] = CyASYNC;
2672 base_addr[CyLICR] = DEBUG_PORT << 2;
2673 base_addr[CyLIVR] = 0x5c;
2674
2675
2676
2677 base_addr[CyTCOR] = baud_co[i];
2678 base_addr[CyTBPR] = baud_bpr[i];
2679 base_addr[CyRCOR] = baud_co[i] >> 5;
2680 base_addr[CyRBPR] = baud_bpr[i];
2681
2682
2683
2684 base_addr[CySCHR1] = 0;
2685 base_addr[CySCHR2] = 0;
2686 base_addr[CySCRL] = 0;
2687 base_addr[CySCRH] = 0;
2688 base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2689 base_addr[CyCOR2] = 0;
2690 base_addr[CyCOR3] = Cy_1_STOP;
2691 base_addr[CyCOR4] = baud_cor4[i];
2692 base_addr[CyCOR5] = 0;
2693 base_addr[CyCOR6] = 0;
2694 base_addr[CyCOR7] = 0;
2695
2696 write_cy_cmd(base_addr, CyINIT_CHAN);
2697 write_cy_cmd(base_addr, CyENB_RCVR);
2698
2699 base_addr[CyCAR] = DEBUG_PORT;
2700
2701 base_addr[CyRTPRL] = 2;
2702 base_addr[CyRTPRH] = 0;
2703
2704 base_addr[CyMSVR1] = CyRTS;
2705 base_addr[CyMSVR2] = CyDTR;
2706
2707 base_addr[CyIER] = CyRxData;
2708
2709 local_irq_restore(flags);
2710
2711}
2712
2713#endif
2714
2715MODULE_LICENSE("GPL");
2716