pckbd.c revision 1.31 1 1.31 martin /* $NetBSD: pckbd.c,v 1.31 2013/09/15 09:24:05 martin 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.31 martin __KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.31 2013/09/15 09:24:05 martin 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.30 jdc int t_translating;
104 1.30 jdc
105 1.1 bjh21 int t_lastchar;
106 1.1 bjh21 int t_extended0;
107 1.1 bjh21 int t_extended1;
108 1.30 jdc 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.30 jdc int pckbd_scancode_translate(struct pckbd_internal *, int);
174 1.30 jdc int pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t,
175 1.30 jdc 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.30 jdc pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot,
188 1.30 jdc struct pckbd_internal *id)
189 1.1 bjh21 {
190 1.30 jdc 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.30 jdc * tough luck. If the PCKBC_CANT_TRANSLATE pckbc flag was set, we
202 1.30 jdc * 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.30 jdc xt = pckbport_xt_translation(kbctag, kbcslot, 1);
208 1.30 jdc 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.30 jdc if (id != NULL)
228 1.30 jdc id->t_translating = 1;
229 1.30 jdc } else if (xt == -1) {
230 1.30 jdc /* Software translation required */
231 1.30 jdc if (id != NULL)
232 1.30 jdc 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.30 jdc if (id != NULL)
241 1.30 jdc 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.30 jdc 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.30 jdc 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.30 jdc const u_int8_t pckbd_xtbl[] = {
466 1.30 jdc /* 0x00 */
467 1.30 jdc 0,
468 1.30 jdc 0x43, /* F9 */
469 1.30 jdc 0x89, /* SunStop */
470 1.30 jdc 0x3f, /* F5 */
471 1.30 jdc 0x3d, /* F3 */
472 1.30 jdc 0x3b, /* F1 */
473 1.30 jdc 0x3c, /* F2 */
474 1.30 jdc 0x58, /* F12 */
475 1.30 jdc 0,
476 1.30 jdc 0x44, /* F10 */
477 1.30 jdc 0x42, /* F8 */
478 1.30 jdc 0x40, /* F6 */
479 1.30 jdc 0x3e, /* F4 */
480 1.30 jdc 0x0f, /* Tab */
481 1.30 jdc 0x29, /* ` ~ */
482 1.30 jdc 0,
483 1.30 jdc /* 0x10 */
484 1.30 jdc 0,
485 1.30 jdc 0x38, /* Left Alt */
486 1.30 jdc 0x2a, /* Left Shift */
487 1.30 jdc 0,
488 1.30 jdc 0x1d, /* Left Ctrl */
489 1.30 jdc 0x10, /* q */
490 1.30 jdc 0x02, /* 1 ! */
491 1.30 jdc 0,
492 1.30 jdc 0,
493 1.30 jdc 0,
494 1.30 jdc 0x2c, /* z */
495 1.30 jdc 0x1f, /* s */
496 1.30 jdc 0x1e, /* a */
497 1.30 jdc 0x11, /* w */
498 1.30 jdc 0x03, /* 2 @ */
499 1.30 jdc 0,
500 1.30 jdc /* 0x20 */
501 1.30 jdc 0,
502 1.30 jdc 0x2e, /* c */
503 1.30 jdc 0x2d, /* x */
504 1.30 jdc 0x20, /* d */
505 1.30 jdc 0x12, /* e */
506 1.30 jdc 0x05, /* 4 $ */
507 1.30 jdc 0x04, /* 3 # */
508 1.30 jdc 0,
509 1.30 jdc 0,
510 1.30 jdc 0x39, /* Space */
511 1.30 jdc 0x2f, /* v */
512 1.30 jdc 0x21, /* f */
513 1.30 jdc 0x14, /* t */
514 1.30 jdc 0x13, /* r */
515 1.30 jdc 0x06, /* 5 % */
516 1.30 jdc 0,
517 1.30 jdc /* 0x30 */
518 1.30 jdc 0,
519 1.30 jdc 0x31, /* n */
520 1.30 jdc 0x30, /* b */
521 1.30 jdc 0x23, /* h */
522 1.30 jdc 0x22, /* g */
523 1.30 jdc 0x15, /* y */
524 1.30 jdc 0x07, /* 6 ^ */
525 1.30 jdc 0,
526 1.30 jdc 0,
527 1.30 jdc 0,
528 1.30 jdc 0x32, /* m */
529 1.30 jdc 0x24, /* j */
530 1.30 jdc 0x16, /* u */
531 1.30 jdc 0x08, /* 7 & */
532 1.30 jdc 0x09, /* 8 * */
533 1.30 jdc 0,
534 1.30 jdc /* 0x40 */
535 1.30 jdc 0,
536 1.30 jdc 0x33, /* , < */
537 1.30 jdc 0x25, /* k */
538 1.30 jdc 0x17, /* i */
539 1.30 jdc 0x18, /* o */
540 1.30 jdc 0x0b, /* 0 ) */
541 1.30 jdc 0x0a, /* 9 ( */
542 1.30 jdc 0,
543 1.30 jdc 0,
544 1.30 jdc 0x34, /* . > */
545 1.30 jdc 0x35, /* / ? */
546 1.30 jdc 0x26, /* l */
547 1.30 jdc 0x27, /* ; : */
548 1.30 jdc 0x19, /* p */
549 1.30 jdc 0x0c, /* - _ */
550 1.30 jdc 0,
551 1.30 jdc /* 0x50 */
552 1.30 jdc 0,
553 1.30 jdc 0,
554 1.30 jdc 0x28, /* ' " */
555 1.30 jdc 0,
556 1.30 jdc 0x1a, /* [ { */
557 1.30 jdc 0x0d, /* = + */
558 1.30 jdc 0,
559 1.30 jdc 0,
560 1.30 jdc 0x3a, /* Caps Lock */
561 1.30 jdc 0x36, /* Right Shift */
562 1.30 jdc 0x1c, /* Return */
563 1.30 jdc 0x1b, /* ] } */
564 1.30 jdc 0,
565 1.30 jdc 0x2b, /* \ | */
566 1.30 jdc 0,
567 1.30 jdc 0,
568 1.30 jdc /* 0x60 */
569 1.30 jdc 0,
570 1.30 jdc 0,
571 1.30 jdc 0,
572 1.30 jdc 0,
573 1.30 jdc 0,
574 1.30 jdc 0,
575 1.30 jdc 0x0e, /* Back Space */
576 1.30 jdc 0,
577 1.30 jdc 0,
578 1.30 jdc 0x4f, /* KP 1 */
579 1.30 jdc 0,
580 1.30 jdc 0x4b, /* KP 4 */
581 1.30 jdc 0x47, /* KP 7 */
582 1.30 jdc 0,
583 1.30 jdc 0,
584 1.30 jdc 0,
585 1.30 jdc /* 0x70 */
586 1.30 jdc 0x52, /* KP 0 */
587 1.30 jdc 0x53, /* KP . */
588 1.30 jdc 0x50, /* KP 2 */
589 1.30 jdc 0x4c, /* KP 5 */
590 1.30 jdc 0x4d, /* KP 6 */
591 1.30 jdc 0x48, /* KP 8 */
592 1.30 jdc 0x01, /* Escape */
593 1.30 jdc 0x45, /* Num Lock */
594 1.30 jdc 0x57, /* F11 */
595 1.30 jdc 0x4e, /* KP + */
596 1.30 jdc 0x51, /* KP 3 */
597 1.30 jdc 0x4a, /* KP - */
598 1.30 jdc 0x37, /* KP * */
599 1.30 jdc 0x49, /* KP 9 */
600 1.30 jdc 0x46, /* Scroll Lock */
601 1.30 jdc 0,
602 1.30 jdc /* 0x80 */
603 1.30 jdc 0,
604 1.30 jdc 0,
605 1.30 jdc 0,
606 1.30 jdc 0x41, /* F7 (produced as an actual 8 bit code) */
607 1.30 jdc 0, /* Alt-Print Screen */
608 1.30 jdc 0,
609 1.30 jdc 0,
610 1.30 jdc 0,
611 1.30 jdc 0,
612 1.30 jdc 0,
613 1.30 jdc 0,
614 1.30 jdc 0,
615 1.30 jdc 0,
616 1.30 jdc 0,
617 1.30 jdc 0,
618 1.30 jdc 0,
619 1.30 jdc /* 0x90 */
620 1.30 jdc 0xdb, /* Left Meta */
621 1.30 jdc 0x88, /* SunHelp */
622 1.30 jdc 0x8a, /* SunAgain */
623 1.30 jdc 0x8c, /* SunUndo */
624 1.30 jdc 0x8e, /* SunCopy */
625 1.30 jdc 0x90, /* SunPaste */
626 1.30 jdc 0x92, /* SunCut */
627 1.30 jdc 0x8b, /* SunProps */
628 1.30 jdc 0x8d, /* SunFront */
629 1.30 jdc 0x8f, /* SunOpen */
630 1.30 jdc 0x91 /* SunFind */
631 1.30 jdc };
632 1.30 jdc
633 1.30 jdc const u_int8_t pckbd_xtbl_ext[] = {
634 1.30 jdc /* 0x00 */
635 1.30 jdc 0,
636 1.30 jdc 0,
637 1.30 jdc 0,
638 1.30 jdc 0,
639 1.30 jdc 0,
640 1.30 jdc 0,
641 1.30 jdc 0,
642 1.30 jdc 0,
643 1.30 jdc 0,
644 1.30 jdc 0,
645 1.30 jdc 0,
646 1.30 jdc 0,
647 1.30 jdc 0,
648 1.30 jdc 0,
649 1.30 jdc 0,
650 1.30 jdc 0,
651 1.30 jdc /* 0x10 */
652 1.30 jdc 0,
653 1.30 jdc 0x38, /* Right Alt */
654 1.30 jdc 0, /* E0 12, to be ignored */
655 1.30 jdc 0,
656 1.30 jdc 0x1d, /* Right Ctrl */
657 1.30 jdc 0,
658 1.30 jdc 0,
659 1.30 jdc 0,
660 1.30 jdc 0,
661 1.30 jdc 0,
662 1.30 jdc 0,
663 1.30 jdc 0,
664 1.30 jdc 0,
665 1.30 jdc 0,
666 1.30 jdc 0,
667 1.30 jdc 0,
668 1.30 jdc /* 0x20 */
669 1.30 jdc 0,
670 1.30 jdc 0,
671 1.30 jdc 0,
672 1.30 jdc 0,
673 1.30 jdc 0,
674 1.30 jdc 0,
675 1.30 jdc 0,
676 1.30 jdc 0,
677 1.30 jdc 0,
678 1.30 jdc 0,
679 1.30 jdc 0,
680 1.30 jdc 0,
681 1.30 jdc 0,
682 1.30 jdc 0,
683 1.30 jdc 0,
684 1.30 jdc 0xdd, /* Compose */
685 1.30 jdc /* 0x30 */
686 1.30 jdc 0,
687 1.30 jdc 0,
688 1.30 jdc 0,
689 1.30 jdc 0,
690 1.30 jdc 0,
691 1.30 jdc 0,
692 1.30 jdc 0,
693 1.30 jdc 0,
694 1.30 jdc 0,
695 1.30 jdc 0,
696 1.30 jdc 0,
697 1.30 jdc 0,
698 1.30 jdc 0,
699 1.30 jdc 0,
700 1.30 jdc 0,
701 1.30 jdc 0,
702 1.30 jdc /* 0x40 */
703 1.30 jdc 0,
704 1.30 jdc 0,
705 1.30 jdc 0,
706 1.30 jdc 0,
707 1.30 jdc 0,
708 1.30 jdc 0,
709 1.30 jdc 0,
710 1.30 jdc 0,
711 1.30 jdc 0,
712 1.30 jdc 0,
713 1.30 jdc 0xb5, /* KP / */
714 1.30 jdc 0,
715 1.30 jdc 0,
716 1.30 jdc 0,
717 1.30 jdc 0,
718 1.30 jdc 0,
719 1.30 jdc /* 0x50 */
720 1.30 jdc 0,
721 1.30 jdc 0,
722 1.30 jdc 0,
723 1.30 jdc 0,
724 1.30 jdc 0,
725 1.30 jdc 0,
726 1.30 jdc 0,
727 1.30 jdc 0,
728 1.30 jdc 0,
729 1.30 jdc 0,
730 1.30 jdc 0x1c, /* KP Return */
731 1.30 jdc 0,
732 1.30 jdc 0,
733 1.30 jdc 0,
734 1.30 jdc 0,
735 1.30 jdc 0,
736 1.30 jdc /* 0x60 */
737 1.30 jdc 0,
738 1.30 jdc 0,
739 1.30 jdc 0,
740 1.30 jdc 0,
741 1.30 jdc 0,
742 1.30 jdc 0,
743 1.30 jdc 0,
744 1.30 jdc 0,
745 1.30 jdc 0,
746 1.30 jdc 0x4f, /* End */
747 1.30 jdc 0,
748 1.30 jdc 0x4b, /* Left */
749 1.30 jdc 0x47, /* Home */
750 1.30 jdc 0,
751 1.30 jdc 0,
752 1.30 jdc 0,
753 1.30 jdc /* 0x70 */
754 1.30 jdc 0x52, /* Insert */
755 1.30 jdc 0x53, /* Delete */
756 1.30 jdc 0x50, /* Down */
757 1.30 jdc 0,
758 1.30 jdc 0x4d, /* Right */
759 1.30 jdc 0x48, /* Up */
760 1.30 jdc 0,
761 1.30 jdc 0,
762 1.30 jdc 0,
763 1.30 jdc 0,
764 1.30 jdc 0x51, /* Page Down */
765 1.30 jdc 0,
766 1.30 jdc 0x37, /* Print Screen */
767 1.30 jdc 0x49, /* Page Up */
768 1.30 jdc 0x46, /* Ctrl-Break */
769 1.30 jdc 0
770 1.30 jdc };
771 1.30 jdc
772 1.30 jdc /*
773 1.30 jdc * Translate scan codes from set 2 to set 1
774 1.30 jdc */
775 1.30 jdc int
776 1.30 jdc pckbd_scancode_translate(struct pckbd_internal *id, int datain)
777 1.30 jdc {
778 1.30 jdc if (id->t_translating != 0)
779 1.30 jdc return datain;
780 1.30 jdc
781 1.30 jdc if (datain == KBR_BREAK) {
782 1.30 jdc id->t_releasing = 0x80; /* next keycode is a release */
783 1.30 jdc return 0; /* consume scancode */
784 1.30 jdc }
785 1.30 jdc
786 1.30 jdc /*
787 1.30 jdc * Handle extended sequences
788 1.30 jdc */
789 1.30 jdc if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1)
790 1.30 jdc return datain;
791 1.30 jdc
792 1.30 jdc /*
793 1.30 jdc * Convert BREAK sequence (14 77 -> 1D 45)
794 1.30 jdc */
795 1.30 jdc if (id->t_extended1 == 2 && datain == 0x14)
796 1.30 jdc return 0x1d | id->t_releasing;
797 1.30 jdc else if (id->t_extended1 == 1 && datain == 0x77)
798 1.30 jdc return 0x45 | id->t_releasing;
799 1.30 jdc
800 1.30 jdc if (id->t_extended0 != 0) {
801 1.30 jdc if (datain >= sizeof pckbd_xtbl_ext)
802 1.30 jdc datain = 0;
803 1.30 jdc else
804 1.30 jdc datain = pckbd_xtbl_ext[datain];
805 1.30 jdc } else {
806 1.30 jdc if (datain >= sizeof pckbd_xtbl)
807 1.30 jdc datain = 0;
808 1.30 jdc else
809 1.30 jdc datain = pckbd_xtbl[datain];
810 1.30 jdc }
811 1.30 jdc
812 1.30 jdc /*
813 1.30 jdc * If we are mapping in the range 128-254, then make this
814 1.30 jdc * an extended keycode, as table 1 codes are limited to
815 1.30 jdc * the range 0-127 (the top bit is used for key up/break).
816 1.30 jdc */
817 1.30 jdc if (datain > 0x7f) {
818 1.30 jdc datain &= 0x7f;
819 1.30 jdc id->t_extended0 = 0x80;
820 1.30 jdc }
821 1.30 jdc
822 1.30 jdc if (datain == 0) {
823 1.30 jdc /*
824 1.30 jdc * We don't know how to translate this scan code, but
825 1.30 jdc * we can't silently eat it either (because there might
826 1.30 jdc * have been an extended byte transmitted already).
827 1.30 jdc * Hopefully this value will be harmless to the upper
828 1.30 jdc * layers.
829 1.30 jdc */
830 1.30 jdc return 0xff;
831 1.30 jdc }
832 1.30 jdc return datain | id->t_releasing;
833 1.30 jdc }
834 1.30 jdc
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.30 jdc int releasing;
840 1.1 bjh21
841 1.1 bjh21 if (datain == KBR_EXTENDED0) {
842 1.30 jdc 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.30 jdc releasing = datain & 0x80;
850 1.30 jdc datain &= 0x7f;
851 1.30 jdc
852 1.30 jdc if (id->t_extended0 == 0x80) {
853 1.30 jdc 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.30 jdc /* map extended keys to (unused) codes 128-254 */
864 1.30 jdc 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.30 jdc if (id->t_translating != 0) {
883 1.30 jdc id->t_releasing = releasing;
884 1.30 jdc } else {
885 1.30 jdc /* id->t_releasing computed in pckbd_scancode_translate() */
886 1.30 jdc }
887 1.30 jdc
888 1.30 jdc if (id->t_releasing) {
889 1.30 jdc 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.30 jdc 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.30 jdc data = pckbd_scancode_translate(sc->id, data);
975 1.30 jdc if (data == 0)
976 1.30 jdc return;
977 1.30 jdc
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.31 martin 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.30 jdc if (val == -1)
1097 1.30 jdc continue;
1098 1.30 jdc
1099 1.30 jdc val = pckbd_scancode_translate(t, val);
1100 1.30 jdc if (val == 0)
1101 1.30 jdc continue;
1102 1.30 jdc
1103 1.30 jdc 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