|
|
1.1.1.3 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.3 ! root 5: * 1.1 root 6: * Permission to use, copy, modify and distribute this software and its 7: * documentation is hereby granted, provided that both the copyright 8: * notice and this permission notice appear in all copies of the 9: * software, derivative works or modified versions, and any portions 10: * thereof, and that both notices appear in supporting documentation. 1.1.1.3 ! root 11: * 1.1 root 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1.1.1.3 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.3 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.3 ! root 22: * 1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon 24: * the rights to redistribute these changes. 25: */ 26: /* ********************************************************************** 27: File: kd_mouse.c 28: Description: mouse driver as part of keyboard/display driver 29: 30: $ Header: $ 31: 32: Copyright Ing. C. Olivetti & C. S.p.A. 1989. 33: All rights reserved. 34: ********************************************************************** */ 35: /* 36: Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., 37: Cupertino, California. 38: 39: All Rights Reserved 40: 41: Permission to use, copy, modify, and distribute this software and 42: its documentation for any purpose and without fee is hereby 43: granted, provided that the above copyright notice appears in all 44: copies and that both the copyright notice and this permission notice 45: appear in supporting documentation, and that the name of Olivetti 46: not be used in advertising or publicity pertaining to distribution 47: of the software without specific, written prior permission. 48: 49: OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 50: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, 51: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 52: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 53: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 54: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION 55: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 56: */ 57: 58: /* 59: * Hacked up support for serial mouse connected to COM1, using Mouse 60: * Systems 5-byte protocol at 1200 baud. This should work for 61: * Mouse Systems, SummaMouse, and Logitek C7 mice. 62: * 63: * The interface provided by /dev/mouse is a series of events as 64: * described in i386at/kd.h. 65: */ 66: 67: #include <mach/boolean.h> 68: #include <sys/types.h> 69: #ifdef MACH_KERNEL 70: #include <device/errno.h> 71: #include <device/io_req.h> 1.1.1.3 ! root 72: #else /* MACH_KERNEL */ 1.1 root 73: #include <sys/file.h> 74: #include <sys/errno.h> 75: #include <kern/thread.h> 76: #include <sys/user.h> 77: #include <sys/proc.h> 78: #include <sys/kernel.h> 79: #include <sys/ioctl.h> 80: #include <sys/tty.h> 1.1.1.3 ! root 81: #endif /* MACH_KERNEL */ 1.1 root 82: #include <i386/ipl.h> 83: #include <chips/busses.h> 84: #include <i386at/kd.h> 85: #include <i386at/kd_queue.h> 86: #include <i386at/i8250.h> 87: 88: static int (*oldvect)(); /* old interrupt vector */ 89: static int oldunit; 90: static spl_t oldspl; 91: extern struct bus_device *cominfo[]; 92: 93: kd_event_queue mouse_queue; /* queue of mouse events */ 94: boolean_t mouse_in_use = FALSE; 95: #ifdef MACH_KERNEL 96: queue_head_t mouse_read_queue = { &mouse_read_queue, &mouse_read_queue }; 1.1.1.3 ! root 97: #else /* MACH_KERNEL */ 1.1 root 98: struct proc *mouse_sel = 0; /* selecting process, if any */ 99: short mousepgrp = 0; /* process group leader when dev is open */ 1.1.1.3 ! root 100: #endif /* MACH_KERNEL */ 1.1 root 101: 102: #ifdef MACH_KERNEL 1.1.1.3 ! root 103: #else /* MACH_KERNEL */ 1.1 root 104: int mouseflag = 0; 105: #define MOUSE_COLL 1 /* select collision */ 106: #define MOUSE_ASYNC 2 /* user wants asynch notification */ 107: #define MOUSE_NBIO 4 /* user wants non-blocking I/O */ 1.1.1.3 ! root 108: #endif /* MACH_KERNEL */ 1.1 root 109: 110: /* 111: * The state of the 3 buttons is encoded in the low-order 3 bits (both 112: * here and in other variables in the driver). 113: */ 114: u_char lastbuttons; /* previous state of mouse buttons */ 115: #define MOUSE_UP 1 116: #define MOUSE_DOWN 0 117: #define MOUSE_ALL_UP 0x7 118: 119: int mouseintr(); 120: void mouse_enqueue(); 121: int mouse_baud = BCNT1200; 122: 123: boolean_t mouse_char_cmd = FALSE; /* mouse response is to cmd */ 124: boolean_t mouse_char_wanted = FALSE; /* want mouse response */ 125: boolean_t mouse_char_in = FALSE; /* have mouse response */ 126: unsigned char mouse_char; /* mouse response */ 127: 128: 129: /* 130: * init_mouse_hw - initialize the serial port. 131: */ 132: init_mouse_hw(unit, mode) 133: { 134: caddr_t base_addr = (caddr_t)cominfo[unit]->address; 135: 136: outb(base_addr + RIE, 0); 137: outb(base_addr + RLC, LCDLAB); 138: outb(base_addr + RDLSB, mouse_baud & 0xff); 139: outb(base_addr + RDMSB, (mouse_baud >> 8) & 0xff); 140: outb(base_addr + RLC, mode); 141: outb(base_addr + RMC, MCDTR | MCRTS | MCOUT2); 142: outb(base_addr + RIE, IERD | IELS); 143: } 144: 145: 146: /* 147: * mouseopen - Verify that the request is read-only, initialize, 148: * and remember process group leader. 149: */ 150: /* 151: * Low 3 bits of minor are the com port #. 152: * The high 5 bits of minor are the mouse type 153: */ 154: #define MOUSE_SYSTEM_MOUSE 0 155: #define MICROSOFT_MOUSE 1 156: #define IBM_MOUSE 2 157: #define NO_MOUSE 3 158: #define LOGITECH_TRACKMAN 4 159: #define MICROSOFT_MOUSE7 5 160: static int mouse_type; 161: static int mousebufsize; 162: static int mousebufindex = 0; 163: int track_man[10]; 164: 165: /*ARGSUSED*/ 166: mouseopen(dev, flags) 167: dev_t dev; 168: int flags; 169: { 170: #ifdef MACH_KERNEL 1.1.1.3 ! root 171: #else /* MACH_KERNEL */ 1.1 root 172: if (flags & FWRITE) 173: return(ENODEV); 1.1.1.3 ! root 174: #endif /* MACH_KERNEL */ 1.1 root 175: if (mouse_in_use) 176: return(EBUSY); 177: mouse_in_use = TRUE; /* locking? */ 178: kdq_reset(&mouse_queue); 179: lastbuttons = MOUSE_ALL_UP; 180: #ifdef MACH_KERNEL 1.1.1.3 ! root 181: #else /* MACH_KERNEL */ 1.1 root 182: mousepgrp = u.u_procp->p_pgrp; 1.1.1.3 ! root 183: #endif /* MACH_KERNEL */ 1.1 root 184: 185: switch (mouse_type = ((minor(dev) & 0xf8) >> 3)) { 186: case MICROSOFT_MOUSE7: 187: mousebufsize = 3; 188: serial_mouse_open(dev); 189: init_mouse_hw(dev&7, LC7); 190: case MICROSOFT_MOUSE: 191: mousebufsize = 3; 192: serial_mouse_open(dev); 193: init_mouse_hw(dev&7, LC8); 194: break; 195: case MOUSE_SYSTEM_MOUSE: 196: mousebufsize = 5; 197: serial_mouse_open(dev); 198: init_mouse_hw(dev&7, LC8); 199: break; 200: case LOGITECH_TRACKMAN: 201: mousebufsize = 3; 202: serial_mouse_open(dev); 203: init_mouse_hw(dev&7, LC7); 204: track_man[0] = comgetc(dev&7); 205: track_man[1] = comgetc(dev&7); 1.1.1.3 ! root 206: if (track_man[0] != 0x4d && 1.1 root 207: track_man[1] != 0x33) { 208: printf("LOGITECH_TRACKMAN: NOT M3"); 209: } 210: break; 211: case IBM_MOUSE: 212: mousebufsize = 3; 213: kd_mouse_open(dev, 12); 214: ibm_ps2_mouse_open(dev); 215: break; 216: case NO_MOUSE: 217: break; 218: } 219: mousebufindex = 0; 220: return(0); 221: } 222: 223: serial_mouse_open(dev) 224: { 225: int unit = minor(dev) & 0x7; 226: int mouse_pic = cominfo[unit]->sysdep1; 227: 228: spl_t s = splhi(); /* disable interrupts */ 229: 230: oldvect = ivect[mouse_pic]; 231: ivect[mouse_pic] = mouseintr; 232: 233: oldunit = iunit[mouse_pic]; 234: iunit[mouse_pic] = unit; 235: 236: /* XXX other arrays to init? */ 237: splx(s); /* XXX - should come after init? */ 238: } 239: 240: int mouse_packets = 0; 241: kd_mouse_open(dev, mouse_pic) 242: { 243: spl_t s = splhi(); /* disable interrupts */ 244: extern int kdintr(); 245: 246: oldvect = ivect[mouse_pic]; 247: ivect[mouse_pic] = kdintr; 248: oldspl = intpri[mouse_pic]; 249: intpri[mouse_pic] = SPL6; 250: form_pic_mask(); 251: splx(s); 252: } 253: 254: /* 1.1.1.3 ! root 255: * mouseclose - Disable interrupts on the serial port, reset driver flags, 1.1 root 256: * and restore the serial port interrupt vector. 257: */ 258: mouseclose(dev, flags) 259: { 260: switch (mouse_type) { 261: case MICROSOFT_MOUSE: 262: case MICROSOFT_MOUSE7: 263: case MOUSE_SYSTEM_MOUSE: 264: case LOGITECH_TRACKMAN: 265: serial_mouse_close(dev); 266: break; 267: case IBM_MOUSE: 268: ibm_ps2_mouse_close(dev); 269: kd_mouse_close(dev, 12); 270: {int i = 20000; for (;i--;); } 271: kd_mouse_drain(); 272: break; 273: case NO_MOUSE: 274: break; 275: } 276: 277: kdq_reset(&mouse_queue); /* paranoia */ 278: mouse_in_use = FALSE; 279: #ifdef MACH_KERNEL 1.1.1.3 ! root 280: #else /* MACH_KERNEL */ 1.1 root 281: mousepgrp = 0; 282: mouseflag = 0; 283: mouse_sel = 0; 1.1.1.3 ! root 284: #endif /* MACH_KERNEL */ 1.1 root 285: } 286: 287: /*ARGSUSED*/ 288: serial_mouse_close(dev, flags) 289: dev_t dev; 290: int flags; 291: { 292: spl_t o_pri = splhi(); /* mutex with open() */ 293: int unit = minor(dev) & 0x7; 294: int mouse_pic = cominfo[unit]->sysdep1; 295: caddr_t base_addr = (caddr_t)cominfo[unit]->address; 296: 297: assert(ivect[mouse_pic] == mouseintr); 298: outb(base_addr + RIE, 0); /* disable serial port */ 299: outb(base_addr + RMC, 0); /* no rts */ 300: ivect[mouse_pic] = oldvect; 301: iunit[mouse_pic] = oldunit; 302: 303: (void)splx(o_pri); 304: } 305: 306: kd_mouse_close(dev, mouse_pic) 307: { 308: spl_t s = splhi(); 309: 310: ivect[mouse_pic] = oldvect; 311: intpri[mouse_pic] = oldspl; 312: form_pic_mask(); 313: splx(s); 314: } 315: 316: #ifdef MACH_KERNEL 1.1.1.2 root 317: io_return_t mousegetstat(dev, flavor, data, count) 318: dev_t dev; 319: int flavor; 320: int * data; /* pointer to OUT array */ 321: unsigned int *count; /* OUT */ 322: { 323: io_return_t result; 324: 325: switch (flavor) { 326: case DEV_GET_SIZE: 327: data[DEV_GET_SIZE_DEVICE_SIZE] = 0; 328: data[DEV_GET_SIZE_RECORD_SIZE] = sizeof(kd_event); 329: *count = DEV_GET_SIZE_COUNT; 330: break; 331: default: 332: return D_INVALID_OPERATION; 333: } 334: return D_SUCCESS; 335: } 336: 1.1.1.3 ! root 337: #else /* MACH_KERNEL */ 1.1 root 338: /* 339: * mouseioctl - handling for asynch & non-blocking I/O. 340: */ 341: 342: /*ARGSUSED*/ 343: mouseioctl(dev, cmd, data, flag) 344: dev_t dev; 345: int cmd; 346: caddr_t data; 347: int flag; 348: { 349: int s = SPLKD(); 350: int err = 0; 351: 352: switch (cmd) { 353: case FIONBIO: 354: if (*(int *)data) 355: mouseflag |= MOUSE_NBIO; 356: else 357: mouseflag &= ~MOUSE_NBIO; 358: break; 359: case FIOASYNC: 360: if (*(int *)data) 361: mouseflag |= MOUSE_ASYNC; 362: else 363: mouseflag &= ~MOUSE_ASYNC; 364: break; 365: default: 366: err = ENOTTY; 367: break; 368: } 369: 370: splx(s); 371: return(err); 372: } 373: 374: 375: /* 376: * mouseselect - check for pending events, etc. 377: */ 378: 379: /*ARGSUSED*/ 380: mouseselect(dev, rw) 381: { 382: int s = SPLKD(); 383: 384: if (!kdq_empty(&mouse_queue)) { 385: splx(s); 386: return(1); 387: } 388: 389: if (mouse_sel) 390: mouseflag |= MOUSE_COLL; 391: else 392: mouse_sel = (struct proc *)current_thread(); 393: /* eeeyuck */ 1.1.1.3 ! root 394: 1.1 root 395: splx(s); 396: return(0); 397: } 1.1.1.3 ! root 398: #endif /* MACH_KERNEL */ 1.1 root 399: 400: /* 401: * mouseread - dequeue and return any queued events. 402: */ 403: #ifdef MACH_KERNEL 404: boolean_t mouse_read_done(); /* forward */ 405: 406: mouseread(dev, ior) 407: dev_t dev; 408: register io_req_t ior; 409: { 410: register int err, count; 411: register spl_t s; 412: 1.1.1.2 root 413: /* Check if IO_COUNT is a multiple of the record size. */ 414: if (ior->io_count % sizeof(kd_event) != 0) 415: return D_INVALID_SIZE; 416: 1.1 root 417: err = device_read_alloc(ior, (vm_size_t)ior->io_count); 418: if (err != KERN_SUCCESS) 419: return (err); 420: 421: s = SPLKD(); 422: if (kdq_empty(&mouse_queue)) { 423: if (ior->io_mode & D_NOWAIT) { 424: splx(s); 425: return (D_WOULD_BLOCK); 426: } 427: ior->io_done = mouse_read_done; 428: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior); 429: splx(s); 430: return (D_IO_QUEUED); 431: } 432: count = 0; 433: while (!kdq_empty(&mouse_queue) && count < ior->io_count) { 434: register kd_event *ev; 435: 436: ev = kdq_get(&mouse_queue); 437: *(kd_event *)(&ior->io_data[count]) = *ev; 438: count += sizeof(kd_event); 439: } 440: splx(s); 441: ior->io_residual = ior->io_count - count; 442: return (D_SUCCESS); 443: } 444: 445: boolean_t mouse_read_done(ior) 446: register io_req_t ior; 447: { 448: register int count; 449: register spl_t s; 450: 451: s = SPLKD(); 452: if (kdq_empty(&mouse_queue)) { 453: ior->io_done = mouse_read_done; 454: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior); 455: splx(s); 456: return (FALSE); 457: } 458: 459: count = 0; 460: while (!kdq_empty(&mouse_queue) && count < ior->io_count) { 461: register kd_event *ev; 462: 463: ev = kdq_get(&mouse_queue); 464: *(kd_event *)(&ior->io_data[count]) = *ev; 465: count += sizeof(kd_event); 466: } 467: splx(s); 468: 469: ior->io_residual = ior->io_count - count; 470: ds_read_done(ior); 471: 472: return (TRUE); 473: } 474: 1.1.1.3 ! root 475: #else /* MACH_KERNEL */ 1.1 root 476: /*ARGSUSED*/ 477: mouseread(dev, uio) 478: dev_t dev; 479: struct uio *uio; 480: { 481: int s = SPLKD(); 482: int err = 0; 483: kd_event *ev; 484: int i; 485: char *cp; 486: 487: if (kdq_empty(&mouse_queue)) 488: if (mouseflag & MOUSE_NBIO) { 489: err = EWOULDBLOCK; 490: goto done; 1.1.1.3 ! root 491: } else 1.1 root 492: while (kdq_empty(&mouse_queue)) { 493: splx(s); 494: sleep((caddr_t)&mouse_queue, TTIPRI); 495: s = SPLKD(); 496: } 497: 498: while (!kdq_empty(&mouse_queue) && uio->uio_resid >= sizeof(kd_event)) { 499: ev = kdq_get(&mouse_queue); 500: for (cp = (char *)ev, i = 0; i < sizeof(kd_event); 501: ++i, ++cp) { 502: err = ureadc(*cp, uio); 503: if (err) 504: goto done; 505: } 506: } 507: 508: done: 509: splx(s); 510: return(err); 511: } 1.1.1.3 ! root 512: #endif /* MACH_KERNEL */ 1.1 root 513: 514: 515: /* 516: * mouseintr - Get a byte and pass it up for handling. Called at SPLKD. 517: */ 518: mouseintr(unit) 519: { 520: caddr_t base_addr = (caddr_t)cominfo[unit]->address; 521: unsigned char id, ls; 522: 523: /* get reason for interrupt and line status */ 524: id = inb(base_addr + RID); 525: ls = inb(base_addr + RLS); 526: 527: /* handle status changes */ 528: if (id == IDLS) { 529: if (ls & LSDR) { 530: inb(base_addr + RDAT); /* flush bad character */ 531: } 532: return; /* ignore status change */ 533: } 534: 535: if (id & IDRD) { 536: mouse_handle_byte((u_char)(inb(base_addr + RDAT) & 0xff)); 537: } 538: } 539: 540: 541: /* 542: * handle_byte - Accumulate bytes until we have an entire packet. 543: * If the mouse has moved or any of the buttons have changed state (up 544: * or down), enqueue the corresponding events. 545: * Called at SPLKD. 546: * XXX - magic numbers. 547: */ 548: int show_mouse_byte = 0; 549: /* 1.1.1.3 ! root 550: X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0 1.1 root 551: X down; middle down; X up; middle up 50 0 0; 50 0 0 22; 40 0 0 22; 40 0 0 2 552: * 553: * The trick here is that all the while the middle button is down you get 4 byte 554: * packets with the last byte 0x22. When the middle button goes up you get a 555: * last packet with 0x02. 556: */ 557: int lastgitech = 0x40; /* figure whether the first 3 bytes imply */ 558: /* its time to expect a fourth */ 559: int fourthgitech = 0; /* look for the 4th byte; we must process it */ 560: int middlegitech = 0; /* what should the middle button be */ 561: 562: #define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */ 563: static u_char mousebuf[MOUSEBUFSIZE]; /* 5-byte packet from mouse */ 564: 565: mouse_handle_byte(ch) 566: u_char ch; 567: { 568: if (show_mouse_byte) { 569: printf("%x(%c) ", ch, ch); 570: } 571: 572: if (mouse_char_cmd) { 573: /* 574: * Mouse character is response to command 575: */ 576: mouse_char = ch; 577: mouse_char_in = TRUE; 578: if (mouse_char_wanted) { 579: mouse_char_wanted = FALSE; 580: wakeup(&mouse_char); 581: } 582: return; 583: } 584: 585: if (mousebufindex == 0) { 586: switch (mouse_type) { 587: case MICROSOFT_MOUSE7: 588: if ((ch & 0x40) != 0x40) 589: return; 590: break; 591: case MICROSOFT_MOUSE: 592: if ((ch & 0xc0) != 0xc0) 593: return; 594: break; 595: case MOUSE_SYSTEM_MOUSE: 596: if ((ch & 0xf8) != 0x80) 597: return; 598: break; 599: case LOGITECH_TRACKMAN: 600: if (fourthgitech == 1) { 601: fourthgitech = 0; 602: if (ch & 0xf0) 603: middlegitech = 0x4; 604: else 605: middlegitech = 0x0; 606: mouse_packet_microsoft_mouse(mousebuf); 607: return; 608: } else if ((ch & 0xc0) != 0x40) 609: return; 610: break; 611: case IBM_MOUSE: 612: break; 613: } 614: } 615: 616: mousebuf[mousebufindex++] = ch; 617: if (mousebufindex < mousebufsize) 618: return; 1.1.1.3 ! root 619: 1.1 root 620: /* got a packet */ 621: mousebufindex = 0; 622: 623: switch (mouse_type) { 624: case MICROSOFT_MOUSE7: 625: case MICROSOFT_MOUSE: 626: mouse_packet_microsoft_mouse(mousebuf); 627: break; 628: case MOUSE_SYSTEM_MOUSE: 629: mouse_packet_mouse_system_mouse(mousebuf); 630: break; 631: case LOGITECH_TRACKMAN: 632: if ( mousebuf[1] || mousebuf[2] || 633: mousebuf[0] != lastgitech) { 634: mouse_packet_microsoft_mouse(mousebuf); 635: lastgitech = mousebuf[0] & 0xf0; 636: } else { 637: fourthgitech = 1; 638: } 639: break; 640: case IBM_MOUSE: 641: mouse_packet_ibm_ps2_mouse(mousebuf); 642: break; 643: } 644: } 645: 646: mouse_packet_mouse_system_mouse(mousebuf) 647: u_char mousebuf[MOUSEBUFSIZE]; 648: { 649: u_char buttons, buttonchanges; 650: struct mouse_motion moved; 651: 652: buttons = mousebuf[0] & 0x7; /* get current state of buttons */ 653: buttonchanges = buttons ^ lastbuttons; 654: moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3]; 655: moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4]; 656: 657: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) 658: mouse_moved(moved); 659: 660: if (buttonchanges != 0) { 661: lastbuttons = buttons; 662: if (buttonchanges & 1) 663: mouse_button(MOUSE_RIGHT, buttons & 1); 664: if (buttonchanges & 2) 665: mouse_button(MOUSE_MIDDLE, (buttons & 2) >> 1); 666: if (buttonchanges & 4) 667: mouse_button(MOUSE_LEFT, (buttons & 4) >> 2); 668: } 669: } 670: 671: /* same as above for microsoft mouse */ 672: /* 673: * 3 byte microsoft format used 674: * 675: * 7 6 5 4 3 2 1 0 676: * 1 1 L R Y7 Y6 X7 X6 677: * 1 0 X5 X4 X3 X3 X1 X0 678: * 1 0 Y5 Y4 Y3 Y2 Y1 Y0 679: * 680: */ 681: mouse_packet_microsoft_mouse(mousebuf) 682: u_char mousebuf[MOUSEBUFSIZE]; 683: { 684: u_char buttons, buttonchanges; 685: struct mouse_motion moved; 686: 687: buttons = ((mousebuf[0] & 0x30) >> 4); 688: buttons |= middlegitech; 689: /* get current state of buttons */ 690: #ifdef gross_hack 691: if (buttons == 0x03) /* both buttons down */ 692: buttons = 0x04; 693: #endif /* gross_hack */ 694: buttons = (~buttons) & 0x07; /* convert to not pressed */ 695: 696: buttonchanges = buttons ^ lastbuttons; 697: moved.mm_deltaX = ((mousebuf[0] & 0x03) << 6) | (mousebuf[1] & 0x3F); 698: moved.mm_deltaY = ((mousebuf[0] & 0x0c) << 4) | (mousebuf[2] & 0x3F); 699: if (moved.mm_deltaX & 0x80) /* negative, in fact */ 700: moved.mm_deltaX = moved.mm_deltaX - 0x100; 701: if (moved.mm_deltaY & 0x80) /* negative, in fact */ 702: moved.mm_deltaY = moved.mm_deltaY - 0x100; 703: /* and finally the Y orientation is different for the microsoft mouse */ 704: moved.mm_deltaY = -moved.mm_deltaY; 705: 706: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) 707: mouse_moved(moved); 708: 709: if (buttonchanges != 0) { 710: lastbuttons = buttons; 711: if (buttonchanges & 1) 712: mouse_button(MOUSE_RIGHT, (buttons & 1) ? 713: MOUSE_UP : MOUSE_DOWN); 714: if (buttonchanges & 2) 715: mouse_button(MOUSE_LEFT, (buttons & 2) ? 716: MOUSE_UP : MOUSE_DOWN); 717: if (buttonchanges & 4) 718: mouse_button(MOUSE_MIDDLE, (buttons & 4) ? 719: MOUSE_UP : MOUSE_DOWN); 720: } 721: } 722: 723: /* 724: * AUX device (PS2) open/close 725: */ 726: 727: /* 728: * Write character to mouse. Called at spltty. 729: */ 730: void kd_mouse_write( 731: unsigned char ch) 732: { 733: while (inb(K_STATUS) & K_IBUF_FUL) 734: continue; /* wait for 'input' port empty */ 735: outb(K_CMD, 0xd4); /* send next character to mouse */ 736: 737: while (inb(K_STATUS) & K_IBUF_FUL) 738: continue; /* wait for 'input' port empty */ 739: outb(K_RDWR, ch); /* send command to mouse */ 740: } 741: 742: /* 743: * Read next character from mouse, waiting for interrupt 744: * to deliver it. Called at spltty. 745: */ 746: int kd_mouse_read(void) 747: { 748: int ch; 749: 750: while (!mouse_char_in) { 751: mouse_char_wanted = TRUE; 752: #ifdef MACH_KERNEL 753: assert_wait((event_t) &mouse_char, FALSE); 754: thread_block((void (*)()) 0); 1.1.1.3 ! root 755: #else /* MACH_KERNEL */ 1.1 root 756: sleep(&mouse_char, PZERO); 1.1.1.3 ! root 757: #endif /* MACH_KERNEL */ 1.1 root 758: } 759: 760: ch = mouse_char; 761: mouse_char_in = FALSE; 762: 763: return ch; 764: } 765: 766: ibm_ps2_mouse_open(dev) 767: { 768: spl_t s = spltty(); 769: 770: lastbuttons = 0; 771: mouse_char_cmd = TRUE; /* responses are to commands */ 772: 773: kd_sendcmd(0xa8); /* enable mouse in kbd */ 774: 775: kd_cmdreg_write(0x47); /* allow mouse interrupts */ 776: /* magic number for ibm? */ 777: 778: kd_mouse_write(0xff); /* reset mouse */ 779: if (kd_mouse_read() != 0xfa) { 780: splx(s); 781: return; /* need ACK */ 782: } 783: 784: (void) kd_mouse_read(); /* discard 2-character mouse ID */ 785: (void) kd_mouse_read(); 786: 787: kd_mouse_write(0xea); /* set stream mode */ 788: if (kd_mouse_read() != 0xfa) { 789: splx(s); 790: return; /* need ACK */ 791: } 792: 793: kd_mouse_write(0xf4); /* enable */ 794: if (kd_mouse_read() != 0xfa) { 795: splx(s); 796: return; /* need ACK */ 797: } 798: 799: mouse_char_cmd = FALSE; /* now we get mouse packets */ 800: 801: splx(s); 802: } 803: 804: ibm_ps2_mouse_close(dev) 805: { 806: spl_t s = spltty(); 807: 808: mouse_char_cmd = TRUE; /* responses are to commands */ 809: 810: kd_mouse_write(0xff); /* reset mouse */ 811: if (kd_mouse_read() == 0xfa) { 812: /* got ACK: discard 2-char mouse ID */ 813: (void) kd_mouse_read(); 814: (void) kd_mouse_read(); 815: } 816: 817: kd_sendcmd(0xa7); /* disable mouse in kbd */ 818: kd_cmdreg_write(0x65); /* disallow mouse interrupts */ 819: /* magic number for ibm? */ 820: 821: splx(s); 822: } 823: 824: /* 825: * 3 byte ibm ps2 format used 826: * 827: * 7 6 5 4 3 2 1 0 828: * YO XO YS XS 1 M R L 829: * X7 X6 X5 X4 X3 X3 X1 X0 830: * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 831: * 832: */ 833: mouse_packet_ibm_ps2_mouse(mousebuf) 834: u_char mousebuf[MOUSEBUFSIZE]; 835: { 836: u_char buttons, buttonchanges; 837: struct mouse_motion moved; 838: 839: buttons = mousebuf[0] & 0x7; /* get current state of buttons */ 840: buttonchanges = buttons ^ lastbuttons; 841: moved.mm_deltaX = ((mousebuf[0]&0x10) ? 0xffffff00 : 0 ) | (u_char)mousebuf[1]; 842: moved.mm_deltaY = ((mousebuf[0]&0x20) ? 0xffffff00 : 0 ) | (u_char)mousebuf[2]; 843: if (mouse_packets) { 844: printf("(%x:%x:%x)", mousebuf[0], mousebuf[1], mousebuf[2]); 845: return; 846: } 847: 848: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0) 849: mouse_moved(moved); 850: 851: if (buttonchanges != 0) { 852: lastbuttons = buttons; 853: if (buttonchanges & 1) 854: mouse_button(MOUSE_LEFT, !(buttons & 1)); 855: if (buttonchanges & 2) 856: mouse_button(MOUSE_RIGHT, !((buttons & 2) >> 1)); 857: if (buttonchanges & 4) 858: mouse_button(MOUSE_MIDDLE, !((buttons & 4) >> 2)); 859: } 860: } 861: 862: /* 863: * Enqueue a mouse-motion event. Called at SPLKD. 864: */ 865: mouse_moved(where) 866: struct mouse_motion where; 867: { 868: kd_event ev; 869: 870: ev.type = MOUSE_MOTION; 871: ev.time = time; 872: ev.value.mmotion = where; 873: mouse_enqueue(&ev); 874: } 875: 876: 877: /* 878: * Enqueue an event for mouse button press or release. Called at SPLKD. 879: */ 880: mouse_button(which, direction) 881: kev_type which; 882: u_char direction; 883: { 884: kd_event ev; 885: 886: ev.type = which; 887: ev.time = time; 888: ev.value.up = (direction == MOUSE_UP) ? TRUE : FALSE; 889: mouse_enqueue(&ev); 890: } 891: 892: 893: /* 894: * mouse_enqueue - enqueue an event and wake up selecting processes, if 895: * any. Called at SPLKD. 896: */ 897: 898: void 899: mouse_enqueue(ev) 900: kd_event *ev; 901: { 902: if (kdq_full(&mouse_queue)) 903: printf("mouse: queue full\n"); 904: else 905: kdq_put(&mouse_queue, ev); 906: 907: #ifdef MACH_KERNEL 908: { 909: register io_req_t ior; 910: while ((ior = (io_req_t)dequeue_head(&mouse_read_queue)) != 0) 911: iodone(ior); 912: } 1.1.1.3 ! root 913: #else /* MACH_KERNEL */ 1.1 root 914: if (mouse_sel) { 915: selwakeup(mouse_sel, mouseflag & MOUSE_COLL); 916: mouse_sel = 0; 917: mouseflag &= ~MOUSE_COLL; 918: } 919: if (mouseflag & MOUSE_ASYNC) 920: gsignal(mousepgrp, SIGIO); 921: wakeup((caddr_t)&mouse_queue); 1.1.1.3 ! root 922: #endif /* MACH_KERNEL */ 1.1 root 923: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.