xref: /csrg-svn/sys/luna68k/dev/bmc.c (revision 56876)
1*56876Sakito /*
2*56876Sakito  * Copyright (c) 1992 OMRON Corporation.
3*56876Sakito  * Copyright (c) 1992 The Regents of the University of California.
4*56876Sakito  * All rights reserved.
5*56876Sakito  *
6*56876Sakito  * This code is derived from software contributed to Berkeley by
7*56876Sakito  * OMRON Corporation.
8*56876Sakito  *
9*56876Sakito  * %sccs.include.redist.c%
10*56876Sakito  *
11*56876Sakito  *	@(#)bmc.c	7.1 (Berkeley) 11/17/92
12*56876Sakito  */
13*56876Sakito 
14*56876Sakito #define	BMC_NOCONSOLE
15*56876Sakito #define	BMD
16*56876Sakito 
17*56876Sakito #ifdef	BMD
18*56876Sakito #define	BMC_CNPORT	1
19*56876Sakito #else
20*56876Sakito #define	BMC_CNPORT	0
21*56876Sakito #endif
22*56876Sakito 
23*56876Sakito #include "bmc.h"
24*56876Sakito #if NBMC > 0
25*56876Sakito 
26*56876Sakito #include "sys/param.h"
27*56876Sakito #include "sys/systm.h"
28*56876Sakito #include "sys/ioctl.h"
29*56876Sakito #include "sys/proc.h"
30*56876Sakito #include "sys/tty.h"
31*56876Sakito #include "sys/conf.h"
32*56876Sakito #include "sys/file.h"
33*56876Sakito #include "sys/uio.h"
34*56876Sakito #include "sys/kernel.h"
35*56876Sakito #include "sys/syslog.h"
36*56876Sakito 
37*56876Sakito #include "device.h"
38*56876Sakito #include "sioreg.h"
39*56876Sakito #include "siovar.h"
40*56876Sakito 
41*56876Sakito #ifdef	BMD
42*56876Sakito #include "kbdreg.h"
43*56876Sakito #endif
44*56876Sakito 
45*56876Sakito extern	struct sio_portc *sio_port_assign();
46*56876Sakito 
47*56876Sakito int     bmcprobe();
48*56876Sakito int     bmcopen();
49*56876Sakito void    bmcstart();
50*56876Sakito int     bmcparam();
51*56876Sakito int     bmcintr();
52*56876Sakito 
53*56876Sakito struct	driver bmcdriver = {
54*56876Sakito 	bmcprobe, "bmc",
55*56876Sakito };
56*56876Sakito 
57*56876Sakito struct	bmc_softc {
58*56876Sakito 	struct sio_portc *sc_pc;
59*56876Sakito 	int	sc_mask;
60*56876Sakito };
61*56876Sakito 
62*56876Sakito struct	bmc_softc bmc_softc[NBMC];
63*56876Sakito 
64*56876Sakito struct	tty bmc_tty[NBMC];
65*56876Sakito 
66*56876Sakito int	bmc_config_done = 0;
67*56876Sakito 
68*56876Sakito int	bmcconsole;
69*56876Sakito int	bmcdefaultrate = B9600;				/* speed of console line is fixed */
70*56876Sakito int	bmcmajor = 0;
71*56876Sakito 
72*56876Sakito #define	bmcunit(x)		minor(x)
73*56876Sakito 
74*56876Sakito 
75*56876Sakito /*
76*56876Sakito  *  probe routine
77*56876Sakito  */
78*56876Sakito 
79*56876Sakito bmcprobe(hd)
80*56876Sakito 	register struct hp_device *hd;
81*56876Sakito {
82*56876Sakito }
83*56876Sakito 
84*56876Sakito bmcinit(port)
85*56876Sakito 	register int port;
86*56876Sakito {
87*56876Sakito 	register struct bmc_softc *sc = &bmc_softc[0];
88*56876Sakito 
89*56876Sakito 	/*
90*56876Sakito 	 * if BMC is already configured, should be skipped.
91*56876Sakito          */
92*56876Sakito 	if (bmc_config_done)
93*56876Sakito 		return(0);
94*56876Sakito 
95*56876Sakito 	/*
96*56876Sakito 	 * Check out bitmap Interface board
97*56876Sakito 	 */
98*56876Sakito 
99*56876Sakito 	/* port checking (for keyboard) */
100*56876Sakito 	if (port != 1)
101*56876Sakito 		return(0);
102*56876Sakito 
103*56876Sakito 	/* locate the major number */
104*56876Sakito 	for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++)
105*56876Sakito 		if (cdevsw[bmcmajor].d_open == bmcopen)
106*56876Sakito 			break;
107*56876Sakito 
108*56876Sakito 	sc->sc_pc = sio_port_assign(port, bmcmajor, 0, bmcintr);
109*56876Sakito 
110*56876Sakito 	printf("bmc%d: port %d, address 0x%x\n", sc->sc_pc->pc_unit, port, sc->sc_pc->pc_addr);
111*56876Sakito 
112*56876Sakito #ifdef	BMD
113*56876Sakito 	bmdinit();
114*56876Sakito #endif
115*56876Sakito 
116*56876Sakito 	bmc_config_done = 1;
117*56876Sakito 	return(1);
118*56876Sakito }
119*56876Sakito 
120*56876Sakito 
121*56876Sakito /*
122*56876Sakito  *  entry routines
123*56876Sakito  */
124*56876Sakito 
125*56876Sakito /* ARGSUSED */
126*56876Sakito #ifdef __STDC__
127*56876Sakito bmcopen(dev_t dev, int flag, int mode, struct proc *p)
128*56876Sakito #else
129*56876Sakito bmcopen(dev, flag, mode, p)
130*56876Sakito 	dev_t dev;
131*56876Sakito 	int flag, mode;
132*56876Sakito 	struct proc *p;
133*56876Sakito #endif
134*56876Sakito {
135*56876Sakito 	register struct tty *tp;
136*56876Sakito 	register int unit;
137*56876Sakito 	int error = 0;
138*56876Sakito 
139*56876Sakito 	unit = bmcunit(dev);
140*56876Sakito 	if (unit >= NBMC)
141*56876Sakito 		return (ENXIO);
142*56876Sakito 	tp = &bmc_tty[unit];
143*56876Sakito 	tp->t_oproc = bmcstart;
144*56876Sakito 	tp->t_param = bmcparam;
145*56876Sakito 	tp->t_dev = dev;
146*56876Sakito 	if ((tp->t_state & TS_ISOPEN) == 0) {
147*56876Sakito 		tp->t_state |= TS_WOPEN;
148*56876Sakito 		ttychars(tp);
149*56876Sakito 		if (tp->t_ispeed == 0) {
150*56876Sakito 			tp->t_iflag = TTYDEF_IFLAG;
151*56876Sakito 			tp->t_oflag = TTYDEF_OFLAG;
152*56876Sakito 			tp->t_cflag = TTYDEF_CFLAG;
153*56876Sakito /*			tp->t_cflag = (CREAD | CS8 | HUPCL);	*/
154*56876Sakito 			tp->t_lflag = TTYDEF_LFLAG;
155*56876Sakito 			tp->t_ispeed = tp->t_ospeed = bmcdefaultrate;
156*56876Sakito 		}
157*56876Sakito 		bmcparam(tp, &tp->t_termios);
158*56876Sakito 		ttsetwater(tp);
159*56876Sakito 	} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
160*56876Sakito 		return (EBUSY);
161*56876Sakito 	tp->t_state |= TS_CARR_ON;
162*56876Sakito 	(void) spltty();
163*56876Sakito 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
164*56876Sakito 	       (tp->t_state & TS_CARR_ON) == 0) {
165*56876Sakito 		tp->t_state |= TS_WOPEN;
166*56876Sakito 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
167*56876Sakito 		    ttopen, 0))
168*56876Sakito 			break;
169*56876Sakito 	}
170*56876Sakito 	(void) spl0();
171*56876Sakito 	if (error == 0)
172*56876Sakito 		error = (*linesw[tp->t_line].l_open)(dev, tp);
173*56876Sakito 
174*56876Sakito 	return (error);
175*56876Sakito }
176*56876Sakito 
177*56876Sakito /*ARGSUSED*/
178*56876Sakito bmcclose(dev, flag, mode, p)
179*56876Sakito 	dev_t dev;
180*56876Sakito 	int flag, mode;
181*56876Sakito 	struct proc *p;
182*56876Sakito {
183*56876Sakito 	register struct tty *tp;
184*56876Sakito 	register int unit;
185*56876Sakito 
186*56876Sakito 	unit = bmcunit(dev);
187*56876Sakito 	tp = &bmc_tty[unit];
188*56876Sakito 	(*linesw[tp->t_line].l_close)(tp, flag);
189*56876Sakito 	ttyclose(tp);
190*56876Sakito 	return (0);
191*56876Sakito }
192*56876Sakito 
193*56876Sakito bmcread(dev, uio, flag)
194*56876Sakito 	dev_t dev;
195*56876Sakito 	struct uio *uio;
196*56876Sakito {
197*56876Sakito 	register struct tty *tp = &bmc_tty[bmcunit(dev)];
198*56876Sakito 
199*56876Sakito 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
200*56876Sakito }
201*56876Sakito 
202*56876Sakito bmcwrite(dev, uio, flag)
203*56876Sakito 	dev_t dev;
204*56876Sakito 	struct uio *uio;
205*56876Sakito {
206*56876Sakito 	register struct tty *tp = &bmc_tty[bmcunit(dev)];
207*56876Sakito 
208*56876Sakito 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
209*56876Sakito }
210*56876Sakito 
211*56876Sakito /*
212*56876Sakito  * Stop output on a line.
213*56876Sakito  */
214*56876Sakito /*ARGSUSED*/
215*56876Sakito bmcstop(tp, flag)
216*56876Sakito 	register struct tty *tp;
217*56876Sakito {
218*56876Sakito 	register int s;
219*56876Sakito 
220*56876Sakito 	s = spltty();
221*56876Sakito 	if (tp->t_state & TS_BUSY) {
222*56876Sakito 		if ((tp->t_state&TS_TTSTOP)==0)
223*56876Sakito 			tp->t_state |= TS_FLUSH;
224*56876Sakito 	}
225*56876Sakito 	splx(s);
226*56876Sakito }
227*56876Sakito 
228*56876Sakito bmcioctl(dev, cmd, data, flag, p)
229*56876Sakito 	dev_t dev;
230*56876Sakito 	int cmd;
231*56876Sakito 	caddr_t data;
232*56876Sakito 	int flag;
233*56876Sakito 	struct proc *p;
234*56876Sakito {
235*56876Sakito 	register struct tty *tp;
236*56876Sakito 	register int unit = bmcunit(dev);
237*56876Sakito 	register int error;
238*56876Sakito 
239*56876Sakito 	tp = &bmc_tty[unit];
240*56876Sakito 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
241*56876Sakito 	if (error >= 0)
242*56876Sakito 		return (error);
243*56876Sakito 	error = ttioctl(tp, cmd, data, flag);
244*56876Sakito 	if (error >= 0)
245*56876Sakito 		return (error);
246*56876Sakito 
247*56876Sakito 	switch (cmd) {
248*56876Sakito 	default:
249*56876Sakito 		return (ENOTTY);
250*56876Sakito 	}
251*56876Sakito 	return (0);
252*56876Sakito }
253*56876Sakito 
254*56876Sakito /*
255*56876Sakito  *
256*56876Sakito  */
257*56876Sakito #ifdef BMD
258*56876Sakito void
259*56876Sakito bmcstart(tp)
260*56876Sakito 	register struct tty *tp;
261*56876Sakito {
262*56876Sakito 	int unit = bmcunit(tp->t_dev);
263*56876Sakito 	register struct bmc_softc *sc = &bmc_softc[unit];
264*56876Sakito 	register int cc, s;
265*56876Sakito 	int hiwat = 0;
266*56876Sakito 
267*56876Sakito 	s = spltty();
268*56876Sakito 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
269*56876Sakito 		splx(s);
270*56876Sakito 		return;
271*56876Sakito 	}
272*56876Sakito 	tp->t_state |= TS_BUSY;
273*56876Sakito 	cc = tp->t_outq.c_cc;
274*56876Sakito 	if (cc <= tp->t_lowat) {
275*56876Sakito 		if (tp->t_state & TS_ASLEEP) {
276*56876Sakito 			tp->t_state &= ~TS_ASLEEP;
277*56876Sakito 			wakeup((caddr_t)&tp->t_outq);
278*56876Sakito 		}
279*56876Sakito 		selwakeup(&tp->t_wsel);
280*56876Sakito 	}
281*56876Sakito 	/*
282*56876Sakito 	 * Limit the amount of output we do in one burst
283*56876Sakito 	 * to prevent hogging the CPU.
284*56876Sakito 	 */
285*56876Sakito /*
286*56876Sakito 	if (cc > iteburst) {
287*56876Sakito 		hiwat++;
288*56876Sakito 		cc = iteburst;
289*56876Sakito 	}
290*56876Sakito  */
291*56876Sakito 	while (--cc >= 0) {
292*56876Sakito 		register int c;
293*56876Sakito 
294*56876Sakito 		c = getc(&tp->t_outq);
295*56876Sakito 		/*
296*56876Sakito 		 * iteputchar() may take a long time and we don't want to
297*56876Sakito 		 * block all interrupts for long periods of time.  Since
298*56876Sakito 		 * there is no need to stay at high priority while outputing
299*56876Sakito 		 * the character (since we don't have to worry about
300*56876Sakito 		 * interrupts), we don't.  We just need to make sure that
301*56876Sakito 		 * we don't reenter iteputchar, which is guarenteed by the
302*56876Sakito 		 * earlier setting of TS_BUSY.
303*56876Sakito 		 */
304*56876Sakito 		splx(s);
305*56876Sakito 		bmdputc(c & sc->sc_mask);
306*56876Sakito 		spltty();
307*56876Sakito 	}
308*56876Sakito /*
309*56876Sakito 	if (hiwat) {
310*56876Sakito 		tp->t_state |= TS_TIMEOUT;
311*56876Sakito 		timeout(ttrstrt, tp, 1);
312*56876Sakito 	}
313*56876Sakito  */
314*56876Sakito 	tp->t_state &= ~TS_BUSY;
315*56876Sakito 	splx(s);
316*56876Sakito }
317*56876Sakito #else
318*56876Sakito void
319*56876Sakito bmcstart(tp)
320*56876Sakito 	register struct tty *tp;
321*56876Sakito {
322*56876Sakito 	register struct siodevice *sio;
323*56876Sakito 	register int rr;
324*56876Sakito 	int s, unit, c;
325*56876Sakito 
326*56876Sakito 	unit = bmcunit(tp->t_dev);
327*56876Sakito 	sio = bmc_softc[unit].sc_pc->pc_addr;
328*56876Sakito 	s = spltty();
329*56876Sakito 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
330*56876Sakito 		goto out;
331*56876Sakito 	if (tp->t_outq.c_cc <= tp->t_lowat) {
332*56876Sakito 		if (tp->t_state&TS_ASLEEP) {
333*56876Sakito 			tp->t_state &= ~TS_ASLEEP;
334*56876Sakito 			wakeup((caddr_t)&tp->t_outq);
335*56876Sakito 		}
336*56876Sakito 		selwakeup(&tp->t_wsel);
337*56876Sakito 	}
338*56876Sakito 	if (tp->t_outq.c_cc == 0)
339*56876Sakito 		goto out;
340*56876Sakito 	rr = siogetreg(sio);
341*56876Sakito 	if (rr & RR_TXRDY) {
342*56876Sakito 		c = getc(&tp->t_outq);
343*56876Sakito 		tp->t_state |= TS_BUSY;
344*56876Sakito 		sio->sio_data = c;
345*56876Sakito 	}
346*56876Sakito out:
347*56876Sakito 	splx(s);
348*56876Sakito }
349*56876Sakito #endif
350*56876Sakito 
351*56876Sakito bmcparam(tp, t)
352*56876Sakito 	register struct tty *tp;
353*56876Sakito 	register struct termios *t;
354*56876Sakito {
355*56876Sakito 	int unit = bmcunit(tp->t_dev);
356*56876Sakito 	register struct bmc_softc *sc = &bmc_softc[unit];
357*56876Sakito 	register int cflag = t->c_cflag;
358*56876Sakito 
359*56876Sakito         /* and copy to tty */
360*56876Sakito         tp->t_ispeed = t->c_ispeed;
361*56876Sakito         tp->t_ospeed = t->c_ospeed;
362*56876Sakito         tp->t_cflag = cflag;
363*56876Sakito 
364*56876Sakito 	/*
365*56876Sakito 	 * change line speed
366*56876Sakito 	 */
367*56876Sakito 
368*56876Sakito 	switch (cflag&CSIZE) {
369*56876Sakito 	case CS5:
370*56876Sakito 		sc->sc_mask = 0x1F ; break;
371*56876Sakito 	case CS6:
372*56876Sakito 		sc->sc_mask = 0x3F ; break;
373*56876Sakito 	case CS7:
374*56876Sakito 		sc->sc_mask = 0x7F ; break;
375*56876Sakito 	case CS8:
376*56876Sakito 		sc->sc_mask = 0xFF ; break;
377*56876Sakito 	}
378*56876Sakito 
379*56876Sakito 	/*
380*56876Sakito 	 * parity
381*56876Sakito 	 */
382*56876Sakito 
383*56876Sakito 	/*
384*56876Sakito 	 * stop bit
385*56876Sakito 	 */
386*56876Sakito 
387*56876Sakito 	return (0);
388*56876Sakito }
389*56876Sakito 
390*56876Sakito 
391*56876Sakito /*
392*56876Sakito  *  interrupt handling
393*56876Sakito  */
394*56876Sakito 
395*56876Sakito #ifdef BMD
396*56876Sakito bmcintr(unit)
397*56876Sakito 	register int unit;
398*56876Sakito {
399*56876Sakito 	register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr;
400*56876Sakito 	register struct tty *tp;
401*56876Sakito 	register u_char code;
402*56876Sakito 	register int c;
403*56876Sakito 	int s, rr;
404*56876Sakito 
405*56876Sakito 	tp = &bmc_tty[unit];
406*56876Sakito 	rr = siogetreg(sio);
407*56876Sakito 
408*56876Sakito 	if (rr & RR_RXRDY) {
409*56876Sakito 		code = sio->sio_data;
410*56876Sakito 		c = kbd_decode(code);
411*56876Sakito 		if (c & KC_TYPE)			/* skip special codes */
412*56876Sakito 			return;
413*56876Sakito 		code = (c & KC_CHAR);
414*56876Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
415*56876Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
416*56876Sakito 	}
417*56876Sakito }
418*56876Sakito #else
419*56876Sakito bmcintr(unit)
420*56876Sakito 	register int unit;
421*56876Sakito {
422*56876Sakito 	register struct siodevice *sio = bmc_softc[unit].sc_pc->pc_addr;
423*56876Sakito 	register u_char code;
424*56876Sakito 	register struct tty *tp;
425*56876Sakito 	int s, rr;
426*56876Sakito 
427*56876Sakito 	tp = &bmc_tty[unit];
428*56876Sakito 	rr = siogetreg(sio);
429*56876Sakito 
430*56876Sakito 	if (rr & RR_RXRDY) {
431*56876Sakito 		code = sio->sio_data;
432*56876Sakito 		if ((tp->t_state & TS_ISOPEN) != 0)
433*56876Sakito 			(*linesw[tp->t_line].l_rint)(code, tp);
434*56876Sakito 	}
435*56876Sakito 
436*56876Sakito 	if (rr & RR_TXRDY) {
437*56876Sakito 		sio->sio_cmd = WR0_RSTPEND;
438*56876Sakito 		tp->t_state &= ~(TS_BUSY|TS_FLUSH);
439*56876Sakito 		if (tp->t_line)
440*56876Sakito 			(*linesw[tp->t_line].l_start)(tp);
441*56876Sakito 		else
442*56876Sakito 			bmcstart(tp);
443*56876Sakito 	}
444*56876Sakito 
445*56876Sakito }
446*56876Sakito #endif
447*56876Sakito 
448*56876Sakito /*
449*56876Sakito  * Following are all routines needed for SIO to act as console
450*56876Sakito  */
451*56876Sakito #include "../luna68k/cons.h"
452*56876Sakito 
453*56876Sakito bmccnprobe(cp)
454*56876Sakito 	register struct consdev *cp;
455*56876Sakito {
456*56876Sakito #ifdef BMC_NOCONSOLE
457*56876Sakito 	cp->cn_pri = CN_DEAD;
458*56876Sakito 	return;
459*56876Sakito #else
460*56876Sakito 	/* check DIP-SW setup */
461*56876Sakito 	/* check bitmap interface board */
462*56876Sakito 
463*56876Sakito 	/* locate the major number */
464*56876Sakito 	for (bmcmajor = 0; bmcmajor < nchrdev; bmcmajor++)
465*56876Sakito 		if (cdevsw[bmcmajor].d_open == bmcopen)
466*56876Sakito 			break;
467*56876Sakito 
468*56876Sakito 	/* initialize required fields */
469*56876Sakito 	cp->cn_dev = makedev(bmcmajor, 0);
470*56876Sakito 	cp->cn_tp  = &bmc_tty[0];
471*56876Sakito 	cp->cn_pri = CN_INTERNAL;
472*56876Sakito 
473*56876Sakito 	bmc_config_done = 1;
474*56876Sakito #endif
475*56876Sakito }
476*56876Sakito 
477*56876Sakito bmccninit(cp)
478*56876Sakito 	struct consdev *cp;
479*56876Sakito {
480*56876Sakito 	int unit = bmcunit(cp->cn_dev);
481*56876Sakito 	register struct bmc_softc *sc = &bmc_softc[0];
482*56876Sakito 
483*56876Sakito 	sioinit((struct siodevice *) SIO_HARDADDR, bmcdefaultrate);
484*56876Sakito #ifdef	BMD
485*56876Sakito 	bmdinit();
486*56876Sakito #endif
487*56876Sakito 
488*56876Sakito 	/* port assign */
489*56876Sakito 	sc->sc_pc = sio_port_assign(BMC_CNPORT, bmcmajor, 0, bmcintr);
490*56876Sakito 
491*56876Sakito 	bmcconsole = unit;
492*56876Sakito }
493*56876Sakito 
494*56876Sakito bmccngetc(dev)
495*56876Sakito 	dev_t dev;
496*56876Sakito {
497*56876Sakito 	struct bmc_softc *sc = &bmc_softc[bmcunit(dev)];
498*56876Sakito 	struct sio_portc *pc = sc->sc_pc;
499*56876Sakito #ifdef	BMD
500*56876Sakito 	register int c;
501*56876Sakito 	register u_char code;
502*56876Sakito 
503*56876Sakito 	do {
504*56876Sakito 		code = sio_imgetc(pc->pc_addr);
505*56876Sakito 	} while ((c = kbd_decode(code)) & KC_TYPE);
506*56876Sakito 
507*56876Sakito 	return(c);
508*56876Sakito #else
509*56876Sakito 	return(sio_imgetc(pc->pc_addr));
510*56876Sakito #endif
511*56876Sakito }
512*56876Sakito 
513*56876Sakito bmccnputc(dev, c)
514*56876Sakito 	dev_t dev;
515*56876Sakito 	int c;
516*56876Sakito {
517*56876Sakito 	struct bmc_softc *sc = &bmc_softc[bmcunit(dev)];
518*56876Sakito 	struct sio_portc *pc = sc->sc_pc;
519*56876Sakito 
520*56876Sakito #ifdef BMD
521*56876Sakito 	bmdputc(c);
522*56876Sakito #else
523*56876Sakito 	sio_imputc(pc->pc_addr, c);
524*56876Sakito #endif
525*56876Sakito }
526*56876Sakito #endif
527