xref: /csrg-svn/sys/luna68k/dev/bmc.c (revision 57059)
156876Sakito /*
256876Sakito  * Copyright (c) 1992 OMRON Corporation.
356876Sakito  * Copyright (c) 1992 The Regents of the University of California.
456876Sakito  * All rights reserved.
556876Sakito  *
656876Sakito  * This code is derived from software contributed to Berkeley by
756876Sakito  * OMRON Corporation.
856876Sakito  *
956876Sakito  * %sccs.include.redist.c%
1056876Sakito  *
11*57059Sakito  *	@(#)bmc.c	7.2 (Berkeley) 12/10/92
1256876Sakito  */
1356876Sakito 
1456876Sakito #define	BMC_NOCONSOLE
1556876Sakito #define	BMD
1656876Sakito 
1756876Sakito #ifdef	BMD
1856876Sakito #define	BMC_CNPORT	1
1956876Sakito #else
2056876Sakito #define	BMC_CNPORT	0
2156876Sakito #endif
2256876Sakito 
2356876Sakito #include "bmc.h"
2456876Sakito #if NBMC > 0
2556876Sakito 
26*57059Sakito #include <sys/param.h>
27*57059Sakito #include <sys/systm.h>
28*57059Sakito #include <sys/ioctl.h>
29*57059Sakito #include <sys/proc.h>
30*57059Sakito #include <sys/tty.h>
31*57059Sakito #include <sys/conf.h>
32*57059Sakito #include <sys/file.h>
33*57059Sakito #include <sys/uio.h>
34*57059Sakito #include <sys/kernel.h>
35*57059Sakito #include <sys/syslog.h>
3656876Sakito 
37*57059Sakito #include <luna68k/dev/device.h>
38*57059Sakito #include <luna68k/dev/sioreg.h>
39*57059Sakito #include <luna68k/dev/siovar.h>
4056876Sakito 
4156876Sakito #ifdef	BMD
4256876Sakito #include "kbdreg.h"
4356876Sakito #endif
4456876Sakito 
4556876Sakito extern	struct sio_portc *sio_port_assign();
4656876Sakito 
4756876Sakito int     bmcprobe();
4856876Sakito int     bmcopen();
4956876Sakito void    bmcstart();
5056876Sakito int     bmcparam();
5156876Sakito int     bmcintr();
5256876Sakito 
5356876Sakito struct	driver bmcdriver = {
5456876Sakito 	bmcprobe, "bmc",
5556876Sakito };
5656876Sakito 
5756876Sakito struct	bmc_softc {
5856876Sakito 	struct sio_portc *sc_pc;
5956876Sakito 	int	sc_mask;
6056876Sakito };
6156876Sakito 
6256876Sakito struct	bmc_softc bmc_softc[NBMC];
6356876Sakito 
6456876Sakito struct	tty bmc_tty[NBMC];
6556876Sakito 
6656876Sakito int	bmc_config_done = 0;
6756876Sakito 
6856876Sakito int	bmcconsole;
6956876Sakito int	bmcdefaultrate = B9600;				/* speed of console line is fixed */
7056876Sakito int	bmcmajor = 0;
7156876Sakito 
7256876Sakito #define	bmcunit(x)		minor(x)
7356876Sakito 
7456876Sakito 
7556876Sakito /*
7656876Sakito  *  probe routine
7756876Sakito  */
7856876Sakito 
7956876Sakito bmcprobe(hd)
8056876Sakito 	register struct hp_device *hd;
8156876Sakito {
8256876Sakito }
8356876Sakito 
8456876Sakito bmcinit(port)
8556876Sakito 	register int port;
8656876Sakito {
8756876Sakito 	register struct bmc_softc *sc = &bmc_softc[0];
8856876Sakito 
8956876Sakito 	/*
9056876Sakito 	 * if BMC is already configured, should be skipped.
9156876Sakito          */
9256876Sakito 	if (bmc_config_done)
9356876Sakito 		return(0);
9456876Sakito 
9556876Sakito 	/*
9656876Sakito 	 * Check out bitmap Interface board
9756876Sakito 	 */
9856876Sakito 
9956876Sakito 	/* port checking (for keyboard) */
10056876Sakito 	if (port != 1)
10156876Sakito 		return(0);
10256876Sakito 
10356876Sakito 	/* locate the major number */
10456876Sakito 	for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++)
10556876Sakito 		if (cdevsw[bmcmajor].d_open == bmcopen)
10656876Sakito 			break;
10756876Sakito 
10856876Sakito 	sc->sc_pc = sio_port_assign(port, bmcmajor, 0, bmcintr);
10956876Sakito 
11056876Sakito 	printf("bmc%d: port %d, address 0x%x\n", sc->sc_pc->pc_unit, port, sc->sc_pc->pc_addr);
11156876Sakito 
11256876Sakito #ifdef	BMD
11356876Sakito 	bmdinit();
11456876Sakito #endif
11556876Sakito 
11656876Sakito 	bmc_config_done = 1;
11756876Sakito 	return(1);
11856876Sakito }
11956876Sakito 
12056876Sakito 
12156876Sakito /*
12256876Sakito  *  entry routines
12356876Sakito  */
12456876Sakito 
12556876Sakito /* ARGSUSED */
12656876Sakito #ifdef __STDC__
12756876Sakito bmcopen(dev_t dev, int flag, int mode, struct proc *p)
12856876Sakito #else
12956876Sakito bmcopen(dev, flag, mode, p)
13056876Sakito 	dev_t dev;
13156876Sakito 	int flag, mode;
13256876Sakito 	struct proc *p;
13356876Sakito #endif
13456876Sakito {
13556876Sakito 	register struct tty *tp;
13656876Sakito 	register int unit;
13756876Sakito 	int error = 0;
13856876Sakito 
13956876Sakito 	unit = bmcunit(dev);
14056876Sakito 	if (unit >= NBMC)
14156876Sakito 		return (ENXIO);
14256876Sakito 	tp = &bmc_tty[unit];
14356876Sakito 	tp->t_oproc = bmcstart;
14456876Sakito 	tp->t_param = bmcparam;
14556876Sakito 	tp->t_dev = dev;
14656876Sakito 	if ((tp->t_state & TS_ISOPEN) == 0) {
14756876Sakito 		tp->t_state |= TS_WOPEN;
14856876Sakito 		ttychars(tp);
14956876Sakito 		if (tp->t_ispeed == 0) {
15056876Sakito 			tp->t_iflag = TTYDEF_IFLAG;
15156876Sakito 			tp->t_oflag = TTYDEF_OFLAG;
15256876Sakito 			tp->t_cflag = TTYDEF_CFLAG;
15356876Sakito /*			tp->t_cflag = (CREAD | CS8 | HUPCL);	*/
15456876Sakito 			tp->t_lflag = TTYDEF_LFLAG;
15556876Sakito 			tp->t_ispeed = tp->t_ospeed = bmcdefaultrate;
15656876Sakito 		}
15756876Sakito 		bmcparam(tp, &tp->t_termios);
15856876Sakito 		ttsetwater(tp);
15956876Sakito 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
16056876Sakito 		return (EBUSY);
16156876Sakito 	tp->t_state |= TS_CARR_ON;
16256876Sakito 	(void) spltty();
16356876Sakito 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
16456876Sakito 	       (tp->t_state & TS_CARR_ON) == 0) {
16556876Sakito 		tp->t_state |= TS_WOPEN;
16656876Sakito 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
16756876Sakito 		    ttopen, 0))
16856876Sakito 			break;
16956876Sakito 	}
17056876Sakito 	(void) spl0();
17156876Sakito 	if (error == 0)
17256876Sakito 		error = (*linesw[tp->t_line].l_open)(dev, tp);
17356876Sakito 
17456876Sakito 	return (error);
17556876Sakito }
17656876Sakito 
17756876Sakito /*ARGSUSED*/
17856876Sakito bmcclose(dev, flag, mode, p)
17956876Sakito 	dev_t dev;
18056876Sakito 	int flag, mode;
18156876Sakito 	struct proc *p;
18256876Sakito {
18356876Sakito 	register struct tty *tp;
18456876Sakito 	register int unit;
18556876Sakito 
18656876Sakito 	unit = bmcunit(dev);
18756876Sakito 	tp = &bmc_tty[unit];
18856876Sakito 	(*linesw[tp->t_line].l_close)(tp, flag);
18956876Sakito 	ttyclose(tp);
19056876Sakito 	return (0);
19156876Sakito }
19256876Sakito 
19356876Sakito bmcread(dev, uio, flag)
19456876Sakito 	dev_t dev;
19556876Sakito 	struct uio *uio;
19656876Sakito {
19756876Sakito 	register struct tty *tp = &bmc_tty[bmcunit(dev)];
19856876Sakito 
19956876Sakito 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
20056876Sakito }
20156876Sakito 
20256876Sakito bmcwrite(dev, uio, flag)
20356876Sakito 	dev_t dev;
20456876Sakito 	struct uio *uio;
20556876Sakito {
20656876Sakito 	register struct tty *tp = &bmc_tty[bmcunit(dev)];
20756876Sakito 
20856876Sakito 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
20956876Sakito }
21056876Sakito 
21156876Sakito /*
21256876Sakito  * Stop output on a line.
21356876Sakito  */
21456876Sakito /*ARGSUSED*/
21556876Sakito bmcstop(tp, flag)
21656876Sakito 	register struct tty *tp;
21756876Sakito {
21856876Sakito 	register int s;
21956876Sakito 
22056876Sakito 	s = spltty();
22156876Sakito 	if (tp->t_state & TS_BUSY) {
22256876Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
22356876Sakito 			tp->t_state |= TS_FLUSH;
22456876Sakito 	}
22556876Sakito 	splx(s);
22656876Sakito }
22756876Sakito 
22856876Sakito bmcioctl(dev, cmd, data, flag, p)
22956876Sakito 	dev_t dev;
23056876Sakito 	int cmd;
23156876Sakito 	caddr_t data;
23256876Sakito 	int flag;
23356876Sakito 	struct proc *p;
23456876Sakito {
23556876Sakito 	register struct tty *tp;
23656876Sakito 	register int unit = bmcunit(dev);
23756876Sakito 	register int error;
23856876Sakito 
23956876Sakito 	tp = &bmc_tty[unit];
24056876Sakito 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
24156876Sakito 	if (error >= 0)
24256876Sakito 		return (error);
24356876Sakito 	error = ttioctl(tp, cmd, data, flag);
24456876Sakito 	if (error >= 0)
24556876Sakito 		return (error);
24656876Sakito 
24756876Sakito 	switch (cmd) {
24856876Sakito 	default:
24956876Sakito 		return (ENOTTY);
25056876Sakito 	}
25156876Sakito 	return (0);
25256876Sakito }
25356876Sakito 
25456876Sakito /*
25556876Sakito  *
25656876Sakito  */
25756876Sakito #ifdef BMD
25856876Sakito void
25956876Sakito bmcstart(tp)
26056876Sakito 	register struct tty *tp;
26156876Sakito {
26256876Sakito 	int unit = bmcunit(tp->t_dev);
26356876Sakito 	register struct bmc_softc *sc = &bmc_softc[unit];
26456876Sakito 	register int cc, s;
26556876Sakito 	int hiwat = 0;
26656876Sakito 
26756876Sakito 	s = spltty();
26856876Sakito 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
26956876Sakito 		splx(s);
27056876Sakito 		return;
27156876Sakito 	}
27256876Sakito 	tp->t_state |= TS_BUSY;
27356876Sakito 	cc = tp->t_outq.c_cc;
27456876Sakito 	if (cc <= tp->t_lowat) {
27556876Sakito 		if (tp->t_state & TS_ASLEEP) {
27656876Sakito 			tp->t_state &= ~TS_ASLEEP;
27756876Sakito 			wakeup((caddr_t)&tp->t_outq);
27856876Sakito 		}
27956876Sakito 		selwakeup(&tp->t_wsel);
28056876Sakito 	}
28156876Sakito 	/*
28256876Sakito 	 * Limit the amount of output we do in one burst
28356876Sakito 	 * to prevent hogging the CPU.
28456876Sakito 	 */
28556876Sakito /*
28656876Sakito 	if (cc > iteburst) {
28756876Sakito 		hiwat++;
28856876Sakito 		cc = iteburst;
28956876Sakito 	}
29056876Sakito  */
29156876Sakito 	while (--cc >= 0) {
29256876Sakito 		register int c;
29356876Sakito 
29456876Sakito 		c = getc(&tp->t_outq);
29556876Sakito 		/*
29656876Sakito 		 * iteputchar() may take a long time and we don't want to
29756876Sakito 		 * block all interrupts for long periods of time.  Since
29856876Sakito 		 * there is no need to stay at high priority while outputing
29956876Sakito 		 * the character (since we don't have to worry about
30056876Sakito 		 * interrupts), we don't.  We just need to make sure that
30156876Sakito 		 * we don't reenter iteputchar, which is guarenteed by the
30256876Sakito 		 * earlier setting of TS_BUSY.
30356876Sakito 		 */
30456876Sakito 		splx(s);
30556876Sakito 		bmdputc(c & sc->sc_mask);
30656876Sakito 		spltty();
30756876Sakito 	}
30856876Sakito /*
30956876Sakito 	if (hiwat) {
31056876Sakito 		tp->t_state |= TS_TIMEOUT;
31156876Sakito 		timeout(ttrstrt, tp, 1);
31256876Sakito 	}
31356876Sakito  */
31456876Sakito 	tp->t_state &= ~TS_BUSY;
31556876Sakito 	splx(s);
31656876Sakito }
31756876Sakito #else
31856876Sakito void
31956876Sakito bmcstart(tp)
32056876Sakito 	register struct tty *tp;
32156876Sakito {
32256876Sakito 	register struct siodevice *sio;
32356876Sakito 	register int rr;
32456876Sakito 	int s, unit, c;
32556876Sakito 
32656876Sakito 	unit = bmcunit(tp->t_dev);
32756876Sakito 	sio = bmc_softc[unit].sc_pc->pc_addr;
32856876Sakito 	s = spltty();
32956876Sakito 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
33056876Sakito 		goto out;
33156876Sakito 	if (tp->t_outq.c_cc <= tp->t_lowat) {
33256876Sakito 		if (tp->t_state&TS_ASLEEP) {
33356876Sakito 			tp->t_state &= ~TS_ASLEEP;
33456876Sakito 			wakeup((caddr_t)&tp->t_outq);
33556876Sakito 		}
33656876Sakito 		selwakeup(&tp->t_wsel);
33756876Sakito 	}
33856876Sakito 	if (tp->t_outq.c_cc == 0)
33956876Sakito 		goto out;
34056876Sakito 	rr = siogetreg(sio);
34156876Sakito 	if (rr & RR_TXRDY) {
34256876Sakito 		c = getc(&tp->t_outq);
34356876Sakito 		tp->t_state |= TS_BUSY;
34456876Sakito 		sio->sio_data = c;
34556876Sakito 	}
34656876Sakito out:
34756876Sakito 	splx(s);
34856876Sakito }
34956876Sakito #endif
35056876Sakito 
35156876Sakito bmcparam(tp, t)
35256876Sakito 	register struct tty *tp;
35356876Sakito 	register struct termios *t;
35456876Sakito {
35556876Sakito 	int unit = bmcunit(tp->t_dev);
35656876Sakito 	register struct bmc_softc *sc = &bmc_softc[unit];
35756876Sakito 	register int cflag = t->c_cflag;
35856876Sakito 
35956876Sakito         /* and copy to tty */
36056876Sakito         tp->t_ispeed = t->c_ispeed;
36156876Sakito         tp->t_ospeed = t->c_ospeed;
36256876Sakito         tp->t_cflag = cflag;
36356876Sakito 
36456876Sakito 	/*
36556876Sakito 	 * change line speed
36656876Sakito 	 */
36756876Sakito 
36856876Sakito 	switch (cflag&CSIZE) {
36956876Sakito 	case CS5:
37056876Sakito 		sc->sc_mask = 0x1F ; break;
37156876Sakito 	case CS6:
37256876Sakito 		sc->sc_mask = 0x3F ; break;
37356876Sakito 	case CS7:
37456876Sakito 		sc->sc_mask = 0x7F ; break;
37556876Sakito 	case CS8:
37656876Sakito 		sc->sc_mask = 0xFF ; break;
37756876Sakito 	}
37856876Sakito 
37956876Sakito 	/*
38056876Sakito 	 * parity
38156876Sakito 	 */
38256876Sakito 
38356876Sakito 	/*
38456876Sakito 	 * stop bit
38556876Sakito 	 */
38656876Sakito 
38756876Sakito 	return (0);
38856876Sakito }
38956876Sakito 
39056876Sakito 
39156876Sakito /*
39256876Sakito  *  interrupt handling
39356876Sakito  */
39456876Sakito 
39556876Sakito #ifdef BMD
39656876Sakito bmcintr(unit)
39756876Sakito 	register int unit;
39856876Sakito {
39956876Sakito 	register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr;
40056876Sakito 	register struct tty *tp;
40156876Sakito 	register u_char code;
40256876Sakito 	register int c;
40356876Sakito 	int s, rr;
40456876Sakito 
40556876Sakito 	tp = &bmc_tty[unit];
40656876Sakito 	rr = siogetreg(sio);
40756876Sakito 
40856876Sakito 	if (rr & RR_RXRDY) {
40956876Sakito 		code = sio->sio_data;
41056876Sakito 		c = kbd_decode(code);
41156876Sakito 		if (c & KC_TYPE)			/* skip special codes */
41256876Sakito 			return;
41356876Sakito 		code = (c & KC_CHAR);
41456876Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
41556876Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
41656876Sakito 	}
41756876Sakito }
41856876Sakito #else
41956876Sakito bmcintr(unit)
42056876Sakito 	register int unit;
42156876Sakito {
42256876Sakito 	register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr;
42356876Sakito 	register u_char code;
42456876Sakito 	register struct tty *tp;
42556876Sakito 	int s, rr;
42656876Sakito 
42756876Sakito 	tp = &bmc_tty[unit];
42856876Sakito 	rr = siogetreg(sio);
42956876Sakito 
43056876Sakito 	if (rr & RR_RXRDY) {
43156876Sakito 		code = sio->sio_data;
43256876Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
43356876Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
43456876Sakito 	}
43556876Sakito 
43656876Sakito 	if (rr & RR_TXRDY) {
43756876Sakito 		sio->sio_cmd = WR0_RSTPEND;
43856876Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
43956876Sakito 		if (tp->t_line)
44056876Sakito 			(*linesw[tp->t_line].l_start)(tp);
44156876Sakito 		else
44256876Sakito 			bmcstart(tp);
44356876Sakito 	}
44456876Sakito 
44556876Sakito }
44656876Sakito #endif
44756876Sakito 
44856876Sakito /*
44956876Sakito  * Following are all routines needed for SIO to act as console
45056876Sakito  */
45156876Sakito #include "../luna68k/cons.h"
45256876Sakito 
45356876Sakito bmccnprobe(cp)
45456876Sakito 	register struct consdev *cp;
45556876Sakito {
45656876Sakito #ifdef BMC_NOCONSOLE
45756876Sakito 	cp->cn_pri = CN_DEAD;
45856876Sakito 	return;
45956876Sakito #else
46056876Sakito 	/* check DIP-SW setup */
46156876Sakito 	/* check bitmap interface board */
46256876Sakito 
46356876Sakito 	/* locate the major number */
46456876Sakito 	for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++)
46556876Sakito 		if (cdevsw[bmcmajor].d_open == bmcopen)
46656876Sakito 			break;
46756876Sakito 
46856876Sakito 	/* initialize required fields */
46956876Sakito 	cp->cn_dev = makedev(bmcmajor, 0);
47056876Sakito 	cp->cn_tp  = &bmc_tty[0];
47156876Sakito 	cp->cn_pri = CN_INTERNAL;
47256876Sakito 
47356876Sakito 	bmc_config_done = 1;
47456876Sakito #endif
47556876Sakito }
47656876Sakito 
47756876Sakito bmccninit(cp)
47856876Sakito 	struct consdev *cp;
47956876Sakito {
48056876Sakito 	int unit = bmcunit(cp->cn_dev);
48156876Sakito 	register struct bmc_softc *sc = &bmc_softc[0];
48256876Sakito 
48356876Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, bmcdefaultrate);
48456876Sakito #ifdef	BMD
48556876Sakito 	bmdinit();
48656876Sakito #endif
48756876Sakito 
48856876Sakito 	/* port assign */
48956876Sakito 	sc->sc_pc = sio_port_assign(BMC_CNPORT, bmcmajor, 0, bmcintr);
49056876Sakito 
49156876Sakito 	bmcconsole = unit;
49256876Sakito }
49356876Sakito 
49456876Sakito bmccngetc(dev)
49556876Sakito 	dev_t dev;
49656876Sakito {
49756876Sakito 	struct bmc_softc *sc = &bmc_softc[bmcunit(dev)];
49856876Sakito 	struct sio_portc *pc = sc->sc_pc;
49956876Sakito #ifdef	BMD
50056876Sakito 	register int c;
50156876Sakito 	register u_char code;
50256876Sakito 
50356876Sakito 	do {
50456876Sakito 		code = sio_imgetc(pc->pc_addr);
50556876Sakito 	} while ((c = kbd_decode(code)) & KC_TYPE);
50656876Sakito 
50756876Sakito 	return(c);
50856876Sakito #else
50956876Sakito 	return(sio_imgetc(pc->pc_addr));
51056876Sakito #endif
51156876Sakito }
51256876Sakito 
51356876Sakito bmccnputc(dev, c)
51456876Sakito 	dev_t dev;
51556876Sakito 	int c;
51656876Sakito {
51756876Sakito 	struct bmc_softc *sc = &bmc_softc[bmcunit(dev)];
51856876Sakito 	struct sio_portc *pc = sc->sc_pc;
51956876Sakito 
52056876Sakito #ifdef BMD
52156876Sakito 	bmdputc(c);
52256876Sakito #else
52356876Sakito 	sio_imputc(pc->pc_addr, c);
52456876Sakito #endif
52556876Sakito }
52656876Sakito #endif
527