|
|
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
317: #else MACH_KERNEL
318: /*
319: * mouseioctl - handling for asynch & non-blocking I/O.
320: */
321:
322: /*ARGSUSED*/
323: mouseioctl(dev, cmd, data, flag)
324: dev_t dev;
325: int cmd;
326: caddr_t data;
327: int flag;
328: {
329: int s = SPLKD();
330: int err = 0;
331:
332: switch (cmd) {
333: case FIONBIO:
334: if (*(int *)data)
335: mouseflag |= MOUSE_NBIO;
336: else
337: mouseflag &= ~MOUSE_NBIO;
338: break;
339: case FIOASYNC:
340: if (*(int *)data)
341: mouseflag |= MOUSE_ASYNC;
342: else
343: mouseflag &= ~MOUSE_ASYNC;
344: break;
345: default:
346: err = ENOTTY;
347: break;
348: }
349:
350: splx(s);
351: return(err);
352: }
353:
354:
355: /*
356: * mouseselect - check for pending events, etc.
357: */
358:
359: /*ARGSUSED*/
360: mouseselect(dev, rw)
361: {
362: int s = SPLKD();
363:
364: if (!kdq_empty(&mouse_queue)) {
365: splx(s);
366: return(1);
367: }
368:
369: if (mouse_sel)
370: mouseflag |= MOUSE_COLL;
371: else
372: mouse_sel = (struct proc *)current_thread();
373: /* eeeyuck */
374:
375: splx(s);
376: return(0);
377: }
378: #endif MACH_KERNEL
379:
380: /*
381: * mouseread - dequeue and return any queued events.
382: */
383: #ifdef MACH_KERNEL
384: boolean_t mouse_read_done(); /* forward */
385:
386: mouseread(dev, ior)
387: dev_t dev;
388: register io_req_t ior;
389: {
390: register int err, count;
391: register spl_t s;
392:
393: err = device_read_alloc(ior, (vm_size_t)ior->io_count);
394: if (err != KERN_SUCCESS)
395: return (err);
396:
397: s = SPLKD();
398: if (kdq_empty(&mouse_queue)) {
399: if (ior->io_mode & D_NOWAIT) {
400: splx(s);
401: return (D_WOULD_BLOCK);
402: }
403: ior->io_done = mouse_read_done;
404: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
405: splx(s);
406: return (D_IO_QUEUED);
407: }
408: count = 0;
409: while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
410: register kd_event *ev;
411:
412: ev = kdq_get(&mouse_queue);
413: *(kd_event *)(&ior->io_data[count]) = *ev;
414: count += sizeof(kd_event);
415: }
416: splx(s);
417: ior->io_residual = ior->io_count - count;
418: return (D_SUCCESS);
419: }
420:
421: boolean_t mouse_read_done(ior)
422: register io_req_t ior;
423: {
424: register int count;
425: register spl_t s;
426:
427: s = SPLKD();
428: if (kdq_empty(&mouse_queue)) {
429: ior->io_done = mouse_read_done;
430: enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
431: splx(s);
432: return (FALSE);
433: }
434:
435: count = 0;
436: while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
437: register kd_event *ev;
438:
439: ev = kdq_get(&mouse_queue);
440: *(kd_event *)(&ior->io_data[count]) = *ev;
441: count += sizeof(kd_event);
442: }
443: splx(s);
444:
445: ior->io_residual = ior->io_count - count;
446: ds_read_done(ior);
447:
448: return (TRUE);
449: }
450:
451: #else MACH_KERNEL
452: /*ARGSUSED*/
453: mouseread(dev, uio)
454: dev_t dev;
455: struct uio *uio;
456: {
457: int s = SPLKD();
458: int err = 0;
459: kd_event *ev;
460: int i;
461: char *cp;
462:
463: if (kdq_empty(&mouse_queue))
464: if (mouseflag & MOUSE_NBIO) {
465: err = EWOULDBLOCK;
466: goto done;
467: } else
468: while (kdq_empty(&mouse_queue)) {
469: splx(s);
470: sleep((caddr_t)&mouse_queue, TTIPRI);
471: s = SPLKD();
472: }
473:
474: while (!kdq_empty(&mouse_queue) && uio->uio_resid >= sizeof(kd_event)) {
475: ev = kdq_get(&mouse_queue);
476: for (cp = (char *)ev, i = 0; i < sizeof(kd_event);
477: ++i, ++cp) {
478: err = ureadc(*cp, uio);
479: if (err)
480: goto done;
481: }
482: }
483:
484: done:
485: splx(s);
486: return(err);
487: }
488: #endif MACH_KERNEL
489:
490:
491: /*
492: * mouseintr - Get a byte and pass it up for handling. Called at SPLKD.
493: */
494: mouseintr(unit)
495: {
496: caddr_t base_addr = (caddr_t)cominfo[unit]->address;
497: unsigned char id, ls;
498:
499: /* get reason for interrupt and line status */
500: id = inb(base_addr + RID);
501: ls = inb(base_addr + RLS);
502:
503: /* handle status changes */
504: if (id == IDLS) {
505: if (ls & LSDR) {
506: inb(base_addr + RDAT); /* flush bad character */
507: }
508: return; /* ignore status change */
509: }
510:
511: if (id & IDRD) {
512: mouse_handle_byte((u_char)(inb(base_addr + RDAT) & 0xff));
513: }
514: }
515:
516:
517: /*
518: * handle_byte - Accumulate bytes until we have an entire packet.
519: * If the mouse has moved or any of the buttons have changed state (up
520: * or down), enqueue the corresponding events.
521: * Called at SPLKD.
522: * XXX - magic numbers.
523: */
524: int show_mouse_byte = 0;
525: /*
526: X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0
527: X down; middle down; X up; middle up 50 0 0; 50 0 0 22; 40 0 0 22; 40 0 0 2
528: *
529: * The trick here is that all the while the middle button is down you get 4 byte
530: * packets with the last byte 0x22. When the middle button goes up you get a
531: * last packet with 0x02.
532: */
533: int lastgitech = 0x40; /* figure whether the first 3 bytes imply */
534: /* its time to expect a fourth */
535: int fourthgitech = 0; /* look for the 4th byte; we must process it */
536: int middlegitech = 0; /* what should the middle button be */
537:
538: #define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */
539: static u_char mousebuf[MOUSEBUFSIZE]; /* 5-byte packet from mouse */
540:
541: mouse_handle_byte(ch)
542: u_char ch;
543: {
544: if (show_mouse_byte) {
545: printf("%x(%c) ", ch, ch);
546: }
547:
548: if (mouse_char_cmd) {
549: /*
550: * Mouse character is response to command
551: */
552: mouse_char = ch;
553: mouse_char_in = TRUE;
554: if (mouse_char_wanted) {
555: mouse_char_wanted = FALSE;
556: wakeup(&mouse_char);
557: }
558: return;
559: }
560:
561: if (mousebufindex == 0) {
562: switch (mouse_type) {
563: case MICROSOFT_MOUSE7:
564: if ((ch & 0x40) != 0x40)
565: return;
566: break;
567: case MICROSOFT_MOUSE:
568: if ((ch & 0xc0) != 0xc0)
569: return;
570: break;
571: case MOUSE_SYSTEM_MOUSE:
572: if ((ch & 0xf8) != 0x80)
573: return;
574: break;
575: case LOGITECH_TRACKMAN:
576: if (fourthgitech == 1) {
577: fourthgitech = 0;
578: if (ch & 0xf0)
579: middlegitech = 0x4;
580: else
581: middlegitech = 0x0;
582: mouse_packet_microsoft_mouse(mousebuf);
583: return;
584: } else if ((ch & 0xc0) != 0x40)
585: return;
586: break;
587: case IBM_MOUSE:
588: break;
589: }
590: }
591:
592: mousebuf[mousebufindex++] = ch;
593: if (mousebufindex < mousebufsize)
594: return;
595:
596: /* got a packet */
597: mousebufindex = 0;
598:
599: switch (mouse_type) {
600: case MICROSOFT_MOUSE7:
601: case MICROSOFT_MOUSE:
602: mouse_packet_microsoft_mouse(mousebuf);
603: break;
604: case MOUSE_SYSTEM_MOUSE:
605: mouse_packet_mouse_system_mouse(mousebuf);
606: break;
607: case LOGITECH_TRACKMAN:
608: if ( mousebuf[1] || mousebuf[2] ||
609: mousebuf[0] != lastgitech) {
610: mouse_packet_microsoft_mouse(mousebuf);
611: lastgitech = mousebuf[0] & 0xf0;
612: } else {
613: fourthgitech = 1;
614: }
615: break;
616: case IBM_MOUSE:
617: mouse_packet_ibm_ps2_mouse(mousebuf);
618: break;
619: }
620: }
621:
622: mouse_packet_mouse_system_mouse(mousebuf)
623: u_char mousebuf[MOUSEBUFSIZE];
624: {
625: u_char buttons, buttonchanges;
626: struct mouse_motion moved;
627:
628: buttons = mousebuf[0] & 0x7; /* get current state of buttons */
629: buttonchanges = buttons ^ lastbuttons;
630: moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3];
631: moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4];
632:
633: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
634: mouse_moved(moved);
635:
636: if (buttonchanges != 0) {
637: lastbuttons = buttons;
638: if (buttonchanges & 1)
639: mouse_button(MOUSE_RIGHT, buttons & 1);
640: if (buttonchanges & 2)
641: mouse_button(MOUSE_MIDDLE, (buttons & 2) >> 1);
642: if (buttonchanges & 4)
643: mouse_button(MOUSE_LEFT, (buttons & 4) >> 2);
644: }
645: }
646:
647: /* same as above for microsoft mouse */
648: /*
649: * 3 byte microsoft format used
650: *
651: * 7 6 5 4 3 2 1 0
652: * 1 1 L R Y7 Y6 X7 X6
653: * 1 0 X5 X4 X3 X3 X1 X0
654: * 1 0 Y5 Y4 Y3 Y2 Y1 Y0
655: *
656: */
657: mouse_packet_microsoft_mouse(mousebuf)
658: u_char mousebuf[MOUSEBUFSIZE];
659: {
660: u_char buttons, buttonchanges;
661: struct mouse_motion moved;
662:
663: buttons = ((mousebuf[0] & 0x30) >> 4);
664: buttons |= middlegitech;
665: /* get current state of buttons */
666: #ifdef gross_hack
667: if (buttons == 0x03) /* both buttons down */
668: buttons = 0x04;
669: #endif /* gross_hack */
670: buttons = (~buttons) & 0x07; /* convert to not pressed */
671:
672: buttonchanges = buttons ^ lastbuttons;
673: moved.mm_deltaX = ((mousebuf[0] & 0x03) << 6) | (mousebuf[1] & 0x3F);
674: moved.mm_deltaY = ((mousebuf[0] & 0x0c) << 4) | (mousebuf[2] & 0x3F);
675: if (moved.mm_deltaX & 0x80) /* negative, in fact */
676: moved.mm_deltaX = moved.mm_deltaX - 0x100;
677: if (moved.mm_deltaY & 0x80) /* negative, in fact */
678: moved.mm_deltaY = moved.mm_deltaY - 0x100;
679: /* and finally the Y orientation is different for the microsoft mouse */
680: moved.mm_deltaY = -moved.mm_deltaY;
681:
682: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
683: mouse_moved(moved);
684:
685: if (buttonchanges != 0) {
686: lastbuttons = buttons;
687: if (buttonchanges & 1)
688: mouse_button(MOUSE_RIGHT, (buttons & 1) ?
689: MOUSE_UP : MOUSE_DOWN);
690: if (buttonchanges & 2)
691: mouse_button(MOUSE_LEFT, (buttons & 2) ?
692: MOUSE_UP : MOUSE_DOWN);
693: if (buttonchanges & 4)
694: mouse_button(MOUSE_MIDDLE, (buttons & 4) ?
695: MOUSE_UP : MOUSE_DOWN);
696: }
697: }
698:
699: /*
700: * AUX device (PS2) open/close
701: */
702:
703: /*
704: * Write character to mouse. Called at spltty.
705: */
706: void kd_mouse_write(
707: unsigned char ch)
708: {
709: while (inb(K_STATUS) & K_IBUF_FUL)
710: continue; /* wait for 'input' port empty */
711: outb(K_CMD, 0xd4); /* send next character to mouse */
712:
713: while (inb(K_STATUS) & K_IBUF_FUL)
714: continue; /* wait for 'input' port empty */
715: outb(K_RDWR, ch); /* send command to mouse */
716: }
717:
718: /*
719: * Read next character from mouse, waiting for interrupt
720: * to deliver it. Called at spltty.
721: */
722: int kd_mouse_read(void)
723: {
724: int ch;
725:
726: while (!mouse_char_in) {
727: mouse_char_wanted = TRUE;
728: #ifdef MACH_KERNEL
729: assert_wait((event_t) &mouse_char, FALSE);
730: thread_block((void (*)()) 0);
731: #else MACH_KERNEL
732: sleep(&mouse_char, PZERO);
733: #endif MACH_KERNEL
734: }
735:
736: ch = mouse_char;
737: mouse_char_in = FALSE;
738:
739: return ch;
740: }
741:
742: ibm_ps2_mouse_open(dev)
743: {
744: spl_t s = spltty();
745:
746: lastbuttons = 0;
747: mouse_char_cmd = TRUE; /* responses are to commands */
748:
749: kd_sendcmd(0xa8); /* enable mouse in kbd */
750:
751: kd_cmdreg_write(0x47); /* allow mouse interrupts */
752: /* magic number for ibm? */
753:
754: kd_mouse_write(0xff); /* reset mouse */
755: if (kd_mouse_read() != 0xfa) {
756: splx(s);
757: return; /* need ACK */
758: }
759:
760: (void) kd_mouse_read(); /* discard 2-character mouse ID */
761: (void) kd_mouse_read();
762:
763: kd_mouse_write(0xea); /* set stream mode */
764: if (kd_mouse_read() != 0xfa) {
765: splx(s);
766: return; /* need ACK */
767: }
768:
769: kd_mouse_write(0xf4); /* enable */
770: if (kd_mouse_read() != 0xfa) {
771: splx(s);
772: return; /* need ACK */
773: }
774:
775: mouse_char_cmd = FALSE; /* now we get mouse packets */
776:
777: splx(s);
778: }
779:
780: ibm_ps2_mouse_close(dev)
781: {
782: spl_t s = spltty();
783:
784: mouse_char_cmd = TRUE; /* responses are to commands */
785:
786: kd_mouse_write(0xff); /* reset mouse */
787: if (kd_mouse_read() == 0xfa) {
788: /* got ACK: discard 2-char mouse ID */
789: (void) kd_mouse_read();
790: (void) kd_mouse_read();
791: }
792:
793: kd_sendcmd(0xa7); /* disable mouse in kbd */
794: kd_cmdreg_write(0x65); /* disallow mouse interrupts */
795: /* magic number for ibm? */
796:
797: splx(s);
798: }
799:
800: /*
801: * 3 byte ibm ps2 format used
802: *
803: * 7 6 5 4 3 2 1 0
804: * YO XO YS XS 1 M R L
805: * X7 X6 X5 X4 X3 X3 X1 X0
806: * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
807: *
808: */
809: mouse_packet_ibm_ps2_mouse(mousebuf)
810: u_char mousebuf[MOUSEBUFSIZE];
811: {
812: u_char buttons, buttonchanges;
813: struct mouse_motion moved;
814:
815: buttons = mousebuf[0] & 0x7; /* get current state of buttons */
816: buttonchanges = buttons ^ lastbuttons;
817: moved.mm_deltaX = ((mousebuf[0]&0x10) ? 0xffffff00 : 0 ) | (u_char)mousebuf[1];
818: moved.mm_deltaY = ((mousebuf[0]&0x20) ? 0xffffff00 : 0 ) | (u_char)mousebuf[2];
819: if (mouse_packets) {
820: printf("(%x:%x:%x)", mousebuf[0], mousebuf[1], mousebuf[2]);
821: return;
822: }
823:
824: if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
825: mouse_moved(moved);
826:
827: if (buttonchanges != 0) {
828: lastbuttons = buttons;
829: if (buttonchanges & 1)
830: mouse_button(MOUSE_LEFT, !(buttons & 1));
831: if (buttonchanges & 2)
832: mouse_button(MOUSE_RIGHT, !((buttons & 2) >> 1));
833: if (buttonchanges & 4)
834: mouse_button(MOUSE_MIDDLE, !((buttons & 4) >> 2));
835: }
836: }
837:
838: /*
839: * Enqueue a mouse-motion event. Called at SPLKD.
840: */
841: mouse_moved(where)
842: struct mouse_motion where;
843: {
844: kd_event ev;
845:
846: ev.type = MOUSE_MOTION;
847: ev.time = time;
848: ev.value.mmotion = where;
849: mouse_enqueue(&ev);
850: }
851:
852:
853: /*
854: * Enqueue an event for mouse button press or release. Called at SPLKD.
855: */
856: mouse_button(which, direction)
857: kev_type which;
858: u_char direction;
859: {
860: kd_event ev;
861:
862: ev.type = which;
863: ev.time = time;
864: ev.value.up = (direction == MOUSE_UP) ? TRUE : FALSE;
865: mouse_enqueue(&ev);
866: }
867:
868:
869: /*
870: * mouse_enqueue - enqueue an event and wake up selecting processes, if
871: * any. Called at SPLKD.
872: */
873:
874: void
875: mouse_enqueue(ev)
876: kd_event *ev;
877: {
878: if (kdq_full(&mouse_queue))
879: printf("mouse: queue full\n");
880: else
881: kdq_put(&mouse_queue, ev);
882:
883: #ifdef MACH_KERNEL
884: {
885: register io_req_t ior;
886: while ((ior = (io_req_t)dequeue_head(&mouse_read_queue)) != 0)
887: iodone(ior);
888: }
889: #else MACH_KERNEL
890: if (mouse_sel) {
891: selwakeup(mouse_sel, mouseflag & MOUSE_COLL);
892: mouse_sel = 0;
893: mouseflag &= ~MOUSE_COLL;
894: }
895: if (mouseflag & MOUSE_ASYNC)
896: gsignal(mousepgrp, SIGIO);
897: wakeup((caddr_t)&mouse_queue);
898: #endif MACH_KERNEL
899: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.