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