xref: /csrg-svn/sys/news3400/sio/scc.c (revision 57610)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7  *
8  * %sccs.include.redist.c%
9  *
10  * from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY
11  *
12  *	@(#)scc.c	7.3 (Berkeley) 01/20/93
13  */
14 
15 /*
16  * LH8530 SCC (serial communication controller) driver
17  *
18  * NOTE: This driver is available only for news700/1200/1700/3400.
19  *
20  * Any code and mechanism in this module may not be used
21  * in any form without permissions.  COPYRIGHT (C) 1989-
22  * SONY  Corporation,   Super Microsystems Group (SMSG),
23  * Work Station Division, all rights RESERVED.
24  */
25 
26 #include <machine/fix_machine_type.h>
27 #include <machine/adrsmap.h>
28 
29 #include "rs.h"
30 
31 #include <sys/param.h>
32 #include <sys/ioctl.h>
33 #include <sys/tty.h>
34 #include <sys/malloc.h>
35 
36 #include <news3400/sio/sccparam.h>
37 #include <news3400/sio/sccreg.h>
38 #include <news3400/sio/scc.h>
39 #include <news3400/sio/scc.conf>
40 
41 #define	PROBE_DATA	0x55
42 
43 #ifdef mips
44 #define	VOLATILE	volatile
45 #else
46 #define	VOLATILE
47 #endif
48 
49 int	tty00_is_console = 0;
50 
51 #define	SCC_BUFSIZE	256
52 
53 char	scc_buf[2][SCC_BUFSIZE];
54 
55 scc_open(chan)
56 	int chan;
57 {
58 	register Scc_channel *scc = &sccsw[chan];
59 	register int s;
60 
61 	s = splscc();
62 	if ((scc->scc_status & CHAN_ACTIVE) == 0) {
63 		scc_init(chan);
64 		if (chan <= SCC_REMOTE1)
65 			scc->r_dma.dma_addr = scc_buf[chan];
66 		else
67 			scc->r_dma.dma_addr =
68 				malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK);
69 		scc->r_dma.dma_count = 0;
70 		scc->scc_status |= CHAN_ACTIVE;
71 	}
72 	(void) splx(s);
73 	return (0);
74 }
75 
76 scc_probe(chan)
77 	register int chan;
78 {
79 	VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
80 	int s, temp, probe;
81 
82 	if (badaddr(port, 1))
83 		return (0);
84 	s = splscc();
85 	temp = scc_read_reg(chan, RR12);
86 	scc_write_reg(chan, WR12, PROBE_DATA);
87 	probe = scc_read_reg(chan, RR12);
88 	scc_write_reg(chan, WR12, temp);
89 	(void) splx(s);
90 	return (probe == PROBE_DATA);
91 }
92 
93 scc_getc(chan)
94 	int chan;
95 {
96 	VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
97 	int c;
98 
99 	if (port->ctrl & R0_RxCA) {
100 		SCCWAIT;
101 		c = port->data;
102 		SCCWAIT;
103 		return (c);
104 	}
105 	SCCWAIT;
106 	return (-1);
107 }
108 
109 #ifndef notdef
110 scc_putc(chan, c)
111 	int chan, c;
112 {
113 	register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
114 
115 	while ((port->ctrl & R0_TxBE) == 0)
116 		SCCWAIT;
117 	SCCWAIT;
118 	port->data = c;
119 	SCCWAIT;
120 }
121 #else
122 scc_putc(chan, c)
123         int chan, c;
124 {
125 	register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
126 	register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl;
127 	register VOLATILE u_char *data = &sccsw[chan].scc_port->data;
128 
129         SCCWAIT;
130         while ((*ctrl & R0_TxBE) == 0) {
131                 SCCWAIT;
132         }
133         SCCWAIT;
134 
135         *ctrl = W0_RES_TxINT;
136         SCCWAIT;
137         *data = (char)(c & 0xff);
138         SCCWAIT;
139         scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY);
140         SCCWAIT;
141 }
142 #endif
143 
144 scc_init(chan)
145 	int chan;
146 {
147 	register VOLATILE struct scc_reg *port;
148 	register char *data;
149 	register int i;
150 	register Scc_channel *scc = &sccsw[chan];
151 	int s;
152 
153 	s = splscc();
154 	data = scc->scc_init;
155 	port = scc->scc_port;
156 	for (i = 0; i < N_INITDATA; i++) {
157 		port->ctrl = *data++;
158 		SCCWAIT;
159 	}
160 	scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f);
161 /* KU:XXX
162 This must be bug because scc->scc_param is not initialized yet.
163 	scc_set_param(chan, scc->scc_param);
164 */
165 	(void) splx(s);
166 }
167 
168 #define	vec_to_scc(vec)		((((vec) - SCCVEC0) >> 3) & 0x000f)
169 #define	vec_to_chan(vec)	scc2chan[vec_to_scc(vec)]
170 
171 int scc2chan[] = {
172 	1,	0,
173 	3,	2,
174 	5,	4,
175 	7,	6,
176 	9,	8
177 };
178 
179 scc_rint(vec)
180 	int vec;
181 {
182 	int chan = vec_to_chan(vec);
183 	register Scc_channel *scc = &sccsw[chan];
184 	register VOLATILE struct scc_reg *port = scc->scc_port;
185 	register int c;
186 
187 	if ((scc->scc_status & CHAN_ACTIVE) == 0) {
188 		scc_reset(chan);
189 		goto out;
190 	}
191 	if (scc->scc_status & LINE_BREAK){
192 		scc->scc_status &= ~LINE_BREAK;
193 		c = port->data;
194 		SCCWAIT;
195 	}
196 	while (port->ctrl & R0_RxCA) {
197 		SCCWAIT;
198 		c = port->data;
199 		SCCWAIT;
200 #if NRS > 0
201 		scc_pdma(chan, c);
202 #endif
203 	}
204 	SCCWAIT;
205 out:
206 	port->ctrl = W0_RES_IUS;
207 	SCCWAIT;
208 }
209 
210 #if NRS > 0
211 scc_enable(chan)
212 	int chan;
213 {
214 	register Scc_channel *scc = &sccsw[chan];
215 	int n;
216 	int s;
217 
218 	s = splscc();
219 	if ((n = scc->r_dma.dma_count) > 0) {
220 		scc->r_dma.dma_count = 0;
221 		rsrint(chan, scc->r_dma.dma_addr, n);
222 	} else
223 		scc->scc_status |= ENABLE;
224 	(void) splx(s);
225 }
226 
227 scc_pdma(chan, c)
228 	int chan;
229 	int c;
230 {
231 	register Scc_channel *scc = &sccsw[chan];
232 	int n;
233 
234 	if (scc->r_dma.dma_count >= SCC_BUFSIZE)
235 		printf("rs%d soft fifo overflow\n", chan);
236 	else
237 		scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c;
238 	if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) {
239 		scc->scc_status &= ~ENABLE;
240 		n = scc->r_dma.dma_count;
241 		scc->r_dma.dma_count = 0;
242 		rsrint(chan, scc->r_dma.dma_addr, n);
243 	}
244 }
245 #endif /* NRS > 0 */
246 
247 scc_xint(vec)
248 	int vec;
249 {
250 	int chan = vec_to_chan(vec);
251 	register Scc_channel *scc = &sccsw[chan];
252 	register VOLATILE struct scc_reg *port = scc->scc_port;
253 
254 	if (scc->scc_status & OSTOP)
255 		scc->scc_status &= ~(OACTIVE|OSTOP);
256 	if (scc->scc_status & OFLUSH) {
257 		scc->x_dma.dma_count = 0;
258 		scc->scc_status &= ~(OACTIVE|OFLUSH);
259 	}
260 	if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) {
261 		port->data = *(scc->x_dma.dma_addr)++;
262 		SCCWAIT;
263 		scc->x_dma.dma_count--;
264 	} else {
265 		port->ctrl = W0_RES_TxINT;
266 		SCCWAIT;
267 		scc->scc_status &= ~OACTIVE;
268 #if NRS > 0
269 		if (scc->x_dma.dma_count == 0)
270 			rsxint(chan);
271 #endif
272 	}
273 	port->ctrl = W0_RES_IUS;
274 	SCCWAIT;
275 }
276 
277 scc_sint(vec)
278 	int vec;
279 {
280 	int chan = vec_to_chan(vec);
281 	register Scc_channel *scc = &sccsw[chan];
282 	register VOLATILE struct scc_reg *port = scc->scc_port;
283 	register int status;
284 	register int param = 0;
285 
286 	port->ctrl = W0_RES_EXT;
287 	SCCWAIT;
288 	if ((scc->scc_status & CHAN_ACTIVE) == 0) {
289 		scc_reset(chan);
290 		goto out;
291 	}
292 	status = port->ctrl;
293 	SCCWAIT;
294 	if (status & R0_DCD)
295 		param |= DCD;
296 	if (status & R0_CTS)
297 		param |= CTS;
298 	if (status & R0_BREAK){
299 		param |= RBREAK;
300 		scc->scc_status |= LINE_BREAK;
301 	}
302 	if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) {
303 		scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param;
304 #if NRS > 0
305 		rssint(chan, scc->scc_param);
306 #endif
307 	}
308 out:
309 	port->ctrl = W0_RES_IUS;
310 	SCCWAIT;
311 }
312 
313 scc_cint(vec)
314 	int vec;
315 {
316 	int chan = vec_to_chan(vec);
317 	register Scc_channel *scc = &sccsw[chan];
318 	register VOLATILE struct scc_reg *port = scc->scc_port;
319 	register int status;
320 	int c;
321 
322 	if ((scc->scc_status & CHAN_ACTIVE) == 0) {
323 		scc_reset(chan);
324 		goto out;
325 	}
326 	status = scc_read_reg(chan, RR1);
327 	if (status & R1_CRC)
328 		scc->scc_param |= FRAMING_ERROR;
329 	if (status & R1_OVRUN) {
330 		if ((scc->scc_param & OVERRUN_ERROR) == 0) {
331 			scc->scc_param |= OVERRUN_ERROR;
332 #if NRS > 0
333 			rssint(chan, scc->scc_param);
334 #endif
335 		}
336 	}
337 	if (status & R1_PARITY) {
338 		scc->scc_param |= SCC_PARITY_ERROR;
339 		while (port->ctrl & R0_RxCA) {
340 			SCCWAIT;
341 			c = port->data;
342 			SCCWAIT;
343 #if NRS > 0
344 			if (scc->scc_param & NOCHECK)
345 				scc_pdma(chan, c);
346 #endif
347 		}
348 		SCCWAIT;
349 	}
350 out:
351 	port->ctrl = W0_RES_ERROR;
352 	SCCWAIT;
353 	port->ctrl = W0_RES_IUS;
354 	SCCWAIT;
355 }
356 
357 scc_write_reg(chan, reg, data)
358 	int chan, reg, data;
359 {
360 	register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
361 
362 	port->ctrl = reg;
363 	SCCWAIT;
364 	port->ctrl = data;
365 	SCCWAIT;
366 }
367 
368 scc_read_reg(chan, reg)
369 	int chan, reg;
370 {
371 	register VOLATILE struct scc_reg *port = sccsw[chan].scc_port;
372 	int result;
373 
374 	port->ctrl = reg;
375 	SCCWAIT;
376 	result = port->ctrl;
377 	SCCWAIT;
378 	return (result);
379 }
380 
381 #ifdef news3400
382 #define	DSRA	0x01
383 #define	RIA	0x02
384 #define	DSRB	0x04
385 #define	RIB	0x08
386 
387 #define	DSRC	0x01
388 #define	RIC	0x02
389 #define	DSRD	0x04
390 #define	RID	0x08
391 #define	DSRE	0x10
392 #define	RIE	0x20
393 #define	DSRF	0x40
394 #define	RIF	0x80
395 #endif /* news3400 */
396 
397 struct ri_dsr {
398 	char	*status;
399 	int	ri;
400 	int	dsr;
401 } ri_dsr[] = {
402 	{ (char *)SCC_STATUS0, RIA, DSRA },
403 	{ (char *)SCC_STATUS0, RIB, DSRB },
404 #if !defined(news3200)
405 	{ (char *)SCC_STATUS1, RIC, DSRC },
406 	{ (char *)SCC_STATUS1, RID, DSRD },
407 	{ (char *)SCC_STATUS1, RIE, DSRE },
408 	{ (char *)SCC_STATUS1, RIF, DSRF },
409 	{ (char *)SCC_STATUS2, RIC, DSRC },
410 	{ (char *)SCC_STATUS2, RID, DSRD },
411 	{ (char *)SCC_STATUS2, RIE, DSRE },
412 	{ (char *)SCC_STATUS2, RIF, DSRF }
413 #endif /* !news3200 */
414 };
415 
416 get_ri_dsr(chan)
417 	int chan;
418 {
419 	register struct ri_dsr *p;
420 	register int status, param;
421 
422 	param = 0;
423 	p = &ri_dsr[chan];
424 	status = *p->status;
425 	if ((status & p->ri) == 0)
426 		param |= RI;
427 	if ((status & p->dsr) == 0)
428 		param |= DSR;
429 	return (param);
430 }
431 
432 #if defined(news3400)
433 /*
434  *	tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5);
435  */
436 static int tc0[] = {
437 	0,		/* B0 */
438 	3070,		/* B50 */
439 	2046,		/* B75 */
440 	1394,		/* B110 */
441 	1144,		/* B134 */
442 	1022,		/* B150 */
443 	766,		/* B200 */
444 	510,		/* B300 */
445 	254,		/* B600 */
446 	126,		/* B1200 */
447 	83,		/* B1800 */
448 	62,		/* B2400 */
449 	30,		/* B4800 */
450 	14,		/* B9600 */
451 	6,		/* EXTA (B19200) */
452 	2		/* EXTB (B38400) */
453 	};
454 #endif /* news3400 */
455 
456 static int tc1[] = {
457 /*
458  *	tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5);
459  */
460 	0,		/* B0 */
461 	2302,		/* B50 */
462 	1534,		/* B75 */
463 	1045,		/* B110 */
464 	858,		/* B134 */
465 	766,		/* B150 */
466 	574,		/* B200 */
467 	382,		/* B300 */
468 	190,		/* B600 */
469 	94,		/* B1200 */
470 	62,		/* B1800 */
471 	46,		/* B2400 */
472 	22,		/* B4800 */
473 	10,		/* B9600 */
474 	4,		/* B19200 */
475 	1,		/* B38400 */
476 };
477 
478 scc_set_param(chan, param)
479 	int chan;
480 	register int param;
481 {
482 	register Scc_channel *scc = &sccsw[chan];
483 	register int bit, baud, *tc;
484 	int s;
485 
486 	s = splscc();
487 
488 	/*
489 	 * Baud rate / external clock
490 	 */
491 	if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 &&
492 	    param & EXTCLK_ENABLE) {
493 		scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC);
494 		bit = W4_X1;
495 	} else {
496 		tc = (chan <= SCC_REMOTE1) ? tc0 : tc1;
497 		scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG);
498 		scc_write_reg(chan, WR12, tc[baud] & 0xff);
499 		scc_write_reg(chan, WR13, tc[baud] >> 8);
500 		bit = W4_X16;
501 	}
502 
503 	/*
504 	 * Clock mode / parity / stop bit
505 	 */
506 	if (param & PARITY) {
507 		bit |= W4_PARITY;
508 		if (param & EVEN)
509 			bit |= W4_EVEN;
510 	}
511 	switch (param & STOPBIT) {
512 
513 	case STOP1:
514 		bit |= W4_STOP1;
515 		break;
516 
517 	case STOP1_5:
518 		bit |= W4_STOP1_5;
519 		break;
520 
521 	case STOP2:
522 		bit |= W4_STOP2;
523 		break;
524 
525 	}
526 	scc_write_reg(chan, WR4, bit);
527 
528 	/*
529 	 * Receiver enable / receive character size / auto enable
530 	 */
531 	bit = (param & RXE ? W3_RxE : 0);
532 	switch (param & CHAR_SIZE) {
533 
534 	case C5BIT:
535 		break;
536 
537 	case C6BIT:
538 		bit |= W3_Rx6BIT;
539 		break;
540 
541 	case C7BIT:
542 		bit |= W3_Rx7BIT;
543 		break;
544 
545 	case C8BIT:
546 		bit |= W3_Rx8BIT;
547 		break;
548 	}
549 #ifdef AUTO_ENABLE
550 	if (param & AUTO_ENABLE)
551 		bit |= W3_AUTO;
552 #endif /* AUTO_ENABLE */
553 	scc_write_reg(chan, WR3, bit);
554 
555 	/*
556 	 * Transmitter enable / transmit character size / RTS / DTR / BREAK
557 	 */
558 	bit = (param & TXE ? W5_TxE : 0);
559 	switch (param & CHAR_SIZE) {
560 
561 	case C5BIT:
562 		break;
563 
564 	case C6BIT:
565 		bit |= W5_Tx6BIT;
566 		break;
567 
568 	case C7BIT:
569 		bit |= W5_Tx7BIT;
570 		break;
571 
572 	case C8BIT:
573 		bit |= W5_Tx8BIT;
574 		break;
575 	}
576 	if (param & RTS)
577 		bit |= W5_RTS;
578 	if (param & DTR)
579 		bit |= W5_DTR;
580 	if (param & XBREAK)
581 		bit |= W5_BREAK;
582 	scc_write_reg(chan, WR5, bit);
583 	scc->scc_param = param;
584 	(void) splx(s);
585 	return (0);
586 }
587 
588 scc_get_param(chan)
589 	int chan;
590 {
591 	register Scc_channel *scc = &sccsw[chan];
592 
593 	scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan);
594 	return (scc->scc_param);
595 }
596 
597 scc_get_status(chan)
598 	int chan;
599 {
600 
601 	return (sccsw[chan].scc_status);
602 }
603 
604 scc_set_status(chan, stat)
605 	int chan, stat;
606 {
607 
608 	sccsw[chan].scc_status = stat;
609 
610 	return (0);
611 }
612 
613 scc_flush(chan)
614 	int chan;
615 {
616 	register Scc_channel *scc = &sccsw[chan];
617 
618 	if (scc->scc_status & OACTIVE)
619 		scc->scc_status |= OFLUSH;
620 	else if (scc->x_dma.dma_count > 0) {
621 		scc->x_dma.dma_count = 0;
622 #if NRS > 0
623 		rsxint(chan);
624 #endif
625 	}
626 	return (0);
627 }
628 
629 scc_start(chan)
630 	int chan;
631 {
632 	register Scc_channel *scc = &sccsw[chan];
633 
634 	if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) {
635 		scc->scc_port->data = *(scc->x_dma.dma_addr)++;
636 		SCCWAIT;
637 		scc->x_dma.dma_count--;
638 		scc->scc_status |= OACTIVE;
639 	}
640 	return (0);
641 }
642 
643 scc_stop(chan)
644 	int chan;
645 {
646 	register Scc_channel *scc = &sccsw[chan];
647 
648 	if (scc->scc_status & OACTIVE)
649 		scc->scc_status |= OSTOP;
650 	return (0);
651 }
652 
653 scc_write(chan, buf, count)
654 	int chan;
655 	caddr_t buf;
656 	int count;
657 {
658 	register Scc_channel *scc = &sccsw[chan];
659 
660 	if (count <= 0)
661 		return (0);
662 	scc->x_dma.dma_addr = buf;
663 	scc->x_dma.dma_count = count;
664 	scc_start(chan);
665 	return (count);
666 }
667 
668 scc_error_write(chan, buf, count)
669 	int chan;
670 	register char *buf;
671 	register int count;
672 {
673 	register int i;
674 
675 	for (i = 0; i < count; i++)
676 		scc_putc(chan, *buf++);
677 	return (i);
678 }
679 
680 scc_reset(chan)
681 	int chan;
682 {
683 	register Scc_channel *scc = &sccsw[chan];
684 
685 	while (scc_getc(chan) != -1)
686 		;
687 	scc->scc_status &= ~CHAN_ACTIVE;
688 }
689