1 1.12 andvar /* $NetBSD: kbdsun.c,v 1.12 2024/09/14 21:22:37 andvar Exp $ */ 2 1.1 uwe /* NetBSD: kbd.c,v 1.29 2001/11/13 06:54:32 lukem Exp */ 3 1.1 uwe 4 1.1 uwe /* 5 1.1 uwe * Copyright (c) 1992, 1993 6 1.1 uwe * The Regents of the University of California. All rights reserved. 7 1.1 uwe * 8 1.1 uwe * This software was developed by the Computer Systems Engineering group 9 1.1 uwe * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 1.1 uwe * contributed to Berkeley. 11 1.1 uwe * 12 1.1 uwe * All advertising materials mentioning features or use of this software 13 1.1 uwe * must display the following acknowledgement: 14 1.1 uwe * This product includes software developed by the University of 15 1.1 uwe * California, Lawrence Berkeley Laboratory. 16 1.1 uwe * 17 1.1 uwe * Redistribution and use in source and binary forms, with or without 18 1.1 uwe * modification, are permitted provided that the following conditions 19 1.1 uwe * are met: 20 1.1 uwe * 1. Redistributions of source code must retain the above copyright 21 1.1 uwe * notice, this list of conditions and the following disclaimer. 22 1.1 uwe * 2. Redistributions in binary form must reproduce the above copyright 23 1.1 uwe * notice, this list of conditions and the following disclaimer in the 24 1.1 uwe * documentation and/or other materials provided with the distribution. 25 1.3 agc * 3. Neither the name of the University nor the names of its contributors 26 1.1 uwe * may be used to endorse or promote products derived from this software 27 1.1 uwe * without specific prior written permission. 28 1.1 uwe * 29 1.1 uwe * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 1.1 uwe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 1.1 uwe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 1.1 uwe * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 1.1 uwe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 1.1 uwe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 1.1 uwe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 1.1 uwe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 1.1 uwe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 1.1 uwe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 1.1 uwe * SUCH DAMAGE. 40 1.1 uwe * 41 1.1 uwe * @(#)kbd.c 8.2 (Berkeley) 10/30/93 42 1.1 uwe */ 43 1.1 uwe 44 1.1 uwe /* 45 1.1 uwe * /dev/kbd middle layer for sun keyboard off a serial line 46 1.1 uwe * This code is used by kbd_zs and sunkbd drivers (lower layer). 47 1.1 uwe */ 48 1.1 uwe 49 1.1 uwe #include <sys/cdefs.h> 50 1.12 andvar __KERNEL_RCSID(0, "$NetBSD: kbdsun.c,v 1.12 2024/09/14 21:22:37 andvar Exp $"); 51 1.1 uwe 52 1.1 uwe #include <sys/param.h> 53 1.1 uwe #include <sys/systm.h> 54 1.1 uwe #include <sys/conf.h> 55 1.1 uwe #include <sys/device.h> 56 1.1 uwe #include <sys/ioctl.h> 57 1.1 uwe #include <sys/kernel.h> 58 1.1 uwe #include <sys/proc.h> 59 1.1 uwe #include <sys/signal.h> 60 1.1 uwe #include <sys/signalvar.h> 61 1.1 uwe #include <sys/time.h> 62 1.1 uwe #include <sys/syslog.h> 63 1.1 uwe #include <sys/select.h> 64 1.1 uwe #include <sys/poll.h> 65 1.1 uwe #include <sys/file.h> 66 1.1 uwe 67 1.2 uwe #include <dev/sun/kbd_reg.h> 68 1.2 uwe #include <dev/sun/kbio.h> 69 1.2 uwe #include <dev/sun/vuid_event.h> 70 1.1 uwe #include <dev/sun/event_var.h> 71 1.1 uwe #include <dev/sun/kbd_xlate.h> 72 1.1 uwe 73 1.1 uwe #include <dev/sun/kbdvar.h> 74 1.1 uwe #include <dev/sun/kbdsunvar.h> 75 1.1 uwe 76 1.1 uwe 77 1.1 uwe /* callbacks for the upper /dev/kbd layer */ 78 1.1 uwe static int kbd_sun_open(struct kbd_softc *); 79 1.1 uwe static int kbd_sun_close(struct kbd_softc *); 80 1.1 uwe static int kbd_sun_do_cmd(struct kbd_softc *, int, int); 81 1.1 uwe static int kbd_sun_set_leds(struct kbd_softc *, int, int); 82 1.1 uwe 83 1.1 uwe static void kbd_sun_set_leds1(struct kbd_softc *, int); /* aux */ 84 1.1 uwe 85 1.2 uwe const struct kbd_ops kbd_ops_sun = { 86 1.1 uwe kbd_sun_open, 87 1.1 uwe kbd_sun_close, 88 1.1 uwe kbd_sun_do_cmd, 89 1.1 uwe kbd_sun_set_leds 90 1.1 uwe }; 91 1.1 uwe 92 1.1 uwe /* in user context, wait for keyboard output to finish */ 93 1.1 uwe static int kbd_sun_drain_tx(struct kbd_sun_softc *); 94 1.1 uwe 95 1.1 uwe /* helper functions for kbd_sun_input */ 96 1.1 uwe static void kbd_sun_was_reset(struct kbd_sun_softc *); 97 1.1 uwe static void kbd_sun_new_layout(struct kbd_sun_softc *); 98 1.1 uwe 99 1.1 uwe 100 1.1 uwe /*********************************************************************** 101 1.1 uwe * Callbacks for upper layer. 102 1.1 uwe */ 103 1.1 uwe 104 1.1 uwe /* 105 1.1 uwe * Initialization to be done at first open. 106 1.1 uwe * This is called from kbdopen() or kd_cc_open() 107 1.1 uwe * Called with user context. 108 1.1 uwe */ 109 1.1 uwe static int 110 1.11 tsutsui kbd_sun_open(struct kbd_softc *kbd) 111 1.1 uwe { 112 1.1 uwe struct kbd_sun_softc *k = (struct kbd_sun_softc *)kbd; 113 1.1 uwe struct kbd_state *ks; 114 1.5 heas int error, ntries, s; 115 1.1 uwe 116 1.1 uwe if (kbd == NULL) 117 1.1 uwe return (ENXIO); 118 1.1 uwe 119 1.1 uwe ks = &kbd->k_state; 120 1.1 uwe 121 1.1 uwe /* tolerate extra calls. */ 122 1.1 uwe if (k->k_isopen) 123 1.1 uwe return (0); 124 1.1 uwe 125 1.1 uwe /* open internal device */ 126 1.1 uwe if (k->k_deviopen) 127 1.11 tsutsui (*k->k_deviopen)(k->k_kbd.k_dev, FREAD|FWRITE); 128 1.1 uwe 129 1.1 uwe s = spltty(); 130 1.1 uwe 131 1.1 uwe /* reset the keyboard and find out its type */ 132 1.1 uwe kbd_sun_output(k, KBD_CMD_RESET); 133 1.1 uwe kbd_sun_start_tx(k); 134 1.1 uwe kbd_sun_drain_tx(k); 135 1.1 uwe 136 1.5 heas /* the wakeup for this is in kbd_sun_was_reset(). */ 137 1.7 martin for (ntries = 30; ntries; ntries--) { 138 1.10 christos error = tsleep((void *)&ks->kbd_id, PZERO | PCATCH, devopn, 139 1.7 martin hz/10); 140 1.5 heas if (ks->kbd_id) 141 1.5 heas break; 142 1.5 heas } 143 1.5 heas 144 1.5 heas if (error == EWOULDBLOCK || ks->kbd_id == 0) { /* no response */ 145 1.11 tsutsui log(LOG_ERR, "%s: reset failed\n", device_xname(kbd->k_dev)); 146 1.1 uwe 147 1.1 uwe /* 148 1.1 uwe * Allow the open anyway (to keep getty happy) 149 1.1 uwe * but assume the "least common denominator". 150 1.1 uwe */ 151 1.1 uwe error = 0; 152 1.1 uwe ks->kbd_id = KB_SUN2; 153 1.1 uwe } 154 1.1 uwe 155 1.2 uwe /* earlier than type 4 does not know "layout" */ 156 1.2 uwe if (ks->kbd_id >= KB_SUN4) { 157 1.5 heas ks->kbd_layout = 0xff; 158 1.5 heas 159 1.2 uwe /* ask for the layout */ 160 1.2 uwe kbd_sun_output(k, KBD_CMD_GETLAYOUT); 161 1.2 uwe kbd_sun_start_tx(k); 162 1.2 uwe kbd_sun_drain_tx(k); 163 1.1 uwe 164 1.5 heas /* the wakeup for this is in kbd_sun_new_layout() */ 165 1.5 heas for (ntries = 200; ntries; ntries--) { 166 1.10 christos error = tsleep((void *)&ks->kbd_layout, PZERO | PCATCH, 167 1.5 heas devopn, hz); 168 1.5 heas if (ks->kbd_layout != 0xff || error) 169 1.5 heas break; 170 1.5 heas DELAY(10000); 171 1.5 heas } 172 1.5 heas if (error == EWOULDBLOCK || ks->kbd_layout == 0xff) { 173 1.2 uwe log(LOG_ERR, "%s: no response to get_layout\n", 174 1.11 tsutsui device_xname(kbd->k_dev)); 175 1.2 uwe error = 0; 176 1.2 uwe ks->kbd_layout = 0; /* US layout */ 177 1.2 uwe } 178 1.2 uwe } 179 1.1 uwe 180 1.2 uwe /* initialize the table pointers for this type/layout */ 181 1.2 uwe kbd_xlate_init(ks); 182 1.1 uwe 183 1.1 uwe splx(s); 184 1.1 uwe 185 1.1 uwe if (error == 0) 186 1.1 uwe k->k_isopen = 1; 187 1.1 uwe return (error); 188 1.1 uwe } 189 1.1 uwe 190 1.1 uwe 191 1.1 uwe static int 192 1.11 tsutsui kbd_sun_close(struct kbd_softc *kbd) 193 1.1 uwe { 194 1.1 uwe 195 1.1 uwe return (0); /* nothing to do so far */ 196 1.1 uwe } 197 1.1 uwe 198 1.1 uwe 199 1.1 uwe /* 200 1.1 uwe * keyboard command ioctl 201 1.1 uwe * ``unimplemented commands are ignored'' (blech) 202 1.1 uwe * XXX: This is also exported to the fb driver (for bell). 203 1.1 uwe */ 204 1.1 uwe static int 205 1.11 tsutsui kbd_sun_do_cmd(struct kbd_softc *kbd, int cmd, int isioctl) 206 1.1 uwe { 207 1.1 uwe struct kbd_sun_softc *k = (struct kbd_sun_softc *)kbd; 208 1.1 uwe struct kbd_state *ks; 209 1.1 uwe int error, s; 210 1.1 uwe 211 1.1 uwe error = 0; 212 1.1 uwe ks = &kbd->k_state; 213 1.1 uwe 214 1.1 uwe switch (cmd) { 215 1.1 uwe 216 1.1 uwe case KBD_CMD_BELL: 217 1.1 uwe case KBD_CMD_NOBELL: 218 1.1 uwe /* Supported by type 2, 3, and 4 keyboards */ 219 1.1 uwe break; 220 1.1 uwe 221 1.1 uwe case KBD_CMD_CLICK: 222 1.1 uwe case KBD_CMD_NOCLICK: 223 1.1 uwe /* Unsupported by type 2 keyboards */ 224 1.1 uwe if (ks->kbd_id <= KB_SUN2) 225 1.1 uwe return (0); 226 1.1 uwe ks->kbd_click = (cmd == KBD_CMD_CLICK); 227 1.1 uwe break; 228 1.1 uwe 229 1.1 uwe default: 230 1.1 uwe return (0); 231 1.1 uwe } 232 1.1 uwe 233 1.1 uwe s = spltty(); 234 1.1 uwe 235 1.1 uwe if (isioctl) 236 1.1 uwe error = kbd_sun_drain_tx(k); 237 1.1 uwe 238 1.1 uwe if (error == 0) { 239 1.1 uwe kbd_sun_output(k, cmd); 240 1.1 uwe kbd_sun_start_tx(k); 241 1.1 uwe } 242 1.1 uwe 243 1.1 uwe splx(s); 244 1.1 uwe 245 1.1 uwe return (error); 246 1.1 uwe } 247 1.1 uwe 248 1.1 uwe 249 1.1 uwe /* 250 1.1 uwe * KIOCSLED. Has user context. 251 1.1 uwe * Take care about spl and call kbd_sun_set_leds. 252 1.1 uwe */ 253 1.1 uwe static int 254 1.11 tsutsui kbd_sun_set_leds(struct kbd_softc *kbd, int leds, int isioctl) 255 1.1 uwe { 256 1.1 uwe struct kbd_sun_softc *k = (struct kbd_sun_softc *)kbd; 257 1.1 uwe 258 1.1 uwe if (isioctl) { 259 1.1 uwe int error, s; 260 1.1 uwe s = spltty(); 261 1.1 uwe error = kbd_sun_drain_tx(k); 262 1.1 uwe if (error == 0) { 263 1.1 uwe kbd_sun_set_leds1(kbd, leds); 264 1.1 uwe } 265 1.1 uwe splx(s); 266 1.1 uwe return (error); 267 1.1 uwe } 268 1.1 uwe else { 269 1.1 uwe kbd_sun_set_leds1(kbd, leds); 270 1.1 uwe return (0); 271 1.1 uwe } 272 1.1 uwe } 273 1.1 uwe 274 1.1 uwe 275 1.1 uwe /* 276 1.12 andvar * Safe to call from interrupt handler. Called at spltty() 277 1.1 uwe * by kbd_sun_iocsled and kbd_sun_input (via kbd_update_leds). 278 1.1 uwe */ 279 1.1 uwe static void 280 1.11 tsutsui kbd_sun_set_leds1(struct kbd_softc *kbd, int new_leds) 281 1.1 uwe { 282 1.1 uwe struct kbd_sun_softc *k = (struct kbd_sun_softc *)kbd; 283 1.1 uwe struct kbd_state *ks = &kbd->k_state; 284 1.1 uwe 285 1.1 uwe /* Don't send unless state changes. */ 286 1.1 uwe if (ks->kbd_leds == new_leds) 287 1.1 uwe return; 288 1.1 uwe 289 1.1 uwe ks->kbd_leds = new_leds; 290 1.1 uwe 291 1.1 uwe /* Only type 4 and later has LEDs anyway. */ 292 1.1 uwe if (ks->kbd_id < KB_SUN4) 293 1.1 uwe return; 294 1.1 uwe 295 1.1 uwe kbd_sun_output(k, KBD_CMD_SETLED); 296 1.1 uwe kbd_sun_output(k, new_leds); 297 1.1 uwe kbd_sun_start_tx(k); 298 1.1 uwe } 299 1.1 uwe 300 1.1 uwe 301 1.1 uwe 302 1.1 uwe /*********************************************************************** 303 1.1 uwe * Methods for lower layer to call and related functions. 304 1.1 uwe */ 305 1.1 uwe 306 1.1 uwe /* 307 1.1 uwe * Enqueue some output for the keyboard 308 1.1 uwe * Called at spltty(). 309 1.1 uwe */ 310 1.1 uwe void 311 1.11 tsutsui kbd_sun_output(struct kbd_sun_softc *k, int c) 312 1.1 uwe { 313 1.1 uwe int put; 314 1.1 uwe 315 1.1 uwe put = k->k_tbput; 316 1.11 tsutsui k->k_tbuf[put] = (uint8_t)c; 317 1.1 uwe put = (put + 1) & KBD_TX_RING_MASK; 318 1.1 uwe 319 1.1 uwe /* Would overrun if increment makes (put == get) */ 320 1.1 uwe if (put == k->k_tbget) { 321 1.1 uwe log(LOG_WARNING, "%s: output overrun\n", 322 1.11 tsutsui device_xname(k->k_kbd.k_dev)); 323 1.1 uwe } else { 324 1.1 uwe /* OK, really increment. */ 325 1.1 uwe k->k_tbput = put; 326 1.1 uwe } 327 1.1 uwe } 328 1.1 uwe 329 1.1 uwe 330 1.1 uwe /* 331 1.1 uwe * In user context. Called at spltty(). 332 1.1 uwe * Wait for output to keyboard to finish. 333 1.1 uwe */ 334 1.1 uwe static int 335 1.11 tsutsui kbd_sun_drain_tx(struct kbd_sun_softc *k) 336 1.1 uwe { 337 1.7 martin int error = 0, bail = 0; 338 1.1 uwe 339 1.7 martin while ((k->k_txflags & K_TXBUSY) && (!error) && (bail<1000)) { 340 1.1 uwe k->k_txflags |= K_TXWANT; 341 1.8 christos error = tsleep(&k->k_txflags, PZERO | PCATCH, "kbdout", 1); 342 1.7 martin bail++; 343 1.1 uwe } 344 1.11 tsutsui if (bail == 1000) 345 1.11 tsutsui error = EIO; 346 1.1 uwe return (error); 347 1.1 uwe } 348 1.1 uwe 349 1.1 uwe /* 350 1.1 uwe * Start the sending data from the output queue 351 1.1 uwe * Called at spltty(). 352 1.1 uwe */ 353 1.1 uwe void 354 1.11 tsutsui kbd_sun_start_tx(struct kbd_sun_softc *k) 355 1.1 uwe { 356 1.1 uwe int get; 357 1.11 tsutsui uint8_t c; 358 1.1 uwe 359 1.1 uwe if (k->k_txflags & K_TXBUSY) 360 1.1 uwe return; 361 1.1 uwe 362 1.1 uwe /* Is there anything to send? */ 363 1.1 uwe get = k->k_tbget; 364 1.1 uwe if (get == k->k_tbput) { 365 1.1 uwe /* Nothing to send. Wake drain waiters. */ 366 1.1 uwe if (k->k_txflags & K_TXWANT) { 367 1.1 uwe k->k_txflags &= ~K_TXWANT; 368 1.8 christos wakeup(&k->k_txflags); 369 1.1 uwe } 370 1.1 uwe return; 371 1.1 uwe } 372 1.1 uwe 373 1.1 uwe /* Have something to send. */ 374 1.1 uwe c = k->k_tbuf[get]; 375 1.1 uwe get = (get + 1) & KBD_TX_RING_MASK; 376 1.1 uwe k->k_tbget = get; 377 1.1 uwe k->k_txflags |= K_TXBUSY; 378 1.1 uwe 379 1.1 uwe /* Pass data down to the underlying device. */ 380 1.1 uwe (*k->k_write_data)(k, c); 381 1.1 uwe } 382 1.1 uwe 383 1.1 uwe 384 1.1 uwe /* 385 1.1 uwe * Called by underlying driver's softint() routine on input, 386 1.2 uwe * which passes us the raw hardware make/break codes. 387 1.1 uwe * Called at spltty() 388 1.1 uwe */ 389 1.4 heas int 390 1.11 tsutsui kbd_sun_input(struct kbd_sun_softc *k, int code) 391 1.1 uwe { 392 1.1 uwe struct kbd_softc *kbd = (struct kbd_softc *)k; 393 1.1 uwe 394 1.1 uwe /* XXX - Input errors already handled. */ 395 1.1 uwe 396 1.1 uwe /* Are we expecting special input? */ 397 1.1 uwe if (k->k_expect) { 398 1.1 uwe if (k->k_expect & KBD_EXPECT_IDCODE) { 399 1.1 uwe /* We read a KBD_RESET last time. */ 400 1.2 uwe kbd->k_state.kbd_id = code; 401 1.1 uwe kbd_sun_was_reset(k); 402 1.1 uwe } 403 1.1 uwe if (k->k_expect & KBD_EXPECT_LAYOUT) { 404 1.1 uwe /* We read a KBD_LAYOUT last time. */ 405 1.2 uwe kbd->k_state.kbd_layout = code; 406 1.1 uwe kbd_sun_new_layout(k); 407 1.1 uwe } 408 1.1 uwe k->k_expect = 0; 409 1.4 heas return(0); 410 1.1 uwe } 411 1.1 uwe 412 1.1 uwe /* Is this one of the "special" input codes? */ 413 1.2 uwe if (KBD_SPECIAL(code)) { 414 1.2 uwe switch (code) { 415 1.1 uwe case KBD_RESET: 416 1.1 uwe k->k_expect |= KBD_EXPECT_IDCODE; 417 1.1 uwe /* Fake an "all-up" to resync. translation. */ 418 1.2 uwe code = KBD_IDLE; 419 1.1 uwe break; 420 1.1 uwe 421 1.1 uwe case KBD_LAYOUT: 422 1.1 uwe k->k_expect |= KBD_EXPECT_LAYOUT; 423 1.6 heas return(0); 424 1.1 uwe 425 1.1 uwe case KBD_ERROR: 426 1.1 uwe log(LOG_WARNING, "%s: received error indicator\n", 427 1.11 tsutsui device_xname(kbd->k_dev)); 428 1.4 heas return(-1); 429 1.1 uwe 430 1.1 uwe case KBD_IDLE: 431 1.1 uwe /* Let this go to the translator. */ 432 1.1 uwe break; 433 1.1 uwe } 434 1.1 uwe } 435 1.1 uwe 436 1.2 uwe kbd_input(kbd, code); 437 1.4 heas return(0); 438 1.1 uwe } 439 1.1 uwe 440 1.1 uwe 441 1.1 uwe /* 442 1.1 uwe * Called by kbd_sun_input to handle keyboard's response to reset. 443 1.1 uwe * Called at spltty(). 444 1.1 uwe */ 445 1.1 uwe static void 446 1.11 tsutsui kbd_sun_was_reset(struct kbd_sun_softc *k) 447 1.1 uwe { 448 1.1 uwe struct kbd_state *ks = &k->k_kbd.k_state; 449 1.1 uwe 450 1.1 uwe /* 451 1.1 uwe * On first identification, wake up anyone waiting for type 452 1.1 uwe * and set up the table pointers. 453 1.1 uwe */ 454 1.10 christos wakeup((void *)&ks->kbd_id); 455 1.1 uwe 456 1.1 uwe /* Restore keyclick, if necessary */ 457 1.1 uwe switch (ks->kbd_id) { 458 1.1 uwe 459 1.1 uwe case KB_SUN2: 460 1.1 uwe /* Type 2 keyboards don't support keyclick */ 461 1.1 uwe break; 462 1.1 uwe 463 1.1 uwe case KB_SUN3: 464 1.1 uwe /* Type 3 keyboards come up with keyclick on */ 465 1.1 uwe if (!ks->kbd_click) { 466 1.1 uwe /* turn off the click */ 467 1.1 uwe kbd_sun_output(k, KBD_CMD_NOCLICK); 468 1.1 uwe kbd_sun_start_tx(k); 469 1.1 uwe } 470 1.1 uwe break; 471 1.1 uwe 472 1.1 uwe case KB_SUN4: 473 1.1 uwe /* Type 4 keyboards come up with keyclick off */ 474 1.1 uwe if (ks->kbd_click) { 475 1.1 uwe /* turn on the click */ 476 1.1 uwe kbd_sun_output(k, KBD_CMD_CLICK); 477 1.1 uwe kbd_sun_start_tx(k); 478 1.1 uwe } 479 1.1 uwe break; 480 1.4 heas default: 481 1.4 heas printf("%s: unknown keyboard type ID %u\n", 482 1.11 tsutsui device_xname(k->k_kbd.k_dev), (unsigned int)ks->kbd_id); 483 1.1 uwe } 484 1.1 uwe 485 1.1 uwe /* LEDs are off after reset. */ 486 1.1 uwe ks->kbd_leds = 0; 487 1.1 uwe } 488 1.1 uwe 489 1.1 uwe /* 490 1.1 uwe * Called by kbd_sun_input to handle response to layout request. 491 1.1 uwe * Called at spltty(). 492 1.1 uwe */ 493 1.1 uwe static void 494 1.11 tsutsui kbd_sun_new_layout(struct kbd_sun_softc *k) 495 1.1 uwe { 496 1.1 uwe struct kbd_state *ks = &k->k_kbd.k_state; 497 1.1 uwe 498 1.1 uwe /* 499 1.1 uwe * On first identification, wake up anyone waiting for type 500 1.1 uwe * and set up the table pointers. 501 1.1 uwe */ 502 1.10 christos wakeup((void *)&ks->kbd_layout); 503 1.1 uwe 504 1.1 uwe /* XXX: switch decoding tables? */ 505 1.1 uwe } 506