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