VirtualBox

Changeset 13302 in vbox for trunk/src


Ignore:
Timestamp:
Oct 15, 2008 8:27:33 PM (16 years ago)
Author:
vboxsync
Message:

PCI: put bridges on a separate array to speed up searching for the right bridge when forwarding configuration transactions

File:
1 edited

Legend:

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

    r13233 r13302  
    5555#include <iprt/assert.h>
    5656#include <iprt/string.h>
     57#ifdef IN_RING3
     58# include <iprt/mem.h>
     59#endif
    5760
    5861#include "../Builtins.h"
     
    7982    /** Start device number. */
    8083    int32_t             iDevSearch;
    81 
    82     uint32_t            Alignment0[2];
     84    /** Number of bridges attached to the bus. */
     85    uint32_t            cBridges;
     86
     87    uint32_t            Alignment0;
    8388
    8489    /** Array of PCI devices. */
    8590    R3PTRTYPE(PPCIDEVICE) devices[256];
     91    /** Array of bridges attached to the bus. */
     92    R3PTRTYPE(PPCIDEVICE) apBridgesR3[256]; /* @todo: Waste of precious hypervisor space. */
    8693
    8794    /** R3 pointer to the device instance. */
     
    212219PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
    213220PDMBOTHCBDECL(void) pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
     221
     222#ifdef IN_RING3
     223static PPCIDEVICE pciFindBridge(PPCIBUS pBus, uint8_t iBus);
     224#endif
    214225
    215226__END_DECLS
     
    482493    if (iBus != 0)
    483494    {
    484         /** @todo r=bird: Guess you should cache the pci-bridges instead of searching
    485          *        the full array, that way we don't need to make assumptions about
    486          *        multi function devices. */
    487         /*
    488          * Search for a fitting bridge. Because we don't support multi function devices at the moment
    489          * we only search all devices with function 0 to speed things up.
    490          * If no bridge is found the write will be ignored.
    491          */
    492         for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8)
    493         {
    494             /*
    495              * Examine secondary and subordinate bus number.
    496              * If the target bus is in the range we pass the request on to the bridge.
    497              */
    498             PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev];
    499             if (!pBridgeDevice)
    500                 continue;
    501             if (!pBridgeDevice->Int.s.fPciToPciBridge)
    502                 continue;
    503 
    504             if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
    505                 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
    506             {
    507                 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
    508 
    509                 /* Start the journey... */
    510                 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, val, len);
    511             }
     495        PPCIDEVICE pBridgeDevice = pciFindBridge(&pGlobals->PciBus, iBus);
     496
     497        if (pBridgeDevice)
     498        {
     499            AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
     500
     501            pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, val, len);
    512502        }
    513503    }
     
    537527    if (iBus != 0)
    538528    {
    539         /*
    540          * Search for a fitting bridge. Because we don't support multi function devices at the moment
    541          * we only search all devices with function 0 to speed things up.
    542          * If no bridge is found the read will be ignored.
    543          */
    544         for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8)
    545         {
    546             /*
    547              * Examine secondary and subordinate bus number.
    548              * If the target bus is in the range we pass the request on to the bridge.
    549              */
    550             PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev];
    551             if (!pBridgeDevice)
    552                 continue;
    553             if (!pBridgeDevice->Int.s.fPciToPciBridge)
    554                 continue;
    555 
    556             if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
    557                 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
    558             {
    559                 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
    560 
    561                 val = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, len);
    562             }
     529        PPCIDEVICE pBridgeDevice = pciFindBridge(&pGlobals->PciBus, iBus);
     530
     531        if (pBridgeDevice)
     532        {
     533            AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
     534
     535            val = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, len);
    563536        }
    564537    }
     
    754727
    755728#ifdef IN_RING3
     729
     730/**
     731 * Finds a bridge on the bus which contains the destination bus.
     732 *
     733 * @return Pointer to the device instance data of the bus or
     734 *         NULL if no bridge was found.
     735 * @param  pBus    Pointer to the bus to search on.
     736 * @param  iBus    Destination bus number.
     737 */
     738static PPCIDEVICE pciFindBridge(PPCIBUS pBus, uint8_t iBus)
     739{
     740    /* Search for a fitting bridge. */
     741    for (uint32_t iBridge = 0; iBridge < pBus->cBridges; iBridge++)
     742    {
     743        /*
     744            * Examine secondary and subordinate bus number.
     745            * If the target bus is in the range we pass the request on to the bridge.
     746            */
     747        PPCIDEVICE pBridgeTemp = pBus->apBridgesR3[iBridge];
     748        AssertMsg(pBridgeTemp && pBridgeTemp->Int.s.fPciToPciBridge,
     749                  ("Device is not a PCI bridge but on the list of PCi bridges\n"));
     750
     751        if (   iBus >= pBridgeTemp->config[VBOX_PCI_SECONDARY_BUS]
     752            && iBus <= pBridgeTemp->config[VBOX_PCI_SUBORDINATE_BUS])
     753            return pBridgeTemp;
     754    }
     755
     756    /* Nothing found. */
     757    return NULL;
     758}
    756759
    757760static void piix3_reset(PIIX3State *d)
     
    10031006                /* default memory mappings */
    10041007                /*
    1005                  * PCI_NUM_REGIONS is 7 bcause of the rom region but there are only 6 base address register defined by the PCi spec.
     1008                 * PCI_NUM_REGIONS is 7 because of the rom region but there are only 6 base address register defined by the PCI spec.
    10061009                 * Leaving only PCI_NUM_REGIONS would cause reading another and enabling a memory region which does not exist.
    10071010                 */
     
    13971400
    13981401/* -=-=-=-=-=- real code -=-=-=-=-=- */
    1399 
    14001402
    14011403/**
     
    15181520    pPciDev->Int.s.pfnConfigWrite   = pci_default_write_config;
    15191521    pBus->devices[iDev]             = pPciDev;
     1522    if (pPciDev->Int.s.fPciToPciBridge)
     1523    {
     1524        AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->apBridgesR3), ("Number of bridges exceeds the number of possible bridges on the bus\n"));
     1525        AssertMsg(pPciDev->Int.s.pfnBridgeConfigRead && pPciDev->Int.s.pfnBridgeConfigWrite,
     1526                  ("device is a bridge but does not implement read/write functions\n"));
     1527        pBus->apBridgesR3[pBus->cBridges] = pPciDev;
     1528        pBus->cBridges++;
     1529    }
     1530
    15201531    Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
    15211532         iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
     
    19301941    if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS])
    19311942    {
    1932         /*
    1933          * Search for a fitting bridge. Because we don't support multi function devices at the moment
    1934          * we only search all devices with function 0 to speed things up.
    1935          * If no bridge is found the write will be ignored.
    1936          */
    1937         for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8)
    1938         {
    1939             /*
    1940              * Examine secondary and subordinate bus number.
    1941              * If the target bus is in the range we pass the request on to the bridge.
    1942              */
    1943             PPCIDEVICE pBridgeDevice = pBus->devices[iDev];
    1944             if (!pBridgeDevice)
    1945                 continue;
    1946             if (!pBridgeDevice->Int.s.fPciToPciBridge)
    1947                 continue;
    1948 
    1949             if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
    1950                 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
    1951             {
    1952                 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
    1953 
    1954                 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb);
    1955             }
     1943        PPCIDEVICE pBridgeDevice = pciFindBridge(pBus, iBus);
     1944
     1945        if (pBridgeDevice)
     1946        {
     1947            AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite);
     1948
     1949            pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb);
    19561950        }
    19571951    }
     
    19781972    if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS])
    19791973    {
    1980         /*
    1981          * Search for a fitting bridge. Because we don't support multi function devices at the moment
    1982          * we only search all devices with function 0 to speed things up.
    1983          * If no bridge is found the read will return 0xffffffff.
    1984          */
    1985         for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8)
    1986         {
    1987             /*
    1988              * Examine secondary and subordinate bus number.
    1989              * If the target bus is in the range we pass the request on to the bridge.
    1990              */
    1991             PPCIDEVICE pBridgeDevice = pBus->devices[iDev];
    1992             if (!pBridgeDevice)
    1993                 continue;
    1994             if (!pBridgeDevice->Int.s.fPciToPciBridge)
    1995                 continue;
    1996 
    1997             if (   iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS]
    1998                 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS])
    1999             {
    2000                 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
    2001 
    2002                 u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb);
    2003             }
     1974        PPCIDEVICE pBridgeDevice = pciFindBridge(pBus, iBus);
     1975
     1976        if (pBridgeDevice)
     1977        {
     1978            AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead);
     1979
     1980            u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb);
    20041981        }
    20051982    }
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