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