MsiCommon.cpp revision 377f1df8d6ec248927bcdf0efabf87ab55c4a615
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * MSI support routines
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Copyright (C) 2010 Oracle Corporation
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * available from http://www.virtualbox.org. This file is free software;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * General Public License (GPL) as published by the Free Software
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/* Hack to get PCIDEVICEINT declare at the right point - include "PCIInternal.h". */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync/** @todo: use accessors so that raw PCI devices work correctly with MSI. */
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(uint16_t) msiGetMessageControl(PPCIDEVICE pDev)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return PCIDevGetWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_CONTROL);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(uint32_t*) msiGetMaskBits(PPCIDEVICE pDev)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync uint8_t iOff = msiIs64Bit(pDev) ? VBOX_MSI_CAP_MASK_BITS_64 : VBOX_MSI_CAP_MASK_BITS_32;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(uint32_t*) msiGetPendingBits(PPCIDEVICE pDev)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync uint8_t iOff = msiIs64Bit(pDev) ? VBOX_MSI_CAP_PENDING_BITS_64 : VBOX_MSI_CAP_PENDING_BITS_32;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return (msiGetMessageControl(pDev) & VBOX_PCI_MSI_FLAGS_ENABLE) != 0;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return (msiGetMessageControl(pDev) & VBOX_PCI_MSI_FLAGS_QSIZE) >> 4;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(RTGCPHYS) msiGetMsiAddress(PPCIDEVICE pDev)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync uint32_t lo = PCIDevGetDWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_ADDRESS_LO);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync uint32_t hi = PCIDevGetDWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_ADDRESS_HI);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return PCIDevGetDWord(pDev, pDev->Int.s.u8MsiCapOffset + VBOX_MSI_CAP_MESSAGE_ADDRESS_32);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(uint32_t) msiGetMsiData(PPCIDEVICE pDev, int32_t iVector)
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync int16_t iOff = msiIs64Bit(pDev) ? VBOX_MSI_CAP_MESSAGE_DATA_64 : VBOX_MSI_CAP_MESSAGE_DATA_32;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync uint16_t lo = PCIDevGetWord(pDev, pDev->Int.s.u8MsiCapOffset + iOff);
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync // vector encoding into lower bits of message data
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncDECLINLINE(bool) msiBitJustCleared(uint32_t uOldValue,
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return (!!(uOldValue & uMask) && !(uNewValue & uMask));
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync return (!(uOldValue & uMask) && !!(uNewValue & uMask));
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsyncvoid MsiPciConfigWrite(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev,
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync int32_t iOff = u32Address - pDev->Int.s.u8MsiCapOffset;
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync Assert(iOff >= 0 && (pciDevIsMsiCapable(pDev) && iOff < pDev->Int.s.u8MsiCapSize));
a4ba1fc5788b1fb4c078587d5f55936e1b83098dvboxsync Log2(("MsiPciConfigWrite: %d <- %x (%d)\n", iOff, val, len));
switch (reg)
if ( !f64Bit
if ( f64Bit
uAddr++;
switch (len)
Assert(false);
return rv;
return VINF_SUCCESS;
int iMmc;
return VERR_TOO_MUCH_DATA;
if (f64bit)
return VINF_SUCCESS;
void MsiNotify(PPDMDEVINS pDevIns, PCPDMPCIHLP pPciHlp, PPCIDEVICE pDev, int iVector, int iLevel, uint32_t uTagSrc)