xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 59648)
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*59648Sakito  *	@(#)sio.c	7.8 (Berkeley) 05/02/93
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();
4057291Sakito struct sio_portc *sio_port_get();
4154008Sfujita 
4256873Sakito int	sioprobe();
4356873Sakito int	sioopen();
4456873Sakito void	siostart();
4556873Sakito int	sioparam();
4656873Sakito int	siointr();
4754008Sfujita 
4854008Sfujita struct	driver siodriver = {
4954008Sfujita 	sioprobe, "sio",
5054008Sfujita };
5154008Sfujita 
5256873Sakito struct	sio_portc sio_portc[NPORT] = {
53*59648Sakito 	{ -1, -1, 0, (struct siodevice *) 0x51000000, (int (*)()) 0 },
54*59648Sakito 	{ -1, -1, 1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
5556873Sakito };
5654008Sfujita 
57*59648Sakito struct	sio_softc sio_softc[NSIO];
5854008Sfujita 
5956873Sakito int	sio_init_done = 0;
6054008Sfujita 
6156873Sakito int	siosoftCAR;
6256873Sakito int	sio_active;
6357126Sakito int	sioconsole = -1;
6456873Sakito int	siodefaultrate = TTYDEF_SPEED;
6557291Sakito int	siomajor = 12;
6654008Sfujita 
67*59648Sakito struct	tty sio_tty[NSIO];
6854008Sfujita 
6956873Sakito struct speedtab siospeedtab[] = {
7056873Sakito 	2400,	WR4_BAUD24,
7156873Sakito 	4800,	WR4_BAUD48,
7256873Sakito 	9600,	WR4_BAUD96,
7354008Sfujita };
7454008Sfujita 
7556873Sakito #define	siounit(x)		minor(x)
7654008Sfujita 
7757126Sakito extern	struct tty *constty;
7854008Sfujita 
7954008Sfujita /*
8056873Sakito  *  probe routines
8154008Sfujita  */
8254008Sfujita 
8354008Sfujita sioprobe(hd)
8454008Sfujita 	register struct hp_device *hd;
8554008Sfujita {
86*59648Sakito 	int unit = hd->hp_unit;
87*59648Sakito 	register struct sio_softc *sc = &sio_softc[unit];
8856873Sakito 	register struct sio_portc *pc;
8954008Sfujita 
90*59648Sakito 	if (sc->sc_pc != 0) {
91*59648Sakito 		pc = sc->sc_pc;
92*59648Sakito 		printf("sio%d: port %d, address 0x%x, intr 0x%x (console)\n",
93*59648Sakito 		       pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
94*59648Sakito 		return(0);
95*59648Sakito 	}
9654008Sfujita 
97*59648Sakito 	sc->sc_pc = pc = sio_port_assign(SIO_PORT, siomajor, unit, siointr);
9854008Sfujita 
99*59648Sakito 	printf("sio%d: port %d, address 0x%x, intr 0x%x\n",
100*59648Sakito 	       pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
10154008Sfujita 
102*59648Sakito 	sio_active |= 1 << unit;
103*59648Sakito 	siosoftCAR |= 1 << unit;
104*59648Sakito 	return(1);
10556873Sakito }
10654008Sfujita 
10756873Sakito struct sio_portc *
10856873Sakito sio_port_assign(port, major, unit, intr)
10956873Sakito 	int	port, major, unit;
11056873Sakito 	int	(*intr)();
11156873Sakito {
11257291Sakito 	register struct sio_portc *pc;
11354008Sfujita 
11457291Sakito 	pc = &sio_portc[port];
11557291Sakito 
11656873Sakito 	pc->pc_major = major;
11756873Sakito 	pc->pc_intr  = intr;
11856873Sakito 	pc->pc_unit  = unit;
11954008Sfujita 
12056873Sakito 	return(pc);
12154008Sfujita }
12254008Sfujita 
12357291Sakito struct sio_portc *
12457291Sakito sio_port_get(port)
12557291Sakito 	int port;
12657291Sakito {
12757291Sakito 	register struct sio_portc *pc;
12856873Sakito 
12957291Sakito 	pc = &sio_portc[port];
13057291Sakito 
13157291Sakito 	return(pc);
13257291Sakito }
13357291Sakito 
13457291Sakito int
13557291Sakito sio_port_info()
13657291Sakito {
13757291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
13857291Sakito 		0, sio_portc[0].pc_major, sio_portc[0].pc_unit, sio_portc[0].pc_intr);
13957291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
14057291Sakito 		1, sio_portc[1].pc_major, sio_portc[1].pc_unit, sio_portc[1].pc_intr);
14157291Sakito }
14257291Sakito 
14357291Sakito 
14456873Sakito /*
14556873Sakito  *  entry routines
14656873Sakito  */
14756873Sakito 
14854008Sfujita /* ARGSUSED */
14954008Sfujita #ifdef __STDC__
15054008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
15154008Sfujita #else
15254008Sfujita sioopen(dev, flag, mode, p)
15354008Sfujita 	dev_t dev;
15454008Sfujita 	int flag, mode;
15554008Sfujita 	struct proc *p;
15654008Sfujita #endif
15754008Sfujita {
15854008Sfujita 	register struct tty *tp;
15954008Sfujita 	register int unit;
16054008Sfujita 	int error = 0;
16154008Sfujita 
16254008Sfujita 	unit = siounit(dev);
163*59648Sakito 	if (unit >= NSIO || (sio_active & (1 << unit)) == 0)
16454008Sfujita 		return (ENXIO);
16554008Sfujita 	tp = &sio_tty[unit];
16654008Sfujita 	tp->t_oproc = siostart;
16754008Sfujita 	tp->t_param = sioparam;
16854008Sfujita 	tp->t_dev = dev;
16954008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
17054008Sfujita 		tp->t_state |= TS_WOPEN;
17154008Sfujita 		ttychars(tp);
17254008Sfujita 		if (tp->t_ispeed == 0) {
17354008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
17454008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
17556873Sakito /*			tp->t_cflag = TTYDEF_CFLAG;		*/
17654008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
17754008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
17854008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
17954008Sfujita 		}
18054008Sfujita 		sioparam(tp, &tp->t_termios);
18154008Sfujita 		ttsetwater(tp);
18254008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
18354008Sfujita 		return (EBUSY);
18456873Sakito 	(void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
18556873Sakito 	if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
18656873Sakito 		tp->t_state |= TS_CARR_ON;
18754008Sfujita 	(void) spltty();
18854008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
18954008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
19054008Sfujita 		tp->t_state |= TS_WOPEN;
19154008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
19254008Sfujita 		    ttopen, 0))
19354008Sfujita 			break;
19454008Sfujita 	}
19554008Sfujita 	(void) spl0();
19654008Sfujita 	if (error == 0)
19754008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
19854008Sfujita 	return (error);
19954008Sfujita }
20056873Sakito 
20154008Sfujita /*ARGSUSED*/
20254008Sfujita sioclose(dev, flag, mode, p)
20354008Sfujita 	dev_t dev;
20454008Sfujita 	int flag, mode;
20554008Sfujita 	struct proc *p;
20654008Sfujita {
20754008Sfujita 	register struct tty *tp;
20854008Sfujita 	register int unit;
20954008Sfujita 
21054008Sfujita 	unit = siounit(dev);
21154008Sfujita 	tp = &sio_tty[unit];
21254008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
21356873Sakito 	(void) siomctl(dev, WR5_BREAK, DMBIS);
21456873Sakito 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
21556873Sakito 	    (tp->t_state&TS_ISOPEN) == 0)
21656873Sakito 		(void) siomctl(dev, 0, DMSET);
21754008Sfujita 	ttyclose(tp);
21854008Sfujita 	return (0);
21954008Sfujita }
22054008Sfujita 
22154008Sfujita sioread(dev, uio, flag)
22254008Sfujita 	dev_t dev;
22354008Sfujita 	struct uio *uio;
22454008Sfujita {
22554008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
22654008Sfujita 
22754008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
22854008Sfujita }
22954008Sfujita 
23054008Sfujita siowrite(dev, uio, flag)
23154008Sfujita 	dev_t dev;
23254008Sfujita 	struct uio *uio;
23354008Sfujita {
23457126Sakito 	register int unit = siounit(dev);
23557126Sakito 	register struct tty *tp = &sio_tty[unit];
23654008Sfujita 
23757126Sakito 	if ((unit == sioconsole) && constty &&
23857126Sakito 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
23957126Sakito 		tp = constty;
24057126Sakito 
24154008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
24254008Sfujita }
24354008Sfujita 
24456873Sakito /*
24556873Sakito  * Stop output on a line.
24656873Sakito  */
24756873Sakito /*ARGSUSED*/
24856873Sakito siostop(tp, flag)
24956873Sakito 	register struct tty *tp;
25054008Sfujita {
25156873Sakito 	register int s;
25254008Sfujita 
25356873Sakito 	s = spltty();
25456873Sakito 	if (tp->t_state & TS_BUSY) {
25556873Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
25656873Sakito 			tp->t_state |= TS_FLUSH;
25754008Sfujita 	}
25856873Sakito 	splx(s);
25954008Sfujita }
26054008Sfujita 
26154008Sfujita sioioctl(dev, cmd, data, flag, p)
26254008Sfujita 	dev_t dev;
26354008Sfujita 	int cmd;
26454008Sfujita 	caddr_t data;
26554008Sfujita 	int flag;
26654008Sfujita 	struct proc *p;
26754008Sfujita {
26854008Sfujita 	register struct tty *tp;
26954008Sfujita 	register int unit = siounit(dev);
27054008Sfujita 	register int error;
27156873Sakito 
27254008Sfujita 	tp = &sio_tty[unit];
27354008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
27454008Sfujita 	if (error >= 0)
27554008Sfujita 		return (error);
27654008Sfujita 	error = ttioctl(tp, cmd, data, flag);
27754008Sfujita 	if (error >= 0)
27854008Sfujita 		return (error);
27954008Sfujita 
28054008Sfujita 	switch (cmd) {
28154008Sfujita 
28254008Sfujita 	case TIOCSBRK:
28356873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIS);
28456873Sakito 		break;
28556873Sakito 
28654008Sfujita 	case TIOCCBRK:
28756873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIC);
28856873Sakito 		break;
28956873Sakito 
29054008Sfujita 	case TIOCSDTR:
29156873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
29256873Sakito 		break;
29356873Sakito 
29454008Sfujita 	case TIOCCDTR:
29556873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
29656873Sakito 		break;
29756873Sakito 
29854008Sfujita 	case TIOCMSET:
29956873Sakito 		(void) siomctl(dev, *(int *)data, DMSET);
30056873Sakito 		break;
30156873Sakito 
30254008Sfujita 	case TIOCMBIS:
30356873Sakito 		(void) siomctl(dev, *(int *)data, DMBIS);
30456873Sakito 		break;
30556873Sakito 
30654008Sfujita 	case TIOCMBIC:
30756873Sakito 		(void) siomctl(dev, *(int *)data, DMBIC);
30856873Sakito 		break;
30956873Sakito 
31054008Sfujita 	case TIOCMGET:
31156873Sakito 		*(int *)data = siomctl(dev, 0, DMGET);
31256873Sakito 		break;
31356873Sakito 
31454008Sfujita 	default:
31554008Sfujita 		return (ENOTTY);
31654008Sfujita 	}
31754008Sfujita 	return (0);
31854008Sfujita }
31954008Sfujita 
32054008Sfujita 
32156873Sakito /*
32256873Sakito  *
32356873Sakito  */
32456873Sakito 
32554008Sfujita void
32654008Sfujita siostart(tp)
32754008Sfujita 	register struct tty *tp;
32854008Sfujita {
32954008Sfujita 	register struct siodevice *sio;
33056873Sakito 	register int rr;
33156873Sakito 	int s, unit, c;
33254008Sfujita 
33354008Sfujita 	unit = siounit(tp->t_dev);
33456873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
33554008Sfujita 	s = spltty();
33654008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
33754008Sfujita 		goto out;
33854008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
33954008Sfujita 		if (tp->t_state&TS_ASLEEP) {
34054008Sfujita 			tp->t_state &= ~TS_ASLEEP;
34154008Sfujita 			wakeup((caddr_t)&tp->t_outq);
34254008Sfujita 		}
34354008Sfujita 		selwakeup(&tp->t_wsel);
34454008Sfujita 	}
34554008Sfujita 	if (tp->t_outq.c_cc == 0)
34654008Sfujita 		goto out;
34756873Sakito 	rr = siogetreg(sio);
34854008Sfujita 	if (rr & RR_TXRDY) {
34954008Sfujita 		c = getc(&tp->t_outq);
35054008Sfujita 		tp->t_state |= TS_BUSY;
35154008Sfujita 		sio->sio_data = c;
35254008Sfujita 	}
35354008Sfujita out:
35454008Sfujita 	splx(s);
35554008Sfujita }
35656873Sakito 
35756873Sakito sioparam(tp, t)
35856873Sakito 	register struct tty *tp;
35956873Sakito 	register struct termios *t;
36056873Sakito {
36156873Sakito 	int unit = siounit(tp->t_dev);
36256873Sakito 	register struct siodevice *sio;
36356873Sakito 	register cflag = t->c_cflag;
36456873Sakito 	register u_char wr;
36556873Sakito 	int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
36656873Sakito 
36756873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
36856873Sakito 
36956873Sakito 	switch (cflag & CSIZE) {
37056873Sakito 	case CS5:
37156873Sakito 	case CS6:
37256873Sakito 	case CS7:
37356873Sakito 	case CS8:
37456873Sakito 		break;
37556873Sakito 	}
37656873Sakito 
37756873Sakito 	wr = ospeed;
37856873Sakito 
37956873Sakito 	if (cflag & PARENB) {
38056873Sakito 		wr |= WR4_PARENAB;
38156873Sakito 		if ((cflag&PARODD) == 0)
38256873Sakito 			wr |= WR4_EPARITY;
38356873Sakito 	}
38456873Sakito 
38556873Sakito 	if (cflag & CSTOPB)
38656873Sakito 		wr |= WR4_STOP2;			/* 2 stop bit */
38756873Sakito 	else
38856873Sakito 		wr |= WR4_STOP1;			/* 1 stop bit */
38956873Sakito 
39056873Sakito 	(void) sioreg(sio, WR4, wr);
39156873Sakito 
39256873Sakito 	return (0);
39356873Sakito }
39456873Sakito 
39556873Sakito siomctl()
39656873Sakito {
39756873Sakito 	return (0);
39856873Sakito }
39956873Sakito 
40056873Sakito 
40154008Sfujita /*
40256873Sakito  *  Interrupt handling
40354008Sfujita  */
40456873Sakito 
40556873Sakito void
40656873Sakito _siointr()
40754008Sfujita {
40856873Sakito 	register int port;
40956873Sakito 	register struct sio_portc *pc;
41054008Sfujita 
41156873Sakito 	for (port = 0; port < NPORT; port++) {
41256873Sakito 		pc = &sio_portc[port];
41356873Sakito 
41456873Sakito 		if (pc->pc_major != -1)
41556873Sakito 			(pc->pc_intr)(pc->pc_unit);
41654008Sfujita 	}
41754008Sfujita }
41854008Sfujita 
41956873Sakito siointr(unit)
42056873Sakito 	register int unit;
42156873Sakito {
42256873Sakito 	register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
42356873Sakito 	register u_char code;
42456873Sakito 	register struct tty *tp;
42556873Sakito 	int s, rr;
42656873Sakito 
42756873Sakito 	tp = &sio_tty[unit];
42857850Sakito 
42957850Sakito start:
43056873Sakito 	rr = siogetreg(sio);
43157850Sakito 	if (rr & RR_RXRDY) {
43257850Sakito 		if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
43357850Sakito 			sioeint(unit, rr, sio);
43457850Sakito 			goto start;
43557850Sakito 		}
43656873Sakito 
43756873Sakito 		code = sio->sio_data;
43856873Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
43956873Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
44057850Sakito 
44157850Sakito 		while ((rr = siogetreg(sio)) & RR_RXRDY) {
44257850Sakito 			code = sio->sio_data;
44357850Sakito 			if ((tp->t_state & TS_ISOPEN) != 0)
44457850Sakito 				(*linesw[tp->t_line].l_rint)(code, tp);
44557850Sakito 		}
44656873Sakito 	}
44756873Sakito 
44856873Sakito 	if (rr & RR_TXRDY) {
44956873Sakito 		sio->sio_cmd = WR0_RSTPEND;
45056873Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
45156873Sakito 		if (tp->t_line)
45256873Sakito 			(*linesw[tp->t_line].l_start)(tp);
45356873Sakito 		else
45456873Sakito 			siostart(tp);
45556873Sakito 	}
45656873Sakito }
45756873Sakito 
45857850Sakito sioeint(unit, stat, sio)
45957850Sakito 	register int unit, stat;
46057850Sakito 	register struct siodevice *sio;
46157850Sakito {
46257850Sakito 	register struct tty *tp;
46357850Sakito 	register int code;
46457850Sakito 
46557850Sakito 	tp = &sio_tty[unit];
46657850Sakito 
46757850Sakito 	code = sio->sio_data;
46857850Sakito 
46957850Sakito 	sio->sio_cmd = WR0_ERRRST;
47057850Sakito 
47157850Sakito 	if ((tp->t_state & TS_ISOPEN) == 0)
47257850Sakito 		return;
47357850Sakito 
47457850Sakito 	if (stat & RR_FRAMING)
47557850Sakito 		code |= TTY_FE;
47657850Sakito 	else if (stat & RR_PARITY)
47757850Sakito 		code |= TTY_PE;
47857850Sakito 
47957850Sakito 	(*linesw[tp->t_line].l_rint)(code, tp);
48057850Sakito }
48157850Sakito 
48254008Sfujita /*
48354008Sfujita  * Following are all routines needed for SIO to act as console
48454008Sfujita  */
48557058Sakito #include <luna68k/luna68k/cons.h>
48654008Sfujita 
48754008Sfujita siocnprobe(cp)
48856873Sakito 	register struct consdev *cp;
48954008Sfujita {
49056873Sakito 	register int unit = 0;
49154008Sfujita 
49254008Sfujita 	/* locate the major number */
49354008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
49454008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
49554008Sfujita 			break;
49654008Sfujita 
49754008Sfujita 	/* initialize required fields */
49854008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
49956873Sakito 	cp->cn_tp  = &sio_tty[unit];
50054008Sfujita 	cp->cn_pri = CN_NORMAL;
50154008Sfujita }
50254008Sfujita 
50354008Sfujita siocninit(cp)
50454008Sfujita 	struct consdev *cp;
50554008Sfujita {
50654008Sfujita 	int unit = siounit(cp->cn_dev);
50756873Sakito 	register struct sio_softc *sc = &sio_softc[unit];
50854008Sfujita 
50956873Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
51056873Sakito 
51156873Sakito 	/* port assign */
512*59648Sakito 	sc->sc_pc = sio_port_assign(SIO_PORT, siomajor, unit, siointr);
51356873Sakito 
51454008Sfujita 	sioconsole = unit;
51556873Sakito 	sio_active |= 1 << unit;
51656873Sakito 	siosoftCAR |= 1 << unit;
51754008Sfujita }
51854008Sfujita 
51954008Sfujita siocngetc(dev)
52054008Sfujita 	dev_t dev;
52154008Sfujita {
52256873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
52356873Sakito 	struct sio_portc *pc = sc->sc_pc;
52454008Sfujita 
52556873Sakito 	return(sio_imgetc(pc->pc_addr));
52654008Sfujita }
52754008Sfujita 
52854008Sfujita siocnputc(dev, c)
52954008Sfujita 	dev_t dev;
53054008Sfujita 	int c;
53154008Sfujita {
53256873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
53356873Sakito 	struct sio_portc *pc = sc->sc_pc;
53454008Sfujita 
53556873Sakito 	sio_imputc(pc->pc_addr, c);
53656873Sakito }
53754008Sfujita 
53854008Sfujita 
53956873Sakito /*
54056873Sakito  *  sio raw-level routines
54156873Sakito  */
54254008Sfujita 
54356873Sakito sioinit(sio0, rate)
54456873Sakito 	register struct siodevice *sio0;
54556873Sakito 	register int rate;
54656873Sakito {
54756873Sakito 	register struct siodevice *sio1;
54856873Sakito 	int s;
54954008Sfujita 
55056873Sakito 	rate = ttspeedtab(rate, siospeedtab);
55154008Sfujita 
55256873Sakito 	if (sio_init_done)
55356873Sakito 		return;
55454008Sfujita 
55556873Sakito 	sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
55654008Sfujita 
55754008Sfujita 	s = splhigh();
55854008Sfujita 
55956873Sakito 	sioreg(sio0, WR0,  WR0_CHANRST);		/* Channel-A Reset */
56054008Sfujita 
56156873Sakito 	sioreg(sio0, WR2, (WR2_VEC86  | WR2_INTR_1));	/* Set CPU BUS Interface Mode */
56256873Sakito 	sioreg(sio1, WR2,  0);				/* Set Interrupt Vector */
56354008Sfujita 
56456873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
56556873Sakito 	sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
56656873Sakito 	sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
56756873Sakito 	sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
56856873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
56956873Sakito 	sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
57054008Sfujita 
57156873Sakito 	sioreg(sio1, WR0,  WR0_CHANRST);		/* Channel-B Reset */
57254008Sfujita 
57356873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
57456873Sakito 	sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
57556873Sakito 	sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
57656873Sakito 	sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
57756873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
57856873Sakito 	sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
57956873Sakito 
58054008Sfujita 	splx(s);
58156873Sakito 
58256873Sakito 	sio_init_done = 1;
58354008Sfujita }
58454008Sfujita 
58556873Sakito sio_imgetc(sio)
58656873Sakito 	register struct siodevice *sio;
58754008Sfujita {
58856873Sakito 	register int rr0, rr1;
58956873Sakito 	int c, s;
59054008Sfujita 
59156873Sakito 	s = splhigh();
59256873Sakito 	while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
59356873Sakito 		;
59456873Sakito 	c = sio->sio_data;
59556873Sakito 	sioreg(sio, WR0, WR0_RSTPEND);
59656873Sakito 	splx(s);
59756873Sakito 	return (c);
59854008Sfujita }
59954008Sfujita 
60056873Sakito sio_imputc(sio, c)
60156873Sakito 	register struct siodevice *sio;
60254008Sfujita 	int c;
60354008Sfujita {
60454008Sfujita 	register u_char code;
60556873Sakito 	register int rr;
60656873Sakito 	int s;
60754008Sfujita 
60854008Sfujita 	s = splhigh();
60954008Sfujita 
61056873Sakito 	sioreg(sio, WR1, WR1_RXALLS);
61156873Sakito 
61254008Sfujita 	do {
61354008Sfujita 		DELAY(1);
61456873Sakito 		rr = siogetreg(sio);
61554008Sfujita 	} while (!(rr & RR_TXRDY));
61656873Sakito 
61756873Sakito 	code = (c & 0xFF);
61854008Sfujita 	sio->sio_data = code;
61954008Sfujita 
62054008Sfujita 	do {
62154008Sfujita 		DELAY(1);
62256873Sakito 		rr = siogetreg(sio);
62354008Sfujita 	} while (!(rr & RR_TXRDY));
62454008Sfujita 
62556873Sakito 	sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
62656873Sakito 
62754008Sfujita 	splx(s);
62854008Sfujita }
62954008Sfujita 
63056873Sakito /*
63156873Sakito  *  uPD7201A register operation
63256873Sakito  */
63354008Sfujita 
63454008Sfujita int
63556873Sakito siogetreg(sio)
63656873Sakito 	register struct siodevice *sio;
63754008Sfujita {
63854008Sfujita 	register int rr = 0;
63954008Sfujita 
64054008Sfujita 	rr = sio->sio_stat;
64154008Sfujita 	rr <<= 8;
64254008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
64354008Sfujita 	rr |= sio->sio_stat;
64454008Sfujita 
64554008Sfujita 	return(rr);
64654008Sfujita }
64754008Sfujita 
64854008Sfujita int
64956873Sakito sioreg(sio, reg, val)
65056873Sakito 	register struct siodevice *sio;
65154008Sfujita 	register int reg, val;
65254008Sfujita {
65354008Sfujita 	if (isStatusReg(reg)) {
65456873Sakito 		if (reg != 0)
65556873Sakito 		    sio->sio_cmd = reg;
65656873Sakito 		val = sio->sio_stat;
65754008Sfujita 	} else {
65856873Sakito 		if (reg != 0)
65956873Sakito 		    sio->sio_cmd = reg;
66056873Sakito 		sio->sio_cmd = val;
66154008Sfujita 	}
66256873Sakito 
66356873Sakito 	return(val);
66454008Sfujita }
66554008Sfujita #endif
666