xref: /netbsd-src/sys/arch/pmax/tc/dt.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: dt.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $	*/
29aa9b8ebSad 
39aa9b8ebSad /*-
49aa9b8ebSad  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
59aa9b8ebSad  * All rights reserved.
69aa9b8ebSad  *
79aa9b8ebSad  * This code is derived from software contributed to The NetBSD Foundation
89aa9b8ebSad  * by Andrew Doran.
99aa9b8ebSad  *
109aa9b8ebSad  * Redistribution and use in source and binary forms, with or without
119aa9b8ebSad  * modification, are permitted provided that the following conditions
129aa9b8ebSad  * are met:
139aa9b8ebSad  * 1. Redistributions of source code must retain the above copyright
149aa9b8ebSad  *    notice, this list of conditions and the following disclaimer.
159aa9b8ebSad  * 2. Redistributions in binary form must reproduce the above copyright
169aa9b8ebSad  *    notice, this list of conditions and the following disclaimer in the
179aa9b8ebSad  *    documentation and/or other materials provided with the distribution.
189aa9b8ebSad  *
199aa9b8ebSad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209aa9b8ebSad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219aa9b8ebSad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229aa9b8ebSad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239aa9b8ebSad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249aa9b8ebSad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259aa9b8ebSad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269aa9b8ebSad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279aa9b8ebSad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289aa9b8ebSad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299aa9b8ebSad  * POSSIBILITY OF SUCH DAMAGE.
309aa9b8ebSad  */
319aa9b8ebSad 
329aa9b8ebSad /*-
339aa9b8ebSad  * Copyright (c) 1992, 1993
349aa9b8ebSad  *	The Regents of the University of California.  All rights reserved.
359aa9b8ebSad  *
369aa9b8ebSad  * This code is derived from software contributed to Berkeley by
379aa9b8ebSad  * Ralph Campbell and Rick Macklem.
389aa9b8ebSad  *
399aa9b8ebSad  * Redistribution and use in source and binary forms, with or without
409aa9b8ebSad  * modification, are permitted provided that the following conditions
419aa9b8ebSad  * are met:
429aa9b8ebSad  * 1. Redistributions of source code must retain the above copyright
439aa9b8ebSad  *    notice, this list of conditions and the following disclaimer.
449aa9b8ebSad  * 2. Redistributions in binary form must reproduce the above copyright
459aa9b8ebSad  *    notice, this list of conditions and the following disclaimer in the
469aa9b8ebSad  *    documentation and/or other materials provided with the distribution.
479aa9b8ebSad  * 3. Neither the name of the University nor the names of its contributors
489aa9b8ebSad  *    may be used to endorse or promote products derived from this software
499aa9b8ebSad  *    without specific prior written permission.
509aa9b8ebSad  *
519aa9b8ebSad  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
529aa9b8ebSad  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
539aa9b8ebSad  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
549aa9b8ebSad  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
559aa9b8ebSad  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
569aa9b8ebSad  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
579aa9b8ebSad  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
589aa9b8ebSad  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
599aa9b8ebSad  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
609aa9b8ebSad  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
619aa9b8ebSad  * SUCH DAMAGE.
629aa9b8ebSad  *
639aa9b8ebSad  *	@(#)dtop.c	8.2 (Berkeley) 11/30/93
649aa9b8ebSad  */
659aa9b8ebSad 
669aa9b8ebSad /*
679aa9b8ebSad  * Mach Operating System
689aa9b8ebSad  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
699aa9b8ebSad  * All Rights Reserved.
709aa9b8ebSad  *
719aa9b8ebSad  * Permission to use, copy, modify and distribute this software and its
729aa9b8ebSad  * documentation is hereby granted, provided that both the copyright
739aa9b8ebSad  * notice and this permission notice appear in all copies of the
749aa9b8ebSad  * software, derivative works or modified versions, and any portions
759aa9b8ebSad  * thereof, and that both notices appear in supporting documentation.
769aa9b8ebSad  *
779aa9b8ebSad  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
789aa9b8ebSad  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
799aa9b8ebSad  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
809aa9b8ebSad  *
819aa9b8ebSad  * Carnegie Mellon requests users of this software to return to
829aa9b8ebSad  *
839aa9b8ebSad  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
849aa9b8ebSad  *  School of Computer Science
859aa9b8ebSad  *  Carnegie Mellon University
869aa9b8ebSad  *  Pittsburgh PA 15213-3890
879aa9b8ebSad  *
889aa9b8ebSad  * any improvements or extensions that they make and grant Carnegie the
899aa9b8ebSad  * rights to redistribute these changes.
909aa9b8ebSad  */
919aa9b8ebSad /*
929aa9b8ebSad  * 	Author: Alessandro Forin, Carnegie Mellon University
939aa9b8ebSad  *
949aa9b8ebSad  *	Hardware-level operations for the Desktop serial line
959aa9b8ebSad  *	bus (i2c aka ACCESS).
969aa9b8ebSad  */
979aa9b8ebSad /************************************************************
989aa9b8ebSad Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
999aa9b8ebSad and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
1009aa9b8ebSad 
1019aa9b8ebSad                         All Rights Reserved
1029aa9b8ebSad 
1039aa9b8ebSad Permission to use, copy, modify, and distribute this software and its
1049aa9b8ebSad documentation for any purpose and without fee is hereby granted,
1059aa9b8ebSad provided that the above copyright notice appear in all copies and that
1069aa9b8ebSad both that copyright notice and this permission notice appear in
1079aa9b8ebSad supporting documentation, and that the names of Digital or MIT not be
1089aa9b8ebSad used in advertising or publicity pertaining to distribution of the
1099aa9b8ebSad software without specific, written prior permission.
1109aa9b8ebSad 
1119aa9b8ebSad DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1129aa9b8ebSad ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1139aa9b8ebSad DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1149aa9b8ebSad ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1159aa9b8ebSad WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1169aa9b8ebSad ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1179aa9b8ebSad SOFTWARE.
1189aa9b8ebSad 
1199aa9b8ebSad ********************************************************/
1209aa9b8ebSad 
121520489e1Sad /*
122520489e1Sad  * ACCESS.bus device support for the Personal DECstation.  This code handles
123520489e1Sad  * only the keyboard and mouse, and will likely not work if other ACCESS.bus
124520489e1Sad  * devices are physically attached to the system.
125520489e1Sad  *
126520489e1Sad  * Since we do not know how to drive the hardware (the only reference being
127520489e1Sad  * Mach), we can't identify which devices are connected to the system by
128520489e1Sad  * sending idenfication requests.  With only a mouse and keyboard attached
129520489e1Sad  * to the system, we do know which two slave addresses will be in use.
130520489e1Sad  * However, we don't know which is the mouse, and which is the keyboard.
131520489e1Sad  * So, we resort to inspecting device reports and making an educated guess
132520489e1Sad  * as to which is which.
133520489e1Sad  */
134520489e1Sad 
1359aa9b8ebSad #include <sys/cdefs.h>
136*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: dt.c,v 1.16 2021/08/07 16:19:02 thorpej Exp $");
1379aa9b8ebSad 
1389aa9b8ebSad #include <sys/param.h>
1399aa9b8ebSad #include <sys/systm.h>
1409aa9b8ebSad #include <sys/tty.h>
1419aa9b8ebSad #include <sys/proc.h>
1429aa9b8ebSad #include <sys/conf.h>
1439aa9b8ebSad #include <sys/file.h>
1449aa9b8ebSad #include <sys/kernel.h>
1459aa9b8ebSad #include <sys/device.h>
146d206c345Sthorpej #include <sys/kmem.h>
14746ed8f7dSad #include <sys/intr.h>
1489aa9b8ebSad 
1499aa9b8ebSad #include <dev/dec/lk201.h>
1509aa9b8ebSad 
1519aa9b8ebSad #include <dev/tc/tcvar.h>
1529aa9b8ebSad #include <dev/tc/ioasicreg.h>
1539aa9b8ebSad #include <dev/tc/ioasicvar.h>
1549aa9b8ebSad 
1559aa9b8ebSad #include <pmax/pmax/maxine.h>
1569aa9b8ebSad 
1579aa9b8ebSad #include <pmax/tc/dtreg.h>
1589aa9b8ebSad #include <pmax/tc/dtvar.h>
1599aa9b8ebSad 
1609aa9b8ebSad #define	DT_BUF_CNT		16
1619aa9b8ebSad #define	DT_ESC_CHAR		0xf8
162520489e1Sad #define	DT_XMT_OK		0xfb
1639aa9b8ebSad #define	DT_MAX_POLL		0x70000		/* about half a sec */
1649aa9b8ebSad 
1659aa9b8ebSad #define	DT_GET_BYTE(data)	(((*(data)) >> 8) & 0xff)
1669aa9b8ebSad #define	DT_PUT_BYTE(data,c)	{ *(data) = (c) << 8; wbflush(); }
1679aa9b8ebSad 
1689aa9b8ebSad #define	DT_RX_AVAIL(poll)	((*(poll) & 1) != 0)
1699aa9b8ebSad #define	DT_TX_AVAIL(poll)	((*(poll) & 2) != 0)
1709aa9b8ebSad 
17103335d0bStsutsui int	dt_match(device_t, cfdata_t, void *);
17203335d0bStsutsui void	dt_attach(device_t, device_t, void *);
1739aa9b8ebSad int	dt_intr(void *);
1749aa9b8ebSad int	dt_print(void *, const char *);
1759aa9b8ebSad void	dt_strvis(uint8_t *, char *, int);
176520489e1Sad void	dt_dispatch(void *);
1779aa9b8ebSad 
1789aa9b8ebSad int	dt_kbd_addr = DT_ADDR_KBD;
179520489e1Sad struct	dt_device dt_kbd_dv;
180520489e1Sad int	dt_ms_addr = DT_ADDR_MOUSE;
181520489e1Sad struct	dt_device dt_ms_dv;
1829aa9b8ebSad struct	dt_state dt_state;
1839aa9b8ebSad 
18403335d0bStsutsui CFATTACH_DECL_NEW(dt, sizeof(struct dt_softc),
1859aa9b8ebSad     dt_match, dt_attach, NULL, NULL);
1869aa9b8ebSad 
1879aa9b8ebSad int
dt_match(device_t parent,cfdata_t cf,void * aux)18803335d0bStsutsui dt_match(device_t parent, cfdata_t cf, void *aux)
1899aa9b8ebSad {
1909aa9b8ebSad 	struct ioasicdev_attach_args *d;
1919aa9b8ebSad 
1929aa9b8ebSad 	d = aux;
1939aa9b8ebSad 
1949aa9b8ebSad 	if (strcmp(d->iada_modname, "dtop") != 0)
1959aa9b8ebSad 		return (0);
1969aa9b8ebSad 
19753524e44Schristos 	if (badaddr((void *)(d->iada_addr), 2))
1989aa9b8ebSad 		return (0);
1999aa9b8ebSad 
2009aa9b8ebSad 	return (1);
2019aa9b8ebSad }
2029aa9b8ebSad 
2039aa9b8ebSad void
dt_attach(device_t parent,device_t self,void * aux)20403335d0bStsutsui dt_attach(device_t parent, device_t self, void *aux)
2059aa9b8ebSad {
2069aa9b8ebSad 	struct ioasicdev_attach_args *d;
2079aa9b8ebSad 	struct dt_attach_args dta;
2089aa9b8ebSad 	struct dt_softc *sc;
2099aa9b8ebSad 	struct dt_msg *msg;
2109aa9b8ebSad 	int i;
2119aa9b8ebSad 
2129aa9b8ebSad 	d = aux;
21303335d0bStsutsui 	sc = device_private(self);
21403335d0bStsutsui 	sc->sc_dev = self;
2159aa9b8ebSad 
2169aa9b8ebSad 	dt_cninit();
2179aa9b8ebSad 
218d206c345Sthorpej 	msg = kmem_alloc(sizeof(*msg) * DT_BUF_CNT, KM_SLEEP);
21946ed8f7dSad 	sc->sc_sih = softint_establish(SOFTINT_SERIAL, dt_dispatch, sc);
220520489e1Sad 	if (sc->sc_sih == NULL) {
22103335d0bStsutsui 		printf("%s: memory exhausted\n", device_xname(self));
222d206c345Sthorpej 		kmem_free(msg, sizeof(*msg) * DT_BUF_CNT);
223204cdd3fSmaxv 		return;
224520489e1Sad 	}
225520489e1Sad 
226520489e1Sad 	SIMPLEQ_INIT(&sc->sc_queue);
2279aa9b8ebSad 	SLIST_INIT(&sc->sc_free);
2289aa9b8ebSad 	for (i = 0; i < DT_BUF_CNT; i++, msg++)
2299aa9b8ebSad 		SLIST_INSERT_HEAD(&sc->sc_free, msg, chain.slist);
2309aa9b8ebSad 
2319aa9b8ebSad 	ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY, dt_intr, sc);
2329aa9b8ebSad 	printf("\n");
2339aa9b8ebSad 
234520489e1Sad 	dta.dta_addr = DT_ADDR_KBD;
235*c7fb772bSthorpej 	config_found(self, &dta, dt_print, CFARGS_NONE);
236520489e1Sad 	dta.dta_addr = DT_ADDR_MOUSE;
237*c7fb772bSthorpej 	config_found(self, &dta, dt_print, CFARGS_NONE);
2389aa9b8ebSad }
2399aa9b8ebSad 
2409aa9b8ebSad void
dt_cninit(void)2419aa9b8ebSad dt_cninit(void)
2429aa9b8ebSad {
2439aa9b8ebSad 
2449aa9b8ebSad 	dt_state.ds_poll = (volatile u_int *)
2459aa9b8ebSad 	    MIPS_PHYS_TO_KSEG1(XINE_REG_INTR);
2469aa9b8ebSad 	dt_state.ds_data = (volatile u_int *)
2479aa9b8ebSad 	    MIPS_PHYS_TO_KSEG1(XINE_PHYS_TC_3_START + 0x280000);
2489aa9b8ebSad }
2499aa9b8ebSad 
2509aa9b8ebSad int
dt_print(void * aux,const char * pnp)2519aa9b8ebSad dt_print(void *aux, const char *pnp)
2529aa9b8ebSad {
2539aa9b8ebSad 
2549aa9b8ebSad 	return (QUIET);
2559aa9b8ebSad }
2569aa9b8ebSad 
2579aa9b8ebSad int
dt_establish_handler(struct dt_softc * sc,struct dt_device * dtdv,void * arg,void (* hdlr)(void *,struct dt_msg *))258520489e1Sad dt_establish_handler(struct dt_softc *sc, struct dt_device *dtdv,
25903335d0bStsutsui     void *arg, void (*hdlr)(void *, struct dt_msg *))
2609aa9b8ebSad {
2619aa9b8ebSad 
26203335d0bStsutsui 	dtdv->dtdv_arg = arg;
263520489e1Sad 	dtdv->dtdv_handler = hdlr;
2649aa9b8ebSad 	return (0);
2659aa9b8ebSad }
2669aa9b8ebSad 
2679aa9b8ebSad int
dt_intr(void * cookie)2689aa9b8ebSad dt_intr(void *cookie)
2699aa9b8ebSad {
2709aa9b8ebSad 	struct dt_softc *sc;
2719aa9b8ebSad 	struct dt_msg *msg, *pend;
2729aa9b8ebSad 
2739aa9b8ebSad 	sc = cookie;
2749aa9b8ebSad 
2759aa9b8ebSad 	switch (dt_msg_get(&sc->sc_msg, 1)) {
2769aa9b8ebSad 	case DT_GET_ERROR:
2779aa9b8ebSad 		/*
2789aa9b8ebSad 		 * Ugh! The most common occurrence of a data overrun is upon
2799aa9b8ebSad 		 * a key press and the result is a software generated "stuck
2809aa9b8ebSad 		 * key".  All I can think to do is fake an "all keys up"
2819aa9b8ebSad 		 * whenever a data overrun occurs.
2829aa9b8ebSad 		 */
2839aa9b8ebSad 		sc->sc_msg.src = dt_kbd_addr;
284520489e1Sad 		sc->sc_msg.ctl = DT_CTL(1, 0, 0);
2859aa9b8ebSad 		sc->sc_msg.body[0] = DT_KBD_EMPTY;
2869aa9b8ebSad #ifdef DIAGNOSTIC
2879aa9b8ebSad 		printf("%s: data overrun or stray interrupt\n",
28803335d0bStsutsui 		    device_xname(sc->sc_dev));
2899aa9b8ebSad #endif
2909aa9b8ebSad 		break;
2919aa9b8ebSad 
2929aa9b8ebSad 	case DT_GET_DONE:
2939aa9b8ebSad 		break;
2949aa9b8ebSad 
2959aa9b8ebSad 	case DT_GET_NOTYET:
2969aa9b8ebSad 		return (1);
2979aa9b8ebSad 	}
2989aa9b8ebSad 
2999aa9b8ebSad 	if ((msg = SLIST_FIRST(&sc->sc_free)) == NULL) {
30003335d0bStsutsui 		printf("%s: input overflow\n", device_xname(sc->sc_dev));
3019aa9b8ebSad 		return (1);
3029aa9b8ebSad 	}
3039aa9b8ebSad 	SLIST_REMOVE_HEAD(&sc->sc_free, chain.slist);
3049aa9b8ebSad 	memcpy(msg, &sc->sc_msg, sizeof(*msg));
3059aa9b8ebSad 
306520489e1Sad 	pend = SIMPLEQ_FIRST(&sc->sc_queue);
307520489e1Sad 	SIMPLEQ_INSERT_TAIL(&sc->sc_queue, msg, chain.simpleq);
3089aa9b8ebSad 	if (pend == NULL)
30946ed8f7dSad 		softint_schedule(sc->sc_sih);
3109aa9b8ebSad 
3119aa9b8ebSad 	return (1);
3129aa9b8ebSad }
3139aa9b8ebSad 
314520489e1Sad void
dt_dispatch(void * cookie)315520489e1Sad dt_dispatch(void *cookie)
316520489e1Sad {
317520489e1Sad 	struct dt_softc *sc;
318520489e1Sad 	struct dt_msg *msg;
3193eeb49f1Smhitch 	int s;
320520489e1Sad 	struct dt_device *dtdv;
321520489e1Sad 
322520489e1Sad 	sc = cookie;
323520489e1Sad 	msg = NULL;
324520489e1Sad 
325520489e1Sad 	for (;;) {
326520489e1Sad 		s = spltty();
3273eeb49f1Smhitch 		if (msg != NULL)
328520489e1Sad 			SLIST_INSERT_HEAD(&sc->sc_free, msg, chain.slist);
329520489e1Sad 		msg = SIMPLEQ_FIRST(&sc->sc_queue);
330520489e1Sad 		if (msg != NULL)
331520489e1Sad 			SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, chain.simpleq);
332520489e1Sad 		splx(s);
333520489e1Sad 		if (msg == NULL)
334520489e1Sad 			break;
335520489e1Sad 
3363eeb49f1Smhitch 		if (msg->src != DT_ADDR_MOUSE && msg->src != DT_ADDR_KBD) {
337520489e1Sad 			printf("%s: message from unknown dev 0x%x\n",
33803335d0bStsutsui 			    device_xname(sc->sc_dev), sc->sc_msg.src);
339520489e1Sad 			dt_msg_dump(msg);
340520489e1Sad 			continue;
341520489e1Sad 		}
342520489e1Sad 		if (DT_CTL_P(msg->ctl) != 0) {
343520489e1Sad 			printf("%s: received control message\n",
34403335d0bStsutsui 			    device_xname(sc->sc_dev));
345520489e1Sad 			dt_msg_dump(msg);
346520489e1Sad 			continue;
347520489e1Sad 		}
348520489e1Sad 
349520489e1Sad 		/*
3503eeb49f1Smhitch 		 * 1. Mouse should have no more than eight buttons, so first
3513eeb49f1Smhitch 		 *    8 bits of body will be zero.
352520489e1Sad 		 * 2. Mouse should always send full locator report.
3533eeb49f1Smhitch 		 *    Note:  my mouse does not send 'z' data, so the size
3543eeb49f1Smhitch 		 *    did not match the size of struct dt_locator_msg - mhitch
355520489e1Sad 		 * 3. Keyboard should never report all-up (0x00) in
356520489e1Sad 		 *    a packet with size > 1.
357520489e1Sad 		 */
3583eeb49f1Smhitch 		if (DT_CTL_LEN(msg->ctl) >= 6 &&
3593eeb49f1Smhitch 		    msg->body[0] == 0 && msg->src != dt_ms_addr) {
3603eeb49f1Smhitch 			dt_kbd_addr = dt_ms_addr;
3613eeb49f1Smhitch 			dt_ms_addr = msg->src;
3623eeb49f1Smhitch 		} else if (DT_CTL_LEN(msg->ctl) < 6 && msg->body[0] != 0 &&
3633eeb49f1Smhitch 		    msg->src != dt_kbd_addr) {
3643eeb49f1Smhitch 			dt_ms_addr = dt_kbd_addr;
3653eeb49f1Smhitch 			dt_kbd_addr = msg->src;
366520489e1Sad 		}
367520489e1Sad 
3683eeb49f1Smhitch 		if (msg->src == dt_kbd_addr)
3693eeb49f1Smhitch 			dtdv = &dt_kbd_dv;
3703eeb49f1Smhitch 		else
3713eeb49f1Smhitch 			dtdv = &dt_ms_dv;
3723eeb49f1Smhitch 
373520489e1Sad 		if (dtdv->dtdv_handler != NULL)
37403335d0bStsutsui 			(*dtdv->dtdv_handler)(dtdv->dtdv_arg, msg);
375520489e1Sad 	}
376520489e1Sad }
377520489e1Sad 
3789aa9b8ebSad int
dt_msg_get(struct dt_msg * msg,int intr)3799aa9b8ebSad dt_msg_get(struct dt_msg *msg, int intr)
3809aa9b8ebSad {
3819aa9b8ebSad 	volatile u_int *poll, *data;
3829aa9b8ebSad 	uint8_t c;
383abacafe4Sjmc 	int max_polls;
3849aa9b8ebSad 
3859aa9b8ebSad 	poll = dt_state.ds_poll;
3869aa9b8ebSad 	data = dt_state.ds_data;
3879aa9b8ebSad 
3889aa9b8ebSad 	/*
3899aa9b8ebSad 	 * The interface does not hand us the first byte, which is our
3909aa9b8ebSad 	 * address and cannot ever be anything else but 0x50.
3919aa9b8ebSad 	 */
3929aa9b8ebSad 	if (dt_state.ds_state == 0) {
3939aa9b8ebSad 		dt_state.ds_escaped = 0;
3949aa9b8ebSad 		dt_state.ds_ptr = 0;
3959aa9b8ebSad 	}
3969aa9b8ebSad 
3979aa9b8ebSad 	for (;;) {
398abacafe4Sjmc 		max_polls = DT_MAX_POLL;
3999aa9b8ebSad 
4009aa9b8ebSad 		while (!DT_RX_AVAIL(poll)) {
4019aa9b8ebSad 			if (intr)
4029aa9b8ebSad 				return (DT_GET_NOTYET);
403abacafe4Sjmc 			if (max_polls-- <= 0)
4049aa9b8ebSad 				break;
4059aa9b8ebSad 			DELAY(1);
4069aa9b8ebSad 		}
4079aa9b8ebSad 
408abacafe4Sjmc 		if (max_polls <= 0) {
4099aa9b8ebSad 			if (dt_state.ds_state != 0) {
4109aa9b8ebSad 				dt_state.ds_bad_pkts++;
4119aa9b8ebSad 				dt_state.ds_state = 0;
4129aa9b8ebSad 			}
4139aa9b8ebSad 			return (DT_GET_ERROR);
4149aa9b8ebSad 		}
4159aa9b8ebSad 
4169aa9b8ebSad 		c = DT_GET_BYTE(data);
4179aa9b8ebSad 
4189aa9b8ebSad 		if (dt_state.ds_escaped) {
4199aa9b8ebSad 			switch (c) {
4209aa9b8ebSad 			case 0xe8:
4219aa9b8ebSad 			case 0xe9:
4229aa9b8ebSad 			case 0xea:
4239aa9b8ebSad 			case 0xeb:
4249aa9b8ebSad 				c += 0x10;
4259aa9b8ebSad 				break;
4269aa9b8ebSad 			}
4279aa9b8ebSad 			if (c == 'O') {
4289aa9b8ebSad 				dt_state.ds_bad_pkts++;
4299aa9b8ebSad 				dt_state.ds_state = 0;
4309aa9b8ebSad 				return (DT_GET_ERROR);
4319aa9b8ebSad 			}
4329aa9b8ebSad 			dt_state.ds_escaped = 0;
4339aa9b8ebSad 		} else if (c == DT_ESC_CHAR) {
4349aa9b8ebSad 			dt_state.ds_escaped = 1;
4359aa9b8ebSad 			continue;
4369aa9b8ebSad 		}
4379aa9b8ebSad 
4389aa9b8ebSad 		if (dt_state.ds_state == 0) {
4399aa9b8ebSad 			msg->src = c;
4409aa9b8ebSad 			dt_state.ds_state = 1;
4419aa9b8ebSad 		} else if (dt_state.ds_state == 1) {
442520489e1Sad 			msg->ctl = c;
4439aa9b8ebSad 			dt_state.ds_state = 2;
444520489e1Sad 			dt_state.ds_len = DT_CTL_LEN(msg->ctl) + 1;
4459aa9b8ebSad 			if (dt_state.ds_len > sizeof(msg->body))
4469aa9b8ebSad 				printf("dt_msg_get: msg truncated: %d\n",
4479aa9b8ebSad 				    dt_state.ds_len);
4489aa9b8ebSad 		} else /* if (dt_state.ds_state == 2) */ {
4499aa9b8ebSad 			if (dt_state.ds_ptr < sizeof(msg->body))
4509aa9b8ebSad 				msg->body[dt_state.ds_ptr++] = c;
4519aa9b8ebSad 			if (dt_state.ds_ptr >= dt_state.ds_len)
4529aa9b8ebSad 				break;
4539aa9b8ebSad 		}
4549aa9b8ebSad 	}
4559aa9b8ebSad 
4569aa9b8ebSad 	msg->dst = DT_ADDR_HOST;
4579aa9b8ebSad 	dt_state.ds_state = 0;
4589aa9b8ebSad 	return (DT_GET_DONE);
4599aa9b8ebSad }
4609aa9b8ebSad 
4619aa9b8ebSad void
dt_msg_dump(struct dt_msg * msg)462520489e1Sad dt_msg_dump(struct dt_msg *msg)
4639aa9b8ebSad {
464520489e1Sad 	int i, l;
4659aa9b8ebSad 
466520489e1Sad 	l = DT_CTL_LEN(msg->ctl);
467520489e1Sad 
468520489e1Sad 	printf("hdr: dst=%02x src=%02x p=%02x sub=%02x len=%02x\n",
469520489e1Sad 	   msg->dst, msg->src, DT_CTL_P(msg->ctl), DT_CTL_SUBADDR(msg->ctl),
470520489e1Sad 	   l);
471520489e1Sad 
472520489e1Sad 	printf("body: ");
473520489e1Sad 	for (i = 0; i < l && i < 20; i++)
474520489e1Sad 		printf("%02x ", msg->body[i]);
475520489e1Sad 	if (i < l) {
476520489e1Sad 		printf("\n");
477520489e1Sad 		for (; i < l; i++)
478520489e1Sad 			printf("%02x ", msg->body[i]);
4799aa9b8ebSad 	}
480520489e1Sad 	printf("\n");
4819aa9b8ebSad }
482