xref: /original-bsd/sys/pmax/dev/dtop.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell and Rick Macklem.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)dtop.c	8.1 (Berkeley) 06/10/93
11  */
12 
13 /*
14  * Mach Operating System
15  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
16  * All Rights Reserved.
17  *
18  * Permission to use, copy, modify and distribute this software and its
19  * documentation is hereby granted, provided that both the copyright
20  * notice and this permission notice appear in all copies of the
21  * software, derivative works or modified versions, and any portions
22  * thereof, and that both notices appear in supporting documentation.
23  *
24  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
25  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
26  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27  *
28  * Carnegie Mellon requests users of this software to return to
29  *
30  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31  *  School of Computer Science
32  *  Carnegie Mellon University
33  *  Pittsburgh PA 15213-3890
34  *
35  * any improvements or extensions that they make and grant Carnegie the
36  * rights to redistribute these changes.
37  */
38 /*
39  * 	Author: Alessandro Forin, Carnegie Mellon University
40  *
41  *	Hardware-level operations for the Desktop serial line
42  *	bus (i2c aka ACCESS).
43  */
44 /************************************************************
45 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
46 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
47 
48                         All Rights Reserved
49 
50 Permission to use, copy, modify, and distribute this software and its
51 documentation for any purpose and without fee is hereby granted,
52 provided that the above copyright notice appear in all copies and that
53 both that copyright notice and this permission notice appear in
54 supporting documentation, and that the names of Digital or MIT not be
55 used in advertising or publicity pertaining to distribution of the
56 software without specific, written prior permission.
57 
58 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
59 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
60 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
62 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
63 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64 SOFTWARE.
65 
66 ********************************************************/
67 
68 #include <dtop.h>
69 #if NDTOP > 0
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/ioctl.h>
73 #include <sys/tty.h>
74 #include <sys/proc.h>
75 #include <sys/map.h>
76 #include <sys/buf.h>
77 #include <sys/conf.h>
78 #include <sys/file.h>
79 #include <sys/uio.h>
80 #include <sys/kernel.h>
81 #include <sys/syslog.h>
82 
83 #include <machine/pmioctl.h>
84 #include <machine/machConst.h>
85 #include <machine/dc7085cons.h>
86 
87 #include <pmax/pmax/pmaxtype.h>
88 #include <pmax/pmax/maxine.h>
89 #include <pmax/pmax/asic.h>
90 
91 #include <pmax/dev/device.h>
92 #include <pmax/dev/dtopreg.h>
93 #include <pmax/dev/fbreg.h>
94 
95 extern int pmax_boardtype;
96 
97 extern int ttrstrt	__P((void *));
98 void dtop_keyboard_repeat	__P((void *));
99 int dtop_null_device_handler	__P((dtop_device_t, dtop_message_t, int, int));
100 int dtop_locator_handler	__P((dtop_device_t, dtop_message_t, int, int));
101 int dtop_keyboard_handler	__P((dtop_device_t, dtop_message_t, int, int));
102 int dtopparam		__P((struct tty *, struct termios *));
103 int dtopstop		__P((struct tty *, int));
104 void dtopstart		__P((struct tty *));
105 void dtopKBDPutc	__P((dev_t, int));
106 
107 struct	tty dtop_tty[NDTOP];
108 void	(*dtopDivertXInput)();	/* X windows keyboard input routine */
109 void	(*dtopMouseEvent)();	/* X windows mouse motion event routine */
110 void	(*dtopMouseButtons)();	/* X windows mouse buttons event routine */
111 
112 #define	DTOP_MAX_POLL	0x7fff		/* about half a sec */
113 
114 typedef volatile unsigned int	*data_reg_t;	/* uC  */
115 #define	DTOP_GET_BYTE(data)	(((*(data)) >> 8) & 0xff)
116 #define	DTOP_PUT_BYTE(data,c)	{ *(data) = (c) << 8; }
117 
118 typedef volatile unsigned int	*poll_reg_t;	/* SIR */
119 #define	DTOP_RX_AVAIL(poll)	(*(poll) & 1)
120 #define	DTOP_TX_AVAIL(poll)	(*(poll) & 2)
121 
122 #define	GET_SHORT(b0,b1)	(((b0)<<8)|(b1))
123 
124 /*
125  * Driver status
126  */
127 struct dtop_softc {
128 	data_reg_t	data;
129 	poll_reg_t	poll;
130 	char		polling_mode;
131 	char		probed_once;
132 	short		bad_pkts;
133 
134 	struct dtop_ds {
135 		int		(*handler)();
136 		dtop_device	status;
137 	} device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
138 
139 #	define	DTOP_DEVICE_NO(address)	(((address)-DTOP_ADDR_FIRST)>>1)
140 
141 } dtop_softc[NDTOP];
142 
143 typedef struct dtop_softc *dtop_softc_t;
144 struct tty dtop_tty[NDTOP];
145 
146 /*
147  * lk201 keyboard divisions and up/down mode key bitmap.
148  */
149 #define NUMDIVS 14
150 static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6,
151 				 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e};
152 static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8,
153 				 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87};
154 /*
155  * Initial defaults, groups 5 and 6 are up/down
156  */
157 static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0};
158 
159 /*
160  * Definition of the driver for the auto-configuration program.
161  */
162 int	dtopprobe();
163 void	dtopintr();
164 struct	driver dtopdriver =  {
165 	"dtop", dtopprobe, 0, 0, dtopintr,
166 };
167 
168 dtopprobe(cp)
169 	struct pmax_ctlr *cp;
170 {
171 	register struct tty *tp;
172 	register int cntr;
173 	int dtopunit = cp->pmax_unit, i, s;
174 	dtop_softc_t dtop;
175 
176 	if (dtopunit >= NDTOP)
177 		return (0);
178 	if (badaddr(cp->pmax_addr, 2))
179 		return (0);
180 	dtop = &dtop_softc[dtopunit];
181 
182 	dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
183 	dtop->data = (data_reg_t)cp->pmax_addr;
184 
185 	for (i = 0; i < DTOP_MAX_DEVICES; i++)
186 		dtop->device[i].handler = dtop_null_device_handler;
187 
188 	/* a lot more needed here, fornow: */
189 	dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
190 	dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
191 	dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state =
192 		K_AR_IDLE;
193 
194 	dtop->probed_once = 1;
195 	printf("dtop%d at nexus0 csr 0x%x priority %d\n",
196 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
197 	return (1);
198 }
199 
200 dtopopen(dev, flag, mode, p)
201 	dev_t dev;
202 	int flag, mode;
203 	struct proc *p;
204 {
205 	register struct tty *tp;
206 	register int unit;
207 	int s, error = 0;
208 
209 	unit = minor(dev);
210 	if (unit >= NDTOP)
211 		return (ENXIO);
212 	tp = &dtop_tty[unit];
213 	tp->t_oproc = dtopstart;
214 	tp->t_param = dtopparam;
215 	tp->t_dev = dev;
216 	if ((tp->t_state & TS_ISOPEN) == 0) {
217 		tp->t_state |= TS_WOPEN;
218 		ttychars(tp);
219 		if (tp->t_ispeed == 0) {
220 			tp->t_iflag = TTYDEF_IFLAG;
221 			tp->t_oflag = TTYDEF_OFLAG;
222 			tp->t_cflag = TTYDEF_CFLAG;
223 			tp->t_lflag = TTYDEF_LFLAG;
224 			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
225 		}
226 		(void) dtopparam(tp, &tp->t_termios);
227 		ttsetwater(tp);
228 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
229 		return (EBUSY);
230 	s = spltty();
231 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
232 	       !(tp->t_state & TS_CARR_ON)) {
233 		tp->t_state |= TS_WOPEN;
234 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
235 		    ttopen, 0))
236 			break;
237 	}
238 	splx(s);
239 	if (error)
240 		return (error);
241 	error = (*linesw[tp->t_line].l_open)(dev, tp);
242 	return (error);
243 }
244 
245 /*ARGSUSED*/
246 dtopclose(dev, flag, mode, p)
247 	dev_t dev;
248 	int flag, mode;
249 	struct proc *p;
250 {
251 	register struct tty *tp;
252 	register int unit;
253 
254 	unit = minor(dev);
255 	tp = &dtop_tty[unit];
256 	(*linesw[tp->t_line].l_close)(tp, flag);
257 	return (ttyclose(tp));
258 }
259 
260 dtopread(dev, uio, flag)
261 	dev_t dev;
262 	struct uio *uio;
263 {
264 	register struct tty *tp;
265 
266 	tp = &dtop_tty[minor(dev)];
267 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
268 }
269 
270 dtopwrite(dev, uio, flag)
271 	dev_t dev;
272 	struct uio *uio;
273 {
274 	register struct tty *tp;
275 
276 	tp = &dtop_tty[minor(dev)];
277 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
278 }
279 
280 /*ARGSUSED*/
281 dtopioctl(dev, cmd, data, flag, p)
282 	dev_t dev;
283 	int cmd;
284 	caddr_t data;
285 	int flag;
286 	struct proc *p;
287 {
288 	register struct tty *tp;
289 	register int unit = minor(dev);
290 	int error;
291 
292 	tp = &dtop_tty[unit];
293 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
294 	if (error >= 0)
295 		return (error);
296 	error = ttioctl(tp, cmd, data, flag);
297 	if (error >= 0)
298 		return (error);
299 
300 	switch (cmd) {
301 
302 	case TIOCSBRK:
303 		ttyoutput(0, tp);
304 		break;
305 
306 	case TIOCCBRK:
307 		ttyoutput(0, tp);
308 		break;
309 
310 	case TIOCMGET:
311 		*(int *)data = DML_DTR | DML_DSR | DML_CAR;
312 		break;
313 
314 	default:
315 		return (ENOTTY);
316 	}
317 	return (0);
318 }
319 
320 /*
321  * Interrupt routine
322  */
323 void
324 dtopintr(unit)
325 	int unit;
326 {
327 	dtop_message msg;
328 	int devno;
329 	dtop_softc_t dtop;
330 
331 	dtop = &dtop_softc[unit];
332 	if (dtop_get_packet(dtop, &msg) < 0) {
333 #ifdef DIAGNOSTIC
334 	    printf("dtop: overrun (or stray)\n");
335 #endif
336 	    /*
337 	     * Ugh! The most common occurrence of a data overrun is upon a
338 	     * key press and the result is a software generated "stuck key".
339 	     * All I can think to do is fake an "all keys up" whenever a
340 	     * data overrun occurs.
341 	     */
342 	    msg.src_address = 0x6c;
343 	    msg.code.val.len = 1;
344 	    msg.body[0] = DTOP_KBD_EMPTY;
345 	}
346 
347 	/*
348 	 * If not probed yet, just throw the data away.
349 	 */
350 	if (!dtop->probed_once)
351 		return;
352 
353 	devno = DTOP_DEVICE_NO(msg.src_address);
354 	if (devno < 0 || devno > 15)
355 		return;
356 	(void) (*dtop->device[devno].handler)
357 			(&dtop->device[devno].status, &msg,
358 			 DTOP_EVENT_RECEIVE_PACKET, 0);
359 }
360 
361 void
362 dtopstart(tp)
363 	register struct tty *tp;
364 {
365 	register int cc;
366 	int s;
367 
368 	s = spltty();
369 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
370 		goto out;
371 	if (tp->t_outq.c_cc <= tp->t_lowat) {
372 		if (tp->t_state & TS_ASLEEP) {
373 			tp->t_state &= ~TS_ASLEEP;
374 			wakeup((caddr_t)&tp->t_outq);
375 		}
376 		selwakeup(&tp->t_wsel);
377 	}
378 	if (tp->t_outq.c_cc == 0)
379 		goto out;
380 	/* handle console specially */
381 	if (tp == dtop_tty) {
382 		while (tp->t_outq.c_cc > 0) {
383 			cc = getc(&tp->t_outq) & 0x7f;
384 			cnputc(cc);
385 		}
386 		/*
387 		 * After we flush the output queue we may need to wake
388 		 * up the process that made the output.
389 		 */
390 		if (tp->t_outq.c_cc <= tp->t_lowat) {
391 			if (tp->t_state & TS_ASLEEP) {
392 				tp->t_state &= ~TS_ASLEEP;
393 				wakeup((caddr_t)&tp->t_outq);
394 			}
395 			selwakeup(&tp->t_wsel);
396 		}
397 	}
398 out:
399 	splx(s);
400 }
401 
402 void
403 dtopKBDPutc(dev, c)
404 	dev_t dev;
405 	int c;
406 {
407 	register int i;
408 	static int param = 0, cmd, mod, typ;
409 	static u_char parms[2];
410 
411 	/*
412 	 * Emulate the lk201 command codes.
413 	 */
414 	if (param == 0) {
415 		typ = (c & 0x1);
416 		cmd = ((c >> 3) & 0xf);
417 		mod = ((c >> 1) & 0x3);
418 	} else
419 		parms[param - 1] = (c & 0x7f);
420 	if (c & 0x80) {
421 		if (typ) {
422 			/*
423 			 * A peripheral command code. Someday this driver
424 			 * should know how to send commands to the lk501,
425 			 * but until then this is all essentially a no-op.
426 			 */
427 			;
428 		} else {
429 			/*
430 			 * Set modes. These have to be emulated in software.
431 			 */
432 			if (cmd > 0 && cmd < 15) {
433 				cmd--;
434 				if (mod & 0x2)
435 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
436 					keymodes[i >> 5] |=
437 						(1 << (i & 0x1f));
438 				else
439 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
440 					keymodes[i >> 5] &=
441 						~(1 << (i & 0x1f));
442 			}
443 		}
444 		param = 0;
445 	} else if (++param > 2)
446 		param = 2;
447 }
448 
449 /*
450  * Take a packet off dtop interface
451  * A packet MUST be there, this is not checked for.
452  */
453 #define	DTOP_ESC_CHAR		0xf8
454 dtop_escape(c)
455 {
456 	/* I donno much about this stuff.. */
457 	switch (c) {
458 	case 0xe8:	return (0xf8);
459 	case 0xe9:	return (0xf9);
460 	case 0xea:	return (0xfa);
461 	case 0xeb:	return (0xfb);
462 	default:	/* printf("{esc %x}", c); */
463 			return (c);
464 	}
465 }
466 
467 dtop_get_packet(dtop, pkt)
468 	dtop_softc_t	dtop;
469 	dtop_message_t	pkt;
470 {
471 	register poll_reg_t	poll;
472 	register data_reg_t	data;
473 	register int		max, i, len;
474 	register unsigned char	c;
475 
476 	poll = dtop->poll;
477 	data = dtop->data;
478 
479 	/*
480 	 * The interface does not handle us the first byte,
481 	 * which is our address and cannot ever be anything
482 	 * else but 0x50.  This is a good thing, it makes
483 	 * the average packet exactly one word long, too.
484 	 */
485 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
486 		DELAY(1);
487 	if (max == DTOP_MAX_POLL)
488 		goto bad;
489 	pkt->src_address = DTOP_GET_BYTE(data);
490 
491 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
492 		DELAY(1);
493 	if (max == DTOP_MAX_POLL)
494 		goto bad;
495 	pkt->code.bits = DTOP_GET_BYTE(data);
496 
497 	/*
498 	 * Now get data and checksum
499 	 */
500 	len = pkt->code.val.len + 1;
501 	c = 0;
502 	for (i = 0; i < len; i++) {
503 again:
504 		for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
505 			DELAY(1);
506 		if (max == DTOP_MAX_POLL)
507 			goto bad;
508 		if (c == DTOP_ESC_CHAR) {
509 			c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
510 		} else {
511 			c = DTOP_GET_BYTE(data);
512 			if (c == DTOP_ESC_CHAR)
513 				goto again;
514 		}
515 		pkt->body[i] = c;
516 	}
517 	return (len);
518 bad:
519 	dtop->bad_pkts++;
520 	return (-1);
521 }
522 
523 /*
524  * Get a keyboard char for the console
525  */
526 dtopKBDGetc()
527 {
528 	register int c;
529 	dtop_softc_t dtop;
530 
531 	dtop = &dtop_softc[0];
532 again:
533 	c = -1;
534 
535 	/*
536 	 * Now check keyboard
537 	 */
538 	if (DTOP_RX_AVAIL(dtop->poll)) {
539 
540 		dtop_message	msg;
541 		struct dtop_ds	*ds;
542 
543 		if (dtop_get_packet(dtop, &msg) >= 0) {
544 
545 		    ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
546 		    if (ds->handler == dtop_keyboard_handler) {
547 
548 			c = dtop_keyboard_handler(
549 					&ds->status, &msg,
550 					DTOP_EVENT_RECEIVE_PACKET, -1);
551 
552 			if (c > 0) return c;
553 
554 			c = -1;
555 		    }
556 		}
557 	}
558 
559 	if (c == -1) {
560 		DELAY(100);
561 		goto again;
562 	}
563 
564 	return c;
565 }
566 
567 int
568 dtopparam(tp, t)
569 	struct tty *tp;
570 	struct termios *t;
571 {
572 	if (tp->t_ispeed == 0)
573 		ttymodem(tp, 0);
574 	else
575 		/* called too early to invoke ttymodem, sigh */
576 		tp->t_state |= TS_CARR_ON;
577 	return (0);
578 }
579 
580 /*
581  * Stop output on a line.
582  */
583 /*ARGSUSED*/
584 dtopstop(tp, flag)
585 	register struct tty *tp;
586 	int flag;
587 {
588 	int s;
589 
590 	s = spltty();
591 	if (tp->t_state & TS_BUSY) {
592 		if (!(tp->t_state & TS_TTSTOP))
593 			tp->t_state |= TS_FLUSH;
594 	}
595 	splx(s);
596 }
597 
598 /*
599  * Default handler function
600  */
601 int
602 dtop_null_device_handler(dev, msg, event, outc)
603 	 dtop_device_t	dev;
604 	 dtop_message_t	msg;
605 	 int		event;
606 	 int		outc;
607 {
608 	/* See if the message was to the default address (powerup) */
609 
610 	/* Uhmm, donno how to handle this. Drop it */
611 	if (event == DTOP_EVENT_RECEIVE_PACKET)
612 		dev->unknown_report = *msg;
613 	return 0;
614 }
615 
616 /*
617  * Handler for locator devices (mice)
618  */
619 int
620 dtop_locator_handler(dev, msg, event, outc)
621 	 dtop_device_t	dev;
622 	 dtop_message_t	msg;
623 	 int		event;
624 	 int		outc;
625 {
626 	register unsigned short	buttons;
627 	register short coord;
628 	register int moved = 0;
629 	static MouseReport currentRep;
630 	register MouseReport *mrp = &currentRep;
631 
632 	if (dtopMouseButtons) {
633 		mrp->state = 0;
634 		/*
635 		 * Do the position first
636 		 */
637 		coord = GET_SHORT(msg->body[2], msg->body[3]);
638 		if (coord < 0) {
639 			coord = -coord;
640 			moved = 1;
641 		} else if (coord > 0) {
642 			mrp->state |= MOUSE_X_SIGN;
643 			moved = 1;
644 		}
645 		mrp->dx = (coord & 0x1f);
646 		coord = GET_SHORT(msg->body[4], msg->body[5]);
647 		if (coord < 0) {
648 			coord = -coord;
649 			moved = 1;
650 		} else if (coord > 0) {
651 			mrp->state |= MOUSE_Y_SIGN;
652 			moved = 1;
653 		}
654 		mrp->dy = (coord & 0x1f);
655 
656 		/*
657 		 * Time for the buttons now
658 		 * Shuffle button bits around to serial mouse order.
659 		 */
660 		buttons = GET_SHORT(msg->body[0], msg->body[1]);
661 		mrp->state |= (((buttons >> 1) & 0x3) | ((buttons << 2) & 0x4));
662 		if (moved)
663 			(*dtopMouseEvent)(mrp);
664 		(*dtopMouseButtons)(mrp);
665 	}
666 	return (0);
667 }
668 
669 /*
670  * Handler for keyboard devices
671  * Special case: outc set for recv packet means
672  * we are inside the kernel debugger
673  */
674 int
675 dtop_keyboard_handler(dev, msg, event, outc)
676 	dtop_device_t dev;
677 	dtop_message_t msg;
678 	int event;
679 	int outc;
680 {
681 	register u_char *ls, *le, *ns, *ne;
682 	u_char save[11], retc;
683 	int msg_len, c, s;
684 	struct tty *tp = &dtop_tty[0];
685 
686 	/*
687 	 * Fiddle about emulating an lk201 keyboard. The lk501
688 	 * designers carefully ensured that keyboard handlers could be
689 	 * stateless, then we turn around and use lots of state to
690 	 * emulate the stateful lk201, since the X11R5 X servers
691 	 * only know about the lk201... (oh well)
692 	 */
693 	/*
694 	 * Turn off any autorepeat timeout.
695 	 */
696 	s = splhigh();
697 	if (dev->keyboard.k_ar_state != K_AR_IDLE) {
698 		dev->keyboard.k_ar_state = K_AR_IDLE;
699 		untimeout(dtop_keyboard_repeat, (void *)dev);
700 	}
701 	splx(s);
702 	msg_len = msg->code.val.len;
703 
704 	/* Check for errors */
705 	c = msg->body[0];
706 	if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
707 		printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
708 #ifdef notdef
709 		if (c != DTOP_KBD_OUT_ERR) return -1;
710 #endif
711 		/*
712 		 * Fake an "all ups" to avoid the stuck key syndrome.
713 		 */
714 		c = msg->body[0] = DTOP_KBD_EMPTY;
715 		msg_len = 1;
716 	}
717 
718 	dev->keyboard.last_msec = TO_MS(time);
719 	/*
720 	 * To make things readable, do a first pass cancelling out
721 	 * all keys that are still pressed, and a second one generating
722 	 * events.  While generating events, do the upstrokes first
723 	 * from oldest to youngest, then the downstrokes from oldest
724 	 * to youngest.  This copes with lost packets and provides
725 	 * a reasonable model even if scans are too slow.
726 	 */
727 
728 	/* make a copy of new state first */
729 	if (msg_len == 1)
730 		save[0] = msg->body[0];
731 	else if (msg_len > 0)
732 		bcopy(msg->body, save, msg_len);
733 
734 	/*
735 	 * Cancel out any keys in both the last and current message as
736 	 * they are unchanged.
737 	 */
738 	if (msg_len > 0 && dev->keyboard.last_codes_count > 0) {
739 		ls = dev->keyboard.last_codes;
740 		le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count];
741 		ne = &msg->body[msg_len];
742 		for (; ls < le; ls++) {
743 			for (ns = msg->body; ns < ne; ns++)
744 				if (*ls == *ns) {
745 					*ls = *ns = 0;
746 					break;
747 				}
748 		}
749 	}
750 
751 	/*
752 	 * Now generate all upstrokes
753 	 */
754 	le = dev->keyboard.last_codes;
755 	ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
756 	for ( ; ls >= le; ls--)
757 	    if (c = *ls) {
758 		(void) kbdMapChar(c);
759 
760 		if (outc == 0 && dtopDivertXInput &&
761 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))))
762 			(*dtopDivertXInput)(c);
763 	    }
764 	/*
765 	 * And finally the downstrokes
766 	 */
767 	ne = (char*)msg->body;
768 	ns = (char*)&msg->body[msg_len - 1];
769 	retc = 0;
770 	for ( ; ns >= ne; ns--)
771 	    if (*ns) {
772 		c = kbdMapChar(*ns);
773 		if (outc == 0) {
774 		    if (dtopDivertXInput) {
775 			(*dtopDivertXInput)(*ns);
776 			c = -1; /* consumed by X */
777 		    } else if (c >= 0)
778 			(*linesw[tp->t_line].l_rint)(c, tp);
779 		    dev->keyboard.k_ar_state = K_AR_ACTIVE;
780 		}
781 		/* return the related keycode anyways */
782 		if ((c >= 0) && (retc == 0))
783 		    retc = c;
784 	    }
785 	outc = retc;
786 	/* install new scan state */
787 	if (msg_len == 1)
788 		dev->keyboard.last_codes[0] = save[0];
789 	else if (msg_len > 0)
790 		bcopy(save, dev->keyboard.last_codes, msg_len);
791 	dev->keyboard.last_codes_count = msg_len;
792 	if (dev->keyboard.k_ar_state == K_AR_ACTIVE)
793 		timeout(dtop_keyboard_repeat, (void *)dev, hz / 2);
794 	return (outc);
795 }
796 
797 /*
798  * Do an autorepeat as required.
799  */
800 void
801 dtop_keyboard_repeat(arg)
802 	void *arg;
803 {
804 	dtop_device_t dev = (dtop_device_t)arg;
805 	register int i, c;
806 	struct tty *tp = dtop_tty;
807 	int s = spltty(), gotone = 0;
808 
809 	for (i = 0; i < dev->keyboard.last_codes_count; i++) {
810 		c = (int)dev->keyboard.last_codes[i];
811 		if (c != DTOP_KBD_EMPTY &&
812 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) {
813 			dev->keyboard.k_ar_state = K_AR_TRIGGER;
814 			if (dtopDivertXInput) {
815 				(*dtopDivertXInput)(KEY_REPEAT);
816 				gotone = 1;
817 				continue;
818 			}
819 
820 			if ((c = kbdMapChar(KEY_REPEAT)) >= 0) {
821 				(*linesw[tp->t_line].l_rint)(c, tp);
822 				gotone = 1;
823 			}
824 		}
825 	}
826 	if (gotone)
827 		timeout(dtop_keyboard_repeat, arg, hz / 20);
828 	else
829 		dev->keyboard.k_ar_state = K_AR_IDLE;
830 	splx(s);
831 }
832 #endif
833