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