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