Example #1
0
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);
        }
    }
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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;
}
Example #5
0
/* 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);
}