1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 5 * Copyright (c) 2015 Nahanni Systems Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 #include <sys/types.h> 32 33 #include <machine/vmm.h> 34 #include <machine/vmm_snapshot.h> 35 36 #include <vmmapi.h> 37 38 #include <assert.h> 39 #include <errno.h> 40 #include <stdbool.h> 41 #include <stdlib.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <unistd.h> 45 #include <pthread.h> 46 #include <pthread_np.h> 47 48 #include "acpi.h" 49 #include "atkbdc.h" 50 #include "inout.h" 51 #include "pci_emul.h" 52 #include "pci_irq.h" 53 #include "pci_lpc.h" 54 #include "ps2kbd.h" 55 #include "ps2mouse.h" 56 57 #define KBD_DATA_PORT 0x60 58 59 #define KBD_STS_CTL_PORT 0x64 60 61 #define KBDC_RESET 0xfe 62 63 #define KBD_DEV_IRQ 1 64 #define AUX_DEV_IRQ 12 65 66 /* controller commands */ 67 #define KBDC_SET_COMMAND_BYTE 0x60 68 #define KBDC_GET_COMMAND_BYTE 0x20 69 #define KBDC_DISABLE_AUX_PORT 0xa7 70 #define KBDC_ENABLE_AUX_PORT 0xa8 71 #define KBDC_TEST_AUX_PORT 0xa9 72 #define KBDC_TEST_CTRL 0xaa 73 #define KBDC_TEST_KBD_PORT 0xab 74 #define KBDC_DISABLE_KBD_PORT 0xad 75 #define KBDC_ENABLE_KBD_PORT 0xae 76 #define KBDC_READ_INPORT 0xc0 77 #define KBDC_READ_OUTPORT 0xd0 78 #define KBDC_WRITE_OUTPORT 0xd1 79 #define KBDC_WRITE_KBD_OUTBUF 0xd2 80 #define KBDC_WRITE_AUX_OUTBUF 0xd3 81 #define KBDC_WRITE_TO_AUX 0xd4 82 83 /* controller command byte (set by KBDC_SET_COMMAND_BYTE) */ 84 #define KBD_TRANSLATION 0x40 85 #define KBD_SYS_FLAG_BIT 0x04 86 #define KBD_DISABLE_KBD_PORT 0x10 87 #define KBD_DISABLE_AUX_PORT 0x20 88 #define KBD_ENABLE_AUX_INT 0x02 89 #define KBD_ENABLE_KBD_INT 0x01 90 #define KBD_KBD_CONTROL_BITS (KBD_DISABLE_KBD_PORT | KBD_ENABLE_KBD_INT) 91 #define KBD_AUX_CONTROL_BITS (KBD_DISABLE_AUX_PORT | KBD_ENABLE_AUX_INT) 92 93 /* controller status bits */ 94 #define KBDS_KBD_BUFFER_FULL 0x01 95 #define KBDS_SYS_FLAG 0x04 96 #define KBDS_CTRL_FLAG 0x08 97 #define KBDS_AUX_BUFFER_FULL 0x20 98 99 /* controller output port */ 100 #define KBDO_KBD_OUTFULL 0x10 101 #define KBDO_AUX_OUTFULL 0x20 102 103 #define RAMSZ 32 104 #define FIFOSZ 15 105 #define CTRL_CMD_FLAG 0x8000 106 107 struct kbd_dev { 108 bool irq_active; 109 int irq; 110 111 uint8_t buffer[FIFOSZ]; 112 int brd, bwr; 113 int bcnt; 114 }; 115 116 struct aux_dev { 117 bool irq_active; 118 int irq; 119 }; 120 121 struct atkbdc_softc { 122 struct vmctx *ctx; 123 pthread_mutex_t mtx; 124 125 struct ps2kbd_softc *ps2kbd_sc; 126 struct ps2mouse_softc *ps2mouse_sc; 127 128 uint8_t status; /* status register */ 129 uint8_t outport; /* controller output port */ 130 uint8_t ram[RAMSZ]; /* byte0 = controller config */ 131 132 uint32_t curcmd; /* current command for next byte */ 133 uint32_t ctrlbyte; 134 135 struct kbd_dev kbd; 136 struct aux_dev aux; 137 }; 138 139 #ifdef BHYVE_SNAPSHOT 140 static struct atkbdc_softc *atkbdc_sc = NULL; 141 #endif 142 143 static void 144 atkbdc_assert_kbd_intr(struct atkbdc_softc *sc) 145 { 146 if ((sc->ram[0] & KBD_ENABLE_KBD_INT) != 0) { 147 sc->kbd.irq_active = true; 148 vm_isa_pulse_irq(sc->ctx, sc->kbd.irq, sc->kbd.irq); 149 } 150 } 151 152 static void 153 atkbdc_assert_aux_intr(struct atkbdc_softc *sc) 154 { 155 if ((sc->ram[0] & KBD_ENABLE_AUX_INT) != 0) { 156 sc->aux.irq_active = true; 157 vm_isa_pulse_irq(sc->ctx, sc->aux.irq, sc->aux.irq); 158 } 159 } 160 161 static int 162 atkbdc_kbd_queue_data(struct atkbdc_softc *sc, uint8_t val) 163 { 164 assert(pthread_mutex_isowned_np(&sc->mtx)); 165 166 if (sc->kbd.bcnt < FIFOSZ) { 167 sc->kbd.buffer[sc->kbd.bwr] = val; 168 sc->kbd.bwr = (sc->kbd.bwr + 1) % FIFOSZ; 169 sc->kbd.bcnt++; 170 sc->status |= KBDS_KBD_BUFFER_FULL; 171 sc->outport |= KBDO_KBD_OUTFULL; 172 } else { 173 printf("atkbd data buffer full\n"); 174 } 175 176 return (sc->kbd.bcnt < FIFOSZ); 177 } 178 179 static void 180 atkbdc_kbd_read(struct atkbdc_softc *sc) 181 { 182 const uint8_t translation[256] = { 183 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 184 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, 185 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 186 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, 187 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 188 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, 189 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 190 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, 191 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 192 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, 193 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 194 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, 195 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 196 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, 197 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 198 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, 199 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 200 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 201 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 202 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 203 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 204 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 205 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 206 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 207 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 208 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 209 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 210 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 211 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 212 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 213 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 214 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff 215 }; 216 uint8_t val; 217 uint8_t release = 0; 218 219 assert(pthread_mutex_isowned_np(&sc->mtx)); 220 221 if (sc->ram[0] & KBD_TRANSLATION) { 222 while (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) { 223 if (val == 0xf0) { 224 release = 0x80; 225 continue; 226 } else { 227 val = translation[val] | release; 228 } 229 atkbdc_kbd_queue_data(sc, val); 230 break; 231 } 232 } else { 233 while (sc->kbd.bcnt < FIFOSZ) { 234 if (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) 235 atkbdc_kbd_queue_data(sc, val); 236 else 237 break; 238 } 239 } 240 241 if (((sc->ram[0] & KBD_DISABLE_AUX_PORT) || 242 ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) && sc->kbd.bcnt > 0) 243 atkbdc_assert_kbd_intr(sc); 244 } 245 246 static void 247 atkbdc_aux_poll(struct atkbdc_softc *sc) 248 { 249 if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0) { 250 sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL; 251 sc->outport |= KBDO_AUX_OUTFULL; 252 atkbdc_assert_aux_intr(sc); 253 } 254 } 255 256 static void 257 atkbdc_kbd_poll(struct atkbdc_softc *sc) 258 { 259 assert(pthread_mutex_isowned_np(&sc->mtx)); 260 261 atkbdc_kbd_read(sc); 262 } 263 264 static void 265 atkbdc_poll(struct atkbdc_softc *sc) 266 { 267 atkbdc_aux_poll(sc); 268 atkbdc_kbd_poll(sc); 269 } 270 271 static void 272 atkbdc_dequeue_data(struct atkbdc_softc *sc, uint8_t *buf) 273 { 274 assert(pthread_mutex_isowned_np(&sc->mtx)); 275 276 if (ps2mouse_read(sc->ps2mouse_sc, buf) == 0) { 277 if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) { 278 if (sc->kbd.bcnt == 0) 279 sc->status &= ~(KBDS_AUX_BUFFER_FULL | 280 KBDS_KBD_BUFFER_FULL); 281 else 282 sc->status &= ~(KBDS_AUX_BUFFER_FULL); 283 sc->outport &= ~KBDO_AUX_OUTFULL; 284 } 285 286 atkbdc_poll(sc); 287 return; 288 } 289 290 if (sc->kbd.bcnt > 0) { 291 *buf = sc->kbd.buffer[sc->kbd.brd]; 292 sc->kbd.brd = (sc->kbd.brd + 1) % FIFOSZ; 293 sc->kbd.bcnt--; 294 if (sc->kbd.bcnt == 0) { 295 sc->status &= ~KBDS_KBD_BUFFER_FULL; 296 sc->outport &= ~KBDO_KBD_OUTFULL; 297 } 298 299 atkbdc_poll(sc); 300 } 301 302 if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0 && sc->kbd.bcnt == 0) { 303 sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL); 304 } 305 } 306 307 static int 308 atkbdc_data_handler(struct vmctx *ctx __unused, int in, 309 int port __unused, int bytes, uint32_t *eax, void *arg) 310 { 311 struct atkbdc_softc *sc; 312 uint8_t buf; 313 int retval; 314 315 if (bytes != 1) 316 return (-1); 317 sc = arg; 318 retval = 0; 319 320 pthread_mutex_lock(&sc->mtx); 321 if (in) { 322 sc->curcmd = 0; 323 if (sc->ctrlbyte != 0) { 324 *eax = sc->ctrlbyte & 0xff; 325 sc->ctrlbyte = 0; 326 } else { 327 /* read device buffer; includes kbd cmd responses */ 328 atkbdc_dequeue_data(sc, &buf); 329 *eax = buf; 330 } 331 332 sc->status &= ~KBDS_CTRL_FLAG; 333 pthread_mutex_unlock(&sc->mtx); 334 return (retval); 335 } 336 337 if (sc->status & KBDS_CTRL_FLAG) { 338 /* 339 * Command byte for the controller. 340 */ 341 switch (sc->curcmd) { 342 case KBDC_SET_COMMAND_BYTE: 343 sc->ram[0] = *eax; 344 if (sc->ram[0] & KBD_SYS_FLAG_BIT) 345 sc->status |= KBDS_SYS_FLAG; 346 else 347 sc->status &= ~KBDS_SYS_FLAG; 348 break; 349 case KBDC_WRITE_OUTPORT: 350 sc->outport = *eax; 351 break; 352 case KBDC_WRITE_TO_AUX: 353 ps2mouse_write(sc->ps2mouse_sc, *eax, 0); 354 atkbdc_poll(sc); 355 break; 356 case KBDC_WRITE_KBD_OUTBUF: 357 atkbdc_kbd_queue_data(sc, *eax); 358 break; 359 case KBDC_WRITE_AUX_OUTBUF: 360 ps2mouse_write(sc->ps2mouse_sc, *eax, 1); 361 sc->status |= (KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL); 362 atkbdc_aux_poll(sc); 363 break; 364 default: 365 /* write to particular RAM byte */ 366 if (sc->curcmd >= 0x61 && sc->curcmd <= 0x7f) { 367 int byten; 368 369 byten = (sc->curcmd - 0x60) & 0x1f; 370 sc->ram[byten] = *eax & 0xff; 371 } 372 break; 373 } 374 375 sc->curcmd = 0; 376 sc->status &= ~KBDS_CTRL_FLAG; 377 378 pthread_mutex_unlock(&sc->mtx); 379 return (retval); 380 } 381 382 /* 383 * Data byte for the device. 384 */ 385 ps2kbd_write(sc->ps2kbd_sc, *eax); 386 atkbdc_poll(sc); 387 388 pthread_mutex_unlock(&sc->mtx); 389 390 return (retval); 391 } 392 393 static int 394 atkbdc_sts_ctl_handler(struct vmctx *ctx, int in, 395 int port __unused, int bytes, uint32_t *eax, void *arg) 396 { 397 struct atkbdc_softc *sc; 398 int error, retval; 399 400 if (bytes != 1) 401 return (-1); 402 403 sc = arg; 404 retval = 0; 405 406 pthread_mutex_lock(&sc->mtx); 407 408 if (in) { 409 /* read status register */ 410 *eax = sc->status; 411 pthread_mutex_unlock(&sc->mtx); 412 return (retval); 413 } 414 415 416 sc->curcmd = 0; 417 sc->status |= KBDS_CTRL_FLAG; 418 sc->ctrlbyte = 0; 419 420 switch (*eax) { 421 case KBDC_GET_COMMAND_BYTE: 422 sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[0]; 423 break; 424 case KBDC_TEST_CTRL: 425 sc->ctrlbyte = CTRL_CMD_FLAG | 0x55; 426 break; 427 case KBDC_TEST_AUX_PORT: 428 case KBDC_TEST_KBD_PORT: 429 sc->ctrlbyte = CTRL_CMD_FLAG | 0; 430 break; 431 case KBDC_READ_INPORT: 432 sc->ctrlbyte = CTRL_CMD_FLAG | 0; 433 break; 434 case KBDC_READ_OUTPORT: 435 sc->ctrlbyte = CTRL_CMD_FLAG | sc->outport; 436 break; 437 case KBDC_SET_COMMAND_BYTE: 438 case KBDC_WRITE_OUTPORT: 439 case KBDC_WRITE_KBD_OUTBUF: 440 case KBDC_WRITE_AUX_OUTBUF: 441 sc->curcmd = *eax; 442 break; 443 case KBDC_DISABLE_KBD_PORT: 444 sc->ram[0] |= KBD_DISABLE_KBD_PORT; 445 break; 446 case KBDC_ENABLE_KBD_PORT: 447 sc->ram[0] &= ~KBD_DISABLE_KBD_PORT; 448 if (sc->kbd.bcnt > 0) 449 sc->status |= KBDS_KBD_BUFFER_FULL; 450 atkbdc_poll(sc); 451 break; 452 case KBDC_WRITE_TO_AUX: 453 sc->curcmd = *eax; 454 break; 455 case KBDC_DISABLE_AUX_PORT: 456 sc->ram[0] |= KBD_DISABLE_AUX_PORT; 457 ps2mouse_toggle(sc->ps2mouse_sc, 0); 458 sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL); 459 sc->outport &= ~KBDS_AUX_BUFFER_FULL; 460 break; 461 case KBDC_ENABLE_AUX_PORT: 462 sc->ram[0] &= ~KBD_DISABLE_AUX_PORT; 463 ps2mouse_toggle(sc->ps2mouse_sc, 1); 464 if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0) 465 sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL; 466 break; 467 case KBDC_RESET: /* Pulse "reset" line */ 468 error = vm_suspend(ctx, VM_SUSPEND_RESET); 469 assert(error == 0 || errno == EALREADY); 470 break; 471 default: 472 if (*eax >= 0x21 && *eax <= 0x3f) { 473 /* read "byte N" from RAM */ 474 int byten; 475 476 byten = (*eax - 0x20) & 0x1f; 477 sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[byten]; 478 } 479 break; 480 } 481 482 pthread_mutex_unlock(&sc->mtx); 483 484 if (sc->ctrlbyte != 0) { 485 sc->status |= KBDS_KBD_BUFFER_FULL; 486 sc->status &= ~KBDS_AUX_BUFFER_FULL; 487 atkbdc_assert_kbd_intr(sc); 488 } else if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0 && 489 (sc->ram[0] & KBD_DISABLE_AUX_PORT) == 0) { 490 sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL; 491 atkbdc_assert_aux_intr(sc); 492 } else if (sc->kbd.bcnt > 0 && (sc->ram[0] & KBD_DISABLE_KBD_PORT) == 0) { 493 sc->status |= KBDS_KBD_BUFFER_FULL; 494 atkbdc_assert_kbd_intr(sc); 495 } 496 497 return (retval); 498 } 499 500 void 501 atkbdc_event(struct atkbdc_softc *sc, int iskbd) 502 { 503 pthread_mutex_lock(&sc->mtx); 504 505 if (iskbd) 506 atkbdc_kbd_poll(sc); 507 else 508 atkbdc_aux_poll(sc); 509 pthread_mutex_unlock(&sc->mtx); 510 } 511 512 void 513 atkbdc_init(struct vmctx *ctx) 514 { 515 struct inout_port iop; 516 struct atkbdc_softc *sc; 517 int error; 518 519 sc = calloc(1, sizeof(struct atkbdc_softc)); 520 sc->ctx = ctx; 521 522 pthread_mutex_init(&sc->mtx, NULL); 523 524 bzero(&iop, sizeof(struct inout_port)); 525 iop.name = "atkdbc"; 526 iop.port = KBD_STS_CTL_PORT; 527 iop.size = 1; 528 iop.flags = IOPORT_F_INOUT; 529 iop.handler = atkbdc_sts_ctl_handler; 530 iop.arg = sc; 531 532 error = register_inout(&iop); 533 assert(error == 0); 534 535 bzero(&iop, sizeof(struct inout_port)); 536 iop.name = "atkdbc"; 537 iop.port = KBD_DATA_PORT; 538 iop.size = 1; 539 iop.flags = IOPORT_F_INOUT; 540 iop.handler = atkbdc_data_handler; 541 iop.arg = sc; 542 543 error = register_inout(&iop); 544 assert(error == 0); 545 546 pci_irq_reserve(KBD_DEV_IRQ); 547 sc->kbd.irq = KBD_DEV_IRQ; 548 549 pci_irq_reserve(AUX_DEV_IRQ); 550 sc->aux.irq = AUX_DEV_IRQ; 551 552 sc->ps2kbd_sc = ps2kbd_init(sc); 553 sc->ps2mouse_sc = ps2mouse_init(sc); 554 555 #ifdef BHYVE_SNAPSHOT 556 assert(atkbdc_sc == NULL); 557 atkbdc_sc = sc; 558 #endif 559 } 560 561 #ifdef BHYVE_SNAPSHOT 562 int 563 atkbdc_snapshot(struct vm_snapshot_meta *meta) 564 { 565 int ret; 566 567 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->status, meta, ret, done); 568 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->outport, meta, ret, done); 569 SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->ram, 570 sizeof(atkbdc_sc->ram), meta, ret, done); 571 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->curcmd, meta, ret, done); 572 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->ctrlbyte, meta, ret, done); 573 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd, meta, ret, done); 574 575 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq_active, meta, ret, done); 576 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq, meta, ret, done); 577 SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->kbd.buffer, 578 sizeof(atkbdc_sc->kbd.buffer), meta, ret, done); 579 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.brd, meta, ret, done); 580 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bwr, meta, ret, done); 581 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bcnt, meta, ret, done); 582 583 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq_active, meta, ret, done); 584 SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq, meta, ret, done); 585 586 ret = ps2kbd_snapshot(atkbdc_sc->ps2kbd_sc, meta); 587 if (ret != 0) 588 goto done; 589 590 ret = ps2mouse_snapshot(atkbdc_sc->ps2mouse_sc, meta); 591 592 done: 593 return (ret); 594 } 595 #endif 596 597 static void 598 atkbdc_dsdt(void) 599 { 600 601 dsdt_line(""); 602 dsdt_line("Device (KBD)"); 603 dsdt_line("{"); 604 dsdt_line(" Name (_HID, EisaId (\"PNP0303\"))"); 605 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 606 dsdt_line(" {"); 607 dsdt_indent(2); 608 dsdt_fixed_ioport(KBD_DATA_PORT, 1); 609 dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1); 610 dsdt_fixed_irq(1); 611 dsdt_unindent(2); 612 dsdt_line(" })"); 613 dsdt_line("}"); 614 615 dsdt_line(""); 616 dsdt_line("Device (MOU)"); 617 dsdt_line("{"); 618 dsdt_line(" Name (_HID, EisaId (\"PNP0F13\"))"); 619 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 620 dsdt_line(" {"); 621 dsdt_indent(2); 622 dsdt_fixed_ioport(KBD_DATA_PORT, 1); 623 dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1); 624 dsdt_fixed_irq(12); 625 dsdt_unindent(2); 626 dsdt_line(" })"); 627 dsdt_line("}"); 628 } 629 LPC_DSDT(atkbdc_dsdt); 630 631