|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4: * All Rights Reserved.
5: *
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.
11: *
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.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
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>
72: #else MACH_KERNEL
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>
81: #endif MACH_KERNEL
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 };
97: #else MACH_KERNEL
98: struct proc *mouse_sel = 0; /* selecting process, if any */
99: short mousepgrp = 0; /* process group leader when dev is open */
100: #endif MACH_KERNEL
101:
102: #ifdef MACH_KERNEL
103: #else MACH_KERNEL
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 */
108: #endif MACH_KERNEL
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
171: #else MACH_KERNEL
172: if (flags & FWRITE)
173: return(ENODEV);
174: #endif MACH_KERNEL
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
181: #else MACH_KERNEL
182: mousepgrp = u.u_procp->p_pgrp;
183: #endif MACH_KERNEL
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);
206: if (track_man[0] != 0x4d &&
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: /*
255: * mouseclose - Disable interrupts on the serial port, reset driver flags,
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
280: #else MACH_KERNEL
281: mousepgrp = 0;
282: mouseflag = 0;
283: mouse_sel = 0;
284: #endif MACH_KERNEL
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 root 337: #else MACH_KERNEL
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 */
394:
395: splx(s);
396: return(0);
397: }
398: #endif MACH_KERNEL
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:
475: #else MACH_KERNEL
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;
491: } else
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: }
512: #endif MACH_KERNEL
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: /*
550: X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0
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;
619:
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);
755: #else MACH_KERNEL
756: sleep(&mouse_char, PZERO);
757: #endif MACH_KERNEL
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: }
913: #else MACH_KERNEL
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);
922: #endif MACH_KERNEL
923: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.