/* return the pic wanted interrupt. return -1 if none */ static int pic_get_irq(PPICSTATE pPic) { int mask, cur_priority, priority; Log(("pic_get_irq%d: mask=%x\n", pPic->idxPic, pPic->irr & ~pPic->imr)); DumpPICState(pPic, "pic_get_irq"); mask = pPic->irr & ~pPic->imr; priority = get_priority(pPic, mask); Log(("pic_get_irq: priority=%x\n", priority)); if (priority == 8) return -1; /* compute current priority. If special fully nested mode on the master, the IRQ coming from the slave is not taken into account for the priority computation. */ mask = pPic->isr; if (pPic->special_fully_nested_mode && pPic->idxPic == 0) mask &= ~(1 << 2); cur_priority = get_priority(pPic, mask); Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", pPic->idxPic, cur_priority, (priority == 8) ? -1 : (priority + pPic->priority_add) & 7)); if (priority < cur_priority) { /* higher priority found: an irq should be generated */ return (priority + pPic->priority_add) & 7; } return -1; }
/* return the pic wanted interrupt. return -1 if none */ static int pic_get_irq(PicState *s) { PicState *pics = &(PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC))->aPics[0]; int mask, cur_priority, priority; Log(("pic_get_irq%d: mask=%x\n", (s == pics) ? 0 : 1, s->irr & ~s->imr)); DumpPICState(s, "pic_get_irq"); mask = s->irr & ~s->imr; priority = get_priority(s, mask); Log(("pic_get_irq: priority=%x\n", priority)); if (priority == 8) return -1; /* compute current priority. If special fully nested mode on the master, the IRQ coming from the slave is not taken into account for the priority computation. */ mask = s->isr; if (s->special_fully_nested_mode && s == &pics[0]) mask &= ~(1 << 2); cur_priority = get_priority(s, mask); Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", (s == pics) ? 0 : 1, cur_priority, (priority == 8) ? -1 : (priority + s->priority_add) & 7)); if (priority < cur_priority) { /* higher priority found: an irq should be generated */ return (priority + s->priority_add) & 7; } else { return -1; } }
/* set irq level. If an edge is detected, then the IRR is set to 1 */ static inline void pic_set_irq1(PicState *s, int irq, int level) { int mask; Log(("pic_set_irq1: irq=%d level=%d\n", irq, level)); mask = 1 << irq; if (s->elcr & mask) { /* level triggered */ if (level) { Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", s->irr, s->irr | mask)); s->irr |= mask; s->last_irr |= mask; } else { Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", s->irr, s->irr & ~mask)); s->irr &= ~mask; s->last_irr &= ~mask; } } else { /* edge triggered */ if (level) { if ((s->last_irr & mask) == 0) { Log2(("pic_set_irq1 irr=%x last_irr=%x\n", s->irr | mask, s->last_irr)); s->irr |= mask; } s->last_irr |= mask; } else { s->irr &= ~mask; s->last_irr &= ~mask; } } DumpPICState(s, "pic_set_irq1"); }
/** * 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); }
/* set irq level. If an edge is detected, then the IRR is set to 1 */ DECLINLINE(void) pic_set_irq1(PPICSTATE pPic, int irq, int level, uint32_t uTagSrc) { Log(("pic_set_irq1: irq=%d level=%d\n", irq, level)); int mask = 1 << irq; if (pPic->elcr & mask) { /* level triggered */ if (level) { Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", pPic->irr, pPic->irr | mask)); pPic->irr |= mask; pPic->last_irr |= mask; } else { Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", pPic->irr, pPic->irr & ~mask)); pPic->irr &= ~mask; pPic->last_irr &= ~mask; } } else { /* edge triggered */ if (level) { if ((pPic->last_irr & mask) == 0) { Log2(("pic_set_irq1 irr=%x last_irr=%x\n", pPic->irr | mask, pPic->last_irr)); pPic->irr |= mask; } pPic->last_irr |= mask; } else { pPic->irr &= ~mask; pPic->last_irr &= ~mask; } } /* Save the tag. */ if (level) { if (!pPic->auTags[irq]) pPic->auTags[irq] = uTagSrc; else pPic->auTags[irq] |= RT_BIT_32(31); } DumpPICState(pPic, "pic_set_irq1"); }