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