adb.c revision 1.1 1 /* $NetBSD: adb.c,v 1.1 1998/05/15 10:15:47 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1994 Bradley A. Grantham
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bradley A. Grantham.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/device.h>
35 #include <sys/fcntl.h>
36 #include <sys/poll.h>
37 #include <sys/select.h>
38 #include <sys/proc.h>
39 #include <sys/signalvar.h>
40 #include <sys/systm.h>
41
42 #include <machine/autoconf.h>
43 #include <machine/keyboard.h>
44
45 #include <macppc/dev/adbvar.h>
46 #include <macppc/dev/viareg.h>
47
48 #define spladb splhigh /* XXX */
49
50 /*
51 * Function declarations.
52 */
53 static int adbmatch __P((struct device *, struct cfdata *, void *));
54 static void adbattach __P((struct device *, struct device *, void *));
55
56 /*
57 * Global variables.
58 */
59 int adb_polling = 0; /* Are we polling? (Debugger mode) */
60 int adb_initted = 0; /* adb_init() has completed successfully */
61 #ifdef ADB_DEBUG
62 int adb_debug = 0; /* Output debugging messages */
63 #endif /* ADB_DEBUG */
64
65 volatile u_char *Via1Base;
66
67 /*
68 * Local variables.
69 */
70
71 /* External keyboard translation matrix */
72 extern unsigned char keyboard[128][3];
73
74 /* Event queue definitions */
75 #if !defined(ADB_MAX_EVENTS)
76 #define ADB_MAX_EVENTS 200 /* Maximum events to be kept in queue */
77 /* maybe should be higher for slower macs? */
78 #endif /* !defined(ADB_MAX_EVENTS) */
79 static adb_event_t adb_evq[ADB_MAX_EVENTS]; /* ADB event queue */
80 static int adb_evq_tail = 0; /* event queue tail */
81 static int adb_evq_len = 0; /* event queue length */
82
83 /* ADB device state information */
84 static int adb_isopen = 0; /* Are we queuing events for adb_read? */
85 static struct selinfo adb_selinfo; /* select() info */
86 static struct proc *adb_ioproc = NULL; /* process to wakeup */
87
88 /* Key repeat parameters */
89 static int adb_rptdelay = 20; /* ticks before auto-repeat */
90 static int adb_rptinterval = 6; /* ticks between auto-repeat */
91 static int adb_repeating = -1; /* key that is auto-repeating */
92 static adb_event_t adb_rptevent;/* event to auto-repeat */
93
94 /* Mouse button state */
95 static int adb_ms_buttons = 0;
96
97 /* Driver definition. -- This should probably be a bus... */
98 struct cfattach adb_ca = {
99 sizeof(struct adb_softc), adbmatch, adbattach
100 };
101
102 static int
103 adbmatch(parent, cf, aux)
104 struct device *parent;
105 struct cfdata *cf;
106 void *aux;
107 {
108 struct confargs *ca = aux;
109
110 if (strcmp(ca->ca_name, "via-cuda") != 0)
111 return 0;
112
113 if (ca->ca_nreg < 8)
114 return 0;
115
116 if (ca->ca_nintr < 4)
117 return 0;
118
119 return 1;
120 }
121
122 static void
123 adbattach(parent, self, aux)
124 struct device *parent, *self;
125 void *aux;
126 {
127 struct adb_softc *sc = (struct adb_softc *)self;
128 struct confargs *ca = aux;
129 u_long time = -1;
130 extern adb_intr();
131
132 ca->ca_reg[0] += ca->ca_baseaddr;
133
134 sc->sc_regbase = mapiodev(ca->ca_reg[0], ca->ca_reg[1]);
135 Via1Base = sc->sc_regbase;
136
137 printf(" irq %d\n", ca->ca_intr[0]);
138
139 adb_polling = 1;
140 adb_init();
141 kbd_init();
142 adb_polling = 0;
143
144 intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_HIGH, adb_intr, sc);
145 }
146
147 void
148 adb_enqevent(event)
149 adb_event_t *event;
150 {
151 int s;
152
153 s = spladb();
154
155 #ifdef DIAGNOSTIC
156 if (adb_evq_tail < 0 || adb_evq_tail >= ADB_MAX_EVENTS)
157 panic("adb: event queue tail is out of bounds");
158
159 if (adb_evq_len < 0 || adb_evq_len > ADB_MAX_EVENTS)
160 panic("adb: event queue len is out of bounds");
161 #endif
162
163 if (adb_evq_len == ADB_MAX_EVENTS) {
164 splx(s);
165 return; /* Oh, well... */
166 }
167 adb_evq[(adb_evq_len + adb_evq_tail) % ADB_MAX_EVENTS] =
168 *event;
169 adb_evq_len++;
170
171 selwakeup(&adb_selinfo);
172 if (adb_ioproc)
173 psignal(adb_ioproc, SIGIO);
174
175 splx(s);
176 }
177
178 void
179 adb_handoff(event)
180 adb_event_t *event;
181 {
182 if (adb_isopen && !adb_polling) {
183 adb_enqevent(event);
184 } else {
185 if (event->def_addr == 2)
186 ite_intr(event);
187 }
188 }
189
190
191 void
192 adb_autorepeat(keyp)
193 void *keyp;
194 {
195 int key = (int)keyp;
196
197 adb_rptevent.bytes[0] |= 0x80;
198 microtime(&adb_rptevent.timestamp);
199 adb_handoff(&adb_rptevent); /* do key up */
200
201 adb_rptevent.bytes[0] &= 0x7f;
202 microtime(&adb_rptevent.timestamp);
203 adb_handoff(&adb_rptevent); /* do key down */
204
205 if (adb_repeating == key) {
206 timeout(adb_autorepeat, keyp, adb_rptinterval);
207 }
208 }
209
210
211 void
212 adb_dokeyupdown(event)
213 adb_event_t *event;
214 {
215 int adb_key;
216
217 if (event->def_addr == 2) {
218 adb_key = event->u.k.key & 0x7f;
219 if (!(event->u.k.key & 0x80) &&
220 keyboard[event->u.k.key & 0x7f][0] != 0) {
221 /* ignore shift & control */
222 if (adb_repeating != -1) {
223 untimeout(adb_autorepeat,
224 (void *)adb_rptevent.u.k.key);
225 }
226 adb_rptevent = *event;
227 adb_repeating = adb_key;
228 timeout(adb_autorepeat,
229 (void *)adb_key, adb_rptdelay);
230 } else {
231 if (adb_repeating != -1) {
232 adb_repeating = -1;
233 untimeout(adb_autorepeat,
234 (void *)adb_rptevent.u.k.key);
235 }
236 adb_rptevent = *event;
237 }
238 }
239 adb_handoff(event);
240 }
241
242 void
243 adb_keymaybemouse(event)
244 adb_event_t *event;
245 {
246 static int optionkey_down = 0;
247 adb_event_t new_event;
248
249 if (event->u.k.key == ADBK_KEYDOWN(ADBK_OPTION)) {
250 optionkey_down = 1;
251 } else if (event->u.k.key == ADBK_KEYUP(ADBK_OPTION)) {
252 /* key up */
253 optionkey_down = 0;
254 if (adb_ms_buttons & 0xfe) {
255 adb_ms_buttons &= 1;
256 new_event.def_addr = ADBADDR_MS;
257 new_event.u.m.buttons = adb_ms_buttons;
258 new_event.u.m.dx = new_event.u.m.dy = 0;
259 microtime(&new_event.timestamp);
260 adb_dokeyupdown(&new_event);
261 }
262 } else if (optionkey_down) {
263 #ifdef ALTXBUTTONS
264 if (event->u.k.key == ADBK_KEYDOWN(ADBK_1)) {
265 adb_ms_buttons |= 1; /* left down */
266 new_event.def_addr = ADBADDR_MS;
267 new_event.u.m.buttons = adb_ms_buttons;
268 new_event.u.m.dx = new_event.u.m.dy = 0;
269 microtime(&new_event.timestamp);
270 adb_dokeyupdown(&new_event);
271 } else if (event->u.k.key == ADBK_KEYUP(ADBK_1)) {
272 adb_ms_buttons &= ~1; /* left up */
273 new_event.def_addr = ADBADDR_MS;
274 new_event.u.m.buttons = adb_ms_buttons;
275 new_event.u.m.dx = new_event.u.m.dy = 0;
276 microtime(&new_event.timestamp);
277 adb_dokeyupdown(&new_event);
278 } else
279 #endif
280 if (event->u.k.key == ADBK_KEYDOWN(ADBK_LEFT)
281 #ifdef ALTXBUTTONS
282 || event->u.k.key == ADBK_KEYDOWN(ADBK_2)
283 #endif
284 ) {
285 adb_ms_buttons |= 2; /* middle down */
286 new_event.def_addr = ADBADDR_MS;
287 new_event.u.m.buttons = adb_ms_buttons;
288 new_event.u.m.dx = new_event.u.m.dy = 0;
289 microtime(&new_event.timestamp);
290 adb_dokeyupdown(&new_event);
291 } else if (event->u.k.key == ADBK_KEYUP(ADBK_LEFT)
292 #ifdef ALTXBUTTONS
293 || event->u.k.key == ADBK_KEYUP(ADBK_2)
294 #endif
295 ) {
296 adb_ms_buttons &= ~2; /* middle up */
297 new_event.def_addr = ADBADDR_MS;
298 new_event.u.m.buttons = adb_ms_buttons;
299 new_event.u.m.dx = new_event.u.m.dy = 0;
300 microtime(&new_event.timestamp);
301 adb_dokeyupdown(&new_event);
302 } else if (event->u.k.key == ADBK_KEYDOWN(ADBK_RIGHT)
303 #ifdef ALTXBUTTONS
304 || event->u.k.key == ADBK_KEYDOWN(ADBK_3)
305 #endif
306 ) {
307 adb_ms_buttons |= 4; /* right down */
308 new_event.def_addr = ADBADDR_MS;
309 new_event.u.m.buttons = adb_ms_buttons;
310 new_event.u.m.dx = new_event.u.m.dy = 0;
311 microtime(&new_event.timestamp);
312 adb_dokeyupdown(&new_event);
313 } else if (event->u.k.key == ADBK_KEYUP(ADBK_RIGHT)
314 #ifdef ALTXBUTTONS
315 || event->u.k.key == ADBK_KEYUP(ADBK_3)
316 #endif
317 ) {
318 adb_ms_buttons &= ~4; /* right up */
319 new_event.def_addr = ADBADDR_MS;
320 new_event.u.m.buttons = adb_ms_buttons;
321 new_event.u.m.dx = new_event.u.m.dy = 0;
322 microtime(&new_event.timestamp);
323 adb_dokeyupdown(&new_event);
324 } else if (ADBK_MODIFIER(event->u.k.key)) {
325 /* ctrl, shift, cmd */
326 adb_dokeyupdown(event);
327 } else if (!(event->u.k.key & 0x80)) {
328 /* key down */
329 new_event = *event;
330
331 /* send option-down */
332 new_event.u.k.key = ADBK_KEYDOWN(ADBK_OPTION);
333 new_event.bytes[0] = new_event.u.k.key;
334 microtime(&new_event.timestamp);
335 adb_dokeyupdown(&new_event);
336
337 /* send key-down */
338 new_event.u.k.key = event->bytes[0];
339 new_event.bytes[0] = new_event.u.k.key;
340 microtime(&new_event.timestamp);
341 adb_dokeyupdown(&new_event);
342
343 /* send key-up */
344 new_event.u.k.key =
345 ADBK_KEYUP(ADBK_KEYVAL(event->bytes[0]));
346 microtime(&new_event.timestamp);
347 new_event.bytes[0] = new_event.u.k.key;
348 adb_dokeyupdown(&new_event);
349
350 /* send option-up */
351 new_event.u.k.key = ADBK_KEYUP(ADBK_OPTION);
352 new_event.bytes[0] = new_event.u.k.key;
353 microtime(&new_event.timestamp);
354 adb_dokeyupdown(&new_event);
355 } else {
356 /* option-keyup -- do nothing. */
357 }
358 } else {
359 adb_dokeyupdown(event);
360 }
361 }
362
363
364 void
365 adb_processevent(event)
366 adb_event_t *event;
367 {
368 adb_event_t new_event;
369 int i, button_bit, max_byte, mask, buttons;
370
371 new_event = *event;
372 buttons = 0;
373
374 switch (event->def_addr) {
375 case ADBADDR_KBD:
376 new_event.u.k.key = event->bytes[0];
377 new_event.bytes[1] = 0xff;
378 adb_keymaybemouse(&new_event);
379 if (event->bytes[1] != 0xff) {
380 new_event.u.k.key = event->bytes[1];
381 new_event.bytes[0] = event->bytes[1];
382 new_event.bytes[1] = 0xff;
383 adb_keymaybemouse(&new_event);
384 }
385 break;
386 case ADBADDR_MS:
387 /*
388 * This should handle both plain ol' Apple mice and mice
389 * that claim to support the Extended Apple Mouse Protocol.
390 */
391 max_byte = event->byte_count;
392 button_bit = 1;
393 switch (event->hand_id) {
394 case ADBMS_USPEED:
395 /* MicroSpeed mouse */
396 if (max_byte == 4)
397 buttons = (~event->bytes[2]) & 0xff;
398 else
399 buttons = (event->bytes[0] & 0x80) ? 0 : 1;
400 break;
401 case ADBMS_MSA3:
402 /* Mouse Systems A3 mouse */
403 if (max_byte == 3)
404 buttons = (~event->bytes[2]) & 0x07;
405 else
406 buttons = (event->bytes[0] & 0x80) ? 0 : 1;
407 break;
408 default:
409 /* Classic Mouse Protocol (up to 2 buttons) */
410 for (i = 0; i < 2; i++, button_bit <<= 1)
411 /* 0 when button down */
412 if (!(event->bytes[i] & 0x80))
413 buttons |= button_bit;
414 else
415 buttons &= ~button_bit;
416 /* Extended Protocol (up to 6 more buttons) */
417 for (mask = 0x80; i < max_byte;
418 i += (mask == 0x80), button_bit <<= 1) {
419 /* 0 when button down */
420 if (!(event->bytes[i] & mask))
421 buttons |= button_bit;
422 else
423 buttons &= ~button_bit;
424 mask = ((mask >> 4) & 0xf)
425 | ((mask & 0xf) << 4);
426 }
427 break;
428 }
429 new_event.u.m.buttons = adb_ms_buttons | buttons;
430 new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) -
431 ((event->bytes[1] & 0x40) ? 64 : 0);
432 new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) -
433 ((event->bytes[0] & 0x40) ? 64 : 0);
434 adb_dokeyupdown(&new_event);
435 break;
436 default: /* God only knows. */
437 adb_dokeyupdown(event);
438 }
439 }
440
441
442 int
443 adbopen(dev, flag, mode, p)
444 dev_t dev;
445 int flag, mode;
446 struct proc *p;
447 {
448 register int unit;
449 int error = 0;
450 int s;
451
452 unit = minor(dev);
453 if (unit != 0 || !adb_initted)
454 return (ENXIO);
455
456 s = spladb();
457 if (adb_isopen) {
458 splx(s);
459 return (EBUSY);
460 }
461 adb_evq_tail = 0;
462 adb_evq_len = 0;
463 adb_isopen = 1;
464 adb_ioproc = p;
465 splx(s);
466
467 return (error);
468 }
469
470
471 int
472 adbclose(dev, flag, mode, p)
473 dev_t dev;
474 int flag, mode;
475 struct proc *p;
476 {
477 int s = spladb();
478
479 adb_isopen = 0;
480 adb_ioproc = NULL;
481 splx(s);
482
483 return (0);
484 }
485
486
487 int
488 adbread(dev, uio, flag)
489 dev_t dev;
490 struct uio *uio;
491 int flag;
492 {
493 int s, error;
494 int willfit;
495 int total;
496 int firstmove;
497 int moremove;
498
499 if (uio->uio_resid < sizeof(adb_event_t))
500 return (EMSGSIZE); /* close enough. */
501
502 s = spladb();
503 if (adb_evq_len == 0) {
504 splx(s);
505 return (0);
506 }
507 willfit = howmany(uio->uio_resid, sizeof(adb_event_t));
508 total = (adb_evq_len < willfit) ? adb_evq_len : willfit;
509
510 firstmove = (adb_evq_tail + total > ADB_MAX_EVENTS)
511 ? (ADB_MAX_EVENTS - adb_evq_tail) : total;
512
513 error = uiomove((caddr_t) & adb_evq[adb_evq_tail],
514 firstmove * sizeof(adb_event_t), uio);
515 if (error) {
516 splx(s);
517 return (error);
518 }
519 moremove = total - firstmove;
520
521 if (moremove > 0) {
522 error = uiomove((caddr_t) & adb_evq[0],
523 moremove * sizeof(adb_event_t), uio);
524 if (error) {
525 splx(s);
526 return (error);
527 }
528 }
529 adb_evq_tail = (adb_evq_tail + total) % ADB_MAX_EVENTS;
530 adb_evq_len -= total;
531 splx(s);
532 return (0);
533 }
534
535
536 int
537 adbwrite(dev, uio, flag)
538 dev_t dev;
539 struct uio *uio;
540 int flag;
541 {
542 return 0;
543 }
544
545
546 int
547 adbioctl(dev, cmd, data, flag, p)
548 dev_t dev;
549 int cmd;
550 caddr_t data;
551 int flag;
552 struct proc *p;
553 {
554 switch (cmd) {
555 case ADBIOCDEVSINFO: {
556 adb_devinfo_t *di;
557 ADBDataBlock adbdata;
558 int totaldevs;
559 int adbaddr;
560 int i;
561
562 di = (void *)data;
563
564 /* Initialize to no devices */
565 for (i = 0; i < 16; i++)
566 di->dev[i].addr = -1;
567
568 totaldevs = CountADBs();
569 for (i = 1; i <= totaldevs; i++) {
570 adbaddr = GetIndADB(&adbdata, i);
571 di->dev[adbaddr].addr = adbaddr;
572 di->dev[adbaddr].default_addr = adbdata.origADBAddr;
573 di->dev[adbaddr].handler_id = adbdata.devType;
574 }
575
576 /* Must call ADB Manager to get devices now */
577 break;
578 }
579
580 case ADBIOCGETREPEAT:{
581 adb_rptinfo_t *ri;
582
583 ri = (void *)data;
584 ri->delay_ticks = adb_rptdelay;
585 ri->interval_ticks = adb_rptinterval;
586 break;
587 }
588
589 case ADBIOCSETREPEAT:{
590 adb_rptinfo_t *ri;
591
592 ri = (void *)data;
593 adb_rptdelay = ri->delay_ticks;
594 adb_rptinterval = ri->interval_ticks;
595 break;
596 }
597
598 case ADBIOCRESET:
599 adb_init();
600 break;
601
602 case ADBIOCLISTENCMD:{
603 adb_listencmd_t *lc;
604
605 lc = (void *)data;
606 }
607
608 default:
609 return (EINVAL);
610 }
611 return (0);
612 }
613
614
615 int
616 adbpoll(dev, events, p)
617 dev_t dev;
618 int events;
619 struct proc *p;
620 {
621 int s, revents;
622
623 revents = events & (POLLOUT | POLLWRNORM);
624
625 if ((events & (POLLIN | POLLRDNORM)) == 0)
626 return (revents);
627
628 s = spladb();
629 if (adb_evq_len > 0)
630 revents |= events & (POLLIN | POLLRDNORM);
631 else
632 selrecord(p, &adb_selinfo);
633 splx(s);
634
635 return (revents);
636 }
637