static void bms_timer(void *opaque) { MouState *s = (MouState*)opaque; uint8_t irq_bit; /* Toggle the IRQ line if interrupts are enabled. */ irq_bit = BMS_IRQ_BIT(s->irq); if (s->port_c & irq_bit) { if (!(s->port_c & BMS_CTL_INT_DIS)) PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, PDM_IRQ_LEVEL_LOW); s->port_c &= ~irq_bit; } else { s->port_c |= irq_bit; if (!(s->port_c & BMS_CTL_INT_DIS)) PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), s->irq, PDM_IRQ_LEVEL_HIGH); } /* Handle enabling/disabling of the mouse interface. */ if (s->port_c & BMS_CTL_INT_DIS) { if (s->disable_counter) --s->disable_counter; if (s->disable_counter == 0 && s->mouse_enabled) { s->mouse_enabled = false; bms_update_downstream_status(s); } } else { s->disable_counter = 8; /* Re-arm the disable countdown. */ if (!s->mouse_enabled) { s->mouse_enabled = true; bms_update_downstream_status(s); } } }
static void kbc_dbb_out(void *opaque, uint8_t val) { KBDState *s = (KBDState*)opaque; s->dbbout = val; /* Set the OBF and raise IRQ. */ s->status |= KBD_STAT_OBF; if (s->mode & KBD_MODE_KBD_INT) PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 1, 1); }
static void kbc_dbb_out_aux(void *opaque, uint8_t val) { KBDState *s = (KBDState*)opaque; s->dbbout = val; /* Set the aux OBF and raise IRQ. */ s->status |= KBD_STAT_OBF | KBD_STAT_MOUSE_OBF; if (s->mode & KBD_MODE_MOUSE_INT) PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 12, PDM_IRQ_LEVEL_HIGH); }
static uint32_t kbd_read_data(void *opaque, uint32_t addr) { KBDState *s = (KBDState*)opaque; uint32_t val; NOREF(addr); /* Return the current DBB contents. */ val = s->dbbout; /* Reading the DBB deasserts IRQs... */ if (s->status & KBD_STAT_MOUSE_OBF) PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 12, 0); else PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 1, 0); /* ...and clears the OBF bits. */ s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); /* Check if more data is available. */ kbd_update_irq(s); #ifdef DEBUG_KBD Log(("kbd: read data=0x%02x\n", val)); #endif return val; }
/* update irq and KBD_STAT_[MOUSE_]OBF */ static void kbd_update_irq(KBDState *s) { int irq12_level, irq1_level; uint8_t val; irq1_level = 0; irq12_level = 0; /* Determine new OBF state, but only if OBF is clear. If OBF was already * set, we cannot risk changing the event type after an ISR potentially * started executing! Only kbd_read_data() clears the OBF bits. */ if (!(s->status & KBD_STAT_OBF)) { s->status &= ~KBD_STAT_MOUSE_OBF; /* Keyboard data has priority if both kbd and aux data is available. */ if (!(s->mode & KBD_MODE_DISABLE_KBD) && PS2KByteFromKbd(&s->Kbd, &val) == VINF_SUCCESS) { bool fHaveData = true; /* If scancode translation is on (it usually is), there's more work to do. */ if (s->translate) { uint8_t xlated_val; s->xlat_state = XlateAT2PC(s->xlat_state, val, &xlated_val); val = xlated_val; /* If the translation state is XS_BREAK, there's nothing to report * and we keep going until the state changes or there's no more data. */ while (s->xlat_state == XS_BREAK && PS2KByteFromKbd(&s->Kbd, &val) == VINF_SUCCESS) { s->xlat_state = XlateAT2PC(s->xlat_state, val, &xlated_val); val = xlated_val; } /* This can happen if the last byte in the queue is F0... */ if (s->xlat_state == XS_BREAK) fHaveData = false; } if (fHaveData) { s->dbbout = val; s->status |= KBD_STAT_OBF; } } else if (!(s->mode & KBD_MODE_DISABLE_MOUSE) && PS2MByteFromAux(&s->Aux, &val) == VINF_SUCCESS) { s->dbbout = val; s->status |= KBD_STAT_OBF | KBD_STAT_MOUSE_OBF; } } /* Determine new IRQ state. */ if (s->status & KBD_STAT_OBF) { if (s->status & KBD_STAT_MOUSE_OBF) { if (s->mode & KBD_MODE_MOUSE_INT) irq12_level = 1; } else { /* KBD_STAT_OBF set but KBD_STAT_MOUSE_OBF isn't. */ if (s->mode & KBD_MODE_KBD_INT) irq1_level = 1; } } PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 1, irq1_level); PDMDevHlpISASetIrq(s->CTX_SUFF(pDevIns), 12, irq12_level); }