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