FreeBSD/Linux Kernel Cross Reference
sys/i386at/kd_mouse.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992,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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: kd_mouse.c,v $
29 * Revision 2.17 93/11/17 16:51:33 dbg
30 * Use sys_clock instead of 'time'. Remove non-MACH_KERNEL code.
31 * ANSI-fy.
32 * [93/06/10 dbg]
33 *
34 * Revision 2.16 93/08/10 15:57:52 mrt
35 * Make protocol 5 (-- minor [40-47] ) be Microsoft mouse
36 * but 7 bits. If this works universally, change protocol 1.
37 * [93/08/03 rvb]
38 * Support Logitech TrackMan mouse (V [or M+]) protocol as
39 * protocol 4 -- minor [32-39]
40 *
41 * Revision 2.15 93/05/11 13:58:56 rvb
42 * Typo
43 *
44 * Revision 2.14 93/05/10 21:19:45 rvb
45 * Lint.
46 * [93/05/08 11:22:15 af]
47 *
48 * Revision 2.13 93/05/10 17:43:39 rvb
49 * Allow for mouse speed to be patchable
50 *
51 * Revision 2.12 93/01/24 13:18:05 danner
52 * Added 3 button ps2 mouse from Jim Reese.
53 * [93/01/19 13:15:08 rvb]
54 *
55 * Revision 2.11 93/01/14 17:31:28 danner
56 * Proper spl typing.
57 * [92/11/30 af]
58 *
59 * Revision 2.10 92/07/09 22:54:39 rvb
60 * Fix microsoft 2 button mouse emulation to ignore two buttons down
61 * simultaneously and let X11R5 handle it.
62 * [92/07/06 rvb]
63 *
64 * Revision 2.9 92/02/19 16:30:17 elf
65 * On ps2_mouse_close, wait a bit and then drain console. For
66 * T2200 and sometime the IBM axion bus extender, data will show
67 * up after a while (a 0) w/o interrupt and your kbd would hang.
68 * [92/01/30 rvb]
69 *
70 * Allow for only "keyboard mouse". Does not use serial line.
71 * [92/01/25 rvb]
72 *
73 * Revision 2.8 91/10/07 17:26:02 af
74 * Add support for ibm ps2 "keyboard" mouse. Try to be general
75 * about it to support other "keyboard mice", but we don't have
76 * any.
77 * [91/09/25 rvb]
78 * Add support for MicroSoft 2 button Mouse from 2.5
79 * [91/09/04 rvb]
80 *
81 * Revision 2.7 91/08/24 11:58:51 af
82 * New MI autoconf.
83 * [91/08/02 02:49:38 af]
84 *
85 * Revision 2.6 91/05/14 16:27:26 mrt
86 * Correcting copyright
87 *
88 * Revision 2.5 91/02/05 17:19:17 mrt
89 * Changed to new Mach copyright
90 * [91/02/01 17:45:43 mrt]
91 *
92 * Revision 2.4 91/01/08 17:33:25 rpd
93 * Trim $ Header
94 * [90/11/27 11:44:31 rvb]
95 *
96 * Revision 2.3 90/11/26 14:50:33 rvb
97 * jsb beat me to XMK34, sigh ...
98 * [90/11/26 rvb]
99 * Synched 2.5 & 3.0 at I386q (r1.5.1.5) & XMK35 (r2.3)
100 * [90/11/15 rvb]
101 *
102 * Revision 1.5.1.4 90/07/10 11:45:04 rvb
103 * Allow mouse minor to select the serial line the mouse is on.
104 * [90/06/15 rvb]
105 *
106 * Revision 2.2 90/05/21 13:27:25 dbg
107 * Convert for pure kernel.
108 * [90/04/24 dbg]
109 *
110 * Revision 1.5.1.3 90/02/28 15:50:25 rvb
111 * Fix numerous typo's in Olivetti disclaimer.
112 * [90/02/28 rvb]
113 *
114 * Revision 1.5.1.2 90/01/08 13:30:55 rvb
115 * Add Olivetti copyright.
116 * [90/01/08 rvb]
117 *
118 * Revision 1.5.1.1 89/10/22 11:34:32 rvb
119 * Received from Intel October 5, 1989.
120 * [89/10/13 rvb]
121 *
122 * Revision 1.5 89/07/17 10:41:24 rvb
123 * Olivetti Changes to X79 upto 5/9/89:
124 * [89/07/11 rvb]
125 *
126 * Revision 1.4.1.1 89/04/27 12:21:17 kupfer
127 * Merge X79 with our latest and greatest.
128 *
129 * Revision 1.2.1.1 89/04/27 11:54:40 kupfer
130 * X79 from CMU.
131 *
132 * Revision 1.4 89/03/09 20:06:46 rpd
133 * More cleanup.
134 *
135 * Revision 1.3 89/02/26 12:42:38 gm0w
136 * Changes for cleanup.
137 *
138 */
139
140 /* **********************************************************************
141 File: kd_mouse.c
142 Description: mouse driver as part of keyboard/display driver
143
144 $ Header: $
145
146 Copyright Ing. C. Olivetti & C. S.p.A. 1989.
147 All rights reserved.
148 ********************************************************************** */
149 /*
150 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
151 Cupertino, California.
152
153 All Rights Reserved
154
155 Permission to use, copy, modify, and distribute this software and
156 its documentation for any purpose and without fee is hereby
157 granted, provided that the above copyright notice appears in all
158 copies and that both the copyright notice and this permission notice
159 appear in supporting documentation, and that the name of Olivetti
160 not be used in advertising or publicity pertaining to distribution
161 of the software without specific, written prior permission.
162
163 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
164 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
165 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
166 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
167 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
168 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
169 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
170 */
171
172 /*
173 * Hacked up support for serial mouse connected to COM1, using Mouse
174 * Systems 5-byte protocol at 1200 baud. This should work for
175 * Mouse Systems, SummaMouse, and Logitek C7 mice.
176 *
177 * The interface provided by /dev/mouse is a series of events as
178 * described in i386at/kd.h.
179 */
180
181 #include <mach/boolean.h>
182 #include <kern/clock.h>
183 #include <kern/kern_io.h>
184 #include <sys/types.h>
185 #include <device/ds_routines.h>
186 #include <device/errno.h>
187 #include <device/io_req.h>
188 #include <i386/ipl.h>
189 #include <i386/pio.h>
190 #include <chips/busses.h>
191 #include <i386at/kd.h>
192 #include <i386at/kd_queue.h>
193 #include <i386at/i8250.h>
194
195 static int (*oldvect)(); /* old interrupt vector */
196 static int oldunit;
197 static spl_t oldspl;
198 extern struct bus_device *cominfo[];
199
200 kd_event_queue mouse_queue; /* queue of mouse events */
201 boolean_t mouse_in_use = FALSE;
202 queue_head_t mouse_read_queue = { &mouse_read_queue, &mouse_read_queue };
203
204
205 /*
206 * The state of the 3 buttons is encoded in the low-order 3 bits (both
207 * here and in other variables in the driver).
208 */
209 u_char lastbuttons; /* previous state of mouse buttons */
210 #define MOUSE_UP 1
211 #define MOUSE_DOWN 0
212 #define MOUSE_ALL_UP 0x7
213
214 void mouseintr(int unit);
215 void mouse_enqueue();
216 int mouse_baud = BCNT1200;
217
218 /*
219 * init_mouse_hw - initialize the serial port.
220 */
221 void init_mouse_hw(
222 int unit,
223 int mode)
224 {
225 vm_offset_t base_addr = cominfo[unit]->address;
226
227 outb(base_addr + RIE, 0);
228 outb(base_addr + RLC, LCDLAB);
229 outb(base_addr + RDLSB, mouse_baud & 0xff);
230 outb(base_addr + RDMSB, (mouse_baud >> 8) & 0xff);
231 outb(base_addr + RLC, mode);
232 outb(base_addr + RMC, MCDTR | MCRTS | MCOUT2);
233 outb(base_addr + RIE, IERD | IELS);
234 }
235
236
237 /*
238 * mouseopen - Verify that the request is read-only, initialize,
239 * and remember process group leader.
240 */
241 /*
242 * Low 3 bits of minor are the com port #.
243 * The high 5 bits of minor are the mouse type
244 */
245 #define MOUSE_SYSTEM_MOUSE 0
246 #define MICROSOFT_MOUSE 1
247 #define IBM_MOUSE 2
248 #define NO_MOUSE 3
249 #define LOGITECH_TRACKMAN 4
250 #define MICROSOFT_MOUSE7 5
251 static int mouse_type;
252 static int mousebufsize;
253 int track_man[10];
254
255 void serial_mouse_open(int dev); /* forward */
256 void kd_mouse_open(int dev, int mouse_pic); /* forward */
257 void ibm_ps2_mouse_open(int dev); /* forward */
258
259 /*ARGSUSED*/
260 io_return_t
261 mouseopen(
262 int dev,
263 int flags)
264 {
265 if (mouse_in_use)
266 return EBUSY;
267 mouse_in_use = TRUE; /* locking? */
268 kdq_reset(&mouse_queue);
269 lastbuttons = MOUSE_ALL_UP;
270
271 switch (mouse_type = ((dev & 0xf8) >> 3)) {
272 case MICROSOFT_MOUSE7:
273 mousebufsize = 3;
274 serial_mouse_open(dev);
275 init_mouse_hw(dev&7, LC7);
276 case MICROSOFT_MOUSE:
277 mousebufsize = 3;
278 serial_mouse_open(dev);
279 init_mouse_hw(dev&7, LC8);
280 break;
281 case MOUSE_SYSTEM_MOUSE:
282 mousebufsize = 5;
283 serial_mouse_open(dev);
284 init_mouse_hw(dev&7, LC8);
285 break;
286 case LOGITECH_TRACKMAN:
287 mousebufsize = 3;
288 serial_mouse_open(dev);
289 init_mouse_hw(dev&7, LC7);
290 track_man[0] = comgetc(dev&7);
291 track_man[1] = comgetc(dev&7);
292 if (track_man[0] != 0x4d &&
293 track_man[1] != 0x33) {
294 printf("LOGITECH_TRACKMAN: NOT M3");
295 }
296 break;
297 case IBM_MOUSE:
298 mousebufsize = 3;
299 kd_mouse_open(dev, 12);
300 ibm_ps2_mouse_open(dev);
301 break;
302 case NO_MOUSE:
303 break;
304 }
305 return D_SUCCESS;
306 }
307
308 void serial_mouse_open(int dev)
309 {
310 int unit = dev & 0x7;
311 int mouse_pic = cominfo[unit]->sysdep1;
312
313 spl_t s = splhigh(); /* disable interrupts */
314
315 oldvect = ivect[mouse_pic];
316 ivect[mouse_pic] = mouseintr;
317
318 oldunit = iunit[mouse_pic];
319 iunit[mouse_pic] = unit;
320
321 /* XXX other arrays to init? */
322 splx(s); /* XXX - should come after init? */
323 }
324
325 int mouse_packets = 0;
326 void kd_mouse_open(int dev, int mouse_pic)
327 {
328 spl_t s = splhi(); /* disable interrupts */
329 extern int kdintr();
330
331 oldvect = ivect[mouse_pic];
332 ivect[mouse_pic] = kdintr;
333 oldspl = intpri[mouse_pic];
334 intpri[mouse_pic] = SPL6;
335 form_pic_mask();
336 splx(s);
337 }
338
339 /*
340 * mouseclose - Disable interrupts on the serial port, reset driver flags,
341 * and restore the serial port interrupt vector.
342 */
343 void serial_mouse_close(int dev); /* forward */
344 void kd_mouse_close(int dev, int mouse_pic); /* forward */
345 void ibm_ps2_mouse_close(int dev); /* forward */
346
347 io_return_t
348 mouseclose(int dev, int flags)
349 {
350 switch (mouse_type) {
351 case MICROSOFT_MOUSE:
352 case MICROSOFT_MOUSE7:
353 case MOUSE_SYSTEM_MOUSE:
354 case LOGITECH_TRACKMAN:
355 serial_mouse_close(dev);
356 break;
357 case IBM_MOUSE:
358 ibm_ps2_mouse_close(dev);
359 kd_mouse_close(dev, 12);
360 {int i = 20000; for (;i--;); }
361 kd_mouse_drain();
362 break;
363 case NO_MOUSE:
364 break;
365 }
366
367 kdq_reset(&mouse_queue); /* paranoia */
368 mouse_in_use = FALSE;
369
370 return D_SUCCESS;
371 }
372
373 /*ARGSUSED*/
374 void serial_mouse_close(
375 int dev)
376 {
377 spl_t o_pri = splhigh(); /* mutex with open() */
378 int unit = dev & 0x7;
379 int mouse_pic = cominfo[unit]->sysdep1;
380 vm_offset_t base_addr = cominfo[unit]->address;
381
382 assert(ivect[mouse_pic] == mouseintr);
383 outb(base_addr + RIE, 0); /* disable serial port */
384 outb(base_addr + RMC, 0); /* no rts */
385 ivect[mouse_pic] = oldvect;
386 iunit[mouse_pic] = oldunit;
387
388 splx(o_pri);
389 }
390
391 void kd_mouse_close(int dev, int mouse_pic)
392 {
393 spl_t s = splhigh();
394
395 ivect[mouse_pic] = oldvect;
396 intpri[mouse_pic] = oldspl;
397 form_pic_mask();
398 splx(s);
399 }
400
401
402 /*
403 * mouseread - dequeue and return any queued events.
404 */
405 boolean_t mouse_read_done(io_req_t); /* forward */
406
407 io_return_t
408 mouseread(
409 int dev,
410 register io_req_t ior)
411 {
412 register int err, count;
413 register spl_t s;
414
415 err = device_read_alloc(ior, (vm_size_t)ior->io_count);
416 if (err != KERN_SUCCESS)
417 return err;
418
419 s = SPLKD();
420 if (kdq_empty(&mouse_queue)) {
421 if (ior->io_mode & D_NOWAIT) {
422 splx(s);
423 return D_WOULD_BLOCK;
424 }
425 ior->io_done = mouse_read_done;
426 enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
427 splx(s);
428 return D_IO_QUEUED;
429 }
430 count = 0;
431 while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
432 register kd_event *ev;
433
434 ev = kdq_get(&mouse_queue);
435 *(kd_event *)(&ior->io_data[count]) = *ev;
436 count += sizeof(kd_event);
437 }
438 splx(s);
439 ior->io_residual = ior->io_count - count;
440 return D_SUCCESS;
441 }
442
443 boolean_t mouse_read_done(
444 register io_req_t ior)
445 {
446 register int count;
447 register spl_t s;
448
449 s = SPLKD();
450 if (kdq_empty(&mouse_queue)) {
451 ior->io_done = mouse_read_done;
452 enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
453 splx(s);
454 return FALSE;
455 }
456
457 count = 0;
458 while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
459 register kd_event *ev;
460
461 ev = kdq_get(&mouse_queue);
462 *(kd_event *)(&ior->io_data[count]) = *ev;
463 count += sizeof(kd_event);
464 }
465 splx(s);
466
467 ior->io_residual = ior->io_count - count;
468 ds_read_done(ior);
469
470 return TRUE;
471 }
472
473
474
475 /*
476 * mouseintr - Get a byte and pass it up for handling. Called at SPLKD.
477 */
478 void mouse_handle_byte(unsigned char ch); /* forward */
479
480 void mouseintr(int unit)
481 {
482 vm_offset_t base_addr = cominfo[unit]->address;
483 unsigned char id, ls;
484
485 /* get reason for interrupt and line status */
486 id = inb(base_addr + RID);
487 ls = inb(base_addr + RLS);
488
489 /* handle status changes */
490 if (id == IDLS) {
491 if (ls & LSDR) {
492 inb(base_addr + RDAT); /* flush bad character */
493 }
494 return; /* ignore status change */
495 }
496
497 if (id & IDRD) {
498 mouse_handle_byte((u_char)(inb(base_addr + RDAT) & 0xff));
499 }
500 }
501
502
503 /*
504 * handle_byte - Accumulate bytes until we have an entire packet.
505 * If the mouse has moved or any of the buttons have changed state (up
506 * or down), enqueue the corresponding events.
507 * Called at SPLKD.
508 * XXX - magic numbers.
509 */
510 int show_mouse_byte = 0;
511 /*
512 X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0
513 X down; middle down; X up; middle up 50 0 0; 50 0 0 22; 40 0 0 22; 40 0 0 2
514 *
515 * The trick here is that all the while the middle button is down you get 4 byte
516 * packets with the last byte 0x22. When the middle button goes up you get a
517 * last packet with 0x02.
518 */
519 int lastgitech = 0x40; /* figure whether the first 3 bytes imply */
520 /* its time to expect a fourth */
521 int fourthgitech = 0; /* look for the 4th byte; we must process it */
522 int middlegitech = 0; /* what should the middle button be */
523
524 #define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */
525 static u_char mousebuf[MOUSEBUFSIZE]; /* 5-byte packet from mouse */
526 static short mbindex = 0; /* index into mousebuf */
527
528 void mouse_packet_mouse_system_mouse(u_char mousebuf[MOUSEBUFSIZE]);
529 void mouse_packet_microsoft_mouse(u_char mousebuf[MOUSEBUFSIZE]);
530 void mouse_packet_ibm_ps2_mouse(u_char mousebuf[MOUSEBUFSIZE]);
531
532 void mouse_handle_byte(
533 unsigned char ch)
534 {
535 if (show_mouse_byte) {
536 printf("%x(%c) ", ch, ch);
537 }
538 if (mbindex == 0) {
539 switch (mouse_type) {
540 case MICROSOFT_MOUSE7:
541 if ((ch & 0x40) != 0x40)
542 return;
543 break;
544 case MICROSOFT_MOUSE:
545 if ((ch & 0xc0) != 0xc0)
546 return;
547 break;
548 case MOUSE_SYSTEM_MOUSE:
549 if ((ch & 0xf8) != 0x80)
550 return;
551 break;
552 case LOGITECH_TRACKMAN:
553 if (fourthgitech == 1) {
554 fourthgitech = 0;
555 if (ch & 0xf0)
556 middlegitech = 0x4;
557 else
558 middlegitech = 0x0;
559 mouse_packet_microsoft_mouse(mousebuf);
560 return;
561 } else if ((ch & 0xc0) != 0x40)
562 return;
563 break;
564 case IBM_MOUSE:
565 break;
566 }
567 }
568
569 mousebuf[mbindex++] = ch;
570 if (mbindex < mousebufsize)
571 return;
572
573 /* got a packet */
574 mbindex = 0;
575
576 switch (mouse_type) {
577 case MICROSOFT_MOUSE7:
578 case MICROSOFT_MOUSE:
579 mouse_packet_microsoft_mouse(mousebuf);
580 break;
581 case MOUSE_SYSTEM_MOUSE:
582 mouse_packet_mouse_system_mouse(mousebuf);
583 break;
584 case LOGITECH_TRACKMAN:
585 if ( mousebuf[1] || mousebuf[2] ||
586 mousebuf[0] != lastgitech) {
587 mouse_packet_microsoft_mouse(mousebuf);
588 lastgitech = mousebuf[0] & 0xf0;
589 } else {
590 fourthgitech = 1;
591 }
592 break;
593 case IBM_MOUSE:
594 mouse_packet_ibm_ps2_mouse(mousebuf);
595 break;
596 }
597 }
598
599 void mouse_moved(struct mouse_motion where); /* forward */
600 void mouse_button(kev_type which, u_char direction); /* forward */
601
602 void mouse_packet_mouse_system_mouse(
603 u_char mousebuf[MOUSEBUFSIZE])
604 {
605 u_char buttons, buttonchanges;
606 struct mouse_motion moved;
607
608 buttons = mousebuf[0] & 0x7; /* get current state of buttons */
609 buttonchanges = buttons ^ lastbuttons;
610 moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3];
611 moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4];
612
613 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
614 mouse_moved(moved);
615
616 if (buttonchanges != 0) {
617 lastbuttons = buttons;
618 if (buttonchanges & 1)
619 mouse_button(MOUSE_RIGHT, buttons & 1);
620 if (buttonchanges & 2)
621 mouse_button(MOUSE_MIDDLE, (buttons & 2) >> 1);
622 if (buttonchanges & 4)
623 mouse_button(MOUSE_LEFT, (buttons & 4) >> 2);
624 }
625 }
626
627 /* same as above for microsoft mouse */
628 /*
629 * 3 byte microsoft format used
630 *
631 * 7 6 5 4 3 2 1 0
632 * 1 1 L R Y7 Y6 X7 X6
633 * 1 0 X5 X4 X3 X3 X1 X0
634 * 1 0 Y5 Y4 Y3 Y2 Y1 Y0
635 *
636 */
637 void mouse_packet_microsoft_mouse(
638 u_char mousebuf[MOUSEBUFSIZE])
639 {
640 u_char buttons, buttonchanges;
641 struct mouse_motion moved;
642
643 buttons = ((mousebuf[0] & 0x30) >> 4);
644 buttons |= middlegitech;
645 /* get current state of buttons */
646 #ifdef gross_hack
647 if (buttons == 0x03) /* both buttons down */
648 buttons = 0x04;
649 #endif /* gross_hack */
650 buttons = (~buttons) & 0x07; /* convert to not pressed */
651
652 buttonchanges = buttons ^ lastbuttons;
653 moved.mm_deltaX = ((mousebuf[0] & 0x03) << 6) | (mousebuf[1] & 0x3F);
654 moved.mm_deltaY = ((mousebuf[0] & 0x0c) << 4) | (mousebuf[2] & 0x3F);
655 if (moved.mm_deltaX & 0x80) /* negative, in fact */
656 moved.mm_deltaX = moved.mm_deltaX - 0x100;
657 if (moved.mm_deltaY & 0x80) /* negative, in fact */
658 moved.mm_deltaY = moved.mm_deltaY - 0x100;
659 /* and finally the Y orientation is different for the microsoft mouse */
660 moved.mm_deltaY = -moved.mm_deltaY;
661
662 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
663 mouse_moved(moved);
664
665 if (buttonchanges != 0) {
666 lastbuttons = buttons;
667 if (buttonchanges & 1)
668 mouse_button(MOUSE_RIGHT, (buttons & 1) ?
669 MOUSE_UP : MOUSE_DOWN);
670 if (buttonchanges & 2)
671 mouse_button(MOUSE_LEFT, (buttons & 2) ?
672 MOUSE_UP : MOUSE_DOWN);
673 if (buttonchanges & 4)
674 mouse_button(MOUSE_MIDDLE, (buttons & 4) ?
675 MOUSE_UP : MOUSE_DOWN);
676 }
677 }
678
679 void ibm_ps2_mouse_open(int dev)
680 {
681 char buf[4] = {0,0,0,0};
682
683 lastbuttons = 0;
684 mbindex = 0;
685
686 kd_sendcmd(0xa8); /* enable mouse in kbd */
687
688 kd_cmdreg_write(0x47); /* allow mouse interrupts */
689 /* magic number for ibm? */
690
691 if (kd_mouse_write(0xff) != 0xfa) /* reset mouse */
692 return;
693
694 kd_mouse_read(2, buf);
695
696 kd_mouse_write(0xea); /* stream mode */
697 kd_mouse_write(0xf4); /* enable */
698
699 }
700
701 void ibm_ps2_mouse_close(int dev)
702 {
703 char buf[4] = {0,0,0,0};
704
705 if (kd_mouse_write(0xff) == 0xfa) /* reset mouse */
706 kd_mouse_read(2, buf);
707
708 kd_sendcmd(0xa7); /* disable mouse in kbd */
709 kd_cmdreg_write(0x65); /* disallow mouse interrupts */
710 /* magic number for ibm? */
711 }
712
713 /*
714 * 3 byte ibm ps2 format used
715 *
716 * 7 6 5 4 3 2 1 0
717 * YO XO YS XS 1 M R L
718 * X7 X6 X5 X4 X3 X3 X1 X0
719 * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
720 *
721 */
722 void mouse_packet_ibm_ps2_mouse(
723 u_char mousebuf[MOUSEBUFSIZE])
724 {
725 u_char buttons, buttonchanges;
726 struct mouse_motion moved;
727
728 buttons = mousebuf[0] & 0x7; /* get current state of buttons */
729 buttonchanges = buttons ^ lastbuttons;
730 moved.mm_deltaX = ((mousebuf[0]&0x10) ? 0xffffff00 : 0 ) | (u_char)mousebuf[1];
731 moved.mm_deltaY = ((mousebuf[0]&0x20) ? 0xffffff00 : 0 ) | (u_char)mousebuf[2];
732 if (mouse_packets) {
733 printf("(%x:%x:%x)", mousebuf[0], mousebuf[1], mousebuf[2]);
734 return;
735 }
736
737 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
738 mouse_moved(moved);
739
740 if (buttonchanges != 0) {
741 lastbuttons = buttons;
742 if (buttonchanges & 1)
743 mouse_button(MOUSE_LEFT, !(buttons & 1));
744 if (buttonchanges & 2)
745 mouse_button(MOUSE_RIGHT, !((buttons & 2) >> 1));
746 if (buttonchanges & 4)
747 mouse_button(MOUSE_MIDDLE, !((buttons & 4) >> 2));
748 }
749 }
750
751 void mouse_enqueue(kd_event *ev); /* forward */
752
753 /*
754 * Enqueue a mouse-motion event. Called at SPLKD.
755 */
756 void mouse_moved(
757 struct mouse_motion where)
758 {
759 kd_event ev;
760 time_spec_t cur_time;
761
762 clock_read(cur_time, sys_clock);
763
764 ev.type = MOUSE_MOTION;
765 ev.time.seconds = cur_time.seconds;
766 ev.time.microseconds = cur_time.nanoseconds / 1000;
767 ev.value.mmotion = where;
768 mouse_enqueue(&ev);
769 }
770
771
772 /*
773 * Enqueue an event for mouse button press or release. Called at SPLKD.
774 */
775 void mouse_button(
776 kev_type which,
777 u_char direction)
778 {
779 kd_event ev;
780 time_spec_t cur_time;
781
782 clock_read(cur_time, sys_clock);
783
784 ev.type = which;
785 ev.time.seconds = cur_time.seconds;
786 ev.time.microseconds = cur_time.nanoseconds / 1000;
787 ev.value.up = (direction == MOUSE_UP) ? TRUE : FALSE;
788 mouse_enqueue(&ev);
789 }
790
791
792 /*
793 * mouse_enqueue - enqueue an event and wake up selecting processes, if
794 * any. Called at SPLKD.
795 */
796
797 void
798 mouse_enqueue(
799 kd_event *ev)
800 {
801 if (kdq_full(&mouse_queue))
802 printf("mouse: queue full\n");
803 else
804 kdq_put(&mouse_queue, ev);
805
806 {
807 register io_req_t ior;
808 while ((ior = (io_req_t)dequeue_head(&mouse_read_queue)) != 0)
809 iodone(ior);
810 }
811 }
Cache object: 6dca7cd89497aa604d3722651f387185
|