xref: /csrg-svn/sys/pmax/dev/dtop.c (revision 57234)
156813Sralph /*-
256813Sralph  * Copyright (c) 1992 The Regents of the University of California.
356813Sralph  * All rights reserved.
456813Sralph  *
556813Sralph  * This code is derived from software contributed to Berkeley by
656813Sralph  * Ralph Campbell and Rick Macklem.
756813Sralph  *
856813Sralph  * %sccs.include.redist.c%
956813Sralph  *
10*57234Sralph  *	@(#)dtop.c	7.2 (Berkeley) 12/20/92
1156813Sralph  */
1256813Sralph 
1356813Sralph /*
1456813Sralph  * Mach Operating System
1556813Sralph  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
1656813Sralph  * All Rights Reserved.
1756813Sralph  *
1856813Sralph  * Permission to use, copy, modify and distribute this software and its
1956813Sralph  * documentation is hereby granted, provided that both the copyright
2056813Sralph  * notice and this permission notice appear in all copies of the
2156813Sralph  * software, derivative works or modified versions, and any portions
2256813Sralph  * thereof, and that both notices appear in supporting documentation.
2356813Sralph  *
2456813Sralph  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
2556813Sralph  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
2656813Sralph  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
2756813Sralph  *
2856813Sralph  * Carnegie Mellon requests users of this software to return to
2956813Sralph  *
3056813Sralph  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
3156813Sralph  *  School of Computer Science
3256813Sralph  *  Carnegie Mellon University
3356813Sralph  *  Pittsburgh PA 15213-3890
3456813Sralph  *
3556813Sralph  * any improvements or extensions that they make and grant Carnegie the
3656813Sralph  * rights to redistribute these changes.
3756813Sralph  */
3856813Sralph /*
3956813Sralph  * 	Author: Alessandro Forin, Carnegie Mellon University
4056813Sralph  *
4156813Sralph  *	Hardware-level operations for the Desktop serial line
4256813Sralph  *	bus (i2c aka ACCESS).
4356813Sralph  */
44*57234Sralph /************************************************************
45*57234Sralph Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
46*57234Sralph and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4756813Sralph 
48*57234Sralph                         All Rights Reserved
49*57234Sralph 
50*57234Sralph Permission to use, copy, modify, and distribute this software and its
51*57234Sralph documentation for any purpose and without fee is hereby granted,
52*57234Sralph provided that the above copyright notice appear in all copies and that
53*57234Sralph both that copyright notice and this permission notice appear in
54*57234Sralph supporting documentation, and that the names of Digital or MIT not be
55*57234Sralph used in advertising or publicity pertaining to distribution of the
56*57234Sralph software without specific, written prior permission.
57*57234Sralph 
58*57234Sralph DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
59*57234Sralph ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
60*57234Sralph DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61*57234Sralph ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
62*57234Sralph WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
63*57234Sralph ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
64*57234Sralph SOFTWARE.
65*57234Sralph 
66*57234Sralph ********************************************************/
67*57234Sralph 
6856813Sralph #include <dtop.h>
6956813Sralph #if NDTOP > 0
7056813Sralph #include <sys/param.h>
7156813Sralph #include <sys/systm.h>
7256813Sralph #include <sys/ioctl.h>
7356813Sralph #include <sys/tty.h>
7456813Sralph #include <sys/proc.h>
7556813Sralph #include <sys/map.h>
7656813Sralph #include <sys/buf.h>
7756813Sralph #include <sys/conf.h>
7856813Sralph #include <sys/file.h>
7956813Sralph #include <sys/uio.h>
8056813Sralph #include <sys/kernel.h>
8156813Sralph #include <sys/syslog.h>
8256813Sralph 
8356813Sralph #include <machine/pmioctl.h>
8456813Sralph #include <machine/machConst.h>
8556813Sralph #include <machine/dc7085cons.h>
8656813Sralph 
8756813Sralph #include <pmax/pmax/pmaxtype.h>
8856813Sralph #include <pmax/pmax/maxine.h>
8956813Sralph #include <pmax/pmax/asic.h>
9056813Sralph 
9156813Sralph #include <pmax/dev/device.h>
9256813Sralph #include <pmax/dev/dtopreg.h>
9356813Sralph #include <pmax/dev/fbreg.h>
9456813Sralph 
9556813Sralph extern int pmax_boardtype;
9656813Sralph 
9756813Sralph extern int ttrstrt	__P((void *));
9856813Sralph void dtop_keyboard_autorepeat	__P((void *));
9956813Sralph int dtop_null_device_handler	__P((dtop_device_t, dtop_message_t, int, int));
10056813Sralph int dtop_locator_handler	__P((dtop_device_t, dtop_message_t, int, int));
10156813Sralph int dtop_keyboard_handler	__P((dtop_device_t, dtop_message_t, int, int));
10256813Sralph int dtopparam		__P((struct tty *, struct termios *));
10356813Sralph int dtopstop		__P((struct tty *, int));
10456813Sralph void dtopstart		__P((struct tty *));
10556813Sralph void dtopKBDPutc	__P((dev_t, int));
106*57234Sralph static void dtop_keyboard_repeat __P((dtop_device_t));
10756813Sralph 
10856813Sralph struct	tty dtop_tty[NDTOP];
10956813Sralph void	(*dtopDivertXInput)();	/* X windows keyboard input routine */
11056813Sralph void	(*dtopMouseEvent)();	/* X windows mouse motion event routine */
11156813Sralph void	(*dtopMouseButtons)();	/* X windows mouse buttons event routine */
11256813Sralph 
11356813Sralph #define	DTOP_MAX_POLL	0x7fff		/* about half a sec */
11456813Sralph 
11556813Sralph typedef volatile unsigned int	*data_reg_t;	/* uC  */
11656813Sralph #define	DTOP_GET_BYTE(data)	(((*(data)) >> 8) & 0xff)
11756813Sralph #define	DTOP_PUT_BYTE(data,c)	{ *(data) = (c) << 8; }
11856813Sralph 
11956813Sralph typedef volatile unsigned int	*poll_reg_t;	/* SIR */
12056813Sralph #define	DTOP_RX_AVAIL(poll)	(*(poll) & 1)
12156813Sralph #define	DTOP_TX_AVAIL(poll)	(*(poll) & 2)
12256813Sralph 
12356813Sralph #define	GET_SHORT(b0,b1)	(((b0)<<8)|(b1))
12456813Sralph 
12556813Sralph /*
12656813Sralph  * Driver status
12756813Sralph  */
12856813Sralph struct dtop_softc {
12956813Sralph 	data_reg_t	data;
13056813Sralph 	poll_reg_t	poll;
13156813Sralph 	char		polling_mode;
13256813Sralph 	char		probed_once;
13356813Sralph 	short		bad_pkts;
13456813Sralph 
13556813Sralph 	struct dtop_ds {
13656813Sralph 		int		(*handler)();
13756813Sralph 		dtop_device	status;
13856813Sralph 	} device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
13956813Sralph 
14056813Sralph #	define	DTOP_DEVICE_NO(address)	(((address)-DTOP_ADDR_FIRST)>>1)
14156813Sralph 
14256813Sralph } dtop_softc[NDTOP];
14356813Sralph 
14456813Sralph typedef struct dtop_softc *dtop_softc_t;
14556813Sralph struct tty dtop_tty[NDTOP];
14656813Sralph 
14756813Sralph /*
148*57234Sralph  * lk201 keyboard divisions and up/down mode key bitmap.
149*57234Sralph  */
150*57234Sralph #define NUMDIVS 14
151*57234Sralph static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6,
152*57234Sralph 				 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e};
153*57234Sralph static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8,
154*57234Sralph 				 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87};
155*57234Sralph /*
156*57234Sralph  * Initial defaults, groups 5 and 6 are up/down
157*57234Sralph  */
158*57234Sralph static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0};
159*57234Sralph 
160*57234Sralph /*
16156813Sralph  * Definition of the driver for the auto-configuration program.
16256813Sralph  */
16356813Sralph int	dtopprobe();
16456813Sralph void	dtopintr();
16556813Sralph struct	driver dtopdriver =  {
16656813Sralph 	"dtop", dtopprobe, 0, 0, dtopintr,
16756813Sralph };
16856813Sralph 
16956813Sralph dtopprobe(cp)
17056813Sralph 	struct pmax_ctlr *cp;
17156813Sralph {
17256813Sralph 	register struct tty *tp;
17356813Sralph 	register int cntr;
17456813Sralph 	int dtopunit = cp->pmax_unit, i, s;
17556813Sralph 	dtop_softc_t dtop;
17656813Sralph 
17756813Sralph 	if (dtopunit >= NDTOP)
17856813Sralph 		return (0);
17956813Sralph 	if (badaddr(cp->pmax_addr, 2))
18056813Sralph 		return (0);
18156813Sralph 	dtop = &dtop_softc[dtopunit];
18256813Sralph 
18356813Sralph 	dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
18456813Sralph 	dtop->data = (data_reg_t)cp->pmax_addr;
18556813Sralph 
18656813Sralph 	for (i = 0; i < DTOP_MAX_DEVICES; i++)
18756813Sralph 		dtop->device[i].handler = dtop_null_device_handler;
18856813Sralph 
18956813Sralph 	/* a lot more needed here, fornow: */
19056813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
19156813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
19256813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.poll_frequency =
19356813Sralph 		(hz * 5) / 100; /* x0.01 secs */
19456813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state =
19556813Sralph 		K_AR_IDLE;
19656813Sralph 
19756813Sralph 	/*
19856813Sralph 	 * Sometimes a first interrupt gets lost, so just in case
19956813Sralph 	 * poke it now.
20056813Sralph 	 */
20156813Sralph 	dtopintr(dtopunit);
202*57234Sralph 	dtop->probed_once = 1;
203*57234Sralph 	printf("dtop%d at nexus0 csr 0x%x priority %d\n",
204*57234Sralph 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
20556813Sralph 	return (1);
20656813Sralph }
20756813Sralph 
20856813Sralph dtopopen(dev, flag, mode, p)
20956813Sralph 	dev_t dev;
21056813Sralph 	int flag, mode;
21156813Sralph 	struct proc *p;
21256813Sralph {
21356813Sralph 	register struct tty *tp;
21456813Sralph 	register int unit;
21556813Sralph 	int s, error = 0;
21656813Sralph 
21756813Sralph 	unit = minor(dev);
21856813Sralph 	if (unit >= NDTOP)
21956813Sralph 		return (ENXIO);
22056813Sralph 	tp = &dtop_tty[unit];
22156813Sralph 	tp->t_oproc = dtopstart;
22256813Sralph 	tp->t_param = dtopparam;
22356813Sralph 	tp->t_dev = dev;
22456813Sralph 	if ((tp->t_state & TS_ISOPEN) == 0) {
22556813Sralph 		tp->t_state |= TS_WOPEN;
22656813Sralph 		ttychars(tp);
22756813Sralph 		if (tp->t_ispeed == 0) {
22856813Sralph 			tp->t_iflag = TTYDEF_IFLAG;
22956813Sralph 			tp->t_oflag = TTYDEF_OFLAG;
23056813Sralph 			tp->t_cflag = TTYDEF_CFLAG;
23156813Sralph 			tp->t_lflag = TTYDEF_LFLAG;
23256813Sralph 			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
23356813Sralph 		}
23456813Sralph 		(void) dtopparam(tp, &tp->t_termios);
23556813Sralph 		ttsetwater(tp);
23656813Sralph 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
23756813Sralph 		return (EBUSY);
23856813Sralph 	s = spltty();
23956813Sralph 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
24056813Sralph 	       !(tp->t_state & TS_CARR_ON)) {
24156813Sralph 		tp->t_state |= TS_WOPEN;
24256813Sralph 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
24356813Sralph 		    ttopen, 0))
24456813Sralph 			break;
24556813Sralph 	}
24656813Sralph 	splx(s);
24756813Sralph 	if (error)
24856813Sralph 		return (error);
24956813Sralph 	error = (*linesw[tp->t_line].l_open)(dev, tp);
25056813Sralph 	return (error);
25156813Sralph }
25256813Sralph 
25356813Sralph /*ARGSUSED*/
25456813Sralph dtopclose(dev, flag, mode, p)
25556813Sralph 	dev_t dev;
25656813Sralph 	int flag, mode;
25756813Sralph 	struct proc *p;
25856813Sralph {
25956813Sralph 	register struct tty *tp;
26056813Sralph 	register int unit;
26156813Sralph 
26256813Sralph 	unit = minor(dev);
26356813Sralph 	tp = &dtop_tty[unit];
26456813Sralph 	(*linesw[tp->t_line].l_close)(tp, flag);
26556813Sralph 	return (ttyclose(tp));
26656813Sralph }
26756813Sralph 
26856813Sralph dtopread(dev, uio, flag)
26956813Sralph 	dev_t dev;
27056813Sralph 	struct uio *uio;
27156813Sralph {
27256813Sralph 	register struct tty *tp;
27356813Sralph 
27456813Sralph 	tp = &dtop_tty[minor(dev)];
27556813Sralph 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
27656813Sralph }
27756813Sralph 
27856813Sralph dtopwrite(dev, uio, flag)
27956813Sralph 	dev_t dev;
28056813Sralph 	struct uio *uio;
28156813Sralph {
28256813Sralph 	register struct tty *tp;
28356813Sralph 
28456813Sralph 	tp = &dtop_tty[minor(dev)];
28556813Sralph 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
28656813Sralph }
28756813Sralph 
28856813Sralph /*ARGSUSED*/
28956813Sralph dtopioctl(dev, cmd, data, flag, p)
29056813Sralph 	dev_t dev;
29156813Sralph 	int cmd;
29256813Sralph 	caddr_t data;
29356813Sralph 	int flag;
29456813Sralph 	struct proc *p;
29556813Sralph {
29656813Sralph 	register struct tty *tp;
29756813Sralph 	register int unit = minor(dev);
29856813Sralph 	int error;
29956813Sralph 
30056813Sralph 	tp = &dtop_tty[unit];
30156813Sralph 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
30256813Sralph 	if (error >= 0)
30356813Sralph 		return (error);
30456813Sralph 	error = ttioctl(tp, cmd, data, flag);
30556813Sralph 	if (error >= 0)
30656813Sralph 		return (error);
30756813Sralph 
30856813Sralph 	switch (cmd) {
30956813Sralph 
31056813Sralph 	case TIOCSBRK:
31156813Sralph 		ttyoutput(0, tp);
31256813Sralph 		break;
31356813Sralph 
31456813Sralph 	case TIOCCBRK:
31556813Sralph 		ttyoutput(0, tp);
31656813Sralph 		break;
31756813Sralph 
31856813Sralph 	case TIOCMGET:
31956813Sralph 		*(int *)data = DML_DTR | DML_DSR | DML_CAR;
32056813Sralph 		break;
32156813Sralph 
32256813Sralph 	default:
32356813Sralph 		return (ENOTTY);
32456813Sralph 	}
32556813Sralph 	return (0);
32656813Sralph }
32756813Sralph 
32856813Sralph /*
32956813Sralph  * Interrupt routine
33056813Sralph  */
33156813Sralph void
33256813Sralph dtopintr(unit)
33356813Sralph 	int unit;
33456813Sralph {
33556813Sralph 	dtop_message msg;
33656813Sralph 	int devno;
33756813Sralph 	dtop_softc_t dtop;
33856813Sralph 
33956813Sralph 	dtop = &dtop_softc[unit];
34056813Sralph 	if (dtop_get_packet(dtop, &msg) < 0) {
341*57234Sralph 		if (dtop->probed_once)
34256813Sralph 			printf("%s", "dtop: overrun (or stray)\n");
34356813Sralph 		return;
34456813Sralph 	}
34556813Sralph 
34656813Sralph 	devno = DTOP_DEVICE_NO(msg.src_address);
34756813Sralph 	if (devno < 0 || devno > 15)
34856813Sralph 		return;
34956813Sralph 
35056813Sralph 	(void) (*dtop->device[devno].handler)
35156813Sralph 			(&dtop->device[devno].status, &msg,
35256813Sralph 			 DTOP_EVENT_RECEIVE_PACKET, 0);
35356813Sralph }
35456813Sralph 
35556813Sralph void
35656813Sralph dtopstart(tp)
35756813Sralph 	register struct tty *tp;
35856813Sralph {
35956813Sralph 	register int cc;
36056813Sralph 	int s;
36156813Sralph 
36256813Sralph 	s = spltty();
36356813Sralph 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
36456813Sralph 		goto out;
36556813Sralph 	if (tp->t_outq.c_cc <= tp->t_lowat) {
36656813Sralph 		if (tp->t_state & TS_ASLEEP) {
36756813Sralph 			tp->t_state &= ~TS_ASLEEP;
36856813Sralph 			wakeup((caddr_t)&tp->t_outq);
36956813Sralph 		}
37056813Sralph 		selwakeup(&tp->t_wsel);
37156813Sralph 	}
37256813Sralph 	if (tp->t_outq.c_cc == 0)
37356813Sralph 		goto out;
37456813Sralph 	/* handle console specially */
37556813Sralph 	if (tp == dtop_tty) {
37656813Sralph 		while (tp->t_outq.c_cc > 0) {
37756813Sralph 			cc = getc(&tp->t_outq) & 0x7f;
37856813Sralph 			cnputc(cc);
37956813Sralph 		}
38056813Sralph 		/*
38156813Sralph 		 * After we flush the output queue we may need to wake
38256813Sralph 		 * up the process that made the output.
38356813Sralph 		 */
38456813Sralph 		if (tp->t_outq.c_cc <= tp->t_lowat) {
38556813Sralph 			if (tp->t_state & TS_ASLEEP) {
38656813Sralph 				tp->t_state &= ~TS_ASLEEP;
38756813Sralph 				wakeup((caddr_t)&tp->t_outq);
38856813Sralph 			}
38956813Sralph 			selwakeup(&tp->t_wsel);
39056813Sralph 		}
39156813Sralph 	}
39256813Sralph out:
39356813Sralph 	splx(s);
39456813Sralph }
39556813Sralph 
39656813Sralph void
39756813Sralph dtopKBDPutc(dev, c)
39856813Sralph 	dev_t dev;
39956813Sralph 	int c;
40056813Sralph {
401*57234Sralph 	register int i;
402*57234Sralph 	static int param = 0, cmd, mod, typ;
403*57234Sralph 	static u_char parms[2];
40456813Sralph 
40556813Sralph 	/*
406*57234Sralph 	 * Emulate the lk201 command codes.
40756813Sralph 	 */
408*57234Sralph 	if (param == 0) {
409*57234Sralph 		typ = (c & 0x1);
410*57234Sralph 		cmd = ((c >> 3) & 0xf);
411*57234Sralph 		mod = ((c >> 1) & 0x3);
412*57234Sralph 	} else
413*57234Sralph 		parms[param - 1] = (c & 0x7f);
414*57234Sralph 	if (c & 0x80) {
415*57234Sralph 		if (typ) {
416*57234Sralph 			/*
417*57234Sralph 			 * A peripheral command code. Someday this driver
418*57234Sralph 			 * should know how to send commands to the lk501,
419*57234Sralph 			 * but until then this is all essentially a no-op.
420*57234Sralph 			 */
421*57234Sralph 			;
422*57234Sralph 		} else {
423*57234Sralph 			/*
424*57234Sralph 			 * Set modes. These have to be emulated in software.
425*57234Sralph 			 */
426*57234Sralph 			if (cmd > 0 && cmd < 15) {
427*57234Sralph 				cmd--;
428*57234Sralph 				if (mod & 0x2)
429*57234Sralph 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
430*57234Sralph 					keymodes[i >> 5] |=
431*57234Sralph 						(1 << (i & 0x1f));
432*57234Sralph 				else
433*57234Sralph 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
434*57234Sralph 					keymodes[i >> 5] &=
435*57234Sralph 						~(1 << (i & 0x1f));
436*57234Sralph 			}
437*57234Sralph 		}
438*57234Sralph 		param = 0;
439*57234Sralph 	} else if (++param > 2)
440*57234Sralph 		param = 2;
44156813Sralph }
44256813Sralph 
44356813Sralph /*
44456813Sralph  * Take a packet off dtop interface
44556813Sralph  * A packet MUST be there, this is not checked for.
44656813Sralph  */
44756813Sralph #define	DTOP_ESC_CHAR		0xf8
44856813Sralph dtop_escape(c)
44956813Sralph {
45056813Sralph 	/* I donno much about this stuff.. */
45156813Sralph 	switch (c) {
45256813Sralph 	case 0xe8:	return (0xf8);
45356813Sralph 	case 0xe9:	return (0xf9);
45456813Sralph 	case 0xea:	return (0xfa);
45556813Sralph 	case 0xeb:	return (0xfb);
45656813Sralph 	default:	/* printf("{esc %x}", c); */
45756813Sralph 			return (c);
45856813Sralph 	}
45956813Sralph }
46056813Sralph 
46156813Sralph dtop_get_packet(dtop, pkt)
46256813Sralph 	dtop_softc_t	dtop;
46356813Sralph 	dtop_message_t	pkt;
46456813Sralph {
46556813Sralph 	register poll_reg_t	poll;
46656813Sralph 	register data_reg_t	data;
46756813Sralph 	register int		max, i, len;
46856813Sralph 	register unsigned char	c;
46956813Sralph 
47056813Sralph 	poll = dtop->poll;
47156813Sralph 	data = dtop->data;
47256813Sralph 
47356813Sralph 	/*
47456813Sralph 	 * The interface does not handle us the first byte,
47556813Sralph 	 * which is our address and cannot ever be anything
47656813Sralph 	 * else but 0x50.  This is a good thing, it makes
47756813Sralph 	 * the average packet exactly one word long, too.
47856813Sralph 	 */
47956813Sralph 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
480*57234Sralph 		DELAY(1);
48156813Sralph 	if (max == DTOP_MAX_POLL)
48256813Sralph 		goto bad;
48356813Sralph 	pkt->src_address = DTOP_GET_BYTE(data);
48456813Sralph 
48556813Sralph 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
486*57234Sralph 		DELAY(1);
48756813Sralph 	if (max == DTOP_MAX_POLL)
48856813Sralph 		goto bad;
48956813Sralph 	pkt->code.bits = DTOP_GET_BYTE(data);
49056813Sralph 
49156813Sralph 	/*
49256813Sralph 	 * Now get data and checksum
49356813Sralph 	 */
49456813Sralph 	len = pkt->code.val.len + 1;
49556813Sralph 	c = 0;
49656813Sralph 	for (i = 0; i < len; i++) {
49756813Sralph again:
49856813Sralph 		for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
499*57234Sralph 			DELAY(1);
50056813Sralph 		if (max == DTOP_MAX_POLL)
50156813Sralph 			goto bad;
50256813Sralph 		if (c == DTOP_ESC_CHAR) {
50356813Sralph 			c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
50456813Sralph 		} else {
50556813Sralph 			c = DTOP_GET_BYTE(data);
50656813Sralph 			if (c == DTOP_ESC_CHAR)
50756813Sralph 				goto again;
50856813Sralph 		}
50956813Sralph 		pkt->body[i] = c;
51056813Sralph 	}
51156813Sralph 	return (len);
51256813Sralph bad:
51356813Sralph 	dtop->bad_pkts++;
51456813Sralph 	return (-1);
51556813Sralph }
51656813Sralph 
51756813Sralph /*
51856813Sralph  * Get a keyboard char for the console
51956813Sralph  */
52056813Sralph dtopKBDGetc()
52156813Sralph {
52256813Sralph 	register int c;
52356813Sralph 	dtop_softc_t dtop;
52456813Sralph 
52556813Sralph 	dtop = &dtop_softc[0];
52656813Sralph again:
52756813Sralph 	c = -1;
52856813Sralph 
52956813Sralph 	/*
53056813Sralph 	 * Now check keyboard
53156813Sralph 	 */
53256813Sralph 	if (DTOP_RX_AVAIL(dtop->poll)) {
53356813Sralph 
53456813Sralph 		dtop_message	msg;
53556813Sralph 		struct dtop_ds	*ds;
53656813Sralph 
53756813Sralph 		if (dtop_get_packet(dtop, &msg) >= 0) {
53856813Sralph 
53956813Sralph 		    ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
54056813Sralph 		    if (ds->handler == dtop_keyboard_handler) {
54156813Sralph 
54256813Sralph 			c = dtop_keyboard_handler(
54356813Sralph 					&ds->status, &msg,
54456813Sralph 					DTOP_EVENT_RECEIVE_PACKET, -1);
54556813Sralph 
54656813Sralph 			if (c > 0) return c;
54756813Sralph 
54856813Sralph 			c = -1;
54956813Sralph 		    }
55056813Sralph 		}
55156813Sralph 	}
55256813Sralph 
55356813Sralph 	if (c == -1) {
55456813Sralph 		DELAY(100);
55556813Sralph 		goto again;
55656813Sralph 	}
55756813Sralph 
55856813Sralph 	return c;
55956813Sralph }
56056813Sralph 
56156813Sralph int
56256813Sralph dtopparam(tp, t)
56356813Sralph 	struct tty *tp;
56456813Sralph 	struct termios *t;
56556813Sralph {
56656813Sralph 	if (tp->t_ispeed == 0)
56756813Sralph 		ttymodem(tp, 0);
56856813Sralph 	else
56956813Sralph 		/* called too early to invoke ttymodem, sigh */
57056813Sralph 		tp->t_state |= TS_CARR_ON;
57156813Sralph 	return (0);
57256813Sralph }
57356813Sralph 
57456813Sralph /*
57556813Sralph  * Stop output on a line.
57656813Sralph  */
57756813Sralph /*ARGSUSED*/
57856813Sralph dtopstop(tp, flag)
57956813Sralph 	register struct tty *tp;
58056813Sralph 	int flag;
58156813Sralph {
58256813Sralph 	int s;
58356813Sralph 
58456813Sralph 	s = spltty();
58556813Sralph 	if (tp->t_state & TS_BUSY) {
58656813Sralph 		if (!(tp->t_state & TS_TTSTOP))
58756813Sralph 			tp->t_state |= TS_FLUSH;
58856813Sralph 	}
58956813Sralph 	splx(s);
59056813Sralph }
59156813Sralph 
59256813Sralph /*
59356813Sralph  * Default handler function
59456813Sralph  */
59556813Sralph int
59656813Sralph dtop_null_device_handler(dev, msg, event, outc)
59756813Sralph 	 dtop_device_t	dev;
59856813Sralph 	 dtop_message_t	msg;
59956813Sralph 	 int		event;
60056813Sralph 	 int		outc;
60156813Sralph {
60256813Sralph 	/* See if the message was to the default address (powerup) */
60356813Sralph 
60456813Sralph 	/* Uhmm, donno how to handle this. Drop it */
60556813Sralph 	if (event == DTOP_EVENT_RECEIVE_PACKET)
60656813Sralph 		dev->unknown_report = *msg;
60756813Sralph 	return 0;
60856813Sralph }
60956813Sralph 
61056813Sralph /*
61156813Sralph  * Handler for locator devices (mice)
61256813Sralph  */
61356813Sralph int
61456813Sralph dtop_locator_handler(dev, msg, event, outc)
61556813Sralph 	 dtop_device_t	dev;
61656813Sralph 	 dtop_message_t	msg;
61756813Sralph 	 int		event;
61856813Sralph 	 int		outc;
61956813Sralph {
62056813Sralph 	register unsigned short	buttons;
62156813Sralph 	register short coord;
62256813Sralph 	register int moved = 0;
62356813Sralph 	static MouseReport currentRep;
62456813Sralph 	register MouseReport *mrp = &currentRep;
62556813Sralph 
62656813Sralph 	if (dtopMouseButtons) {
627*57234Sralph 		mrp->state = 0;
62856813Sralph 		/*
62956813Sralph 		 * Do the position first
63056813Sralph 		 */
63156813Sralph 		coord = GET_SHORT(msg->body[2], msg->body[3]);
632*57234Sralph 		if (coord < 0) {
633*57234Sralph 			coord = -coord;
63456813Sralph 			moved = 1;
635*57234Sralph 		} else if (coord > 0) {
636*57234Sralph 			mrp->state |= MOUSE_X_SIGN;
637*57234Sralph 			moved = 1;
638*57234Sralph 		}
639*57234Sralph 		mrp->dx = (coord & 0x1f);
64056813Sralph 		coord = GET_SHORT(msg->body[4], msg->body[5]);
641*57234Sralph 		if (coord < 0) {
642*57234Sralph 			coord = -coord;
64356813Sralph 			moved = 1;
644*57234Sralph 		} else if (coord > 0) {
645*57234Sralph 			mrp->state |= MOUSE_Y_SIGN;
646*57234Sralph 			moved = 1;
647*57234Sralph 		}
648*57234Sralph 		mrp->dy = (coord & 0x1f);
64956813Sralph 
65056813Sralph 		/*
65156813Sralph 		 * Time for the buttons now
65256813Sralph 		 */
65356813Sralph 		buttons = GET_SHORT(msg->body[0], msg->body[1]);
654*57234Sralph 		mrp->state |= (buttons & 0x7);
65556813Sralph 		if (moved)
65656813Sralph 			(*dtopMouseEvent)(mrp);
65756813Sralph 		(*dtopMouseButtons)(mrp);
65856813Sralph 	}
65956813Sralph 	return (0);
66056813Sralph }
66156813Sralph 
66256813Sralph /*
66356813Sralph  * Handler for keyboard devices
66456813Sralph  * Special case: outc set for recv packet means
66556813Sralph  * we are inside the kernel debugger
66656813Sralph  */
66756813Sralph int
66856813Sralph dtop_keyboard_handler(dev, msg, event, outc)
66956813Sralph 	dtop_device_t dev;
67056813Sralph 	dtop_message_t msg;
67156813Sralph 	int event;
67256813Sralph 	int outc;
67356813Sralph {
67456813Sralph 	register u_char *ls, *le, *ns, *ne;
67556813Sralph 	u_char save[11], retc;
67656813Sralph 	int msg_len, c;
67756813Sralph 	struct tty *tp = &dtop_tty[0];
67856813Sralph 
67956813Sralph 	/*
68056813Sralph 	 * Fiddle about emulating an lk201 keyboard. The lk501
68156813Sralph 	 * designers carefully ensured that keyboard handlers could be
68256813Sralph 	 * stateless, then we turn around and use lots of state to
68356813Sralph 	 * emulate the stateful lk201, since the X11R5 X servers
68456813Sralph 	 * only know about the lk201... (oh well)
68556813Sralph 	 */
68656813Sralph 	msg_len = msg->code.val.len;
68756813Sralph 
68856813Sralph 	/* Check for errors */
68956813Sralph 	c = msg->body[0];
69056813Sralph 	if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
69156813Sralph 		printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
69256813Sralph 		if (c != DTOP_KBD_OUT_ERR) return -1;
69356813Sralph 		/* spec sez if scan list overflow still there is data */
69456813Sralph 		msg->body[0] = 0;
69556813Sralph 	}
69656813Sralph 
69756813Sralph 	dev->keyboard.last_msec = TO_MS(time);
69856813Sralph 
69956813Sralph 	switch (dev->keyboard.k_ar_state) {
70056813Sralph 	case K_AR_IDLE:
70156813Sralph 		if (outc != 0xff) /* from debugger, might be too early */
70256813Sralph 			dtop_keyboard_autorepeat(dev);
70356813Sralph 		/* fall through */
70456813Sralph 	case K_AR_TRIGGER:
70556813Sralph 		dev->keyboard.k_ar_state = K_AR_ACTIVE;
70656813Sralph 		break;
70756813Sralph 	case K_AR_ACTIVE:
70856813Sralph 		break;
70956813Sralph 	case K_AR_OFF:
71056813Sralph 		printf("dtop keyb off?\n");
71156813Sralph 		dev->keyboard.k_ar_state = K_AR_IDLE;
71256813Sralph 	}
71356813Sralph 
71456813Sralph 	/*
71556813Sralph 	 * To make things readable, do a first pass cancelling out
71656813Sralph 	 * all keys that are still pressed, and a second one generating
71756813Sralph 	 * events.  While generating events, do the upstrokes first
71856813Sralph 	 * from oldest to youngest, then the downstrokes from oldest
71956813Sralph 	 * to youngest.  This copes with lost packets and provides
72056813Sralph 	 * a reasonable model even if scans are too slow.
72156813Sralph 	 */
72256813Sralph 
72356813Sralph 	/* make a copy of new state first */
72456813Sralph 	if (msg_len == 1)
72556813Sralph 		save[0] = msg->body[0];
72656813Sralph 	else if (msg_len > 0)
72756813Sralph 		bcopy(msg->body, save, msg_len);
72856813Sralph 
72956813Sralph 	/*
73056813Sralph 	 * Cancel out any keys in both the last and current message as
73156813Sralph 	 * they are unchanged.
73256813Sralph 	 */
73356813Sralph 	if (msg_len > 0 && dev->keyboard.last_codes_count > 0) {
73456813Sralph 		ls = dev->keyboard.last_codes;
73556813Sralph 		le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count];
73656813Sralph 		ne = &msg->body[msg_len];
73756813Sralph 		for (; ls < le; ls++) {
73856813Sralph 			for (ns = msg->body; ns < ne; ns++)
73956813Sralph 				if (*ls == *ns) {
74056813Sralph 					*ls = *ns = 0;
74156813Sralph 					break;
74256813Sralph 				}
74356813Sralph 		}
74456813Sralph 	}
74556813Sralph 
74656813Sralph 	/*
74756813Sralph 	 * Now generate all upstrokes
74856813Sralph 	 */
74956813Sralph 	le = dev->keyboard.last_codes;
75056813Sralph 	ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
75156813Sralph 	for ( ; ls >= le; ls--)
75256813Sralph 	    if (c = *ls) {
75356813Sralph 		(void) kbdMapChar(c);
75456813Sralph 
755*57234Sralph 		if (outc == 0 && dtopDivertXInput &&
756*57234Sralph 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))))
75756813Sralph 			(*dtopDivertXInput)(c);
75856813Sralph 	    }
75956813Sralph 	/*
76056813Sralph 	 * And finally the downstrokes
76156813Sralph 	 */
76256813Sralph 	ne = (char*)msg->body;
76356813Sralph 	ns = (char*)&msg->body[msg_len - 1];
76456813Sralph 	retc = 0;
76556813Sralph 	for ( ; ns >= ne; ns--)
76656813Sralph 	    if (*ns) {
76756813Sralph 		c = kbdMapChar(*ns);
76856813Sralph 		if (outc == 0) {
76956813Sralph 		    if (dtopDivertXInput) {
77056813Sralph 			(*dtopDivertXInput)(*ns);
77156813Sralph 			c = -1; /* consumed by X */
77256813Sralph 		    } else if (c >= 0)
77356813Sralph 			(*linesw[tp->t_line].l_rint)(c, tp);
77456813Sralph 		}
77556813Sralph 		/* return the related keycode anyways */
77656813Sralph 		if ((c >= 0) && (retc == 0))
77756813Sralph 		    retc = c;
77856813Sralph 	    }
77956813Sralph 	outc = retc;
78056813Sralph 	/* install new scan state */
78156813Sralph 	if (msg_len == 1)
78256813Sralph 		dev->keyboard.last_codes[0] = save[0];
78356813Sralph 	else if (msg_len > 0)
78456813Sralph 		bcopy(save, dev->keyboard.last_codes, msg_len);
78556813Sralph 	dev->keyboard.last_codes_count = msg_len;
78656813Sralph 	return (outc);
78756813Sralph }
78856813Sralph 
78956813Sralph /*
790*57234Sralph  * Timeout routine to do autorepeat.
79156813Sralph  */
79256813Sralph void
79356813Sralph dtop_keyboard_autorepeat(arg)
79456813Sralph 	void *arg;
79556813Sralph {
79656813Sralph 	dtop_device_t dev = (dtop_device_t)arg;
79756813Sralph 	int s;
79856813Sralph 
79956813Sralph 	s = spltty();
80056813Sralph 	if (dev->keyboard.k_ar_state != K_AR_IDLE)
801*57234Sralph 		dtop_keyboard_repeat(dev);
80256813Sralph 
80356813Sralph 	if (dev->keyboard.k_ar_state == K_AR_OFF)
80456813Sralph 		dev->keyboard.k_ar_state = K_AR_IDLE;
80556813Sralph 	else
80656813Sralph 		timeout(dtop_keyboard_autorepeat, dev, dev->keyboard.poll_frequency);
80756813Sralph 
80856813Sralph 	splx(s);
80956813Sralph }
810*57234Sralph 
811*57234Sralph /*
812*57234Sralph  * See if an autorepeat is required.
813*57234Sralph  */
814*57234Sralph static void
815*57234Sralph dtop_keyboard_repeat(dev)
816*57234Sralph 	dtop_device_t dev;
817*57234Sralph {
818*57234Sralph 	register int i, c;
819*57234Sralph 	register u_int t, t0;
820*57234Sralph 	struct tty *tp = dtop_tty;
821*57234Sralph 
822*57234Sralph 	for (i = 0; i < dev->keyboard.last_codes_count; i++) {
823*57234Sralph 		c = (int)dev->keyboard.last_codes[i];
824*57234Sralph 		if (c != DTOP_KBD_EMPTY &&
825*57234Sralph 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) {
826*57234Sralph 			/*
827*57234Sralph 			 * Got a char. See if enough time from stroke,
828*57234Sralph 			 * or from last repeat.
829*57234Sralph 			 */
830*57234Sralph 			t0 = (dev->keyboard.k_ar_state == K_AR_TRIGGER) ? 30 : 500;
831*57234Sralph 			t = TO_MS(time);
832*57234Sralph 			if ((t - dev->keyboard.last_msec) < t0)
833*57234Sralph 				return;
834*57234Sralph 
835*57234Sralph 			dev->keyboard.k_ar_state = K_AR_TRIGGER;
836*57234Sralph 
837*57234Sralph 			if (dtopDivertXInput) {
838*57234Sralph 				(*dtopDivertXInput)(KEY_REPEAT);
839*57234Sralph 				return;
840*57234Sralph 			}
841*57234Sralph 
842*57234Sralph 			if ((c = kbdMapChar(KEY_REPEAT)) >= 0)
843*57234Sralph 				(*linesw[tp->t_line].l_rint)(c, tp);
844*57234Sralph 			return;
845*57234Sralph 		}
846*57234Sralph 	}
847*57234Sralph 	dev->keyboard.k_ar_state = K_AR_OFF;
848*57234Sralph }
84956813Sralph #endif
850