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 = ¤tRep;
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