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