xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 54008)
1*54008Sfujita /*
2*54008Sfujita  * Copyright (c) 1992 OMRON Corporation.
3*54008Sfujita  * Copyright (c) 1992 The Regents of the University of California.
4*54008Sfujita  * All rights reserved.
5*54008Sfujita  *
6*54008Sfujita  * This code is derived from software contributed to Berkeley by
7*54008Sfujita  * OMRON Corporation.
8*54008Sfujita  *
9*54008Sfujita  * %sccs.include.redist.c%
10*54008Sfujita  *
11*54008Sfujita  *	@(#)sio.c	7.1 (Berkeley) 06/15/92
12*54008Sfujita  */
13*54008Sfujita 
14*54008Sfujita /*
15*54008Sfujita  * sio.c -- NEC uPD7201A UART Device Driver
16*54008Sfujita  * by A.Fujita, NOV-25-1991
17*54008Sfujita  */
18*54008Sfujita 
19*54008Sfujita #include "sio.h"
20*54008Sfujita #if NSIO > 0
21*54008Sfujita 
22*54008Sfujita #undef LOCAL_CONSOLE
23*54008Sfujita 
24*54008Sfujita /*
25*54008Sfujita  *  OMRON LUNA internal serial interface
26*54008Sfujita  *  uese NEC uPD7201A SIO
27*54008Sfujita  */
28*54008Sfujita 
29*54008Sfujita #include "sys/param.h"
30*54008Sfujita #include "sys/systm.h"
31*54008Sfujita #include "sys/ioctl.h"
32*54008Sfujita #include "sys/proc.h"
33*54008Sfujita #include "sys/tty.h"
34*54008Sfujita #include "sys/conf.h"
35*54008Sfujita #include "sys/file.h"
36*54008Sfujita #include "sys/uio.h"
37*54008Sfujita #include "sys/kernel.h"
38*54008Sfujita #include "sys/syslog.h"
39*54008Sfujita 
40*54008Sfujita #include "device.h"
41*54008Sfujita #include "sioreg.h"
42*54008Sfujita 
43*54008Sfujita #define SIO_IPL		6
44*54008Sfujita 
45*54008Sfujita int	sioprobe();
46*54008Sfujita struct	driver siodriver = {
47*54008Sfujita 	sioprobe, "sio",
48*54008Sfujita };
49*54008Sfujita 
50*54008Sfujita void	siostart();
51*54008Sfujita int	sioparam(), siointr();
52*54008Sfujita int	sio_active;
53*54008Sfujita int	sioconsole = -1;
54*54008Sfujita int	sioconsinit;
55*54008Sfujita int	siodefaultrate = TTYDEF_SPEED;
56*54008Sfujita int	siomajor;
57*54008Sfujita struct	siodevice *sio_addr[2];
58*54008Sfujita struct	tty sio_tty[NSIO];
59*54008Sfujita 
60*54008Sfujita #define	siounit(x)		minor(x)
61*54008Sfujita 
62*54008Sfujita 
63*54008Sfujita #ifndef	LOCAL_CONSOLE
64*54008Sfujita 
65*54008Sfujita /*
66*54008Sfujita  * local buffering
67*54008Sfujita  */
68*54008Sfujita 
69*54008Sfujita #define LOCAL_BUFSIZ	128
70*54008Sfujita 
71*54008Sfujita struct local_buf {
72*54008Sfujita 	u_char	*push;
73*54008Sfujita 	u_char	*pop;
74*54008Sfujita 	u_char	buf[LOCAL_BUFSIZ+4];
75*54008Sfujita };
76*54008Sfujita 
77*54008Sfujita struct local_buf rbuf, *rbp = &rbuf;
78*54008Sfujita 
79*54008Sfujita 
80*54008Sfujita siolbufinit(bp)
81*54008Sfujita 	register struct local_buf *bp;
82*54008Sfujita {
83*54008Sfujita 	bp->push = bp->pop = &(bp->buf[LOCAL_BUFSIZ]);
84*54008Sfujita }
85*54008Sfujita 
86*54008Sfujita siolbufpush(bp, c)
87*54008Sfujita 	register struct local_buf *bp;
88*54008Sfujita 	register int c;
89*54008Sfujita {
90*54008Sfujita 
91*54008Sfujita 	*(--bp->push) = c;
92*54008Sfujita 
93*54008Sfujita 	if (bp->push == &(bp->buf[0]))
94*54008Sfujita 		bp->push = &(bp->buf[LOCAL_BUFSIZ]);
95*54008Sfujita 
96*54008Sfujita 	if (bp->push == bp->pop)
97*54008Sfujita 		bp->pop == (u_char *) 0;
98*54008Sfujita }
99*54008Sfujita 
100*54008Sfujita int
101*54008Sfujita siolbufpop(bp)
102*54008Sfujita 	register struct local_buf *bp;
103*54008Sfujita {
104*54008Sfujita 	register int c;
105*54008Sfujita 
106*54008Sfujita 	if (bp->pop == (u_char *) 0)
107*54008Sfujita 		bp->pop = bp->push;
108*54008Sfujita 
109*54008Sfujita 	c = *(--bp->pop);
110*54008Sfujita 
111*54008Sfujita 	if (bp->pop == &(bp->buf[0]))
112*54008Sfujita 		bp->pop = &(bp->buf[LOCAL_BUFSIZ]);
113*54008Sfujita 
114*54008Sfujita 	return(c);
115*54008Sfujita }
116*54008Sfujita 
117*54008Sfujita int
118*54008Sfujita siolbufempty(bp)
119*54008Sfujita 	register struct local_buf *bp;
120*54008Sfujita {
121*54008Sfujita 	if (bp->push == bp->pop)
122*54008Sfujita 		return(1);
123*54008Sfujita 	else
124*54008Sfujita 		return(0);
125*54008Sfujita }
126*54008Sfujita #endif
127*54008Sfujita 
128*54008Sfujita /*
129*54008Sfujita  * probing
130*54008Sfujita  */
131*54008Sfujita 
132*54008Sfujita sioprobe(hd)
133*54008Sfujita 	register struct hp_device *hd;
134*54008Sfujita {
135*54008Sfujita 	register struct siodevice *sio;
136*54008Sfujita 	register int unit;
137*54008Sfujita 
138*54008Sfujita 	sio = (struct siodevice *)hd->hp_addr;
139*54008Sfujita 	unit = hd->hp_unit;
140*54008Sfujita 
141*54008Sfujita 	hd->hp_ipl = SIO_IPL;
142*54008Sfujita 
143*54008Sfujita 	/*
144*54008Sfujita 	 *  We must set hardware address here.
145*54008Sfujita 	 *  but now already it's done.
146*54008Sfujita 
147*54008Sfujita 	sio_addr[unit] = sio;
148*54008Sfujita 
149*54008Sfujita 	*/
150*54008Sfujita 
151*54008Sfujita 	sio_active |= 1 << unit;
152*54008Sfujita 
153*54008Sfujita 	/*
154*54008Sfujita 	 *  We must pick up information from hd->hp_flags here.
155*54008Sfujita 	 *  It should be used instead of TTYDEF_CFLAG or like something.
156*54008Sfujita 	 *
157*54008Sfujita 	 */
158*54008Sfujita 
159*54008Sfujita #ifdef LOCAL_CONSOLE
160*54008Sfujita 
161*54008Sfujita 	/*
162*54008Sfujita 	 *  Enable Interrupt
163*54008Sfujita 	 *    I must rewirte basic handlers of console support,
164*54008Sfujita 	 *    Because it does not work, if interrupt occar.
165*54008Sfujita 	 *    Now using LOCAL_CONSOLE, so the problem isn't happend.
166*54008Sfujita 	 *
167*54008Sfujita 	 */
168*54008Sfujita 
169*54008Sfujita 	sioreg(REG(unit, WR1), WR1_RXALLS | WR1_TXENBL);
170*54008Sfujita 
171*54008Sfujita #endif
172*54008Sfujita 	if (unit == sioconsole) {
173*54008Sfujita 		sioconsinit = 0;
174*54008Sfujita 	}
175*54008Sfujita 
176*54008Sfujita 	return (1);
177*54008Sfujita }
178*54008Sfujita 
179*54008Sfujita int
180*54008Sfujita /* ARGSUSED */
181*54008Sfujita #ifdef __STDC__
182*54008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
183*54008Sfujita #else
184*54008Sfujita sioopen(dev, flag, mode, p)
185*54008Sfujita 	dev_t dev;
186*54008Sfujita 	int flag, mode;
187*54008Sfujita 	struct proc *p;
188*54008Sfujita #endif
189*54008Sfujita {
190*54008Sfujita 	register struct tty *tp;
191*54008Sfujita 	register int unit;
192*54008Sfujita 	int error = 0;
193*54008Sfujita 
194*54008Sfujita 	unit = siounit(dev);
195*54008Sfujita 	if (unit >= NSIO || (sio_active & (1 << unit)) == 0)
196*54008Sfujita 		return (ENXIO);
197*54008Sfujita 
198*54008Sfujita 	tp = &sio_tty[unit];
199*54008Sfujita 	tp->t_oproc = siostart;
200*54008Sfujita 	tp->t_param = sioparam;
201*54008Sfujita 	tp->t_dev = dev;
202*54008Sfujita 
203*54008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
204*54008Sfujita 		tp->t_state |= TS_WOPEN;
205*54008Sfujita 		ttychars(tp);
206*54008Sfujita 		if (tp->t_ispeed == 0) {
207*54008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
208*54008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
209*54008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
210*54008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
211*54008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
212*54008Sfujita 		}
213*54008Sfujita 		sioparam(tp, &tp->t_termios);
214*54008Sfujita 		ttsetwater(tp);
215*54008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
216*54008Sfujita 		return (EBUSY);
217*54008Sfujita 
218*54008Sfujita 	/*
219*54008Sfujita 	 *  We must set DTR & RTS here.
220*54008Sfujita 	 *  Need a routine like XXXmctl().
221*54008Sfujita 	 *
222*54008Sfujita 	 */
223*54008Sfujita 
224*54008Sfujita 	/*
225*54008Sfujita 	 *  The next statment should be executed, when Carrier Detected
226*54008Sfujita 	 *  or using special serial line which ignore carrier.
227*54008Sfujita 	 *
228*54008Sfujita 	 *  Should be checked out RR0, I think. Omit this time.
229*54008Sfujita 	 */
230*54008Sfujita 
231*54008Sfujita 	 tp->t_state |= TS_CARR_ON;
232*54008Sfujita 
233*54008Sfujita 	(void) spltty();
234*54008Sfujita 
235*54008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
236*54008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
237*54008Sfujita 		tp->t_state |= TS_WOPEN;
238*54008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
239*54008Sfujita 		    ttopen, 0))
240*54008Sfujita 			break;
241*54008Sfujita 	}
242*54008Sfujita 
243*54008Sfujita 	(void) spl0();
244*54008Sfujita 
245*54008Sfujita 	if (error == 0)
246*54008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
247*54008Sfujita 
248*54008Sfujita 	return (error);
249*54008Sfujita }
250*54008Sfujita 
251*54008Sfujita /*ARGSUSED*/
252*54008Sfujita sioclose(dev, flag, mode, p)
253*54008Sfujita 	dev_t dev;
254*54008Sfujita 	int flag, mode;
255*54008Sfujita 	struct proc *p;
256*54008Sfujita {
257*54008Sfujita 	register struct tty *tp;
258*54008Sfujita 	register struct siodevice *sio;
259*54008Sfujita 	register int unit;
260*54008Sfujita 
261*54008Sfujita 	unit = siounit(dev);
262*54008Sfujita 	sio = sio_addr[unit];
263*54008Sfujita 	tp = &sio_tty[unit];
264*54008Sfujita 
265*54008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
266*54008Sfujita 
267*54008Sfujita 	/*
268*54008Sfujita 	 *  We must send BREAK to current line here.
269*54008Sfujita 	 *  Not supported yet.
270*54008Sfujita 	 */
271*54008Sfujita 
272*54008Sfujita 	/*
273*54008Sfujita 	 *  We must reset DTR & RTS here.
274*54008Sfujita 	 *  Need a routine like XXXmctl().
275*54008Sfujita 	 *
276*54008Sfujita 	 */
277*54008Sfujita 
278*54008Sfujita 	ttyclose(tp);
279*54008Sfujita 	return (0);
280*54008Sfujita }
281*54008Sfujita 
282*54008Sfujita sioread(dev, uio, flag)
283*54008Sfujita 	dev_t dev;
284*54008Sfujita 	struct uio *uio;
285*54008Sfujita 	int flag;
286*54008Sfujita {
287*54008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
288*54008Sfujita 
289*54008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
290*54008Sfujita }
291*54008Sfujita 
292*54008Sfujita siowrite(dev, uio, flag)
293*54008Sfujita 	dev_t dev;
294*54008Sfujita 	struct uio *uio;
295*54008Sfujita 	int flag;
296*54008Sfujita {
297*54008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
298*54008Sfujita 
299*54008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
300*54008Sfujita }
301*54008Sfujita 
302*54008Sfujita siointr()
303*54008Sfujita {
304*54008Sfujita 	register int unit = 0;
305*54008Sfujita 	register struct siodevice *sio = sio_addr[unit];
306*54008Sfujita 	register u_char code;
307*54008Sfujita 	register struct tty *tp;
308*54008Sfujita 	int s, rr;
309*54008Sfujita 
310*54008Sfujita 	rr = siogetreg(unit);
311*54008Sfujita 	tp = &sio_tty[unit];
312*54008Sfujita 	if (rr & RR_RXRDY) {
313*54008Sfujita 		code = sio->sio_data;
314*54008Sfujita 		if ((tp->t_state & TS_ISOPEN) != 0)
315*54008Sfujita 			(*linesw[tp->t_line].l_rint)(code, tp);
316*54008Sfujita #ifndef LOCAL_CONSOLE
317*54008Sfujita 		else
318*54008Sfujita 			siolbufpush(rbp, code);
319*54008Sfujita #endif
320*54008Sfujita 	}
321*54008Sfujita 
322*54008Sfujita 	if (rr & RR_TXRDY) {
323*54008Sfujita 		sio->sio_cmd = WR0_RSTPEND;
324*54008Sfujita 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
325*54008Sfujita 		if (tp->t_line)
326*54008Sfujita 			(*linesw[tp->t_line].l_start)(tp);
327*54008Sfujita 		else
328*54008Sfujita 			siostart(tp);
329*54008Sfujita 	}
330*54008Sfujita }
331*54008Sfujita 
332*54008Sfujita sioioctl(dev, cmd, data, flag, p)
333*54008Sfujita 	dev_t dev;
334*54008Sfujita 	int cmd;
335*54008Sfujita 	caddr_t data;
336*54008Sfujita 	int flag;
337*54008Sfujita 	struct proc *p;
338*54008Sfujita {
339*54008Sfujita 	register struct tty *tp;
340*54008Sfujita 	register int unit = siounit(dev);
341*54008Sfujita 	register struct siodevice *sio;
342*54008Sfujita 	register int error;
343*54008Sfujita 
344*54008Sfujita 	tp = &sio_tty[unit];
345*54008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
346*54008Sfujita 	if (error >= 0)
347*54008Sfujita 		return (error);
348*54008Sfujita 	error = ttioctl(tp, cmd, data, flag);
349*54008Sfujita 	if (error >= 0)
350*54008Sfujita 		return (error);
351*54008Sfujita 
352*54008Sfujita 	/*
353*54008Sfujita 	 *  We must support flow control of serial lines.
354*54008Sfujita 	 *  Not yet.
355*54008Sfujita 	 */
356*54008Sfujita 
357*54008Sfujita 	sio = sio_addr[unit];
358*54008Sfujita 	switch (cmd) {
359*54008Sfujita 
360*54008Sfujita 	case TIOCSBRK:
361*54008Sfujita 	case TIOCCBRK:
362*54008Sfujita 	case TIOCSDTR:
363*54008Sfujita 	case TIOCCDTR:
364*54008Sfujita 	case TIOCMSET:
365*54008Sfujita 	case TIOCMBIS:
366*54008Sfujita 	case TIOCMBIC:
367*54008Sfujita 	case TIOCMGET:
368*54008Sfujita 	default:
369*54008Sfujita 		return (ENOTTY);
370*54008Sfujita 	}
371*54008Sfujita 
372*54008Sfujita 	return (0);
373*54008Sfujita }
374*54008Sfujita 
375*54008Sfujita sioparam(tp, t)
376*54008Sfujita 	register struct tty *tp;
377*54008Sfujita 	register struct termios *t;
378*54008Sfujita {
379*54008Sfujita 	return (0);
380*54008Sfujita }
381*54008Sfujita 
382*54008Sfujita void
383*54008Sfujita siostart(tp)
384*54008Sfujita 	register struct tty *tp;
385*54008Sfujita {
386*54008Sfujita 	register struct siodevice *sio;
387*54008Sfujita 	int s, unit, c, rr;
388*54008Sfujita 
389*54008Sfujita 	unit = siounit(tp->t_dev);
390*54008Sfujita 	sio = sio_addr[unit];
391*54008Sfujita 
392*54008Sfujita 	s = spltty();
393*54008Sfujita 
394*54008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
395*54008Sfujita 		goto out;
396*54008Sfujita 
397*54008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
398*54008Sfujita 		if (tp->t_state&TS_ASLEEP) {
399*54008Sfujita 			tp->t_state &= ~TS_ASLEEP;
400*54008Sfujita 			wakeup((caddr_t)&tp->t_outq);
401*54008Sfujita 		}
402*54008Sfujita 		selwakeup(&tp->t_wsel);
403*54008Sfujita 	}
404*54008Sfujita 
405*54008Sfujita 	if (tp->t_outq.c_cc == 0)
406*54008Sfujita 		goto out;
407*54008Sfujita 
408*54008Sfujita 	rr = siogetreg(unit);
409*54008Sfujita 	if (rr & RR_TXRDY) {
410*54008Sfujita 		c = getc(&tp->t_outq);
411*54008Sfujita 		tp->t_state |= TS_BUSY;
412*54008Sfujita 		sio->sio_data = c;
413*54008Sfujita 	}
414*54008Sfujita 
415*54008Sfujita out:
416*54008Sfujita 	splx(s);
417*54008Sfujita }
418*54008Sfujita 
419*54008Sfujita /*
420*54008Sfujita  * Stop output on a line.
421*54008Sfujita  */
422*54008Sfujita /*ARGSUSED*/
423*54008Sfujita siostop(tp, flag)
424*54008Sfujita 	register struct tty *tp;
425*54008Sfujita 	int flag;
426*54008Sfujita {
427*54008Sfujita 	register int s;
428*54008Sfujita 
429*54008Sfujita 	s = spltty();
430*54008Sfujita 	if (tp->t_state & TS_BUSY) {
431*54008Sfujita 		if ((tp->t_state&TS_TTSTOP)==0)
432*54008Sfujita 			tp->t_state |= TS_FLUSH;
433*54008Sfujita 	}
434*54008Sfujita 	splx(s);
435*54008Sfujita }
436*54008Sfujita 
437*54008Sfujita /*
438*54008Sfujita  * Following are all routines needed for SIO to act as console
439*54008Sfujita  */
440*54008Sfujita #include "../luna68k/cons.h"
441*54008Sfujita 
442*54008Sfujita siocnprobe(cp)
443*54008Sfujita 	struct consdev *cp;
444*54008Sfujita {
445*54008Sfujita 	int unit;
446*54008Sfujita 
447*54008Sfujita 	/* Line Selection: 0: Channel-A (ttya),  1: Channel-B (keyboard) */
448*54008Sfujita 	unit = 0;
449*54008Sfujita 
450*54008Sfujita 	/* locate the major number */
451*54008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
452*54008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
453*54008Sfujita 			break;
454*54008Sfujita 
455*54008Sfujita 	sio_addr[0] = (struct siodevice *) 0x51000000;
456*54008Sfujita 	sio_addr[1] = (struct siodevice *) 0x51000004;
457*54008Sfujita 
458*54008Sfujita 	/* make sure hardware exists */
459*54008Sfujita 	if (badaddr((short *)sio_addr[0])) {
460*54008Sfujita 		cp->cn_pri = CN_DEAD;
461*54008Sfujita 		return;
462*54008Sfujita 	}
463*54008Sfujita 
464*54008Sfujita 	/* locate the major number */
465*54008Sfujita 
466*54008Sfujita 	/* initialize required fields */
467*54008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
468*54008Sfujita 	cp->cn_tp  = 0;
469*54008Sfujita 	cp->cn_pri = CN_NORMAL;
470*54008Sfujita }
471*54008Sfujita 
472*54008Sfujita siocninit(cp)
473*54008Sfujita 	struct consdev *cp;
474*54008Sfujita {
475*54008Sfujita 	int unit = siounit(cp->cn_dev);
476*54008Sfujita 
477*54008Sfujita 	sioinit(unit);
478*54008Sfujita 	sioconsole = unit;
479*54008Sfujita }
480*54008Sfujita 
481*54008Sfujita /*
482*54008Sfujita  * Routines for Console Support
483*54008Sfujita  */
484*54008Sfujita 
485*54008Sfujita 
486*54008Sfujita #ifdef LOCAL_CONSOLE
487*54008Sfujita 
488*54008Sfujita int local_console;
489*54008Sfujita 
490*54008Sfujita siocngetc(dev)
491*54008Sfujita 	dev_t dev;
492*54008Sfujita {
493*54008Sfujita 	int c, rr0, rr1;
494*54008Sfujita 	int unit;
495*54008Sfujita 	int s;
496*54008Sfujita 
497*54008Sfujita 	unit = local_console;
498*54008Sfujita 
499*54008Sfujita 	s = splhigh();
500*54008Sfujita loop:
501*54008Sfujita 	while (((rr0 = sioreg(REG(unit, RR0), 0)) & RR0_RXAVAIL) == 0);
502*54008Sfujita 	rr1 = sioreg(REG(unit, RR1), 0);
503*54008Sfujita 	c = sio_addr[unit]->sio_data;
504*54008Sfujita 
505*54008Sfujita 	if ((rr0 & RR0_BREAK) == RR0_BREAK)		/* Break Detected */
506*54008Sfujita 		goto loop;
507*54008Sfujita 
508*54008Sfujita 	if ((rr1 & RR1_OVERRUN) == RR1_OVERRUN) {	/* Data Over Run */
509*54008Sfujita 		sioreg(REG(unit, WR0), WR0_ERRRST);
510*54008Sfujita 		goto loop;
511*54008Sfujita 	}
512*54008Sfujita 
513*54008Sfujita 	if ((rr1 & RR1_PARITY) == RR1_PARITY) {		/* Parity Error */
514*54008Sfujita 		sioreg(REG(unit, WR0), WR0_ERRRST);
515*54008Sfujita 		goto loop;
516*54008Sfujita 	}
517*54008Sfujita 
518*54008Sfujita 	if ((rr1 & RR1_FRAMING) == RR1_FRAMING) {	/* Framing Error */
519*54008Sfujita 		sioreg(REG(unit, WR0), WR0_ERRRST);
520*54008Sfujita 		goto loop;
521*54008Sfujita 	}
522*54008Sfujita 
523*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTPEND);
524*54008Sfujita 	splx(s);
525*54008Sfujita 	return(c);
526*54008Sfujita }
527*54008Sfujita 
528*54008Sfujita siocnputc(dev, c)
529*54008Sfujita 	dev_t dev;
530*54008Sfujita 	int c;
531*54008Sfujita {
532*54008Sfujita 	int unit;
533*54008Sfujita 	int s;
534*54008Sfujita 
535*54008Sfujita 	unit = local_console;
536*54008Sfujita 
537*54008Sfujita 	if (sioconsole == -1) {
538*54008Sfujita 		(void) sioinit(unit);
539*54008Sfujita 		sioconsole = unit;
540*54008Sfujita 	}
541*54008Sfujita 
542*54008Sfujita 	s = splhigh();
543*54008Sfujita 
544*54008Sfujita 	/* wait for any pending transmission to finish */
545*54008Sfujita 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
546*54008Sfujita 
547*54008Sfujita 	sio_addr[unit]->sio_data = (c & 0xFF);
548*54008Sfujita 
549*54008Sfujita 	/* wait for any pending transmission to finish */
550*54008Sfujita 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
551*54008Sfujita 
552*54008Sfujita 	splx(s);
553*54008Sfujita }
554*54008Sfujita 
555*54008Sfujita sioinit(unit)
556*54008Sfujita 	int unit;
557*54008Sfujita {
558*54008Sfujita 	int s;
559*54008Sfujita 
560*54008Sfujita 	s = splhigh();
561*54008Sfujita 
562*54008Sfujita 	sioreg(REG(unit, WR0), WR0_CHANRST);		/* Channel-A Reset */
563*54008Sfujita 	sioreg(WR2A, WR2_VEC86  | WR2_INTR_1);		/* Set CPU BUS Interface Mode */
564*54008Sfujita 	sioreg(WR2B, 0);				/* Set Interrupt Vector */
565*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
566*54008Sfujita 	sioreg(REG(unit, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
567*54008Sfujita 	sioreg(REG(unit, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
568*54008Sfujita 	sioreg(REG(unit, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
569*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
570*54008Sfujita 
571*54008Sfujita 	unit = local_console = 1 - unit;
572*54008Sfujita 
573*54008Sfujita 	sioreg(REG(unit, WR0), WR0_CHANRST);		/* Channel-B Reset */
574*54008Sfujita 
575*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
576*54008Sfujita 	sioreg(REG(unit, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
577*54008Sfujita 	sioreg(REG(unit, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
578*54008Sfujita 	sioreg(REG(unit, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
579*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
580*54008Sfujita 
581*54008Sfujita 	splx(s);
582*54008Sfujita }
583*54008Sfujita #else
584*54008Sfujita 
585*54008Sfujita /*
586*54008Sfujita  * console put & get
587*54008Sfujita  */
588*54008Sfujita 
589*54008Sfujita siocngetc(dev)
590*54008Sfujita 	dev_t dev;
591*54008Sfujita {
592*54008Sfujita 	while (siolbufempty(rbp))
593*54008Sfujita 		DELAY(10);
594*54008Sfujita 
595*54008Sfujita 	return(siolbufpop(rbp));
596*54008Sfujita }
597*54008Sfujita 
598*54008Sfujita siocnputc(dev, c)
599*54008Sfujita 	dev_t dev;
600*54008Sfujita 	int c;
601*54008Sfujita {
602*54008Sfujita 	register int unit = siounit(dev);
603*54008Sfujita 	register struct siodevice *sio = sio_addr[unit];
604*54008Sfujita 	register u_char code;
605*54008Sfujita 	int s, rr;
606*54008Sfujita 
607*54008Sfujita 	s = splhigh();
608*54008Sfujita 	sioreg(REG(unit, WR1), WR1_RXALLS);
609*54008Sfujita 
610*54008Sfujita 	do {
611*54008Sfujita 		DELAY(1);
612*54008Sfujita 		rr = siogetreg(unit);
613*54008Sfujita 	} while (!(rr & RR_TXRDY));
614*54008Sfujita 
615*54008Sfujita 	code = (c & 0xff);
616*54008Sfujita 	sio->sio_data = code;
617*54008Sfujita 
618*54008Sfujita 	do {
619*54008Sfujita 		DELAY(1);
620*54008Sfujita 		rr = siogetreg(unit);
621*54008Sfujita 	} while (!(rr & RR_TXRDY));
622*54008Sfujita 
623*54008Sfujita 	sioreg(REG(unit, WR1), WR1_RXALLS | WR1_TXENBL);
624*54008Sfujita 	splx(s);
625*54008Sfujita }
626*54008Sfujita 
627*54008Sfujita sioinit(unit)
628*54008Sfujita 	int unit;
629*54008Sfujita {
630*54008Sfujita 	int s;
631*54008Sfujita 
632*54008Sfujita 	siolbufinit(rbp);
633*54008Sfujita 
634*54008Sfujita 	s = splhigh();
635*54008Sfujita 
636*54008Sfujita 	unit = 0;
637*54008Sfujita 
638*54008Sfujita 	sioreg(REG(unit, WR0), WR0_CHANRST);		/* Channel-A Reset */
639*54008Sfujita 	sioreg(WR2A, WR2_VEC86  | WR2_INTR_1);		/* Set CPU BUS Interface Mode */
640*54008Sfujita 	sioreg(WR2B, 0);				/* Set Interrupt Vector */
641*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
642*54008Sfujita 	sioreg(REG(unit, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
643*54008Sfujita 	sioreg(REG(unit, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
644*54008Sfujita 	sioreg(REG(unit, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
645*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
646*54008Sfujita 	sioreg(REG(unit, WR1), WR1_RXALLS | WR1_TXENBL);
647*54008Sfujita 
648*54008Sfujita 	unit = 1;
649*54008Sfujita 
650*54008Sfujita 	sioreg(REG(unit, WR0), WR0_CHANRST);		/* Channel-A Reset */
651*54008Sfujita 
652*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
653*54008Sfujita 	sioreg(REG(unit, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
654*54008Sfujita 	sioreg(REG(unit, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
655*54008Sfujita 	sioreg(REG(unit, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
656*54008Sfujita 	sioreg(REG(unit, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
657*54008Sfujita 	sioreg(REG(unit, WR1), WR1_RXALLS | WR1_TXENBL);
658*54008Sfujita 
659*54008Sfujita 	splx(s);
660*54008Sfujita }
661*54008Sfujita #endif
662*54008Sfujita 
663*54008Sfujita int
664*54008Sfujita siogetreg(unit)
665*54008Sfujita 	register int unit;
666*54008Sfujita {
667*54008Sfujita 	register struct siodevice *sio = sio_addr[unit];
668*54008Sfujita 	register int rr = 0;
669*54008Sfujita 
670*54008Sfujita 	rr = sio->sio_stat;
671*54008Sfujita 	rr <<= 8;
672*54008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
673*54008Sfujita 	rr |= sio->sio_stat;
674*54008Sfujita 
675*54008Sfujita 	return(rr);
676*54008Sfujita }
677*54008Sfujita 
678*54008Sfujita int
679*54008Sfujita sioreg(reg, val)
680*54008Sfujita 	register int reg, val;
681*54008Sfujita {
682*54008Sfujita 	register int chan;
683*54008Sfujita 
684*54008Sfujita 	chan = CHANNEL(reg);
685*54008Sfujita 
686*54008Sfujita 	if (isStatusReg(reg)) {
687*54008Sfujita 		if (REGNO(reg) != 0)
688*54008Sfujita 		    sio_addr[chan]->sio_cmd = REGNO(reg);
689*54008Sfujita 		return(sio_addr[chan]->sio_stat);
690*54008Sfujita 	} else {
691*54008Sfujita 		if (REGNO(reg) != 0)
692*54008Sfujita 		    sio_addr[chan]->sio_cmd = REGNO(reg);
693*54008Sfujita 		sio_addr[chan]->sio_cmd = val;
694*54008Sfujita 		return(val);
695*54008Sfujita 	}
696*54008Sfujita }
697*54008Sfujita #endif
698