xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 57291)
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*57291Sakito  *	@(#)sio.c	7.6 (Berkeley) 12/25/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();
40*57291Sakito 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 #define NPORT	2					/* uPD7201A has 2 serial-port */
5356873Sakito #define NLINE	1					/* number of active line */
5454008Sfujita 
5556873Sakito struct	sio_portc sio_portc[NPORT] = {
5656873Sakito 	{ -1, -1, (struct siodevice *) 0x51000000, (int (*)()) 0 },
5756873Sakito 	{ -1, -1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
5856873Sakito };
5954008Sfujita 
6056873Sakito struct	sio_softc sio_softc[NLINE];
6154008Sfujita 
6256873Sakito int	sio_init_done = 0;
6356873Sakito int	siounitbase = 0;				/* This counter is used unit number assignment */
6454008Sfujita 
6556873Sakito int	siosoftCAR;
6656873Sakito int	sio_active;
6757126Sakito int	sioconsole = -1;
6856873Sakito int	siodefaultrate = TTYDEF_SPEED;
69*57291Sakito int	siomajor = 12;
7054008Sfujita 
7156873Sakito struct	tty sio_tty[NLINE];
7254008Sfujita 
7356873Sakito struct speedtab siospeedtab[] = {
7456873Sakito 	2400,	WR4_BAUD24,
7556873Sakito 	4800,	WR4_BAUD48,
7656873Sakito 	9600,	WR4_BAUD96,
7754008Sfujita };
7854008Sfujita 
7956873Sakito #define	siounit(x)		minor(x)
8054008Sfujita 
8157126Sakito extern	struct tty *constty;
8254008Sfujita 
8354008Sfujita /*
8456873Sakito  *  probe routines
8554008Sfujita  */
8654008Sfujita 
8754008Sfujita sioprobe(hd)
8854008Sfujita 	register struct hp_device *hd;
8954008Sfujita {
9056873Sakito 	register int port;
9156873Sakito 	register struct sio_portc *pc;
9256873Sakito 	register struct sio_softc *sc;
9354008Sfujita 
9456873Sakito 	sioinit((struct siodevice *) hd->hp_addr, siodefaultrate);
9554008Sfujita 
9656873Sakito 	/* locate the major number */
9756873Sakito 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
9856873Sakito 		if (cdevsw[siomajor].d_open == sioopen)
9956873Sakito 			break;
10054008Sfujita 
10156873Sakito 	for (port = 0; port < NPORT; port++) {
10256873Sakito 		pc = &sio_portc[port];
10354008Sfujita 
10456873Sakito 		if (pc->pc_major != -1) {
10556873Sakito 			printf("%s%d: port %d, address 0x%x, intr 0x%x (console)\n",
10656873Sakito 			       (pc->pc_major == siomajor ? "sio" : "bmc" ),
10756873Sakito 			       pc->pc_unit, port, pc->pc_addr, pc->pc_intr);
10856873Sakito 			continue;
10956873Sakito 		}
11054008Sfujita 
11156873Sakito 		pc->pc_addr =
11256873Sakito 			(struct siodevice *)((u_long) hd->hp_addr + (sizeof(struct siodevice) * port));
11356873Sakito #if NBMC > 0
11456873Sakito 		if (bmcinit(port))
11556873Sakito 			continue;
11656873Sakito #endif
11756873Sakito 		if (++siounitbase < NLINE) {
11856873Sakito 			pc->pc_major = siomajor;
11956873Sakito 			pc->pc_intr  = siointr;
12056873Sakito 			pc->pc_unit  = siounitbase;
12156873Sakito 			printf("sio%d: port %d, address 0x%x\n", pc->pc_unit, port, pc->pc_addr);
12254008Sfujita 
12356873Sakito 			sc = &sio_softc[pc->pc_unit];
12456873Sakito 			sc->sc_pc = pc;
12554008Sfujita 
12656873Sakito 			sio_active |= 1 << pc->pc_unit;
12756873Sakito 			siosoftCAR |= 1 << pc->pc_unit;
12856873Sakito 		}
12956873Sakito 	}
13056873Sakito }
13154008Sfujita 
13256873Sakito struct sio_portc *
13356873Sakito sio_port_assign(port, major, unit, intr)
13456873Sakito 	int	port, major, unit;
13556873Sakito 	int	(*intr)();
13656873Sakito {
137*57291Sakito 	register struct sio_portc *pc;
13854008Sfujita 
139*57291Sakito 	pc = &sio_portc[port];
140*57291Sakito 
141*57291Sakito /*
142*57291Sakito 	if ((pc->pc_major != -1) && (major != 2))
14356873Sakito 		return((struct sio_portc *) 0);
144*57291Sakito  */
14556873Sakito 	pc->pc_major = major;
14656873Sakito 	pc->pc_intr  = intr;
14756873Sakito 	pc->pc_unit  = unit;
14854008Sfujita 
14956873Sakito 	return(pc);
15054008Sfujita }
15154008Sfujita 
152*57291Sakito struct sio_portc *
153*57291Sakito sio_port_get(port)
154*57291Sakito 	int port;
155*57291Sakito {
156*57291Sakito 	register struct sio_portc *pc;
15756873Sakito 
158*57291Sakito 	pc = &sio_portc[port];
159*57291Sakito 
160*57291Sakito 	return(pc);
161*57291Sakito }
162*57291Sakito 
163*57291Sakito int
164*57291Sakito sio_port_info()
165*57291Sakito {
166*57291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
167*57291Sakito 		0, sio_portc[0].pc_major, sio_portc[0].pc_unit, sio_portc[0].pc_intr);
168*57291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
169*57291Sakito 		1, sio_portc[1].pc_major, sio_portc[1].pc_unit, sio_portc[1].pc_intr);
170*57291Sakito }
171*57291Sakito 
172*57291Sakito 
17356873Sakito /*
17456873Sakito  *  entry routines
17556873Sakito  */
17656873Sakito 
17754008Sfujita /* ARGSUSED */
17854008Sfujita #ifdef __STDC__
17954008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
18054008Sfujita #else
18154008Sfujita sioopen(dev, flag, mode, p)
18254008Sfujita 	dev_t dev;
18354008Sfujita 	int flag, mode;
18454008Sfujita 	struct proc *p;
18554008Sfujita #endif
18654008Sfujita {
18754008Sfujita 	register struct tty *tp;
18854008Sfujita 	register int unit;
18954008Sfujita 	int error = 0;
19054008Sfujita 
19154008Sfujita 	unit = siounit(dev);
19256873Sakito 	if (unit >= NLINE || (sio_active & (1 << unit)) == 0)
19354008Sfujita 		return (ENXIO);
19454008Sfujita 	tp = &sio_tty[unit];
19554008Sfujita 	tp->t_oproc = siostart;
19654008Sfujita 	tp->t_param = sioparam;
19754008Sfujita 	tp->t_dev = dev;
19854008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
19954008Sfujita 		tp->t_state |= TS_WOPEN;
20054008Sfujita 		ttychars(tp);
20154008Sfujita 		if (tp->t_ispeed == 0) {
20254008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
20354008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
20456873Sakito /*			tp->t_cflag = TTYDEF_CFLAG;		*/
20554008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
20654008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
20754008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
20854008Sfujita 		}
20954008Sfujita 		sioparam(tp, &tp->t_termios);
21054008Sfujita 		ttsetwater(tp);
21154008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
21254008Sfujita 		return (EBUSY);
21356873Sakito 	(void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
21456873Sakito 	if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
21556873Sakito 		tp->t_state |= TS_CARR_ON;
21654008Sfujita 	(void) spltty();
21754008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
21854008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
21954008Sfujita 		tp->t_state |= TS_WOPEN;
22054008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
22154008Sfujita 		    ttopen, 0))
22254008Sfujita 			break;
22354008Sfujita 	}
22454008Sfujita 	(void) spl0();
22554008Sfujita 	if (error == 0)
22654008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
22754008Sfujita 	return (error);
22854008Sfujita }
22956873Sakito 
23054008Sfujita /*ARGSUSED*/
23154008Sfujita sioclose(dev, flag, mode, p)
23254008Sfujita 	dev_t dev;
23354008Sfujita 	int flag, mode;
23454008Sfujita 	struct proc *p;
23554008Sfujita {
23654008Sfujita 	register struct tty *tp;
23754008Sfujita 	register int unit;
23854008Sfujita 
23954008Sfujita 	unit = siounit(dev);
24054008Sfujita 	tp = &sio_tty[unit];
24154008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
24256873Sakito 	(void) siomctl(dev, WR5_BREAK, DMBIS);
24356873Sakito 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
24456873Sakito 	    (tp->t_state&TS_ISOPEN) == 0)
24556873Sakito 		(void) siomctl(dev, 0, DMSET);
24654008Sfujita 	ttyclose(tp);
24754008Sfujita 	return (0);
24854008Sfujita }
24954008Sfujita 
25054008Sfujita sioread(dev, uio, flag)
25154008Sfujita 	dev_t dev;
25254008Sfujita 	struct uio *uio;
25354008Sfujita {
25454008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
25554008Sfujita 
25654008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
25754008Sfujita }
25854008Sfujita 
25954008Sfujita siowrite(dev, uio, flag)
26054008Sfujita 	dev_t dev;
26154008Sfujita 	struct uio *uio;
26254008Sfujita {
26357126Sakito 	register int unit = siounit(dev);
26457126Sakito 	register struct tty *tp = &sio_tty[unit];
26554008Sfujita 
26657126Sakito 	if ((unit == sioconsole) && constty &&
26757126Sakito 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
26857126Sakito 		tp = constty;
26957126Sakito 
27054008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
27154008Sfujita }
27254008Sfujita 
27356873Sakito /*
27456873Sakito  * Stop output on a line.
27556873Sakito  */
27656873Sakito /*ARGSUSED*/
27756873Sakito siostop(tp, flag)
27856873Sakito 	register struct tty *tp;
27954008Sfujita {
28056873Sakito 	register int s;
28154008Sfujita 
28256873Sakito 	s = spltty();
28356873Sakito 	if (tp->t_state & TS_BUSY) {
28456873Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
28556873Sakito 			tp->t_state |= TS_FLUSH;
28654008Sfujita 	}
28756873Sakito 	splx(s);
28854008Sfujita }
28954008Sfujita 
29054008Sfujita sioioctl(dev, cmd, data, flag, p)
29154008Sfujita 	dev_t dev;
29254008Sfujita 	int cmd;
29354008Sfujita 	caddr_t data;
29454008Sfujita 	int flag;
29554008Sfujita 	struct proc *p;
29654008Sfujita {
29754008Sfujita 	register struct tty *tp;
29854008Sfujita 	register int unit = siounit(dev);
29954008Sfujita 	register int error;
30056873Sakito 
30154008Sfujita 	tp = &sio_tty[unit];
30254008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
30354008Sfujita 	if (error >= 0)
30454008Sfujita 		return (error);
30554008Sfujita 	error = ttioctl(tp, cmd, data, flag);
30654008Sfujita 	if (error >= 0)
30754008Sfujita 		return (error);
30854008Sfujita 
30954008Sfujita 	switch (cmd) {
31054008Sfujita 
31154008Sfujita 	case TIOCSBRK:
31256873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIS);
31356873Sakito 		break;
31456873Sakito 
31554008Sfujita 	case TIOCCBRK:
31656873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIC);
31756873Sakito 		break;
31856873Sakito 
31954008Sfujita 	case TIOCSDTR:
32056873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
32156873Sakito 		break;
32256873Sakito 
32354008Sfujita 	case TIOCCDTR:
32456873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
32556873Sakito 		break;
32656873Sakito 
32754008Sfujita 	case TIOCMSET:
32856873Sakito 		(void) siomctl(dev, *(int *)data, DMSET);
32956873Sakito 		break;
33056873Sakito 
33154008Sfujita 	case TIOCMBIS:
33256873Sakito 		(void) siomctl(dev, *(int *)data, DMBIS);
33356873Sakito 		break;
33456873Sakito 
33554008Sfujita 	case TIOCMBIC:
33656873Sakito 		(void) siomctl(dev, *(int *)data, DMBIC);
33756873Sakito 		break;
33856873Sakito 
33954008Sfujita 	case TIOCMGET:
34056873Sakito 		*(int *)data = siomctl(dev, 0, DMGET);
34156873Sakito 		break;
34256873Sakito 
34354008Sfujita 	default:
34454008Sfujita 		return (ENOTTY);
34554008Sfujita 	}
34654008Sfujita 	return (0);
34754008Sfujita }
34854008Sfujita 
34954008Sfujita 
35056873Sakito /*
35156873Sakito  *
35256873Sakito  */
35356873Sakito 
35454008Sfujita void
35554008Sfujita siostart(tp)
35654008Sfujita 	register struct tty *tp;
35754008Sfujita {
35854008Sfujita 	register struct siodevice *sio;
35956873Sakito 	register int rr;
36056873Sakito 	int s, unit, c;
36154008Sfujita 
36254008Sfujita 	unit = siounit(tp->t_dev);
36356873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
36454008Sfujita 	s = spltty();
36554008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
36654008Sfujita 		goto out;
36754008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
36854008Sfujita 		if (tp->t_state&TS_ASLEEP) {
36954008Sfujita 			tp->t_state &= ~TS_ASLEEP;
37054008Sfujita 			wakeup((caddr_t)&tp->t_outq);
37154008Sfujita 		}
37254008Sfujita 		selwakeup(&tp->t_wsel);
37354008Sfujita 	}
37454008Sfujita 	if (tp->t_outq.c_cc == 0)
37554008Sfujita 		goto out;
37656873Sakito 	rr = siogetreg(sio);
37754008Sfujita 	if (rr & RR_TXRDY) {
37854008Sfujita 		c = getc(&tp->t_outq);
37954008Sfujita 		tp->t_state |= TS_BUSY;
38054008Sfujita 		sio->sio_data = c;
38154008Sfujita 	}
38254008Sfujita out:
38354008Sfujita 	splx(s);
38454008Sfujita }
38556873Sakito 
38656873Sakito sioparam(tp, t)
38756873Sakito 	register struct tty *tp;
38856873Sakito 	register struct termios *t;
38956873Sakito {
39056873Sakito 	int unit = siounit(tp->t_dev);
39156873Sakito 	register struct siodevice *sio;
39256873Sakito 	register cflag = t->c_cflag;
39356873Sakito 	register u_char wr;
39456873Sakito 	int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
39556873Sakito 
39656873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
39756873Sakito 
39856873Sakito 	switch (cflag & CSIZE) {
39956873Sakito 	case CS5:
40056873Sakito 	case CS6:
40156873Sakito 	case CS7:
40256873Sakito 	case CS8:
40356873Sakito 		break;
40456873Sakito 	}
40556873Sakito 
40656873Sakito 	wr = ospeed;
40756873Sakito 
40856873Sakito 	if (cflag & PARENB) {
40956873Sakito 		wr |= WR4_PARENAB;
41056873Sakito 		if ((cflag&PARODD) == 0)
41156873Sakito 			wr |= WR4_EPARITY;
41256873Sakito 	}
41356873Sakito 
41456873Sakito 	if (cflag & CSTOPB)
41556873Sakito 		wr |= WR4_STOP2;			/* 2 stop bit */
41656873Sakito 	else
41756873Sakito 		wr |= WR4_STOP1;			/* 1 stop bit */
41856873Sakito 
41956873Sakito 	(void) sioreg(sio, WR4, wr);
42056873Sakito 
42156873Sakito 	return (0);
42256873Sakito }
42356873Sakito 
42456873Sakito siomctl()
42556873Sakito {
42656873Sakito 	return (0);
42756873Sakito }
42856873Sakito 
42956873Sakito 
43054008Sfujita /*
43156873Sakito  *  Interrupt handling
43254008Sfujita  */
43356873Sakito 
43456873Sakito void
43556873Sakito _siointr()
43654008Sfujita {
43756873Sakito 	register int port;
43856873Sakito 	register struct sio_portc *pc;
43954008Sfujita 
44056873Sakito 	for (port = 0; port < NPORT; port++) {
44156873Sakito 		pc = &sio_portc[port];
44256873Sakito 
44356873Sakito 		if (pc->pc_major != -1)
44456873Sakito 			(pc->pc_intr)(pc->pc_unit);
44554008Sfujita 	}
44654008Sfujita }
44754008Sfujita 
44856873Sakito siointr(unit)
44956873Sakito 	register int unit;
45056873Sakito {
45156873Sakito 	register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
45256873Sakito 	register u_char code;
45356873Sakito 	register struct tty *tp;
45456873Sakito 	int s, rr;
45556873Sakito 
45656873Sakito 	tp = &sio_tty[unit];
45756873Sakito 	rr = siogetreg(sio);
45856873Sakito 
45956873Sakito 	if (rr & RR_RXRDY) {
46056873Sakito 		code = sio->sio_data;
46156873Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
46256873Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
46356873Sakito 	}
46456873Sakito 
46556873Sakito 	if (rr & RR_TXRDY) {
46656873Sakito 		sio->sio_cmd = WR0_RSTPEND;
46756873Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
46856873Sakito 		if (tp->t_line)
46956873Sakito 			(*linesw[tp->t_line].l_start)(tp);
47056873Sakito 		else
47156873Sakito 			siostart(tp);
47256873Sakito 	}
47356873Sakito }
47456873Sakito 
47554008Sfujita /*
47654008Sfujita  * Following are all routines needed for SIO to act as console
47754008Sfujita  */
47857058Sakito #include <luna68k/luna68k/cons.h>
47954008Sfujita 
48054008Sfujita siocnprobe(cp)
48156873Sakito 	register struct consdev *cp;
48254008Sfujita {
48356873Sakito 	register int unit = 0;
48454008Sfujita 
48554008Sfujita 	/* locate the major number */
48654008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
48754008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
48854008Sfujita 			break;
48954008Sfujita 
49056873Sakito 	siounitbase = -1;
49154008Sfujita 
49254008Sfujita 	/* initialize required fields */
49354008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
49456873Sakito 	cp->cn_tp  = &sio_tty[unit];
49554008Sfujita 	cp->cn_pri = CN_NORMAL;
49654008Sfujita }
49754008Sfujita 
49854008Sfujita siocninit(cp)
49954008Sfujita 	struct consdev *cp;
50054008Sfujita {
50154008Sfujita 	int unit = siounit(cp->cn_dev);
50256873Sakito 	register struct sio_softc *sc = &sio_softc[unit];
50354008Sfujita 
50456873Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
50556873Sakito 
50656873Sakito 	/* port assign */
50756873Sakito 	sc->sc_pc = sio_port_assign(0, siomajor, unit, siointr);
50856873Sakito 
50954008Sfujita 	sioconsole = unit;
51056873Sakito 	siounitbase = 0;
51156873Sakito 
51256873Sakito 	sio_active |= 1 << unit;
51356873Sakito 	siosoftCAR |= 1 << unit;
51454008Sfujita }
51554008Sfujita 
51654008Sfujita siocngetc(dev)
51754008Sfujita 	dev_t dev;
51854008Sfujita {
51956873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
52056873Sakito 	struct sio_portc *pc = sc->sc_pc;
52154008Sfujita 
52256873Sakito 	return(sio_imgetc(pc->pc_addr));
52354008Sfujita }
52454008Sfujita 
52554008Sfujita siocnputc(dev, c)
52654008Sfujita 	dev_t dev;
52754008Sfujita 	int c;
52854008Sfujita {
52956873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
53056873Sakito 	struct sio_portc *pc = sc->sc_pc;
53154008Sfujita 
53256873Sakito 	sio_imputc(pc->pc_addr, c);
53356873Sakito }
53454008Sfujita 
53554008Sfujita 
53656873Sakito /*
53756873Sakito  *  sio raw-level routines
53856873Sakito  */
53954008Sfujita 
54056873Sakito sioinit(sio0, rate)
54156873Sakito 	register struct siodevice *sio0;
54256873Sakito 	register int rate;
54356873Sakito {
54456873Sakito 	register struct siodevice *sio1;
54556873Sakito 	int s;
54654008Sfujita 
54756873Sakito 	rate = ttspeedtab(rate, siospeedtab);
54854008Sfujita 
54956873Sakito 	if (sio_init_done)
55056873Sakito 		return;
55154008Sfujita 
55256873Sakito 	sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
55354008Sfujita 
55454008Sfujita 	s = splhigh();
55554008Sfujita 
55656873Sakito 	sioreg(sio0, WR0,  WR0_CHANRST);		/* Channel-A Reset */
55754008Sfujita 
55856873Sakito 	sioreg(sio0, WR2, (WR2_VEC86  | WR2_INTR_1));	/* Set CPU BUS Interface Mode */
55956873Sakito 	sioreg(sio1, WR2,  0);				/* Set Interrupt Vector */
56054008Sfujita 
56156873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
56256873Sakito 	sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
56356873Sakito 	sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
56456873Sakito 	sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
56556873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
56656873Sakito 	sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
56754008Sfujita 
56856873Sakito 	sioreg(sio1, WR0,  WR0_CHANRST);		/* Channel-B Reset */
56954008Sfujita 
57056873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
57156873Sakito 	sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
57256873Sakito 	sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
57356873Sakito 	sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
57456873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
57556873Sakito 	sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
57656873Sakito 
57754008Sfujita 	splx(s);
57856873Sakito 
57956873Sakito 	sio_init_done = 1;
58054008Sfujita }
58154008Sfujita 
58256873Sakito sio_imgetc(sio)
58356873Sakito 	register struct siodevice *sio;
58454008Sfujita {
58556873Sakito 	register int rr0, rr1;
58656873Sakito 	int c, s;
58754008Sfujita 
58856873Sakito 	s = splhigh();
58956873Sakito 	while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
59056873Sakito 		;
59156873Sakito 	c = sio->sio_data;
59256873Sakito 	sioreg(sio, WR0, WR0_RSTPEND);
59356873Sakito 	splx(s);
59456873Sakito 	return (c);
59554008Sfujita }
59654008Sfujita 
59756873Sakito sio_imputc(sio, c)
59856873Sakito 	register struct siodevice *sio;
59954008Sfujita 	int c;
60054008Sfujita {
60154008Sfujita 	register u_char code;
60256873Sakito 	register int rr;
60356873Sakito 	int s;
60454008Sfujita 
60554008Sfujita 	s = splhigh();
60654008Sfujita 
60756873Sakito 	sioreg(sio, WR1, WR1_RXALLS);
60856873Sakito 
60954008Sfujita 	do {
61054008Sfujita 		DELAY(1);
61156873Sakito 		rr = siogetreg(sio);
61254008Sfujita 	} while (!(rr & RR_TXRDY));
61356873Sakito 
61456873Sakito 	code = (c & 0xFF);
61554008Sfujita 	sio->sio_data = code;
61654008Sfujita 
61754008Sfujita 	do {
61854008Sfujita 		DELAY(1);
61956873Sakito 		rr = siogetreg(sio);
62054008Sfujita 	} while (!(rr & RR_TXRDY));
62154008Sfujita 
62256873Sakito 	sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
62356873Sakito 
62454008Sfujita 	splx(s);
62554008Sfujita }
62654008Sfujita 
62756873Sakito /*
62856873Sakito  *  uPD7201A register operation
62956873Sakito  */
63054008Sfujita 
63154008Sfujita int
63256873Sakito siogetreg(sio)
63356873Sakito 	register struct siodevice *sio;
63454008Sfujita {
63554008Sfujita 	register int rr = 0;
63654008Sfujita 
63754008Sfujita 	rr = sio->sio_stat;
63854008Sfujita 	rr <<= 8;
63954008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
64054008Sfujita 	rr |= sio->sio_stat;
64154008Sfujita 
64254008Sfujita 	return(rr);
64354008Sfujita }
64454008Sfujita 
64554008Sfujita int
64656873Sakito sioreg(sio, reg, val)
64756873Sakito 	register struct siodevice *sio;
64854008Sfujita 	register int reg, val;
64954008Sfujita {
65054008Sfujita 	if (isStatusReg(reg)) {
65156873Sakito 		if (reg != 0)
65256873Sakito 		    sio->sio_cmd = reg;
65356873Sakito 		val = sio->sio_stat;
65454008Sfujita 	} else {
65556873Sakito 		if (reg != 0)
65656873Sakito 		    sio->sio_cmd = reg;
65756873Sakito 		sio->sio_cmd = val;
65854008Sfujita 	}
65956873Sakito 
66056873Sakito 	return(val);
66154008Sfujita }
66254008Sfujita #endif
663