1*5ab06420Sthorpej /* $NetBSD: opms.c,v 1.26 2021/09/26 16:36:18 thorpej Exp $ */
2b7abba77Ssoda /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */
3b7abba77Ssoda /* NetBSD: pms.c,v 1.21 1995/04/18 02:25:18 mycroft Exp */
4b7abba77Ssoda
5b7abba77Ssoda /*-
6b7abba77Ssoda * Copyright (c) 1990 The Regents of the University of California.
7b7abba77Ssoda * All rights reserved.
8b7abba77Ssoda *
9b7abba77Ssoda * This code is derived from software contributed to Berkeley by
10b7abba77Ssoda * William Jolitz and Don Ahn.
11b7abba77Ssoda *
12b7abba77Ssoda * Copyright (c) 1994 Charles M. Hannum.
13b7abba77Ssoda * Copyright (c) 1992, 1993 Erik Forsberg.
14b7abba77Ssoda *
15b7abba77Ssoda * Redistribution and use in source and binary forms, with or without
16b7abba77Ssoda * modification, are permitted provided that the following conditions
17b7abba77Ssoda * are met:
18b7abba77Ssoda * 1. Redistributions of source code must retain the above copyright
19b7abba77Ssoda * notice, this list of conditions and the following disclaimer.
20b7abba77Ssoda * 2. Redistributions in binary form must reproduce the above copyright
21b7abba77Ssoda * notice, this list of conditions and the following disclaimer in the
22b7abba77Ssoda * documentation and/or other materials provided with the distribution.
23aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
24aad01611Sagc * may be used to endorse or promote products derived from this software
25aad01611Sagc * without specific prior written permission.
26aad01611Sagc *
27aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37aad01611Sagc * SUCH DAMAGE.
38aad01611Sagc *
39aad01611Sagc * @(#)pccons.c 5.11 (Berkeley) 5/21/91
40aad01611Sagc */
41aad01611Sagc
42aad01611Sagc /*-
43aad01611Sagc * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
44aad01611Sagc *
45aad01611Sagc * This code is derived from software contributed to Berkeley by
46aad01611Sagc * William Jolitz and Don Ahn.
47aad01611Sagc *
48aad01611Sagc * Copyright (c) 1994 Charles M. Hannum.
49aad01611Sagc * Copyright (c) 1992, 1993 Erik Forsberg.
50aad01611Sagc *
51aad01611Sagc * Redistribution and use in source and binary forms, with or without
52aad01611Sagc * modification, are permitted provided that the following conditions
53aad01611Sagc * are met:
54aad01611Sagc * 1. Redistributions of source code must retain the above copyright
55aad01611Sagc * notice, this list of conditions and the following disclaimer.
56aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright
57aad01611Sagc * notice, this list of conditions and the following disclaimer in the
58aad01611Sagc * documentation and/or other materials provided with the distribution.
59b7abba77Ssoda * 3. All advertising materials mentioning features or use of this software
60b7abba77Ssoda * must display the following acknowledgement:
61b7abba77Ssoda * This product includes software developed by the University of
62b7abba77Ssoda * California, Berkeley and its contributors.
63b7abba77Ssoda * 4. Neither the name of the University nor the names of its contributors
64b7abba77Ssoda * may be used to endorse or promote products derived from this software
65b7abba77Ssoda * without specific prior written permission.
66b7abba77Ssoda *
67b7abba77Ssoda * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
68b7abba77Ssoda * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69b7abba77Ssoda * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
70b7abba77Ssoda * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
71b7abba77Ssoda * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72b7abba77Ssoda * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
73b7abba77Ssoda * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
74b7abba77Ssoda * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
75b7abba77Ssoda * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
76b7abba77Ssoda * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77b7abba77Ssoda * SUCH DAMAGE.
78b7abba77Ssoda *
79b7abba77Ssoda * @(#)pccons.c 5.11 (Berkeley) 5/21/91
80b7abba77Ssoda */
81b7abba77Ssoda
82a4183603Slukem #include <sys/cdefs.h>
83*5ab06420Sthorpej __KERNEL_RCSID(0, "$NetBSD: opms.c,v 1.26 2021/09/26 16:36:18 thorpej Exp $");
84a4183603Slukem
85b7abba77Ssoda #include <sys/param.h>
86b7abba77Ssoda #include <sys/systm.h>
87b7abba77Ssoda #include <sys/vnode.h>
88b7abba77Ssoda #include <sys/poll.h>
89b7abba77Ssoda #include <sys/tty.h>
90b7abba77Ssoda #include <sys/device.h>
9180373b7eSchs #include <sys/proc.h>
9277a6b82bSgehenna #include <sys/conf.h>
93b7abba77Ssoda
94cf10107dSdyoung #include <sys/bus.h>
95b7abba77Ssoda #include <machine/kbdreg.h>
96b7abba77Ssoda #include <machine/mouse.h>
97b7abba77Ssoda
98b7abba77Ssoda #include <arc/dev/pcconsvar.h>
99b7abba77Ssoda #include <arc/dev/opmsvar.h>
100b7abba77Ssoda
101c234c43aStsutsui #include "ioconf.h"
102c234c43aStsutsui
103b7abba77Ssoda #define PMSUNIT(dev) (minor(dev))
104b7abba77Ssoda
105b7abba77Ssoda /* status bits */
106b7abba77Ssoda #define PMS_OBUF_FULL 0x01
107b7abba77Ssoda #define PMS_IBUF_FULL 0x02
108b7abba77Ssoda
109b7abba77Ssoda /* controller commands */
110b7abba77Ssoda #define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
111b7abba77Ssoda #define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
112b7abba77Ssoda #define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */
113b7abba77Ssoda #define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */
114b7abba77Ssoda #define PMS_MAGIC_1 0xa9 /* XXX */
115b7abba77Ssoda
116b7abba77Ssoda #define PMS_8042_CMD 0x65
117b7abba77Ssoda
118b7abba77Ssoda /* mouse commands */
119b7abba77Ssoda #define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
120b7abba77Ssoda #define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
121b7abba77Ssoda #define PMS_SET_RES 0xe8 /* set resolution */
122b7abba77Ssoda #define PMS_GET_SCALE 0xe9 /* get scaling factor */
123b7abba77Ssoda #define PMS_SET_STREAM 0xea /* set streaming mode */
124b7abba77Ssoda #define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
125b7abba77Ssoda #define PMS_DEV_ENABLE 0xf4 /* mouse on */
126b7abba77Ssoda #define PMS_DEV_DISABLE 0xf5 /* mouse off */
127b7abba77Ssoda #define PMS_RESET 0xff /* reset */
128b7abba77Ssoda
129b7abba77Ssoda #define PMS_CHUNK 128 /* chunk size for read */
130b7abba77Ssoda #define PMS_BSIZE 1020 /* buffer size */
131b7abba77Ssoda
132b7abba77Ssoda #define FLUSHQ(q) { if((q)->c_cc) ndflush(q, (q)->c_cc); }
133b7abba77Ssoda
13477a6b82bSgehenna dev_type_open(opmsopen);
13577a6b82bSgehenna dev_type_close(opmsclose);
13677a6b82bSgehenna dev_type_read(opmsread);
13777a6b82bSgehenna dev_type_ioctl(opmsioctl);
13877a6b82bSgehenna dev_type_poll(opmspoll);
139a8dbe271Sjdolecek dev_type_kqfilter(opmskqfilter);
14077a6b82bSgehenna
14177a6b82bSgehenna const struct cdevsw opms_cdevsw = {
142a68f9396Sdholland .d_open = opmsopen,
143a68f9396Sdholland .d_close = opmsclose,
144a68f9396Sdholland .d_read = opmsread,
145a68f9396Sdholland .d_write = nowrite,
146a68f9396Sdholland .d_ioctl = opmsioctl,
147a68f9396Sdholland .d_stop = nostop,
148a68f9396Sdholland .d_tty = notty,
149a68f9396Sdholland .d_poll = opmspoll,
150a68f9396Sdholland .d_mmap = nommap,
151a68f9396Sdholland .d_kqfilter = opmskqfilter,
152f9228f42Sdholland .d_discard = nodiscard,
153a68f9396Sdholland .d_flag = 0
15477a6b82bSgehenna };
15577a6b82bSgehenna
1565f1c88d7Sperry static inline void pms_dev_cmd(uint8_t);
1575f1c88d7Sperry static inline void pms_aux_cmd(uint8_t);
1585f1c88d7Sperry static inline void pms_pit_cmd(uint8_t);
159b7abba77Ssoda
1605f1c88d7Sperry static inline void
pms_dev_cmd(uint8_t value)1617fe2a5a0Stsutsui pms_dev_cmd(uint8_t value)
162b7abba77Ssoda {
1637fe2a5a0Stsutsui
164b7abba77Ssoda kbd_flush_input();
165b7abba77Ssoda kbd_cmd_write_1(0xd4);
166b7abba77Ssoda kbd_flush_input();
167b7abba77Ssoda kbd_data_write_1(value);
168b7abba77Ssoda }
169b7abba77Ssoda
1705f1c88d7Sperry static inline void
pms_aux_cmd(uint8_t value)1717fe2a5a0Stsutsui pms_aux_cmd(uint8_t value)
172b7abba77Ssoda {
1737fe2a5a0Stsutsui
174b7abba77Ssoda kbd_flush_input();
175b7abba77Ssoda kbd_cmd_write_1(value);
176b7abba77Ssoda }
177b7abba77Ssoda
1785f1c88d7Sperry static inline void
pms_pit_cmd(uint8_t value)1797fe2a5a0Stsutsui pms_pit_cmd(uint8_t value)
180b7abba77Ssoda {
1817fe2a5a0Stsutsui
182b7abba77Ssoda kbd_flush_input();
183b7abba77Ssoda kbd_cmd_write_1(0x60);
184b7abba77Ssoda kbd_flush_input();
185b7abba77Ssoda kbd_data_write_1(value);
186b7abba77Ssoda }
187b7abba77Ssoda
opms_common_match(bus_space_tag_t kbd_iot,struct pccons_config * config)1887fe2a5a0Stsutsui int opms_common_match(bus_space_tag_t kbd_iot, struct pccons_config *config)
189b7abba77Ssoda {
1907fe2a5a0Stsutsui uint8_t x;
191b7abba77Ssoda
192b7abba77Ssoda kbd_context_init(kbd_iot, config);
193b7abba77Ssoda
194b7abba77Ssoda pms_dev_cmd(KBC_RESET);
195b7abba77Ssoda pms_aux_cmd(PMS_MAGIC_1);
196b7abba77Ssoda delay(10000);
197b7abba77Ssoda x = kbd_data_read_1();
198b7abba77Ssoda pms_pit_cmd(PMS_INT_DISABLE);
199b7abba77Ssoda if (x & 0x04)
200b7abba77Ssoda return 0;
201b7abba77Ssoda
202b7abba77Ssoda return 1;
203b7abba77Ssoda }
204b7abba77Ssoda
205b7abba77Ssoda void
opms_common_attach(struct opms_softc * sc,bus_space_tag_t opms_iot,struct pccons_config * config)2067fe2a5a0Stsutsui opms_common_attach(struct opms_softc *sc, bus_space_tag_t opms_iot,
2077fe2a5a0Stsutsui struct pccons_config *config)
208b7abba77Ssoda {
2097fe2a5a0Stsutsui
210b7abba77Ssoda kbd_context_init(opms_iot, config);
211c6186facSrmind selinit(&sc->sc_rsel);
212b7abba77Ssoda
213b7abba77Ssoda /* Other initialization was done by opmsprobe. */
214b7abba77Ssoda sc->sc_state = 0;
215b7abba77Ssoda }
216b7abba77Ssoda
217b7abba77Ssoda int
opmsopen(dev_t dev,int flag,int mode,struct lwp * l)21895e1ffb1Schristos opmsopen(dev_t dev, int flag, int mode, struct lwp *l)
219b7abba77Ssoda {
220b7abba77Ssoda struct opms_softc *sc;
221b7abba77Ssoda
222fa11f9bfScegger sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
223b7abba77Ssoda if (!sc)
224b7abba77Ssoda return ENXIO;
225b7abba77Ssoda
226b7abba77Ssoda if (sc->sc_state & PMS_OPEN)
227b7abba77Ssoda return EBUSY;
228b7abba77Ssoda
229b7abba77Ssoda if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
230b7abba77Ssoda return ENOMEM;
231b7abba77Ssoda
232b7abba77Ssoda sc->sc_state |= PMS_OPEN;
233b7abba77Ssoda sc->sc_status = 0;
234b7abba77Ssoda sc->sc_x = sc->sc_y = 0;
235b7abba77Ssoda
236b7abba77Ssoda /* Enable interrupts. */
237b7abba77Ssoda pms_dev_cmd(PMS_DEV_ENABLE);
238b7abba77Ssoda pms_aux_cmd(PMS_AUX_ENABLE);
239b7abba77Ssoda pms_dev_cmd(PMS_SET_RES);
240b7abba77Ssoda pms_dev_cmd(3); /* 8 counts/mm */
241b7abba77Ssoda pms_dev_cmd(PMS_SET_SCALE21);
242b7abba77Ssoda #if 0
243b7abba77Ssoda pms_dev_cmd(PMS_SET_SAMPLE);
244b7abba77Ssoda pms_dev_cmd(100); /* 100 samples/sec */
245b7abba77Ssoda pms_dev_cmd(PMS_SET_STREAM);
246b7abba77Ssoda #endif
247b7abba77Ssoda pms_pit_cmd(PMS_INT_ENABLE);
248b7abba77Ssoda
249b7abba77Ssoda return 0;
250b7abba77Ssoda }
251b7abba77Ssoda
252b7abba77Ssoda int
opmsclose(dev_t dev,int flag,int mode,struct lwp * l)25395e1ffb1Schristos opmsclose(dev_t dev, int flag, int mode, struct lwp *l)
254b7abba77Ssoda {
255fa11f9bfScegger struct opms_softc *sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
256b7abba77Ssoda
257b7abba77Ssoda /* Disable interrupts. */
258b7abba77Ssoda pms_dev_cmd(PMS_DEV_DISABLE);
259b7abba77Ssoda pms_pit_cmd(PMS_INT_DISABLE);
260b7abba77Ssoda pms_aux_cmd(PMS_AUX_DISABLE);
261b7abba77Ssoda
262b7abba77Ssoda sc->sc_state &= ~PMS_OPEN;
263b7abba77Ssoda
264b7abba77Ssoda clfree(&sc->sc_q);
265b7abba77Ssoda
266b7abba77Ssoda return 0;
267b7abba77Ssoda }
268b7abba77Ssoda
269b7abba77Ssoda int
opmsread(dev_t dev,struct uio * uio,int flag)2706196dae1Smatt opmsread(dev_t dev, struct uio *uio, int flag)
271b7abba77Ssoda {
272fa11f9bfScegger struct opms_softc *sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
273b7abba77Ssoda int s;
274b7abba77Ssoda int error = 0;
275b7abba77Ssoda size_t length;
276b7abba77Ssoda u_char buffer[PMS_CHUNK];
277b7abba77Ssoda
278456dff6cSwiz /* Block until mouse activity occurred. */
279b7abba77Ssoda
280b7abba77Ssoda s = spltty();
281b7abba77Ssoda while (sc->sc_q.c_cc == 0) {
282b7abba77Ssoda if (flag & IO_NDELAY) {
283b7abba77Ssoda splx(s);
284b7abba77Ssoda return EWOULDBLOCK;
285b7abba77Ssoda }
286b7abba77Ssoda sc->sc_state |= PMS_ASLP;
28753524e44Schristos error = tsleep((void *)sc, PZERO | PCATCH, "pmsrea", 0);
288b7abba77Ssoda if (error) {
289b7abba77Ssoda sc->sc_state &= ~PMS_ASLP;
290b7abba77Ssoda splx(s);
291b7abba77Ssoda return error;
292b7abba77Ssoda }
293b7abba77Ssoda }
294b7abba77Ssoda splx(s);
295b7abba77Ssoda
296b7abba77Ssoda /* Transfer as many chunks as possible. */
297b7abba77Ssoda
298b7abba77Ssoda while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
299d1579b2dSriastradh length = uimin(sc->sc_q.c_cc, uio->uio_resid);
300b7abba77Ssoda if (length > sizeof(buffer))
301b7abba77Ssoda length = sizeof(buffer);
302b7abba77Ssoda
303b7abba77Ssoda /* Remove a small chunk from the input queue. */
304b7abba77Ssoda (void) q_to_b(&sc->sc_q, buffer, length);
305b7abba77Ssoda
306b7abba77Ssoda /* Copy the data to the user process. */
307b7abba77Ssoda error = uiomove(buffer, length, uio);
308b7abba77Ssoda if (error)
309b7abba77Ssoda break;
310b7abba77Ssoda }
311b7abba77Ssoda
312b7abba77Ssoda return error;
313b7abba77Ssoda }
314b7abba77Ssoda
315b7abba77Ssoda int
opmsioctl(dev_t dev,u_long cmd,void * addr,int flag,struct lwp * l)31653524e44Schristos opmsioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
317b7abba77Ssoda {
318fa11f9bfScegger struct opms_softc *sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
319b7abba77Ssoda struct mouseinfo info;
320b7abba77Ssoda int s;
321b7abba77Ssoda int error;
322b7abba77Ssoda
323b7abba77Ssoda switch (cmd) {
324b7abba77Ssoda case MOUSEIOCREAD:
325b7abba77Ssoda s = spltty();
326b7abba77Ssoda
327b7abba77Ssoda info.status = sc->sc_status;
328b7abba77Ssoda if (sc->sc_x || sc->sc_y)
329b7abba77Ssoda info.status |= MOVEMENT;
330b7abba77Ssoda
331b7abba77Ssoda if (sc->sc_x > 127)
332b7abba77Ssoda info.xmotion = 127;
333b7abba77Ssoda else if (sc->sc_x < -127)
334b7abba77Ssoda /* Bounding at -127 avoids a bug in XFree86. */
335b7abba77Ssoda info.xmotion = -127;
336b7abba77Ssoda else
337b7abba77Ssoda info.xmotion = sc->sc_x;
338b7abba77Ssoda
339b7abba77Ssoda if (sc->sc_y > 127)
340b7abba77Ssoda info.ymotion = 127;
341b7abba77Ssoda else if (sc->sc_y < -127)
342b7abba77Ssoda info.ymotion = -127;
343b7abba77Ssoda else
344b7abba77Ssoda info.ymotion = sc->sc_y;
345b7abba77Ssoda
346b7abba77Ssoda /* Reset historical information. */
347b7abba77Ssoda sc->sc_x = sc->sc_y = 0;
348b7abba77Ssoda sc->sc_status &= ~BUTCHNGMASK;
349b7abba77Ssoda ndflush(&sc->sc_q, sc->sc_q.c_cc);
350b7abba77Ssoda
351b7abba77Ssoda splx(s);
352b7abba77Ssoda error = copyout(&info, addr, sizeof(struct mouseinfo));
353b7abba77Ssoda break;
354b7abba77Ssoda default:
355b7abba77Ssoda error = EINVAL;
356b7abba77Ssoda break;
357b7abba77Ssoda }
358b7abba77Ssoda
359b7abba77Ssoda return error;
360b7abba77Ssoda }
361b7abba77Ssoda
362b7abba77Ssoda /* Masks for the first byte of a packet */
363b7abba77Ssoda #define PS2LBUTMASK 0x01
364b7abba77Ssoda #define PS2RBUTMASK 0x02
365b7abba77Ssoda #define PS2MBUTMASK 0x04
366b7abba77Ssoda
367b7abba77Ssoda int
opmsintr(void * arg)3687fe2a5a0Stsutsui opmsintr(void *arg)
369b7abba77Ssoda {
370b7abba77Ssoda struct opms_softc *sc = arg;
371b7abba77Ssoda static int state = 0;
372b7abba77Ssoda static u_char buttons;
373b7abba77Ssoda u_char changed;
374b7abba77Ssoda static char dx, dy;
375b7abba77Ssoda u_char buffer[5];
376b7abba77Ssoda
377b7abba77Ssoda if ((sc->sc_state & PMS_OPEN) == 0) {
378b7abba77Ssoda /* Interrupts are not expected. Discard the byte. */
379b7abba77Ssoda kbd_flush_input();
380b7abba77Ssoda return 0;
381b7abba77Ssoda }
382b7abba77Ssoda
383b7abba77Ssoda switch (state) {
384b7abba77Ssoda
385b7abba77Ssoda case 0:
386b7abba77Ssoda buttons = kbd_data_read_1();
387b7abba77Ssoda if ((buttons & 0xc0) == 0)
388b7abba77Ssoda ++state;
389b7abba77Ssoda break;
390b7abba77Ssoda
391b7abba77Ssoda case 1:
392b7abba77Ssoda dx = kbd_data_read_1();
393b7abba77Ssoda /* Bounding at -127 avoids a bug in XFree86. */
394b7abba77Ssoda dx = (dx == -128) ? -127 : dx;
395b7abba77Ssoda ++state;
396b7abba77Ssoda break;
397b7abba77Ssoda
398b7abba77Ssoda case 2:
399b7abba77Ssoda dy = kbd_data_read_1();
400b7abba77Ssoda dy = (dy == -128) ? -127 : dy;
401b7abba77Ssoda state = 0;
402b7abba77Ssoda
403b7abba77Ssoda buttons = ((buttons & PS2LBUTMASK) << 2) |
404b7abba77Ssoda ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
405b7abba77Ssoda changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
4067fe2a5a0Stsutsui sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) |
4077fe2a5a0Stsutsui changed;
408b7abba77Ssoda
409b7abba77Ssoda if (dx || dy || changed) {
410b7abba77Ssoda /* Update accumulated movements. */
411b7abba77Ssoda sc->sc_x += dx;
412b7abba77Ssoda sc->sc_y += dy;
413b7abba77Ssoda
414b7abba77Ssoda /* Add this event to the queue. */
415b7abba77Ssoda buffer[0] = 0x80 | (buttons & BUTSTATMASK);
416b7abba77Ssoda if(dx < 0)
417b7abba77Ssoda buffer[0] |= 0x10;
418b7abba77Ssoda buffer[1] = dx & 0x7f;
419b7abba77Ssoda if(dy < 0)
420b7abba77Ssoda buffer[0] |= 0x20;
421b7abba77Ssoda buffer[2] = dy & 0x7f;
422b7abba77Ssoda buffer[3] = buffer[4] = 0;
423b7abba77Ssoda (void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
424b7abba77Ssoda
425b7abba77Ssoda if (sc->sc_state & PMS_ASLP) {
426b7abba77Ssoda sc->sc_state &= ~PMS_ASLP;
42753524e44Schristos wakeup((void *)sc);
428b7abba77Ssoda }
429c6186facSrmind selnotify(&sc->sc_rsel, 0, 0);
430b7abba77Ssoda }
431b7abba77Ssoda
432b7abba77Ssoda break;
433b7abba77Ssoda }
434b7abba77Ssoda return -1;
435b7abba77Ssoda }
436b7abba77Ssoda
437b7abba77Ssoda int
opmspoll(dev_t dev,int events,struct lwp * l)43895e1ffb1Schristos opmspoll(dev_t dev, int events, struct lwp *l)
439b7abba77Ssoda {
440fa11f9bfScegger struct opms_softc *sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
441b7abba77Ssoda int revents = 0;
442b7abba77Ssoda int s = spltty();
443b7abba77Ssoda
444b7abba77Ssoda if (events & (POLLIN | POLLRDNORM)) {
445b7abba77Ssoda if (sc->sc_q.c_cc > 0)
446b7abba77Ssoda revents |= events & (POLLIN | POLLRDNORM);
447b7abba77Ssoda else
44895e1ffb1Schristos selrecord(l, &sc->sc_rsel);
449b7abba77Ssoda }
450b7abba77Ssoda
451b7abba77Ssoda splx(s);
4527fe2a5a0Stsutsui return revents;
453b7abba77Ssoda }
454e0cc03a0Sjdolecek
455e0cc03a0Sjdolecek static void
filt_opmsrdetach(struct knote * kn)456e0cc03a0Sjdolecek filt_opmsrdetach(struct knote *kn)
457e0cc03a0Sjdolecek {
458e0cc03a0Sjdolecek struct opms_softc *sc = kn->kn_hook;
459e0cc03a0Sjdolecek int s;
460e0cc03a0Sjdolecek
461e0cc03a0Sjdolecek s = spltty();
46266b33a40Sthorpej selremove_knote(&sc->sc_rsel, kn);
463e0cc03a0Sjdolecek splx(s);
464e0cc03a0Sjdolecek }
465e0cc03a0Sjdolecek
466e0cc03a0Sjdolecek static int
filt_opmsread(struct knote * kn,long hint)467e0cc03a0Sjdolecek filt_opmsread(struct knote *kn, long hint)
468e0cc03a0Sjdolecek {
469e0cc03a0Sjdolecek struct opms_softc *sc = kn->kn_hook;
470e0cc03a0Sjdolecek
471e0cc03a0Sjdolecek kn->kn_data = sc->sc_q.c_cc;
4727fe2a5a0Stsutsui return kn->kn_data > 0;
473e0cc03a0Sjdolecek }
474e0cc03a0Sjdolecek
47518b796d4Smaya static const struct filterops opmsread_filtops = {
47612ae65d9Sthorpej .f_flags = FILTEROP_ISFD,
47718b796d4Smaya .f_attach = NULL,
47818b796d4Smaya .f_detach = filt_opmsrdetach,
47918b796d4Smaya .f_event = filt_opmsread,
48018b796d4Smaya };
481e0cc03a0Sjdolecek
482e0cc03a0Sjdolecek int
opmskqfilter(dev_t dev,struct knote * kn)483e0cc03a0Sjdolecek opmskqfilter(dev_t dev, struct knote *kn)
484e0cc03a0Sjdolecek {
485fa11f9bfScegger struct opms_softc *sc = device_lookup_private(&opms_cd, PMSUNIT(dev));
486e0cc03a0Sjdolecek int s;
487e0cc03a0Sjdolecek
488e0cc03a0Sjdolecek switch (kn->kn_filter) {
489e0cc03a0Sjdolecek case EVFILT_READ:
490e0cc03a0Sjdolecek kn->kn_fop = &opmsread_filtops;
491e0cc03a0Sjdolecek break;
492e0cc03a0Sjdolecek
493e0cc03a0Sjdolecek default:
494*5ab06420Sthorpej return EINVAL;
495e0cc03a0Sjdolecek }
496e0cc03a0Sjdolecek
497e0cc03a0Sjdolecek kn->kn_hook = sc;
498e0cc03a0Sjdolecek
499e0cc03a0Sjdolecek s = spltty();
50066b33a40Sthorpej selrecord_knote(&sc->sc_rsel, kn);
501e0cc03a0Sjdolecek splx(s);
502e0cc03a0Sjdolecek
5037fe2a5a0Stsutsui return 0;
504e0cc03a0Sjdolecek }
505