1 1.39 andvar /* $NetBSD: pckbd.c,v 1.39 2024/02/09 22:08:36 andvar 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.39 andvar __KERNEL_RCSID(0, "$NetBSD: pckbd.c,v 1.39 2024/02/09 22:08:36 andvar 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.23 cube int pckbdprobe(device_t, cfdata_t, void *); 128 1.23 cube void pckbdattach(device_t, device_t, void *); 129 1.1 bjh21 130 1.22 cube CFATTACH_DECL_NEW(pckbd, sizeof(struct pckbd_softc), 131 1.1 bjh21 pckbdprobe, pckbdattach, NULL, NULL); 132 1.1 bjh21 133 1.2 bjh21 int pckbd_enable(void *, int); 134 1.2 bjh21 void pckbd_set_leds(void *, int); 135 1.15 christos int pckbd_ioctl(void *, u_long, void *, int, struct lwp *); 136 1.1 bjh21 137 1.1 bjh21 const struct wskbd_accessops pckbd_accessops = { 138 1.37 riastrad .enable = pckbd_enable, 139 1.37 riastrad .set_leds = pckbd_set_leds, 140 1.37 riastrad .ioctl = pckbd_ioctl, 141 1.1 bjh21 }; 142 1.1 bjh21 143 1.2 bjh21 void pckbd_cngetc(void *, u_int *, int *); 144 1.2 bjh21 void pckbd_cnpollc(void *, int); 145 1.2 bjh21 void pckbd_cnbell(void *, u_int, u_int, u_int); 146 1.1 bjh21 147 1.1 bjh21 const struct wskbd_consops pckbd_consops = { 148 1.37 riastrad .getc = pckbd_cngetc, 149 1.37 riastrad .pollc = pckbd_cnpollc, 150 1.37 riastrad .bell = pckbd_cnbell, 151 1.1 bjh21 }; 152 1.1 bjh21 153 1.1 bjh21 const struct wskbd_mapdata pckbd_keymapdata = { 154 1.37 riastrad .keydesc = pckbd_keydesctab, 155 1.1 bjh21 #ifdef PCKBD_LAYOUT 156 1.37 riastrad .layout = PCKBD_LAYOUT, 157 1.1 bjh21 #else 158 1.37 riastrad .layout = KB_US, 159 1.1 bjh21 #endif 160 1.1 bjh21 }; 161 1.1 bjh21 162 1.1 bjh21 /* 163 1.39 andvar * Hackish support for a bell on the PC Keyboard; when a suitable beeper 164 1.1 bjh21 * is found, it attaches itself into the pckbd driver here. 165 1.1 bjh21 */ 166 1.2 bjh21 void (*pckbd_bell_fn)(void *, u_int, u_int, u_int, int); 167 1.1 bjh21 void *pckbd_bell_fn_arg; 168 1.1 bjh21 169 1.2 bjh21 void pckbd_bell(u_int, u_int, u_int, int); 170 1.1 bjh21 171 1.30 jdc int pckbd_scancode_translate(struct pckbd_internal *, int); 172 1.30 jdc int pckbd_set_xtscancode(pckbport_tag_t, pckbport_slot_t, 173 1.30 jdc struct pckbd_internal *); 174 1.2 bjh21 int pckbd_init(struct pckbd_internal *, pckbport_tag_t, pckbport_slot_t, 175 1.2 bjh21 int); 176 1.2 bjh21 void pckbd_input(void *, int); 177 1.2 bjh21 178 1.1 bjh21 struct pckbd_internal pckbd_consdata; 179 1.1 bjh21 180 1.1 bjh21 int 181 1.30 jdc pckbd_set_xtscancode(pckbport_tag_t kbctag, pckbport_slot_t kbcslot, 182 1.30 jdc struct pckbd_internal *id) 183 1.1 bjh21 { 184 1.30 jdc int xt, res = 0; 185 1.1 bjh21 u_char cmd[2]; 186 1.1 bjh21 187 1.1 bjh21 /* 188 1.1 bjh21 * Some keyboard/8042 combinations do not seem to work if the keyboard 189 1.1 bjh21 * is set to table 1; in fact, it would appear that some keyboards just 190 1.1 bjh21 * ignore the command altogether. So by default, we use the AT scan 191 1.1 bjh21 * codes and have the 8042 translate them. Unfortunately, this is 192 1.1 bjh21 * known to not work on some PS/2 machines. We try desperately to deal 193 1.1 bjh21 * with this by checking the (lack of a) translate bit in the 8042 and 194 1.1 bjh21 * attempting to set the keyboard to XT mode. If this all fails, well, 195 1.30 jdc * tough luck. If the PCKBC_CANT_TRANSLATE pckbc flag was set, we 196 1.30 jdc * enable software translation. 197 1.1 bjh21 * 198 1.1 bjh21 * XXX It would perhaps be a better choice to just use AT scan codes 199 1.1 bjh21 * and not bother with this. 200 1.1 bjh21 */ 201 1.30 jdc xt = pckbport_xt_translation(kbctag, kbcslot, 1); 202 1.30 jdc if (xt == 1) { 203 1.1 bjh21 /* The 8042 is translating for us; use AT codes. */ 204 1.1 bjh21 cmd[0] = KBC_SETTABLE; 205 1.1 bjh21 cmd[1] = 2; 206 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0); 207 1.1 bjh21 if (res) { 208 1.8 christos u_char cmdb[1]; 209 1.38 christos aprint_debug("%s: error setting scanset 2\n", __func__); 210 1.1 bjh21 /* 211 1.1 bjh21 * XXX at least one keyboard is reported to lock up 212 1.1 bjh21 * if a "set table" is attempted, thus the "reset". 213 1.1 bjh21 * XXX ignore errors, scanset 2 should be 214 1.1 bjh21 * default anyway. 215 1.1 bjh21 */ 216 1.8 christos cmdb[0] = KBC_RESET; 217 1.38 christos (void)pckbport_poll_cmd(kbctag, kbcslot, cmdb, 1, 1, 218 1.38 christos 0, 1); 219 1.1 bjh21 pckbport_flush(kbctag, kbcslot); 220 1.1 bjh21 res = 0; 221 1.1 bjh21 } 222 1.30 jdc if (id != NULL) 223 1.30 jdc id->t_translating = 1; 224 1.30 jdc } else if (xt == -1) { 225 1.30 jdc /* Software translation required */ 226 1.30 jdc if (id != NULL) 227 1.30 jdc id->t_translating = 0; 228 1.1 bjh21 } else { 229 1.1 bjh21 /* Stupid 8042; set keyboard to XT codes. */ 230 1.1 bjh21 cmd[0] = KBC_SETTABLE; 231 1.1 bjh21 cmd[1] = 1; 232 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0); 233 1.1 bjh21 if (res) 234 1.38 christos aprint_debug("%s: error setting scanset 1\n", __func__); 235 1.30 jdc if (id != NULL) 236 1.30 jdc id->t_translating = 1; 237 1.1 bjh21 } 238 1.2 bjh21 return res; 239 1.1 bjh21 } 240 1.1 bjh21 241 1.1 bjh21 static int 242 1.2 bjh21 pckbd_is_console(pckbport_tag_t tag, pckbport_slot_t slot) 243 1.2 bjh21 { 244 1.2 bjh21 245 1.2 bjh21 return pckbd_consdata.t_isconsole && 246 1.2 bjh21 tag == pckbd_consdata.t_kbctag && slot == pckbd_consdata.t_kbcslot; 247 1.1 bjh21 } 248 1.1 bjh21 249 1.18 jmcneill static bool 250 1.29 dyoung pckbd_suspend(device_t dv, const pmf_qual_t *qual) 251 1.11 christos { 252 1.18 jmcneill struct pckbd_softc *sc = device_private(dv); 253 1.18 jmcneill u_char cmd[1]; 254 1.11 christos int res; 255 1.11 christos 256 1.18 jmcneill /* XXX duped from pckbd_enable, but we want to disable 257 1.18 jmcneill * it even if it's the console kbd 258 1.18 jmcneill */ 259 1.18 jmcneill cmd[0] = KBC_DISABLE; 260 1.38 christos res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 261 1.38 christos cmd, 1, 0, 1, 0); 262 1.18 jmcneill if (res) 263 1.18 jmcneill return false; 264 1.18 jmcneill 265 1.18 jmcneill pckbport_slot_enable(sc->id->t_kbctag, 266 1.18 jmcneill sc->id->t_kbcslot, 0); 267 1.11 christos 268 1.18 jmcneill sc->sc_enabled = 0; 269 1.18 jmcneill return true; 270 1.18 jmcneill } 271 1.11 christos 272 1.18 jmcneill static bool 273 1.29 dyoung pckbd_resume(device_t dv, const pmf_qual_t *qual) 274 1.18 jmcneill { 275 1.18 jmcneill struct pckbd_softc *sc = device_private(dv); 276 1.18 jmcneill u_char cmd[1], resp[1]; 277 1.18 jmcneill int res; 278 1.11 christos 279 1.18 jmcneill /* XXX jmcneill reset the keyboard */ 280 1.18 jmcneill pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot); 281 1.11 christos 282 1.18 jmcneill cmd[0] = KBC_RESET; 283 1.18 jmcneill res = pckbport_poll_cmd(sc->id->t_kbctag, 284 1.18 jmcneill sc->id->t_kbcslot, cmd, 1, 1, resp, 1); 285 1.18 jmcneill if (res) 286 1.32 prlw1 aprint_debug("%s: reset error %d\n", __func__, res); 287 1.18 jmcneill if (resp[0] != KBR_RSTDONE) 288 1.32 prlw1 printf("%s: reset response 0x%x\n", __func__, resp[0]); 289 1.11 christos 290 1.18 jmcneill pckbport_flush(sc->id->t_kbctag, sc->id->t_kbcslot); 291 1.11 christos 292 1.18 jmcneill pckbd_enable(sc, 1); 293 1.11 christos 294 1.18 jmcneill return true; 295 1.11 christos } 296 1.11 christos 297 1.1 bjh21 /* 298 1.38 christos * these are three bad jokes 299 1.1 bjh21 */ 300 1.38 christos static bool 301 1.38 christos check_keyboard_by_id(struct pckbport_attach_args *pa) 302 1.38 christos { 303 1.38 christos u_char cmd[1], resp[2]; 304 1.38 christos int res; 305 1.38 christos 306 1.38 christos cmd[0] = KBC_GETID; 307 1.38 christos res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 2, resp, 0); 308 1.38 christos if (res) { 309 1.38 christos aprint_debug("%s: getid failed with %d\n", __func__, res); 310 1.38 christos return false; 311 1.38 christos } 312 1.38 christos 313 1.38 christos switch (resp[0]) { 314 1.38 christos case 0xab: case 0xac: /* Regular and NCD Sun keyboards */ 315 1.38 christos case 0x2b: case 0x5d: /* Trust keyboard, raw and translated */ 316 1.38 christos case 0x60: case 0x47: /* NMB SGI keyboard, raw and translated */ 317 1.38 christos return true; 318 1.38 christos default: 319 1.38 christos aprint_debug("%s: getid returned %#x\n", __func__, resp[0]); 320 1.38 christos return false; 321 1.38 christos } 322 1.38 christos 323 1.38 christos } 324 1.38 christos 325 1.1 bjh21 int 326 1.23 cube pckbdprobe(device_t parent, cfdata_t cf, void *aux) 327 1.1 bjh21 { 328 1.1 bjh21 struct pckbport_attach_args *pa = aux; 329 1.2 bjh21 int res; 330 1.1 bjh21 u_char cmd[1], resp[1]; 331 1.1 bjh21 332 1.1 bjh21 /* 333 1.1 bjh21 * XXX There are rumours that a keyboard can be connected 334 1.1 bjh21 * to the aux port as well. For me, this didn't work. 335 1.1 bjh21 * For further experiments, allow it if explicitly 336 1.1 bjh21 * wired in the config file. 337 1.1 bjh21 */ 338 1.1 bjh21 if ((pa->pa_slot != PCKBPORT_KBD_SLOT) && 339 1.1 bjh21 (cf->cf_loc[PCKBPORTCF_SLOT] == PCKBPORTCF_SLOT_DEFAULT)) 340 1.2 bjh21 return 0; 341 1.1 bjh21 342 1.1 bjh21 /* Flush any garbage. */ 343 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot); 344 1.1 bjh21 345 1.1 bjh21 /* Reset the keyboard. */ 346 1.1 bjh21 cmd[0] = KBC_RESET; 347 1.1 bjh21 res = pckbport_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 1, resp, 1); 348 1.1 bjh21 if (res) { 349 1.38 christos aprint_debug("%s: reset error %d\n", __func__, res); 350 1.38 christos 351 1.38 christos /* 352 1.38 christos * On Chromebooks reset fails but otherwise the controller 353 1.38 christos * works fine. 354 1.38 christos * Check keyboard IDs similar to Linux and Haiku. 355 1.38 christos * FreeBSD's approach here is to skip probing if 356 1.38 christos * coreboot is detected which is suboptimal as coreboot 357 1.38 christos * also supports some mac models which have no PC controller 358 1.38 christos */ 359 1.38 christos if (check_keyboard_by_id(pa)) { 360 1.38 christos if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL)) 361 1.38 christos return 0; 362 1.38 christos return 2; 363 1.38 christos } 364 1.38 christos 365 1.1 bjh21 /* 366 1.1 bjh21 * There is probably no keyboard connected. 367 1.1 bjh21 * Let the probe succeed if the keyboard is used 368 1.1 bjh21 * as console input - it can be connected later. 369 1.1 bjh21 */ 370 1.2 bjh21 return pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0; 371 1.1 bjh21 } 372 1.1 bjh21 if (resp[0] != KBR_RSTDONE) { 373 1.38 christos printf("%s: reset response %#x\n", __func__, resp[0]); 374 1.38 christos 375 1.38 christos if (check_keyboard_by_id(pa)) { 376 1.38 christos if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL)) 377 1.38 christos return 0; 378 1.38 christos return 2; 379 1.38 christos } 380 1.38 christos 381 1.2 bjh21 return 0; 382 1.1 bjh21 } 383 1.1 bjh21 384 1.1 bjh21 /* 385 1.1 bjh21 * Some keyboards seem to leave a second ack byte after the reset. 386 1.1 bjh21 * This is kind of stupid, but we account for them anyway by just 387 1.1 bjh21 * flushing the buffer. 388 1.1 bjh21 */ 389 1.1 bjh21 pckbport_flush(pa->pa_tag, pa->pa_slot); 390 1.1 bjh21 391 1.30 jdc if (pckbd_set_xtscancode(pa->pa_tag, pa->pa_slot, NULL)) 392 1.2 bjh21 return 0; 393 1.1 bjh21 394 1.2 bjh21 return 2; 395 1.1 bjh21 } 396 1.1 bjh21 397 1.1 bjh21 void 398 1.23 cube pckbdattach(device_t parent, device_t self, void *aux) 399 1.1 bjh21 { 400 1.10 thorpej struct pckbd_softc *sc = device_private(self); 401 1.1 bjh21 struct pckbport_attach_args *pa = aux; 402 1.2 bjh21 struct wskbddev_attach_args a; 403 1.1 bjh21 int isconsole; 404 1.1 bjh21 u_char cmd[1]; 405 1.1 bjh21 406 1.17 jmcneill aprint_naive("\n"); 407 1.17 jmcneill aprint_normal("\n"); 408 1.1 bjh21 409 1.22 cube sc->sc_dev = self; 410 1.1 bjh21 isconsole = pckbd_is_console(pa->pa_tag, pa->pa_slot); 411 1.1 bjh21 412 1.1 bjh21 if (isconsole) { 413 1.1 bjh21 sc->id = &pckbd_consdata; 414 1.1 bjh21 415 1.3 perry /* 416 1.3 perry * Some keyboards are not enabled after a reset, 417 1.1 bjh21 * so make sure it is enabled now. 418 1.1 bjh21 */ 419 1.1 bjh21 cmd[0] = KBC_ENABLE; 420 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 421 1.38 christos cmd, 1, 0, 0, 0); 422 1.1 bjh21 sc->sc_enabled = 1; 423 1.1 bjh21 } else { 424 1.38 christos sc->id = malloc(sizeof(*sc->id), M_DEVBUF, M_WAITOK); 425 1.1 bjh21 (void) pckbd_init(sc->id, pa->pa_tag, pa->pa_slot, 0); 426 1.1 bjh21 427 1.1 bjh21 /* no interrupts until enabled */ 428 1.1 bjh21 cmd[0] = KBC_DISABLE; 429 1.1 bjh21 (void) pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 430 1.38 christos cmd, 1, 0, 0, 0); 431 1.1 bjh21 sc->sc_enabled = 0; 432 1.1 bjh21 } 433 1.1 bjh21 434 1.1 bjh21 sc->id->t_sc = sc; 435 1.1 bjh21 436 1.1 bjh21 pckbport_set_inputhandler(sc->id->t_kbctag, sc->id->t_kbcslot, 437 1.22 cube pckbd_input, sc, device_xname(sc->sc_dev)); 438 1.1 bjh21 439 1.1 bjh21 a.console = isconsole; 440 1.1 bjh21 441 1.1 bjh21 a.keymap = &pckbd_keymapdata; 442 1.1 bjh21 443 1.1 bjh21 a.accessops = &pckbd_accessops; 444 1.1 bjh21 a.accesscookie = sc; 445 1.1 bjh21 446 1.18 jmcneill if (!pmf_device_register(self, pckbd_suspend, pckbd_resume)) 447 1.18 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 448 1.11 christos 449 1.1 bjh21 /* 450 1.1 bjh21 * Attach the wskbd, saving a handle to it. 451 1.1 bjh21 * XXX XXX XXX 452 1.1 bjh21 */ 453 1.36 thorpej sc->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE); 454 1.1 bjh21 } 455 1.1 bjh21 456 1.1 bjh21 int 457 1.2 bjh21 pckbd_enable(void *v, int on) 458 1.1 bjh21 { 459 1.1 bjh21 struct pckbd_softc *sc = v; 460 1.2 bjh21 int res; 461 1.1 bjh21 u_char cmd[1]; 462 1.1 bjh21 463 1.1 bjh21 if (on) { 464 1.1 bjh21 if (sc->sc_enabled) { 465 1.38 christos aprint_debug("%s: bad enable\n", __func__); 466 1.2 bjh21 return EBUSY; 467 1.1 bjh21 } 468 1.1 bjh21 469 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 1); 470 1.1 bjh21 471 1.1 bjh21 cmd[0] = KBC_ENABLE; 472 1.1 bjh21 res = pckbport_poll_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 473 1.38 christos cmd, 1, 0, NULL, 0); 474 1.1 bjh21 if (res) { 475 1.38 christos printf("%s: command error\n", __func__); 476 1.38 christos return res; 477 1.1 bjh21 } 478 1.1 bjh21 479 1.1 bjh21 res = pckbd_set_xtscancode(sc->id->t_kbctag, 480 1.38 christos sc->id->t_kbcslot, sc->id); 481 1.1 bjh21 if (res) 482 1.2 bjh21 return res; 483 1.1 bjh21 484 1.1 bjh21 sc->sc_enabled = 1; 485 1.1 bjh21 } else { 486 1.1 bjh21 if (sc->id->t_isconsole) 487 1.2 bjh21 return EBUSY; 488 1.1 bjh21 489 1.1 bjh21 cmd[0] = KBC_DISABLE; 490 1.1 bjh21 res = pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 491 1.38 christos cmd, 1, 0, 1, 0); 492 1.1 bjh21 if (res) { 493 1.38 christos printf("%s: command error\n", __func__); 494 1.2 bjh21 return res; 495 1.1 bjh21 } 496 1.1 bjh21 497 1.1 bjh21 pckbport_slot_enable(sc->id->t_kbctag, sc->id->t_kbcslot, 0); 498 1.1 bjh21 499 1.1 bjh21 sc->sc_enabled = 0; 500 1.1 bjh21 } 501 1.1 bjh21 502 1.2 bjh21 return 0; 503 1.1 bjh21 } 504 1.1 bjh21 505 1.30 jdc const u_int8_t pckbd_xtbl[] = { 506 1.30 jdc /* 0x00 */ 507 1.30 jdc 0, 508 1.30 jdc 0x43, /* F9 */ 509 1.30 jdc 0x89, /* SunStop */ 510 1.30 jdc 0x3f, /* F5 */ 511 1.30 jdc 0x3d, /* F3 */ 512 1.30 jdc 0x3b, /* F1 */ 513 1.30 jdc 0x3c, /* F2 */ 514 1.30 jdc 0x58, /* F12 */ 515 1.30 jdc 0, 516 1.30 jdc 0x44, /* F10 */ 517 1.30 jdc 0x42, /* F8 */ 518 1.30 jdc 0x40, /* F6 */ 519 1.30 jdc 0x3e, /* F4 */ 520 1.30 jdc 0x0f, /* Tab */ 521 1.30 jdc 0x29, /* ` ~ */ 522 1.30 jdc 0, 523 1.30 jdc /* 0x10 */ 524 1.30 jdc 0, 525 1.30 jdc 0x38, /* Left Alt */ 526 1.30 jdc 0x2a, /* Left Shift */ 527 1.30 jdc 0, 528 1.30 jdc 0x1d, /* Left Ctrl */ 529 1.30 jdc 0x10, /* q */ 530 1.30 jdc 0x02, /* 1 ! */ 531 1.30 jdc 0, 532 1.30 jdc 0, 533 1.30 jdc 0, 534 1.30 jdc 0x2c, /* z */ 535 1.30 jdc 0x1f, /* s */ 536 1.30 jdc 0x1e, /* a */ 537 1.30 jdc 0x11, /* w */ 538 1.30 jdc 0x03, /* 2 @ */ 539 1.30 jdc 0, 540 1.30 jdc /* 0x20 */ 541 1.30 jdc 0, 542 1.30 jdc 0x2e, /* c */ 543 1.30 jdc 0x2d, /* x */ 544 1.30 jdc 0x20, /* d */ 545 1.30 jdc 0x12, /* e */ 546 1.30 jdc 0x05, /* 4 $ */ 547 1.30 jdc 0x04, /* 3 # */ 548 1.30 jdc 0, 549 1.30 jdc 0, 550 1.30 jdc 0x39, /* Space */ 551 1.30 jdc 0x2f, /* v */ 552 1.30 jdc 0x21, /* f */ 553 1.30 jdc 0x14, /* t */ 554 1.30 jdc 0x13, /* r */ 555 1.30 jdc 0x06, /* 5 % */ 556 1.30 jdc 0, 557 1.30 jdc /* 0x30 */ 558 1.30 jdc 0, 559 1.30 jdc 0x31, /* n */ 560 1.30 jdc 0x30, /* b */ 561 1.30 jdc 0x23, /* h */ 562 1.30 jdc 0x22, /* g */ 563 1.30 jdc 0x15, /* y */ 564 1.30 jdc 0x07, /* 6 ^ */ 565 1.30 jdc 0, 566 1.30 jdc 0, 567 1.30 jdc 0, 568 1.30 jdc 0x32, /* m */ 569 1.30 jdc 0x24, /* j */ 570 1.30 jdc 0x16, /* u */ 571 1.30 jdc 0x08, /* 7 & */ 572 1.30 jdc 0x09, /* 8 * */ 573 1.30 jdc 0, 574 1.30 jdc /* 0x40 */ 575 1.30 jdc 0, 576 1.30 jdc 0x33, /* , < */ 577 1.30 jdc 0x25, /* k */ 578 1.30 jdc 0x17, /* i */ 579 1.30 jdc 0x18, /* o */ 580 1.30 jdc 0x0b, /* 0 ) */ 581 1.30 jdc 0x0a, /* 9 ( */ 582 1.30 jdc 0, 583 1.30 jdc 0, 584 1.30 jdc 0x34, /* . > */ 585 1.30 jdc 0x35, /* / ? */ 586 1.30 jdc 0x26, /* l */ 587 1.30 jdc 0x27, /* ; : */ 588 1.30 jdc 0x19, /* p */ 589 1.30 jdc 0x0c, /* - _ */ 590 1.30 jdc 0, 591 1.30 jdc /* 0x50 */ 592 1.30 jdc 0, 593 1.30 jdc 0, 594 1.30 jdc 0x28, /* ' " */ 595 1.30 jdc 0, 596 1.30 jdc 0x1a, /* [ { */ 597 1.30 jdc 0x0d, /* = + */ 598 1.30 jdc 0, 599 1.30 jdc 0, 600 1.30 jdc 0x3a, /* Caps Lock */ 601 1.30 jdc 0x36, /* Right Shift */ 602 1.30 jdc 0x1c, /* Return */ 603 1.30 jdc 0x1b, /* ] } */ 604 1.30 jdc 0, 605 1.30 jdc 0x2b, /* \ | */ 606 1.30 jdc 0, 607 1.30 jdc 0, 608 1.30 jdc /* 0x60 */ 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 0x0e, /* Back Space */ 616 1.30 jdc 0, 617 1.30 jdc 0, 618 1.30 jdc 0x4f, /* KP 1 */ 619 1.30 jdc 0, 620 1.30 jdc 0x4b, /* KP 4 */ 621 1.30 jdc 0x47, /* KP 7 */ 622 1.30 jdc 0, 623 1.30 jdc 0, 624 1.30 jdc 0, 625 1.30 jdc /* 0x70 */ 626 1.30 jdc 0x52, /* KP 0 */ 627 1.30 jdc 0x53, /* KP . */ 628 1.30 jdc 0x50, /* KP 2 */ 629 1.30 jdc 0x4c, /* KP 5 */ 630 1.30 jdc 0x4d, /* KP 6 */ 631 1.30 jdc 0x48, /* KP 8 */ 632 1.30 jdc 0x01, /* Escape */ 633 1.30 jdc 0x45, /* Num Lock */ 634 1.30 jdc 0x57, /* F11 */ 635 1.30 jdc 0x4e, /* KP + */ 636 1.30 jdc 0x51, /* KP 3 */ 637 1.30 jdc 0x4a, /* KP - */ 638 1.30 jdc 0x37, /* KP * */ 639 1.30 jdc 0x49, /* KP 9 */ 640 1.30 jdc 0x46, /* Scroll Lock */ 641 1.30 jdc 0, 642 1.30 jdc /* 0x80 */ 643 1.30 jdc 0, 644 1.30 jdc 0, 645 1.30 jdc 0, 646 1.30 jdc 0x41, /* F7 (produced as an actual 8 bit code) */ 647 1.30 jdc 0, /* Alt-Print Screen */ 648 1.30 jdc 0, 649 1.30 jdc 0, 650 1.30 jdc 0, 651 1.30 jdc 0, 652 1.30 jdc 0, 653 1.30 jdc 0, 654 1.30 jdc 0, 655 1.30 jdc 0, 656 1.30 jdc 0, 657 1.30 jdc 0, 658 1.30 jdc 0, 659 1.30 jdc /* 0x90 */ 660 1.30 jdc 0xdb, /* Left Meta */ 661 1.30 jdc 0x88, /* SunHelp */ 662 1.30 jdc 0x8a, /* SunAgain */ 663 1.30 jdc 0x8c, /* SunUndo */ 664 1.30 jdc 0x8e, /* SunCopy */ 665 1.30 jdc 0x90, /* SunPaste */ 666 1.30 jdc 0x92, /* SunCut */ 667 1.30 jdc 0x8b, /* SunProps */ 668 1.30 jdc 0x8d, /* SunFront */ 669 1.30 jdc 0x8f, /* SunOpen */ 670 1.30 jdc 0x91 /* SunFind */ 671 1.30 jdc }; 672 1.30 jdc 673 1.30 jdc const u_int8_t pckbd_xtbl_ext[] = { 674 1.30 jdc /* 0x00 */ 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 0, 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 /* 0x10 */ 692 1.30 jdc 0, 693 1.30 jdc 0x38, /* Right Alt */ 694 1.30 jdc 0, /* E0 12, to be ignored */ 695 1.30 jdc 0, 696 1.30 jdc 0x1d, /* Right Ctrl */ 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 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 /* 0x20 */ 709 1.30 jdc 0, 710 1.30 jdc 0, 711 1.30 jdc 0, 712 1.30 jdc 0, 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 0, 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 0xdd, /* Compose */ 725 1.30 jdc /* 0x30 */ 726 1.30 jdc 0, 727 1.30 jdc 0, 728 1.30 jdc 0, 729 1.30 jdc 0, 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 0, 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 /* 0x40 */ 743 1.30 jdc 0, 744 1.30 jdc 0, 745 1.30 jdc 0, 746 1.30 jdc 0, 747 1.30 jdc 0, 748 1.30 jdc 0, 749 1.30 jdc 0, 750 1.30 jdc 0, 751 1.30 jdc 0, 752 1.30 jdc 0, 753 1.30 jdc 0xb5, /* KP / */ 754 1.30 jdc 0, 755 1.30 jdc 0, 756 1.30 jdc 0, 757 1.30 jdc 0, 758 1.30 jdc 0, 759 1.30 jdc /* 0x50 */ 760 1.30 jdc 0, 761 1.30 jdc 0, 762 1.30 jdc 0, 763 1.30 jdc 0, 764 1.30 jdc 0, 765 1.30 jdc 0, 766 1.30 jdc 0, 767 1.30 jdc 0, 768 1.30 jdc 0, 769 1.30 jdc 0, 770 1.30 jdc 0x1c, /* KP Return */ 771 1.30 jdc 0, 772 1.30 jdc 0, 773 1.30 jdc 0, 774 1.30 jdc 0, 775 1.30 jdc 0, 776 1.30 jdc /* 0x60 */ 777 1.30 jdc 0, 778 1.30 jdc 0, 779 1.30 jdc 0, 780 1.30 jdc 0, 781 1.30 jdc 0, 782 1.30 jdc 0, 783 1.30 jdc 0, 784 1.30 jdc 0, 785 1.30 jdc 0, 786 1.30 jdc 0x4f, /* End */ 787 1.30 jdc 0, 788 1.30 jdc 0x4b, /* Left */ 789 1.30 jdc 0x47, /* Home */ 790 1.30 jdc 0, 791 1.30 jdc 0, 792 1.30 jdc 0, 793 1.30 jdc /* 0x70 */ 794 1.30 jdc 0x52, /* Insert */ 795 1.30 jdc 0x53, /* Delete */ 796 1.30 jdc 0x50, /* Down */ 797 1.30 jdc 0, 798 1.30 jdc 0x4d, /* Right */ 799 1.30 jdc 0x48, /* Up */ 800 1.30 jdc 0, 801 1.30 jdc 0, 802 1.30 jdc 0, 803 1.30 jdc 0, 804 1.30 jdc 0x51, /* Page Down */ 805 1.30 jdc 0, 806 1.30 jdc 0x37, /* Print Screen */ 807 1.30 jdc 0x49, /* Page Up */ 808 1.30 jdc 0x46, /* Ctrl-Break */ 809 1.30 jdc 0 810 1.30 jdc }; 811 1.30 jdc 812 1.30 jdc /* 813 1.30 jdc * Translate scan codes from set 2 to set 1 814 1.30 jdc */ 815 1.30 jdc int 816 1.30 jdc pckbd_scancode_translate(struct pckbd_internal *id, int datain) 817 1.30 jdc { 818 1.30 jdc if (id->t_translating != 0) 819 1.30 jdc return datain; 820 1.30 jdc 821 1.30 jdc if (datain == KBR_BREAK) { 822 1.30 jdc id->t_releasing = 0x80; /* next keycode is a release */ 823 1.30 jdc return 0; /* consume scancode */ 824 1.30 jdc } 825 1.30 jdc 826 1.30 jdc /* 827 1.30 jdc * Handle extended sequences 828 1.30 jdc */ 829 1.30 jdc if (datain == KBR_EXTENDED0 || datain == KBR_EXTENDED1) 830 1.30 jdc return datain; 831 1.30 jdc 832 1.30 jdc /* 833 1.30 jdc * Convert BREAK sequence (14 77 -> 1D 45) 834 1.30 jdc */ 835 1.30 jdc if (id->t_extended1 == 2 && datain == 0x14) 836 1.30 jdc return 0x1d | id->t_releasing; 837 1.30 jdc else if (id->t_extended1 == 1 && datain == 0x77) 838 1.30 jdc return 0x45 | id->t_releasing; 839 1.30 jdc 840 1.30 jdc if (id->t_extended0 != 0) { 841 1.30 jdc if (datain >= sizeof pckbd_xtbl_ext) 842 1.30 jdc datain = 0; 843 1.30 jdc else 844 1.30 jdc datain = pckbd_xtbl_ext[datain]; 845 1.30 jdc } else { 846 1.30 jdc if (datain >= sizeof pckbd_xtbl) 847 1.30 jdc datain = 0; 848 1.30 jdc else 849 1.30 jdc datain = pckbd_xtbl[datain]; 850 1.30 jdc } 851 1.30 jdc 852 1.30 jdc /* 853 1.30 jdc * If we are mapping in the range 128-254, then make this 854 1.30 jdc * an extended keycode, as table 1 codes are limited to 855 1.30 jdc * the range 0-127 (the top bit is used for key up/break). 856 1.30 jdc */ 857 1.30 jdc if (datain > 0x7f) { 858 1.30 jdc datain &= 0x7f; 859 1.30 jdc id->t_extended0 = 0x80; 860 1.30 jdc } 861 1.30 jdc 862 1.30 jdc if (datain == 0) { 863 1.30 jdc /* 864 1.30 jdc * We don't know how to translate this scan code, but 865 1.30 jdc * we can't silently eat it either (because there might 866 1.30 jdc * have been an extended byte transmitted already). 867 1.30 jdc * Hopefully this value will be harmless to the upper 868 1.30 jdc * layers. 869 1.30 jdc */ 870 1.30 jdc return 0xff; 871 1.30 jdc } 872 1.30 jdc return datain | id->t_releasing; 873 1.30 jdc } 874 1.30 jdc 875 1.38 christos static bool 876 1.2 bjh21 pckbd_decode(struct pckbd_internal *id, int datain, u_int *type, int *dataout) 877 1.1 bjh21 { 878 1.1 bjh21 int key; 879 1.30 jdc int releasing; 880 1.1 bjh21 881 1.1 bjh21 if (datain == KBR_EXTENDED0) { 882 1.30 jdc id->t_extended0 = 0x80; 883 1.38 christos return false; 884 1.1 bjh21 } else if (datain == KBR_EXTENDED1) { 885 1.1 bjh21 id->t_extended1 = 2; 886 1.38 christos return false; 887 1.1 bjh21 } 888 1.1 bjh21 889 1.30 jdc releasing = datain & 0x80; 890 1.30 jdc datain &= 0x7f; 891 1.30 jdc 892 1.30 jdc if (id->t_extended0 == 0x80) { 893 1.30 jdc switch (datain) { 894 1.27 jakllsch case 0x2a: 895 1.27 jakllsch case 0x36: 896 1.27 jakllsch id->t_extended0 = 0; 897 1.38 christos return false; 898 1.27 jakllsch default: 899 1.27 jakllsch break; 900 1.27 jakllsch } 901 1.27 jakllsch } 902 1.27 jakllsch 903 1.30 jdc /* map extended keys to (unused) codes 128-254 */ 904 1.30 jdc key = datain | id->t_extended0; 905 1.1 bjh21 id->t_extended0 = 0; 906 1.1 bjh21 907 1.1 bjh21 /* 908 1.1 bjh21 * process PAUSE (also break) key (EXT1 1D 45 EXT1 9D C5): 909 1.1 bjh21 * map to (unused) code 7F 910 1.1 bjh21 */ 911 1.1 bjh21 if (id->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) { 912 1.1 bjh21 id->t_extended1 = 1; 913 1.38 christos return false; 914 1.1 bjh21 } else if (id->t_extended1 == 1 && 915 1.1 bjh21 (datain == 0x45 || datain == 0xc5)) { 916 1.1 bjh21 id->t_extended1 = 0; 917 1.1 bjh21 key = 0x7f; 918 1.1 bjh21 } else if (id->t_extended1 > 0) { 919 1.1 bjh21 id->t_extended1 = 0; 920 1.1 bjh21 } 921 1.1 bjh21 922 1.30 jdc if (id->t_translating != 0) { 923 1.30 jdc id->t_releasing = releasing; 924 1.30 jdc } else { 925 1.30 jdc /* id->t_releasing computed in pckbd_scancode_translate() */ 926 1.30 jdc } 927 1.30 jdc 928 1.30 jdc if (id->t_releasing) { 929 1.30 jdc id->t_releasing = 0; 930 1.1 bjh21 id->t_lastchar = 0; 931 1.1 bjh21 *type = WSCONS_EVENT_KEY_UP; 932 1.1 bjh21 } else { 933 1.1 bjh21 /* Always ignore typematic keys */ 934 1.1 bjh21 if (key == id->t_lastchar) 935 1.38 christos return false; 936 1.1 bjh21 id->t_lastchar = key; 937 1.1 bjh21 *type = WSCONS_EVENT_KEY_DOWN; 938 1.1 bjh21 } 939 1.1 bjh21 940 1.1 bjh21 *dataout = key; 941 1.38 christos return true; 942 1.1 bjh21 } 943 1.1 bjh21 944 1.1 bjh21 int 945 1.2 bjh21 pckbd_init(struct pckbd_internal *t, pckbport_tag_t kbctag, 946 1.2 bjh21 pckbport_slot_t kbcslot, int console) 947 1.1 bjh21 { 948 1.2 bjh21 949 1.1 bjh21 memset(t, 0, sizeof(struct pckbd_internal)); 950 1.1 bjh21 951 1.1 bjh21 t->t_isconsole = console; 952 1.1 bjh21 t->t_kbctag = kbctag; 953 1.1 bjh21 t->t_kbcslot = kbcslot; 954 1.1 bjh21 955 1.30 jdc return pckbd_set_xtscancode(kbctag, kbcslot, t); 956 1.1 bjh21 } 957 1.1 bjh21 958 1.1 bjh21 static int 959 1.2 bjh21 pckbd_led_encode(int led) 960 1.1 bjh21 { 961 1.1 bjh21 int res; 962 1.1 bjh21 963 1.1 bjh21 res = 0; 964 1.1 bjh21 965 1.1 bjh21 if (led & WSKBD_LED_SCROLL) 966 1.1 bjh21 res |= 0x01; 967 1.1 bjh21 if (led & WSKBD_LED_NUM) 968 1.1 bjh21 res |= 0x02; 969 1.1 bjh21 if (led & WSKBD_LED_CAPS) 970 1.1 bjh21 res |= 0x04; 971 1.2 bjh21 return res; 972 1.1 bjh21 } 973 1.1 bjh21 974 1.1 bjh21 static int 975 1.2 bjh21 pckbd_led_decode(int led) 976 1.1 bjh21 { 977 1.1 bjh21 int res; 978 1.1 bjh21 979 1.1 bjh21 res = 0; 980 1.1 bjh21 if (led & 0x01) 981 1.1 bjh21 res |= WSKBD_LED_SCROLL; 982 1.1 bjh21 if (led & 0x02) 983 1.1 bjh21 res |= WSKBD_LED_NUM; 984 1.1 bjh21 if (led & 0x04) 985 1.1 bjh21 res |= WSKBD_LED_CAPS; 986 1.2 bjh21 return res; 987 1.1 bjh21 } 988 1.1 bjh21 989 1.1 bjh21 void 990 1.2 bjh21 pckbd_set_leds(void *v, int leds) 991 1.1 bjh21 { 992 1.1 bjh21 struct pckbd_softc *sc = v; 993 1.1 bjh21 u_char cmd[2]; 994 1.1 bjh21 995 1.1 bjh21 cmd[0] = KBC_MODEIND; 996 1.1 bjh21 cmd[1] = pckbd_led_encode(leds); 997 1.1 bjh21 sc->sc_ledstate = cmd[1]; 998 1.1 bjh21 999 1.2 bjh21 (void)pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 1000 1.38 christos cmd, 2, 0, 0, 0); 1001 1.1 bjh21 } 1002 1.1 bjh21 1003 1.1 bjh21 /* 1004 1.1 bjh21 * Got a console receive interrupt - 1005 1.1 bjh21 * the console processor wants to give us a character. 1006 1.1 bjh21 */ 1007 1.1 bjh21 void 1008 1.2 bjh21 pckbd_input(void *vsc, int data) 1009 1.1 bjh21 { 1010 1.1 bjh21 struct pckbd_softc *sc = vsc; 1011 1.1 bjh21 int key; 1012 1.1 bjh21 u_int type; 1013 1.1 bjh21 1014 1.30 jdc data = pckbd_scancode_translate(sc->id, data); 1015 1.30 jdc if (data == 0) 1016 1.30 jdc return; 1017 1.30 jdc 1018 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD 1019 1.1 bjh21 if (sc->rawkbd) { 1020 1.1 bjh21 u_char d = data; 1021 1.1 bjh21 wskbd_rawinput(sc->sc_wskbddev, &d, 1); 1022 1.1 bjh21 return; 1023 1.1 bjh21 } 1024 1.1 bjh21 #endif 1025 1.1 bjh21 if (pckbd_decode(sc->id, data, &type, &key)) 1026 1.1 bjh21 wskbd_input(sc->sc_wskbddev, type, key); 1027 1.1 bjh21 } 1028 1.1 bjh21 1029 1.1 bjh21 int 1030 1.38 christos pckbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 1031 1.1 bjh21 { 1032 1.1 bjh21 struct pckbd_softc *sc = v; 1033 1.38 christos u_char cmdb[2]; 1034 1.1 bjh21 1035 1.1 bjh21 switch (cmd) { 1036 1.2 bjh21 case WSKBDIO_GTYPE: 1037 1.1 bjh21 *(int *)data = WSKBD_TYPE_PC_XT; 1038 1.1 bjh21 return 0; 1039 1.2 bjh21 case WSKBDIO_SETLEDS: 1040 1.8 christos cmdb[0] = KBC_MODEIND; 1041 1.8 christos cmdb[1] = pckbd_led_encode(*(int *)data); 1042 1.8 christos sc->sc_ledstate = cmdb[1]; 1043 1.38 christos return pckbport_enqueue_cmd(sc->id->t_kbctag, sc->id->t_kbcslot, 1044 1.38 christos cmdb, 2, 0, 1, 0); 1045 1.2 bjh21 case WSKBDIO_GETLEDS: 1046 1.1 bjh21 *(int *)data = pckbd_led_decode(sc->sc_ledstate); 1047 1.2 bjh21 return 0; 1048 1.33 nat #if 0 1049 1.2 bjh21 case WSKBDIO_COMPLEXBELL: 1050 1.1 bjh21 #define d ((struct wskbd_bell_data *)data) 1051 1.1 bjh21 /* 1052 1.1 bjh21 * Keyboard can't beep directly; we have an 1053 1.1 bjh21 * externally-provided global hook to do this. 1054 1.1 bjh21 */ 1055 1.1 bjh21 pckbd_bell(d->pitch, d->period, d->volume, 0); 1056 1.1 bjh21 #undef d 1057 1.2 bjh21 return 0; 1058 1.33 nat #endif 1059 1.1 bjh21 #ifdef WSDISPLAY_COMPAT_RAWKBD 1060 1.2 bjh21 case WSKBDIO_SETMODE: 1061 1.1 bjh21 sc->rawkbd = (*(int *)data == WSKBD_RAW); 1062 1.2 bjh21 return 0; 1063 1.1 bjh21 #endif 1064 1.1 bjh21 } 1065 1.1 bjh21 return EPASSTHROUGH; 1066 1.1 bjh21 } 1067 1.1 bjh21 1068 1.1 bjh21 void 1069 1.2 bjh21 pckbd_bell(u_int pitch, u_int period, u_int volume, int poll) 1070 1.1 bjh21 { 1071 1.1 bjh21 1072 1.1 bjh21 if (pckbd_bell_fn != NULL) 1073 1.1 bjh21 (*pckbd_bell_fn)(pckbd_bell_fn_arg, pitch, period, 1074 1.1 bjh21 volume, poll); 1075 1.1 bjh21 } 1076 1.1 bjh21 1077 1.1 bjh21 void 1078 1.19 dyoung pckbd_unhook_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg) 1079 1.19 dyoung { 1080 1.19 dyoung if (pckbd_bell_fn != fn && pckbd_bell_fn_arg != arg) 1081 1.19 dyoung return; 1082 1.19 dyoung pckbd_bell_fn = NULL; 1083 1.19 dyoung pckbd_bell_fn_arg = NULL; 1084 1.19 dyoung } 1085 1.19 dyoung 1086 1.19 dyoung void 1087 1.2 bjh21 pckbd_hookup_bell(void (*fn)(void *, u_int, u_int, u_int, int), void *arg) 1088 1.1 bjh21 { 1089 1.1 bjh21 1090 1.1 bjh21 if (pckbd_bell_fn == NULL) { 1091 1.1 bjh21 pckbd_bell_fn = fn; 1092 1.1 bjh21 pckbd_bell_fn_arg = arg; 1093 1.1 bjh21 } 1094 1.1 bjh21 } 1095 1.1 bjh21 1096 1.1 bjh21 int 1097 1.2 bjh21 pckbd_cnattach(pckbport_tag_t kbctag, int kbcslot) 1098 1.1 bjh21 { 1099 1.2 bjh21 int res; 1100 1.1 bjh21 u_char cmd[1]; 1101 1.1 bjh21 1102 1.1 bjh21 res = pckbd_init(&pckbd_consdata, kbctag, kbcslot, 1); 1103 1.7 augustss /* We may allow the console to be attached if no keyboard is present */ 1104 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL) 1105 1.1 bjh21 if (res) 1106 1.2 bjh21 return res; 1107 1.1 bjh21 #endif 1108 1.1 bjh21 1109 1.1 bjh21 /* Just to be sure. */ 1110 1.1 bjh21 cmd[0] = KBC_ENABLE; 1111 1.1 bjh21 res = pckbport_poll_cmd(kbctag, kbcslot, cmd, 1, 0, 0, 0); 1112 1.1 bjh21 1113 1.7 augustss #if defined(PCKBD_CNATTACH_MAY_FAIL) 1114 1.1 bjh21 if (res) 1115 1.2 bjh21 return res; 1116 1.1 bjh21 #endif 1117 1.1 bjh21 1118 1.1 bjh21 wskbd_cnattach(&pckbd_consops, &pckbd_consdata, &pckbd_keymapdata); 1119 1.1 bjh21 1120 1.31 martin return res; 1121 1.1 bjh21 } 1122 1.1 bjh21 1123 1.1 bjh21 /* ARGSUSED */ 1124 1.1 bjh21 void 1125 1.2 bjh21 pckbd_cngetc(void *v, u_int *type, int *data) 1126 1.1 bjh21 { 1127 1.1 bjh21 struct pckbd_internal *t = v; 1128 1.1 bjh21 int val; 1129 1.1 bjh21 1130 1.1 bjh21 for (;;) { 1131 1.1 bjh21 val = pckbport_poll_data(t->t_kbctag, t->t_kbcslot); 1132 1.34 jmcneill if (val == -1) { 1133 1.34 jmcneill *type = 0; 1134 1.34 jmcneill *data = 0; 1135 1.34 jmcneill return; 1136 1.34 jmcneill } 1137 1.30 jdc 1138 1.30 jdc val = pckbd_scancode_translate(t, val); 1139 1.30 jdc if (val == 0) 1140 1.30 jdc continue; 1141 1.30 jdc 1142 1.30 jdc if (pckbd_decode(t, val, type, data)) 1143 1.1 bjh21 return; 1144 1.1 bjh21 } 1145 1.1 bjh21 } 1146 1.1 bjh21 1147 1.1 bjh21 void 1148 1.2 bjh21 pckbd_cnpollc(void *v, int on) 1149 1.1 bjh21 { 1150 1.1 bjh21 struct pckbd_internal *t = v; 1151 1.1 bjh21 1152 1.1 bjh21 pckbport_set_poll(t->t_kbctag, t->t_kbcslot, on); 1153 1.1 bjh21 } 1154 1.1 bjh21 1155 1.1 bjh21 void 1156 1.14 christos pckbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) 1157 1.1 bjh21 { 1158 1.1 bjh21 1159 1.1 bjh21 pckbd_bell(pitch, period, volume, 1); 1160 1.1 bjh21 } 1161