/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */ static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel) { PDMDEV_ASSERT_DEVINS(pDevIns); LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel)); PVM pVM = pDevIns->Internal.s.pVMR0; 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; bool fRc = pdmR0IsaSetIrq(pVM, iIrq, iLevel, uTagSrc); if (iLevel == PDM_IRQ_LEVEL_LOW && fRc) VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc)); pdmUnlock(pVM); LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, uTagSrc)); }
bool WinAltGrMonitor::isCurrentEventDefinitelyFake(unsigned iDownScanCode, bool fKeyDown, bool fExtendedKey) const { MSG peekMsg; LONG messageTime = GetMessageTime(); if ( iDownScanCode != 0x1d /* scan code: Control */ || fExtendedKey) return false; if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)) return false; if (messageTime != peekMsg.time) return false; if ( fKeyDown && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN)) return false; if ( !fKeyDown && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP)) return false; if ( ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */) || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED)) return false; if (!doesCurrentLayoutHaveAltGr()) return false; return true; }
/** @interface_method_impl{PDMHPETHLPR3,pfnSetIrq} */ static DECLCALLBACK(int) pdmR3HpetHlp_SetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel) { PDMDEV_ASSERT_DEVINS(pDevIns); LogFlow(("pdmR3HpetHlp_SetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel)); PVM pVM = pDevIns->Internal.s.pVMR3; 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; PDMIsaSetIrq(pVM, iIrq, iLevel, uTagSrc); /* (The API takes the lock recursively.) */ if (iLevel == PDM_IRQ_LEVEL_LOW) VBOXVMM_PDM_IRQ_LOW(VMMGetCpu(pVM), RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc)); pdmUnlock(pVM); return 0; }
/** * @brief isSyntheticLCtrl * @param pMsg Windows WM_[SYS]KEY* event message structure * @return true if this is a synthetic LCtrl event, false otherwise * This function is a heuristic to tell whether a key event is the first in * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr. Our * heuristic is in two parts. First of all, we check whether there is a pending * RAlt key event matching this LCtrl event (i.e. both key up or both key down) * and if there is, we check whether the current layout has an AltGr key. We * check this by looking to see if any of the layout-dependent keys has a symbol * associated when AltGr is pressed. */ static bool isSyntheticLCtrl(MSG *pMsg) { MSG peekMsg; /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */ const BYTE auKeyStates[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 }; WORD ach; unsigned i; Assert( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP); if ( ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */) || RT_HIWORD(pMsg->lParam) & KF_EXTENDED) return false; if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)) return false; if ( (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN)) return false; if ( (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP)) return false; if ( ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */) || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED)) return false; /* If we got this far then we have a key event which could potentially * be a synthetic left control. Now we check to see whether the current * keyboard layout actually has an AltGr key by checking whether any of * the keys which might do produce a symbol when AltGr (Control + Alt) is * depressed. Generally this loop will exit pretty early (it exits on the * first iteration for my German layout). If there is no AltGr key in the * layout then it will run right through, but that should not happen very * often as we should hardly ever reach the loop in that case. * * In theory we could do this once and cache the result, but that involves * tracking layout switches to invalidate the cache, and I don't think * that the added complexity is worth the price. */ for (i = '0'; i <= VK_OEM_102; ++i) { if (ToAscii(i, 0, auKeyStates, &ach, 0)) break; /* Skip ranges of virtual keys which are undefined or not relevant. */ if (i == '9') i = 'A' - 1; if (i == 'Z') i = VK_OEM_1 - 1; if (i == VK_OEM_3) i = VK_OEM_4 - 1; if (i == VK_OEM_8) i = VK_OEM_102 - 1; } if (i > VK_OEM_102) return false; return true; }
/** * Gets the pending interrupt. * * @returns VBox status code. * @param pVCpu Pointer to the VMCPU. * @param pu8Interrupt Where to store the interrupt on success. */ VMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt) { PVM pVM = pVCpu->CTX_SUFF(pVM); pdmLock(pVM); /* * The local APIC has a higher priority than the PIC. */ if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC)) { VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC); Assert(pVM->pdm.s.Apic.CTX_SUFF(pDevIns)); Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)); uint32_t uTagSrc; int i = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu, &uTagSrc); AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i)); if (i >= 0) { pdmUnlock(pVM); *pu8Interrupt = (uint8_t)i; VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i); return VINF_SUCCESS; } } /* * Check the PIC. */ if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_PIC)) { VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC); Assert(pVM->pdm.s.Pic.CTX_SUFF(pDevIns)); Assert(pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt)); uint32_t uTagSrc; int i = pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Pic.CTX_SUFF(pDevIns), &uTagSrc); AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i)); if (i >= 0) { pdmUnlock(pVM); *pu8Interrupt = (uint8_t)i; VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i); return VINF_SUCCESS; } } /** @todo Figure out exactly why we can get here without anything being set. (REM) */ pdmUnlock(pVM); return VERR_NO_DATA; }
/** @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)); }
/** * @copydoc RTNetIPv6PseudoChecksumBits */ DECLINLINE(uint32_t) rtNetIPv6PseudoChecksumBits(PCRTNETADDRIPV6 pSrcAddr, PCRTNETADDRIPV6 pDstAddr, uint8_t bProtocol, uint32_t cbPkt) { uint32_t u32Sum = pSrcAddr->au16[0] + pSrcAddr->au16[1] + pSrcAddr->au16[2] + pSrcAddr->au16[3] + pSrcAddr->au16[4] + pSrcAddr->au16[5] + pSrcAddr->au16[6] + pSrcAddr->au16[7] + pDstAddr->au16[0] + pDstAddr->au16[1] + pDstAddr->au16[2] + pDstAddr->au16[3] + pDstAddr->au16[4] + pDstAddr->au16[5] + pDstAddr->au16[6] + pDstAddr->au16[7] + RT_H2BE_U16(RT_HIWORD(cbPkt)) + RT_H2BE_U16(RT_LOWORD(cbPkt)) + 0 + RT_H2BE_U16(RT_MAKE_U16(bProtocol, 0)); return u32Sum; }
/** @interface_method_impl{PDMAPICHLPR0,pfnCalcIrqTag} */ static DECLCALLBACK(uint32_t) pdmR0ApicHlp_CalcIrqTag(PPDMDEVINS pDevIns, uint8_t u8Level) { PDMDEV_ASSERT_DEVINS(pDevIns); PVM pVM = pDevIns->Internal.s.pVMR0; pdmLock(pVM); uint32_t uTagSrc = pdmCalcIrqTag(pVM, pDevIns->idTracing); if (u8Level == 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)); pdmUnlock(pVM); LogFlow(("pdmR0ApicHlp_CalcIrqTag: caller=%p/%d: returns %#x (u8Level=%d)\n", pDevIns, pDevIns->iInstance, uTagSrc, u8Level)); return uTagSrc; }