pckbd.c revision 1.36 1 1.36 thorpej /* $NetBSD: pckbd.c,v 1.36 2021/08/07 16:19:15 thorpej 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.36 thorpej __KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.36 2021/08/07 16:19:15 thorpej 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.32 prlw1 aprint_debug("%s: reset error %d\n", __func__, res);
292 1.18 jmcneill if (resp[0] != KBR_RSTDONE)
293 1.32 prlw1 printf("%s: reset response 0x%x\n", __func__, resp[0]);
294 1.11 christos
295 1.18 jmcneill pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot);
296 1.11 christos
297 1.18 jmcneill pckbd_enable(sc, 1);
298 1.11 christos
299 1.18 jmcneill return true;
300 1.11 christos }
301 1.11 christos
302 1.1 bjh21 /*
303 1.1 bjh21 * these are both bad jokes
304 1.1 bjh21 */
305 1.1 bjh21 int
306 1.23 cube pckbdprobe(device_t parent, cfdata_t cf, void *aux)
307 1.1 bjh21 {
308 1.1 bjh21 struct pckbport_attach_args *pa = aux;
309 1.2 bjh21 int res;
310 1.1 bjh21 u_char cmd[1], resp[1];
311 1.1 bjh21
312 1.1 bjh21 /*
313 1.1 bjh21 * XXX There are rumours that a keyboard can be connected
314 1.1 bjh21 * to the aux port as well. For me, this didn't work.
315 1.1 bjh21 * For further experiments, allow it if explicitly
316 1.1 bjh21 * wired in the config file.
317 1.1 bjh21 */
318 1.1 bjh21 if ((pa->pa_slot != PCKBPORT_KBD_SLOT) &&
319 1.1 bjh21 (cf->cf_loc[PCKBPORTCF_SLOT] == PCKBPORTCF_SLOT_DEFAULT))
320 1.2 bjh21 return 0;
321 1.1 bjh21
322 1.1 bjh21 /* Flush any garbage. */
323 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot);
324 1.1 bjh21
325 1.1 bjh21 /* Reset the keyboard. */
326 1.1 bjh21 cmd[0] = KBC_RESET;
327 1.1 bjh21 res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1);
328 1.1 bjh21 if (res) {
329 1.26 ad aprint_debug("pckbdprobe: reset error %d\n", res);
330 1.1 bjh21 /*
331 1.1 bjh21 * There is probably no keyboard connected.
332 1.1 bjh21 * Let the probe succeed if the keyboard is used
333 1.1 bjh21 * as console input - it can be connected later.
334 1.1 bjh21 */
335 1.2 bjh21 return pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0;
336 1.1 bjh21 }
337 1.1 bjh21 if (resp[0] != KBR_RSTDONE) {
338 1.1 bjh21 printf("pckbdprobe: reset response 0x%x\n", resp[0]);
339 1.2 bjh21 return 0;
340 1.1 bjh21 }
341 1.1 bjh21
342 1.1 bjh21 /*
343 1.1 bjh21 * Some keyboards seem to leave a second ack byte after the reset.
344 1.1 bjh21 * This is kind of stupid, but we account for them anyway by just
345 1.1 bjh21 * flushing the buffer.
346 1.1 bjh21 */
347 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot);
348 1.1 bjh21
349 1.30 jdc if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL))
350 1.2 bjh21 return 0;
351 1.1 bjh21
352 1.2 bjh21 return 2;
353 1.1 bjh21 }
354 1.1 bjh21
355 1.1 bjh21 void
356 1.23 cube pckbdattach(device_t parent, device_t self, void *aux)
357 1.1 bjh21 {
358 1.10 thorpej struct pckbd_softc *sc = device_private(self);
359 1.1 bjh21 struct pckbport_attach_args *pa = aux;
360 1.2 bjh21 struct wskbddev_attach_args a;
361 1.1 bjh21 int isconsole;
362 1.1 bjh21 u_char cmd[1];
363 1.1 bjh21
364 1.17 jmcneill aprint_naive("\n");
365 1.17 jmcneill aprint_normal("\n");
366 1.1 bjh21
367 1.22 cube sc->sc_dev = self;
368 1.1 bjh21 isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot);
369 1.1 bjh21
370 1.1 bjh21 if (isconsole) {
371 1.1 bjh21 sc->id = &pckbd_consdata;
372 1.1 bjh21
373 1.3 perry /*
374 1.3 perry * Some keyboards are not enabled after a reset,
375 1.1 bjh21 * so make sure it is enabled now.
376 1.1 bjh21 */
377 1.1 bjh21 cmd[0] = KBC_ENABLE;
378 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
379 1.1 bjh21 cmd, 1, 0, 0, 0);
380 1.1 bjh21 sc->sc_enabled = 1;
381 1.1 bjh21 } else {
382 1.1 bjh21 sc->id = malloc(sizeof(struct pckbd_internal),
383 1.1 bjh21 M_DEVBUF, M_WAITOK);
384 1.1 bjh21 (void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0);
385 1.1 bjh21
386 1.1 bjh21 /* no interrupts until enabled */
387 1.1 bjh21 cmd[0] = KBC_DISABLE;
388 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
389 1.1 bjh21 cmd, 1, 0, 0, 0);
390 1.1 bjh21 sc->sc_enabled = 0;
391 1.1 bjh21 }
392 1.1 bjh21
393 1.1 bjh21 sc->id->t_sc = sc;
394 1.1 bjh21
395 1.1 bjh21 pckbport_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot,
396 1.22 cube pckbd_input, sc, device_xname(sc->sc_dev));
397 1.1 bjh21
398 1.1 bjh21 a.console = isconsole;
399 1.1 bjh21
400 1.1 bjh21 a.keymap = &pckbd_keymapdata;
401 1.1 bjh21
402 1.1 bjh21 a.accessops = &pckbd_accessops;
403 1.1 bjh21 a.accesscookie = sc;
404 1.1 bjh21
405 1.18 jmcneill if (!pmf_device_register(self, pckbd_suspend, pckbd_resume))
406 1.18 jmcneill aprint_error_dev(self, "couldn't establish power handler\n");
407 1.11 christos
408 1.1 bjh21 /*
409 1.1 bjh21 * Attach the wskbd, saving a handle to it.
410 1.1 bjh21 * XXX XXX XXX
411 1.1 bjh21 */
412 1.36 thorpej sc->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE);
413 1.1 bjh21 }
414 1.1 bjh21
415 1.1 bjh21 int
416 1.2 bjh21 pckbd_enable(void *v, int on)
417 1.1 bjh21 {
418 1.1 bjh21 struct pckbd_softc *sc = v;
419 1.2 bjh21 int res;
420 1.1 bjh21 u_char cmd[1];
421 1.1 bjh21
422 1.1 bjh21 if (on) {
423 1.1 bjh21 if (sc->sc_enabled) {
424 1.26 ad aprint_debug("pckbd_enable: bad enable\n");
425 1.2 bjh21 return EBUSY;
426 1.1 bjh21 }
427 1.1 bjh21
428 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1);
429 1.1 bjh21
430 1.1 bjh21 cmd[0] = KBC_ENABLE;
431 1.1 bjh21 res = pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
432 1.1 bjh21 cmd, 1, 0, NULL, 0);
433 1.1 bjh21 if (res) {
434 1.1 bjh21 printf("pckbd_enable: command error\n");
435 1.1 bjh21 return (res);
436 1.1 bjh21 }
437 1.1 bjh21
438 1.1 bjh21 res = pckbd_set_xtscancode(sc->id->t_kbctag,
439 1.30 jdc sc->id->t_kbcslot, sc->id);
440 1.1 bjh21 if (res)
441 1.2 bjh21 return res;
442 1.1 bjh21
443 1.1 bjh21 sc->sc_enabled = 1;
444 1.1 bjh21 } else {
445 1.1 bjh21 if (sc->id->t_isconsole)
446 1.2 bjh21 return EBUSY;
447 1.1 bjh21
448 1.1 bjh21 cmd[0] = KBC_DISABLE;
449 1.1 bjh21 res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
450 1.1 bjh21 cmd, 1, 0, 1, 0);
451 1.1 bjh21 if (res) {
452 1.1 bjh21 printf("pckbd_disable: command error\n");
453 1.2 bjh21 return res;
454 1.1 bjh21 }
455 1.1 bjh21
456 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0);
457 1.1 bjh21
458 1.1 bjh21 sc->sc_enabled = 0;
459 1.1 bjh21 }
460 1.1 bjh21
461 1.2 bjh21 return 0;
462 1.1 bjh21 }
463 1.1 bjh21
464 1.30 jdc const u_int8_t pckbd_xtbl[] = {
465 1.30 jdc /* 0x00 */
466 1.30 jdc 0,
467 1.30 jdc 0x43, /* F9 */
468 1.30 jdc 0x89, /* SunStop */
469 1.30 jdc 0x3f, /* F5 */
470 1.30 jdc 0x3d, /* F3 */
471 1.30 jdc 0x3b, /* F1 */
472 1.30 jdc 0x3c, /* F2 */
473 1.30 jdc 0x58, /* F12 */
474 1.30 jdc 0,
475 1.30 jdc 0x44, /* F10 */
476 1.30 jdc 0x42, /* F8 */
477 1.30 jdc 0x40, /* F6 */
478 1.30 jdc 0x3e, /* F4 */
479 1.30 jdc 0x0f, /* Tab */
480 1.30 jdc 0x29, /* ` ~ */
481 1.30 jdc 0,
482 1.30 jdc /* 0x10 */
483 1.30 jdc 0,
484 1.30 jdc 0x38, /* Left Alt */
485 1.30 jdc 0x2a, /* Left Shift */
486 1.30 jdc 0,
487 1.30 jdc 0x1d, /* Left Ctrl */
488 1.30 jdc 0x10, /* q */
489 1.30 jdc 0x02, /* 1 ! */
490 1.30 jdc 0,
491 1.30 jdc 0,
492 1.30 jdc 0,
493 1.30 jdc 0x2c, /* z */
494 1.30 jdc 0x1f, /* s */
495 1.30 jdc 0x1e, /* a */
496 1.30 jdc 0x11, /* w */
497 1.30 jdc 0x03, /* 2 @ */
498 1.30 jdc 0,
499 1.30 jdc /* 0x20 */
500 1.30 jdc 0,
501 1.30 jdc 0x2e, /* c */
502 1.30 jdc 0x2d, /* x */
503 1.30 jdc 0x20, /* d */
504 1.30 jdc 0x12, /* e */
505 1.30 jdc 0x05, /* 4 $ */
506 1.30 jdc 0x04, /* 3 # */
507 1.30 jdc 0,
508 1.30 jdc 0,
509 1.30 jdc 0x39, /* Space */
510 1.30 jdc 0x2f, /* v */
511 1.30 jdc 0x21, /* f */
512 1.30 jdc 0x14, /* t */
513 1.30 jdc 0x13, /* r */
514 1.30 jdc 0x06, /* 5 % */
515 1.30 jdc 0,
516 1.30 jdc /* 0x30 */
517 1.30 jdc 0,
518 1.30 jdc 0x31, /* n */
519 1.30 jdc 0x30, /* b */
520 1.30 jdc 0x23, /* h */
521 1.30 jdc 0x22, /* g */
522 1.30 jdc 0x15, /* y */
523 1.30 jdc 0x07, /* 6 ^ */
524 1.30 jdc 0,
525 1.30 jdc 0,
526 1.30 jdc 0,
527 1.30 jdc 0x32, /* m */
528 1.30 jdc 0x24, /* j */
529 1.30 jdc 0x16, /* u */
530 1.30 jdc 0x08, /* 7 & */
531 1.30 jdc 0x09, /* 8 * */
532 1.30 jdc 0,
533 1.30 jdc /* 0x40 */
534 1.30 jdc 0,
535 1.30 jdc 0x33, /* , < */
536 1.30 jdc 0x25, /* k */
537 1.30 jdc 0x17, /* i */
538 1.30 jdc 0x18, /* o */
539 1.30 jdc 0x0b, /* 0 ) */
540 1.30 jdc 0x0a, /* 9 ( */
541 1.30 jdc 0,
542 1.30 jdc 0,
543 1.30 jdc 0x34, /* . > */
544 1.30 jdc 0x35, /* / ? */
545 1.30 jdc 0x26, /* l */
546 1.30 jdc 0x27, /* ; : */
547 1.30 jdc 0x19, /* p */
548 1.30 jdc 0x0c, /* - _ */
549 1.30 jdc 0,
550 1.30 jdc /* 0x50 */
551 1.30 jdc 0,
552 1.30 jdc 0,
553 1.30 jdc 0x28, /* ' " */
554 1.30 jdc 0,
555 1.30 jdc 0x1a, /* [ { */
556 1.30 jdc 0x0d, /* = + */
557 1.30 jdc 0,
558 1.30 jdc 0,
559 1.30 jdc 0x3a, /* Caps Lock */
560 1.30 jdc 0x36, /* Right Shift */
561 1.30 jdc 0x1c, /* Return */
562 1.30 jdc 0x1b, /* ] } */
563 1.30 jdc 0,
564 1.30 jdc 0x2b, /* \ | */
565 1.30 jdc 0,
566 1.30 jdc 0,
567 1.30 jdc /* 0x60 */
568 1.30 jdc 0,
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 0x0e, /* Back Space */
575 1.30 jdc 0,
576 1.30 jdc 0,
577 1.30 jdc 0x4f, /* KP 1 */
578 1.30 jdc 0,
579 1.30 jdc 0x4b, /* KP 4 */
580 1.30 jdc 0x47, /* KP 7 */
581 1.30 jdc 0,
582 1.30 jdc 0,
583 1.30 jdc 0,
584 1.30 jdc /* 0x70 */
585 1.30 jdc 0x52, /* KP 0 */
586 1.30 jdc 0x53, /* KP . */
587 1.30 jdc 0x50, /* KP 2 */
588 1.30 jdc 0x4c, /* KP 5 */
589 1.30 jdc 0x4d, /* KP 6 */
590 1.30 jdc 0x48, /* KP 8 */
591 1.30 jdc 0x01, /* Escape */
592 1.30 jdc 0x45, /* Num Lock */
593 1.30 jdc 0x57, /* F11 */
594 1.30 jdc 0x4e, /* KP + */
595 1.30 jdc 0x51, /* KP 3 */
596 1.30 jdc 0x4a, /* KP - */
597 1.30 jdc 0x37, /* KP * */
598 1.30 jdc 0x49, /* KP 9 */
599 1.30 jdc 0x46, /* Scroll Lock */
600 1.30 jdc 0,
601 1.30 jdc /* 0x80 */
602 1.30 jdc 0,
603 1.30 jdc 0,
604 1.30 jdc 0,
605 1.30 jdc 0x41, /* F7 (produced as an actual 8 bit code) */
606 1.30 jdc 0, /* Alt-Print Screen */
607 1.30 jdc 0,
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 /* 0x90 */
619 1.30 jdc 0xdb, /* Left Meta */
620 1.30 jdc 0x88, /* SunHelp */
621 1.30 jdc 0x8a, /* SunAgain */
622 1.30 jdc 0x8c, /* SunUndo */
623 1.30 jdc 0x8e, /* SunCopy */
624 1.30 jdc 0x90, /* SunPaste */
625 1.30 jdc 0x92, /* SunCut */
626 1.30 jdc 0x8b, /* SunProps */
627 1.30 jdc 0x8d, /* SunFront */
628 1.30 jdc 0x8f, /* SunOpen */
629 1.30 jdc 0x91 /* SunFind */
630 1.30 jdc };
631 1.30 jdc
632 1.30 jdc const u_int8_t pckbd_xtbl_ext[] = {
633 1.30 jdc /* 0x00 */
634 1.30 jdc 0,
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 /* 0x10 */
651 1.30 jdc 0,
652 1.30 jdc 0x38, /* Right Alt */
653 1.30 jdc 0, /* E0 12, to be ignored */
654 1.30 jdc 0,
655 1.30 jdc 0x1d, /* Right Ctrl */
656 1.30 jdc 0,
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 /* 0x20 */
668 1.30 jdc 0,
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 0xdd, /* Compose */
684 1.30 jdc /* 0x30 */
685 1.30 jdc 0,
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 /* 0x40 */
702 1.30 jdc 0,
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 0xb5, /* KP / */
713 1.30 jdc 0,
714 1.30 jdc 0,
715 1.30 jdc 0,
716 1.30 jdc 0,
717 1.30 jdc 0,
718 1.30 jdc /* 0x50 */
719 1.30 jdc 0,
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 0x1c, /* KP Return */
730 1.30 jdc 0,
731 1.30 jdc 0,
732 1.30 jdc 0,
733 1.30 jdc 0,
734 1.30 jdc 0,
735 1.30 jdc /* 0x60 */
736 1.30 jdc 0,
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 0x4f, /* End */
746 1.30 jdc 0,
747 1.30 jdc 0x4b, /* Left */
748 1.30 jdc 0x47, /* Home */
749 1.30 jdc 0,
750 1.30 jdc 0,
751 1.30 jdc 0,
752 1.30 jdc /* 0x70 */
753 1.30 jdc 0x52, /* Insert */
754 1.30 jdc 0x53, /* Delete */
755 1.30 jdc 0x50, /* Down */
756 1.30 jdc 0,
757 1.30 jdc 0x4d, /* Right */
758 1.30 jdc 0x48, /* Up */
759 1.30 jdc 0,
760 1.30 jdc 0,
761 1.30 jdc 0,
762 1.30 jdc 0,
763 1.30 jdc 0x51, /* Page Down */
764 1.30 jdc 0,
765 1.30 jdc 0x37, /* Print Screen */
766 1.30 jdc 0x49, /* Page Up */
767 1.30 jdc 0x46, /* Ctrl-Break */
768 1.30 jdc 0
769 1.30 jdc };
770 1.30 jdc
771 1.30 jdc /*
772 1.30 jdc * Translate scan codes from set 2 to set 1
773 1.30 jdc */
774 1.30 jdc int
775 1.30 jdc pckbd_scancode_translate(struct pckbd_internal *id, int datain)
776 1.30 jdc {
777 1.30 jdc if (id->t_translating != 0)
778 1.30 jdc return datain;
779 1.30 jdc
780 1.30 jdc if (datain == KBR_BREAK) {
781 1.30 jdc id->t_releasing = 0x80; /* next keycode is a release */
782 1.30 jdc return 0; /* consume scancode */
783 1.30 jdc }
784 1.30 jdc
785 1.30 jdc /*
786 1.30 jdc * Handle extended sequences
787 1.30 jdc */
788 1.30 jdc if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1)
789 1.30 jdc return datain;
790 1.30 jdc
791 1.30 jdc /*
792 1.30 jdc * Convert BREAK sequence (14 77 -> 1D 45)
793 1.30 jdc */
794 1.30 jdc if (id->t_extended1 == 2 && datain == 0x14)
795 1.30 jdc return 0x1d | id->t_releasing;
796 1.30 jdc else if (id->t_extended1 == 1 && datain == 0x77)
797 1.30 jdc return 0x45 | id->t_releasing;
798 1.30 jdc
799 1.30 jdc if (id->t_extended0 != 0) {
800 1.30 jdc if (datain >= sizeof pckbd_xtbl_ext)
801 1.30 jdc datain = 0;
802 1.30 jdc else
803 1.30 jdc datain = pckbd_xtbl_ext[datain];
804 1.30 jdc } else {
805 1.30 jdc if (datain >= sizeof pckbd_xtbl)
806 1.30 jdc datain = 0;
807 1.30 jdc else
808 1.30 jdc datain = pckbd_xtbl[datain];
809 1.30 jdc }
810 1.30 jdc
811 1.30 jdc /*
812 1.30 jdc * If we are mapping in the range 128-254, then make this
813 1.30 jdc * an extended keycode, as table 1 codes are limited to
814 1.30 jdc * the range 0-127 (the top bit is used for key up/break).
815 1.30 jdc */
816 1.30 jdc if (datain > 0x7f) {
817 1.30 jdc datain &= 0x7f;
818 1.30 jdc id->t_extended0 = 0x80;
819 1.30 jdc }
820 1.30 jdc
821 1.30 jdc if (datain == 0) {
822 1.30 jdc /*
823 1.30 jdc * We don't know how to translate this scan code, but
824 1.30 jdc * we can't silently eat it either (because there might
825 1.30 jdc * have been an extended byte transmitted already).
826 1.30 jdc * Hopefully this value will be harmless to the upper
827 1.30 jdc * layers.
828 1.30 jdc */
829 1.30 jdc return 0xff;
830 1.30 jdc }
831 1.30 jdc return datain | id->t_releasing;
832 1.30 jdc }
833 1.30 jdc
834 1.1 bjh21 static int
835 1.2 bjh21 pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout)
836 1.1 bjh21 {
837 1.1 bjh21 int key;
838 1.30 jdc int releasing;
839 1.1 bjh21
840 1.1 bjh21 if (datain == KBR_EXTENDED0) {
841 1.30 jdc id->t_extended0 = 0x80;
842 1.2 bjh21 return 0;
843 1.1 bjh21 } else if (datain == KBR_EXTENDED1) {
844 1.1 bjh21 id->t_extended1 = 2;
845 1.2 bjh21 return 0;
846 1.1 bjh21 }
847 1.1 bjh21
848 1.30 jdc releasing = datain & 0x80;
849 1.30 jdc datain &= 0x7f;
850 1.30 jdc
851 1.30 jdc if (id->t_extended0 == 0x80) {
852 1.30 jdc switch (datain) {
853 1.27 jakllsch case 0x2a:
854 1.27 jakllsch case 0x36:
855 1.27 jakllsch id->t_extended0 = 0;
856 1.27 jakllsch return 0;
857 1.27 jakllsch default:
858 1.27 jakllsch break;
859 1.27 jakllsch }
860 1.27 jakllsch }
861 1.27 jakllsch
862 1.30 jdc /* map extended keys to (unused) codes 128-254 */
863 1.30 jdc key = datain | id->t_extended0;
864 1.1 bjh21 id->t_extended0 = 0;
865 1.1 bjh21
866 1.1 bjh21 /*
867 1.1 bjh21 * process PAUSE (also break) key (EXT1 1D 45 EXT1 9D C5):
868 1.1 bjh21 * map to (unused) code 7F
869 1.1 bjh21 */
870 1.1 bjh21 if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
871 1.1 bjh21 id->t_extended1 = 1;
872 1.2 bjh21 return 0;
873 1.1 bjh21 } else if (id->t_extended1 == 1 &&
874 1.1 bjh21 (datain == 0x45 || datain == 0xc5)) {
875 1.1 bjh21 id->t_extended1 = 0;
876 1.1 bjh21 key = 0x7f;
877 1.1 bjh21 } else if (id->t_extended1 > 0) {
878 1.1 bjh21 id->t_extended1 = 0;
879 1.1 bjh21 }
880 1.1 bjh21
881 1.30 jdc if (id->t_translating != 0) {
882 1.30 jdc id->t_releasing = releasing;
883 1.30 jdc } else {
884 1.30 jdc /* id->t_releasing computed in pckbd_scancode_translate() */
885 1.30 jdc }
886 1.30 jdc
887 1.30 jdc if (id->t_releasing) {
888 1.30 jdc id->t_releasing = 0;
889 1.1 bjh21 id->t_lastchar = 0;
890 1.1 bjh21 *type = WSCONS_EVENT_KEY_UP;
891 1.1 bjh21 } else {
892 1.1 bjh21 /* Always ignore typematic keys */
893 1.1 bjh21 if (key == id->t_lastchar)
894 1.2 bjh21 return 0;
895 1.1 bjh21 id->t_lastchar = key;
896 1.1 bjh21 *type = WSCONS_EVENT_KEY_DOWN;
897 1.1 bjh21 }
898 1.1 bjh21
899 1.1 bjh21 *dataout = key;
900 1.2 bjh21 return 1;
901 1.1 bjh21 }
902 1.1 bjh21
903 1.1 bjh21 int
904 1.2 bjh21 pckbd_init(struct pckbd_internal *t, pckbport_tag_t kbctag,
905 1.2 bjh21 pckbport_slot_t kbcslot, int console)
906 1.1 bjh21 {
907 1.2 bjh21
908 1.1 bjh21 memset(t, 0, sizeof(struct pckbd_internal));
909 1.1 bjh21
910 1.1 bjh21 t->t_isconsole = console;
911 1.1 bjh21 t->t_kbctag = kbctag;
912 1.1 bjh21 t->t_kbcslot = kbcslot;
913 1.1 bjh21
914 1.30 jdc return pckbd_set_xtscancode(kbctag, kbcslot, t);
915 1.1 bjh21 }
916 1.1 bjh21
917 1.1 bjh21 static int
918 1.2 bjh21 pckbd_led_encode(int led)
919 1.1 bjh21 {
920 1.1 bjh21 int res;
921 1.1 bjh21
922 1.1 bjh21 res = 0;
923 1.1 bjh21
924 1.1 bjh21 if (led & WSKBD_LED_SCROLL)
925 1.1 bjh21 res |= 0x01;
926 1.1 bjh21 if (led & WSKBD_LED_NUM)
927 1.1 bjh21 res |= 0x02;
928 1.1 bjh21 if (led & WSKBD_LED_CAPS)
929 1.1 bjh21 res |= 0x04;
930 1.2 bjh21 return res;
931 1.1 bjh21 }
932 1.1 bjh21
933 1.1 bjh21 static int
934 1.2 bjh21 pckbd_led_decode(int led)
935 1.1 bjh21 {
936 1.1 bjh21 int res;
937 1.1 bjh21
938 1.1 bjh21 res = 0;
939 1.1 bjh21 if (led & 0x01)
940 1.1 bjh21 res |= WSKBD_LED_SCROLL;
941 1.1 bjh21 if (led & 0x02)
942 1.1 bjh21 res |= WSKBD_LED_NUM;
943 1.1 bjh21 if (led & 0x04)
944 1.1 bjh21 res |= WSKBD_LED_CAPS;
945 1.2 bjh21 return res;
946 1.1 bjh21 }
947 1.1 bjh21
948 1.1 bjh21 void
949 1.2 bjh21 pckbd_set_leds(void *v, int leds)
950 1.1 bjh21 {
951 1.1 bjh21 struct pckbd_softc *sc = v;
952 1.1 bjh21 u_char cmd[2];
953 1.1 bjh21
954 1.1 bjh21 cmd[0] = KBC_MODEIND;
955 1.1 bjh21 cmd[1] = pckbd_led_encode(leds);
956 1.1 bjh21 sc->sc_ledstate = cmd[1];
957 1.1 bjh21
958 1.2 bjh21 (void)pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
959 1.1 bjh21 cmd, 2, 0, 0, 0);
960 1.1 bjh21 }
961 1.1 bjh21
962 1.1 bjh21 /*
963 1.1 bjh21 * Got a console receive interrupt -
964 1.1 bjh21 * the console processor wants to give us a character.
965 1.1 bjh21 */
966 1.1 bjh21 void
967 1.2 bjh21 pckbd_input(void *vsc, int data)
968 1.1 bjh21 {
969 1.1 bjh21 struct pckbd_softc *sc = vsc;
970 1.1 bjh21 int key;
971 1.1 bjh21 u_int type;
972 1.1 bjh21
973 1.30 jdc data = pckbd_scancode_translate(sc->id, data);
974 1.30 jdc if (data == 0)
975 1.30 jdc return;
976 1.30 jdc
977 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
978 1.1 bjh21 if (sc->rawkbd) {
979 1.1 bjh21 u_char d = data;
980 1.1 bjh21 wskbd_rawinput(sc->sc_wskbddev, &d, 1);
981 1.1 bjh21 return;
982 1.1 bjh21 }
983 1.1 bjh21 #endif
984 1.1 bjh21 if (pckbd_decode(sc->id, data, &type, &key))
985 1.1 bjh21 wskbd_input(sc->sc_wskbddev, type, key);
986 1.1 bjh21 }
987 1.1 bjh21
988 1.1 bjh21 int
989 1.15 christos pckbd_ioctl(void *v, u_long cmd, void *data, int flag,
990 1.14 christos struct lwp *l)
991 1.1 bjh21 {
992 1.1 bjh21 struct pckbd_softc *sc = v;
993 1.1 bjh21
994 1.1 bjh21 switch (cmd) {
995 1.2 bjh21 case WSKBDIO_GTYPE:
996 1.1 bjh21 *(int *)data = WSKBD_TYPE_PC_XT;
997 1.1 bjh21 return 0;
998 1.2 bjh21 case WSKBDIO_SETLEDS:
999 1.2 bjh21 {
1000 1.2 bjh21 int res;
1001 1.8 christos u_char cmdb[2];
1002 1.2 bjh21
1003 1.8 christos cmdb[0] = KBC_MODEIND;
1004 1.8 christos cmdb[1] = pckbd_led_encode(*(int *)data);
1005 1.8 christos sc->sc_ledstate = cmdb[1];
1006 1.1 bjh21 res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot,
1007 1.8 christos cmdb, 2, 0, 1, 0);
1008 1.2 bjh21 return res;
1009 1.2 bjh21 }
1010 1.2 bjh21 case WSKBDIO_GETLEDS:
1011 1.1 bjh21 *(int *)data = pckbd_led_decode(sc->sc_ledstate);
1012 1.2 bjh21 return 0;
1013 1.33 nat #if 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.33 nat #endif
1024 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD
1025 1.2 bjh21 case WSKBDIO_SETMODE:
1026 1.1 bjh21 sc->rawkbd = (*(int *)data == WSKBD_RAW);
1027 1.2 bjh21 return 0;
1028 1.1 bjh21 #endif
1029 1.1 bjh21 }
1030 1.1 bjh21 return EPASSTHROUGH;
1031 1.1 bjh21 }
1032 1.1 bjh21
1033 1.1 bjh21 void
1034 1.2 bjh21 pckbd_bell(u_int pitch, u_int period, u_int volume, int poll)
1035 1.1 bjh21 {
1036 1.1 bjh21
1037 1.1 bjh21 if (pckbd_bell_fn != NULL)
1038 1.1 bjh21 (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period,
1039 1.1 bjh21 volume, poll);
1040 1.1 bjh21 }
1041 1.1 bjh21
1042 1.1 bjh21 void
1043 1.19 dyoung pckbd_unhook_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
1044 1.19 dyoung {
1045 1.19 dyoung if (pckbd_bell_fn != fn && pckbd_bell_fn_arg != arg)
1046 1.19 dyoung return;
1047 1.19 dyoung pckbd_bell_fn = NULL;
1048 1.19 dyoung pckbd_bell_fn_arg = NULL;
1049 1.19 dyoung }
1050 1.19 dyoung
1051 1.19 dyoung void
1052 1.2 bjh21 pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg)
1053 1.1 bjh21 {
1054 1.1 bjh21
1055 1.1 bjh21 if (pckbd_bell_fn == NULL) {
1056 1.1 bjh21 pckbd_bell_fn = fn;
1057 1.1 bjh21 pckbd_bell_fn_arg = arg;
1058 1.1 bjh21 }
1059 1.1 bjh21 }
1060 1.1 bjh21
1061 1.1 bjh21 int
1062 1.2 bjh21 pckbd_cnattach(pckbport_tag_t kbctag, int kbcslot)
1063 1.1 bjh21 {
1064 1.2 bjh21 int res;
1065 1.1 bjh21 u_char cmd[1];
1066 1.1 bjh21
1067 1.1 bjh21 res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1);
1068 1.7 augustss /* We may allow the console to be attached if no keyboard is present */
1069 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
1070 1.1 bjh21 if (res)
1071 1.2 bjh21 return res;
1072 1.1 bjh21 #endif
1073 1.1 bjh21
1074 1.1 bjh21 /* Just to be sure. */
1075 1.1 bjh21 cmd[0] = KBC_ENABLE;
1076 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0);
1077 1.1 bjh21
1078 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL)
1079 1.1 bjh21 if (res)
1080 1.2 bjh21 return res;
1081 1.1 bjh21 #endif
1082 1.1 bjh21
1083 1.1 bjh21 wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata);
1084 1.1 bjh21
1085 1.31 martin return res;
1086 1.1 bjh21 }
1087 1.1 bjh21
1088 1.1 bjh21 /* ARGSUSED */
1089 1.1 bjh21 void
1090 1.2 bjh21 pckbd_cngetc(void *v, u_int *type, int *data)
1091 1.1 bjh21 {
1092 1.1 bjh21 struct pckbd_internal *t = v;
1093 1.1 bjh21 int val;
1094 1.1 bjh21
1095 1.1 bjh21 for (;;) {
1096 1.1 bjh21 val = pckbport_poll_data(t->t_kbctag, t->t_kbcslot);
1097 1.34 jmcneill if (val == -1) {
1098 1.34 jmcneill *type = 0;
1099 1.34 jmcneill *data = 0;
1100 1.34 jmcneill return;
1101 1.34 jmcneill }
1102 1.30 jdc
1103 1.30 jdc val = pckbd_scancode_translate(t, val);
1104 1.30 jdc if (val == 0)
1105 1.30 jdc continue;
1106 1.30 jdc
1107 1.30 jdc if (pckbd_decode(t, val, type, data))
1108 1.1 bjh21 return;
1109 1.1 bjh21 }
1110 1.1 bjh21 }
1111 1.1 bjh21
1112 1.1 bjh21 void
1113 1.2 bjh21 pckbd_cnpollc(void *v, int on)
1114 1.1 bjh21 {
1115 1.1 bjh21 struct pckbd_internal *t = v;
1116 1.1 bjh21
1117 1.1 bjh21 pckbport_set_poll(t->t_kbctag, t->t_kbcslot, on);
1118 1.1 bjh21 }
1119 1.1 bjh21
1120 1.1 bjh21 void
1121 1.14 christos pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
1122 1.1 bjh21 {
1123 1.1 bjh21
1124 1.1 bjh21 pckbd_bell(pitch, period, volume, 1);
1125 1.1 bjh21 }
1126