xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 56873)
154008Sfujita /*
254008Sfujita  * Copyright (c) 1992 OMRON Corporation.
354008Sfujita  * Copyright (c) 1992 The Regents of the University of California.
454008Sfujita  * All rights reserved.
554008Sfujita  *
654008Sfujita  * This code is derived from software contributed to Berkeley by
754008Sfujita  * OMRON Corporation.
854008Sfujita  *
954008Sfujita  * %sccs.include.redist.c%
1054008Sfujita  *
11*56873Sakito  *	@(#)sio.c	7.3 (Berkeley) 11/17/92
1254008Sfujita  */
1354008Sfujita 
1454008Sfujita /*
1554008Sfujita  * sio.c -- NEC uPD7201A UART Device Driver
16*56873Sakito  *    remaked by A.Fujita, NOV-5-1992
1754008Sfujita  */
1854008Sfujita 
1954008Sfujita #include "sio.h"
2054008Sfujita #if NSIO > 0
2154008Sfujita 
22*56873Sakito #include "bmc.h"
2354008Sfujita 
24*56873Sakito #include "sys/param.h"
25*56873Sakito #include "sys/systm.h"
26*56873Sakito #include "sys/ioctl.h"
27*56873Sakito #include "sys/proc.h"
28*56873Sakito #include "sys/tty.h"
29*56873Sakito #include "sys/conf.h"
30*56873Sakito #include "sys/file.h"
31*56873Sakito #include "sys/uio.h"
32*56873Sakito #include "sys/kernel.h"
33*56873Sakito #include "sys/syslog.h"
3454008Sfujita 
35*56873Sakito #include "device.h"
36*56873Sakito #include "sioreg.h"
37*56873Sakito #include "siovar.h"
3854008Sfujita 
39*56873Sakito struct sio_portc *sio_port_assign();
4054008Sfujita 
41*56873Sakito int	sioprobe();
42*56873Sakito int	sioopen();
43*56873Sakito void	siostart();
44*56873Sakito int	sioparam();
45*56873Sakito int	siointr();
4654008Sfujita 
4754008Sfujita struct	driver siodriver = {
4854008Sfujita 	sioprobe, "sio",
4954008Sfujita };
5054008Sfujita 
51*56873Sakito #define NPORT	2					/* uPD7201A has 2 serial-port */
52*56873Sakito #define NLINE	1					/* number of active line */
5354008Sfujita 
54*56873Sakito struct	sio_portc sio_portc[NPORT] = {
55*56873Sakito 	{ -1, -1, (struct siodevice *) 0x51000000, (int (*)()) 0 },
56*56873Sakito 	{ -1, -1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
57*56873Sakito };
5854008Sfujita 
59*56873Sakito struct	sio_softc sio_softc[NLINE];
6054008Sfujita 
61*56873Sakito int	sio_init_done = 0;
62*56873Sakito int	siounitbase = 0;				/* This counter is used unit number assignment */
6354008Sfujita 
64*56873Sakito int	siosoftCAR;
65*56873Sakito int	sio_active;
66*56873Sakito int	sioconsole;
67*56873Sakito int	siodefaultrate = TTYDEF_SPEED;
68*56873Sakito int	siomajor = 0;
6954008Sfujita 
70*56873Sakito struct	tty sio_tty[NLINE];
7154008Sfujita 
72*56873Sakito struct speedtab siospeedtab[] = {
73*56873Sakito 	2400,	WR4_BAUD24,
74*56873Sakito 	4800,	WR4_BAUD48,
75*56873Sakito 	9600,	WR4_BAUD96,
7654008Sfujita };
7754008Sfujita 
78*56873Sakito #define	siounit(x)		minor(x)
7954008Sfujita 
8054008Sfujita 
8154008Sfujita /*
82*56873Sakito  *  probe routines
8354008Sfujita  */
8454008Sfujita 
8554008Sfujita sioprobe(hd)
8654008Sfujita 	register struct hp_device *hd;
8754008Sfujita {
88*56873Sakito 	register int port;
89*56873Sakito 	register struct sio_portc *pc;
90*56873Sakito 	register struct sio_softc *sc;
9154008Sfujita 
92*56873Sakito 	sioinit((struct siodevice *) hd->hp_addr, siodefaultrate);
9354008Sfujita 
94*56873Sakito 	/* locate the major number */
95*56873Sakito 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
96*56873Sakito 		if (cdevsw[siomajor].d_open == sioopen)
97*56873Sakito 			break;
9854008Sfujita 
99*56873Sakito 	for (port = 0; port < NPORT; port++) {
100*56873Sakito 		pc = &sio_portc[port];
10154008Sfujita 
102*56873Sakito 		if (pc->pc_major != -1) {
103*56873Sakito 			printf("%s%d: port %d, address 0x%x, intr 0x%x (console)\n",
104*56873Sakito 			       (pc->pc_major == siomajor ? "sio" : "bmc" ),
105*56873Sakito 			       pc->pc_unit, port, pc->pc_addr, pc->pc_intr);
106*56873Sakito 			continue;
107*56873Sakito 		}
10854008Sfujita 
109*56873Sakito 		pc->pc_addr =
110*56873Sakito 			(struct siodevice *)((u_long) hd->hp_addr + (sizeof(struct siodevice) * port));
111*56873Sakito #if NBMC > 0
112*56873Sakito 		if (bmcinit(port))
113*56873Sakito 			continue;
114*56873Sakito #endif
115*56873Sakito 		if (++siounitbase < NLINE) {
116*56873Sakito 			pc->pc_major = siomajor;
117*56873Sakito 			pc->pc_intr  = siointr;
118*56873Sakito 			pc->pc_unit  = siounitbase;
119*56873Sakito 			printf("sio%d: port %d, address 0x%x\n", pc->pc_unit, port, pc->pc_addr);
12054008Sfujita 
121*56873Sakito 			sc = &sio_softc[pc->pc_unit];
122*56873Sakito 			sc->sc_pc = pc;
12354008Sfujita 
124*56873Sakito 			sio_active |= 1 << pc->pc_unit;
125*56873Sakito 			siosoftCAR |= 1 << pc->pc_unit;
126*56873Sakito 		}
127*56873Sakito 	}
128*56873Sakito }
12954008Sfujita 
130*56873Sakito struct sio_portc *
131*56873Sakito sio_port_assign(port, major, unit, intr)
132*56873Sakito 	int	port, major, unit;
133*56873Sakito 	int	(*intr)();
134*56873Sakito {
135*56873Sakito 	register struct sio_portc *pc = &sio_portc[port];
13654008Sfujita 
137*56873Sakito 	if (pc->pc_major != -1)
138*56873Sakito 		return((struct sio_portc *) 0);
13954008Sfujita 
140*56873Sakito 	pc->pc_major = major;
141*56873Sakito 	pc->pc_intr  = intr;
142*56873Sakito 	pc->pc_unit  = unit;
14354008Sfujita 
144*56873Sakito 	return(pc);
14554008Sfujita }
14654008Sfujita 
147*56873Sakito 
148*56873Sakito /*
149*56873Sakito  *  entry routines
150*56873Sakito  */
151*56873Sakito 
15254008Sfujita /* ARGSUSED */
15354008Sfujita #ifdef __STDC__
15454008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
15554008Sfujita #else
15654008Sfujita sioopen(dev, flag, mode, p)
15754008Sfujita 	dev_t dev;
15854008Sfujita 	int flag, mode;
15954008Sfujita 	struct proc *p;
16054008Sfujita #endif
16154008Sfujita {
16254008Sfujita 	register struct tty *tp;
16354008Sfujita 	register int unit;
16454008Sfujita 	int error = 0;
16554008Sfujita 
16654008Sfujita 	unit = siounit(dev);
167*56873Sakito 	if (unit >= NLINE || (sio_active & (1 << unit)) == 0)
16854008Sfujita 		return (ENXIO);
16954008Sfujita 	tp = &sio_tty[unit];
17054008Sfujita 	tp->t_oproc = siostart;
17154008Sfujita 	tp->t_param = sioparam;
17254008Sfujita 	tp->t_dev = dev;
17354008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
17454008Sfujita 		tp->t_state |= TS_WOPEN;
17554008Sfujita 		ttychars(tp);
17654008Sfujita 		if (tp->t_ispeed == 0) {
17754008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
17854008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
179*56873Sakito /*			tp->t_cflag = TTYDEF_CFLAG;		*/
18054008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
18154008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
18254008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
18354008Sfujita 		}
18454008Sfujita 		sioparam(tp, &tp->t_termios);
18554008Sfujita 		ttsetwater(tp);
18654008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
18754008Sfujita 		return (EBUSY);
188*56873Sakito 	(void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
189*56873Sakito 	if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
190*56873Sakito 		tp->t_state |= TS_CARR_ON;
19154008Sfujita 	(void) spltty();
19254008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
19354008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
19454008Sfujita 		tp->t_state |= TS_WOPEN;
19554008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
19654008Sfujita 		    ttopen, 0))
19754008Sfujita 			break;
19854008Sfujita 	}
19954008Sfujita 	(void) spl0();
20054008Sfujita 	if (error == 0)
20154008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
20254008Sfujita 	return (error);
20354008Sfujita }
204*56873Sakito 
20554008Sfujita /*ARGSUSED*/
20654008Sfujita sioclose(dev, flag, mode, p)
20754008Sfujita 	dev_t dev;
20854008Sfujita 	int flag, mode;
20954008Sfujita 	struct proc *p;
21054008Sfujita {
21154008Sfujita 	register struct tty *tp;
21254008Sfujita 	register int unit;
21354008Sfujita 
21454008Sfujita 	unit = siounit(dev);
21554008Sfujita 	tp = &sio_tty[unit];
21654008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
217*56873Sakito 	(void) siomctl(dev, WR5_BREAK, DMBIS);
218*56873Sakito 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
219*56873Sakito 	    (tp->t_state&TS_ISOPEN) == 0)
220*56873Sakito 		(void) siomctl(dev, 0, DMSET);
22154008Sfujita 	ttyclose(tp);
22254008Sfujita 	return (0);
22354008Sfujita }
22454008Sfujita 
22554008Sfujita sioread(dev, uio, flag)
22654008Sfujita 	dev_t dev;
22754008Sfujita 	struct uio *uio;
22854008Sfujita {
22954008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
23054008Sfujita 
23154008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
23254008Sfujita }
23354008Sfujita 
23454008Sfujita siowrite(dev, uio, flag)
23554008Sfujita 	dev_t dev;
23654008Sfujita 	struct uio *uio;
23754008Sfujita {
23854008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
23954008Sfujita 
24054008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24154008Sfujita }
24254008Sfujita 
243*56873Sakito /*
244*56873Sakito  * Stop output on a line.
245*56873Sakito  */
246*56873Sakito /*ARGSUSED*/
247*56873Sakito siostop(tp, flag)
248*56873Sakito 	register struct tty *tp;
24954008Sfujita {
250*56873Sakito 	register int s;
25154008Sfujita 
252*56873Sakito 	s = spltty();
253*56873Sakito 	if (tp->t_state & TS_BUSY) {
254*56873Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
255*56873Sakito 			tp->t_state |= TS_FLUSH;
25654008Sfujita 	}
257*56873Sakito 	splx(s);
25854008Sfujita }
25954008Sfujita 
26054008Sfujita sioioctl(dev, cmd, data, flag, p)
26154008Sfujita 	dev_t dev;
26254008Sfujita 	int cmd;
26354008Sfujita 	caddr_t data;
26454008Sfujita 	int flag;
26554008Sfujita 	struct proc *p;
26654008Sfujita {
26754008Sfujita 	register struct tty *tp;
26854008Sfujita 	register int unit = siounit(dev);
26954008Sfujita 	register int error;
270*56873Sakito 
27154008Sfujita 	tp = &sio_tty[unit];
27254008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
27354008Sfujita 	if (error >= 0)
27454008Sfujita 		return (error);
27554008Sfujita 	error = ttioctl(tp, cmd, data, flag);
27654008Sfujita 	if (error >= 0)
27754008Sfujita 		return (error);
27854008Sfujita 
27954008Sfujita 	switch (cmd) {
28054008Sfujita 
28154008Sfujita 	case TIOCSBRK:
282*56873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIS);
283*56873Sakito 		break;
284*56873Sakito 
28554008Sfujita 	case TIOCCBRK:
286*56873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIC);
287*56873Sakito 		break;
288*56873Sakito 
28954008Sfujita 	case TIOCSDTR:
290*56873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
291*56873Sakito 		break;
292*56873Sakito 
29354008Sfujita 	case TIOCCDTR:
294*56873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
295*56873Sakito 		break;
296*56873Sakito 
29754008Sfujita 	case TIOCMSET:
298*56873Sakito 		(void) siomctl(dev, *(int *)data, DMSET);
299*56873Sakito 		break;
300*56873Sakito 
30154008Sfujita 	case TIOCMBIS:
302*56873Sakito 		(void) siomctl(dev, *(int *)data, DMBIS);
303*56873Sakito 		break;
304*56873Sakito 
30554008Sfujita 	case TIOCMBIC:
306*56873Sakito 		(void) siomctl(dev, *(int *)data, DMBIC);
307*56873Sakito 		break;
308*56873Sakito 
30954008Sfujita 	case TIOCMGET:
310*56873Sakito 		*(int *)data = siomctl(dev, 0, DMGET);
311*56873Sakito 		break;
312*56873Sakito 
31354008Sfujita 	default:
31454008Sfujita 		return (ENOTTY);
31554008Sfujita 	}
31654008Sfujita 	return (0);
31754008Sfujita }
31854008Sfujita 
31954008Sfujita 
320*56873Sakito /*
321*56873Sakito  *
322*56873Sakito  */
323*56873Sakito 
32454008Sfujita void
32554008Sfujita siostart(tp)
32654008Sfujita 	register struct tty *tp;
32754008Sfujita {
32854008Sfujita 	register struct siodevice *sio;
329*56873Sakito 	register int rr;
330*56873Sakito 	int s, unit, c;
33154008Sfujita 
33254008Sfujita 	unit = siounit(tp->t_dev);
333*56873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
33454008Sfujita 	s = spltty();
33554008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
33654008Sfujita 		goto out;
33754008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
33854008Sfujita 		if (tp->t_state&TS_ASLEEP) {
33954008Sfujita 			tp->t_state &= ~TS_ASLEEP;
34054008Sfujita 			wakeup((caddr_t)&tp->t_outq);
34154008Sfujita 		}
34254008Sfujita 		selwakeup(&tp->t_wsel);
34354008Sfujita 	}
34454008Sfujita 	if (tp->t_outq.c_cc == 0)
34554008Sfujita 		goto out;
346*56873Sakito 	rr = siogetreg(sio);
34754008Sfujita 	if (rr & RR_TXRDY) {
34854008Sfujita 		c = getc(&tp->t_outq);
34954008Sfujita 		tp->t_state |= TS_BUSY;
35054008Sfujita 		sio->sio_data = c;
35154008Sfujita 	}
35254008Sfujita out:
35354008Sfujita 	splx(s);
35454008Sfujita }
355*56873Sakito 
356*56873Sakito sioparam(tp, t)
357*56873Sakito 	register struct tty *tp;
358*56873Sakito 	register struct termios *t;
359*56873Sakito {
360*56873Sakito 	int unit = siounit(tp->t_dev);
361*56873Sakito 	register struct siodevice *sio;
362*56873Sakito 	register cflag = t->c_cflag;
363*56873Sakito 	register u_char wr;
364*56873Sakito 	int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
365*56873Sakito 
366*56873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
367*56873Sakito 
368*56873Sakito 	switch (cflag & CSIZE) {
369*56873Sakito 	case CS5:
370*56873Sakito 	case CS6:
371*56873Sakito 	case CS7:
372*56873Sakito 	case CS8:
373*56873Sakito 		break;
374*56873Sakito 	}
375*56873Sakito 
376*56873Sakito 	wr = ospeed;
377*56873Sakito 
378*56873Sakito 	if (cflag & PARENB) {
379*56873Sakito 		wr |= WR4_PARENAB;
380*56873Sakito 		if ((cflag&PARODD) == 0)
381*56873Sakito 			wr |= WR4_EPARITY;
382*56873Sakito 	}
383*56873Sakito 
384*56873Sakito 	if (cflag & CSTOPB)
385*56873Sakito 		wr |= WR4_STOP2;			/* 2 stop bit */
386*56873Sakito 	else
387*56873Sakito 		wr |= WR4_STOP1;			/* 1 stop bit */
388*56873Sakito 
389*56873Sakito 	(void) sioreg(sio, WR4, wr);
390*56873Sakito 
391*56873Sakito 	return (0);
392*56873Sakito }
393*56873Sakito 
394*56873Sakito siomctl()
395*56873Sakito {
396*56873Sakito 	return (0);
397*56873Sakito }
398*56873Sakito 
399*56873Sakito 
40054008Sfujita /*
401*56873Sakito  *  Interrupt handling
40254008Sfujita  */
403*56873Sakito 
404*56873Sakito void
405*56873Sakito _siointr()
40654008Sfujita {
407*56873Sakito 	register int port;
408*56873Sakito 	register struct sio_portc *pc;
40954008Sfujita 
410*56873Sakito 	for (port = 0; port < NPORT; port++) {
411*56873Sakito 		pc = &sio_portc[port];
412*56873Sakito 
413*56873Sakito 		if (pc->pc_major != -1)
414*56873Sakito 			(pc->pc_intr)(pc->pc_unit);
41554008Sfujita 	}
41654008Sfujita }
41754008Sfujita 
418*56873Sakito siointr(unit)
419*56873Sakito 	register int unit;
420*56873Sakito {
421*56873Sakito 	register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
422*56873Sakito 	register u_char code;
423*56873Sakito 	register struct tty *tp;
424*56873Sakito 	int s, rr;
425*56873Sakito 
426*56873Sakito 	tp = &sio_tty[unit];
427*56873Sakito 	rr = siogetreg(sio);
428*56873Sakito 
429*56873Sakito 	if (rr & RR_RXRDY) {
430*56873Sakito 		code = sio->sio_data;
431*56873Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
432*56873Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
433*56873Sakito 	}
434*56873Sakito 
435*56873Sakito 	if (rr & RR_TXRDY) {
436*56873Sakito 		sio->sio_cmd = WR0_RSTPEND;
437*56873Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
438*56873Sakito 		if (tp->t_line)
439*56873Sakito 			(*linesw[tp->t_line].l_start)(tp);
440*56873Sakito 		else
441*56873Sakito 			siostart(tp);
442*56873Sakito 	}
443*56873Sakito }
444*56873Sakito 
44554008Sfujita /*
44654008Sfujita  * Following are all routines needed for SIO to act as console
44754008Sfujita  */
448*56873Sakito #include "../luna68k/cons.h"
44954008Sfujita 
45054008Sfujita siocnprobe(cp)
451*56873Sakito 	register struct consdev *cp;
45254008Sfujita {
453*56873Sakito 	register int unit = 0;
45454008Sfujita 
45554008Sfujita 	/* locate the major number */
45654008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
45754008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
45854008Sfujita 			break;
45954008Sfujita 
460*56873Sakito 	siounitbase = -1;
46154008Sfujita 
46254008Sfujita 	/* initialize required fields */
46354008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
464*56873Sakito 	cp->cn_tp  = &sio_tty[unit];
46554008Sfujita 	cp->cn_pri = CN_NORMAL;
46654008Sfujita }
46754008Sfujita 
46854008Sfujita siocninit(cp)
46954008Sfujita 	struct consdev *cp;
47054008Sfujita {
47154008Sfujita 	int unit = siounit(cp->cn_dev);
472*56873Sakito 	register struct sio_softc *sc = &sio_softc[unit];
47354008Sfujita 
474*56873Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
475*56873Sakito 
476*56873Sakito 	/* port assign */
477*56873Sakito 	sc->sc_pc = sio_port_assign(0, siomajor, unit, siointr);
478*56873Sakito 
47954008Sfujita 	sioconsole = unit;
480*56873Sakito 	siounitbase = 0;
481*56873Sakito 
482*56873Sakito 	sio_active |= 1 << unit;
483*56873Sakito 	siosoftCAR |= 1 << unit;
48454008Sfujita }
48554008Sfujita 
48654008Sfujita siocngetc(dev)
48754008Sfujita 	dev_t dev;
48854008Sfujita {
489*56873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
490*56873Sakito 	struct sio_portc *pc = sc->sc_pc;
49154008Sfujita 
492*56873Sakito 	return(sio_imgetc(pc->pc_addr));
49354008Sfujita }
49454008Sfujita 
49554008Sfujita siocnputc(dev, c)
49654008Sfujita 	dev_t dev;
49754008Sfujita 	int c;
49854008Sfujita {
499*56873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
500*56873Sakito 	struct sio_portc *pc = sc->sc_pc;
50154008Sfujita 
502*56873Sakito 	sio_imputc(pc->pc_addr, c);
503*56873Sakito }
50454008Sfujita 
50554008Sfujita 
506*56873Sakito /*
507*56873Sakito  *  sio raw-level routines
508*56873Sakito  */
50954008Sfujita 
510*56873Sakito sioinit(sio0, rate)
511*56873Sakito 	register struct siodevice *sio0;
512*56873Sakito 	register int rate;
513*56873Sakito {
514*56873Sakito 	register struct siodevice *sio1;
515*56873Sakito 	int s;
51654008Sfujita 
517*56873Sakito 	rate = ttspeedtab(rate, siospeedtab);
51854008Sfujita 
519*56873Sakito 	if (sio_init_done)
520*56873Sakito 		return;
52154008Sfujita 
522*56873Sakito 	sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
52354008Sfujita 
52454008Sfujita 	s = splhigh();
52554008Sfujita 
526*56873Sakito 	sioreg(sio0, WR0,  WR0_CHANRST);		/* Channel-A Reset */
52754008Sfujita 
528*56873Sakito 	sioreg(sio0, WR2, (WR2_VEC86  | WR2_INTR_1));	/* Set CPU BUS Interface Mode */
529*56873Sakito 	sioreg(sio1, WR2,  0);				/* Set Interrupt Vector */
53054008Sfujita 
531*56873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
532*56873Sakito 	sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
533*56873Sakito 	sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
534*56873Sakito 	sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
535*56873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
536*56873Sakito 	sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
53754008Sfujita 
538*56873Sakito 	sioreg(sio1, WR0,  WR0_CHANRST);		/* Channel-B Reset */
53954008Sfujita 
540*56873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
541*56873Sakito 	sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
542*56873Sakito 	sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
543*56873Sakito 	sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
544*56873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
545*56873Sakito 	sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
546*56873Sakito 
54754008Sfujita 	splx(s);
548*56873Sakito 
549*56873Sakito 	sio_init_done = 1;
55054008Sfujita }
55154008Sfujita 
552*56873Sakito sio_imgetc(sio)
553*56873Sakito 	register struct siodevice *sio;
55454008Sfujita {
555*56873Sakito 	register int rr0, rr1;
556*56873Sakito 	int c, s;
55754008Sfujita 
558*56873Sakito 	s = splhigh();
559*56873Sakito 	while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
560*56873Sakito 		;
561*56873Sakito 	c = sio->sio_data;
562*56873Sakito 	sioreg(sio, WR0, WR0_RSTPEND);
563*56873Sakito 	splx(s);
564*56873Sakito 	return (c);
56554008Sfujita }
56654008Sfujita 
567*56873Sakito sio_imputc(sio, c)
568*56873Sakito 	register struct siodevice *sio;
56954008Sfujita 	int c;
57054008Sfujita {
57154008Sfujita 	register u_char code;
572*56873Sakito 	register int rr;
573*56873Sakito 	int s;
57454008Sfujita 
57554008Sfujita 	s = splhigh();
57654008Sfujita 
577*56873Sakito 	sioreg(sio, WR1, WR1_RXALLS);
578*56873Sakito 
57954008Sfujita 	do {
58054008Sfujita 		DELAY(1);
581*56873Sakito 		rr = siogetreg(sio);
58254008Sfujita 	} while (!(rr & RR_TXRDY));
583*56873Sakito 
584*56873Sakito 	code = (c & 0xFF);
58554008Sfujita 	sio->sio_data = code;
58654008Sfujita 
58754008Sfujita 	do {
58854008Sfujita 		DELAY(1);
589*56873Sakito 		rr = siogetreg(sio);
59054008Sfujita 	} while (!(rr & RR_TXRDY));
59154008Sfujita 
592*56873Sakito 	sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
593*56873Sakito 
59454008Sfujita 	splx(s);
59554008Sfujita }
59654008Sfujita 
597*56873Sakito /*
598*56873Sakito  *  uPD7201A register operation
599*56873Sakito  */
60054008Sfujita 
60154008Sfujita int
602*56873Sakito siogetreg(sio)
603*56873Sakito 	register struct siodevice *sio;
60454008Sfujita {
60554008Sfujita 	register int rr = 0;
60654008Sfujita 
60754008Sfujita 	rr = sio->sio_stat;
60854008Sfujita 	rr <<= 8;
60954008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
61054008Sfujita 	rr |= sio->sio_stat;
61154008Sfujita 
61254008Sfujita 	return(rr);
61354008Sfujita }
61454008Sfujita 
61554008Sfujita int
616*56873Sakito sioreg(sio, reg, val)
617*56873Sakito 	register struct siodevice *sio;
61854008Sfujita 	register int reg, val;
61954008Sfujita {
62054008Sfujita 	if (isStatusReg(reg)) {
621*56873Sakito 		if (reg != 0)
622*56873Sakito 		    sio->sio_cmd = reg;
623*56873Sakito 		val = sio->sio_stat;
62454008Sfujita 	} else {
625*56873Sakito 		if (reg != 0)
626*56873Sakito 		    sio->sio_cmd = reg;
627*56873Sakito 		sio->sio_cmd = val;
62854008Sfujita 	}
629*56873Sakito 
630*56873Sakito 	return(val);
63154008Sfujita }
63254008Sfujita #endif
633