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