/** * Sets an irq on the PIC and I/O APIC. * * @returns true if delivered, false if postponed. * @param pVM Pointer to the VM. * @param iIrq The irq. * @param iLevel The new level. * @param uTagSrc The IRQ tag and source. * * @remarks The caller holds the PDM lock. */ static bool pdmR0IsaSetIrq(PVM pVM, int iIrq, int iLevel, uint32_t uTagSrc) { if (RT_LIKELY( ( pVM->pdm.s.IoApic.pDevInsR0 || !pVM->pdm.s.IoApic.pDevInsR3) && ( pVM->pdm.s.Pic.pDevInsR0 || !pVM->pdm.s.Pic.pDevInsR3))) { if (pVM->pdm.s.Pic.pDevInsR0) pVM->pdm.s.Pic.pfnSetIrqR0(pVM->pdm.s.Pic.pDevInsR0, iIrq, iLevel, uTagSrc); if (pVM->pdm.s.IoApic.pDevInsR0) pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc); return true; } /* queue for ring-3 execution. */ PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0); AssertReturn(pTask, false); pTask->enmOp = PDMDEVHLPTASKOP_ISA_SET_IRQ; pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */ pTask->u.SetIRQ.iIrq = iIrq; pTask->u.SetIRQ.iLevel = iLevel; pTask->u.SetIRQ.uTagSrc = uTagSrc; PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0); return false; }
/** @interface_method_impl{PDMPCIHLPR0,pfnIoApicSetIrq} */ static DECLCALLBACK(void) pdmR0PciHlp_IoApicSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc) { PDMDEV_ASSERT_DEVINS(pDevIns); Log4(("pdmR0PciHlp_IoApicSetIrq: iIrq=%d iLevel=%d uTagSrc=%#x\n", iIrq, iLevel, uTagSrc)); PVM pVM = pDevIns->Internal.s.pVMR0; if (pVM->pdm.s.IoApic.pDevInsR0) { pdmLock(pVM); pVM->pdm.s.IoApic.pfnSetIrqR0(pVM->pdm.s.IoApic.pDevInsR0, iIrq, iLevel, uTagSrc); pdmUnlock(pVM); } else if (pVM->pdm.s.IoApic.pDevInsR3) { /* queue for ring-3 execution. */ PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0); if (pTask) { pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ; pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */ pTask->u.SetIRQ.iIrq = iIrq; pTask->u.SetIRQ.iLevel = iLevel; pTask->u.SetIRQ.uTagSrc = uTagSrc; PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0); } else AssertMsgFailed(("We're out of devhlp queue items!!!\n")); } }
/** * Sets an irq on the I/O APIC. * * @param pVM The VM handle. * @param iIrq The irq. * @param iLevel The new level. */ static void pdmRCIoApicSetIrq(PVM pVM, int iIrq, int iLevel) { if (pVM->pdm.s.IoApic.pDevInsRC) { pdmLock(pVM); pVM->pdm.s.IoApic.pfnSetIrqRC(pVM->pdm.s.IoApic.pDevInsRC, iIrq, iLevel); pdmUnlock(pVM); } else if (pVM->pdm.s.IoApic.pDevInsR3) { /* queue for ring-3 execution. */ PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC); if (pTask) { pTask->enmOp = PDMDEVHLPTASKOP_IOAPIC_SET_IRQ; pTask->pDevInsR3 = NIL_RTR3PTR; /* not required */ pTask->u.SetIRQ.iIrq = iIrq; pTask->u.SetIRQ.iLevel = iLevel; PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0); } else AssertMsgFailed(("We're out of devhlp queue items!!!\n")); } }
/** @interface_method_impl{PDMDEVHLPRC,pfnPCISetIrq} */ static DECLCALLBACK(void) pdmRCDevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel) { PDMDEV_ASSERT_DEVINS(pDevIns); LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel)); PVM pVM = pDevIns->Internal.s.pVMRC; PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceRC; PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusRC; if ( pPciDev && pPciBus && pPciBus->pDevInsRC) { pdmLock(pVM); pPciBus->pfnSetIrqRC(pPciBus->pDevInsRC, pPciDev, iIrq, iLevel); pdmUnlock(pVM); } else { /* queue for ring-3 execution. */ PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueRC); if (pTask) { pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ; pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns); pTask->u.SetIRQ.iIrq = iIrq; pTask->u.SetIRQ.iLevel = iLevel; PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueRC, &pTask->Core, 0); } else AssertMsgFailed(("We're out of devhlp queue items!!!\n")); } LogFlow(("pdmRCDevHlp_PCISetIrq: caller=%p/%d: returns void\n", pDevIns, pDevIns->iInstance)); }
/** * Queues a keyboard event. * Because of the event queueing the EMT context requirement is lifted. * * @returns VBox status code. * @param pInterface Pointer to this interface structure. * @param u8ScanCode The scan code to translate/queue. * @thread Any thread. */ static DECLCALLBACK(int) drvKbdQueuePutEventScan(PPDMIKEYBOARDPORT pInterface, uint8_t u8ScanCode) { PDRVKBDQUEUE pDrv = IKEYBOARDPORT_2_DRVKBDQUEUE(pInterface); /* Ignore any attempt to send events if queue is inactive. */ if (pDrv->fInactive) return VINF_SUCCESS; uint32_t u32Usage = 0; pDrv->XlatState = ScancodeToHidUsage(pDrv->XlatState, u8ScanCode, &u32Usage); if (pDrv->XlatState == SS_IDLE) { PDRVKBDQUEUEITEM pItem = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue); if (pItem) { /* * Work around incredibly poorly desgined Korean keyboards which * only send break events for Hangul/Hanja keys -- convert a lone * key up into a key up/key down sequence. */ if (u32Usage == 0x80000090 || u32Usage == 0x80000091) { PDRVKBDQUEUEITEM pItem2 = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue); /* * NB: If there's no room in the queue, we will drop the faked * key down event. Probably less bad than the alternatives. */ if (pItem2) { /* Manufacture a key down event. */ pItem2->u32UsageCode = u32Usage & ~0x80000000; PDMQueueInsert(pDrv->pQueue, &pItem2->Core); } } pItem->u32UsageCode = u32Usage; PDMQueueInsert(pDrv->pQueue, &pItem->Core); return VINF_SUCCESS; } if (!pDrv->fSuspended) AssertMsgFailed(("drvKbdQueuePutEventScan: Queue is full!!!!\n")); return VERR_PDM_NO_QUEUE_ITEMS; } else return VINF_SUCCESS; }
/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */ static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel) { PDMDEV_ASSERT_DEVINS(pDevIns); LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel)); PVM pVM = pDevIns->Internal.s.pVMR0; PPCIDEVICE pPciDev = pDevIns->Internal.s.pPciDeviceR0; PPDMPCIBUS pPciBus = pDevIns->Internal.s.pPciBusR0; pdmLock(pVM); uint32_t uTagSrc; if (iLevel & PDM_IRQ_LEVEL_HIGH) { pDevIns->Internal.s.uLastIrqTag = uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing); if (iLevel == PDM_IRQ_LEVEL_HIGH) VBOXVMM_PDM_IRQ_HIGH(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc)); else VBOXVMM_PDM_IRQ_HILO(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc)); } else uTagSrc = pDevIns->Internal.s.uLastIrqTag; if ( pPciDev && pPciBus && pPciBus->pDevInsR0) { pPciBus->pfnSetIrqR0(pPciBus->pDevInsR0, pPciDev, iIrq, iLevel, uTagSrc); pdmUnlock(pVM); if (iLevel == PDM_IRQ_LEVEL_LOW) VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc)); } else { pdmUnlock(pVM); /* queue for ring-3 execution. */ PPDMDEVHLPTASK pTask = (PPDMDEVHLPTASK)PDMQueueAlloc(pVM->pdm.s.pDevHlpQueueR0); AssertReturnVoid(pTask); pTask->enmOp = PDMDEVHLPTASKOP_PCI_SET_IRQ; pTask->pDevInsR3 = PDMDEVINS_2_R3PTR(pDevIns); pTask->u.SetIRQ.iIrq = iIrq; pTask->u.SetIRQ.iLevel = iLevel; pTask->u.SetIRQ.uTagSrc = uTagSrc; PDMQueueInsertEx(pVM->pdm.s.pDevHlpQueueR0, &pTask->Core, 0); } LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc)); }