1*c7fb772bSthorpej /* $NetBSD: qvms.c,v 1.3 2021/08/07 16:19:07 thorpej Exp $ */
2e95f8d8cSmatt
3e95f8d8cSmatt /* Copyright (c) 2015 Charles H. Dickman. All rights reserved.
4e95f8d8cSmatt * Derived from dzms.c
5e95f8d8cSmatt *
6e95f8d8cSmatt * Copyright (c) 1992, 1993
7e95f8d8cSmatt * The Regents of the University of California. All rights reserved.
8e95f8d8cSmatt *
9e95f8d8cSmatt * This software was developed by the Computer Systems Engineering group
10e95f8d8cSmatt * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11e95f8d8cSmatt * contributed to Berkeley.
12e95f8d8cSmatt *
13e95f8d8cSmatt * All advertising materials mentioning features or use of this software
14e95f8d8cSmatt * must display the following acknowledgement:
15e95f8d8cSmatt * This product includes software developed by the University of
16e95f8d8cSmatt * California, Lawrence Berkeley Laboratory.
17e95f8d8cSmatt *
18e95f8d8cSmatt * Redistribution and use in source and binary forms, with or without
19e95f8d8cSmatt * modification, are permitted provided that the following conditions
20e95f8d8cSmatt * are met:
21e95f8d8cSmatt * 1. Redistributions of source code must retain the above copyright
22e95f8d8cSmatt * notice, this list of conditions and the following disclaimer.
23e95f8d8cSmatt * 2. Redistributions in binary form must reproduce the above copyright
24e95f8d8cSmatt * notice, this list of conditions and the following disclaimer in the
25e95f8d8cSmatt * documentation and/or other materials provided with the distribution.
26e95f8d8cSmatt * 3. Neither the name of the University nor the names of its contributors
27e95f8d8cSmatt * may be used to endorse or promote products derived from this software
28e95f8d8cSmatt * without specific prior written permission.
29e95f8d8cSmatt *
30e95f8d8cSmatt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31e95f8d8cSmatt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32e95f8d8cSmatt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33e95f8d8cSmatt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34e95f8d8cSmatt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35e95f8d8cSmatt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36e95f8d8cSmatt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37e95f8d8cSmatt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38e95f8d8cSmatt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39e95f8d8cSmatt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40e95f8d8cSmatt * SUCH DAMAGE.
41e95f8d8cSmatt *
42e95f8d8cSmatt * @(#)ms.c 8.1 (Berkeley) 6/11/93
43e95f8d8cSmatt */
44e95f8d8cSmatt
45e95f8d8cSmatt /*
46e95f8d8cSmatt * VSXXX mice attached to line 1 of the QVSS
47e95f8d8cSmatt */
48e95f8d8cSmatt
49e95f8d8cSmatt #include <sys/cdefs.h>
50*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: qvms.c,v 1.3 2021/08/07 16:19:07 thorpej Exp $");
51e95f8d8cSmatt
52e95f8d8cSmatt #include <sys/param.h>
53e95f8d8cSmatt #include <sys/systm.h>
54e95f8d8cSmatt #include <sys/device.h>
55e95f8d8cSmatt #include <sys/ioctl.h>
56e95f8d8cSmatt #include <sys/syslog.h>
57e95f8d8cSmatt #include <sys/kernel.h>
58e95f8d8cSmatt #include <sys/proc.h>
59e95f8d8cSmatt #include <sys/tty.h>
60e95f8d8cSmatt
61e95f8d8cSmatt #include <sys/bus.h>
62e95f8d8cSmatt
63e95f8d8cSmatt #include <vax/uba/qvareg.h>
64e95f8d8cSmatt #include <vax/uba/qvavar.h>
65e95f8d8cSmatt #include <vax/uba/qvkbdvar.h>
66e95f8d8cSmatt #include <dev/dec/lk201.h>
67e95f8d8cSmatt
68e95f8d8cSmatt #include <dev/wscons/wsconsio.h>
69e95f8d8cSmatt #include <dev/wscons/wsmousevar.h>
70e95f8d8cSmatt
71e95f8d8cSmatt #include "locators.h"
72e95f8d8cSmatt
73e95f8d8cSmatt struct qvms_softc { /* driver status information */
74e95f8d8cSmatt struct device qvms_dev; /* required first: base device */
75e95f8d8cSmatt struct qvaux_linestate *qvms_ls;
76e95f8d8cSmatt
77e95f8d8cSmatt int sc_enabled; /* input enabled? */
78e95f8d8cSmatt int sc_selftest;
79e95f8d8cSmatt
80e95f8d8cSmatt int inputstate;
81e95f8d8cSmatt u_int buttons;
82e95f8d8cSmatt int dx, dy;
83e95f8d8cSmatt
84e95f8d8cSmatt device_t sc_wsmousedev;
85e95f8d8cSmatt };
86e95f8d8cSmatt
87e95f8d8cSmatt static int qvms_match(device_t, cfdata_t, void *);
88e95f8d8cSmatt static void qvms_attach(device_t, device_t, void *);
89e95f8d8cSmatt static int qvms_input(void *, int);
90e95f8d8cSmatt
91e95f8d8cSmatt CFATTACH_DECL_NEW(qvms, sizeof(struct qvms_softc),
92e95f8d8cSmatt qvms_match, qvms_attach, NULL, NULL);
93e95f8d8cSmatt
94e95f8d8cSmatt static int qvms_enable(void *);
95e95f8d8cSmatt static int qvms_ioctl(void *, u_long, void *, int, struct lwp *);
96e95f8d8cSmatt static void qvms_disable(void *);
97e95f8d8cSmatt
98e95f8d8cSmatt const struct wsmouse_accessops qvms_accessops = {
99e95f8d8cSmatt qvms_enable,
100e95f8d8cSmatt qvms_ioctl,
101e95f8d8cSmatt qvms_disable,
102e95f8d8cSmatt };
103e95f8d8cSmatt
104e95f8d8cSmatt static int
qvms_match(device_t parent,cfdata_t cf,void * aux)105e95f8d8cSmatt qvms_match(device_t parent, cfdata_t cf, void *aux)
106e95f8d8cSmatt {
107e95f8d8cSmatt struct qvauxkm_attach_args *daa = aux;
108e95f8d8cSmatt
109e95f8d8cSmatt /* Exact match is better than wildcard. */
110e95f8d8cSmatt if (cf->cf_loc[QVAUXCF_LINE] == daa->daa_line)
111e95f8d8cSmatt return 2;
112e95f8d8cSmatt
113e95f8d8cSmatt /* This driver accepts wildcard. */
114e95f8d8cSmatt if (cf->cf_loc[QVAUXCF_LINE] == QVAUXCF_LINE_DEFAULT)
115e95f8d8cSmatt return 1;
116e95f8d8cSmatt
117e95f8d8cSmatt return 0;
118e95f8d8cSmatt }
119e95f8d8cSmatt
120e95f8d8cSmatt static void
qvms_attach(device_t parent,device_t self,void * aux)121e95f8d8cSmatt qvms_attach(device_t parent, device_t self, void *aux)
122e95f8d8cSmatt {
123e95f8d8cSmatt struct qvaux_softc *qvaux = device_private(parent);
124e95f8d8cSmatt struct qvms_softc *qvms = device_private(self);
125e95f8d8cSmatt struct qvauxkm_attach_args *daa = aux;
126e95f8d8cSmatt struct qvaux_linestate *ls;
127e95f8d8cSmatt struct wsmousedev_attach_args a;
128e95f8d8cSmatt
129e95f8d8cSmatt qvaux->sc_qvaux[daa->daa_line].qvaux_catch = qvms_input;
130e95f8d8cSmatt qvaux->sc_qvaux[daa->daa_line].qvaux_private = qvms;
131e95f8d8cSmatt ls = &qvaux->sc_qvaux[daa->daa_line];
132e95f8d8cSmatt qvms->qvms_ls = ls;
133e95f8d8cSmatt
134e95f8d8cSmatt printf("\n");
135e95f8d8cSmatt
136e95f8d8cSmatt a.accessops = &qvms_accessops;
137e95f8d8cSmatt a.accesscookie = qvms;
138e95f8d8cSmatt
139e95f8d8cSmatt qvms->sc_enabled = 0;
140e95f8d8cSmatt qvms->sc_selftest = 0;
1412685996bSthorpej qvms->sc_wsmousedev = config_found(self, &a, wsmousedevprint,
142*c7fb772bSthorpej CFARGS_NONE);
143e95f8d8cSmatt }
144e95f8d8cSmatt
145e95f8d8cSmatt static int
qvms_enable(void * v)146e95f8d8cSmatt qvms_enable(void *v)
147e95f8d8cSmatt {
148e95f8d8cSmatt struct qvms_softc *sc = v;
149e95f8d8cSmatt
150e95f8d8cSmatt if (sc->sc_enabled)
151e95f8d8cSmatt return EBUSY;
152e95f8d8cSmatt
153e95f8d8cSmatt sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */
154e95f8d8cSmatt qvauxputc(sc->qvms_ls, MOUSE_SELF_TEST);
155e95f8d8cSmatt (void)tsleep(qvms_enable, TTIPRI, "qvmsopen", hz / 2);
156e95f8d8cSmatt if (sc->sc_selftest != 0) {
157e95f8d8cSmatt sc->sc_selftest = 0;
158e95f8d8cSmatt return ENXIO;
159e95f8d8cSmatt }
160e95f8d8cSmatt DELAY(150);
161e95f8d8cSmatt qvauxputc(sc->qvms_ls, MOUSE_INCREMENTAL);
162e95f8d8cSmatt sc->sc_enabled = 1;
163e95f8d8cSmatt sc->inputstate = 0;
164e95f8d8cSmatt return 0;
165e95f8d8cSmatt }
166e95f8d8cSmatt
167e95f8d8cSmatt static void
qvms_disable(void * v)168e95f8d8cSmatt qvms_disable(void *v)
169e95f8d8cSmatt {
170e95f8d8cSmatt struct qvms_softc *sc = v;
171e95f8d8cSmatt
172e95f8d8cSmatt sc->sc_enabled = 0;
173e95f8d8cSmatt }
174e95f8d8cSmatt
175e95f8d8cSmatt static int
qvms_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)176e95f8d8cSmatt qvms_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
177e95f8d8cSmatt {
178e95f8d8cSmatt if (cmd == WSMOUSEIO_GTYPE) {
179e95f8d8cSmatt *(u_int *)data = WSMOUSE_TYPE_VSXXX;
180e95f8d8cSmatt return 0;
181e95f8d8cSmatt }
182e95f8d8cSmatt return EPASSTHROUGH;
183e95f8d8cSmatt }
184e95f8d8cSmatt
185e95f8d8cSmatt static int
qvms_input(void * vsc,int data)186e95f8d8cSmatt qvms_input(void *vsc, int data)
187e95f8d8cSmatt {
188e95f8d8cSmatt struct qvms_softc *sc = vsc;
189e95f8d8cSmatt
190e95f8d8cSmatt if (sc->sc_enabled == 0) {
191e95f8d8cSmatt if (sc->sc_selftest > 0) {
192e95f8d8cSmatt sc->sc_selftest -= 1;
193e95f8d8cSmatt if (sc->sc_selftest == 0)
194e95f8d8cSmatt wakeup(qvms_enable);
195e95f8d8cSmatt }
196e95f8d8cSmatt return (1);
197e95f8d8cSmatt }
198e95f8d8cSmatt
199e95f8d8cSmatt #define WSMS_BUTTON1 0x01
200e95f8d8cSmatt #define WSMS_BUTTON2 0x02
201e95f8d8cSmatt #define WSMS_BUTTON3 0x04
202e95f8d8cSmatt
203e95f8d8cSmatt if ((data & MOUSE_START_FRAME) != 0)
204e95f8d8cSmatt sc->inputstate = 1;
205e95f8d8cSmatt else
206e95f8d8cSmatt sc->inputstate++;
207e95f8d8cSmatt
208e95f8d8cSmatt if (sc->inputstate == 1) {
209e95f8d8cSmatt sc->buttons = 0;
210e95f8d8cSmatt if ((data & LEFT_BUTTON) != 0)
211e95f8d8cSmatt sc->buttons |= WSMS_BUTTON1;
212e95f8d8cSmatt if ((data & MIDDLE_BUTTON) != 0)
213e95f8d8cSmatt sc->buttons |= WSMS_BUTTON2;
214e95f8d8cSmatt if ((data & RIGHT_BUTTON) != 0)
215e95f8d8cSmatt sc->buttons |= WSMS_BUTTON3;
216e95f8d8cSmatt
217e95f8d8cSmatt sc->dx = data & MOUSE_X_SIGN;
218e95f8d8cSmatt sc->dy = data & MOUSE_Y_SIGN;
219e95f8d8cSmatt } else if (sc->inputstate == 2) {
220e95f8d8cSmatt if (sc->dx == 0)
221e95f8d8cSmatt sc->dx = -data;
222e95f8d8cSmatt else
223e95f8d8cSmatt sc->dx = data;
224e95f8d8cSmatt } else if (sc->inputstate == 3) {
225e95f8d8cSmatt sc->inputstate = 0;
226e95f8d8cSmatt if (sc->dy == 0)
227e95f8d8cSmatt sc->dy = -data;
228e95f8d8cSmatt else
229e95f8d8cSmatt sc->dy = data;
230e95f8d8cSmatt wsmouse_input(sc->sc_wsmousedev,
231e95f8d8cSmatt sc->buttons,
232e95f8d8cSmatt sc->dx, sc->dy, 0, 0,
233e95f8d8cSmatt WSMOUSE_INPUT_DELTA);
234e95f8d8cSmatt }
235e95f8d8cSmatt
236e95f8d8cSmatt return(1);
237e95f8d8cSmatt }
238e95f8d8cSmatt
239