xref: /netbsd-src/sys/arch/arm/iomd/qms.c (revision f82ca6eefb335bf699131a4ebe4cc00c8911db8a)
1*f82ca6eeSskrll /*	$NetBSD: qms.c,v 1.22 2022/09/27 06:36:42 skrll Exp $	*/
2e4247411Sbjh21 
3e4247411Sbjh21 /*-
4e4247411Sbjh21  * Copyright (c) 2001 Reinoud Zandijk
5e4247411Sbjh21  * All rights reserved.
6e4247411Sbjh21  *
7e4247411Sbjh21  * This code is derived from software contributed to The NetBSD Foundation
8e4247411Sbjh21  * by Reinoud Zandijk
9e4247411Sbjh21  *
10e4247411Sbjh21  * Redistribution and use in source and binary forms, with or without
11e4247411Sbjh21  * modification, are permitted provided that the following conditions
12e4247411Sbjh21  * are met:
13e4247411Sbjh21  * 1. Redistributions of source code must retain the above copyright
14e4247411Sbjh21  *    notice, this list of conditions and the following disclaimer.
15e4247411Sbjh21  * 2. Redistributions in binary form must reproduce the above copyright
16e4247411Sbjh21  *    notice, this list of conditions and the following disclaimer in the
17e4247411Sbjh21  *    documentation and/or other materials provided with the distribution.
18e4247411Sbjh21  *
19e4247411Sbjh21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20e4247411Sbjh21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21e4247411Sbjh21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22e4247411Sbjh21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23e4247411Sbjh21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24e4247411Sbjh21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25e4247411Sbjh21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26e4247411Sbjh21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27e4247411Sbjh21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28e4247411Sbjh21  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29e4247411Sbjh21  * POSSIBILITY OF SUCH DAMAGE.
30e4247411Sbjh21  */
31e4247411Sbjh21 /*
32e4247411Sbjh21  * Quadrature mouse driver for the wscons as used in the IOMD
33e4247411Sbjh21  */
34e4247411Sbjh21 
35e4247411Sbjh21 #include <sys/param.h>
36e4247411Sbjh21 
37*f82ca6eeSskrll __KERNEL_RCSID(0, "$NetBSD: qms.c,v 1.22 2022/09/27 06:36:42 skrll Exp $");
38e4247411Sbjh21 
39e4247411Sbjh21 #include <sys/callout.h>
40e4247411Sbjh21 #include <sys/device.h>
41e4247411Sbjh21 #include <sys/errno.h>
42e4247411Sbjh21 #include <sys/ioctl.h>
43e4247411Sbjh21 #include <sys/kernel.h>
44e4247411Sbjh21 #include <sys/proc.h>
45e4247411Sbjh21 #include <sys/tty.h>
46e4247411Sbjh21 #include <sys/types.h>
47e4247411Sbjh21 #include <sys/syslog.h>
48e4247411Sbjh21 #include <sys/systm.h>
49e4247411Sbjh21 #include <sys/select.h>
50e4247411Sbjh21 
51ed9977b1Sdyoung #include <sys/bus.h>
52e4247411Sbjh21 #include <machine/intr.h>
53e4247411Sbjh21 
54e4247411Sbjh21 #include <arm/iomd/iomdvar.h>
55e4247411Sbjh21 
56e4247411Sbjh21 #include <dev/wscons/wsconsio.h>
57e4247411Sbjh21 #include <dev/wscons/wsmousevar.h>
58e4247411Sbjh21 
59e4247411Sbjh21 struct qms_softc {
60e0f866efSskrll 	device_t sc_dev;
61e0f866efSskrll 	device_t sc_wsmousedev;
62e4247411Sbjh21 
63e4247411Sbjh21 	bus_space_tag_t sc_iot;		/* bus tag */
64e4247411Sbjh21 	bus_space_handle_t sc_ioh;	/* bus handle for XY */
65e4247411Sbjh21 	bus_space_handle_t sc_butioh;	/* bus handle for buttons */
66e4247411Sbjh21 
67e4247411Sbjh21 	struct callout sc_callout;
68e4247411Sbjh21 
699ea87d7dSskrll 	uint16_t lastx;
709ea87d7dSskrll 	uint16_t lasty;
71e4247411Sbjh21 	int lastb;
72e4247411Sbjh21 };
73e4247411Sbjh21 
74e4247411Sbjh21 /* Offsets of hardware registers */
75e4247411Sbjh21 #define QMS_MOUSEX	0		/* 16 bits X register */
76e4247411Sbjh21 #define QMS_MOUSEY	1		/* 16 bits Y register */
77e4247411Sbjh21 #define QMS_BUTTONS	0 		/* mouse buttons in bits 4,5,6 */
78e4247411Sbjh21 
79e0f866efSskrll static int  qms_match(device_t , cfdata_t , void *);
80e0f866efSskrll static void qms_attach(device_t , device_t , void *);
81e4247411Sbjh21 
82e4247411Sbjh21 static int qms_enable(void *);
8353524e44Schristos static int qms_ioctl(void *, u_long, void *, int, struct lwp *);
84e4247411Sbjh21 static void qms_disable(void *cookie);
85e4247411Sbjh21 static void qms_intr(void *arg);
86e4247411Sbjh21 
87e0f866efSskrll CFATTACH_DECL_NEW(qms, sizeof(struct qms_softc),
88e4247411Sbjh21     qms_match, qms_attach, NULL, NULL);
89e4247411Sbjh21 
90e4247411Sbjh21 static struct wsmouse_accessops qms_accessops = {
91e4247411Sbjh21 	qms_enable, qms_ioctl, qms_disable
92e4247411Sbjh21 };
93e4247411Sbjh21 
94e4247411Sbjh21 
95e4247411Sbjh21 static int
qms_match(device_t parent,cfdata_t cf,void * aux)96e0f866efSskrll qms_match(device_t parent, cfdata_t cf, void *aux)
97e4247411Sbjh21 {
98e4247411Sbjh21 	struct qms_attach_args *qa = aux;
99e4247411Sbjh21 
100e4247411Sbjh21 	if (strcmp(qa->qa_name, "qms") == 0)
101758ec341Sbjh21 		return 1;
102e4247411Sbjh21 
103758ec341Sbjh21 	return 0;
104e4247411Sbjh21 }
105e4247411Sbjh21 
106e4247411Sbjh21 
107e4247411Sbjh21 static void
qms_attach(device_t parent,device_t self,void * aux)108e0f866efSskrll qms_attach(device_t parent, device_t self, void *aux)
109e4247411Sbjh21 {
110e0f866efSskrll 	struct qms_softc *sc = device_private(self);
111e4247411Sbjh21 	struct qms_attach_args *qa = aux;
112e4247411Sbjh21 	struct wsmousedev_attach_args wsmouseargs;
113e4247411Sbjh21 
114e0f866efSskrll 	sc->sc_dev = self;
115e4247411Sbjh21 	sc->sc_iot = qa->qa_iot;
116e4247411Sbjh21 	sc->sc_ioh = qa->qa_ioh;
117e4247411Sbjh21 	sc->sc_butioh = qa->qa_ioh_but;
118e4247411Sbjh21 
119e4247411Sbjh21 	/* set up wsmouse attach arguments */
120e4247411Sbjh21 	wsmouseargs.accessops = &qms_accessops;
121e4247411Sbjh21 	wsmouseargs.accesscookie = sc;
122e4247411Sbjh21 
123e0f866efSskrll 	aprint_normal("\n");
124e4247411Sbjh21 
125e4247411Sbjh21 	sc->sc_wsmousedev =
126c7fb772bSthorpej 	    config_found(sc->sc_dev, &wsmouseargs, wsmousedevprint, CFARGS_NONE);
127e4247411Sbjh21 
12888ab7da9Sad 	callout_init(&sc->sc_callout, 0);
129e4247411Sbjh21 }
130e4247411Sbjh21 
131e4247411Sbjh21 
132e4247411Sbjh21 static int
qms_enable(void * cookie)133e4247411Sbjh21 qms_enable(void *cookie)
134e4247411Sbjh21 {
135e4247411Sbjh21 	struct qms_softc *sc = cookie;
136e4247411Sbjh21 	int b;
137e4247411Sbjh21 
138e4247411Sbjh21 	/* We don't want the mouse to warp on open. */
139e4247411Sbjh21 	sc->lastx = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEX);
140e4247411Sbjh21 	sc->lasty = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEY);
141e4247411Sbjh21 	b = bus_space_read_1(sc->sc_iot, sc->sc_butioh, QMS_BUTTONS) & 0x70;
142e4247411Sbjh21 
143e4247411Sbjh21 	/* patch up the buttons */
144e4247411Sbjh21 	b >>= 4;
145e4247411Sbjh21 	sc->lastb = ~( ((b & 1)<<2) | (b & 2) | ((b & 4)>>2));
146e4247411Sbjh21 
147e4247411Sbjh21 	callout_reset(&sc->sc_callout, hz / 100, qms_intr, sc);
148e4247411Sbjh21 	return 0;
149e4247411Sbjh21 }
150e4247411Sbjh21 
151e4247411Sbjh21 
152e4247411Sbjh21 static void
qms_disable(void * cookie)153e4247411Sbjh21 qms_disable(void *cookie)
154e4247411Sbjh21 {
155e4247411Sbjh21 	struct qms_softc *sc = cookie;
156e4247411Sbjh21 
157e4247411Sbjh21 	callout_stop(&sc->sc_callout);
158e4247411Sbjh21 }
159e4247411Sbjh21 
160e4247411Sbjh21 
161e4247411Sbjh21 static int
qms_ioctl(void * cookie,u_long cmd,void * data,int flag,struct lwp * l)16253524e44Schristos qms_ioctl(void *cookie, u_long cmd, void *data, int flag, struct lwp *l)
163e4247411Sbjh21 {
164e4247411Sbjh21 
165e4247411Sbjh21 	switch (cmd) {
166e4247411Sbjh21 	case WSMOUSEIO_GTYPE:
167e4247411Sbjh21 		*(int *)data = WSMOUSE_TYPE_ARCHIMEDES;
168e4247411Sbjh21 		return 0;
169e4247411Sbjh21 	}
170e4247411Sbjh21 
171e4247411Sbjh21 	return EPASSTHROUGH;
172e4247411Sbjh21 }
173e4247411Sbjh21 
174e4247411Sbjh21 
175e4247411Sbjh21 static void
qms_intr(void * arg)176e4247411Sbjh21 qms_intr(void *arg)
177e4247411Sbjh21 {
178e4247411Sbjh21 	struct qms_softc *sc = arg;
179e4247411Sbjh21 	int b;
1809ea87d7dSskrll 	uint16_t x, y;
181e4247411Sbjh21 	int16_t dx, dy;
182e4247411Sbjh21 
183e4247411Sbjh21 	x = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEX);
184e4247411Sbjh21 	y = bus_space_read_4(sc->sc_iot, sc->sc_ioh, QMS_MOUSEY);
185e4247411Sbjh21 	b = bus_space_read_1(sc->sc_iot, sc->sc_butioh, QMS_BUTTONS) & 0x70;
186e4247411Sbjh21 
187e4247411Sbjh21 	/* patch up the buttons */
188e4247411Sbjh21 	b >>= 4;
189e4247411Sbjh21 	b = ~( ((b & 1)<<2) | (b & 2) | ((b & 4)>>2));
190e4247411Sbjh21 
191e4247411Sbjh21 	if ((x != sc->lastx) || (y != sc->lasty) || (b != sc->lastb)) {
192e4247411Sbjh21 		/* This assumes that int16_t is two's complement. */
193e4247411Sbjh21 		dx = x - sc->lastx;
194e4247411Sbjh21 		dy = y - sc->lasty;
19557c0199dSplunky 		wsmouse_input(sc->sc_wsmousedev,
19657c0199dSplunky 				b,
19757c0199dSplunky 				dx, dy, 0, 0,
198e4247411Sbjh21 				WSMOUSE_INPUT_DELTA);
199e4247411Sbjh21 
200e4247411Sbjh21 		/* save old values */
201e4247411Sbjh21 		sc->lastx = x;
202e4247411Sbjh21 		sc->lasty = y;
203e4247411Sbjh21 		sc->lastb = b;
204758ec341Sbjh21 	}
205e4247411Sbjh21 	callout_reset(&sc->sc_callout, hz / 100, qms_intr, sc);
206e4247411Sbjh21 }
207e4247411Sbjh21 
208e4247411Sbjh21 
209e4247411Sbjh21 /* end of qms.c */
210