Index: sys/amd64/vmm/io/vatpic.c =================================================================== --- sys/amd64/vmm/io/vatpic.c (revision 275752) +++ sys/amd64/vmm/io/vatpic.c (working copy) @@ -75,7 +75,7 @@ uint8_t mask; /* Interrupt Mask Register (IMR) */ int acnt[8]; /* sum of pin asserts and deasserts */ - int priority; /* current pin priority */ + int lowprio; /* lowest priority input pin */ bool intr_raised; }; @@ -110,8 +110,9 @@ int bit, pin; int i; + pin = atpic->lowprio; for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); + pin = (pin + 1) & 0x7; bit = (1 << pin); if (atpic->service & bit) @@ -137,15 +138,17 @@ if (atpic->sfn) serviced &= ~(1 << 2); + pin = atpic->lowprio; for (i = 0; i <= 7; i++) { - pin = ((i + 7 - atpic->priority) & 0x7); + pin = (pin + 1) & 0x7; bit = (1 << pin); if (serviced & bit) break; } + pin = atpic->lowprio; for (j = 0; j < i; j++) { - pin = ((j + 7 - atpic->priority) & 0x7); + pin = (pin + 1) & 0x7; bit = (1 << pin); if (atpic->request & bit && (~atpic->mask & bit)) return (pin); @@ -238,8 +241,9 @@ atpic->icw_num = 1; atpic->mask = 0; - atpic->priority = 0; + atpic->lowprio = 7; atpic->rd_cmd_reg = 0; + atpic->poll = 0; if ((val & ICW1_SNGL) != 0) { VATPIC_CTR0(vatpic, "vatpic cascade mode required"); @@ -278,6 +282,16 @@ return (0); } +static __inline bool +master_atpic(struct vatpic *vatpic, struct atpic *atpic) +{ + + if (atpic == &vatpic->atpic[0]) + return (true); + else + return (false); +} + static int vatpic_icw4(struct vatpic *vatpic, struct atpic *atpic, uint8_t val) { @@ -291,6 +305,15 @@ if ((val & ICW4_AEOI) != 0) atpic->aeoi = true; + if ((val & ICW4_SFNM) != 0) { + if (master_atpic(vatpic, atpic)) { + atpic->sfn = true; + } else { + VATPIC_CTR1(vatpic, "Ignoring special fully nested " + "mode on slave atpic: %#x", val); + } + } + atpic->icw_num = 0; atpic->ready = true; @@ -329,11 +352,11 @@ atpic->service &= ~(1 << isr_bit); if (atpic->rotate) - atpic->priority = isr_bit; + atpic->lowprio = isr_bit; } } else if ((val & OCW2_SL) != 0 && atpic->rotate == true) { /* specific priority */ - atpic->priority = val & 0x7; + atpic->lowprio = val & 0x7; } return (0); @@ -344,11 +367,12 @@ { VATPIC_CTR1(vatpic, "atpic ocw3 0x%x", val); - atpic->poll = ((val & OCW3_P) != 0); - if (val & OCW3_RR) { /* read register command */ atpic->rd_cmd_reg = val & OCW3_RIS; + + /* Polling mode */ + atpic->poll = ((val & OCW3_P) != 0); } return (0); @@ -528,7 +552,7 @@ if (atpic->aeoi == true) { if (atpic->rotate == true) - atpic->priority = pin; + atpic->lowprio = pin; } else { atpic->service |= (1 << pin); } @@ -566,12 +590,19 @@ vatpic_read(struct vatpic *vatpic, struct atpic *atpic, bool in, int port, int bytes, uint32_t *eax) { + int pin; + VATPIC_LOCK(vatpic); if (atpic->poll) { - VATPIC_CTR0(vatpic, "vatpic polled mode not supported"); - VATPIC_UNLOCK(vatpic); - return (-1); + atpic->poll = 0; + pin = vatpic_get_highest_irrpin(atpic); + if (pin >= 0) { + vatpic_pin_accepted(atpic, pin); + *eax = 0x80 | pin; + } else { + *eax = 0; + } } else { if (port & ICU_IMR_OFFSET) { /* read interrrupt mask register */