Lines Matching +full:virtual +full:- +full:wire +full:- +full:mode
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
52 static MALLOC_DEFINE(M_VATPIC, "atpic", "bhyve virtual atpic (8259)");
54 #define VATPIC_LOCK(vatpic) mtx_lock_spin(&((vatpic)->mtx))
55 #define VATPIC_UNLOCK(vatpic) mtx_unlock_spin(&((vatpic)->mtx))
56 #define VATPIC_LOCKED(vatpic) mtx_owned(&((vatpic)->mtx))
72 bool sfn; /* special fully-nested mode */
78 uint8_t smm; /* special mask mode */
94 VM_CTR0((vatpic)->vm, fmt)
97 VM_CTR1((vatpic)->vm, fmt, a1)
100 VM_CTR2((vatpic)->vm, fmt, a1, a2)
103 VM_CTR3((vatpic)->vm, fmt, a1, a2, a3)
106 VM_CTR4((vatpic)->vm, fmt, a1, a2, a3, a4)
112 for (tmpvar = 0, pinvar = (atpic->lowprio + 1) & 0x7; \
122 if (atpic == &vatpic->atpic[0])
137 if (atpic->service & bit) {
140 * cleared by a non-specific EOI in Special Mask Mode.
142 if (atpic->smm && (atpic->mask & bit) != 0)
149 return (-1);
159 * In 'Special Fully-Nested Mode' when an interrupt request from
163 serviced = atpic->service;
164 if (atpic->sfn)
168 * In 'Special Mask Mode', when a mask bit is set in OCW1 it inhibits
173 if (atpic->smm)
190 if ((atpic->request & bit) != 0 && (atpic->mask & bit) == 0)
194 return (-1);
208 atpic = &vatpic->atpic[1];
209 if (!atpic->intr_raised &&
210 (pin = vatpic_get_highest_irrpin(atpic)) != -1) {
213 atpic->mask, atpic->request, atpic->service);
218 atpic->intr_raised = true;
224 atpic->mask, atpic->request, atpic->service);
230 atpic = &vatpic->atpic[0];
231 if (!atpic->intr_raised &&
232 (pin = vatpic_get_highest_irrpin(atpic)) != -1) {
235 atpic->mask, atpic->request, atpic->service);
245 * 1. Legacy PIC Mode: the PIC effectively bypasses
246 * all APIC components. In this mode the local APIC is
250 * 2. Virtual Wire Mode: the APIC is treated as a
251 * virtual wire which delivers interrupts from the PIC
252 * to the CPU. In this mode LINT0 is programmed as
256 * 3. Virtual Wire Mode via I/O APIC: PIC interrupts are
258 * CPU. In this mode the I/O APIC input 0 is programmed
262 atpic->intr_raised = true;
263 lapic_set_local_intr(vatpic->vm, NULL, APIC_LVT_LINT0);
264 vioapic_pulse_irq(vatpic->vm, 0);
268 atpic->mask, atpic->request, atpic->service);
277 atpic->ready = false;
279 atpic->icw_num = 1;
280 atpic->request = 0;
281 atpic->mask = 0;
282 atpic->lowprio = 7;
283 atpic->rd_cmd_reg = 0;
284 atpic->poll = 0;
285 atpic->smm = 0;
288 VATPIC_CTR0(vatpic, "vatpic cascade mode required");
289 return (-1);
294 return (-1);
297 atpic->icw_num++;
307 atpic->irq_base = val & 0xf8;
309 atpic->icw_num++;
319 atpic->icw_num++;
330 VATPIC_CTR0(vatpic, "vatpic microprocessor mode required");
331 return (-1);
335 atpic->aeoi = true;
339 atpic->sfn = true;
342 "mode on slave atpic: %#x", val);
346 atpic->icw_num = 0;
347 atpic->ready = true;
357 atpic->mask = val & 0xff;
367 atpic->rotate = ((val & OCW2_R) != 0);
376 /* non-specific EOI */
380 if (isr_bit != -1) {
381 atpic->service &= ~(1 << isr_bit);
383 if (atpic->rotate)
384 atpic->lowprio = isr_bit;
386 } else if ((val & OCW2_SL) != 0 && atpic->rotate == true) {
388 atpic->lowprio = val & 0x7;
400 atpic->smm = val & OCW3_SMM ? 1 : 0;
401 VATPIC_CTR2(vatpic, "%s atpic special mask mode %s",
403 atpic->smm ? "enabled" : "disabled");
408 atpic->rd_cmd_reg = val & OCW3_RIS;
410 /* Polling mode */
411 atpic->poll = ((val & OCW3_P) != 0);
429 atpic = &vatpic->atpic[pin >> 3];
431 oldcnt = atpic->acnt[pin & 0x7];
433 atpic->acnt[pin & 0x7]++;
435 atpic->acnt[pin & 0x7]--;
436 newcnt = atpic->acnt[pin & 0x7];
442 level = ((vatpic->elc[pin >> 3] & (1 << (pin & 0x7))) != 0);
447 atpic->request |= (1 << (pin & 0x7));
452 atpic->request &= ~(1 << (pin & 0x7));
471 atpic = &vatpic->atpic[irq >> 3];
473 if (atpic->ready == false)
542 vatpic->elc[irq >> 3] |= 1 << (irq & 0x7);
544 vatpic->elc[irq >> 3] &= ~(1 << (irq & 0x7));
560 atpic = &vatpic->atpic[0];
566 atpic = &vatpic->atpic[1];
574 if (pin == -1)
578 *vecptr = atpic->irq_base + pin;
586 atpic->intr_raised = false;
588 if (atpic->acnt[pin] == 0)
589 atpic->request &= ~(1 << pin);
591 if (atpic->aeoi == true) {
592 if (atpic->rotate == true)
593 atpic->lowprio = pin;
595 atpic->service |= (1 << pin);
611 if ((vector & ~0x7) == vatpic->atpic[1].irq_base) {
612 vatpic_pin_accepted(&vatpic->atpic[1], pin);
617 vatpic_pin_accepted(&vatpic->atpic[0], 2);
619 vatpic_pin_accepted(&vatpic->atpic[0], pin);
635 if (atpic->poll) {
636 atpic->poll = 0;
647 *eax = atpic->mask;
649 if (atpic->rd_cmd_reg == OCW3_RIS) {
651 *eax = atpic->service;
654 *eax = atpic->request;
678 switch (atpic->icw_num) {
696 if (atpic->ready) {
704 if (atpic->ready)
720 atpic = &vatpic->atpic[0];
723 return (-1);
740 atpic = &vatpic->atpic[1];
743 return (-1);
763 return (-1);
769 *eax = vatpic->elc[0];
771 *eax = vatpic->elc[1];
777 * mode.
781 * be programmed for level mode.
784 vatpic->elc[0] = (*eax & 0xf8);
786 vatpic->elc[1] = (*eax & 0xde);
800 vatpic->vm = vm;
802 mtx_init(&vatpic->mtx, "vatpic lock", NULL, MTX_SPIN);
810 mtx_destroy(&vatpic->mtx);
822 for (i = 0; i < nitems(vatpic->atpic); i++) {
823 atpic = &vatpic->atpic[i];
825 SNAPSHOT_VAR_OR_LEAVE(atpic->ready, meta, ret, done);
826 SNAPSHOT_VAR_OR_LEAVE(atpic->icw_num, meta, ret, done);
827 SNAPSHOT_VAR_OR_LEAVE(atpic->rd_cmd_reg, meta, ret, done);
829 SNAPSHOT_VAR_OR_LEAVE(atpic->aeoi, meta, ret, done);
830 SNAPSHOT_VAR_OR_LEAVE(atpic->poll, meta, ret, done);
831 SNAPSHOT_VAR_OR_LEAVE(atpic->rotate, meta, ret, done);
832 SNAPSHOT_VAR_OR_LEAVE(atpic->sfn, meta, ret, done);
833 SNAPSHOT_VAR_OR_LEAVE(atpic->irq_base, meta, ret, done);
834 SNAPSHOT_VAR_OR_LEAVE(atpic->request, meta, ret, done);
835 SNAPSHOT_VAR_OR_LEAVE(atpic->service, meta, ret, done);
836 SNAPSHOT_VAR_OR_LEAVE(atpic->mask, meta, ret, done);
837 SNAPSHOT_VAR_OR_LEAVE(atpic->smm, meta, ret, done);
839 SNAPSHOT_BUF_OR_LEAVE(atpic->acnt, sizeof(atpic->acnt),
841 SNAPSHOT_VAR_OR_LEAVE(atpic->lowprio, meta, ret, done);
842 SNAPSHOT_VAR_OR_LEAVE(atpic->intr_raised, meta, ret, done);
845 SNAPSHOT_BUF_OR_LEAVE(vatpic->elc, sizeof(vatpic->elc),