xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 57126)
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*57126Sakito  *	@(#)sio.c	7.5 (Berkeley) 12/14/92
1254008Sfujita  */
1354008Sfujita 
1454008Sfujita /*
1554008Sfujita  * sio.c -- NEC uPD7201A UART Device Driver
1656873Sakito  *    remaked by A.Fujita, NOV-5-1992
1754008Sfujita  */
1854008Sfujita 
1954008Sfujita #include "sio.h"
2054008Sfujita #if NSIO > 0
2154008Sfujita 
2256873Sakito #include "bmc.h"
2354008Sfujita 
2457058Sakito #include <sys/param.h>
2557058Sakito #include <sys/systm.h>
2657058Sakito #include <sys/ioctl.h>
2757058Sakito #include <sys/proc.h>
2857058Sakito #include <sys/tty.h>
2957058Sakito #include <sys/conf.h>
3057058Sakito #include <sys/file.h>
3157058Sakito #include <sys/uio.h>
3257058Sakito #include <sys/kernel.h>
3357058Sakito #include <sys/syslog.h>
3454008Sfujita 
3557058Sakito #include <luna68k/dev/device.h>
3657058Sakito #include <luna68k/dev/sioreg.h>
3757058Sakito #include <luna68k/dev/siovar.h>
3854008Sfujita 
3956873Sakito struct sio_portc *sio_port_assign();
4054008Sfujita 
4156873Sakito int	sioprobe();
4256873Sakito int	sioopen();
4356873Sakito void	siostart();
4456873Sakito int	sioparam();
4556873Sakito int	siointr();
4654008Sfujita 
4754008Sfujita struct	driver siodriver = {
4854008Sfujita 	sioprobe, "sio",
4954008Sfujita };
5054008Sfujita 
5156873Sakito #define NPORT	2					/* uPD7201A has 2 serial-port */
5256873Sakito #define NLINE	1					/* number of active line */
5354008Sfujita 
5456873Sakito struct	sio_portc sio_portc[NPORT] = {
5556873Sakito 	{ -1, -1, (struct siodevice *) 0x51000000, (int (*)()) 0 },
5656873Sakito 	{ -1, -1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
5756873Sakito };
5854008Sfujita 
5956873Sakito struct	sio_softc sio_softc[NLINE];
6054008Sfujita 
6156873Sakito int	sio_init_done = 0;
6256873Sakito int	siounitbase = 0;				/* This counter is used unit number assignment */
6354008Sfujita 
6456873Sakito int	siosoftCAR;
6556873Sakito int	sio_active;
66*57126Sakito int	sioconsole = -1;
6756873Sakito int	siodefaultrate = TTYDEF_SPEED;
6856873Sakito int	siomajor = 0;
6954008Sfujita 
7056873Sakito struct	tty sio_tty[NLINE];
7154008Sfujita 
7256873Sakito struct speedtab siospeedtab[] = {
7356873Sakito 	2400,	WR4_BAUD24,
7456873Sakito 	4800,	WR4_BAUD48,
7556873Sakito 	9600,	WR4_BAUD96,
7654008Sfujita };
7754008Sfujita 
7856873Sakito #define	siounit(x)		minor(x)
7954008Sfujita 
80*57126Sakito extern	struct tty *constty;
8154008Sfujita 
8254008Sfujita /*
8356873Sakito  *  probe routines
8454008Sfujita  */
8554008Sfujita 
8654008Sfujita sioprobe(hd)
8754008Sfujita 	register struct hp_device *hd;
8854008Sfujita {
8956873Sakito 	register int port;
9056873Sakito 	register struct sio_portc *pc;
9156873Sakito 	register struct sio_softc *sc;
9254008Sfujita 
9356873Sakito 	sioinit((struct siodevice *) hd->hp_addr, siodefaultrate);
9454008Sfujita 
9556873Sakito 	/* locate the major number */
9656873Sakito 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
9756873Sakito 		if (cdevsw[siomajor].d_open == sioopen)
9856873Sakito 			break;
9954008Sfujita 
10056873Sakito 	for (port = 0; port < NPORT; port++) {
10156873Sakito 		pc = &sio_portc[port];
10254008Sfujita 
10356873Sakito 		if (pc->pc_major != -1) {
10456873Sakito 			printf("%s%d: port %d, address 0x%x, intr 0x%x (console)\n",
10556873Sakito 			       (pc->pc_major == siomajor ? "sio" : "bmc" ),
10656873Sakito 			       pc->pc_unit, port, pc->pc_addr, pc->pc_intr);
10756873Sakito 			continue;
10856873Sakito 		}
10954008Sfujita 
11056873Sakito 		pc->pc_addr =
11156873Sakito 			(struct siodevice *)((u_long) hd->hp_addr + (sizeof(struct siodevice) * port));
11256873Sakito #if NBMC > 0
11356873Sakito 		if (bmcinit(port))
11456873Sakito 			continue;
11556873Sakito #endif
11656873Sakito 		if (++siounitbase < NLINE) {
11756873Sakito 			pc->pc_major = siomajor;
11856873Sakito 			pc->pc_intr  = siointr;
11956873Sakito 			pc->pc_unit  = siounitbase;
12056873Sakito 			printf("sio%d: port %d, address 0x%x\n", pc->pc_unit, port, pc->pc_addr);
12154008Sfujita 
12256873Sakito 			sc = &sio_softc[pc->pc_unit];
12356873Sakito 			sc->sc_pc = pc;
12454008Sfujita 
12556873Sakito 			sio_active |= 1 << pc->pc_unit;
12656873Sakito 			siosoftCAR |= 1 << pc->pc_unit;
12756873Sakito 		}
12856873Sakito 	}
12956873Sakito }
13054008Sfujita 
13156873Sakito struct sio_portc *
13256873Sakito sio_port_assign(port, major, unit, intr)
13356873Sakito 	int	port, major, unit;
13456873Sakito 	int	(*intr)();
13556873Sakito {
13656873Sakito 	register struct sio_portc *pc = &sio_portc[port];
13754008Sfujita 
13856873Sakito 	if (pc->pc_major != -1)
13956873Sakito 		return((struct sio_portc *) 0);
14054008Sfujita 
14156873Sakito 	pc->pc_major = major;
14256873Sakito 	pc->pc_intr  = intr;
14356873Sakito 	pc->pc_unit  = unit;
14454008Sfujita 
14556873Sakito 	return(pc);
14654008Sfujita }
14754008Sfujita 
14856873Sakito 
14956873Sakito /*
15056873Sakito  *  entry routines
15156873Sakito  */
15256873Sakito 
15354008Sfujita /* ARGSUSED */
15454008Sfujita #ifdef __STDC__
15554008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
15654008Sfujita #else
15754008Sfujita sioopen(dev, flag, mode, p)
15854008Sfujita 	dev_t dev;
15954008Sfujita 	int flag, mode;
16054008Sfujita 	struct proc *p;
16154008Sfujita #endif
16254008Sfujita {
16354008Sfujita 	register struct tty *tp;
16454008Sfujita 	register int unit;
16554008Sfujita 	int error = 0;
16654008Sfujita 
16754008Sfujita 	unit = siounit(dev);
16856873Sakito 	if (unit >= NLINE || (sio_active & (1 << unit)) == 0)
16954008Sfujita 		return (ENXIO);
17054008Sfujita 	tp = &sio_tty[unit];
17154008Sfujita 	tp->t_oproc = siostart;
17254008Sfujita 	tp->t_param = sioparam;
17354008Sfujita 	tp->t_dev = dev;
17454008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
17554008Sfujita 		tp->t_state |= TS_WOPEN;
17654008Sfujita 		ttychars(tp);
17754008Sfujita 		if (tp->t_ispeed == 0) {
17854008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
17954008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
18056873Sakito /*			tp->t_cflag = TTYDEF_CFLAG;		*/
18154008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
18254008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
18354008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
18454008Sfujita 		}
18554008Sfujita 		sioparam(tp, &tp->t_termios);
18654008Sfujita 		ttsetwater(tp);
18754008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
18854008Sfujita 		return (EBUSY);
18956873Sakito 	(void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
19056873Sakito 	if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
19156873Sakito 		tp->t_state |= TS_CARR_ON;
19254008Sfujita 	(void) spltty();
19354008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
19454008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
19554008Sfujita 		tp->t_state |= TS_WOPEN;
19654008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
19754008Sfujita 		    ttopen, 0))
19854008Sfujita 			break;
19954008Sfujita 	}
20054008Sfujita 	(void) spl0();
20154008Sfujita 	if (error == 0)
20254008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
20354008Sfujita 	return (error);
20454008Sfujita }
20556873Sakito 
20654008Sfujita /*ARGSUSED*/
20754008Sfujita sioclose(dev, flag, mode, p)
20854008Sfujita 	dev_t dev;
20954008Sfujita 	int flag, mode;
21054008Sfujita 	struct proc *p;
21154008Sfujita {
21254008Sfujita 	register struct tty *tp;
21354008Sfujita 	register int unit;
21454008Sfujita 
21554008Sfujita 	unit = siounit(dev);
21654008Sfujita 	tp = &sio_tty[unit];
21754008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
21856873Sakito 	(void) siomctl(dev, WR5_BREAK, DMBIS);
21956873Sakito 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
22056873Sakito 	    (tp->t_state&TS_ISOPEN) == 0)
22156873Sakito 		(void) siomctl(dev, 0, DMSET);
22254008Sfujita 	ttyclose(tp);
22354008Sfujita 	return (0);
22454008Sfujita }
22554008Sfujita 
22654008Sfujita sioread(dev, uio, flag)
22754008Sfujita 	dev_t dev;
22854008Sfujita 	struct uio *uio;
22954008Sfujita {
23054008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
23154008Sfujita 
23254008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
23354008Sfujita }
23454008Sfujita 
23554008Sfujita siowrite(dev, uio, flag)
23654008Sfujita 	dev_t dev;
23754008Sfujita 	struct uio *uio;
23854008Sfujita {
239*57126Sakito 	register int unit = siounit(dev);
240*57126Sakito 	register struct tty *tp = &sio_tty[unit];
24154008Sfujita 
242*57126Sakito 	if ((unit == sioconsole) && constty &&
243*57126Sakito 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
244*57126Sakito 		tp = constty;
245*57126Sakito 
24654008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24754008Sfujita }
24854008Sfujita 
24956873Sakito /*
25056873Sakito  * Stop output on a line.
25156873Sakito  */
25256873Sakito /*ARGSUSED*/
25356873Sakito siostop(tp, flag)
25456873Sakito 	register struct tty *tp;
25554008Sfujita {
25656873Sakito 	register int s;
25754008Sfujita 
25856873Sakito 	s = spltty();
25956873Sakito 	if (tp->t_state & TS_BUSY) {
26056873Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
26156873Sakito 			tp->t_state |= TS_FLUSH;
26254008Sfujita 	}
26356873Sakito 	splx(s);
26454008Sfujita }
26554008Sfujita 
26654008Sfujita sioioctl(dev, cmd, data, flag, p)
26754008Sfujita 	dev_t dev;
26854008Sfujita 	int cmd;
26954008Sfujita 	caddr_t data;
27054008Sfujita 	int flag;
27154008Sfujita 	struct proc *p;
27254008Sfujita {
27354008Sfujita 	register struct tty *tp;
27454008Sfujita 	register int unit = siounit(dev);
27554008Sfujita 	register int error;
27656873Sakito 
27754008Sfujita 	tp = &sio_tty[unit];
27854008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
27954008Sfujita 	if (error >= 0)
28054008Sfujita 		return (error);
28154008Sfujita 	error = ttioctl(tp, cmd, data, flag);
28254008Sfujita 	if (error >= 0)
28354008Sfujita 		return (error);
28454008Sfujita 
28554008Sfujita 	switch (cmd) {
28654008Sfujita 
28754008Sfujita 	case TIOCSBRK:
28856873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIS);
28956873Sakito 		break;
29056873Sakito 
29154008Sfujita 	case TIOCCBRK:
29256873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIC);
29356873Sakito 		break;
29456873Sakito 
29554008Sfujita 	case TIOCSDTR:
29656873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
29756873Sakito 		break;
29856873Sakito 
29954008Sfujita 	case TIOCCDTR:
30056873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
30156873Sakito 		break;
30256873Sakito 
30354008Sfujita 	case TIOCMSET:
30456873Sakito 		(void) siomctl(dev, *(int *)data, DMSET);
30556873Sakito 		break;
30656873Sakito 
30754008Sfujita 	case TIOCMBIS:
30856873Sakito 		(void) siomctl(dev, *(int *)data, DMBIS);
30956873Sakito 		break;
31056873Sakito 
31154008Sfujita 	case TIOCMBIC:
31256873Sakito 		(void) siomctl(dev, *(int *)data, DMBIC);
31356873Sakito 		break;
31456873Sakito 
31554008Sfujita 	case TIOCMGET:
31656873Sakito 		*(int *)data = siomctl(dev, 0, DMGET);
31756873Sakito 		break;
31856873Sakito 
31954008Sfujita 	default:
32054008Sfujita 		return (ENOTTY);
32154008Sfujita 	}
32254008Sfujita 	return (0);
32354008Sfujita }
32454008Sfujita 
32554008Sfujita 
32656873Sakito /*
32756873Sakito  *
32856873Sakito  */
32956873Sakito 
33054008Sfujita void
33154008Sfujita siostart(tp)
33254008Sfujita 	register struct tty *tp;
33354008Sfujita {
33454008Sfujita 	register struct siodevice *sio;
33556873Sakito 	register int rr;
33656873Sakito 	int s, unit, c;
33754008Sfujita 
33854008Sfujita 	unit = siounit(tp->t_dev);
33956873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
34054008Sfujita 	s = spltty();
34154008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
34254008Sfujita 		goto out;
34354008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
34454008Sfujita 		if (tp->t_state&TS_ASLEEP) {
34554008Sfujita 			tp->t_state &= ~TS_ASLEEP;
34654008Sfujita 			wakeup((caddr_t)&tp->t_outq);
34754008Sfujita 		}
34854008Sfujita 		selwakeup(&tp->t_wsel);
34954008Sfujita 	}
35054008Sfujita 	if (tp->t_outq.c_cc == 0)
35154008Sfujita 		goto out;
35256873Sakito 	rr = siogetreg(sio);
35354008Sfujita 	if (rr & RR_TXRDY) {
35454008Sfujita 		c = getc(&tp->t_outq);
35554008Sfujita 		tp->t_state |= TS_BUSY;
35654008Sfujita 		sio->sio_data = c;
35754008Sfujita 	}
35854008Sfujita out:
35954008Sfujita 	splx(s);
36054008Sfujita }
36156873Sakito 
36256873Sakito sioparam(tp, t)
36356873Sakito 	register struct tty *tp;
36456873Sakito 	register struct termios *t;
36556873Sakito {
36656873Sakito 	int unit = siounit(tp->t_dev);
36756873Sakito 	register struct siodevice *sio;
36856873Sakito 	register cflag = t->c_cflag;
36956873Sakito 	register u_char wr;
37056873Sakito 	int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
37156873Sakito 
37256873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
37356873Sakito 
37456873Sakito 	switch (cflag & CSIZE) {
37556873Sakito 	case CS5:
37656873Sakito 	case CS6:
37756873Sakito 	case CS7:
37856873Sakito 	case CS8:
37956873Sakito 		break;
38056873Sakito 	}
38156873Sakito 
38256873Sakito 	wr = ospeed;
38356873Sakito 
38456873Sakito 	if (cflag & PARENB) {
38556873Sakito 		wr |= WR4_PARENAB;
38656873Sakito 		if ((cflag&PARODD) == 0)
38756873Sakito 			wr |= WR4_EPARITY;
38856873Sakito 	}
38956873Sakito 
39056873Sakito 	if (cflag & CSTOPB)
39156873Sakito 		wr |= WR4_STOP2;			/* 2 stop bit */
39256873Sakito 	else
39356873Sakito 		wr |= WR4_STOP1;			/* 1 stop bit */
39456873Sakito 
39556873Sakito 	(void) sioreg(sio, WR4, wr);
39656873Sakito 
39756873Sakito 	return (0);
39856873Sakito }
39956873Sakito 
40056873Sakito siomctl()
40156873Sakito {
40256873Sakito 	return (0);
40356873Sakito }
40456873Sakito 
40556873Sakito 
40654008Sfujita /*
40756873Sakito  *  Interrupt handling
40854008Sfujita  */
40956873Sakito 
41056873Sakito void
41156873Sakito _siointr()
41254008Sfujita {
41356873Sakito 	register int port;
41456873Sakito 	register struct sio_portc *pc;
41554008Sfujita 
41656873Sakito 	for (port = 0; port < NPORT; port++) {
41756873Sakito 		pc = &sio_portc[port];
41856873Sakito 
41956873Sakito 		if (pc->pc_major != -1)
42056873Sakito 			(pc->pc_intr)(pc->pc_unit);
42154008Sfujita 	}
42254008Sfujita }
42354008Sfujita 
42456873Sakito siointr(unit)
42556873Sakito 	register int unit;
42656873Sakito {
42756873Sakito 	register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
42856873Sakito 	register u_char code;
42956873Sakito 	register struct tty *tp;
43056873Sakito 	int s, rr;
43156873Sakito 
43256873Sakito 	tp = &sio_tty[unit];
43356873Sakito 	rr = siogetreg(sio);
43456873Sakito 
43556873Sakito 	if (rr & RR_RXRDY) {
43656873Sakito 		code = sio->sio_data;
43756873Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
43856873Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
43956873Sakito 	}
44056873Sakito 
44156873Sakito 	if (rr & RR_TXRDY) {
44256873Sakito 		sio->sio_cmd = WR0_RSTPEND;
44356873Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
44456873Sakito 		if (tp->t_line)
44556873Sakito 			(*linesw[tp->t_line].l_start)(tp);
44656873Sakito 		else
44756873Sakito 			siostart(tp);
44856873Sakito 	}
44956873Sakito }
45056873Sakito 
45154008Sfujita /*
45254008Sfujita  * Following are all routines needed for SIO to act as console
45354008Sfujita  */
45457058Sakito #include <luna68k/luna68k/cons.h>
45554008Sfujita 
45654008Sfujita siocnprobe(cp)
45756873Sakito 	register struct consdev *cp;
45854008Sfujita {
45956873Sakito 	register int unit = 0;
46054008Sfujita 
46154008Sfujita 	/* locate the major number */
46254008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
46354008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
46454008Sfujita 			break;
46554008Sfujita 
46656873Sakito 	siounitbase = -1;
46754008Sfujita 
46854008Sfujita 	/* initialize required fields */
46954008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
47056873Sakito 	cp->cn_tp  = &sio_tty[unit];
47154008Sfujita 	cp->cn_pri = CN_NORMAL;
47254008Sfujita }
47354008Sfujita 
47454008Sfujita siocninit(cp)
47554008Sfujita 	struct consdev *cp;
47654008Sfujita {
47754008Sfujita 	int unit = siounit(cp->cn_dev);
47856873Sakito 	register struct sio_softc *sc = &sio_softc[unit];
47954008Sfujita 
48056873Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
48156873Sakito 
48256873Sakito 	/* port assign */
48356873Sakito 	sc->sc_pc = sio_port_assign(0, siomajor, unit, siointr);
48456873Sakito 
48554008Sfujita 	sioconsole = unit;
48656873Sakito 	siounitbase = 0;
48756873Sakito 
48856873Sakito 	sio_active |= 1 << unit;
48956873Sakito 	siosoftCAR |= 1 << unit;
49054008Sfujita }
49154008Sfujita 
49254008Sfujita siocngetc(dev)
49354008Sfujita 	dev_t dev;
49454008Sfujita {
49556873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
49656873Sakito 	struct sio_portc *pc = sc->sc_pc;
49754008Sfujita 
49856873Sakito 	return(sio_imgetc(pc->pc_addr));
49954008Sfujita }
50054008Sfujita 
50154008Sfujita siocnputc(dev, c)
50254008Sfujita 	dev_t dev;
50354008Sfujita 	int c;
50454008Sfujita {
50556873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
50656873Sakito 	struct sio_portc *pc = sc->sc_pc;
50754008Sfujita 
50856873Sakito 	sio_imputc(pc->pc_addr, c);
50956873Sakito }
51054008Sfujita 
51154008Sfujita 
51256873Sakito /*
51356873Sakito  *  sio raw-level routines
51456873Sakito  */
51554008Sfujita 
51656873Sakito sioinit(sio0, rate)
51756873Sakito 	register struct siodevice *sio0;
51856873Sakito 	register int rate;
51956873Sakito {
52056873Sakito 	register struct siodevice *sio1;
52156873Sakito 	int s;
52254008Sfujita 
52356873Sakito 	rate = ttspeedtab(rate, siospeedtab);
52454008Sfujita 
52556873Sakito 	if (sio_init_done)
52656873Sakito 		return;
52754008Sfujita 
52856873Sakito 	sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
52954008Sfujita 
53054008Sfujita 	s = splhigh();
53154008Sfujita 
53256873Sakito 	sioreg(sio0, WR0,  WR0_CHANRST);		/* Channel-A Reset */
53354008Sfujita 
53456873Sakito 	sioreg(sio0, WR2, (WR2_VEC86  | WR2_INTR_1));	/* Set CPU BUS Interface Mode */
53556873Sakito 	sioreg(sio1, WR2,  0);				/* Set Interrupt Vector */
53654008Sfujita 
53756873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
53856873Sakito 	sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
53956873Sakito 	sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
54056873Sakito 	sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
54156873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
54256873Sakito 	sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
54354008Sfujita 
54456873Sakito 	sioreg(sio1, WR0,  WR0_CHANRST);		/* Channel-B Reset */
54554008Sfujita 
54656873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
54756873Sakito 	sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
54856873Sakito 	sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
54956873Sakito 	sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
55056873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
55156873Sakito 	sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
55256873Sakito 
55354008Sfujita 	splx(s);
55456873Sakito 
55556873Sakito 	sio_init_done = 1;
55654008Sfujita }
55754008Sfujita 
55856873Sakito sio_imgetc(sio)
55956873Sakito 	register struct siodevice *sio;
56054008Sfujita {
56156873Sakito 	register int rr0, rr1;
56256873Sakito 	int c, s;
56354008Sfujita 
56456873Sakito 	s = splhigh();
56556873Sakito 	while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
56656873Sakito 		;
56756873Sakito 	c = sio->sio_data;
56856873Sakito 	sioreg(sio, WR0, WR0_RSTPEND);
56956873Sakito 	splx(s);
57056873Sakito 	return (c);
57154008Sfujita }
57254008Sfujita 
57356873Sakito sio_imputc(sio, c)
57456873Sakito 	register struct siodevice *sio;
57554008Sfujita 	int c;
57654008Sfujita {
57754008Sfujita 	register u_char code;
57856873Sakito 	register int rr;
57956873Sakito 	int s;
58054008Sfujita 
58154008Sfujita 	s = splhigh();
58254008Sfujita 
58356873Sakito 	sioreg(sio, WR1, WR1_RXALLS);
58456873Sakito 
58554008Sfujita 	do {
58654008Sfujita 		DELAY(1);
58756873Sakito 		rr = siogetreg(sio);
58854008Sfujita 	} while (!(rr & RR_TXRDY));
58956873Sakito 
59056873Sakito 	code = (c & 0xFF);
59154008Sfujita 	sio->sio_data = code;
59254008Sfujita 
59354008Sfujita 	do {
59454008Sfujita 		DELAY(1);
59556873Sakito 		rr = siogetreg(sio);
59654008Sfujita 	} while (!(rr & RR_TXRDY));
59754008Sfujita 
59856873Sakito 	sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
59956873Sakito 
60054008Sfujita 	splx(s);
60154008Sfujita }
60254008Sfujita 
60356873Sakito /*
60456873Sakito  *  uPD7201A register operation
60556873Sakito  */
60654008Sfujita 
60754008Sfujita int
60856873Sakito siogetreg(sio)
60956873Sakito 	register struct siodevice *sio;
61054008Sfujita {
61154008Sfujita 	register int rr = 0;
61254008Sfujita 
61354008Sfujita 	rr = sio->sio_stat;
61454008Sfujita 	rr <<= 8;
61554008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
61654008Sfujita 	rr |= sio->sio_stat;
61754008Sfujita 
61854008Sfujita 	return(rr);
61954008Sfujita }
62054008Sfujita 
62154008Sfujita int
62256873Sakito sioreg(sio, reg, val)
62356873Sakito 	register struct siodevice *sio;
62454008Sfujita 	register int reg, val;
62554008Sfujita {
62654008Sfujita 	if (isStatusReg(reg)) {
62756873Sakito 		if (reg != 0)
62856873Sakito 		    sio->sio_cmd = reg;
62956873Sakito 		val = sio->sio_stat;
63054008Sfujita 	} else {
63156873Sakito 		if (reg != 0)
63256873Sakito 		    sio->sio_cmd = reg;
63356873Sakito 		sio->sio_cmd = val;
63454008Sfujita 	}
63556873Sakito 
63656873Sakito 	return(val);
63754008Sfujita }
63854008Sfujita #endif
639