VirtualBox

Ignore:
Timestamp:
May 17, 2023 7:31:36 AM (20 months ago)
Author:
vboxsync
Message:

Devices/Bus: Implement interrupt forwarding for the PCIe bus, bugref:10445

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevPciGenericEcam.cpp

    r99752 r99820  
    6868*********************************************************************************************************************************/
    6969
     70/**
     71 * Returns the interrupt pin for a given device slot on the root port
     72 * due to swizzeling.
     73 *
     74 * @returns Interrupt pin on the root port.
     75 * @param   uDevFn      The device.
     76 * @param   uPin        The interrupt pin on the device.
     77 */
     78DECLINLINE(uint8_t) pciGenEcamGetPirq(uint8_t uDevFn, uint8_t uPin)
     79{
     80    uint8_t uSlot = (uDevFn >> 3) - 1;
     81    return (uPin + uSlot) & 3;
     82}
     83
     84
     85/**
     86 * Returns whether the interrupt line is asserted on the PCI root for the given pin.
     87 *
     88 * @returns Flag whther the interrupt line is asserted (true) or not (false).
     89 * @param   pPciRoot    The PCI root bus.
     90 * @param   u8IrqPin    The IRQ pin being checked.
     91 */
     92DECLINLINE(bool) pciGenEcamGetIrqLvl(PDEVPCIROOT pPciRoot, uint8_t u8IrqPin)
     93{
     94    return (pPciRoot->u.GenericEcam.auPciIrqLevels[u8IrqPin] != 0);
     95}
     96
     97
     98/**
     99 * @interface_method_impl{PDMPCIBUSREGCC,pfnSetIrqR3}
     100 */
    70101static DECLCALLBACK(void) pciGenEcamSetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc)
    71102{
    72103    PDEVPCIROOT pPciRoot = PDMINS_2_DATA(pDevIns, PDEVPCIROOT);
     104    PDEVPCIBUS  pBus = &pPciRoot->PciBus;
    73105    PDEVPCIBUSCC pBusCC = PDMINS_2_DATA_CC(pDevIns, PDEVPCIBUSCC);
    74106    uint8_t uDevFn = pPciDev->uDevFn;
     107    uint16_t const uBusDevFn = PCIBDF_MAKE(pBus->iBus, uDevFn);
    75108
    76109    LogFlowFunc(("invoked by %p/%d: iIrq=%d iLevel=%d uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, iIrq, iLevel, uTagSrc));
     
    96129    }
    97130
    98     PDEVPCIBUS pBus = &pPciRoot->PciBus;
    99131    LogFlowFunc(("PCI Dev %p : IRQ\n", pPciDev));
    100132
     
    104136        pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH);
    105137
    106         /** @todo */
     138        /* Get the pin. */
     139        uint8_t uIrqPin = devpciR3GetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN);
     140        uint8_t uIrq = pciGenEcamGetPirq(pPciDev->uDevFn, uIrqPin);
     141
     142        if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH)
     143            ASMAtomicIncU32(&pPciRoot->u.GenericEcam.auPciIrqLevels[uIrq]);
     144        else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW)
     145            ASMAtomicDecU32(&pPciRoot->u.GenericEcam.auPciIrqLevels[uIrq]);
     146
     147        bool fIrqLvl = pciGenEcamGetIrqLvl(pPciRoot, uIrq);
     148        uint32_t u32IrqNr = pPciRoot->u.GenericEcam.auPciIrqNr[uIrq];
     149
     150        Log3Func(("%s: uIrqPin=%u uIrqRoot=%u fIrqLvl=%RTbool uIrqNr=%u\n",
     151              R3STRING(pPciDev->pszNameR3), uIrqPin, uIrq, fIrqLvl, u32IrqNr));
     152        pBusCC->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pDevIns, uBusDevFn, u32IrqNr, fIrqLvl, uTagSrc);
     153
     154        if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) {
     155            ASMAtomicDecU32(&pPciRoot->u.GenericEcam.auPciIrqLevels[uIrq]);
     156            pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW;
     157            fIrqLvl = pciGenEcamGetIrqLvl(pPciRoot, uIrq);
     158            Log3Func(("%s: uIrqPin=%u uIrqRoot=%u fIrqLvl=%RTbool uIrqNr=%u\n",
     159                  R3STRING(pPciDev->pszNameR3), uIrqPin, uIrq, fIrqLvl, u32IrqNr));
     160            pBusCC->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pDevIns, uBusDevFn, u32IrqNr, fIrqLvl, uTagSrc);
     161        }
    107162    }
    108163}
     
    111166/**
    112167 * @callback_method_impl{FNIOMMMIONEWWRITE,
    113  * Emulates writes to configuration space.}
     168 * Emulates writes to PIO space.}
    114169 */
    115170static DECLCALLBACK(VBOXSTRICTRC) pciHostR3MmioPioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
     
    146201/**
    147202 * @callback_method_impl{FNIOMMMIONEWWRITE,
    148  * Emulates reads from configuration space.}
     203 * Emulates reads from PIO space.}
    149204 */
    150205static DECLCALLBACK(VBOXSTRICTRC) pciHostR3MmioPioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
     
    156211    AssertReturn(cb <= 4, VERR_INVALID_PARAMETER);
    157212
    158     /* Perform configuration space read */
     213    /* Perform PIO space read */
    159214    uint32_t     u32Value = 0;
    160215    VBOXSTRICTRC rcStrict = PDMDevHlpIoPortRead(pDevIns, (RTIOPORT)off, &u32Value, cb);
     
    205260     * Validate and read configuration.
    206261     */
    207     PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "MmioEcamBase|MmioEcamLength|MmioPioBase|MmioPioSize", "");
     262    PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "MmioEcamBase"
     263                                           "|MmioEcamLength"
     264                                           "|MmioPioBase"
     265                                           "|MmioPioSize"
     266                                           "|IntPinA"
     267                                           "|IntPinB"
     268                                           "|IntPinC"
     269                                           "|IntPinD", "");
    208270
    209271    int rc = pHlp->pfnCFGMQueryU64Def(pCfg, "MmioEcamBase", &pPciRoot->u64PciConfigMMioAddress, 0);
     
    219281    AssertRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"MmioPioSize\"")));
    220282
     283    rc = pHlp->pfnCFGMQueryU32(pCfg, "IntPinA", &pPciRoot->u.GenericEcam.auPciIrqNr[0]);
     284    AssertRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IntPinA\"")));
     285
     286    rc = pHlp->pfnCFGMQueryU32(pCfg, "IntPinB", &pPciRoot->u.GenericEcam.auPciIrqNr[1]);
     287    AssertRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IntPinB\"")));
     288
     289    rc = pHlp->pfnCFGMQueryU32(pCfg, "IntPinB", &pPciRoot->u.GenericEcam.auPciIrqNr[2]);
     290    AssertRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IntPinC\"")));
     291
     292    rc = pHlp->pfnCFGMQueryU32(pCfg, "IntPinB", &pPciRoot->u.GenericEcam.auPciIrqNr[3]);
     293    AssertRCReturn(rc, PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IntPinD\"")));
     294
    221295    Log(("PCI: fUseIoApic=%RTbool McfgBase=%#RX64 McfgLength=%#RX64 fR0Enabled=%RTbool fRCEnabled=%RTbool\n", pPciRoot->fUseIoApic,
    222296         pPciRoot->u64PciConfigMMioAddress, pPciRoot->u64PciConfigMMioLength, pDevIns->fR0Enabled, pDevIns->fRCEnabled));
     297    Log(("PCI: IntPinA=%u IntPinB=%u IntPinC=%u IntPinD=%u\n", pPciRoot->u.GenericEcam.auPciIrqNr[0],
     298         pPciRoot->u.GenericEcam.auPciIrqNr[1], pPciRoot->u.GenericEcam.auPciIrqNr[2], pPciRoot->u.GenericEcam.auPciIrqNr[3]));
    223299
    224300    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette