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