1 /* 2 * QEMU PC keyboard emulation 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu/osdep.h" 26 #include "qemu/error-report.h" 27 #include "qemu/log.h" 28 #include "qemu/timer.h" 29 #include "qapi/error.h" 30 #include "hw/isa/isa.h" 31 #include "migration/vmstate.h" 32 #include "hw/acpi/aml-build.h" 33 #include "hw/input/ps2.h" 34 #include "hw/irq.h" 35 #include "hw/input/i8042.h" 36 #include "hw/qdev-properties.h" 37 #include "sysemu/reset.h" 38 #include "sysemu/runstate.h" 39 40 #include "trace.h" 41 42 /* Keyboard Controller Commands */ 43 #define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ 44 #define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ 45 #define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ 46 #define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ 47 #define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ 48 #define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ 49 #define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ 50 #define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ 51 #define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ 52 #define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ 53 #define KBD_CCMD_READ_INPORT 0xC0 /* read input port */ 54 #define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */ 55 #define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */ 56 #define KBD_CCMD_WRITE_OBUF 0xD2 57 #define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if 58 initiated by the auxiliary device */ 59 #define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ 60 #define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */ 61 #define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */ 62 #define KBD_CCMD_PULSE_BITS_3_0 0xF0 /* Pulse bits 3-0 of the output port P2. */ 63 #define KBD_CCMD_RESET 0xFE /* Pulse bit 0 of the output port P2 = CPU reset. */ 64 #define KBD_CCMD_NO_OP 0xFF /* Pulse no bits of the output port P2. */ 65 66 /* Status Register Bits */ 67 #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ 68 #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ 69 #define KBD_STAT_SELFTEST 0x04 /* Self test successful */ 70 #define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ 71 #define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ 72 #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ 73 #define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ 74 #define KBD_STAT_PERR 0x80 /* Parity error */ 75 76 /* Controller Mode Register Bits */ 77 #define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ 78 #define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ 79 #define KBD_MODE_SYS 0x04 /* The system flag (?) */ 80 #define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ 81 #define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ 82 #define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ 83 #define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ 84 #define KBD_MODE_RFU 0x80 85 86 /* Output Port Bits */ 87 #define KBD_OUT_RESET 0x01 /* 1=normal mode, 0=reset */ 88 #define KBD_OUT_A20 0x02 /* x86 only */ 89 #define KBD_OUT_OBF 0x10 /* Keyboard output buffer full */ 90 #define KBD_OUT_MOUSE_OBF 0x20 /* Mouse output buffer full */ 91 92 /* OSes typically write 0xdd/0xdf to turn the A20 line off and on. 93 * We make the default value of the outport include these four bits, 94 * so that the subsection is rarely necessary. 95 */ 96 #define KBD_OUT_ONES 0xcc 97 98 #define KBD_PENDING_KBD_COMPAT 0x01 99 #define KBD_PENDING_AUX_COMPAT 0x02 100 #define KBD_PENDING_CTRL_KBD 0x04 101 #define KBD_PENDING_CTRL_AUX 0x08 102 #define KBD_PENDING_KBD KBD_MODE_DISABLE_KBD /* 0x10 */ 103 #define KBD_PENDING_AUX KBD_MODE_DISABLE_MOUSE /* 0x20 */ 104 105 #define KBD_MIGR_TIMER_PENDING 0x1 106 107 #define KBD_OBSRC_KBD 0x01 108 #define KBD_OBSRC_MOUSE 0x02 109 #define KBD_OBSRC_CTRL 0x04 110 111 typedef struct KBDState { 112 uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ 113 uint8_t status; 114 uint8_t mode; 115 uint8_t outport; 116 uint32_t migration_flags; 117 uint32_t obsrc; 118 bool outport_present; 119 bool extended_state; 120 bool extended_state_loaded; 121 /* Bitmask of devices with data available. */ 122 uint8_t pending; 123 uint8_t obdata; 124 uint8_t cbdata; 125 uint8_t pending_tmp; 126 void *kbd; 127 void *mouse; 128 QEMUTimer *throttle_timer; 129 130 qemu_irq irq_kbd; 131 qemu_irq irq_mouse; 132 qemu_irq a20_out; 133 hwaddr mask; 134 } KBDState; 135 136 /* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be 137 incorrect, but it avoids having to simulate exact delays */ 138 static void kbd_update_irq_lines(KBDState *s) 139 { 140 int irq_kbd_level, irq_mouse_level; 141 142 irq_kbd_level = 0; 143 irq_mouse_level = 0; 144 145 if (s->status & KBD_STAT_OBF) { 146 if (s->status & KBD_STAT_MOUSE_OBF) { 147 if (s->mode & KBD_MODE_MOUSE_INT) { 148 irq_mouse_level = 1; 149 } 150 } else { 151 if ((s->mode & KBD_MODE_KBD_INT) && 152 !(s->mode & KBD_MODE_DISABLE_KBD)) { 153 irq_kbd_level = 1; 154 } 155 } 156 } 157 qemu_set_irq(s->irq_kbd, irq_kbd_level); 158 qemu_set_irq(s->irq_mouse, irq_mouse_level); 159 } 160 161 static void kbd_deassert_irq(KBDState *s) 162 { 163 s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); 164 s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF); 165 kbd_update_irq_lines(s); 166 } 167 168 static uint8_t kbd_pending(KBDState *s) 169 { 170 if (s->extended_state) { 171 return s->pending & (~s->mode | ~(KBD_PENDING_KBD | KBD_PENDING_AUX)); 172 } else { 173 return s->pending; 174 } 175 } 176 177 /* update irq and KBD_STAT_[MOUSE_]OBF */ 178 static void kbd_update_irq(KBDState *s) 179 { 180 uint8_t pending = kbd_pending(s); 181 182 s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); 183 s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF); 184 if (pending) { 185 s->status |= KBD_STAT_OBF; 186 s->outport |= KBD_OUT_OBF; 187 if (pending & KBD_PENDING_CTRL_KBD) { 188 s->obsrc = KBD_OBSRC_CTRL; 189 } else if (pending & KBD_PENDING_CTRL_AUX) { 190 s->status |= KBD_STAT_MOUSE_OBF; 191 s->outport |= KBD_OUT_MOUSE_OBF; 192 s->obsrc = KBD_OBSRC_CTRL; 193 } else if (pending & KBD_PENDING_KBD) { 194 s->obsrc = KBD_OBSRC_KBD; 195 } else { 196 s->status |= KBD_STAT_MOUSE_OBF; 197 s->outport |= KBD_OUT_MOUSE_OBF; 198 s->obsrc = KBD_OBSRC_MOUSE; 199 } 200 } 201 kbd_update_irq_lines(s); 202 } 203 204 static void kbd_safe_update_irq(KBDState *s) 205 { 206 /* 207 * with KBD_STAT_OBF set, a call to kbd_read_data() will eventually call 208 * kbd_update_irq() 209 */ 210 if (s->status & KBD_STAT_OBF) { 211 return; 212 } 213 /* the throttle timer is pending and will call kbd_update_irq() */ 214 if (s->throttle_timer && timer_pending(s->throttle_timer)) { 215 return; 216 } 217 if (kbd_pending(s)) { 218 kbd_update_irq(s); 219 } 220 } 221 222 static void kbd_update_kbd_irq(void *opaque, int level) 223 { 224 KBDState *s = opaque; 225 226 if (level) { 227 s->pending |= KBD_PENDING_KBD; 228 } else { 229 s->pending &= ~KBD_PENDING_KBD; 230 } 231 kbd_safe_update_irq(s); 232 } 233 234 static void kbd_update_aux_irq(void *opaque, int level) 235 { 236 KBDState *s = opaque; 237 238 if (level) { 239 s->pending |= KBD_PENDING_AUX; 240 } else { 241 s->pending &= ~KBD_PENDING_AUX; 242 } 243 kbd_safe_update_irq(s); 244 } 245 246 static void kbd_throttle_timeout(void *opaque) 247 { 248 KBDState *s = opaque; 249 250 if (kbd_pending(s)) { 251 kbd_update_irq(s); 252 } 253 } 254 255 static uint64_t kbd_read_status(void *opaque, hwaddr addr, 256 unsigned size) 257 { 258 KBDState *s = opaque; 259 int val; 260 val = s->status; 261 trace_pckbd_kbd_read_status(val); 262 return val; 263 } 264 265 static void kbd_queue(KBDState *s, int b, int aux) 266 { 267 if (s->extended_state) { 268 s->cbdata = b; 269 s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX; 270 s->pending |= aux ? KBD_PENDING_CTRL_AUX : KBD_PENDING_CTRL_KBD; 271 kbd_safe_update_irq(s); 272 } else { 273 ps2_queue(aux ? s->mouse : s->kbd, b); 274 } 275 } 276 277 static uint8_t kbd_dequeue(KBDState *s) 278 { 279 uint8_t b = s->cbdata; 280 281 s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX; 282 if (kbd_pending(s)) { 283 kbd_update_irq(s); 284 } 285 return b; 286 } 287 288 static void outport_write(KBDState *s, uint32_t val) 289 { 290 trace_pckbd_outport_write(val); 291 s->outport = val; 292 qemu_set_irq(s->a20_out, (val >> 1) & 1); 293 if (!(val & 1)) { 294 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 295 } 296 } 297 298 static void kbd_write_command(void *opaque, hwaddr addr, 299 uint64_t val, unsigned size) 300 { 301 KBDState *s = opaque; 302 303 trace_pckbd_kbd_write_command(val); 304 305 /* Bits 3-0 of the output port P2 of the keyboard controller may be pulsed 306 * low for approximately 6 micro seconds. Bits 3-0 of the KBD_CCMD_PULSE 307 * command specify the output port bits to be pulsed. 308 * 0: Bit should be pulsed. 1: Bit should not be modified. 309 * The only useful version of this command is pulsing bit 0, 310 * which does a CPU reset. 311 */ 312 if((val & KBD_CCMD_PULSE_BITS_3_0) == KBD_CCMD_PULSE_BITS_3_0) { 313 if(!(val & 1)) 314 val = KBD_CCMD_RESET; 315 else 316 val = KBD_CCMD_NO_OP; 317 } 318 319 switch(val) { 320 case KBD_CCMD_READ_MODE: 321 kbd_queue(s, s->mode, 0); 322 break; 323 case KBD_CCMD_WRITE_MODE: 324 case KBD_CCMD_WRITE_OBUF: 325 case KBD_CCMD_WRITE_AUX_OBUF: 326 case KBD_CCMD_WRITE_MOUSE: 327 case KBD_CCMD_WRITE_OUTPORT: 328 s->write_cmd = val; 329 break; 330 case KBD_CCMD_MOUSE_DISABLE: 331 s->mode |= KBD_MODE_DISABLE_MOUSE; 332 break; 333 case KBD_CCMD_MOUSE_ENABLE: 334 s->mode &= ~KBD_MODE_DISABLE_MOUSE; 335 kbd_safe_update_irq(s); 336 break; 337 case KBD_CCMD_TEST_MOUSE: 338 kbd_queue(s, 0x00, 0); 339 break; 340 case KBD_CCMD_SELF_TEST: 341 s->status |= KBD_STAT_SELFTEST; 342 kbd_queue(s, 0x55, 0); 343 break; 344 case KBD_CCMD_KBD_TEST: 345 kbd_queue(s, 0x00, 0); 346 break; 347 case KBD_CCMD_KBD_DISABLE: 348 s->mode |= KBD_MODE_DISABLE_KBD; 349 break; 350 case KBD_CCMD_KBD_ENABLE: 351 s->mode &= ~KBD_MODE_DISABLE_KBD; 352 kbd_safe_update_irq(s); 353 break; 354 case KBD_CCMD_READ_INPORT: 355 kbd_queue(s, 0x80, 0); 356 break; 357 case KBD_CCMD_READ_OUTPORT: 358 kbd_queue(s, s->outport, 0); 359 break; 360 case KBD_CCMD_ENABLE_A20: 361 qemu_irq_raise(s->a20_out); 362 s->outport |= KBD_OUT_A20; 363 break; 364 case KBD_CCMD_DISABLE_A20: 365 qemu_irq_lower(s->a20_out); 366 s->outport &= ~KBD_OUT_A20; 367 break; 368 case KBD_CCMD_RESET: 369 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 370 break; 371 case KBD_CCMD_NO_OP: 372 /* ignore that */ 373 break; 374 default: 375 qemu_log_mask(LOG_GUEST_ERROR, 376 "unsupported keyboard cmd=0x%02" PRIx64 "\n", val); 377 break; 378 } 379 } 380 381 static uint64_t kbd_read_data(void *opaque, hwaddr addr, 382 unsigned size) 383 { 384 KBDState *s = opaque; 385 386 if (s->status & KBD_STAT_OBF) { 387 kbd_deassert_irq(s); 388 if (s->obsrc & KBD_OBSRC_KBD) { 389 if (s->throttle_timer) { 390 timer_mod(s->throttle_timer, 391 qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 1000); 392 } 393 s->obdata = ps2_read_data(s->kbd); 394 } else if (s->obsrc & KBD_OBSRC_MOUSE) { 395 s->obdata = ps2_read_data(s->mouse); 396 } else if (s->obsrc & KBD_OBSRC_CTRL) { 397 s->obdata = kbd_dequeue(s); 398 } 399 } 400 401 trace_pckbd_kbd_read_data(s->obdata); 402 return s->obdata; 403 } 404 405 static void kbd_write_data(void *opaque, hwaddr addr, 406 uint64_t val, unsigned size) 407 { 408 KBDState *s = opaque; 409 410 trace_pckbd_kbd_write_data(val); 411 412 switch(s->write_cmd) { 413 case 0: 414 ps2_write_keyboard(s->kbd, val); 415 /* sending data to the keyboard reenables PS/2 communication */ 416 s->mode &= ~KBD_MODE_DISABLE_KBD; 417 kbd_safe_update_irq(s); 418 break; 419 case KBD_CCMD_WRITE_MODE: 420 s->mode = val; 421 ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0); 422 /* 423 * a write to the mode byte interrupt enable flags directly updates 424 * the irq lines 425 */ 426 kbd_update_irq_lines(s); 427 /* 428 * a write to the mode byte disable interface flags may raise 429 * an irq if there is pending data in the PS/2 queues. 430 */ 431 kbd_safe_update_irq(s); 432 break; 433 case KBD_CCMD_WRITE_OBUF: 434 kbd_queue(s, val, 0); 435 break; 436 case KBD_CCMD_WRITE_AUX_OBUF: 437 kbd_queue(s, val, 1); 438 break; 439 case KBD_CCMD_WRITE_OUTPORT: 440 outport_write(s, val); 441 break; 442 case KBD_CCMD_WRITE_MOUSE: 443 ps2_write_mouse(s->mouse, val); 444 /* sending data to the mouse reenables PS/2 communication */ 445 s->mode &= ~KBD_MODE_DISABLE_MOUSE; 446 kbd_safe_update_irq(s); 447 break; 448 default: 449 break; 450 } 451 s->write_cmd = 0; 452 } 453 454 static void kbd_reset(void *opaque) 455 { 456 KBDState *s = opaque; 457 458 s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT; 459 s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; 460 s->outport = KBD_OUT_RESET | KBD_OUT_A20 | KBD_OUT_ONES; 461 s->pending = 0; 462 kbd_deassert_irq(s); 463 if (s->throttle_timer) { 464 timer_del(s->throttle_timer); 465 } 466 } 467 468 static uint8_t kbd_outport_default(KBDState *s) 469 { 470 return KBD_OUT_RESET | KBD_OUT_A20 | KBD_OUT_ONES 471 | (s->status & KBD_STAT_OBF ? KBD_OUT_OBF : 0) 472 | (s->status & KBD_STAT_MOUSE_OBF ? KBD_OUT_MOUSE_OBF : 0); 473 } 474 475 static int kbd_outport_post_load(void *opaque, int version_id) 476 { 477 KBDState *s = opaque; 478 s->outport_present = true; 479 return 0; 480 } 481 482 static bool kbd_outport_needed(void *opaque) 483 { 484 KBDState *s = opaque; 485 return s->outport != kbd_outport_default(s); 486 } 487 488 static const VMStateDescription vmstate_kbd_outport = { 489 .name = "pckbd_outport", 490 .version_id = 1, 491 .minimum_version_id = 1, 492 .post_load = kbd_outport_post_load, 493 .needed = kbd_outport_needed, 494 .fields = (VMStateField[]) { 495 VMSTATE_UINT8(outport, KBDState), 496 VMSTATE_END_OF_LIST() 497 } 498 }; 499 500 static int kbd_extended_state_pre_save(void *opaque) 501 { 502 KBDState *s = opaque; 503 504 s->migration_flags = 0; 505 if (s->throttle_timer && timer_pending(s->throttle_timer)) { 506 s->migration_flags |= KBD_MIGR_TIMER_PENDING; 507 } 508 509 return 0; 510 } 511 512 static int kbd_extended_state_post_load(void *opaque, int version_id) 513 { 514 KBDState *s = opaque; 515 516 if (s->migration_flags & KBD_MIGR_TIMER_PENDING) { 517 kbd_throttle_timeout(s); 518 } 519 s->extended_state_loaded = true; 520 521 return 0; 522 } 523 524 static bool kbd_extended_state_needed(void *opaque) 525 { 526 KBDState *s = opaque; 527 528 return s->extended_state; 529 } 530 531 static const VMStateDescription vmstate_kbd_extended_state = { 532 .name = "pckbd/extended_state", 533 .post_load = kbd_extended_state_post_load, 534 .pre_save = kbd_extended_state_pre_save, 535 .needed = kbd_extended_state_needed, 536 .fields = (VMStateField[]) { 537 VMSTATE_UINT32(migration_flags, KBDState), 538 VMSTATE_UINT32(obsrc, KBDState), 539 VMSTATE_UINT8(obdata, KBDState), 540 VMSTATE_UINT8(cbdata, KBDState), 541 VMSTATE_END_OF_LIST() 542 } 543 }; 544 545 static int kbd_pre_save(void *opaque) 546 { 547 KBDState *s = opaque; 548 549 if (s->extended_state) { 550 s->pending_tmp = s->pending; 551 } else { 552 s->pending_tmp = 0; 553 if (s->pending & KBD_PENDING_KBD) { 554 s->pending_tmp |= KBD_PENDING_KBD_COMPAT; 555 } 556 if (s->pending & KBD_PENDING_AUX) { 557 s->pending_tmp |= KBD_PENDING_AUX_COMPAT; 558 } 559 } 560 return 0; 561 } 562 563 static int kbd_pre_load(void *opaque) 564 { 565 KBDState *s = opaque; 566 567 s->outport_present = false; 568 s->extended_state_loaded = false; 569 return 0; 570 } 571 572 static int kbd_post_load(void *opaque, int version_id) 573 { 574 KBDState *s = opaque; 575 if (!s->outport_present) { 576 s->outport = kbd_outport_default(s); 577 } 578 s->pending = s->pending_tmp; 579 if (!s->extended_state_loaded) { 580 s->obsrc = s->status & KBD_STAT_OBF ? 581 (s->status & KBD_STAT_MOUSE_OBF ? KBD_OBSRC_MOUSE : KBD_OBSRC_KBD) : 582 0; 583 if (s->pending & KBD_PENDING_KBD_COMPAT) { 584 s->pending |= KBD_PENDING_KBD; 585 } 586 if (s->pending & KBD_PENDING_AUX_COMPAT) { 587 s->pending |= KBD_PENDING_AUX; 588 } 589 } 590 /* clear all unused flags */ 591 s->pending &= KBD_PENDING_CTRL_KBD | KBD_PENDING_CTRL_AUX | 592 KBD_PENDING_KBD | KBD_PENDING_AUX; 593 return 0; 594 } 595 596 static const VMStateDescription vmstate_kbd = { 597 .name = "pckbd", 598 .version_id = 3, 599 .minimum_version_id = 3, 600 .pre_load = kbd_pre_load, 601 .post_load = kbd_post_load, 602 .pre_save = kbd_pre_save, 603 .fields = (VMStateField[]) { 604 VMSTATE_UINT8(write_cmd, KBDState), 605 VMSTATE_UINT8(status, KBDState), 606 VMSTATE_UINT8(mode, KBDState), 607 VMSTATE_UINT8(pending_tmp, KBDState), 608 VMSTATE_END_OF_LIST() 609 }, 610 .subsections = (const VMStateDescription*[]) { 611 &vmstate_kbd_outport, 612 &vmstate_kbd_extended_state, 613 NULL 614 } 615 }; 616 617 /* Memory mapped interface */ 618 static uint64_t kbd_mm_readfn(void *opaque, hwaddr addr, unsigned size) 619 { 620 KBDState *s = opaque; 621 622 if (addr & s->mask) 623 return kbd_read_status(s, 0, 1) & 0xff; 624 else 625 return kbd_read_data(s, 0, 1) & 0xff; 626 } 627 628 static void kbd_mm_writefn(void *opaque, hwaddr addr, 629 uint64_t value, unsigned size) 630 { 631 KBDState *s = opaque; 632 633 if (addr & s->mask) 634 kbd_write_command(s, 0, value & 0xff, 1); 635 else 636 kbd_write_data(s, 0, value & 0xff, 1); 637 } 638 639 640 static const MemoryRegionOps i8042_mmio_ops = { 641 .read = kbd_mm_readfn, 642 .write = kbd_mm_writefn, 643 .valid.min_access_size = 1, 644 .valid.max_access_size = 4, 645 .endianness = DEVICE_NATIVE_ENDIAN, 646 }; 647 648 void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, 649 MemoryRegion *region, ram_addr_t size, 650 hwaddr mask) 651 { 652 KBDState *s = g_new0(KBDState, 1); 653 654 s->irq_kbd = kbd_irq; 655 s->irq_mouse = mouse_irq; 656 s->mask = mask; 657 658 s->extended_state = true; 659 660 vmstate_register(NULL, 0, &vmstate_kbd, s); 661 662 memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size); 663 664 s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); 665 s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); 666 qemu_register_reset(kbd_reset, s); 667 } 668 669 struct ISAKBDState { 670 ISADevice parent_obj; 671 672 KBDState kbd; 673 bool kbd_throttle; 674 MemoryRegion io[2]; 675 uint8_t kbd_irq; 676 uint8_t mouse_irq; 677 }; 678 679 void i8042_isa_mouse_fake_event(ISAKBDState *isa) 680 { 681 KBDState *s = &isa->kbd; 682 683 ps2_mouse_fake_event(s->mouse); 684 } 685 686 void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out) 687 { 688 qdev_connect_gpio_out_named(DEVICE(dev), I8042_A20_LINE, 0, a20_out); 689 } 690 691 static const VMStateDescription vmstate_kbd_isa = { 692 .name = "pckbd", 693 .version_id = 3, 694 .minimum_version_id = 3, 695 .fields = (VMStateField[]) { 696 VMSTATE_STRUCT(kbd, ISAKBDState, 0, vmstate_kbd, KBDState), 697 VMSTATE_END_OF_LIST() 698 } 699 }; 700 701 static const MemoryRegionOps i8042_data_ops = { 702 .read = kbd_read_data, 703 .write = kbd_write_data, 704 .impl = { 705 .min_access_size = 1, 706 .max_access_size = 1, 707 }, 708 .endianness = DEVICE_LITTLE_ENDIAN, 709 }; 710 711 static const MemoryRegionOps i8042_cmd_ops = { 712 .read = kbd_read_status, 713 .write = kbd_write_command, 714 .impl = { 715 .min_access_size = 1, 716 .max_access_size = 1, 717 }, 718 .endianness = DEVICE_LITTLE_ENDIAN, 719 }; 720 721 static void i8042_initfn(Object *obj) 722 { 723 ISAKBDState *isa_s = I8042(obj); 724 KBDState *s = &isa_s->kbd; 725 726 memory_region_init_io(isa_s->io + 0, obj, &i8042_data_ops, s, 727 "i8042-data", 1); 728 memory_region_init_io(isa_s->io + 1, obj, &i8042_cmd_ops, s, 729 "i8042-cmd", 1); 730 731 qdev_init_gpio_out_named(DEVICE(obj), &s->a20_out, I8042_A20_LINE, 1); 732 } 733 734 static void i8042_realizefn(DeviceState *dev, Error **errp) 735 { 736 ISADevice *isadev = ISA_DEVICE(dev); 737 ISAKBDState *isa_s = I8042(dev); 738 KBDState *s = &isa_s->kbd; 739 740 if (isa_s->kbd_irq >= ISA_NUM_IRQS) { 741 error_setg(errp, "Maximum value for \"kbd-irq\" is: %u", 742 ISA_NUM_IRQS - 1); 743 return; 744 } 745 746 if (isa_s->mouse_irq >= ISA_NUM_IRQS) { 747 error_setg(errp, "Maximum value for \"mouse-irq\" is: %u", 748 ISA_NUM_IRQS - 1); 749 return; 750 } 751 752 s->irq_kbd = isa_get_irq(isadev, isa_s->kbd_irq); 753 s->irq_mouse = isa_get_irq(isadev, isa_s->mouse_irq); 754 755 isa_register_ioport(isadev, isa_s->io + 0, 0x60); 756 isa_register_ioport(isadev, isa_s->io + 1, 0x64); 757 758 s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); 759 s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); 760 if (isa_s->kbd_throttle && !isa_s->kbd.extended_state) { 761 warn_report(TYPE_I8042 ": can't enable kbd-throttle without" 762 " extended-state, disabling kbd-throttle"); 763 } else if (isa_s->kbd_throttle) { 764 s->throttle_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, 765 kbd_throttle_timeout, s); 766 } 767 qemu_register_reset(kbd_reset, s); 768 } 769 770 static void i8042_build_aml(ISADevice *isadev, Aml *scope) 771 { 772 ISAKBDState *isa_s = I8042(isadev); 773 Aml *kbd; 774 Aml *mou; 775 Aml *crs; 776 777 crs = aml_resource_template(); 778 aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01)); 779 aml_append(crs, aml_io(AML_DECODE16, 0x0064, 0x0064, 0x01, 0x01)); 780 aml_append(crs, aml_irq_no_flags(isa_s->kbd_irq)); 781 782 kbd = aml_device("KBD"); 783 aml_append(kbd, aml_name_decl("_HID", aml_eisaid("PNP0303"))); 784 aml_append(kbd, aml_name_decl("_STA", aml_int(0xf))); 785 aml_append(kbd, aml_name_decl("_CRS", crs)); 786 787 crs = aml_resource_template(); 788 aml_append(crs, aml_irq_no_flags(isa_s->mouse_irq)); 789 790 mou = aml_device("MOU"); 791 aml_append(mou, aml_name_decl("_HID", aml_eisaid("PNP0F13"))); 792 aml_append(mou, aml_name_decl("_STA", aml_int(0xf))); 793 aml_append(mou, aml_name_decl("_CRS", crs)); 794 795 aml_append(scope, kbd); 796 aml_append(scope, mou); 797 } 798 799 static Property i8042_properties[] = { 800 DEFINE_PROP_BOOL("extended-state", ISAKBDState, kbd.extended_state, true), 801 DEFINE_PROP_BOOL("kbd-throttle", ISAKBDState, kbd_throttle, false), 802 DEFINE_PROP_UINT8("kbd-irq", ISAKBDState, kbd_irq, 1), 803 DEFINE_PROP_UINT8("mouse-irq", ISAKBDState, mouse_irq, 12), 804 DEFINE_PROP_END_OF_LIST(), 805 }; 806 807 static void i8042_class_initfn(ObjectClass *klass, void *data) 808 { 809 DeviceClass *dc = DEVICE_CLASS(klass); 810 ISADeviceClass *isa = ISA_DEVICE_CLASS(klass); 811 812 device_class_set_props(dc, i8042_properties); 813 dc->realize = i8042_realizefn; 814 dc->vmsd = &vmstate_kbd_isa; 815 isa->build_aml = i8042_build_aml; 816 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 817 } 818 819 static const TypeInfo i8042_info = { 820 .name = TYPE_I8042, 821 .parent = TYPE_ISA_DEVICE, 822 .instance_size = sizeof(ISAKBDState), 823 .instance_init = i8042_initfn, 824 .class_init = i8042_class_initfn, 825 }; 826 827 static void i8042_register_types(void) 828 { 829 type_register_static(&i8042_info); 830 } 831 832 type_init(i8042_register_types) 833