1 /* $NetBSD: ms.c,v 1.15 1999/02/03 20:22:28 mycroft 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/conf.h> 61 #include <sys/device.h> 62 #include <sys/ioctl.h> 63 #include <sys/kernel.h> 64 #include <sys/proc.h> 65 #include <sys/signal.h> 66 #include <sys/signalvar.h> 67 #include <sys/time.h> 68 #include <sys/syslog.h> 69 #include <sys/select.h> 70 #include <sys/poll.h> 71 72 #include <machine/vuid_event.h> 73 74 #include <dev/ic/z8530reg.h> 75 #include <machine/z8530var.h> 76 77 #include "event_var.h" 78 #include "locators.h" 79 80 /* 81 * How many input characters we can buffer. 82 * The port-specific var.h may override this. 83 * Note: must be a power of two! 84 */ 85 #define MS_RX_RING_SIZE 256 86 #define MS_RX_RING_MASK (MS_RX_RING_SIZE-1) 87 /* 88 * Output buffer. Only need a few chars. 89 */ 90 #define MS_TX_RING_SIZE 16 91 #define MS_TX_RING_MASK (MS_TX_RING_SIZE-1) 92 /* 93 * Keyboard serial line speed is fixed at 1200 bps; mouse serial line 94 * speed defaults to 1200 bps. 95 */ 96 #ifdef SUN_MS_BPS 97 #define MS_BPS SUN_MS_BPS 98 #else 99 #define MS_BPS 1200 100 #endif 101 102 /* 103 * Mouse state. A Mouse Systems mouse is a fairly simple device, 104 * producing five-byte blobs of the form: 105 * 106 * b dx dy dx dy 107 * 108 * where b is the button state, encoded as 0x80|(~buttons)---there are 109 * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y 110 * delta values, none of which have are in [0x80..0x87]. (This lets 111 * us sync up with the mouse after an error.) 112 */ 113 struct ms_softc { 114 struct device ms_dev; /* required first: base device */ 115 struct zs_chanstate *ms_cs; 116 117 /* Flags to communicate with ms_softintr() */ 118 volatile int ms_intr_flags; 119 #define INTR_RX_OVERRUN 1 120 #define INTR_TX_EMPTY 2 121 #define INTR_ST_CHECK 4 122 123 /* 124 * The receive ring buffer. 125 */ 126 u_int ms_rbget; /* ring buffer `get' index */ 127 volatile u_int ms_rbput; /* ring buffer `put' index */ 128 u_short ms_rbuf[MS_RX_RING_SIZE]; /* rr1, data pairs */ 129 130 /* 131 * State of input translator 132 */ 133 short ms_byteno; /* input byte number, for decode */ 134 char ms_mb; /* mouse button state */ 135 char ms_ub; /* user button state */ 136 int ms_dx; /* delta-x */ 137 int ms_dy; /* delta-y */ 138 139 /* 140 * State of upper interface. 141 */ 142 volatile int ms_ready; /* event queue is ready */ 143 struct evvar ms_events; /* event queue state */ 144 } ms_softc; 145 146 cdev_decl(ms); /* open, close, read, write, ioctl, stop, ... */ 147 148 struct zsops zsops_ms; 149 150 /**************************************************************** 151 * Definition of the driver for autoconfig. 152 ****************************************************************/ 153 154 static int ms_match(struct device *, struct cfdata *, void *); 155 static void ms_attach(struct device *, struct device *, void *); 156 157 struct cfattach ms_ca = { 158 sizeof(struct ms_softc), ms_match, ms_attach 159 }; 160 161 extern struct cfdriver ms_cd; 162 163 /* 164 * ms_match: how is this zs channel configured? 165 */ 166 int 167 ms_match(parent, cf, aux) 168 struct device *parent; 169 struct cfdata *cf; 170 void *aux; 171 { 172 struct zsc_attach_args *args = aux; 173 174 /* Exact match required for keyboard. */ 175 if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel) 176 return 2; 177 178 return 0; 179 } 180 181 void 182 ms_attach(parent, self, aux) 183 struct device *parent, *self; 184 void *aux; 185 186 { 187 struct zsc_softc *zsc = (void *) parent; 188 struct ms_softc *ms = (void *) self; 189 struct zsc_attach_args *args = aux; 190 struct zs_chanstate *cs; 191 struct cfdata *cf; 192 int channel, ms_unit; 193 int reset, s; 194 195 cf = ms->ms_dev.dv_cfdata; 196 ms_unit = ms->ms_dev.dv_unit; 197 channel = args->channel; 198 cs = zsc->zsc_cs[channel]; 199 cs->cs_private = ms; 200 cs->cs_ops = &zsops_ms; 201 ms->ms_cs = cs; 202 203 printf("\n"); 204 205 /* Initialize the speed, etc. */ 206 s = splzs(); 207 /* May need reset... */ 208 reset = (channel == 0) ? 209 ZSWR9_A_RESET : ZSWR9_B_RESET; 210 zs_write_reg(cs, 9, reset); 211 /* These are OK as set by zscc: WR3, WR4, WR5 */ 212 /* We don't care about status or tx interrupts. */ 213 cs->cs_preg[1] = ZSWR1_RIE; 214 (void) zs_set_speed(cs, MS_BPS); 215 zs_loadchannelregs(cs); 216 splx(s); 217 218 /* Initialize translator. */ 219 ms->ms_byteno = -1; 220 } 221 222 /**************************************************************** 223 * Entry points for /dev/mouse 224 * (open,close,read,write,...) 225 ****************************************************************/ 226 227 int 228 msopen(dev, flags, mode, p) 229 dev_t dev; 230 int flags, mode; 231 struct proc *p; 232 { 233 struct ms_softc *ms; 234 int unit; 235 236 unit = minor(dev); 237 if (unit >= ms_cd.cd_ndevs) 238 return (ENXIO); 239 ms = ms_cd.cd_devs[unit]; 240 if (ms == NULL) 241 return (ENXIO); 242 243 /* This is an exclusive open device. */ 244 if (ms->ms_events.ev_io) 245 return (EBUSY); 246 ms->ms_events.ev_io = p; 247 ev_init(&ms->ms_events); /* may cause sleep */ 248 249 ms->ms_ready = 1; /* start accepting events */ 250 return (0); 251 } 252 253 int 254 msclose(dev, flags, mode, p) 255 dev_t dev; 256 int flags, mode; 257 struct proc *p; 258 { 259 struct ms_softc *ms; 260 261 ms = ms_cd.cd_devs[minor(dev)]; 262 ms->ms_ready = 0; /* stop accepting events */ 263 ev_fini(&ms->ms_events); 264 265 ms->ms_events.ev_io = NULL; 266 return (0); 267 } 268 269 int 270 msread(dev, uio, flags) 271 dev_t dev; 272 struct uio *uio; 273 int flags; 274 { 275 struct ms_softc *ms; 276 277 ms = ms_cd.cd_devs[minor(dev)]; 278 return (ev_read(&ms->ms_events, uio, flags)); 279 } 280 281 /* this routine should not exist, but is convenient to write here for now */ 282 int 283 mswrite(dev, uio, flags) 284 dev_t dev; 285 struct uio *uio; 286 int flags; 287 { 288 289 return (EOPNOTSUPP); 290 } 291 292 int 293 msioctl(dev, cmd, data, flag, p) 294 dev_t dev; 295 u_long cmd; 296 register caddr_t data; 297 int flag; 298 struct proc *p; 299 { 300 struct ms_softc *ms; 301 302 ms = ms_cd.cd_devs[minor(dev)]; 303 304 switch (cmd) { 305 306 case FIONBIO: /* we will remove this someday (soon???) */ 307 return (0); 308 309 case FIOASYNC: 310 ms->ms_events.ev_async = *(int *)data != 0; 311 return (0); 312 313 case TIOCSPGRP: 314 if (*(int *)data != ms->ms_events.ev_io->p_pgid) 315 return (EPERM); 316 return (0); 317 318 case VUIDGFORMAT: 319 /* we only do firm_events */ 320 *(int *)data = VUID_FIRM_EVENT; 321 return (0); 322 323 case VUIDSFORMAT: 324 if (*(int *)data != VUID_FIRM_EVENT) 325 return (EINVAL); 326 return (0); 327 } 328 return (ENOTTY); 329 } 330 331 int 332 mspoll(dev, events, p) 333 dev_t dev; 334 int events; 335 struct proc *p; 336 { 337 struct ms_softc *ms; 338 339 ms = ms_cd.cd_devs[minor(dev)]; 340 return (ev_poll(&ms->ms_events, events, p)); 341 } 342 343 344 /**************************************************************** 345 * Middle layer (translator) 346 ****************************************************************/ 347 348 static void ms_input __P((struct ms_softc *, int c)); 349 350 351 /* 352 * Called by our ms_softint() routine on input. 353 */ 354 void 355 ms_input(ms, c) 356 register struct ms_softc *ms; 357 register int c; 358 { 359 register struct firm_event *fe; 360 register int mb, ub, d, get, put, any; 361 static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 }; 362 static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT }; 363 364 /* 365 * Discard input if not ready. Drop sync on parity or framing 366 * error; gain sync on button byte. 367 */ 368 if (ms->ms_ready == 0) 369 return; 370 if (c == -1) { 371 ms->ms_byteno = -1; 372 return; 373 } 374 if ((c & ~7) == 0x80) /* if in 0x80..0x87 */ 375 ms->ms_byteno = 0; 376 377 /* 378 * Run the decode loop, adding to the current information. 379 * We add, rather than replace, deltas, so that if the event queue 380 * fills, we accumulate data for when it opens up again. 381 */ 382 switch (ms->ms_byteno) { 383 384 case -1: 385 return; 386 387 case 0: 388 /* buttons */ 389 ms->ms_byteno = 1; 390 ms->ms_mb = (~c) & 0x7; 391 return; 392 393 case 1: 394 /* first delta-x */ 395 ms->ms_byteno = 2; 396 ms->ms_dx += (char)c; 397 return; 398 399 case 2: 400 /* first delta-y */ 401 ms->ms_byteno = 3; 402 ms->ms_dy += (char)c; 403 return; 404 405 case 3: 406 /* second delta-x */ 407 ms->ms_byteno = 4; 408 ms->ms_dx += (char)c; 409 return; 410 411 case 4: 412 /* second delta-x */ 413 ms->ms_byteno = -1; /* wait for button-byte again */ 414 ms->ms_dy += (char)c; 415 break; 416 417 default: 418 panic("ms_rint"); 419 /* NOTREACHED */ 420 } 421 422 /* 423 * We have at least one event (mouse button, delta-X, or 424 * delta-Y; possibly all three, and possibly three separate 425 * button events). Deliver these events until we are out 426 * of changes or out of room. As events get delivered, 427 * mark them `unchanged'. 428 */ 429 any = 0; 430 get = ms->ms_events.ev_get; 431 put = ms->ms_events.ev_put; 432 fe = &ms->ms_events.ev_q[put]; 433 434 /* NEXT prepares to put the next event, backing off if necessary */ 435 #define NEXT \ 436 if ((++put) % EV_QSIZE == get) { \ 437 put--; \ 438 goto out; \ 439 } 440 /* ADVANCE completes the `put' of the event */ 441 #define ADVANCE \ 442 fe++; \ 443 if (put >= EV_QSIZE) { \ 444 put = 0; \ 445 fe = &ms->ms_events.ev_q[0]; \ 446 } \ 447 any = 1 448 449 mb = ms->ms_mb; 450 ub = ms->ms_ub; 451 while ((d = mb ^ ub) != 0) { 452 /* 453 * Mouse button change. Convert up to three changes 454 * to the `first' change, and drop it into the event queue. 455 */ 456 NEXT; 457 d = to_one[d - 1]; /* from 1..7 to {1,2,4} */ 458 fe->id = to_id[d - 1]; /* from {1,2,4} to ID */ 459 fe->value = mb & d ? VKEY_DOWN : VKEY_UP; 460 fe->time = time; 461 ADVANCE; 462 ub ^= d; 463 } 464 if (ms->ms_dx) { 465 NEXT; 466 fe->id = LOC_X_DELTA; 467 fe->value = ms->ms_dx; 468 fe->time = time; 469 ADVANCE; 470 ms->ms_dx = 0; 471 } 472 if (ms->ms_dy) { 473 NEXT; 474 fe->id = LOC_Y_DELTA; 475 fe->value = ms->ms_dy; 476 fe->time = time; 477 ADVANCE; 478 ms->ms_dy = 0; 479 } 480 out: 481 if (any) { 482 ms->ms_ub = ub; 483 ms->ms_events.ev_put = put; 484 EV_WAKEUP(&ms->ms_events); 485 } 486 } 487 488 /**************************************************************** 489 * Interface to the lower layer (zscc) 490 ****************************************************************/ 491 492 static void ms_rxint __P((struct zs_chanstate *)); 493 static void ms_stint __P((struct zs_chanstate *, int)); 494 static void ms_txint __P((struct zs_chanstate *)); 495 static void ms_softint __P((struct zs_chanstate *)); 496 497 static void 498 ms_rxint(cs) 499 register struct zs_chanstate *cs; 500 { 501 register struct ms_softc *ms; 502 register int put, put_next; 503 register u_char c, rr1; 504 505 ms = cs->cs_private; 506 put = ms->ms_rbput; 507 508 /* 509 * First read the status, because reading the received char 510 * destroys the status of this char. 511 */ 512 rr1 = zs_read_reg(cs, 1); 513 c = zs_read_data(cs); 514 515 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 516 /* Clear the receive error. */ 517 zs_write_csr(cs, ZSWR0_RESET_ERRORS); 518 } 519 520 ms->ms_rbuf[put] = (c << 8) | rr1; 521 put_next = (put + 1) & MS_RX_RING_MASK; 522 523 /* Would overrun if increment makes (put==get). */ 524 if (put_next == ms->ms_rbget) { 525 ms->ms_intr_flags |= INTR_RX_OVERRUN; 526 } else { 527 /* OK, really increment. */ 528 put = put_next; 529 } 530 531 /* Done reading. */ 532 ms->ms_rbput = put; 533 534 /* Ask for softint() call. */ 535 cs->cs_softreq = 1; 536 } 537 538 539 static void 540 ms_txint(cs) 541 register struct zs_chanstate *cs; 542 { 543 register struct ms_softc *ms; 544 545 ms = cs->cs_private; 546 zs_write_csr(cs, ZSWR0_RESET_TXINT); 547 ms->ms_intr_flags |= INTR_TX_EMPTY; 548 /* Ask for softint() call. */ 549 cs->cs_softreq = 1; 550 } 551 552 553 static void 554 ms_stint(cs, force) 555 register struct zs_chanstate *cs; 556 int force; 557 { 558 register struct ms_softc *ms; 559 register int rr0; 560 561 ms = cs->cs_private; 562 563 rr0 = zs_read_csr(cs); 564 zs_write_csr(cs, ZSWR0_RESET_STATUS); 565 566 /* 567 * We have to accumulate status line changes here. 568 * Otherwise, if we get multiple status interrupts 569 * before the softint runs, we could fail to notice 570 * some status line changes in the softint routine. 571 * Fix from Bill Studenmund, October 1996. 572 */ 573 cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0); 574 cs->cs_rr0 = rr0; 575 ms->ms_intr_flags |= INTR_ST_CHECK; 576 577 /* Ask for softint() call. */ 578 cs->cs_softreq = 1; 579 } 580 581 582 static void 583 ms_softint(cs) 584 struct zs_chanstate *cs; 585 { 586 register struct ms_softc *ms; 587 register int get, c, s; 588 int intr_flags; 589 register u_short ring_data; 590 591 ms = cs->cs_private; 592 593 /* Atomically get and clear flags. */ 594 s = splzs(); 595 intr_flags = ms->ms_intr_flags; 596 ms->ms_intr_flags = 0; 597 598 /* Now lower to spltty for the rest. */ 599 (void) spltty(); 600 601 /* 602 * Copy data from the receive ring to the event layer. 603 */ 604 get = ms->ms_rbget; 605 while (get != ms->ms_rbput) { 606 ring_data = ms->ms_rbuf[get]; 607 get = (get + 1) & MS_RX_RING_MASK; 608 609 /* low byte of ring_data is rr1 */ 610 c = (ring_data >> 8) & 0xff; 611 612 if (ring_data & ZSRR1_DO) 613 intr_flags |= INTR_RX_OVERRUN; 614 if (ring_data & (ZSRR1_FE | ZSRR1_PE)) { 615 log(LOG_ERR, "%s: input error (0x%x)\n", 616 ms->ms_dev.dv_xname, ring_data); 617 c = -1; /* signal input error */ 618 } 619 620 /* Pass this up to the "middle" layer. */ 621 ms_input(ms, c); 622 } 623 if (intr_flags & INTR_RX_OVERRUN) { 624 log(LOG_ERR, "%s: input overrun\n", 625 ms->ms_dev.dv_xname); 626 } 627 ms->ms_rbget = get; 628 629 if (intr_flags & INTR_TX_EMPTY) { 630 /* 631 * Transmit done. (Not expected.) 632 */ 633 log(LOG_ERR, "%s: transmit interrupt?\n", 634 ms->ms_dev.dv_xname); 635 } 636 637 if (intr_flags & INTR_ST_CHECK) { 638 /* 639 * Status line change. (Not expected.) 640 */ 641 log(LOG_ERR, "%s: status interrupt?\n", 642 ms->ms_dev.dv_xname); 643 cs->cs_rr0_delta = 0; 644 } 645 646 splx(s); 647 } 648 649 struct zsops zsops_ms = { 650 ms_rxint, /* receive char available */ 651 ms_stint, /* external/status */ 652 ms_txint, /* xmit buffer empty */ 653 ms_softint, /* process software interrupt */ 654 }; 655