void MsiNotify(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, int iVector, int iLevel, uint32_t uTagSrc) { AssertMsg(msiIsEnabled(pDev), ("Must be enabled to use that")); uint32_t uMask = *msiGetMaskBits(pDev); uint32_t* puPending = msiGetPendingBits(pDev); LogFlow(("MsiNotify: %d pending=%x mask=%x\n", iVector, *puPending, uMask)); /* We only trigger MSI on level up */ if ((iLevel & PDM_IRQ_LEVEL_HIGH) == 0) { /* @todo: maybe clear pending interrupts on level down? */ #if 0 *puPending &= ~(1<<iVector); LogFlow(("msi: clear pending %d, now %x\n", iVector, *puPending)); #endif return; } if ((uMask & (1<<iVector)) != 0) { *puPending |= (1<<iVector); LogFlow(("msi: %d is masked, mark pending, now %x\n", iVector, *puPending)); return; } RTGCPHYS GCAddr = msiGetMsiAddress(pDev); uint32_t u32Value = msiGetMsiData(pDev, iVector); *puPending &= ~(1<<iVector); Assert(pPciHlp->pfnIoApicSendMsi != NULL); pPciHlp->pfnIoApicSendMsi(pDevIns, GCAddr, u32Value, uTagSrc); }
void MsixNotify(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, int iVector, int iLevel, uint32_t uTagSrc) { AssertMsg(msixIsEnabled(pDev), ("Must be enabled to use that")); Assert(pPciHlp->pfnIoApicSendMsi != NULL); /* We only trigger MSI-X on level up */ if ((iLevel & PDM_IRQ_LEVEL_HIGH) == 0) { return; } // if this vector is somehow disabled if (msixIsMasked(pDev) || msixIsVectorMasked(pDev, iVector)) { // mark pending bit msixSetPending(pDev, iVector); return; } // clear pending bit msixClearPending(pDev, iVector); RTGCPHYS GCAddr = msixGetMsiAddress(pDev, iVector); uint32_t u32Value = msixGetMsiData(pDev, iVector); pPciHlp->pfnIoApicSendMsi(pDevIns, GCAddr, u32Value, uTagSrc); }