This source file includes following definitions.
- pckbd_set_xtscancode
- pckbd_is_console
- pckbdprobe
- pckbdattach
- pckbd_enable
- pckbd_decode
- pckbd_init
- pckbd_led_encode
- pckbd_led_decode
- pckbd_set_leds
- pckbd_input
- pckbd_ioctl
- pckbd_bell
- pckbd_hookup_bell
- pckbd_cnattach
- pckbd_cngetc
- pckbd_cnpollc
- pckbd_cnbell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/device.h>
81 #include <sys/malloc.h>
82 #include <sys/ioctl.h>
83
84 #include <machine/bus.h>
85
86 #ifndef __sparc64__
87 #include <dev/isa/isavar.h>
88 #endif
89
90 #include <dev/ic/pckbcvar.h>
91
92 #include <dev/pckbc/pckbdreg.h>
93 #include <dev/pckbc/pckbdvar.h>
94 #include <dev/pckbc/wskbdmap_mfii.h>
95
96 #include <dev/wscons/wsconsio.h>
97 #include <dev/wscons/wskbdvar.h>
98 #include <dev/wscons/wsksymdef.h>
99 #include <dev/wscons/wsksymvar.h>
100
101 #if defined(__i386__) || defined(__alpha__)
102 #include <sys/kernel.h>
103 #endif
104
105 struct pckbd_internal {
106 int t_isconsole;
107 pckbc_tag_t t_kbctag;
108 pckbc_slot_t t_kbcslot;
109
110 int t_lastchar;
111 int t_extended;
112 int t_extended1;
113
114 struct pckbd_softc *t_sc;
115 };
116
117 struct pckbd_softc {
118 struct device sc_dev;
119
120 struct pckbd_internal *id;
121 int sc_enabled;
122
123 int sc_ledstate;
124
125 struct device *sc_wskbddev;
126 #ifdef WSDISPLAY_COMPAT_RAWKBD
127 int rawkbd;
128 #endif
129 };
130
131 static int pckbd_is_console(pckbc_tag_t, pckbc_slot_t);
132
133 int pckbdprobe(struct device *, void *, void *);
134 void pckbdattach(struct device *, struct device *, void *);
135
136 struct cfattach pckbd_ca = {
137 sizeof(struct pckbd_softc), pckbdprobe, pckbdattach,
138 };
139
140 int pckbd_enable(void *, int);
141 void pckbd_set_leds(void *, int);
142 int pckbd_ioctl(void *, u_long, caddr_t, int, struct proc *);
143
144 const struct wskbd_accessops pckbd_accessops = {
145 pckbd_enable,
146 pckbd_set_leds,
147 pckbd_ioctl,
148 };
149
150 void pckbd_cngetc(void *, u_int *, int *);
151 void pckbd_cnpollc(void *, int);
152 void pckbd_cnbell(void *, u_int, u_int, u_int);
153
154 const struct wskbd_consops pckbd_consops = {
155 pckbd_cngetc,
156 pckbd_cnpollc,
157 pckbd_cnbell,
158 };
159
160 const struct wskbd_mapdata pckbd_keymapdata = {
161 pckbd_keydesctab,
162 #ifdef PCKBD_LAYOUT
163 PCKBD_LAYOUT,
164 #else
165 KB_US,
166 #endif
167 };
168
169
170
171
172
173 void (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int);
174 void *pckbd_bell_fn_arg;
175
176 void pckbd_bell(u_int, u_int, u_int, int);
177
178 int pckbd_set_xtscancode(pckbc_tag_t, pckbc_slot_t);
179 int pckbd_init(struct pckbd_internal *, pckbc_tag_t, pckbc_slot_t,
180 int);
181 void pckbd_input(void *, int);
182
183 static int pckbd_decode(struct pckbd_internal *, int,
184 u_int *, int *);
185 static int pckbd_led_encode(int);
186 static int pckbd_led_decode(int);
187
188 struct pckbd_internal pckbd_consdata;
189
190 int
191 pckbd_set_xtscancode(kbctag, kbcslot)
192 pckbc_tag_t kbctag;
193 pckbc_slot_t kbcslot;
194 {
195
196 int table = 3;
197
198 if (!pckbc_xt_translation(kbctag, kbcslot, 1)) {
199 #ifdef DEBUG
200 printf("pckbd: enabling of translation failed\n");
201 #endif
202
203 table = 1;
204 }
205
206
207 for (; table >= 1; table--) {
208 u_char cmd[2];
209 #ifdef DEBUG
210 printf("pckbd: trying table %d\n", table);
211 #endif
212 cmd[0] = KBC_SETTABLE;
213 cmd[1] = table;
214 if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0)) {
215 u_char cmd[1];
216 #ifdef DEBUG
217 printf("pckbd: table set of %d failed\n", table);
218 #endif
219 if (table > 1) {
220 cmd[0] = KBC_RESET;
221 (void)pckbc_poll_cmd(kbctag, kbcslot, cmd,
222 1, 1, 0, 1);
223 pckbc_flush(kbctag, kbcslot);
224
225 continue;
226 }
227 }
228
229
230
231
232
233
234 if (table == 3) {
235 u_char cmd[1], resp[0];
236
237 cmd[0] = KBC_SETTABLE;
238 cmd[1] = 0;
239 if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 1, resp, 0)) {
240
241
242
243
244 #ifdef DEBUG
245 printf("pckbd: table 3 verification failed\n");
246 #endif
247 continue;
248 } else if (resp[0] == 3) {
249 #ifdef DEBUG
250 printf("pckbd: settling on table 3\n");
251 #endif
252 return (0);
253 }
254 #ifdef DEBUG
255 else
256 printf("pckbd: table \"%x\" != 3, trying 2\n",
257 resp[0]);
258 #endif
259 } else {
260 #ifdef DEBUG
261 printf("pckbd: settling on table %d\n", table);
262 #endif
263 return (0);
264 }
265 }
266
267 return (1);
268 }
269
270 static int
271 pckbd_is_console(tag, slot)
272 pckbc_tag_t tag;
273 pckbc_slot_t slot;
274 {
275 return (pckbd_consdata.t_isconsole &&
276 (tag == pckbd_consdata.t_kbctag) &&
277 (slot == pckbd_consdata.t_kbcslot));
278 }
279
280
281
282
283 int
284 pckbdprobe(parent, match, aux)
285 struct device *parent;
286 void *match;
287 void *aux;
288 {
289 struct cfdata *cf = match;
290 struct pckbc_attach_args *pa = aux;
291 u_char cmd[1], resp[1];
292 int res;
293
294
295
296
297
298
299
300 if ((pa->pa_slot != PCKBC_KBD_SLOT) &&
301 (cf->cf_loc[PCKBCCF_SLOT] == PCKBCCF_SLOT_DEFAULT))
302 return (0);
303
304
305 pckbc_flush(pa->pa_tag, pa->pa_slot);
306
307
308 cmd[0] = KBC_RESET;
309 res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
310 if (res) {
311 #ifdef DEBUG
312 printf("pckbdprobe: reset error %d\n", res);
313 #endif
314
315
316
317
318
319 return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0);
320 }
321 if (resp[0] != KBR_RSTDONE) {
322 printf("pckbdprobe: reset response 0x%x\n", resp[0]);
323 return (0);
324 }
325
326
327
328
329
330
331 pckbc_flush(pa->pa_tag, pa->pa_slot);
332
333 if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot))
334 return (0);
335
336 return (2);
337 }
338
339 void
340 pckbdattach(parent, self, aux)
341 struct device *parent, *self;
342 void *aux;
343 {
344 struct pckbd_softc *sc = (void *)self;
345 struct pckbc_attach_args *pa = aux;
346 int isconsole;
347 struct wskbddev_attach_args a;
348 u_char cmd[1];
349
350 printf("\n");
351
352 isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
353
354 if (isconsole) {
355 sc->id = &pckbd_consdata;
356
357
358
359
360 cmd[0] = KBC_ENABLE;
361 (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
362 cmd, 1, 0, 0, 0);
363 sc->sc_enabled = 1;
364 } else {
365 sc->id = malloc(sizeof(struct pckbd_internal),
366 M_DEVBUF, M_WAITOK);
367 (void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
368
369
370 cmd[0] = KBC_DISABLE;
371 (void) pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
372 cmd, 1, 0, 0, 0);
373 sc->sc_enabled = 0;
374 }
375
376 sc->id->t_sc = sc;
377
378 pckbc_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
379 pckbd_input, sc, sc->sc_dev.dv_xname);
380
381 a.console = isconsole;
382
383 a.keymap = &pckbd_keymapdata;
384
385 a.accessops = &pckbd_accessops;
386 a.accesscookie = sc;
387
388
389
390
391
392 sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
393 }
394
395 int
396 pckbd_enable(v, on)
397 void *v;
398 int on;
399 {
400 struct pckbd_softc *sc = v;
401 u_char cmd[1];
402 int res;
403
404 if (on) {
405 if (sc->sc_enabled)
406 return (EBUSY);
407
408 pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
409
410 cmd[0] = KBC_ENABLE;
411 res = pckbc_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
412 cmd, 1, 0, NULL, 0);
413 if (res) {
414 printf("pckbd_enable: command error\n");
415 return (res);
416 }
417
418 res = pckbd_set_xtscancode(sc->id->t_kbctag,
419 sc->id->t_kbcslot);
420 if (res)
421 return (res);
422
423 sc->sc_enabled = 1;
424 } else {
425 if (sc->id->t_isconsole)
426 return (EBUSY);
427
428 cmd[0] = KBC_DISABLE;
429 res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
430 cmd, 1, 0, 1, 0);
431 if (res) {
432 printf("pckbd_disable: command error\n");
433 return (res);
434 }
435
436 pckbc_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
437
438 sc->sc_enabled = 0;
439 }
440
441 return (0);
442 }
443
444 static int
445 pckbd_decode(id, datain, type, dataout)
446 struct pckbd_internal *id;
447 int datain;
448 u_int *type;
449 int *dataout;
450 {
451 int key;
452
453 if (datain == KBR_EXTENDED0) {
454 id->t_extended = 1;
455 return(0);
456 } else if (datain == KBR_EXTENDED1) {
457 id->t_extended1 = 2;
458 return(0);
459 }
460
461
462 key = (datain & 0x7f) | (id->t_extended ? 0x80 : 0);
463 id->t_extended = 0;
464
465
466
467
468
469 if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
470 id->t_extended1 = 1;
471 return(0);
472 } else if (id->t_extended1 == 1 &&
473 (datain == 0x45 || datain == 0xc5)) {
474 id->t_extended1 = 0;
475 key = 0x7f;
476 } else if (id->t_extended1 > 0) {
477 id->t_extended1 = 0;
478 }
479
480 if (datain & 0x80) {
481 id->t_lastchar = 0;
482 *type = WSCONS_EVENT_KEY_UP;
483 } else {
484
485 if (key == id->t_lastchar)
486 return(0);
487 id->t_lastchar = key;
488 *type = WSCONS_EVENT_KEY_DOWN;
489 }
490
491 *dataout = key;
492 return(1);
493 }
494
495 int
496 pckbd_init(t, kbctag, kbcslot, console)
497 struct pckbd_internal *t;
498 pckbc_tag_t kbctag;
499 pckbc_slot_t kbcslot;
500 int console;
501 {
502 bzero(t, sizeof(struct pckbd_internal));
503
504 t->t_isconsole = console;
505 t->t_kbctag = kbctag;
506 t->t_kbcslot = kbcslot;
507
508 return (pckbd_set_xtscancode(kbctag, kbcslot));
509 }
510
511 static int
512 pckbd_led_encode(led)
513 int led;
514 {
515 int res;
516
517 res = 0;
518
519 if (led & WSKBD_LED_SCROLL)
520 res |= 0x01;
521 if (led & WSKBD_LED_NUM)
522 res |= 0x02;
523 if (led & WSKBD_LED_CAPS)
524 res |= 0x04;
525 return(res);
526 }
527
528 static int
529 pckbd_led_decode(led)
530 int led;
531 {
532 int res;
533
534 res = 0;
535 if (led & 0x01)
536 res |= WSKBD_LED_SCROLL;
537 if (led & 0x02)
538 res |= WSKBD_LED_NUM;
539 if (led & 0x04)
540 res |= WSKBD_LED_CAPS;
541 return(res);
542 }
543
544 void
545 pckbd_set_leds(v, leds)
546 void *v;
547 int leds;
548 {
549 struct pckbd_softc *sc = v;
550 u_char cmd[2];
551
552 cmd[0] = KBC_MODEIND;
553 cmd[1] = pckbd_led_encode(leds);
554 sc->sc_ledstate = cmd[1];
555
556 (void) pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
557 cmd, 2, 0, 0, 0);
558 }
559
560
561
562
563
564 void
565 pckbd_input(vsc, data)
566 void *vsc;
567 int data;
568 {
569 struct pckbd_softc *sc = vsc;
570 int type, key;
571
572 #ifdef WSDISPLAY_COMPAT_RAWKBD
573 if (sc->rawkbd) {
574 char d = data;
575 wskbd_rawinput(sc->sc_wskbddev, &d, 1);
576 return;
577 }
578 #endif
579 if (pckbd_decode(sc->id, data, &type, &key))
580 wskbd_input(sc->sc_wskbddev, type, key);
581 }
582
583 int
584 pckbd_ioctl(v, cmd, data, flag, p)
585 void *v;
586 u_long cmd;
587 caddr_t data;
588 int flag;
589 struct proc *p;
590 {
591 struct pckbd_softc *sc = v;
592
593 switch (cmd) {
594 case WSKBDIO_GTYPE:
595 *(int *)data = WSKBD_TYPE_PC_XT;
596 return 0;
597 case WSKBDIO_SETLEDS: {
598 char cmd[2];
599 int res;
600 cmd[0] = KBC_MODEIND;
601 cmd[1] = pckbd_led_encode(*(int *)data);
602 sc->sc_ledstate = cmd[1];
603 res = pckbc_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
604 cmd, 2, 0, 1, 0);
605 return (res);
606 }
607 case WSKBDIO_GETLEDS:
608 *(int *)data = pckbd_led_decode(sc->sc_ledstate);
609 return (0);
610 case WSKBDIO_COMPLEXBELL:
611 #define d ((struct wskbd_bell_data *)data)
612
613
614
615
616 pckbd_bell(d->pitch, d->period, d->volume, 0);
617 #undef d
618 return (0);
619 #ifdef WSDISPLAY_COMPAT_RAWKBD
620 case WSKBDIO_SETMODE:
621 sc->rawkbd = (*(int *)data == WSKBD_RAW);
622 return (0);
623 #endif
624 }
625 return -1;
626 }
627
628 void
629 pckbd_bell(pitch, period, volume, poll)
630 u_int pitch, period, volume;
631 int poll;
632 {
633
634 if (pckbd_bell_fn != NULL)
635 (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
636 volume, poll);
637 }
638
639 void
640 pckbd_hookup_bell(fn, arg)
641 void (*fn)(void *, u_int, u_int, u_int, int);
642 void *arg;
643 {
644
645 if (pckbd_bell_fn == NULL) {
646 pckbd_bell_fn = fn;
647 pckbd_bell_fn_arg = arg;
648 }
649 }
650
651 int
652 pckbd_cnattach(kbctag, kbcslot)
653 pckbc_tag_t kbctag;
654 int kbcslot;
655 {
656 char cmd[1];
657 int res;
658
659 res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1);
660 #if 0
661 if (res)
662 return (res);
663 #endif
664
665
666 cmd[0] = KBC_ENABLE;
667 res = pckbc_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0);
668 #if 0
669 if (res)
670 return (res);
671 #endif
672
673 wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
674
675 return (0);
676 }
677
678
679 void
680 pckbd_cngetc(v, type, data)
681 void *v;
682 u_int *type;
683 int *data;
684 {
685 struct pckbd_internal *t = v;
686 int val;
687
688 for (;;) {
689 val = pckbc_poll_data(t->t_kbctag, t->t_kbcslot);
690 if ((val != -1) && pckbd_decode(t, val, type, data))
691 return;
692 }
693 }
694
695 void
696 pckbd_cnpollc(v, on)
697 void *v;
698 int on;
699 {
700 struct pckbd_internal *t = v;
701
702 pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on);
703 }
704
705 void
706 pckbd_cnbell(v, pitch, period, volume)
707 void *v;
708 u_int pitch, period, volume;
709 {
710
711 pckbd_bell(pitch, period, volume, 1);
712 }
713
714 struct cfdriver pckbd_cd = {
715 NULL, "pckbd", DV_DULL
716 };