pckbd.c revision 1.29.20.2 1 1.29.20.2 tls /* $NetBSD: pckbd.c,v 1.29.20.2 2014/08/20 00:03:49 tls Exp $ */
2 1.1 bjh21
3 1.1 bjh21 /*-
4 1.26 ad * Copyright (c) 1998, 2009 The NetBSD Foundation, Inc.
5 1.1 bjh21 * All rights reserved.
6 1.1 bjh21 *
7 1.1 bjh21 * This code is derived from software contributed to The NetBSD Foundation
8 1.1 bjh21 * by Charles M. Hannum.
9 1.1 bjh21 *
10 1.1 bjh21 * Redistribution and use in source and binary forms, with or without
11 1.1 bjh21 * modification, are permitted provided that the following conditions
12 1.1 bjh21 * are met:
13 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright
14 1.1 bjh21 * notice, this list of conditions and the following disclaimer.
15 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the
17 1.1 bjh21 * documentation and/or other materials provided with the distribution.
18 1.1 bjh21 *
19 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 bjh21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 bjh21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 bjh21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 bjh21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 bjh21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 bjh21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 bjh21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 bjh21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 bjh21 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 bjh21 * POSSIBILITY OF SUCH DAMAGE.
30 1.1 bjh21 */
31 1.1 bjh21
32 1.1 bjh21 /*-
33 1.1 bjh21 * Copyright (c) 1990 The Regents of the University of California.
34 1.1 bjh21 * All rights reserved.
35 1.1 bjh21 *
36 1.1 bjh21 * This code is derived from software contributed to Berkeley by
37 1.1 bjh21 * William Jolitz and Don Ahn.
38 1.1 bjh21 *
39 1.1 bjh21 * Redistribution and use in source and binary forms, with or without
40 1.1 bjh21 * modification, are permitted provided that the following conditions
41 1.1 bjh21 * are met:
42 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright
43 1.1 bjh21 * notice, this list of conditions and the following disclaimer.
44 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright
45 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the
46 1.1 bjh21 * documentation and/or other materials provided with the distribution.
47 1.1 bjh21 * 3. Neither the name of the University nor the names of its contributors
48 1.1 bjh21 * may be used to endorse or promote products derived from this software
49 1.1 bjh21 * without specific prior written permission.
50 1.1 bjh21 *
51 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 1.1 bjh21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 1.1 bjh21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 1.1 bjh21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 1.1 bjh21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 1.1 bjh21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 1.1 bjh21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 1.1 bjh21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 1.1 bjh21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 1.1 bjh21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 1.1 bjh21 * SUCH DAMAGE.
62 1.1 bjh21 *
63 1.1 bjh21 * @(#)pccons.c 5.11 (Berkeley) 5/21/91
64 1.1 bjh21 */
65 1.1 bjh21
66 1.1 bjh21 /*
67 1.1 bjh21 * code to work keyboard for PC-style console
68 1.1 bjh21 */
69 1.1 bjh21
70 1.1 bjh21 #include <sys/cdefs.h>
71 1.29.20.2 tls __KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.29.20.2 2014/08/20 00:03:49 tls Exp $");
72 1.1 bjh21
73 1.1 bjh21 #include <sys/param.h>
74 1.1 bjh21 #include <sys/systm.h>
75 1.1 bjh21 #include <sys/device.h>
76 1.1 bjh21 #include <sys/malloc.h>
77 1.1 bjh21 #include <sys/ioctl.h>
78 1.1 bjh21
79 1.16 ad #include <sys/bus.h>
80 1.1 bjh21
81 1.1 bjh21 #include <dev/pckbport/pckbportvar.h>
82 1.1 bjh21
83 1.1 bjh21 #include <dev/wscons/wsconsio.h>
84 1.1 bjh21 #include <dev/wscons/wskbdvar.h>
85 1.1 bjh21 #include <dev/wscons/wsksymdef.h>
86 1.1 bjh21 #include <dev/wscons/wsksymvar.h>
87 1.1 bjh21
88 1.6 yamt #include <dev/pckbport/pckbdreg.h>
89 1.6 yamt #include <dev/pckbport/pckbdvar.h>
90 1.6 yamt #include <dev/pckbport/wskbdmap_mfii.h>
91 1.6 yamt
92 1.1 bjh21 #include "locators.h"
93 1.1 bjh21
94 1.1 bjh21 #include "opt_pckbd_layout.h"
95 1.7 augustss #include "opt_pckbd_cnattach_may_fail.h"
96 1.1 bjh21 #include "opt_wsdisplay_compat.h"
97 1.1 bjh21
98 1.1 bjh21 struct pckbd_internal {
99 1.1 bjh21 int t_isconsole;
100 1.1 bjh21 pckbport_tag_t t_kbctag;
101 1.1 bjh21 pckbport_slot_t t_kbcslot;
102 1.1 bjh21
103 1.29.20.1 tls int t_translating;
104 1.29.20.1 tls
105 1.1 bjh21 int t_lastchar;
106 1.1 bjh21 int t_extended0;
107 1.1 bjh21 int t_extended1;
108 1.29.20.1 tls int t_releasing;
109 1.1 bjh21
110 1.1 bjh21 struct pckbd_softc *t_sc; /* back pointer */
111 1.1 bjh21 };
112 1.1 bjh21
113 1.1 bjh21 struct pckbd_softc {
114 1.22 cube device_t sc_dev;
115 1.1 bjh21
116 1.1 bjh21 struct pckbd_internal *id;
117 1.1 bjh21 int sc_enabled;
118 1.1 bjh21
119 1.1 bjh21 int sc_ledstate;
120 1.1 bjh21
121 1.23 cube device_t sc_wskbddev;
122 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
123 1.1 bjh21 int rawkbd;
124 1.1 bjh21 #endif
125 1.1 bjh21 };
126 1.1 bjh21
127 1.2 bjh21 static int pckbd_is_console(pckbport_tag_t, pckbport_slot_t);
128 1.1 bjh21
129 1.23 cube int pckbdprobe(device_t, cfdata_t, void *);
130 1.23 cube void pckbdattach(device_t, device_t, void *);
131 1.1 bjh21
132 1.22 cube CFATTACH_DECL_NEW(pckbd, sizeof(struct pckbd_softc),
133 1.1 bjh21 pckbdprobe, pckbdattach, NULL, NULL);
134 1.1 bjh21
135 1.2 bjh21 int pckbd_enable(void *, int);
136 1.2 bjh21 void pckbd_set_leds(void *, int);
137 1.15 christos int pckbd_ioctl(void *, u_long, void *, int, struct lwp *);
138 1.1 bjh21
139 1.1 bjh21 const struct wskbd_accessops pckbd_accessops = {
140 1.1 bjh21 pckbd_enable,
141 1.1 bjh21 pckbd_set_leds,
142 1.1 bjh21 pckbd_ioctl,
143 1.1 bjh21 };
144 1.1 bjh21
145 1.2 bjh21 void pckbd_cngetc(void *, u_int *, int *);
146 1.2 bjh21 void pckbd_cnpollc(void *, int);
147 1.2 bjh21 void pckbd_cnbell(void *, u_int, u_int, u_int);
148 1.1 bjh21
149 1.1 bjh21 const struct wskbd_consops pckbd_consops = {
150 1.1 bjh21 pckbd_cngetc,
151 1.1 bjh21 pckbd_cnpollc,
152 1.1 bjh21 pckbd_cnbell,
153 1.1 bjh21 };
154 1.1 bjh21
155 1.1 bjh21 const struct wskbd_mapdata pckbd_keymapdata = {
156 1.1 bjh21 pckbd_keydesctab,
157 1.1 bjh21 #ifdef PCKBD_LAYOUT
158 1.1 bjh21 PCKBD_LAYOUT,
159 1.1 bjh21 #else
160 1.5 matt KB_US,
161 1.1 bjh21 #endif
162 1.1 bjh21 };
163 1.1 bjh21
164 1.1 bjh21 /*
165 1.1 bjh21 * Hackish support for a bell on the PC Keyboard; when a suitable feeper
166 1.1 bjh21 * is found, it attaches itself into the pckbd driver here.
167 1.1 bjh21 */
168 1.2 bjh21 void (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int);
169 1.1 bjh21 void *pckbd_bell_fn_arg;
170 1.1 bjh21
171 1.2 bjh21 void pckbd_bell(u_int, u_int, u_int, int);
172 1.1 bjh21
173 1.29.20.1 tls int pckbd_scancode_translate(struct pckbd_internal *, int);
174 1.29.20.1 tls int pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t,
175 1.29.20.1 tls struct pckbd_internal *);
176 1.2 bjh21 int pckbd_init(struct pckbd_internal *, pckbport_tag_t, pckbport_slot_t,
177 1.2 bjh21 int);
178 1.2 bjh21 void pckbd_input(void *, int);
179 1.2 bjh21
180 1.2 bjh21 static int pckbd_decode(struct pckbd_internal *, int, u_int *, int *);
181 1.2 bjh21 static int pckbd_led_encode(int);
182 1.2 bjh21 static int pckbd_led_decode(int);
183 1.1 bjh21
184 1.1 bjh21 struct pckbd_internal pckbd_consdata;
185 1.1 bjh21
186 1.1 bjh21 int
187 1.29.20.1 tls pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot,
188 1.29.20.1 tls struct pckbd_internal *id)
189 1.1 bjh21 {
190 1.29.20.1 tls int xt, res = 0;
191 1.1 bjh21 u_char cmd[2];
192 1.1 bjh21
193 1.1 bjh21 /*
194 1.1 bjh21 * Some keyboard/8042 combinations do not seem to work if the keyboard
195 1.1 bjh21 * is set to table 1; in fact, it would appear that some keyboards just
196 1.1 bjh21 * ignore the command altogether. So by default, we use the AT scan
197 1.1 bjh21 * codes and have the 8042 translate them. Unfortunately, this is
198 1.1 bjh21 * known to not work on some PS/2 machines. We try desperately to deal
199 1.1 bjh21 * with this by checking the (lack of a) translate bit in the 8042 and
200 1.1 bjh21 * attempting to set the keyboard to XT mode. If this all fails, well,
201 1.29.20.1 tls * tough luck. If the PCKBC_CANT_TRANSLATE pckbc flag was set, we
202 1.29.20.1 tls * enable software translation.
203 1.1 bjh21 *
204 1.1 bjh21 * XXX It would perhaps be a better choice to just use AT scan codes
205 1.1 bjh21 * and not bother with this.
206 1.1 bjh21 */
207 1.29.20.1 tls xt = pckbport_xt_translation(kbctag, kbcslot, 1);
208 1.29.20.1 tls if (xt == 1) {
209 1.1 bjh21 /* The 8042 is translating for us; use AT codes. */
210 1.1 bjh21 cmd[0] = KBC_SETTABLE;
211 1.1 bjh21 cmd[1] = 2;
212 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
213 1.1 bjh21 if (res) {
214 1.8 christos u_char cmdb[1];
215 1.26 ad aprint_debug("pckbd: error setting scanset 2\n");
216 1.1 bjh21 /*
217 1.1 bjh21 * XXX at least one keyboard is reported to lock up
218 1.1 bjh21 * if a "set table" is attempted, thus the "reset".
219 1.1 bjh21 * XXX ignore errors, scanset 2 should be
220 1.1 bjh21 * default anyway.
221 1.1 bjh21 */
222 1.8 christos cmdb[0] = KBC_RESET;
223 1.8 christos (void)pckbport_poll_cmd(kbctag, kbcslot, cmdb, 1, 1, 0, 1);
224 1.1 bjh21 pckbport_flush(kbctag, kbcslot);
225 1.1 bjh21 res = 0;
226 1.1 bjh21 }
227 1.29.20.1 tls if (id != NULL)
228 1.29.20.1 tls id->t_translating = 1;
229 1.29.20.1 tls } else if (xt == -1) {
230 1.29.20.1 tls /* Software translation required */
231 1.29.20.1 tls if (id != NULL)
232 1.29.20.1 tls id->t_translating = 0;
233 1.1 bjh21 } else {
234 1.1 bjh21 /* Stupid 8042; set keyboard to XT codes. */
235 1.1 bjh21 cmd[0] = KBC_SETTABLE;
236 1.1 bjh21 cmd[1] = 1;
237 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
238 1.1 bjh21 if (res)
239 1.26 ad aprint_debug("pckbd: error setting scanset 1\n");
240 1.29.20.1 tls if (id != NULL)
241 1.29.20.1 tls id->t_translating = 1;
242 1.1 bjh21 }
243 1.2 bjh21 return res;
244 1.1 bjh21 }
245 1.1 bjh21
246 1.1 bjh21 static int
247 1.2 bjh21 pckbd_is_console(pckbport_tag_t tag, pckbport_slot_t slot)
248 1.2 bjh21 {
249 1.2 bjh21
250 1.2 bjh21 return pckbd_consdata.t_isconsole &&
251 1.2 bjh21 tag == pckbd_consdata.t_kbctag && slot == pckbd_consdata.t_kbcslot;
252 1.1 bjh21 }
253 1.1 bjh21
254 1.18 jmcneill static bool
255 1.29 dyoung pckbd_suspend(device_t dv, const pmf_qual_t *qual)
256 1.11 christos {
257 1.18 jmcneill struct pckbd_softc *sc = device_private(dv);
258 1.18 jmcneill u_char cmd[1];
259 1.11 christos int res;
260 1.11 christos
261 1.18 jmcneill /* XXX duped from pckbd_enable, but we want to disable
262 1.18 jmcneill * it even if it's the console kbd
263 1.18 jmcneill */
264 1.18 jmcneill cmd[0] = KBC_DISABLE;
265 1.18 jmcneill res = pckbport_enqueue_cmd(sc->id->t_kbctag,
266 1.18 jmcneill sc->id->t_kbcslot, cmd, 1, 0, 1, 0);
267 1.18 jmcneill if (res)
268 1.18 jmcneill return false;
269 1.18 jmcneill
270 1.18 jmcneill pckbport_slot_enable(sc->id->t_kbctag,
271 1.18 jmcneill sc->id->t_kbcslot, 0);
272 1.11 christos
273 1.18 jmcneill sc->sc_enabled = 0;
274 1.18 jmcneill return true;
275 1.18 jmcneill }
276 1.11 christos
277 1.18 jmcneill static bool
278 1.29 dyoung pckbd_resume(device_t dv, const pmf_qual_t *qual)
279 1.18 jmcneill {
280 1.18 jmcneill struct pckbd_softc *sc = device_private(dv);
281 1.18 jmcneill u_char cmd[1], resp[1];
282 1.18 jmcneill int res;
283 1.11 christos
284 1.18 jmcneill /* XXX jmcneill reset the keyboard */
285 1.18 jmcneill pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot);
286 1.11 christos
287 1.18 jmcneill cmd[0] = KBC_RESET;
288 1.18 jmcneill res = pckbport_poll_cmd(sc->id->t_kbctag,
289 1.18 jmcneill sc->id->t_kbcslot, cmd, 1, 1, resp, 1);
290 1.18 jmcneill if (res)
291 1.26 ad aprint_debug("pckbdprobe: reset error %d\n", res);
292 1.18 jmcneill if (resp[0] != KBR_RSTDONE)
293 1.18 jmcneill printf("pckbdprobe: reset response 0x%x\n",
294 1.18 jmcneill resp[0]);
295 1.11 christos
296 1.18 jmcneill pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot);
297 1.11 christos
298 1.18 jmcneill pckbd_enable(sc, 1);
299 1.11 christos
300 1.18 jmcneill return true;
301 1.11 christos }
302 1.11 christos
303 1.1 bjh21 /*
304 1.1 bjh21 * these are both bad jokes
305 1.1 bjh21 */
306 1.1 bjh21 int
307 1.23 cube pckbdprobe(device_t parent, cfdata_t cf, void *aux)
308 1.1 bjh21 {
309 1.1 bjh21 struct pckbport_attach_args *pa = aux;
310 1.2 bjh21 int res;
311 1.1 bjh21 u_char cmd[1], resp[1];
312 1.1 bjh21
313 1.1 bjh21 /*
314 1.1 bjh21 * XXX There are rumours that a keyboard can be connected
315 1.1 bjh21 * to the aux port as well. For me, this didn't work.
316 1.1 bjh21 * For further experiments, allow it if explicitly
317 1.1 bjh21 * wired in the config file.
318 1.1 bjh21 */
319 1.1 bjh21 if ((pa->pa_slot != PCKBPORT_KBD_SLOT) &&
320 1.1 bjh21 (cf->cf_loc[PCKBPORTCF_SLOT] == PCKBPORTCF_SLOT_DEFAULT))
321 1.2 bjh21 return 0;
322 1.1 bjh21
323 1.1 bjh21 /* Flush any garbage. */
324 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot);
325 1.1 bjh21
326 1.1 bjh21 /* Reset the keyboard. */
327 1.1 bjh21 cmd[0] = KBC_RESET;
328 1.1 bjh21 res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
329 1.1 bjh21 if (res) {
330 1.26 ad aprint_debug("pckbdprobe: reset error %d\n", res);
331 1.1 bjh21 /*
332 1.1 bjh21 * There is probably no keyboard connected.
333 1.1 bjh21 * Let the probe succeed if the keyboard is used
334 1.1 bjh21 * as console input - it can be connected later.
335 1.1 bjh21 */
336 1.2 bjh21 return pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0;
337 1.1 bjh21 }
338 1.1 bjh21 if (resp[0] != KBR_RSTDONE) {
339 1.1 bjh21 printf("pckbdprobe: reset response 0x%x\n", resp[0]);
340 1.2 bjh21 return 0;
341 1.1 bjh21 }
342 1.1 bjh21
343 1.1 bjh21 /*
344 1.1 bjh21 * Some keyboards seem to leave a second ack byte after the reset.
345 1.1 bjh21 * This is kind of stupid, but we account for them anyway by just
346 1.1 bjh21 * flushing the buffer.
347 1.1 bjh21 */
348 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot);
349 1.1 bjh21
350 1.29.20.1 tls if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
351 1.2 bjh21 return 0;
352 1.1 bjh21
353 1.2 bjh21 return 2;
354 1.1 bjh21 }
355 1.1 bjh21
356 1.1 bjh21 void
357 1.23 cube pckbdattach(device_t parent, device_t self, void *aux)
358 1.1 bjh21 {
359 1.10 thorpej struct pckbd_softc *sc = device_private(self);
360 1.1 bjh21 struct pckbport_attach_args *pa = aux;
361 1.2 bjh21 struct wskbddev_attach_args a;
362 1.1 bjh21 int isconsole;
363 1.1 bjh21 u_char cmd[1];
364 1.1 bjh21
365 1.17 jmcneill aprint_naive("\n");
366 1.17 jmcneill aprint_normal("\n");
367 1.1 bjh21
368 1.22 cube sc->sc_dev = self;
369 1.1 bjh21 isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
370 1.1 bjh21
371 1.1 bjh21 if (isconsole) {
372 1.1 bjh21 sc->id = &pckbd_consdata;
373 1.1 bjh21
374 1.3 perry /*
375 1.3 perry * Some keyboards are not enabled after a reset,
376 1.1 bjh21 * so make sure it is enabled now.
377 1.1 bjh21 */
378 1.1 bjh21 cmd[0] = KBC_ENABLE;
379 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
380 1.1 bjh21 cmd, 1, 0, 0, 0);
381 1.1 bjh21 sc->sc_enabled = 1;
382 1.1 bjh21 } else {
383 1.1 bjh21 sc->id = malloc(sizeof(struct pckbd_internal),
384 1.1 bjh21 M_DEVBUF, M_WAITOK);
385 1.1 bjh21 (void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
386 1.1 bjh21
387 1.1 bjh21 /* no interrupts until enabled */
388 1.1 bjh21 cmd[0] = KBC_DISABLE;
389 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
390 1.1 bjh21 cmd, 1, 0, 0, 0);
391 1.1 bjh21 sc->sc_enabled = 0;
392 1.1 bjh21 }
393 1.1 bjh21
394 1.1 bjh21 sc->id->t_sc = sc;
395 1.1 bjh21
396 1.1 bjh21 pckbport_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
397 1.22 cube pckbd_input, sc, device_xname(sc->sc_dev));
398 1.1 bjh21
399 1.1 bjh21 a.console = isconsole;
400 1.1 bjh21
401 1.1 bjh21 a.keymap = &pckbd_keymapdata;
402 1.1 bjh21
403 1.1 bjh21 a.accessops = &pckbd_accessops;
404 1.1 bjh21 a.accesscookie = sc;
405 1.1 bjh21
406 1.18 jmcneill if (!pmf_device_register(self, pckbd_suspend, pckbd_resume))
407 1.18 jmcneill aprint_error_dev(self, "couldn't establish power handler\n");
408 1.11 christos
409 1.1 bjh21 /*
410 1.1 bjh21 * Attach the wskbd, saving a handle to it.
411 1.1 bjh21 * XXX XXX XXX
412 1.1 bjh21 */
413 1.22 cube sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a, wskbddevprint);
414 1.1 bjh21 }
415 1.1 bjh21
416 1.1 bjh21 int
417 1.2 bjh21 pckbd_enable(void *v, int on)
418 1.1 bjh21 {
419 1.1 bjh21 struct pckbd_softc *sc = v;
420 1.2 bjh21 int res;
421 1.1 bjh21 u_char cmd[1];
422 1.1 bjh21
423 1.1 bjh21 if (on) {
424 1.1 bjh21 if (sc->sc_enabled) {
425 1.26 ad aprint_debug("pckbd_enable: bad enable\n");
426 1.2 bjh21 return EBUSY;
427 1.1 bjh21 }
428 1.1 bjh21
429 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
430 1.1 bjh21
431 1.1 bjh21 cmd[0] = KBC_ENABLE;
432 1.1 bjh21 res = pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
433 1.1 bjh21 cmd, 1, 0, NULL, 0);
434 1.1 bjh21 if (res) {
435 1.1 bjh21 printf("pckbd_enable: command error\n");
436 1.1 bjh21 return (res);
437 1.1 bjh21 }
438 1.1 bjh21
439 1.1 bjh21 res = pckbd_set_xtscancode(sc->id->t_kbctag,
440 1.29.20.1 tls sc->id->t_kbcslot, sc->id);
441 1.1 bjh21 if (res)
442 1.2 bjh21 return res;
443 1.1 bjh21
444 1.1 bjh21 sc->sc_enabled = 1;
445 1.1 bjh21 } else {
446 1.1 bjh21 if (sc->id->t_isconsole)
447 1.2 bjh21 return EBUSY;
448 1.1 bjh21
449 1.1 bjh21 cmd[0] = KBC_DISABLE;
450 1.1 bjh21 res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
451 1.1 bjh21 cmd, 1, 0, 1, 0);
452 1.1 bjh21 if (res) {
453 1.1 bjh21 printf("pckbd_disable: command error\n");
454 1.2 bjh21 return res;
455 1.1 bjh21 }
456 1.1 bjh21
457 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
458 1.1 bjh21
459 1.1 bjh21 sc->sc_enabled = 0;
460 1.1 bjh21 }
461 1.1 bjh21
462 1.2 bjh21 return 0;
463 1.1 bjh21 }
464 1.1 bjh21
465 1.29.20.1 tls const u_int8_t pckbd_xtbl[] = {
466 1.29.20.1 tls /* 0x00 */
467 1.29.20.1 tls 0,
468 1.29.20.1 tls 0x43, /* F9 */
469 1.29.20.1 tls 0x89, /* SunStop */
470 1.29.20.1 tls 0x3f, /* F5 */
471 1.29.20.1 tls 0x3d, /* F3 */
472 1.29.20.1 tls 0x3b, /* F1 */
473 1.29.20.1 tls 0x3c, /* F2 */
474 1.29.20.1 tls 0x58, /* F12 */
475 1.29.20.1 tls 0,
476 1.29.20.1 tls 0x44, /* F10 */
477 1.29.20.1 tls 0x42, /* F8 */
478 1.29.20.1 tls 0x40, /* F6 */
479 1.29.20.1 tls 0x3e, /* F4 */
480 1.29.20.1 tls 0x0f, /* Tab */
481 1.29.20.1 tls 0x29, /* ` ~ */
482 1.29.20.1 tls 0,
483 1.29.20.1 tls /* 0x10 */
484 1.29.20.1 tls 0,
485 1.29.20.1 tls 0x38, /* Left Alt */
486 1.29.20.1 tls 0x2a, /* Left Shift */
487 1.29.20.1 tls 0,
488 1.29.20.1 tls 0x1d, /* Left Ctrl */
489 1.29.20.1 tls 0x10, /* q */
490 1.29.20.1 tls 0x02, /* 1 ! */
491 1.29.20.1 tls 0,
492 1.29.20.1 tls 0,
493 1.29.20.1 tls 0,
494 1.29.20.1 tls 0x2c, /* z */
495 1.29.20.1 tls 0x1f, /* s */
496 1.29.20.1 tls 0x1e, /* a */
497 1.29.20.1 tls 0x11, /* w */
498 1.29.20.1 tls 0x03, /* 2 @ */
499 1.29.20.1 tls 0,
500 1.29.20.1 tls /* 0x20 */
501 1.29.20.1 tls 0,
502 1.29.20.1 tls 0x2e, /* c */
503 1.29.20.1 tls 0x2d, /* x */
504 1.29.20.1 tls 0x20, /* d */
505 1.29.20.1 tls 0x12, /* e */
506 1.29.20.1 tls 0x05, /* 4 $ */
507 1.29.20.1 tls 0x04, /* 3 # */
508 1.29.20.1 tls 0,
509 1.29.20.1 tls 0,
510 1.29.20.1 tls 0x39, /* Space */
511 1.29.20.1 tls 0x2f, /* v */
512 1.29.20.1 tls 0x21, /* f */
513 1.29.20.1 tls 0x14, /* t */
514 1.29.20.1 tls 0x13, /* r */
515 1.29.20.1 tls 0x06, /* 5 % */
516 1.29.20.1 tls 0,
517 1.29.20.1 tls /* 0x30 */
518 1.29.20.1 tls 0,
519 1.29.20.1 tls 0x31, /* n */
520 1.29.20.1 tls 0x30, /* b */
521 1.29.20.1 tls 0x23, /* h */
522 1.29.20.1 tls 0x22, /* g */
523 1.29.20.1 tls 0x15, /* y */
524 1.29.20.1 tls 0x07, /* 6 ^ */
525 1.29.20.1 tls 0,
526 1.29.20.1 tls 0,
527 1.29.20.1 tls 0,
528 1.29.20.1 tls 0x32, /* m */
529 1.29.20.1 tls 0x24, /* j */
530 1.29.20.1 tls 0x16, /* u */
531 1.29.20.1 tls 0x08, /* 7 & */
532 1.29.20.1 tls 0x09, /* 8 * */
533 1.29.20.1 tls 0,
534 1.29.20.1 tls /* 0x40 */
535 1.29.20.1 tls 0,
536 1.29.20.1 tls 0x33, /* , < */
537 1.29.20.1 tls 0x25, /* k */
538 1.29.20.1 tls 0x17, /* i */
539 1.29.20.1 tls 0x18, /* o */
540 1.29.20.1 tls 0x0b, /* 0 ) */
541 1.29.20.1 tls 0x0a, /* 9 ( */
542 1.29.20.1 tls 0,
543 1.29.20.1 tls 0,
544 1.29.20.1 tls 0x34, /* . > */
545 1.29.20.1 tls 0x35, /* / ? */
546 1.29.20.1 tls 0x26, /* l */
547 1.29.20.1 tls 0x27, /* ; : */
548 1.29.20.1 tls 0x19, /* p */
549 1.29.20.1 tls 0x0c, /* - _ */
550 1.29.20.1 tls 0,
551 1.29.20.1 tls /* 0x50 */
552 1.29.20.1 tls 0,
553 1.29.20.1 tls 0,
554 1.29.20.1 tls 0x28, /* ' " */
555 1.29.20.1 tls 0,
556 1.29.20.1 tls 0x1a, /* [ { */
557 1.29.20.1 tls 0x0d, /* = + */
558 1.29.20.1 tls 0,
559 1.29.20.1 tls 0,
560 1.29.20.1 tls 0x3a, /* Caps Lock */
561 1.29.20.1 tls 0x36, /* Right Shift */
562 1.29.20.1 tls 0x1c, /* Return */
563 1.29.20.1 tls 0x1b, /* ] } */
564 1.29.20.1 tls 0,
565 1.29.20.1 tls 0x2b, /* \ | */
566 1.29.20.1 tls 0,
567 1.29.20.1 tls 0,
568 1.29.20.1 tls /* 0x60 */
569 1.29.20.1 tls 0,
570 1.29.20.1 tls 0,
571 1.29.20.1 tls 0,
572 1.29.20.1 tls 0,
573 1.29.20.1 tls 0,
574 1.29.20.1 tls 0,
575 1.29.20.1 tls 0x0e, /* Back Space */
576 1.29.20.1 tls 0,
577 1.29.20.1 tls 0,
578 1.29.20.1 tls 0x4f, /* KP 1 */
579 1.29.20.1 tls 0,
580 1.29.20.1 tls 0x4b, /* KP 4 */
581 1.29.20.1 tls 0x47, /* KP 7 */
582 1.29.20.1 tls 0,
583 1.29.20.1 tls 0,
584 1.29.20.1 tls 0,
585 1.29.20.1 tls /* 0x70 */
586 1.29.20.1 tls 0x52, /* KP 0 */
587 1.29.20.1 tls 0x53, /* KP . */
588 1.29.20.1 tls 0x50, /* KP 2 */
589 1.29.20.1 tls 0x4c, /* KP 5 */
590 1.29.20.1 tls 0x4d, /* KP 6 */
591 1.29.20.1 tls 0x48, /* KP 8 */
592 1.29.20.1 tls 0x01, /* Escape */
593 1.29.20.1 tls 0x45, /* Num Lock */
594 1.29.20.1 tls 0x57, /* F11 */
595 1.29.20.1 tls 0x4e, /* KP + */
596 1.29.20.1 tls 0x51, /* KP 3 */
597 1.29.20.1 tls 0x4a, /* KP - */
598 1.29.20.1 tls 0x37, /* KP * */
599 1.29.20.1 tls 0x49, /* KP 9 */
600 1.29.20.1 tls 0x46, /* Scroll Lock */
601 1.29.20.1 tls 0,
602 1.29.20.1 tls /* 0x80 */
603 1.29.20.1 tls 0,
604 1.29.20.1 tls 0,
605 1.29.20.1 tls 0,
606 1.29.20.1 tls 0x41, /* F7 (produced as an actual 8 bit code) */
607 1.29.20.1 tls 0, /* Alt-Print Screen */
608 1.29.20.1 tls 0,
609 1.29.20.1 tls 0,
610 1.29.20.1 tls 0,
611 1.29.20.1 tls 0,
612 1.29.20.1 tls 0,
613 1.29.20.1 tls 0,
614 1.29.20.1 tls 0,
615 1.29.20.1 tls 0,
616 1.29.20.1 tls 0,
617 1.29.20.1 tls 0,
618 1.29.20.1 tls 0,
619 1.29.20.1 tls /* 0x90 */
620 1.29.20.1 tls 0xdb, /* Left Meta */
621 1.29.20.1 tls 0x88, /* SunHelp */
622 1.29.20.1 tls 0x8a, /* SunAgain */
623 1.29.20.1 tls 0x8c, /* SunUndo */
624 1.29.20.1 tls 0x8e, /* SunCopy */
625 1.29.20.1 tls 0x90, /* SunPaste */
626 1.29.20.1 tls 0x92, /* SunCut */
627 1.29.20.1 tls 0x8b, /* SunProps */
628 1.29.20.1 tls 0x8d, /* SunFront */
629 1.29.20.1 tls 0x8f, /* SunOpen */
630 1.29.20.1 tls 0x91 /* SunFind */
631 1.29.20.1 tls };
632 1.29.20.1 tls
633 1.29.20.1 tls const u_int8_t pckbd_xtbl_ext[] = {
634 1.29.20.1 tls /* 0x00 */
635 1.29.20.1 tls 0,
636 1.29.20.1 tls 0,
637 1.29.20.1 tls 0,
638 1.29.20.1 tls 0,
639 1.29.20.1 tls 0,
640 1.29.20.1 tls 0,
641 1.29.20.1 tls 0,
642 1.29.20.1 tls 0,
643 1.29.20.1 tls 0,
644 1.29.20.1 tls 0,
645 1.29.20.1 tls 0,
646 1.29.20.1 tls 0,
647 1.29.20.1 tls 0,
648 1.29.20.1 tls 0,
649 1.29.20.1 tls 0,
650 1.29.20.1 tls 0,
651 1.29.20.1 tls /* 0x10 */
652 1.29.20.1 tls 0,
653 1.29.20.1 tls 0x38, /* Right Alt */
654 1.29.20.1 tls 0, /* E0 12, to be ignored */
655 1.29.20.1 tls 0,
656 1.29.20.1 tls 0x1d, /* Right Ctrl */
657 1.29.20.1 tls 0,
658 1.29.20.1 tls 0,
659 1.29.20.1 tls 0,
660 1.29.20.1 tls 0,
661 1.29.20.1 tls 0,
662 1.29.20.1 tls 0,
663 1.29.20.1 tls 0,
664 1.29.20.1 tls 0,
665 1.29.20.1 tls 0,
666 1.29.20.1 tls 0,
667 1.29.20.1 tls 0,
668 1.29.20.1 tls /* 0x20 */
669 1.29.20.1 tls 0,
670 1.29.20.1 tls 0,
671 1.29.20.1 tls 0,
672 1.29.20.1 tls 0,
673 1.29.20.1 tls 0,
674 1.29.20.1 tls 0,
675 1.29.20.1 tls 0,
676 1.29.20.1 tls 0,
677 1.29.20.1 tls 0,
678 1.29.20.1 tls 0,
679 1.29.20.1 tls 0,
680 1.29.20.1 tls 0,
681 1.29.20.1 tls 0,
682 1.29.20.1 tls 0,
683 1.29.20.1 tls 0,
684 1.29.20.1 tls 0xdd, /* Compose */
685 1.29.20.1 tls /* 0x30 */
686 1.29.20.1 tls 0,
687 1.29.20.1 tls 0,
688 1.29.20.1 tls 0,
689 1.29.20.1 tls 0,
690 1.29.20.1 tls 0,
691 1.29.20.1 tls 0,
692 1.29.20.1 tls 0,
693 1.29.20.1 tls 0,
694 1.29.20.1 tls 0,
695 1.29.20.1 tls 0,
696 1.29.20.1 tls 0,
697 1.29.20.1 tls 0,
698 1.29.20.1 tls 0,
699 1.29.20.1 tls 0,
700 1.29.20.1 tls 0,
701 1.29.20.1 tls 0,
702 1.29.20.1 tls /* 0x40 */
703 1.29.20.1 tls 0,
704 1.29.20.1 tls 0,
705 1.29.20.1 tls 0,
706 1.29.20.1 tls 0,
707 1.29.20.1 tls 0,
708 1.29.20.1 tls 0,
709 1.29.20.1 tls 0,
710 1.29.20.1 tls 0,
711 1.29.20.1 tls 0,
712 1.29.20.1 tls 0,
713 1.29.20.1 tls 0xb5, /* KP / */
714 1.29.20.1 tls 0,
715 1.29.20.1 tls 0,
716 1.29.20.1 tls 0,
717 1.29.20.1 tls 0,
718 1.29.20.1 tls 0,
719 1.29.20.1 tls /* 0x50 */
720 1.29.20.1 tls 0,
721 1.29.20.1 tls 0,
722 1.29.20.1 tls 0,
723 1.29.20.1 tls 0,
724 1.29.20.1 tls 0,
725 1.29.20.1 tls 0,
726 1.29.20.1 tls 0,
727 1.29.20.1 tls 0,
728 1.29.20.1 tls 0,
729 1.29.20.1 tls 0,
730 1.29.20.1 tls 0x1c, /* KP Return */
731 1.29.20.1 tls 0,
732 1.29.20.1 tls 0,
733 1.29.20.1 tls 0,
734 1.29.20.1 tls 0,
735 1.29.20.1 tls 0,
736 1.29.20.1 tls /* 0x60 */
737 1.29.20.1 tls 0,
738 1.29.20.1 tls 0,
739 1.29.20.1 tls 0,
740 1.29.20.1 tls 0,
741 1.29.20.1 tls 0,
742 1.29.20.1 tls 0,
743 1.29.20.1 tls 0,
744 1.29.20.1 tls 0,
745 1.29.20.1 tls 0,
746 1.29.20.1 tls 0x4f, /* End */
747 1.29.20.1 tls 0,
748 1.29.20.1 tls 0x4b, /* Left */
749 1.29.20.1 tls 0x47, /* Home */
750 1.29.20.1 tls 0,
751 1.29.20.1 tls 0,
752 1.29.20.1 tls 0,
753 1.29.20.1 tls /* 0x70 */
754 1.29.20.1 tls 0x52, /* Insert */
755 1.29.20.1 tls 0x53, /* Delete */
756 1.29.20.1 tls 0x50, /* Down */
757 1.29.20.1 tls 0,
758 1.29.20.1 tls 0x4d, /* Right */
759 1.29.20.1 tls 0x48, /* Up */
760 1.29.20.1 tls 0,
761 1.29.20.1 tls 0,
762 1.29.20.1 tls 0,
763 1.29.20.1 tls 0,
764 1.29.20.1 tls 0x51, /* Page Down */
765 1.29.20.1 tls 0,
766 1.29.20.1 tls 0x37, /* Print Screen */
767 1.29.20.1 tls 0x49, /* Page Up */
768 1.29.20.1 tls 0x46, /* Ctrl-Break */
769 1.29.20.1 tls 0
770 1.29.20.1 tls };
771 1.29.20.1 tls
772 1.29.20.1 tls /*
773 1.29.20.1 tls * Translate scan codes from set 2 to set 1
774 1.29.20.1 tls */
775 1.29.20.1 tls int
776 1.29.20.1 tls pckbd_scancode_translate(struct pckbd_internal *id, int datain)
777 1.29.20.1 tls {
778 1.29.20.1 tls if (id->t_translating != 0)
779 1.29.20.1 tls return datain;
780 1.29.20.1 tls
781 1.29.20.1 tls if (datain == KBR_BREAK) {
782 1.29.20.1 tls id->t_releasing = 0x80; /* next keycode is a release */
783 1.29.20.1 tls return 0; /* consume scancode */
784 1.29.20.1 tls }
785 1.29.20.1 tls
786 1.29.20.1 tls /*
787 1.29.20.1 tls * Handle extended sequences
788 1.29.20.1 tls */
789 1.29.20.1 tls if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1)
790 1.29.20.1 tls return datain;
791 1.29.20.1 tls
792 1.29.20.1 tls /*
793 1.29.20.1 tls * Convert BREAK sequence (14 77 -> 1D 45)
794 1.29.20.1 tls */
795 1.29.20.1 tls if (id->t_extended1 == 2 && datain == 0x14)
796 1.29.20.1 tls return 0x1d | id->t_releasing;
797 1.29.20.1 tls else if (id->t_extended1 == 1 && datain == 0x77)
798 1.29.20.1 tls return 0x45 | id->t_releasing;
799 1.29.20.1 tls
800 1.29.20.1 tls if (id->t_extended0 != 0) {
801 1.29.20.1 tls if (datain >= sizeof pckbd_xtbl_ext)
802 1.29.20.1 tls datain = 0;
803 1.29.20.1 tls else
804 1.29.20.1 tls datain = pckbd_xtbl_ext[datain];
805 1.29.20.1 tls } else {
806 1.29.20.1 tls if (datain >= sizeof pckbd_xtbl)
807 1.29.20.1 tls datain = 0;
808 1.29.20.1 tls else
809 1.29.20.1 tls datain = pckbd_xtbl[datain];
810 1.29.20.1 tls }
811 1.29.20.1 tls
812 1.29.20.1 tls /*
813 1.29.20.1 tls * If we are mapping in the range 128-254, then make this
814 1.29.20.1 tls * an extended keycode, as table 1 codes are limited to
815 1.29.20.1 tls * the range 0-127 (the top bit is used for key up/break).
816 1.29.20.1 tls */
817 1.29.20.1 tls if (datain > 0x7f) {
818 1.29.20.1 tls datain &= 0x7f;
819 1.29.20.1 tls id->t_extended0 = 0x80;
820 1.29.20.1 tls }
821 1.29.20.1 tls
822 1.29.20.1 tls if (datain == 0) {
823 1.29.20.1 tls /*
824 1.29.20.1 tls * We don't know how to translate this scan code, but
825 1.29.20.1 tls * we can't silently eat it either (because there might
826 1.29.20.1 tls * have been an extended byte transmitted already).
827 1.29.20.1 tls * Hopefully this value will be harmless to the upper
828 1.29.20.1 tls * layers.
829 1.29.20.1 tls */
830 1.29.20.1 tls return 0xff;
831 1.29.20.1 tls }
832 1.29.20.1 tls return datain | id->t_releasing;
833 1.29.20.1 tls }
834 1.29.20.1 tls
835 1.1 bjh21 static int
836 1.2 bjh21 pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
837 1.1 bjh21 {
838 1.1 bjh21 int key;
839 1.29.20.1 tls int releasing;
840 1.1 bjh21
841 1.1 bjh21 if (datain == KBR_EXTENDED0) {
842 1.29.20.1 tls id->t_extended0 = 0x80;
843 1.2 bjh21 return 0;
844 1.1 bjh21 } else if (datain == KBR_EXTENDED1) {
845 1.1 bjh21 id->t_extended1 = 2;
846 1.2 bjh21 return 0;
847 1.1 bjh21 }
848 1.1 bjh21
849 1.29.20.1 tls releasing = datain & 0x80;
850 1.29.20.1 tls datain &= 0x7f;
851 1.29.20.1 tls
852 1.29.20.1 tls if (id->t_extended0 == 0x80) {
853 1.29.20.1 tls switch (datain) {
854 1.27 jakllsch case 0x2a:
855 1.27 jakllsch case 0x36:
856 1.27 jakllsch id->t_extended0 = 0;
857 1.27 jakllsch return 0;
858 1.27 jakllsch default:
859 1.27 jakllsch break;
860 1.27 jakllsch }
861 1.27 jakllsch }
862 1.27 jakllsch
863 1.29.20.1 tls /* map extended keys to (unused) codes 128-254 */
864 1.29.20.1 tls key = datain | id->t_extended0;
865 1.1 bjh21 id->t_extended0 = 0;
866 1.1 bjh21
867 1.1 bjh21 /*
868 1.1 bjh21 * process PAUSE (also break) key (EXT1 1D 45 EXT1 9D C5):
869 1.1 bjh21 * map to (unused) code 7F
870 1.1 bjh21 */
871 1.1 bjh21 if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
872 1.1 bjh21 id->t_extended1 = 1;
873 1.2 bjh21 return 0;
874 1.1 bjh21 } else if (id->t_extended1 == 1 &&
875 1.1 bjh21 (datain == 0x45 || datain == 0xc5)) {
876 1.1 bjh21 id->t_extended1 = 0;
877 1.1 bjh21 key = 0x7f;
878 1.1 bjh21 } else if (id->t_extended1 > 0) {
879 1.1 bjh21 id->t_extended1 = 0;
880 1.1 bjh21 }
881 1.1 bjh21
882 1.29.20.1 tls if (id->t_translating != 0) {
883 1.29.20.1 tls id->t_releasing = releasing;
884 1.29.20.1 tls } else {
885 1.29.20.1 tls /* id->t_releasing computed in pckbd_scancode_translate() */
886 1.29.20.1 tls }
887 1.29.20.1 tls
888 1.29.20.1 tls if (id->t_releasing) {
889 1.29.20.1 tls id->t_releasing = 0;
890 1.1 bjh21 id->t_lastchar = 0;
891 1.1 bjh21 *type = WSCONS_EVENT_KEY_UP;
892 1.1 bjh21 } else {
893 1.1 bjh21 /* Always ignore typematic keys */
894 1.1 bjh21 if (key == id->t_lastchar)
895 1.2 bjh21 return 0;
896 1.1 bjh21 id->t_lastchar = key;
897 1.1 bjh21 *type = WSCONS_EVENT_KEY_DOWN;
898 1.1 bjh21 }
899 1.1 bjh21
900 1.1 bjh21 *dataout = key;
901 1.2 bjh21 return 1;
902 1.1 bjh21 }
903 1.1 bjh21
904 1.1 bjh21 int
905 1.2 bjh21 pckbd_init(struct pckbd_internal *t, pckbport_tag_t kbctag,
906 1.2 bjh21 pckbport_slot_t kbcslot, int console)
907 1.1 bjh21 {
908 1.2 bjh21
909 1.1 bjh21 memset(t, 0, sizeof(struct pckbd_internal));
910 1.1 bjh21
911 1.1 bjh21 t->t_isconsole = console;
912 1.1 bjh21 t->t_kbctag = kbctag;
913 1.1 bjh21 t->t_kbcslot = kbcslot;
914 1.1 bjh21
915 1.29.20.1 tls return pckbd_set_xtscancode(kbctag, kbcslot, t);
916 1.1 bjh21 }
917 1.1 bjh21
918 1.1 bjh21 static int
919 1.2 bjh21 pckbd_led_encode(int led)
920 1.1 bjh21 {
921 1.1 bjh21 int res;
922 1.1 bjh21
923 1.1 bjh21 res = 0;
924 1.1 bjh21
925 1.1 bjh21 if (led & WSKBD_LED_SCROLL)
926 1.1 bjh21 res |= 0x01;
927 1.1 bjh21 if (led & WSKBD_LED_NUM)
928 1.1 bjh21 res |= 0x02;
929 1.1 bjh21 if (led & WSKBD_LED_CAPS)
930 1.1 bjh21 res |= 0x04;
931 1.2 bjh21 return res;
932 1.1 bjh21 }
933 1.1 bjh21
934 1.1 bjh21 static int
935 1.2 bjh21 pckbd_led_decode(int led)
936 1.1 bjh21 {
937 1.1 bjh21 int res;
938 1.1 bjh21
939 1.1 bjh21 res = 0;
940 1.1 bjh21 if (led & 0x01)
941 1.1 bjh21 res |= WSKBD_LED_SCROLL;
942 1.1 bjh21 if (led & 0x02)
943 1.1 bjh21 res |= WSKBD_LED_NUM;
944 1.1 bjh21 if (led & 0x04)
945 1.1 bjh21 res |= WSKBD_LED_CAPS;
946 1.2 bjh21 return res;
947 1.1 bjh21 }
948 1.1 bjh21
949 1.1 bjh21 void
950 1.2 bjh21 pckbd_set_leds(void *v, int leds)
951 1.1 bjh21 {
952 1.1 bjh21 struct pckbd_softc *sc = v;
953 1.1 bjh21 u_char cmd[2];
954 1.1 bjh21
955 1.1 bjh21 cmd[0] = KBC_MODEIND;
956 1.1 bjh21 cmd[1] = pckbd_led_encode(leds);
957 1.1 bjh21 sc->sc_ledstate = cmd[1];
958 1.1 bjh21
959 1.2 bjh21 (void)pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
960 1.1 bjh21 cmd, 2, 0, 0, 0);
961 1.1 bjh21 }
962 1.1 bjh21
963 1.1 bjh21 /*
964 1.1 bjh21 * Got a console receive interrupt -
965 1.1 bjh21 * the console processor wants to give us a character.
966 1.1 bjh21 */
967 1.1 bjh21 void
968 1.2 bjh21 pckbd_input(void *vsc, int data)
969 1.1 bjh21 {
970 1.1 bjh21 struct pckbd_softc *sc = vsc;
971 1.1 bjh21 int key;
972 1.1 bjh21 u_int type;
973 1.1 bjh21
974 1.29.20.1 tls data = pckbd_scancode_translate(sc->id, data);
975 1.29.20.1 tls if (data == 0)
976 1.29.20.1 tls return;
977 1.29.20.1 tls
978 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
979 1.1 bjh21 if (sc->rawkbd) {
980 1.1 bjh21 u_char d = data;
981 1.1 bjh21 wskbd_rawinput(sc->sc_wskbddev, &d, 1);
982 1.1 bjh21 return;
983 1.1 bjh21 }
984 1.1 bjh21 #endif
985 1.1 bjh21 if (pckbd_decode(sc->id, data, &type, &key))
986 1.1 bjh21 wskbd_input(sc->sc_wskbddev, type, key);
987 1.1 bjh21 }
988 1.1 bjh21
989 1.1 bjh21 int
990 1.15 christos pckbd_ioctl(void *v, u_long cmd, void *data, int flag,
991 1.14 christos struct lwp *l)
992 1.1 bjh21 {
993 1.1 bjh21 struct pckbd_softc *sc = v;
994 1.1 bjh21
995 1.1 bjh21 switch (cmd) {
996 1.2 bjh21 case WSKBDIO_GTYPE:
997 1.1 bjh21 *(int *)data = WSKBD_TYPE_PC_XT;
998 1.1 bjh21 return 0;
999 1.2 bjh21 case WSKBDIO_SETLEDS:
1000 1.2 bjh21 {
1001 1.2 bjh21 int res;
1002 1.8 christos u_char cmdb[2];
1003 1.2 bjh21
1004 1.8 christos cmdb[0] = KBC_MODEIND;
1005 1.8 christos cmdb[1] = pckbd_led_encode(*(int *)data);
1006 1.8 christos sc->sc_ledstate = cmdb[1];
1007 1.1 bjh21 res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
1008 1.8 christos cmdb, 2, 0, 1, 0);
1009 1.2 bjh21 return res;
1010 1.2 bjh21 }
1011 1.2 bjh21 case WSKBDIO_GETLEDS:
1012 1.1 bjh21 *(int *)data = pckbd_led_decode(sc->sc_ledstate);
1013 1.2 bjh21 return 0;
1014 1.2 bjh21 case WSKBDIO_COMPLEXBELL:
1015 1.1 bjh21 #define d ((struct wskbd_bell_data *)data)
1016 1.1 bjh21 /*
1017 1.1 bjh21 * Keyboard can't beep directly; we have an
1018 1.1 bjh21 * externally-provided global hook to do this.
1019 1.1 bjh21 */
1020 1.1 bjh21 pckbd_bell(d->pitch, d->period, d->volume, 0);
1021 1.1 bjh21 #undef d
1022 1.2 bjh21 return 0;
1023 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
1024 1.2 bjh21 case WSKBDIO_SETMODE:
1025 1.1 bjh21 sc->rawkbd = (*(int *)data == WSKBD_RAW);
1026 1.2 bjh21 return 0;
1027 1.1 bjh21 #endif
1028 1.1 bjh21 }
1029 1.1 bjh21 return EPASSTHROUGH;
1030 1.1 bjh21 }
1031 1.1 bjh21
1032 1.1 bjh21 void
1033 1.2 bjh21 pckbd_bell(u_int pitch, u_int period, u_int volume, int poll)
1034 1.1 bjh21 {
1035 1.1 bjh21
1036 1.1 bjh21 if (pckbd_bell_fn != NULL)
1037 1.1 bjh21 (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
1038 1.1 bjh21 volume, poll);
1039 1.1 bjh21 }
1040 1.1 bjh21
1041 1.1 bjh21 void
1042 1.19 dyoung pckbd_unhook_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
1043 1.19 dyoung {
1044 1.19 dyoung if (pckbd_bell_fn != fn && pckbd_bell_fn_arg != arg)
1045 1.19 dyoung return;
1046 1.19 dyoung pckbd_bell_fn = NULL;
1047 1.19 dyoung pckbd_bell_fn_arg = NULL;
1048 1.19 dyoung }
1049 1.19 dyoung
1050 1.19 dyoung void
1051 1.2 bjh21 pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
1052 1.1 bjh21 {
1053 1.1 bjh21
1054 1.1 bjh21 if (pckbd_bell_fn == NULL) {
1055 1.1 bjh21 pckbd_bell_fn = fn;
1056 1.1 bjh21 pckbd_bell_fn_arg = arg;
1057 1.1 bjh21 }
1058 1.1 bjh21 }
1059 1.1 bjh21
1060 1.1 bjh21 int
1061 1.2 bjh21 pckbd_cnattach(pckbport_tag_t kbctag, int kbcslot)
1062 1.1 bjh21 {
1063 1.2 bjh21 int res;
1064 1.1 bjh21 u_char cmd[1];
1065 1.1 bjh21
1066 1.1 bjh21 res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1);
1067 1.7 augustss /* We may allow the console to be attached if no keyboard is present */
1068 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
1069 1.1 bjh21 if (res)
1070 1.2 bjh21 return res;
1071 1.1 bjh21 #endif
1072 1.1 bjh21
1073 1.1 bjh21 /* Just to be sure. */
1074 1.1 bjh21 cmd[0] = KBC_ENABLE;
1075 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0);
1076 1.1 bjh21
1077 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
1078 1.1 bjh21 if (res)
1079 1.2 bjh21 return res;
1080 1.1 bjh21 #endif
1081 1.1 bjh21
1082 1.1 bjh21 wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
1083 1.1 bjh21
1084 1.29.20.2 tls return res;
1085 1.1 bjh21 }
1086 1.1 bjh21
1087 1.1 bjh21 /* ARGSUSED */
1088 1.1 bjh21 void
1089 1.2 bjh21 pckbd_cngetc(void *v, u_int *type, int *data)
1090 1.1 bjh21 {
1091 1.1 bjh21 struct pckbd_internal *t = v;
1092 1.1 bjh21 int val;
1093 1.1 bjh21
1094 1.1 bjh21 for (;;) {
1095 1.1 bjh21 val = pckbport_poll_data(t->t_kbctag, t->t_kbcslot);
1096 1.29.20.1 tls if (val == -1)
1097 1.29.20.1 tls continue;
1098 1.29.20.1 tls
1099 1.29.20.1 tls val = pckbd_scancode_translate(t, val);
1100 1.29.20.1 tls if (val == 0)
1101 1.29.20.1 tls continue;
1102 1.29.20.1 tls
1103 1.29.20.1 tls if (pckbd_decode(t, val, type, data))
1104 1.1 bjh21 return;
1105 1.1 bjh21 }
1106 1.1 bjh21 }
1107 1.1 bjh21
1108 1.1 bjh21 void
1109 1.2 bjh21 pckbd_cnpollc(void *v, int on)
1110 1.1 bjh21 {
1111 1.1 bjh21 struct pckbd_internal *t = v;
1112 1.1 bjh21
1113 1.1 bjh21 pckbport_set_poll(t->t_kbctag, t->t_kbcslot, on);
1114 1.1 bjh21 }
1115 1.1 bjh21
1116 1.1 bjh21 void
1117 1.14 christos pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
1118 1.1 bjh21 {
1119 1.1 bjh21
1120 1.1 bjh21 pckbd_bell(pitch, period, volume, 1);
1121 1.1 bjh21 }
1122