ms.c revision 1.1 1 /* $NetBSD: ms.c,v 1.1 1996/01/24 01:15:35 gwr Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 * @(#)ms.c 8.1 (Berkeley) 6/11/93
45 */
46
47 /*
48 * Mouse driver (/dev/mouse)
49 */
50
51 /*
52 * Zilog Z8530 Dual UART driver (mouse interface)
53 *
54 * This is the "slave" driver that will be attached to
55 * the "zsc" driver for a Sun mouse.
56 */
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/proc.h>
61 #include <sys/device.h>
62 #include <sys/conf.h>
63 #include <sys/ioctl.h>
64 #include <sys/kernel.h>
65 #include <sys/syslog.h>
66
67 #include <dev/ic/z8530reg.h>
68 #include <machine/z8530var.h>
69 #include <machine/vuid_event.h>
70
71 #include "event_var.h"
72
73 /*
74 * How many input characters we can buffer.
75 * The port-specific var.h may override this.
76 * Note: must be a power of two!
77 */
78 #define MS_RX_RING_SIZE 256
79 #define MS_RX_RING_MASK (MS_RX_RING_SIZE-1)
80 /*
81 * Output buffer. Only need a few chars.
82 */
83 #define MS_TX_RING_SIZE 16
84 #define MS_TX_RING_MASK (MS_TX_RING_SIZE-1)
85 /*
86 * Keyboard serial line speed is fixed at 1200 bps.
87 */
88 #define MS_BPS 1200
89
90 /*
91 * Mouse state. A Mouse Systems mouse is a fairly simple device,
92 * producing five-byte blobs of the form:
93 *
94 * b dx dy dx dy
95 *
96 * where b is the button state, encoded as 0x80|(~buttons)---there are
97 * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y
98 * delta values, none of which have are in [0x80..0x87]. (This lets
99 * us sync up with the mouse after an error.)
100 */
101 struct ms_softc {
102 struct device ms_dev; /* required first: base device */
103 struct zs_chanstate *ms_cs;
104
105 /* Flags to communicate with ms_softintr() */
106 volatile int ms_intr_flags;
107 #define INTR_RX_OVERRUN 1
108 #define INTR_TX_EMPTY 2
109 #define INTR_ST_CHECK 4
110
111 /*
112 * The receive ring buffer.
113 */
114 u_int ms_rbget; /* ring buffer `get' index */
115 volatile u_int ms_rbput; /* ring buffer `put' index */
116 u_short ms_rbuf[MS_RX_RING_SIZE]; /* rr1, data pairs */
117
118 /*
119 * State of input translator
120 */
121 short ms_byteno; /* input byte number, for decode */
122 char ms_mb; /* mouse button state */
123 char ms_ub; /* user button state */
124 int ms_dx; /* delta-x */
125 int ms_dy; /* delta-y */
126
127 /*
128 * State of upper interface.
129 */
130 volatile int ms_ready; /* event queue is ready */
131 struct evvar ms_events; /* event queue state */
132 } ms_softc;
133
134 cdev_decl(ms); /* open, close, read, write, ioctl, stop, ... */
135
136 struct zsops zsops_ms;
137
138 /****************************************************************
139 * Definition of the driver for autoconfig.
140 ****************************************************************/
141
142 static int ms_match(struct device *, void *, void *);
143 static void ms_attach(struct device *, struct device *, void *);
144
145 struct cfdriver mscd = {
146 NULL, "ms", ms_match, ms_attach,
147 DV_DULL, sizeof(struct ms_softc), NULL,
148 };
149
150
151 /*
152 * ms_match: how is this zs channel configured?
153 */
154 int
155 ms_match(parent, match, aux)
156 struct device *parent;
157 void *match, *aux;
158 {
159 struct cfdata *cf = match;
160 struct zsc_attach_args *args = aux;
161
162 /* Exact match required for keyboard. */
163 if (cf->cf_loc[0] == args->channel)
164 return 2;
165
166 return 0;
167 }
168
169 void
170 ms_attach(parent, self, aux)
171 struct device *parent, *self;
172 void *aux;
173
174 {
175 struct zsc_softc *zsc = (void *) parent;
176 struct ms_softc *ms = (void *) self;
177 struct zsc_attach_args *args = aux;
178 struct zs_chanstate *cs;
179 struct cfdata *cf;
180 int channel, ms_unit;
181 int reset, s, tconst;
182
183 cf = ms->ms_dev.dv_cfdata;
184 ms_unit = cf->cf_unit;
185 channel = args->channel;
186 cs = &zsc->zsc_cs[channel];
187 cs->cs_private = ms;
188 cs->cs_ops = &zsops_ms;
189 ms->ms_cs = cs;
190
191 printf("\n");
192
193 /* Initialize the speed, etc. */
194 tconst = BPS_TO_TCONST(cs->cs_pclk_div16, MS_BPS);
195 s = splzs();
196 /* May need reset... */
197 reset = (channel == 0) ?
198 ZSWR9_A_RESET : ZSWR9_B_RESET;
199 ZS_WRITE(cs, 9, reset);
200 /* These are OK as set by zscc: WR3, WR4, WR5 */
201 cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
202 cs->cs_preg[12] = tconst;
203 cs->cs_preg[13] = tconst >> 8;
204 zs_loadchannelregs(cs);
205 splx(s);
206
207 /* Initialize translator. */
208 ms->ms_byteno = -1;
209 }
210
211 /****************************************************************
212 * Entry points for /dev/mouse
213 * (open,close,read,write,...)
214 ****************************************************************/
215
216 int
217 msopen(dev, flags, mode, p)
218 dev_t dev;
219 int flags, mode;
220 struct proc *p;
221 {
222 struct ms_softc *ms;
223 int error, s, unit;
224
225 unit = minor(dev);
226 if (unit >= mscd.cd_ndevs)
227 return (ENXIO);
228 ms = mscd.cd_devs[unit];
229 if (ms == NULL)
230 return (ENXIO);
231
232 /* This is an exclusive open device. */
233 if (ms->ms_events.ev_io)
234 return (EBUSY);
235 ms->ms_events.ev_io = p;
236 ev_init(&ms->ms_events); /* may cause sleep */
237
238 ms->ms_ready = 1; /* start accepting events */
239 return (0);
240 }
241
242 int
243 msclose(dev, flags, mode, p)
244 dev_t dev;
245 int flags, mode;
246 struct proc *p;
247 {
248 struct ms_softc *ms;
249
250 ms = mscd.cd_devs[minor(dev)];
251 ms->ms_ready = 0; /* stop accepting events */
252 ev_fini(&ms->ms_events);
253
254 ms->ms_events.ev_io = NULL;
255 return (0);
256 }
257
258 int
259 msread(dev, uio, flags)
260 dev_t dev;
261 struct uio *uio;
262 int flags;
263 {
264 struct ms_softc *ms;
265
266 ms = mscd.cd_devs[minor(dev)];
267 return (ev_read(&ms->ms_events, uio, flags));
268 }
269
270 /* this routine should not exist, but is convenient to write here for now */
271 int
272 mswrite(dev, uio, flags)
273 dev_t dev;
274 struct uio *uio;
275 int flags;
276 {
277
278 return (EOPNOTSUPP);
279 }
280
281 int
282 msioctl(dev, cmd, data, flag, p)
283 dev_t dev;
284 u_long cmd;
285 register caddr_t data;
286 int flag;
287 struct proc *p;
288 {
289 struct ms_softc *ms;
290
291 ms = mscd.cd_devs[minor(dev)];
292
293 switch (cmd) {
294
295 case FIONBIO: /* we will remove this someday (soon???) */
296 return (0);
297
298 case FIOASYNC:
299 ms->ms_events.ev_async = *(int *)data != 0;
300 return (0);
301
302 case TIOCSPGRP:
303 if (*(int *)data != ms->ms_events.ev_io->p_pgid)
304 return (EPERM);
305 return (0);
306
307 case VUIDGFORMAT:
308 /* we only do firm_events */
309 *(int *)data = VUID_FIRM_EVENT;
310 return (0);
311
312 case VUIDSFORMAT:
313 if (*(int *)data != VUID_FIRM_EVENT)
314 return (EINVAL);
315 return (0);
316 }
317 return (ENOTTY);
318 }
319
320 int
321 msselect(dev, rw, p)
322 dev_t dev;
323 int rw;
324 struct proc *p;
325 {
326 struct ms_softc *ms;
327
328 ms = mscd.cd_devs[minor(dev)];
329 return (ev_select(&ms->ms_events, rw, p));
330 }
331
332
333 /****************************************************************
334 * Middle layer (translator)
335 ****************************************************************/
336
337 /*
338 * Called by our ms_softint() routine on input.
339 */
340 void
341 ms_input(ms, c)
342 register struct ms_softc *ms;
343 register int c;
344 {
345 register struct firm_event *fe;
346 register int mb, ub, d, get, put, any;
347 static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
348 static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
349
350 /*
351 * Discard input if not ready. Drop sync on parity or framing
352 * error; gain sync on button byte.
353 */
354 if (ms->ms_ready == 0)
355 return;
356 if (c == -1) {
357 ms->ms_byteno = -1;
358 return;
359 }
360 if ((c & ~7) == 0x80) /* if in 0x80..0x87 */
361 ms->ms_byteno = 0;
362
363 /*
364 * Run the decode loop, adding to the current information.
365 * We add, rather than replace, deltas, so that if the event queue
366 * fills, we accumulate data for when it opens up again.
367 */
368 switch (ms->ms_byteno) {
369
370 case -1:
371 return;
372
373 case 0:
374 /* buttons */
375 ms->ms_byteno = 1;
376 ms->ms_mb = (~c) & 0x7;
377 return;
378
379 case 1:
380 /* first delta-x */
381 ms->ms_byteno = 2;
382 ms->ms_dx += (char)c;
383 return;
384
385 case 2:
386 /* first delta-y */
387 ms->ms_byteno = 3;
388 ms->ms_dy += (char)c;
389 return;
390
391 case 3:
392 /* second delta-x */
393 ms->ms_byteno = 4;
394 ms->ms_dx += (char)c;
395 return;
396
397 case 4:
398 /* second delta-x */
399 ms->ms_byteno = -1; /* wait for button-byte again */
400 ms->ms_dy += (char)c;
401 break;
402
403 default:
404 panic("ms_rint");
405 /* NOTREACHED */
406 }
407
408 /*
409 * We have at least one event (mouse button, delta-X, or
410 * delta-Y; possibly all three, and possibly three separate
411 * button events). Deliver these events until we are out
412 * of changes or out of room. As events get delivered,
413 * mark them `unchanged'.
414 */
415 any = 0;
416 get = ms->ms_events.ev_get;
417 put = ms->ms_events.ev_put;
418 fe = &ms->ms_events.ev_q[put];
419
420 /* NEXT prepares to put the next event, backing off if necessary */
421 #define NEXT \
422 if ((++put) % EV_QSIZE == get) { \
423 put--; \
424 goto out; \
425 }
426 /* ADVANCE completes the `put' of the event */
427 #define ADVANCE \
428 fe++; \
429 if (put >= EV_QSIZE) { \
430 put = 0; \
431 fe = &ms->ms_events.ev_q[0]; \
432 } \
433 any = 1
434
435 mb = ms->ms_mb;
436 ub = ms->ms_ub;
437 while ((d = mb ^ ub) != 0) {
438 /*
439 * Mouse button change. Convert up to three changes
440 * to the `first' change, and drop it into the event queue.
441 */
442 NEXT;
443 d = to_one[d - 1]; /* from 1..7 to {1,2,4} */
444 fe->id = to_id[d - 1]; /* from {1,2,4} to ID */
445 fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
446 fe->time = time;
447 ADVANCE;
448 ub ^= d;
449 }
450 if (ms->ms_dx) {
451 NEXT;
452 fe->id = LOC_X_DELTA;
453 fe->value = ms->ms_dx;
454 fe->time = time;
455 ADVANCE;
456 ms->ms_dx = 0;
457 }
458 if (ms->ms_dy) {
459 NEXT;
460 fe->id = LOC_Y_DELTA;
461 fe->value = ms->ms_dy;
462 fe->time = time;
463 ADVANCE;
464 ms->ms_dy = 0;
465 }
466 out:
467 if (any) {
468 ms->ms_ub = ub;
469 ms->ms_events.ev_put = put;
470 EV_WAKEUP(&ms->ms_events);
471 }
472 }
473
474 /****************************************************************
475 * Interface to the lower layer (zscc)
476 ****************************************************************/
477
478 static int
479 ms_rxint(cs)
480 register struct zs_chanstate *cs;
481 {
482 register struct ms_softc *ms;
483 register int put, put_next;
484 register u_char c, rr1;
485
486 ms = cs->cs_private;
487 put = ms->ms_rbput;
488
489 /* Read the input data ASAP. */
490 c = *(cs->cs_reg_data);
491 ZS_DELAY();
492
493 /* Save the status register too. */
494 rr1 = ZS_READ(cs, 1);
495
496 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
497 /* Clear the receive error. */
498 *(cs->cs_reg_csr) = ZSWR0_RESET_ERRORS;
499 ZS_DELAY();
500 }
501
502 ms->ms_rbuf[put] = (c << 8) | rr1;
503 put_next = (put + 1) & MS_RX_RING_MASK;
504
505 /* Would overrun if increment makes (put==get). */
506 if (put_next == ms->ms_rbget) {
507 ms->ms_intr_flags |= INTR_RX_OVERRUN;
508 } else {
509 /* OK, really increment. */
510 put = put_next;
511 }
512
513 /* Done reading. */
514 ms->ms_rbput = put;
515
516 /* Ask for softint() call. */
517 cs->cs_softreq = 1;
518 return(1);
519 }
520
521
522 static int
523 ms_txint(cs)
524 register struct zs_chanstate *cs;
525 {
526 register struct ms_softc *ms;
527 register int count, rval;
528
529 ms = cs->cs_private;
530
531 *(cs->cs_reg_csr) = ZSWR0_RESET_TXINT;
532 ZS_DELAY();
533
534 ms->ms_intr_flags |= INTR_TX_EMPTY;
535 /* Ask for softint() call. */
536 cs->cs_softreq = 1;
537 return (1);
538 }
539
540
541 static int
542 ms_stint(cs)
543 register struct zs_chanstate *cs;
544 {
545 register struct ms_softc *ms;
546 register int rr0;
547
548 ms = cs->cs_private;
549
550 rr0 = *(cs->cs_reg_csr);
551 ZS_DELAY();
552
553 *(cs->cs_reg_csr) = ZSWR0_RESET_STATUS;
554 ZS_DELAY();
555
556 ms->ms_intr_flags |= INTR_ST_CHECK;
557 /* Ask for softint() call. */
558 cs->cs_softreq = 1;
559 return (1);
560 }
561
562
563 static int
564 ms_softint(cs)
565 struct zs_chanstate *cs;
566 {
567 register struct ms_softc *ms;
568 register int get, c, s;
569 int intr_flags;
570 register u_short ring_data;
571 register u_char rr0, rr1;
572
573 ms = cs->cs_private;
574
575 /* Atomically get and clear flags. */
576 s = splzs();
577 intr_flags = ms->ms_intr_flags;
578 ms->ms_intr_flags = 0;
579 splx(s);
580
581 /*
582 * Copy data from the receive ring to the event layer.
583 */
584 get = ms->ms_rbget;
585 while (get != ms->ms_rbput) {
586 ring_data = ms->ms_rbuf[get];
587 get = (get + 1) & MS_RX_RING_MASK;
588
589 /* low byte of ring_data is rr1 */
590 c = (ring_data >> 8) & 0xff;
591
592 if (ring_data & ZSRR1_DO)
593 intr_flags |= INTR_RX_OVERRUN;
594 if (ring_data & (ZSRR1_FE | ZSRR1_PE)) {
595 log(LOG_ERR, "%s: input error (0x%x)\n",
596 ms->ms_dev.dv_xname, ring_data);
597 c = -1; /* signal input error */
598 }
599
600 /* Pass this up to the "middle" layer. */
601 ms_input(ms, c);
602 }
603 if (intr_flags & INTR_RX_OVERRUN) {
604 log(LOG_ERR, "%s: input overrun\n",
605 ms->ms_dev.dv_xname);
606 }
607 ms->ms_rbget = get;
608
609 if (intr_flags & INTR_TX_EMPTY) {
610 /*
611 * Transmit done. (Not expected.)
612 */
613 log(LOG_ERR, "%s: transmit interrupt?\n",
614 ms->ms_dev.dv_xname);
615 }
616
617 if (intr_flags & INTR_ST_CHECK) {
618 /*
619 * Status line change. (Not expected.)
620 */
621 log(LOG_ERR, "%s: status interrupt?\n",
622 ms->ms_dev.dv_xname);
623 }
624
625 return (1);
626 }
627
628 struct zsops zsops_ms = {
629 ms_rxint, /* receive char available */
630 ms_stint, /* external/status */
631 ms_txint, /* xmit buffer empty */
632 ms_softint, /* process software interrupt */
633 };
634