xref: /csrg-svn/sys/luna68k/dev/sio.c (revision 63192)
154008Sfujita /*
254008Sfujita  * Copyright (c) 1992 OMRON Corporation.
3*63192Sbostic  * Copyright (c) 1992, 1993
4*63192Sbostic  *	The Regents of the University of California.  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*63192Sbostic  *	@(#)sio.c	8.1 (Berkeley) 06/10/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] = {
5359648Sakito 	{ -1, -1, 0, (struct siodevice *) 0x51000000, (int (*)()) 0 },
5459648Sakito 	{ -1, -1, 1, (struct siodevice *) 0x51000004, (int (*)()) 0 }
5556873Sakito };
5654008Sfujita 
5759648Sakito 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 
6759648Sakito 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 
7962579Sakito #ifdef KGDB
8054008Sfujita /*
8162579Sakito  * Kernel GDB support
8262579Sakito  */
8362579Sakito #include <machine/remote-sl.h>
8462579Sakito 
8562579Sakito extern dev_t kgdb_dev;
8662579Sakito extern int kgdb_rate;
8762579Sakito extern int kgdb_debug_init;
8862579Sakito #endif
8962579Sakito 
9062579Sakito /*
9156873Sakito  *  probe routines
9254008Sfujita  */
9354008Sfujita 
sioprobe(hd)9454008Sfujita sioprobe(hd)
9554008Sfujita 	register struct hp_device *hd;
9654008Sfujita {
9759648Sakito 	int unit = hd->hp_unit;
9859648Sakito 	register struct sio_softc *sc = &sio_softc[unit];
9956873Sakito 	register struct sio_portc *pc;
10054008Sfujita 
10159648Sakito 	if (sc->sc_pc != 0) {
10259648Sakito 		pc = sc->sc_pc;
10359648Sakito 		printf("sio%d: port %d, address 0x%x, intr 0x%x (console)\n",
10459648Sakito 		       pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
10562579Sakito 		return(1);
10659648Sakito 	}
10754008Sfujita 
10862579Sakito 	sc->sc_pc = pc = sio_port_assign(unit, siomajor, unit, siointr);
10954008Sfujita 
11059648Sakito 	printf("sio%d: port %d, address 0x%x, intr 0x%x\n",
11159648Sakito 	       pc->pc_unit, pc->pc_port, pc->pc_addr, pc->pc_intr);
11254008Sfujita 
11359648Sakito 	sio_active |= 1 << unit;
11462579Sakito 
11562579Sakito #ifdef KGDB
11662579Sakito 	if (major(kgdb_dev) == siomajor) {
11762579Sakito #ifdef	notdef
11862579Sakito 		if (sioconsole == siounit(kgdb_dev)) {
11962579Sakito 			kgdb_dev = NODEV; /* can't debug over console port */
12062579Sakito 		} else {
12162579Sakito #endif
12262579Sakito 		/*
12362579Sakito 		 * The following could potentially be replaced
12462579Sakito 		 * by the corresponding code in dcmcnprobe.
12562579Sakito 		 */
12662579Sakito 			if (kgdb_debug_init) {
12762579Sakito 				printf("sio%d: ", siounit(kgdb_dev));
12862579Sakito 				kgdb_connect(1);
12962579Sakito 			} else
13062579Sakito 				printf("sio%d: kgdb enabled\n", siounit(kgdb_dev));
13162579Sakito #ifdef	notdef
13262579Sakito 		}
13362579Sakito #endif
13462579Sakito 		/* end could be replaced */
13562579Sakito 	}
13662579Sakito #endif
13762579Sakito 
13859648Sakito 	siosoftCAR |= 1 << unit;
13959648Sakito 	return(1);
14056873Sakito }
14154008Sfujita 
14256873Sakito struct sio_portc *
sio_port_assign(port,major,unit,intr)14356873Sakito sio_port_assign(port, major, unit, intr)
14456873Sakito 	int	port, major, unit;
14556873Sakito 	int	(*intr)();
14656873Sakito {
14757291Sakito 	register struct sio_portc *pc;
14854008Sfujita 
14957291Sakito 	pc = &sio_portc[port];
15057291Sakito 
15156873Sakito 	pc->pc_major = major;
15256873Sakito 	pc->pc_intr  = intr;
15356873Sakito 	pc->pc_unit  = unit;
15454008Sfujita 
15556873Sakito 	return(pc);
15654008Sfujita }
15754008Sfujita 
15857291Sakito struct sio_portc *
sio_port_get(port)15957291Sakito sio_port_get(port)
16057291Sakito 	int port;
16157291Sakito {
16257291Sakito 	register struct sio_portc *pc;
16356873Sakito 
16457291Sakito 	pc = &sio_portc[port];
16557291Sakito 
16657291Sakito 	return(pc);
16757291Sakito }
16857291Sakito 
16957291Sakito int
sio_port_info()17057291Sakito sio_port_info()
17157291Sakito {
17257291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
17357291Sakito 		0, sio_portc[0].pc_major, sio_portc[0].pc_unit, sio_portc[0].pc_intr);
17457291Sakito 	printf("sio_port_info[sio.c]:\t{%d}       major = %d, unit = %d, intr = 0x%x\n",
17557291Sakito 		1, sio_portc[1].pc_major, sio_portc[1].pc_unit, sio_portc[1].pc_intr);
17657291Sakito }
17757291Sakito 
17857291Sakito 
17956873Sakito /*
18056873Sakito  *  entry routines
18156873Sakito  */
18256873Sakito 
18354008Sfujita /* ARGSUSED */
18454008Sfujita #ifdef __STDC__
sioopen(dev_t dev,int flag,int mode,struct proc * p)18554008Sfujita sioopen(dev_t dev, int flag, int mode, struct proc *p)
18654008Sfujita #else
18754008Sfujita sioopen(dev, flag, mode, p)
18854008Sfujita 	dev_t dev;
18954008Sfujita 	int flag, mode;
19054008Sfujita 	struct proc *p;
19154008Sfujita #endif
19254008Sfujita {
19354008Sfujita 	register struct tty *tp;
19454008Sfujita 	register int unit;
19554008Sfujita 	int error = 0;
19654008Sfujita 
19754008Sfujita 	unit = siounit(dev);
19859648Sakito 	if (unit >= NSIO || (sio_active & (1 << unit)) == 0)
19954008Sfujita 		return (ENXIO);
20054008Sfujita 	tp = &sio_tty[unit];
20154008Sfujita 	tp->t_oproc = siostart;
20254008Sfujita 	tp->t_param = sioparam;
20354008Sfujita 	tp->t_dev = dev;
20454008Sfujita 	if ((tp->t_state & TS_ISOPEN) == 0) {
20554008Sfujita 		tp->t_state |= TS_WOPEN;
20654008Sfujita 		ttychars(tp);
20754008Sfujita 		if (tp->t_ispeed == 0) {
20854008Sfujita 			tp->t_iflag = TTYDEF_IFLAG;
20954008Sfujita 			tp->t_oflag = TTYDEF_OFLAG;
21056873Sakito /*			tp->t_cflag = TTYDEF_CFLAG;		*/
21154008Sfujita 			tp->t_cflag = (CREAD | CS8 | HUPCL);
21254008Sfujita 			tp->t_lflag = TTYDEF_LFLAG;
21354008Sfujita 			tp->t_ispeed = tp->t_ospeed = siodefaultrate;
21454008Sfujita 		}
21554008Sfujita 		sioparam(tp, &tp->t_termios);
21654008Sfujita 		ttsetwater(tp);
21754008Sfujita 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
21854008Sfujita 		return (EBUSY);
21956873Sakito 	(void) siomctl(dev, WR5_DTR | WR5_RTS, DMSET);
22056873Sakito 	if ((siosoftCAR & (1 << unit)) || (siomctl(dev, 0, DMGET) & RR0_DCD))
22156873Sakito 		tp->t_state |= TS_CARR_ON;
22254008Sfujita 	(void) spltty();
22354008Sfujita 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
22454008Sfujita 	       (tp->t_state & TS_CARR_ON) == 0) {
22554008Sfujita 		tp->t_state |= TS_WOPEN;
22654008Sfujita 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
22754008Sfujita 		    ttopen, 0))
22854008Sfujita 			break;
22954008Sfujita 	}
23054008Sfujita 	(void) spl0();
23154008Sfujita 	if (error == 0)
23254008Sfujita 		error = (*linesw[tp->t_line].l_open)(dev, tp);
23354008Sfujita 	return (error);
23454008Sfujita }
23556873Sakito 
23654008Sfujita /*ARGSUSED*/
sioclose(dev,flag,mode,p)23754008Sfujita sioclose(dev, flag, mode, p)
23854008Sfujita 	dev_t dev;
23954008Sfujita 	int flag, mode;
24054008Sfujita 	struct proc *p;
24154008Sfujita {
24254008Sfujita 	register struct tty *tp;
24354008Sfujita 	register int unit;
24454008Sfujita 
24554008Sfujita 	unit = siounit(dev);
24654008Sfujita 	tp = &sio_tty[unit];
24754008Sfujita 	(*linesw[tp->t_line].l_close)(tp, flag);
24856873Sakito 	(void) siomctl(dev, WR5_BREAK, DMBIS);
24956873Sakito 	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
25056873Sakito 	    (tp->t_state&TS_ISOPEN) == 0)
25156873Sakito 		(void) siomctl(dev, 0, DMSET);
25254008Sfujita 	ttyclose(tp);
25354008Sfujita 	return (0);
25454008Sfujita }
25554008Sfujita 
sioread(dev,uio,flag)25654008Sfujita sioread(dev, uio, flag)
25754008Sfujita 	dev_t dev;
25854008Sfujita 	struct uio *uio;
25954008Sfujita {
26054008Sfujita 	register struct tty *tp = &sio_tty[siounit(dev)];
26154008Sfujita 
26254008Sfujita 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
26354008Sfujita }
26454008Sfujita 
siowrite(dev,uio,flag)26554008Sfujita siowrite(dev, uio, flag)
26654008Sfujita 	dev_t dev;
26754008Sfujita 	struct uio *uio;
26854008Sfujita {
26957126Sakito 	register int unit = siounit(dev);
27057126Sakito 	register struct tty *tp = &sio_tty[unit];
27154008Sfujita 
27257126Sakito 	if ((unit == sioconsole) && constty &&
27357126Sakito 	    (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN))
27457126Sakito 		tp = constty;
27557126Sakito 
27654008Sfujita 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
27754008Sfujita }
27854008Sfujita 
27956873Sakito /*
28056873Sakito  * Stop output on a line.
28156873Sakito  */
28256873Sakito /*ARGSUSED*/
siostop(tp,flag)28356873Sakito siostop(tp, flag)
28456873Sakito 	register struct tty *tp;
28554008Sfujita {
28656873Sakito 	register int s;
28754008Sfujita 
28856873Sakito 	s = spltty();
28956873Sakito 	if (tp->t_state & TS_BUSY) {
29056873Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
29156873Sakito 			tp->t_state |= TS_FLUSH;
29254008Sfujita 	}
29356873Sakito 	splx(s);
29454008Sfujita }
29554008Sfujita 
sioioctl(dev,cmd,data,flag,p)29654008Sfujita sioioctl(dev, cmd, data, flag, p)
29754008Sfujita 	dev_t dev;
29854008Sfujita 	int cmd;
29954008Sfujita 	caddr_t data;
30054008Sfujita 	int flag;
30154008Sfujita 	struct proc *p;
30254008Sfujita {
30354008Sfujita 	register struct tty *tp;
30454008Sfujita 	register int unit = siounit(dev);
30554008Sfujita 	register int error;
30656873Sakito 
30754008Sfujita 	tp = &sio_tty[unit];
30854008Sfujita 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
30954008Sfujita 	if (error >= 0)
31054008Sfujita 		return (error);
31154008Sfujita 	error = ttioctl(tp, cmd, data, flag);
31254008Sfujita 	if (error >= 0)
31354008Sfujita 		return (error);
31454008Sfujita 
31554008Sfujita 	switch (cmd) {
31654008Sfujita 
31754008Sfujita 	case TIOCSBRK:
31856873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIS);
31956873Sakito 		break;
32056873Sakito 
32154008Sfujita 	case TIOCCBRK:
32256873Sakito 		(void) siomctl(dev, WR5_BREAK, DMBIC);
32356873Sakito 		break;
32456873Sakito 
32554008Sfujita 	case TIOCSDTR:
32656873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIS);
32756873Sakito 		break;
32856873Sakito 
32954008Sfujita 	case TIOCCDTR:
33056873Sakito 		(void) siomctl(dev, WR5_DTR | WR5_RTS, DMBIC);
33156873Sakito 		break;
33256873Sakito 
33354008Sfujita 	case TIOCMSET:
33456873Sakito 		(void) siomctl(dev, *(int *)data, DMSET);
33556873Sakito 		break;
33656873Sakito 
33754008Sfujita 	case TIOCMBIS:
33856873Sakito 		(void) siomctl(dev, *(int *)data, DMBIS);
33956873Sakito 		break;
34056873Sakito 
34154008Sfujita 	case TIOCMBIC:
34256873Sakito 		(void) siomctl(dev, *(int *)data, DMBIC);
34356873Sakito 		break;
34456873Sakito 
34554008Sfujita 	case TIOCMGET:
34656873Sakito 		*(int *)data = siomctl(dev, 0, DMGET);
34756873Sakito 		break;
34856873Sakito 
34954008Sfujita 	default:
35054008Sfujita 		return (ENOTTY);
35154008Sfujita 	}
35254008Sfujita 	return (0);
35354008Sfujita }
35454008Sfujita 
35554008Sfujita 
35656873Sakito /*
35756873Sakito  *
35856873Sakito  */
35956873Sakito 
36054008Sfujita void
siostart(tp)36154008Sfujita siostart(tp)
36254008Sfujita 	register struct tty *tp;
36354008Sfujita {
36454008Sfujita 	register struct siodevice *sio;
36556873Sakito 	register int rr;
36656873Sakito 	int s, unit, c;
36754008Sfujita 
36854008Sfujita 	unit = siounit(tp->t_dev);
36956873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
37054008Sfujita 	s = spltty();
37154008Sfujita 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
37254008Sfujita 		goto out;
37354008Sfujita 	if (tp->t_outq.c_cc <= tp->t_lowat) {
37454008Sfujita 		if (tp->t_state&TS_ASLEEP) {
37554008Sfujita 			tp->t_state &= ~TS_ASLEEP;
37654008Sfujita 			wakeup((caddr_t)&tp->t_outq);
37754008Sfujita 		}
37854008Sfujita 		selwakeup(&tp->t_wsel);
37954008Sfujita 	}
38054008Sfujita 	if (tp->t_outq.c_cc == 0)
38154008Sfujita 		goto out;
38256873Sakito 	rr = siogetreg(sio);
38354008Sfujita 	if (rr & RR_TXRDY) {
38454008Sfujita 		c = getc(&tp->t_outq);
38554008Sfujita 		tp->t_state |= TS_BUSY;
38654008Sfujita 		sio->sio_data = c;
38754008Sfujita 	}
38854008Sfujita out:
38954008Sfujita 	splx(s);
39054008Sfujita }
39156873Sakito 
sioparam(tp,t)39256873Sakito sioparam(tp, t)
39356873Sakito 	register struct tty *tp;
39456873Sakito 	register struct termios *t;
39556873Sakito {
39656873Sakito 	int unit = siounit(tp->t_dev);
39756873Sakito 	register struct siodevice *sio;
39856873Sakito 	register cflag = t->c_cflag;
39956873Sakito 	register u_char wr;
40056873Sakito 	int ospeed = ttspeedtab(t->c_ospeed, siospeedtab);
40156873Sakito 
40256873Sakito 	sio = sio_softc[unit].sc_pc->pc_addr;
40356873Sakito 
40456873Sakito 	switch (cflag & CSIZE) {
40556873Sakito 	case CS5:
40656873Sakito 	case CS6:
40756873Sakito 	case CS7:
40856873Sakito 	case CS8:
40956873Sakito 		break;
41056873Sakito 	}
41156873Sakito 
41256873Sakito 	wr = ospeed;
41356873Sakito 
41456873Sakito 	if (cflag & PARENB) {
41556873Sakito 		wr |= WR4_PARENAB;
41656873Sakito 		if ((cflag&PARODD) == 0)
41756873Sakito 			wr |= WR4_EPARITY;
41856873Sakito 	}
41956873Sakito 
42056873Sakito 	if (cflag & CSTOPB)
42156873Sakito 		wr |= WR4_STOP2;			/* 2 stop bit */
42256873Sakito 	else
42356873Sakito 		wr |= WR4_STOP1;			/* 1 stop bit */
42456873Sakito 
42556873Sakito 	(void) sioreg(sio, WR4, wr);
42656873Sakito 
42756873Sakito 	return (0);
42856873Sakito }
42956873Sakito 
siomctl()43056873Sakito siomctl()
43156873Sakito {
43256873Sakito 	return (0);
43356873Sakito }
43456873Sakito 
43556873Sakito 
43654008Sfujita /*
43756873Sakito  *  Interrupt handling
43854008Sfujita  */
43956873Sakito 
44056873Sakito void
_siointr()44156873Sakito _siointr()
44254008Sfujita {
44356873Sakito 	register int port;
44456873Sakito 	register struct sio_portc *pc;
44554008Sfujita 
44656873Sakito 	for (port = 0; port < NPORT; port++) {
44756873Sakito 		pc = &sio_portc[port];
44856873Sakito 
44956873Sakito 		if (pc->pc_major != -1)
45056873Sakito 			(pc->pc_intr)(pc->pc_unit);
45154008Sfujita 	}
45254008Sfujita }
45354008Sfujita 
siointr(unit)45456873Sakito siointr(unit)
45556873Sakito 	register int unit;
45656873Sakito {
45756873Sakito 	register struct siodevice *sio = sio_softc[unit].sc_pc->pc_addr;
45856873Sakito 	register u_char code;
45956873Sakito 	register struct tty *tp;
46056873Sakito 	int s, rr;
46156873Sakito 
46256873Sakito 	tp = &sio_tty[unit];
46357850Sakito 
46457850Sakito start:
46556873Sakito 	rr = siogetreg(sio);
46657850Sakito 	if (rr & RR_RXRDY) {
46757850Sakito 		if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
46857850Sakito 			sioeint(unit, rr, sio);
46957850Sakito 			goto start;
47057850Sakito 		}
47156873Sakito 
47256873Sakito 		code = sio->sio_data;
47356873Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
47456873Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
47562579Sakito #ifdef KGDB
47662579Sakito 		else {
47762579Sakito 			if (code == FRAME_END &&
47862579Sakito 			    kgdb_dev == makedev(siomajor, unit))
47962579Sakito 				kgdb_connect(0); /* trap into kgdb */
48062579Sakito 		}
48162579Sakito #endif
48257850Sakito 		while ((rr = siogetreg(sio)) & RR_RXRDY) {
48357850Sakito 			code = sio->sio_data;
48457850Sakito 			if ((tp->t_state & TS_ISOPEN) != 0)
48557850Sakito 				(*linesw[tp->t_line].l_rint)(code, tp);
48662579Sakito #ifdef KGDB
48762579Sakito 			else {
48862579Sakito 				if (code == FRAME_END &&
48962579Sakito 				    kgdb_dev == makedev(siomajor, unit))
49062579Sakito 					kgdb_connect(0); /* trap into kgdb */
49162579Sakito 			}
49262579Sakito #endif
49357850Sakito 		}
49456873Sakito 	}
49556873Sakito 
49656873Sakito 	if (rr & RR_TXRDY) {
49756873Sakito 		sio->sio_cmd = WR0_RSTPEND;
49856873Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
49956873Sakito 		if (tp->t_line)
50056873Sakito 			(*linesw[tp->t_line].l_start)(tp);
50156873Sakito 		else
50256873Sakito 			siostart(tp);
50356873Sakito 	}
50456873Sakito }
50556873Sakito 
sioeint(unit,stat,sio)50657850Sakito sioeint(unit, stat, sio)
50757850Sakito 	register int unit, stat;
50857850Sakito 	register struct siodevice *sio;
50957850Sakito {
51057850Sakito 	register struct tty *tp;
51157850Sakito 	register int code;
51257850Sakito 
51357850Sakito 	tp = &sio_tty[unit];
51457850Sakito 
51557850Sakito 	code = sio->sio_data;
51657850Sakito 
51757850Sakito 	sio->sio_cmd = WR0_ERRRST;
51857850Sakito 
51962579Sakito 	if ((tp->t_state & TS_ISOPEN) == 0) {
52062579Sakito #ifdef KGDB
52162579Sakito 		/* we don't care about parity errors */
52262579Sakito 		if (((stat & (RR_FRAMING|RR_PARITY)) == RR_PARITY) &&
52362579Sakito 		    kgdb_dev == makedev(siomajor, unit) && code == FRAME_END)
52462579Sakito 			kgdb_connect(0); /* trap into kgdb */
52562579Sakito #endif
52657850Sakito 		return;
52762579Sakito 	}
52857850Sakito 
52957850Sakito 	if (stat & RR_FRAMING)
53057850Sakito 		code |= TTY_FE;
53157850Sakito 	else if (stat & RR_PARITY)
53257850Sakito 		code |= TTY_PE;
53357850Sakito 
53457850Sakito 	(*linesw[tp->t_line].l_rint)(code, tp);
53557850Sakito }
53657850Sakito 
53754008Sfujita /*
53854008Sfujita  * Following are all routines needed for SIO to act as console
53954008Sfujita  */
54057058Sakito #include <luna68k/luna68k/cons.h>
54154008Sfujita 
siocnprobe(cp)54254008Sfujita siocnprobe(cp)
54356873Sakito 	register struct consdev *cp;
54454008Sfujita {
54556873Sakito 	register int unit = 0;
54654008Sfujita 
54754008Sfujita 	/* locate the major number */
54854008Sfujita 	for (siomajor = 0; siomajor < nchrdev; siomajor++)
54954008Sfujita 		if (cdevsw[siomajor].d_open == sioopen)
55054008Sfujita 			break;
55154008Sfujita 
55254008Sfujita 	/* initialize required fields */
55354008Sfujita 	cp->cn_dev = makedev(siomajor, unit);
55456873Sakito 	cp->cn_tp  = &sio_tty[unit];
55554008Sfujita 	cp->cn_pri = CN_NORMAL;
55654008Sfujita }
55754008Sfujita 
55854008Sfujita siocninit(cp)
55954008Sfujita 	struct consdev *cp;
56054008Sfujita {
56154008Sfujita 	int unit = siounit(cp->cn_dev);
56256873Sakito 	register struct sio_softc *sc = &sio_softc[unit];
56354008Sfujita 
56456873Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, siodefaultrate);
56556873Sakito 
56656873Sakito 	/* port assign */
56759648Sakito 	sc->sc_pc = sio_port_assign(SIO_PORT, siomajor, unit, siointr);
56856873Sakito 
56954008Sfujita 	sioconsole = unit;
57056873Sakito 	sio_active |= 1 << unit;
57156873Sakito 	siosoftCAR |= 1 << unit;
57254008Sfujita }
57354008Sfujita 
siocngetc(dev)57454008Sfujita siocngetc(dev)
57554008Sfujita 	dev_t dev;
57654008Sfujita {
57756873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
57856873Sakito 	struct sio_portc *pc = sc->sc_pc;
57954008Sfujita 
58056873Sakito 	return(sio_imgetc(pc->pc_addr));
58154008Sfujita }
58254008Sfujita 
siocnputc(dev,c)58354008Sfujita siocnputc(dev, c)
58454008Sfujita 	dev_t dev;
58554008Sfujita 	int c;
58654008Sfujita {
58756873Sakito 	struct sio_softc *sc = &sio_softc[siounit(dev)];
58856873Sakito 	struct sio_portc *pc = sc->sc_pc;
58954008Sfujita 
59056873Sakito 	sio_imputc(pc->pc_addr, c);
59156873Sakito }
59254008Sfujita 
59354008Sfujita 
59456873Sakito /*
59556873Sakito  *  sio raw-level routines
59656873Sakito  */
59754008Sfujita 
sioinit(sio0,rate)59856873Sakito sioinit(sio0, rate)
59956873Sakito 	register struct siodevice *sio0;
60056873Sakito 	register int rate;
60156873Sakito {
60256873Sakito 	register struct siodevice *sio1;
60356873Sakito 	int s;
60454008Sfujita 
60556873Sakito 	rate = ttspeedtab(rate, siospeedtab);
60654008Sfujita 
60756873Sakito 	if (sio_init_done)
60856873Sakito 		return;
60954008Sfujita 
61056873Sakito 	sio1 = (struct siodevice *) ((u_long) sio0 + sizeof(struct siodevice));
61154008Sfujita 
61254008Sfujita 	s = splhigh();
61354008Sfujita 
61456873Sakito 	sioreg(sio0, WR0,  WR0_CHANRST);		/* Channel-A Reset */
61554008Sfujita 
61656873Sakito 	sioreg(sio0, WR2, (WR2_VEC86  | WR2_INTR_1));	/* Set CPU BUS Interface Mode */
61756873Sakito 	sioreg(sio1, WR2,  0);				/* Set Interrupt Vector */
61854008Sfujita 
61956873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
62056873Sakito 	sioreg(sio0, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
62156873Sakito 	sioreg(sio0, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
62256873Sakito 	sioreg(sio0, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
62356873Sakito 	sioreg(sio0, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
62456873Sakito 	sioreg(sio0, WR1, (WR1_RXALLS | WR1_TXENBL));
62554008Sfujita 
62656873Sakito 	sioreg(sio1, WR0,  WR0_CHANRST);		/* Channel-B Reset */
62754008Sfujita 
62856873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
62956873Sakito 	sioreg(sio1, WR4, (rate | WR4_STOP1 | WR4_NPARITY));	/* Tx/Rx */
63056873Sakito 	sioreg(sio1, WR3, (WR3_RX8BIT | WR3_RXENBL));		/* Rx */
63156873Sakito 	sioreg(sio1, WR5, (WR5_TX8BIT | WR5_TXENBL));		/* Tx */
63256873Sakito 	sioreg(sio1, WR0,  WR0_RSTINT);		/* Reset E/S Interrupt */
63356873Sakito 	sioreg(sio1, WR1, (WR1_RXALLS | WR1_TXENBL));
63456873Sakito 
63554008Sfujita 	splx(s);
63656873Sakito 
63756873Sakito 	sio_init_done = 1;
63854008Sfujita }
63954008Sfujita 
sio_imgetc(sio)64056873Sakito sio_imgetc(sio)
64156873Sakito 	register struct siodevice *sio;
64254008Sfujita {
64356873Sakito 	register int rr0, rr1;
64456873Sakito 	int c, s;
64554008Sfujita 
64656873Sakito 	s = splhigh();
64756873Sakito 	while (((rr0 = sioreg(sio, RR0, 0)) & RR0_RXAVAIL) == 0)
64856873Sakito 		;
64956873Sakito 	c = sio->sio_data;
65056873Sakito 	sioreg(sio, WR0, WR0_RSTPEND);
65156873Sakito 	splx(s);
65256873Sakito 	return (c);
65354008Sfujita }
65454008Sfujita 
sio_imputc(sio,c)65556873Sakito sio_imputc(sio, c)
65656873Sakito 	register struct siodevice *sio;
65754008Sfujita 	int c;
65854008Sfujita {
65954008Sfujita 	register u_char code;
66056873Sakito 	register int rr;
66156873Sakito 	int s;
66254008Sfujita 
66354008Sfujita 	s = splhigh();
66454008Sfujita 
66556873Sakito 	sioreg(sio, WR1, WR1_RXALLS);
66656873Sakito 
66754008Sfujita 	do {
66854008Sfujita 		DELAY(1);
66956873Sakito 		rr = siogetreg(sio);
67054008Sfujita 	} while (!(rr & RR_TXRDY));
67156873Sakito 
67256873Sakito 	code = (c & 0xFF);
67354008Sfujita 	sio->sio_data = code;
67454008Sfujita 
67554008Sfujita 	do {
67654008Sfujita 		DELAY(1);
67756873Sakito 		rr = siogetreg(sio);
67854008Sfujita 	} while (!(rr & RR_TXRDY));
67954008Sfujita 
68056873Sakito 	sioreg(sio, WR1, (WR1_RXALLS | WR1_TXENBL));
68156873Sakito 
68254008Sfujita 	splx(s);
68354008Sfujita }
68454008Sfujita 
68556873Sakito /*
68656873Sakito  *  uPD7201A register operation
68756873Sakito  */
68854008Sfujita 
68954008Sfujita int
siogetreg(sio)69056873Sakito siogetreg(sio)
69156873Sakito 	register struct siodevice *sio;
69254008Sfujita {
69354008Sfujita 	register int rr = 0;
69454008Sfujita 
69554008Sfujita 	rr = sio->sio_stat;
69654008Sfujita 	rr <<= 8;
69754008Sfujita 	sio->sio_cmd = 1;	/* Select RR1 */
69854008Sfujita 	rr |= sio->sio_stat;
69954008Sfujita 
70054008Sfujita 	return(rr);
70154008Sfujita }
70254008Sfujita 
70354008Sfujita int
sioreg(sio,reg,val)70456873Sakito sioreg(sio, reg, val)
70556873Sakito 	register struct siodevice *sio;
70654008Sfujita 	register int reg, val;
70754008Sfujita {
70854008Sfujita 	if (isStatusReg(reg)) {
70956873Sakito 		if (reg != 0)
71056873Sakito 		    sio->sio_cmd = reg;
71156873Sakito 		val = sio->sio_stat;
71254008Sfujita 	} else {
71356873Sakito 		if (reg != 0)
71456873Sakito 		    sio->sio_cmd = reg;
71556873Sakito 		sio->sio_cmd = val;
71654008Sfujita 	}
71756873Sakito 
71856873Sakito 	return(val);
71954008Sfujita }
72054008Sfujita #endif
721