Exemplo n.º 1
0
/** @note if an interrupt line state changes from unmasked to masked, then it must be deactivated when currently pending! */
static void pic_update_imr(PDEVPIC pThis, PPICSTATE pPic, uint8_t val)
{
    int       irq, intno;
    PPICSTATE pActivePIC;

    /* Query the current pending irq, if any. */
    pActivePIC = &pThis->aPics[0];
    intno = irq = pic_get_irq(pActivePIC);
    if (irq == 2)
    {
        pActivePIC = &pThis->aPics[1];
        irq = pic_get_irq(pActivePIC);
        intno = irq + 8;
    }

    /* Update IMR */
    Log(("pic_update_imr: pic%u %#x -> %#x\n", pPic->idxPic, pPic->imr, val));
    pPic->imr = val;

    /* If an interrupt is pending and now masked, then clear the FF flag. */
    if (    irq >= 0
        &&  ((1 << irq) & ~pActivePIC->imr) == 0)
    {
        Log(("pic_update_imr: pic0: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
            pThis->aPics[0].elcr, pThis->aPics[0].last_irr, pThis->aPics[0].irr, pThis->aPics[0].imr, pThis->aPics[0].isr, pThis->aPics[0].irq_base));
        Log(("pic_update_imr: pic1: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
            pThis->aPics[1].elcr, pThis->aPics[1].last_irr, pThis->aPics[1].irr, pThis->aPics[1].imr, pThis->aPics[1].isr, pThis->aPics[1].irq_base));

        /* Clear pending IRQ 2 on master controller in case of slave interrupt. */
        /** @todo Is this correct? */
        if (intno > 7)
        {
            pThis->aPics[0].irr &= ~(1 << 2);
            STAM_COUNTER_INC(&pThis->StatClearedActiveSlaveIRQ);
        }
        else
            STAM_COUNTER_INC(&pThis->StatClearedActiveMasterIRQ);

        Log(("pic_update_imr: clear pending interrupt %d\n", intno));
        pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
    }
}
Exemplo n.º 2
0
/**
 * Set the an IRQ.
 *
 * @param   pDevIns         Device instance of the PICs.
 * @param   iIrq            IRQ number to set.
 * @param   iLevel          IRQ level.
 * @param   uTagSrc         The IRQ tag and source ID (for tracing).
 */
PDMBOTHCBDECL(void) picSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc)
{
    PDEVPIC     pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
    Assert(pThis->CTX_SUFF(pDevIns) == pDevIns);
    Assert(pThis->aPics[0].CTX_SUFF(pDevIns) == pDevIns);
    Assert(pThis->aPics[1].CTX_SUFF(pDevIns) == pDevIns);
    AssertMsg(iIrq < 16, ("iIrq=%d\n", iIrq));

    Log(("picSetIrq %d %d\n", iIrq, iLevel));
    DumpPICState(&pThis->aPics[0], "picSetIrq");
    DumpPICState(&pThis->aPics[1], "picSetIrq");
    STAM_COUNTER_INC(&pThis->CTXSUFF(StatSetIrq));
    if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP)
    {
        /* A flip-flop lowers the IRQ line and immediately raises it, so
         * that a rising edge is guaranteed to occur. Note that the IRQ
         * line must be held high for a while to avoid spurious interrupts.
         */
        pic_set_irq1(&pThis->aPics[iIrq >> 3], iIrq & 7, 0, uTagSrc);
        pic_update_irq(pThis);
    }
Exemplo n.º 3
0
/* raise irq to CPU if necessary. must be called every time the active
   irq may change */
static int pic_update_irq(PDEVPIC pThis)
{
    PicState *pics = &pThis->aPics[0];
    int irq2, irq;

    /* first look at slave pic */
    irq2 = pic_get_irq(&pics[1]);
    Log(("pic_update_irq irq2=%d\n", irq2));
    if (irq2 >= 0) {
        /* if irq request by slave pic, signal master PIC */
        pic_set_irq1(&pics[0], 2, 1);
    } else {
        /* If not, clear the IR on the master PIC. */
        pic_set_irq1(&pics[0], 2, 0);
    }
    /* look at requested irq */
    irq = pic_get_irq(&pics[0]);
    if (irq >= 0)
    {
        /* If irq 2 is pending on the master pic, then there must be one pending on the slave pic too! Otherwise we'll get
         * spurious slave interrupts in picGetInterrupt.
         */
        if (irq != 2 || irq2 != -1)
        {
#if defined(DEBUG_PIC)
            int i;
            for(i = 0; i < 2; i++) {
                Log(("pic%d: imr=%x irr=%x padd=%d\n",
                    i, pics[i].imr, pics[i].irr,
                    pics[i].priority_add));
            }
            Log(("pic: cpu_interrupt\n"));
#endif
            pThis->CTX_SUFF(pPicHlp)->pfnSetInterruptFF(pThis->CTX_SUFF(pDevIns));
        }
        else
        {
            STAM_COUNTER_INC(&pThis->StatClearedActiveIRQ2);
            Log(("pic_update_irq: irq 2 is active, but no interrupt is pending on the slave pic!!\n"));
            /* Clear it here, so lower priority interrupts can still be dispatched. */

            /* if this was the only pending irq, then we must clear the interrupt ff flag */
            pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));

            /** @note Is this correct? */
            pics[0].irr &= ~(1 << 2);

            /* Call ourselves again just in case other interrupts are pending */
            return pic_update_irq(pThis);
        }
    }
    else
    {
        Log(("pic_update_irq: no interrupt is pending!!\n"));

        /* we must clear the interrupt ff flag */
        pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
    }
    return VINF_SUCCESS;
}