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