1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 /* 29 * This file and its contents are supplied under the terms of the 30 * Common Development and Distribution License ("CDDL"), version 1.0. 31 * You may only use this file in accordance with the terms of version 32 * 1.0 of the CDDL. 33 * 34 * A full copy of the text of the CDDL should have accompanied this 35 * source. A copy of the CDDL is also available via the Internet at 36 * http://www.illumos.org/license/CDDL. 37 * 38 * Copyright 2021 Oxide Computer Company 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/param.h> 45 #include <sys/types.h> 46 #include <sys/queue.h> 47 #include <sys/kernel.h> 48 #include <sys/malloc.h> 49 #include <sys/mutex.h> 50 #include <sys/systm.h> 51 52 #include <x86/apicreg.h> 53 #include <dev/ic/i8259.h> 54 55 #include <machine/vmm.h> 56 57 #include "vmm_ktr.h" 58 #include "vmm_lapic.h" 59 #include "vioapic.h" 60 #include "vatpic.h" 61 62 static MALLOC_DEFINE(M_VATPIC, "atpic", "bhyve virtual atpic (8259)"); 63 64 #define VATPIC_LOCK(vatpic) mutex_enter(&((vatpic)->lock)) 65 #define VATPIC_UNLOCK(vatpic) mutex_exit(&((vatpic)->lock)) 66 #define VATPIC_LOCKED(vatpic) MUTEX_HELD(&((vatpic)->lock)) 67 68 #define IRQ_BASE_MASK 0xf8 69 70 enum irqstate { 71 IRQSTATE_ASSERT, 72 IRQSTATE_DEASSERT, 73 IRQSTATE_PULSE 74 }; 75 76 enum icw_state { 77 IS_ICW1 = 0, 78 IS_ICW2, 79 IS_ICW3, 80 IS_ICW4, 81 }; 82 83 struct atpic { 84 enum icw_state icw_state; 85 86 bool ready; 87 bool auto_eoi; 88 bool poll; 89 bool rotate; 90 bool special_full_nested; 91 bool read_isr_next; 92 bool intr_raised; 93 bool special_mask_mode; 94 95 uint8_t reg_irr; /* Interrupt Request Register (IIR) */ 96 uint8_t reg_isr; /* Interrupt Service (ISR) */ 97 uint8_t reg_imr; /* Interrupt Mask Register (IMR) */ 98 uint8_t irq_base; /* base interrupt vector */ 99 uint8_t lowprio; /* lowest priority irq */ 100 uint8_t elc; /* level-triggered mode bits */ 101 102 uint_t acnt[8]; /* sum of pin asserts and deasserts */ 103 }; 104 105 struct atpic_stats { 106 uint64_t as_interrupts; 107 uint64_t as_saturate_low; 108 uint64_t as_saturate_high; 109 }; 110 111 struct vatpic { 112 struct vm *vm; 113 kmutex_t lock; 114 struct atpic atpic[2]; 115 struct atpic_stats stats; 116 }; 117 118 #define VATPIC_CTR0(vatpic, fmt) \ 119 VM_CTR0((vatpic)->vm, fmt) 120 121 #define VATPIC_CTR1(vatpic, fmt, a1) \ 122 VM_CTR1((vatpic)->vm, fmt, a1) 123 124 #define VATPIC_CTR2(vatpic, fmt, a1, a2) \ 125 VM_CTR2((vatpic)->vm, fmt, a1, a2) 126 127 #define VATPIC_CTR3(vatpic, fmt, a1, a2, a3) \ 128 VM_CTR3((vatpic)->vm, fmt, a1, a2, a3) 129 130 #define VATPIC_CTR4(vatpic, fmt, a1, a2, a3, a4) \ 131 VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4) 132 133 /* 134 * Loop over all the pins in priority order from highest to lowest. 135 */ 136 #define ATPIC_PIN_FOREACH(pinvar, atpic, tmpvar) \ 137 for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \ 138 tmpvar < 8; \ 139 tmpvar++, pinvar = (pinvar + 1) & 0x7) 140 141 static int vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate); 142 143 static __inline bool 144 master_atpic(struct vatpic *vatpic, struct atpic *atpic) 145 { 146 147 if (atpic == &vatpic->atpic[0]) 148 return (true); 149 else 150 return (false); 151 } 152 153 static __inline int 154 vatpic_get_highest_isrpin(struct atpic *atpic) 155 { 156 int bit, pin; 157 int i; 158 159 ATPIC_PIN_FOREACH(pin, atpic, i) { 160 bit = (1 << pin); 161 162 if (atpic->reg_isr & bit) { 163 /* 164 * An IS bit that is masked by an IMR bit will not be 165 * cleared by a non-specific EOI in Special Mask Mode. 166 */ 167 if (atpic->special_mask_mode && 168 (atpic->reg_imr & bit) != 0) { 169 continue; 170 } else { 171 return (pin); 172 } 173 } 174 } 175 176 return (-1); 177 } 178 179 static __inline int 180 vatpic_get_highest_irrpin(struct atpic *atpic) 181 { 182 int serviced; 183 int bit, pin, tmp; 184 185 /* 186 * In 'Special Fully-Nested Mode' when an interrupt request from 187 * a slave is in service, the slave is not locked out from the 188 * master's priority logic. 189 */ 190 serviced = atpic->reg_isr; 191 if (atpic->special_full_nested) 192 serviced &= ~(1 << 2); 193 194 /* 195 * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits 196 * further interrupts at that level and enables interrupts from all 197 * other levels that are not masked. In other words the ISR has no 198 * bearing on the levels that can generate interrupts. 199 */ 200 if (atpic->special_mask_mode) 201 serviced = 0; 202 203 ATPIC_PIN_FOREACH(pin, atpic, tmp) { 204 bit = 1 << pin; 205 206 /* 207 * If there is already an interrupt in service at the same 208 * or higher priority then bail. 209 */ 210 if ((serviced & bit) != 0) 211 break; 212 213 /* 214 * If an interrupt is asserted and not masked then return 215 * the corresponding 'pin' to the caller. 216 */ 217 if ((atpic->reg_irr & bit) != 0 && (atpic->reg_imr & bit) == 0) 218 return (pin); 219 } 220 221 return (-1); 222 } 223 224 static void 225 vatpic_notify_intr(struct vatpic *vatpic) 226 { 227 struct atpic *atpic; 228 int pin; 229 230 ASSERT(VATPIC_LOCKED(vatpic)); 231 232 /* 233 * First check the slave. 234 */ 235 atpic = &vatpic->atpic[1]; 236 if (!atpic->intr_raised && 237 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 238 VATPIC_CTR4(vatpic, "atpic slave notify pin = %d " 239 "(imr 0x%x irr 0x%x isr 0x%x)", pin, 240 atpic->reg_imr, atpic->reg_irr, atpic->reg_isr); 241 242 /* 243 * Cascade the request from the slave to the master. 244 */ 245 atpic->intr_raised = true; 246 if (vatpic_set_pinstate(vatpic, 2, true) == 0) { 247 (void) vatpic_set_pinstate(vatpic, 2, false); 248 } 249 } else { 250 VATPIC_CTR3(vatpic, "atpic slave no eligible interrupts " 251 "(imr 0x%x irr 0x%x isr 0x%x)", 252 atpic->reg_imr, atpic->reg_irr, atpic->reg_isr); 253 } 254 255 /* 256 * Then check the master. 257 */ 258 atpic = &vatpic->atpic[0]; 259 if (!atpic->intr_raised && 260 (pin = vatpic_get_highest_irrpin(atpic)) != -1) { 261 VATPIC_CTR4(vatpic, "atpic master notify pin = %d " 262 "(imr 0x%x irr 0x%x isr 0x%x)", pin, 263 atpic->reg_imr, atpic->reg_irr, atpic->reg_isr); 264 265 /* 266 * From Section 3.6.2, "Interrupt Modes", in the 267 * MPtable Specification, Version 1.4 268 * 269 * PIC interrupts are routed to both the Local APIC 270 * and the I/O APIC to support operation in 1 of 3 271 * modes. 272 * 273 * 1. Legacy PIC Mode: the PIC effectively bypasses 274 * all APIC components. In this mode the local APIC is 275 * disabled and LINT0 is reconfigured as INTR to 276 * deliver the PIC interrupt directly to the CPU. 277 * 278 * 2. Virtual Wire Mode: the APIC is treated as a 279 * virtual wire which delivers interrupts from the PIC 280 * to the CPU. In this mode LINT0 is programmed as 281 * ExtINT to indicate that the PIC is the source of 282 * the interrupt. 283 * 284 * 3. Virtual Wire Mode via I/O APIC: PIC interrupts are 285 * fielded by the I/O APIC and delivered to the appropriate 286 * CPU. In this mode the I/O APIC input 0 is programmed 287 * as ExtINT to indicate that the PIC is the source of the 288 * interrupt. 289 */ 290 atpic->intr_raised = true; 291 lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); 292 vioapic_pulse_irq(vatpic->vm, 0); 293 vatpic->stats.as_interrupts++; 294 } else { 295 VATPIC_CTR3(vatpic, "atpic master no eligible interrupts " 296 "(imr 0x%x irr 0x%x isr 0x%x)", 297 atpic->reg_imr, atpic->reg_irr, atpic->reg_isr); 298 } 299 } 300 301 static int 302 vatpic_icw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 303 { 304 atpic->ready = false; 305 306 atpic->icw_state = IS_ICW1; 307 atpic->reg_irr = 0; 308 atpic->reg_imr = 0; 309 atpic->lowprio = 7; 310 atpic->read_isr_next = false; 311 atpic->poll = false; 312 atpic->special_mask_mode = false; 313 314 if ((val & ICW1_SNGL) != 0) { 315 VATPIC_CTR0(vatpic, "vatpic cascade mode required"); 316 return (-1); 317 } 318 319 if ((val & ICW1_IC4) == 0) { 320 VATPIC_CTR0(vatpic, "vatpic icw4 required"); 321 return (-1); 322 } 323 324 atpic->icw_state = IS_ICW2; 325 326 return (0); 327 } 328 329 static int 330 vatpic_icw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 331 { 332 atpic->irq_base = val & IRQ_BASE_MASK; 333 atpic->icw_state = IS_ICW3; 334 335 return (0); 336 } 337 338 static int 339 vatpic_icw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 340 { 341 atpic->icw_state = IS_ICW4; 342 343 return (0); 344 } 345 346 static int 347 vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 348 { 349 if ((val & ICW4_8086) == 0) { 350 VATPIC_CTR0(vatpic, "vatpic microprocessor mode required"); 351 return (-1); 352 } 353 354 atpic->auto_eoi = (val & ICW4_AEOI) != 0; 355 if (master_atpic(vatpic, atpic)) { 356 atpic->special_full_nested = (val & ICW4_SFNM) != 0; 357 } 358 359 atpic->icw_state = IS_ICW1; 360 atpic->ready = true; 361 362 return (0); 363 } 364 365 static int 366 vatpic_ocw1(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 367 { 368 atpic->reg_imr = val; 369 370 return (0); 371 } 372 373 static int 374 vatpic_ocw2(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 375 { 376 atpic->rotate = (val & OCW2_R) != 0; 377 378 if ((val & OCW2_EOI) != 0) { 379 int isr_bit; 380 381 if ((val & OCW2_SL) != 0) { 382 /* specific EOI */ 383 isr_bit = val & 0x7; 384 } else { 385 /* non-specific EOI */ 386 isr_bit = vatpic_get_highest_isrpin(atpic); 387 } 388 389 if (isr_bit != -1) { 390 atpic->reg_isr &= ~(1 << isr_bit); 391 392 if (atpic->rotate) 393 atpic->lowprio = isr_bit; 394 } 395 } else if ((val & OCW2_SL) != 0 && atpic->rotate) { 396 /* specific priority */ 397 atpic->lowprio = val & 0x7; 398 } 399 400 return (0); 401 } 402 403 static int 404 vatpic_ocw3(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) 405 { 406 if ((val & OCW3_ESMM) != 0) { 407 atpic->special_mask_mode = (val & OCW3_SMM) != 0; 408 } 409 if ((val & OCW3_RR) != 0) { 410 atpic->read_isr_next = (val & OCW3_RIS) != 0; 411 } 412 if ((val & OCW3_P) != 0) { 413 atpic->poll = true; 414 } 415 416 return (0); 417 } 418 419 static int 420 vatpic_set_pinstate(struct vatpic *vatpic, int pin, bool newstate) 421 { 422 struct atpic *atpic; 423 uint_t oldcnt, newcnt; 424 int err = 0; 425 426 VERIFY(pin >= 0 && pin < 16); 427 ASSERT(VATPIC_LOCKED(vatpic)); 428 429 const int lpin = pin & 0x7; 430 atpic = &vatpic->atpic[pin >> 3]; 431 432 oldcnt = newcnt = atpic->acnt[lpin]; 433 if (newstate) { 434 if (newcnt != UINT_MAX) { 435 newcnt++; 436 } else { 437 err = E2BIG; 438 DTRACE_PROBE2(vatpic__sat_high, struct vatpic *, vatpic, 439 int, pin); 440 vatpic->stats.as_saturate_high++; 441 } 442 } else { 443 if (newcnt != 0) { 444 newcnt--; 445 } else { 446 err = ERANGE; 447 DTRACE_PROBE2(vatpic__sat_low, struct vatpic *, vatpic, 448 int, pin); 449 vatpic->stats.as_saturate_low++; 450 } 451 } 452 atpic->acnt[lpin] = newcnt; 453 454 const bool level = ((atpic->elc & (1 << (lpin))) != 0); 455 if ((oldcnt == 0 && newcnt == 1) || (newcnt > 0 && level == true)) { 456 /* rising edge or level */ 457 DTRACE_PROBE2(vatpic__assert, struct vatpic *, vatpic, 458 int, pin); 459 atpic->reg_irr |= (1 << lpin); 460 } else if (oldcnt == 1 && newcnt == 0) { 461 /* falling edge */ 462 DTRACE_PROBE2(vatpic__deassert, struct vatpic *, vatpic, 463 int, pin); 464 if (level) { 465 atpic->reg_irr &= ~(1 << lpin); 466 } 467 } 468 469 vatpic_notify_intr(vatpic); 470 return (err); 471 } 472 473 static int 474 vatpic_set_irqstate(struct vm *vm, int irq, enum irqstate irqstate) 475 { 476 struct vatpic *vatpic; 477 struct atpic *atpic; 478 int err = 0; 479 480 if (irq < 0 || irq > 15) 481 return (EINVAL); 482 483 vatpic = vm_atpic(vm); 484 atpic = &vatpic->atpic[irq >> 3]; 485 486 if (!atpic->ready) 487 return (0); 488 489 VATPIC_LOCK(vatpic); 490 switch (irqstate) { 491 case IRQSTATE_ASSERT: 492 err = vatpic_set_pinstate(vatpic, irq, true); 493 break; 494 case IRQSTATE_DEASSERT: 495 err = vatpic_set_pinstate(vatpic, irq, false); 496 break; 497 case IRQSTATE_PULSE: 498 err = vatpic_set_pinstate(vatpic, irq, true); 499 if (err == 0) { 500 err = vatpic_set_pinstate(vatpic, irq, false); 501 } 502 break; 503 default: 504 panic("vatpic_set_irqstate: invalid irqstate %d", irqstate); 505 } 506 VATPIC_UNLOCK(vatpic); 507 508 return (err); 509 } 510 511 int 512 vatpic_assert_irq(struct vm *vm, int irq) 513 { 514 return (vatpic_set_irqstate(vm, irq, IRQSTATE_ASSERT)); 515 } 516 517 int 518 vatpic_deassert_irq(struct vm *vm, int irq) 519 { 520 return (vatpic_set_irqstate(vm, irq, IRQSTATE_DEASSERT)); 521 } 522 523 int 524 vatpic_pulse_irq(struct vm *vm, int irq) 525 { 526 return (vatpic_set_irqstate(vm, irq, IRQSTATE_PULSE)); 527 } 528 529 int 530 vatpic_set_irq_trigger(struct vm *vm, int irq, enum vm_intr_trigger trigger) 531 { 532 if (irq < 0 || irq > 15) 533 return (EINVAL); 534 535 /* 536 * See comments in vatpic_elc_handler. 537 * These IRQs must be edge triggered. 538 */ 539 if (trigger == LEVEL_TRIGGER) { 540 switch (irq) { 541 case 0: 542 case 1: 543 case 2: 544 case 8: 545 case 13: 546 return (EINVAL); 547 } 548 } 549 550 struct vatpic *vatpic = vm_atpic(vm); 551 struct atpic *atpic = &vatpic->atpic[irq >> 3]; 552 const int pin = irq & 0x7; 553 554 VATPIC_LOCK(vatpic); 555 if (trigger == LEVEL_TRIGGER) { 556 atpic->elc |= (1 << pin); 557 } else { 558 atpic->elc &= ~(1 << pin); 559 } 560 VATPIC_UNLOCK(vatpic); 561 562 return (0); 563 } 564 565 void 566 vatpic_pending_intr(struct vm *vm, int *vecptr) 567 { 568 struct vatpic *vatpic; 569 struct atpic *atpic; 570 int pin; 571 572 vatpic = vm_atpic(vm); 573 574 atpic = &vatpic->atpic[0]; 575 576 VATPIC_LOCK(vatpic); 577 578 pin = vatpic_get_highest_irrpin(atpic); 579 if (pin == 2) { 580 atpic = &vatpic->atpic[1]; 581 pin = vatpic_get_highest_irrpin(atpic); 582 } 583 584 /* 585 * If there are no pins active at this moment then return the spurious 586 * interrupt vector instead. 587 */ 588 if (pin == -1) 589 pin = 7; 590 591 KASSERT(pin >= 0 && pin <= 7, ("%s: invalid pin %d", __func__, pin)); 592 *vecptr = atpic->irq_base + pin; 593 594 VATPIC_UNLOCK(vatpic); 595 } 596 597 static void 598 vatpic_pin_accepted(struct atpic *atpic, int pin) 599 { 600 ASSERT(pin >= 0 && pin < 8); 601 602 atpic->intr_raised = false; 603 604 if (atpic->acnt[pin] == 0) 605 atpic->reg_irr &= ~(1 << pin); 606 607 if (atpic->auto_eoi) { 608 if (atpic->rotate) 609 atpic->lowprio = pin; 610 } else { 611 atpic->reg_isr |= (1 << pin); 612 } 613 } 614 615 void 616 vatpic_intr_accepted(struct vm *vm, int vector) 617 { 618 struct vatpic *vatpic; 619 int pin; 620 621 vatpic = vm_atpic(vm); 622 623 VATPIC_LOCK(vatpic); 624 625 pin = vector & 0x7; 626 627 if ((vector & IRQ_BASE_MASK) == vatpic->atpic[1].irq_base) { 628 vatpic_pin_accepted(&vatpic->atpic[1], pin); 629 /* 630 * If this vector originated from the slave, 631 * accept the cascaded interrupt too. 632 */ 633 vatpic_pin_accepted(&vatpic->atpic[0], 2); 634 } else { 635 vatpic_pin_accepted(&vatpic->atpic[0], pin); 636 } 637 638 vatpic_notify_intr(vatpic); 639 640 VATPIC_UNLOCK(vatpic); 641 } 642 643 static int 644 vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 645 int bytes, uint32_t *eax) 646 { 647 int pin; 648 649 VATPIC_LOCK(vatpic); 650 651 if (atpic->poll) { 652 atpic->poll = false; 653 pin = vatpic_get_highest_irrpin(atpic); 654 if (pin >= 0) { 655 vatpic_pin_accepted(atpic, pin); 656 *eax = 0x80 | pin; 657 } else { 658 *eax = 0; 659 } 660 } else { 661 if (port & ICU_IMR_OFFSET) { 662 /* read interrrupt mask register */ 663 *eax = atpic->reg_imr; 664 } else { 665 if (atpic->read_isr_next) { 666 /* read interrupt service register */ 667 *eax = atpic->reg_isr; 668 } else { 669 /* read interrupt request register */ 670 *eax = atpic->reg_irr; 671 } 672 } 673 } 674 675 VATPIC_UNLOCK(vatpic); 676 677 return (0); 678 679 } 680 681 static int 682 vatpic_write(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, 683 int bytes, uint32_t *eax) 684 { 685 int error; 686 uint8_t val; 687 688 error = 0; 689 val = *eax; 690 691 VATPIC_LOCK(vatpic); 692 693 if (port & ICU_IMR_OFFSET) { 694 switch (atpic->icw_state) { 695 case IS_ICW2: 696 error = vatpic_icw2(vatpic, atpic, val); 697 break; 698 case IS_ICW3: 699 error = vatpic_icw3(vatpic, atpic, val); 700 break; 701 case IS_ICW4: 702 error = vatpic_icw4(vatpic, atpic, val); 703 break; 704 default: 705 error = vatpic_ocw1(vatpic, atpic, val); 706 break; 707 } 708 } else { 709 if (val & (1 << 4)) 710 error = vatpic_icw1(vatpic, atpic, val); 711 712 if (atpic->ready) { 713 if (val & (1 << 3)) 714 error = vatpic_ocw3(vatpic, atpic, val); 715 else 716 error = vatpic_ocw2(vatpic, atpic, val); 717 } 718 } 719 720 if (atpic->ready) 721 vatpic_notify_intr(vatpic); 722 723 VATPIC_UNLOCK(vatpic); 724 725 return (error); 726 } 727 728 int 729 vatpic_master_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 730 uint32_t *eax) 731 { 732 struct vatpic *vatpic = arg; 733 struct atpic *atpic = &vatpic->atpic[0]; 734 735 if (bytes != 1) 736 return (-1); 737 738 if (in) { 739 return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); 740 } 741 742 return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); 743 } 744 745 int 746 vatpic_slave_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 747 uint32_t *eax) 748 { 749 struct vatpic *vatpic = arg; 750 struct atpic *atpic = &vatpic->atpic[1]; 751 752 if (bytes != 1) 753 return (-1); 754 755 if (in) { 756 return (vatpic_read(vatpic, atpic, in, port, bytes, eax)); 757 } 758 759 return (vatpic_write(vatpic, atpic, in, port, bytes, eax)); 760 } 761 762 int 763 vatpic_elc_handler(void *arg, bool in, uint16_t port, uint8_t bytes, 764 uint32_t *eax) 765 { 766 struct vatpic *vatpic = arg; 767 struct atpic *atpic = NULL; 768 uint8_t elc_mask = 0; 769 770 switch (port) { 771 case IO_ELCR1: 772 atpic = &vatpic->atpic[0]; 773 /* 774 * For the master PIC the cascade channel (IRQ2), the heart beat 775 * timer (IRQ0), and the keyboard controller (IRQ1) cannot be 776 * programmed for level mode. 777 */ 778 elc_mask = 0xf8; 779 break; 780 case IO_ELCR2: 781 atpic = &vatpic->atpic[1]; 782 /* 783 * For the slave PIC the real time clock (IRQ8) and the floating 784 * point error interrupt (IRQ13) cannot be programmed for level 785 * mode. 786 */ 787 elc_mask = 0xde; 788 break; 789 default: 790 return (-1); 791 } 792 793 if (bytes != 1) 794 return (-1); 795 796 VATPIC_LOCK(vatpic); 797 if (in) { 798 *eax = atpic->elc; 799 } else { 800 atpic->elc = *eax & elc_mask; 801 } 802 VATPIC_UNLOCK(vatpic); 803 804 return (0); 805 } 806 807 struct vatpic * 808 vatpic_init(struct vm *vm) 809 { 810 struct vatpic *vatpic; 811 812 vatpic = malloc(sizeof (struct vatpic), M_VATPIC, M_WAITOK | M_ZERO); 813 vatpic->vm = vm; 814 815 mutex_init(&vatpic->lock, NULL, MUTEX_ADAPTIVE, NULL); 816 817 return (vatpic); 818 } 819 820 void 821 vatpic_cleanup(struct vatpic *vatpic) 822 { 823 mutex_destroy(&vatpic->lock); 824 free(vatpic, M_VATPIC); 825 } 826