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