xref: /csrg-svn/sys/pmax/dev/dtop.c (revision 63205)
156813Sralph /*-
2*63205Sbostic  * Copyright (c) 1992, 1993
3*63205Sbostic  *	The Regents of the University of California.  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*63205Sbostic  *	@(#)dtop.c	8.1 (Berkeley) 06/10/93
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  */
4457234Sralph /************************************************************
4557234Sralph Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
4657234Sralph and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4756813Sralph 
4857234Sralph                         All Rights Reserved
4957234Sralph 
5057234Sralph Permission to use, copy, modify, and distribute this software and its
5157234Sralph documentation for any purpose and without fee is hereby granted,
5257234Sralph provided that the above copyright notice appear in all copies and that
5357234Sralph both that copyright notice and this permission notice appear in
5457234Sralph supporting documentation, and that the names of Digital or MIT not be
5557234Sralph used in advertising or publicity pertaining to distribution of the
5657234Sralph software without specific, written prior permission.
5757234Sralph 
5857234Sralph DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
5957234Sralph ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
6057234Sralph DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
6157234Sralph ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
6257234Sralph WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
6357234Sralph ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
6457234Sralph SOFTWARE.
6557234Sralph 
6657234Sralph ********************************************************/
6757234Sralph 
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 *));
9858793Sralph void dtop_keyboard_repeat	__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));
10656813Sralph 
10756813Sralph struct	tty dtop_tty[NDTOP];
10856813Sralph void	(*dtopDivertXInput)();	/* X windows keyboard input routine */
10956813Sralph void	(*dtopMouseEvent)();	/* X windows mouse motion event routine */
11056813Sralph void	(*dtopMouseButtons)();	/* X windows mouse buttons event routine */
11156813Sralph 
11256813Sralph #define	DTOP_MAX_POLL	0x7fff		/* about half a sec */
11356813Sralph 
11456813Sralph typedef volatile unsigned int	*data_reg_t;	/* uC  */
11556813Sralph #define	DTOP_GET_BYTE(data)	(((*(data)) >> 8) & 0xff)
11656813Sralph #define	DTOP_PUT_BYTE(data,c)	{ *(data) = (c) << 8; }
11756813Sralph 
11856813Sralph typedef volatile unsigned int	*poll_reg_t;	/* SIR */
11956813Sralph #define	DTOP_RX_AVAIL(poll)	(*(poll) & 1)
12056813Sralph #define	DTOP_TX_AVAIL(poll)	(*(poll) & 2)
12156813Sralph 
12256813Sralph #define	GET_SHORT(b0,b1)	(((b0)<<8)|(b1))
12356813Sralph 
12456813Sralph /*
12556813Sralph  * Driver status
12656813Sralph  */
12756813Sralph struct dtop_softc {
12856813Sralph 	data_reg_t	data;
12956813Sralph 	poll_reg_t	poll;
13056813Sralph 	char		polling_mode;
13156813Sralph 	char		probed_once;
13256813Sralph 	short		bad_pkts;
13356813Sralph 
13456813Sralph 	struct dtop_ds {
13556813Sralph 		int		(*handler)();
13656813Sralph 		dtop_device	status;
13756813Sralph 	} device[(DTOP_ADDR_DEFAULT - DTOP_ADDR_FIRST) >> 1];
13856813Sralph 
13956813Sralph #	define	DTOP_DEVICE_NO(address)	(((address)-DTOP_ADDR_FIRST)>>1)
14056813Sralph 
14156813Sralph } dtop_softc[NDTOP];
14256813Sralph 
14356813Sralph typedef struct dtop_softc *dtop_softc_t;
14456813Sralph struct tty dtop_tty[NDTOP];
14556813Sralph 
14656813Sralph /*
14757234Sralph  * lk201 keyboard divisions and up/down mode key bitmap.
14857234Sralph  */
14957234Sralph #define NUMDIVS 14
15057234Sralph static u_char divbeg[NUMDIVS] = {0xbf, 0x91, 0xbc, 0xbd, 0xb0, 0xad, 0xa6,
15157234Sralph 				 0xa9, 0x88, 0x56, 0x63, 0x6f, 0x7b, 0x7e};
15257234Sralph static u_char divend[NUMDIVS] = {0xff, 0xa5, 0xbc, 0xbe, 0xb2, 0xaf, 0xa8,
15357234Sralph 				 0xac, 0x90, 0x62, 0x6e, 0x7a, 0x7d, 0x87};
15457234Sralph /*
15557234Sralph  * Initial defaults, groups 5 and 6 are up/down
15657234Sralph  */
15757234Sralph static u_long keymodes[8] = {0, 0, 0, 0, 0, 0x0003e000, 0, 0};
15857234Sralph 
15957234Sralph /*
16056813Sralph  * Definition of the driver for the auto-configuration program.
16156813Sralph  */
16256813Sralph int	dtopprobe();
16356813Sralph void	dtopintr();
16456813Sralph struct	driver dtopdriver =  {
16556813Sralph 	"dtop", dtopprobe, 0, 0, dtopintr,
16656813Sralph };
16756813Sralph 
16856813Sralph dtopprobe(cp)
16956813Sralph 	struct pmax_ctlr *cp;
17056813Sralph {
17156813Sralph 	register struct tty *tp;
17256813Sralph 	register int cntr;
17356813Sralph 	int dtopunit = cp->pmax_unit, i, s;
17456813Sralph 	dtop_softc_t dtop;
17556813Sralph 
17656813Sralph 	if (dtopunit >= NDTOP)
17756813Sralph 		return (0);
17856813Sralph 	if (badaddr(cp->pmax_addr, 2))
17956813Sralph 		return (0);
18056813Sralph 	dtop = &dtop_softc[dtopunit];
18156813Sralph 
18256813Sralph 	dtop->poll = (poll_reg_t)MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
18356813Sralph 	dtop->data = (data_reg_t)cp->pmax_addr;
18456813Sralph 
18556813Sralph 	for (i = 0; i < DTOP_MAX_DEVICES; i++)
18656813Sralph 		dtop->device[i].handler = dtop_null_device_handler;
18756813Sralph 
18856813Sralph 	/* a lot more needed here, fornow: */
18956813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6a)].handler = dtop_locator_handler;
19056813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6c)].handler = dtop_keyboard_handler;
19156813Sralph 	dtop->device[DTOP_DEVICE_NO(0x6c)].status.keyboard.k_ar_state =
19256813Sralph 		K_AR_IDLE;
19356813Sralph 
19457234Sralph 	dtop->probed_once = 1;
19557234Sralph 	printf("dtop%d at nexus0 csr 0x%x priority %d\n",
19657234Sralph 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
19756813Sralph 	return (1);
19856813Sralph }
19956813Sralph 
20056813Sralph dtopopen(dev, flag, mode, p)
20156813Sralph 	dev_t dev;
20256813Sralph 	int flag, mode;
20356813Sralph 	struct proc *p;
20456813Sralph {
20556813Sralph 	register struct tty *tp;
20656813Sralph 	register int unit;
20756813Sralph 	int s, error = 0;
20856813Sralph 
20956813Sralph 	unit = minor(dev);
21056813Sralph 	if (unit >= NDTOP)
21156813Sralph 		return (ENXIO);
21256813Sralph 	tp = &dtop_tty[unit];
21356813Sralph 	tp->t_oproc = dtopstart;
21456813Sralph 	tp->t_param = dtopparam;
21556813Sralph 	tp->t_dev = dev;
21656813Sralph 	if ((tp->t_state & TS_ISOPEN) == 0) {
21756813Sralph 		tp->t_state |= TS_WOPEN;
21856813Sralph 		ttychars(tp);
21956813Sralph 		if (tp->t_ispeed == 0) {
22056813Sralph 			tp->t_iflag = TTYDEF_IFLAG;
22156813Sralph 			tp->t_oflag = TTYDEF_OFLAG;
22256813Sralph 			tp->t_cflag = TTYDEF_CFLAG;
22356813Sralph 			tp->t_lflag = TTYDEF_LFLAG;
22456813Sralph 			tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
22556813Sralph 		}
22656813Sralph 		(void) dtopparam(tp, &tp->t_termios);
22756813Sralph 		ttsetwater(tp);
22856813Sralph 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
22956813Sralph 		return (EBUSY);
23056813Sralph 	s = spltty();
23156813Sralph 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
23256813Sralph 	       !(tp->t_state & TS_CARR_ON)) {
23356813Sralph 		tp->t_state |= TS_WOPEN;
23456813Sralph 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
23556813Sralph 		    ttopen, 0))
23656813Sralph 			break;
23756813Sralph 	}
23856813Sralph 	splx(s);
23956813Sralph 	if (error)
24056813Sralph 		return (error);
24156813Sralph 	error = (*linesw[tp->t_line].l_open)(dev, tp);
24256813Sralph 	return (error);
24356813Sralph }
24456813Sralph 
24556813Sralph /*ARGSUSED*/
24656813Sralph dtopclose(dev, flag, mode, p)
24756813Sralph 	dev_t dev;
24856813Sralph 	int flag, mode;
24956813Sralph 	struct proc *p;
25056813Sralph {
25156813Sralph 	register struct tty *tp;
25256813Sralph 	register int unit;
25356813Sralph 
25456813Sralph 	unit = minor(dev);
25556813Sralph 	tp = &dtop_tty[unit];
25656813Sralph 	(*linesw[tp->t_line].l_close)(tp, flag);
25756813Sralph 	return (ttyclose(tp));
25856813Sralph }
25956813Sralph 
26056813Sralph dtopread(dev, uio, flag)
26156813Sralph 	dev_t dev;
26256813Sralph 	struct uio *uio;
26356813Sralph {
26456813Sralph 	register struct tty *tp;
26556813Sralph 
26656813Sralph 	tp = &dtop_tty[minor(dev)];
26756813Sralph 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
26856813Sralph }
26956813Sralph 
27056813Sralph dtopwrite(dev, uio, flag)
27156813Sralph 	dev_t dev;
27256813Sralph 	struct uio *uio;
27356813Sralph {
27456813Sralph 	register struct tty *tp;
27556813Sralph 
27656813Sralph 	tp = &dtop_tty[minor(dev)];
27756813Sralph 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
27856813Sralph }
27956813Sralph 
28056813Sralph /*ARGSUSED*/
28156813Sralph dtopioctl(dev, cmd, data, flag, p)
28256813Sralph 	dev_t dev;
28356813Sralph 	int cmd;
28456813Sralph 	caddr_t data;
28556813Sralph 	int flag;
28656813Sralph 	struct proc *p;
28756813Sralph {
28856813Sralph 	register struct tty *tp;
28956813Sralph 	register int unit = minor(dev);
29056813Sralph 	int error;
29156813Sralph 
29256813Sralph 	tp = &dtop_tty[unit];
29356813Sralph 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
29456813Sralph 	if (error >= 0)
29556813Sralph 		return (error);
29656813Sralph 	error = ttioctl(tp, cmd, data, flag);
29756813Sralph 	if (error >= 0)
29856813Sralph 		return (error);
29956813Sralph 
30056813Sralph 	switch (cmd) {
30156813Sralph 
30256813Sralph 	case TIOCSBRK:
30356813Sralph 		ttyoutput(0, tp);
30456813Sralph 		break;
30556813Sralph 
30656813Sralph 	case TIOCCBRK:
30756813Sralph 		ttyoutput(0, tp);
30856813Sralph 		break;
30956813Sralph 
31056813Sralph 	case TIOCMGET:
31156813Sralph 		*(int *)data = DML_DTR | DML_DSR | DML_CAR;
31256813Sralph 		break;
31356813Sralph 
31456813Sralph 	default:
31556813Sralph 		return (ENOTTY);
31656813Sralph 	}
31756813Sralph 	return (0);
31856813Sralph }
31956813Sralph 
32056813Sralph /*
32156813Sralph  * Interrupt routine
32256813Sralph  */
32356813Sralph void
32456813Sralph dtopintr(unit)
32556813Sralph 	int unit;
32656813Sralph {
32756813Sralph 	dtop_message msg;
32856813Sralph 	int devno;
32956813Sralph 	dtop_softc_t dtop;
33056813Sralph 
33156813Sralph 	dtop = &dtop_softc[unit];
33256813Sralph 	if (dtop_get_packet(dtop, &msg) < 0) {
33358793Sralph #ifdef DIAGNOSTIC
33458793Sralph 	    printf("dtop: overrun (or stray)\n");
33558793Sralph #endif
33658793Sralph 	    /*
33758793Sralph 	     * Ugh! The most common occurrence of a data overrun is upon a
33858793Sralph 	     * key press and the result is a software generated "stuck key".
33958793Sralph 	     * All I can think to do is fake an "all keys up" whenever a
34058793Sralph 	     * data overrun occurs.
34158793Sralph 	     */
34258793Sralph 	    msg.src_address = 0x6c;
34358793Sralph 	    msg.code.val.len = 1;
34458793Sralph 	    msg.body[0] = DTOP_KBD_EMPTY;
34556813Sralph 	}
34656813Sralph 
34758793Sralph 	/*
34858793Sralph 	 * If not probed yet, just throw the data away.
34958793Sralph 	 */
35058793Sralph 	if (!dtop->probed_once)
35158793Sralph 		return;
35258793Sralph 
35356813Sralph 	devno = DTOP_DEVICE_NO(msg.src_address);
35456813Sralph 	if (devno < 0 || devno > 15)
35556813Sralph 		return;
35656813Sralph 	(void) (*dtop->device[devno].handler)
35756813Sralph 			(&dtop->device[devno].status, &msg,
35856813Sralph 			 DTOP_EVENT_RECEIVE_PACKET, 0);
35956813Sralph }
36056813Sralph 
36156813Sralph void
36256813Sralph dtopstart(tp)
36356813Sralph 	register struct tty *tp;
36456813Sralph {
36556813Sralph 	register int cc;
36656813Sralph 	int s;
36756813Sralph 
36856813Sralph 	s = spltty();
36956813Sralph 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
37056813Sralph 		goto out;
37156813Sralph 	if (tp->t_outq.c_cc <= tp->t_lowat) {
37256813Sralph 		if (tp->t_state & TS_ASLEEP) {
37356813Sralph 			tp->t_state &= ~TS_ASLEEP;
37456813Sralph 			wakeup((caddr_t)&tp->t_outq);
37556813Sralph 		}
37656813Sralph 		selwakeup(&tp->t_wsel);
37756813Sralph 	}
37856813Sralph 	if (tp->t_outq.c_cc == 0)
37956813Sralph 		goto out;
38056813Sralph 	/* handle console specially */
38156813Sralph 	if (tp == dtop_tty) {
38256813Sralph 		while (tp->t_outq.c_cc > 0) {
38356813Sralph 			cc = getc(&tp->t_outq) & 0x7f;
38456813Sralph 			cnputc(cc);
38556813Sralph 		}
38656813Sralph 		/*
38756813Sralph 		 * After we flush the output queue we may need to wake
38856813Sralph 		 * up the process that made the output.
38956813Sralph 		 */
39056813Sralph 		if (tp->t_outq.c_cc <= tp->t_lowat) {
39156813Sralph 			if (tp->t_state & TS_ASLEEP) {
39256813Sralph 				tp->t_state &= ~TS_ASLEEP;
39356813Sralph 				wakeup((caddr_t)&tp->t_outq);
39456813Sralph 			}
39556813Sralph 			selwakeup(&tp->t_wsel);
39656813Sralph 		}
39756813Sralph 	}
39856813Sralph out:
39956813Sralph 	splx(s);
40056813Sralph }
40156813Sralph 
40256813Sralph void
40356813Sralph dtopKBDPutc(dev, c)
40456813Sralph 	dev_t dev;
40556813Sralph 	int c;
40656813Sralph {
40757234Sralph 	register int i;
40857234Sralph 	static int param = 0, cmd, mod, typ;
40957234Sralph 	static u_char parms[2];
41056813Sralph 
41156813Sralph 	/*
41257234Sralph 	 * Emulate the lk201 command codes.
41356813Sralph 	 */
41457234Sralph 	if (param == 0) {
41557234Sralph 		typ = (c & 0x1);
41657234Sralph 		cmd = ((c >> 3) & 0xf);
41757234Sralph 		mod = ((c >> 1) & 0x3);
41857234Sralph 	} else
41957234Sralph 		parms[param - 1] = (c & 0x7f);
42057234Sralph 	if (c & 0x80) {
42157234Sralph 		if (typ) {
42257234Sralph 			/*
42357234Sralph 			 * A peripheral command code. Someday this driver
42457234Sralph 			 * should know how to send commands to the lk501,
42557234Sralph 			 * but until then this is all essentially a no-op.
42657234Sralph 			 */
42757234Sralph 			;
42857234Sralph 		} else {
42957234Sralph 			/*
43057234Sralph 			 * Set modes. These have to be emulated in software.
43157234Sralph 			 */
43257234Sralph 			if (cmd > 0 && cmd < 15) {
43357234Sralph 				cmd--;
43457234Sralph 				if (mod & 0x2)
43557234Sralph 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
43657234Sralph 					keymodes[i >> 5] |=
43757234Sralph 						(1 << (i & 0x1f));
43857234Sralph 				else
43957234Sralph 				   for (i = divbeg[cmd]; i <= divend[cmd]; i++)
44057234Sralph 					keymodes[i >> 5] &=
44157234Sralph 						~(1 << (i & 0x1f));
44257234Sralph 			}
44357234Sralph 		}
44457234Sralph 		param = 0;
44557234Sralph 	} else if (++param > 2)
44657234Sralph 		param = 2;
44756813Sralph }
44856813Sralph 
44956813Sralph /*
45056813Sralph  * Take a packet off dtop interface
45156813Sralph  * A packet MUST be there, this is not checked for.
45256813Sralph  */
45356813Sralph #define	DTOP_ESC_CHAR		0xf8
45456813Sralph dtop_escape(c)
45556813Sralph {
45656813Sralph 	/* I donno much about this stuff.. */
45756813Sralph 	switch (c) {
45856813Sralph 	case 0xe8:	return (0xf8);
45956813Sralph 	case 0xe9:	return (0xf9);
46056813Sralph 	case 0xea:	return (0xfa);
46156813Sralph 	case 0xeb:	return (0xfb);
46256813Sralph 	default:	/* printf("{esc %x}", c); */
46356813Sralph 			return (c);
46456813Sralph 	}
46556813Sralph }
46656813Sralph 
46756813Sralph dtop_get_packet(dtop, pkt)
46856813Sralph 	dtop_softc_t	dtop;
46956813Sralph 	dtop_message_t	pkt;
47056813Sralph {
47156813Sralph 	register poll_reg_t	poll;
47256813Sralph 	register data_reg_t	data;
47356813Sralph 	register int		max, i, len;
47456813Sralph 	register unsigned char	c;
47556813Sralph 
47656813Sralph 	poll = dtop->poll;
47756813Sralph 	data = dtop->data;
47856813Sralph 
47956813Sralph 	/*
48056813Sralph 	 * The interface does not handle us the first byte,
48156813Sralph 	 * which is our address and cannot ever be anything
48256813Sralph 	 * else but 0x50.  This is a good thing, it makes
48356813Sralph 	 * the average packet exactly one word long, too.
48456813Sralph 	 */
48556813Sralph 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
48657234Sralph 		DELAY(1);
48756813Sralph 	if (max == DTOP_MAX_POLL)
48856813Sralph 		goto bad;
48956813Sralph 	pkt->src_address = DTOP_GET_BYTE(data);
49056813Sralph 
49156813Sralph 	for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
49257234Sralph 		DELAY(1);
49356813Sralph 	if (max == DTOP_MAX_POLL)
49456813Sralph 		goto bad;
49556813Sralph 	pkt->code.bits = DTOP_GET_BYTE(data);
49656813Sralph 
49756813Sralph 	/*
49856813Sralph 	 * Now get data and checksum
49956813Sralph 	 */
50056813Sralph 	len = pkt->code.val.len + 1;
50156813Sralph 	c = 0;
50256813Sralph 	for (i = 0; i < len; i++) {
50356813Sralph again:
50456813Sralph 		for (max = 0; (max < DTOP_MAX_POLL) && !DTOP_RX_AVAIL(poll); max++)
50557234Sralph 			DELAY(1);
50656813Sralph 		if (max == DTOP_MAX_POLL)
50756813Sralph 			goto bad;
50856813Sralph 		if (c == DTOP_ESC_CHAR) {
50956813Sralph 			c = dtop_escape(DTOP_GET_BYTE(data) & 0xff);
51056813Sralph 		} else {
51156813Sralph 			c = DTOP_GET_BYTE(data);
51256813Sralph 			if (c == DTOP_ESC_CHAR)
51356813Sralph 				goto again;
51456813Sralph 		}
51556813Sralph 		pkt->body[i] = c;
51656813Sralph 	}
51756813Sralph 	return (len);
51856813Sralph bad:
51956813Sralph 	dtop->bad_pkts++;
52056813Sralph 	return (-1);
52156813Sralph }
52256813Sralph 
52356813Sralph /*
52456813Sralph  * Get a keyboard char for the console
52556813Sralph  */
52656813Sralph dtopKBDGetc()
52756813Sralph {
52856813Sralph 	register int c;
52956813Sralph 	dtop_softc_t dtop;
53056813Sralph 
53156813Sralph 	dtop = &dtop_softc[0];
53256813Sralph again:
53356813Sralph 	c = -1;
53456813Sralph 
53556813Sralph 	/*
53656813Sralph 	 * Now check keyboard
53756813Sralph 	 */
53856813Sralph 	if (DTOP_RX_AVAIL(dtop->poll)) {
53956813Sralph 
54056813Sralph 		dtop_message	msg;
54156813Sralph 		struct dtop_ds	*ds;
54256813Sralph 
54356813Sralph 		if (dtop_get_packet(dtop, &msg) >= 0) {
54456813Sralph 
54556813Sralph 		    ds = &dtop->device[DTOP_DEVICE_NO(msg.src_address)];
54656813Sralph 		    if (ds->handler == dtop_keyboard_handler) {
54756813Sralph 
54856813Sralph 			c = dtop_keyboard_handler(
54956813Sralph 					&ds->status, &msg,
55056813Sralph 					DTOP_EVENT_RECEIVE_PACKET, -1);
55156813Sralph 
55256813Sralph 			if (c > 0) return c;
55356813Sralph 
55456813Sralph 			c = -1;
55556813Sralph 		    }
55656813Sralph 		}
55756813Sralph 	}
55856813Sralph 
55956813Sralph 	if (c == -1) {
56056813Sralph 		DELAY(100);
56156813Sralph 		goto again;
56256813Sralph 	}
56356813Sralph 
56456813Sralph 	return c;
56556813Sralph }
56656813Sralph 
56756813Sralph int
56856813Sralph dtopparam(tp, t)
56956813Sralph 	struct tty *tp;
57056813Sralph 	struct termios *t;
57156813Sralph {
57256813Sralph 	if (tp->t_ispeed == 0)
57356813Sralph 		ttymodem(tp, 0);
57456813Sralph 	else
57556813Sralph 		/* called too early to invoke ttymodem, sigh */
57656813Sralph 		tp->t_state |= TS_CARR_ON;
57756813Sralph 	return (0);
57856813Sralph }
57956813Sralph 
58056813Sralph /*
58156813Sralph  * Stop output on a line.
58256813Sralph  */
58356813Sralph /*ARGSUSED*/
58456813Sralph dtopstop(tp, flag)
58556813Sralph 	register struct tty *tp;
58656813Sralph 	int flag;
58756813Sralph {
58856813Sralph 	int s;
58956813Sralph 
59056813Sralph 	s = spltty();
59156813Sralph 	if (tp->t_state & TS_BUSY) {
59256813Sralph 		if (!(tp->t_state & TS_TTSTOP))
59356813Sralph 			tp->t_state |= TS_FLUSH;
59456813Sralph 	}
59556813Sralph 	splx(s);
59656813Sralph }
59756813Sralph 
59856813Sralph /*
59956813Sralph  * Default handler function
60056813Sralph  */
60156813Sralph int
60256813Sralph dtop_null_device_handler(dev, msg, event, outc)
60356813Sralph 	 dtop_device_t	dev;
60456813Sralph 	 dtop_message_t	msg;
60556813Sralph 	 int		event;
60656813Sralph 	 int		outc;
60756813Sralph {
60856813Sralph 	/* See if the message was to the default address (powerup) */
60956813Sralph 
61056813Sralph 	/* Uhmm, donno how to handle this. Drop it */
61156813Sralph 	if (event == DTOP_EVENT_RECEIVE_PACKET)
61256813Sralph 		dev->unknown_report = *msg;
61356813Sralph 	return 0;
61456813Sralph }
61556813Sralph 
61656813Sralph /*
61756813Sralph  * Handler for locator devices (mice)
61856813Sralph  */
61956813Sralph int
62056813Sralph dtop_locator_handler(dev, msg, event, outc)
62156813Sralph 	 dtop_device_t	dev;
62256813Sralph 	 dtop_message_t	msg;
62356813Sralph 	 int		event;
62456813Sralph 	 int		outc;
62556813Sralph {
62656813Sralph 	register unsigned short	buttons;
62756813Sralph 	register short coord;
62856813Sralph 	register int moved = 0;
62956813Sralph 	static MouseReport currentRep;
63056813Sralph 	register MouseReport *mrp = &currentRep;
63156813Sralph 
63256813Sralph 	if (dtopMouseButtons) {
63357234Sralph 		mrp->state = 0;
63456813Sralph 		/*
63556813Sralph 		 * Do the position first
63656813Sralph 		 */
63756813Sralph 		coord = GET_SHORT(msg->body[2], msg->body[3]);
63857234Sralph 		if (coord < 0) {
63957234Sralph 			coord = -coord;
64056813Sralph 			moved = 1;
64157234Sralph 		} else if (coord > 0) {
64257234Sralph 			mrp->state |= MOUSE_X_SIGN;
64357234Sralph 			moved = 1;
64457234Sralph 		}
64557234Sralph 		mrp->dx = (coord & 0x1f);
64656813Sralph 		coord = GET_SHORT(msg->body[4], msg->body[5]);
64757234Sralph 		if (coord < 0) {
64857234Sralph 			coord = -coord;
64956813Sralph 			moved = 1;
65057234Sralph 		} else if (coord > 0) {
65157234Sralph 			mrp->state |= MOUSE_Y_SIGN;
65257234Sralph 			moved = 1;
65357234Sralph 		}
65457234Sralph 		mrp->dy = (coord & 0x1f);
65556813Sralph 
65656813Sralph 		/*
65756813Sralph 		 * Time for the buttons now
65858793Sralph 		 * Shuffle button bits around to serial mouse order.
65956813Sralph 		 */
66056813Sralph 		buttons = GET_SHORT(msg->body[0], msg->body[1]);
66158793Sralph 		mrp->state |= (((buttons >> 1) & 0x3) | ((buttons << 2) & 0x4));
66256813Sralph 		if (moved)
66356813Sralph 			(*dtopMouseEvent)(mrp);
66456813Sralph 		(*dtopMouseButtons)(mrp);
66556813Sralph 	}
66656813Sralph 	return (0);
66756813Sralph }
66856813Sralph 
66956813Sralph /*
67056813Sralph  * Handler for keyboard devices
67156813Sralph  * Special case: outc set for recv packet means
67256813Sralph  * we are inside the kernel debugger
67356813Sralph  */
67456813Sralph int
67556813Sralph dtop_keyboard_handler(dev, msg, event, outc)
67656813Sralph 	dtop_device_t dev;
67756813Sralph 	dtop_message_t msg;
67856813Sralph 	int event;
67956813Sralph 	int outc;
68056813Sralph {
68156813Sralph 	register u_char *ls, *le, *ns, *ne;
68256813Sralph 	u_char save[11], retc;
68358793Sralph 	int msg_len, c, s;
68456813Sralph 	struct tty *tp = &dtop_tty[0];
68556813Sralph 
68656813Sralph 	/*
68756813Sralph 	 * Fiddle about emulating an lk201 keyboard. The lk501
68856813Sralph 	 * designers carefully ensured that keyboard handlers could be
68956813Sralph 	 * stateless, then we turn around and use lots of state to
69056813Sralph 	 * emulate the stateful lk201, since the X11R5 X servers
69156813Sralph 	 * only know about the lk201... (oh well)
69256813Sralph 	 */
69358793Sralph 	/*
69458793Sralph 	 * Turn off any autorepeat timeout.
69558793Sralph 	 */
69658793Sralph 	s = splhigh();
69758793Sralph 	if (dev->keyboard.k_ar_state != K_AR_IDLE) {
69858793Sralph 		dev->keyboard.k_ar_state = K_AR_IDLE;
69958793Sralph 		untimeout(dtop_keyboard_repeat, (void *)dev);
70058793Sralph 	}
70158793Sralph 	splx(s);
70256813Sralph 	msg_len = msg->code.val.len;
70356813Sralph 
70456813Sralph 	/* Check for errors */
70556813Sralph 	c = msg->body[0];
70656813Sralph 	if ((c < DTOP_KBD_KEY_MIN) && (c != DTOP_KBD_EMPTY)) {
70756813Sralph 		printf("Keyboard error: %x %x %x..\n", msg_len, c, msg->body[1]);
70858793Sralph #ifdef notdef
70956813Sralph 		if (c != DTOP_KBD_OUT_ERR) return -1;
71058793Sralph #endif
71158793Sralph 		/*
71258793Sralph 		 * Fake an "all ups" to avoid the stuck key syndrome.
71358793Sralph 		 */
71458793Sralph 		c = msg->body[0] = DTOP_KBD_EMPTY;
71558793Sralph 		msg_len = 1;
71656813Sralph 	}
71756813Sralph 
71856813Sralph 	dev->keyboard.last_msec = TO_MS(time);
71956813Sralph 	/*
72056813Sralph 	 * To make things readable, do a first pass cancelling out
72156813Sralph 	 * all keys that are still pressed, and a second one generating
72256813Sralph 	 * events.  While generating events, do the upstrokes first
72356813Sralph 	 * from oldest to youngest, then the downstrokes from oldest
72456813Sralph 	 * to youngest.  This copes with lost packets and provides
72556813Sralph 	 * a reasonable model even if scans are too slow.
72656813Sralph 	 */
72756813Sralph 
72856813Sralph 	/* make a copy of new state first */
72956813Sralph 	if (msg_len == 1)
73056813Sralph 		save[0] = msg->body[0];
73156813Sralph 	else if (msg_len > 0)
73256813Sralph 		bcopy(msg->body, save, msg_len);
73356813Sralph 
73456813Sralph 	/*
73556813Sralph 	 * Cancel out any keys in both the last and current message as
73656813Sralph 	 * they are unchanged.
73756813Sralph 	 */
73856813Sralph 	if (msg_len > 0 && dev->keyboard.last_codes_count > 0) {
73956813Sralph 		ls = dev->keyboard.last_codes;
74056813Sralph 		le = &dev->keyboard.last_codes[dev->keyboard.last_codes_count];
74156813Sralph 		ne = &msg->body[msg_len];
74256813Sralph 		for (; ls < le; ls++) {
74356813Sralph 			for (ns = msg->body; ns < ne; ns++)
74456813Sralph 				if (*ls == *ns) {
74556813Sralph 					*ls = *ns = 0;
74656813Sralph 					break;
74756813Sralph 				}
74856813Sralph 		}
74956813Sralph 	}
75056813Sralph 
75156813Sralph 	/*
75256813Sralph 	 * Now generate all upstrokes
75356813Sralph 	 */
75456813Sralph 	le = dev->keyboard.last_codes;
75556813Sralph 	ls = &dev->keyboard.last_codes[dev->keyboard.last_codes_count - 1];
75656813Sralph 	for ( ; ls >= le; ls--)
75756813Sralph 	    if (c = *ls) {
75856813Sralph 		(void) kbdMapChar(c);
75956813Sralph 
76057234Sralph 		if (outc == 0 && dtopDivertXInput &&
76157234Sralph 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))))
76256813Sralph 			(*dtopDivertXInput)(c);
76356813Sralph 	    }
76456813Sralph 	/*
76556813Sralph 	 * And finally the downstrokes
76656813Sralph 	 */
76756813Sralph 	ne = (char*)msg->body;
76856813Sralph 	ns = (char*)&msg->body[msg_len - 1];
76956813Sralph 	retc = 0;
77056813Sralph 	for ( ; ns >= ne; ns--)
77156813Sralph 	    if (*ns) {
77256813Sralph 		c = kbdMapChar(*ns);
77356813Sralph 		if (outc == 0) {
77456813Sralph 		    if (dtopDivertXInput) {
77556813Sralph 			(*dtopDivertXInput)(*ns);
77656813Sralph 			c = -1; /* consumed by X */
77756813Sralph 		    } else if (c >= 0)
77856813Sralph 			(*linesw[tp->t_line].l_rint)(c, tp);
77958793Sralph 		    dev->keyboard.k_ar_state = K_AR_ACTIVE;
78056813Sralph 		}
78156813Sralph 		/* return the related keycode anyways */
78256813Sralph 		if ((c >= 0) && (retc == 0))
78356813Sralph 		    retc = c;
78456813Sralph 	    }
78556813Sralph 	outc = retc;
78656813Sralph 	/* install new scan state */
78756813Sralph 	if (msg_len == 1)
78856813Sralph 		dev->keyboard.last_codes[0] = save[0];
78956813Sralph 	else if (msg_len > 0)
79056813Sralph 		bcopy(save, dev->keyboard.last_codes, msg_len);
79156813Sralph 	dev->keyboard.last_codes_count = msg_len;
79258793Sralph 	if (dev->keyboard.k_ar_state == K_AR_ACTIVE)
79358793Sralph 		timeout(dtop_keyboard_repeat, (void *)dev, hz / 2);
79456813Sralph 	return (outc);
79556813Sralph }
79656813Sralph 
79756813Sralph /*
79858793Sralph  * Do an autorepeat as required.
79956813Sralph  */
80056813Sralph void
80158793Sralph dtop_keyboard_repeat(arg)
80256813Sralph 	void *arg;
80356813Sralph {
80456813Sralph 	dtop_device_t dev = (dtop_device_t)arg;
80557234Sralph 	register int i, c;
80657234Sralph 	struct tty *tp = dtop_tty;
80758793Sralph 	int s = spltty(), gotone = 0;
80857234Sralph 
80957234Sralph 	for (i = 0; i < dev->keyboard.last_codes_count; i++) {
81057234Sralph 		c = (int)dev->keyboard.last_codes[i];
81157234Sralph 		if (c != DTOP_KBD_EMPTY &&
81257234Sralph 		    (keymodes[(c >> 5) & 0x7] & (1 << (c & 0x1f))) == 0) {
81357234Sralph 			dev->keyboard.k_ar_state = K_AR_TRIGGER;
81457234Sralph 			if (dtopDivertXInput) {
81557234Sralph 				(*dtopDivertXInput)(KEY_REPEAT);
81658793Sralph 				gotone = 1;
81758793Sralph 				continue;
81857234Sralph 			}
81957234Sralph 
82058793Sralph 			if ((c = kbdMapChar(KEY_REPEAT)) >= 0) {
82157234Sralph 				(*linesw[tp->t_line].l_rint)(c, tp);
82258793Sralph 				gotone = 1;
82358793Sralph 			}
82457234Sralph 		}
82557234Sralph 	}
82658793Sralph 	if (gotone)
82758793Sralph 		timeout(dtop_keyboard_repeat, arg, hz / 20);
82858793Sralph 	else
82958793Sralph 		dev->keyboard.k_ar_state = K_AR_IDLE;
83058793Sralph 	splx(s);
83157234Sralph }
83256813Sralph #endif
833