VirtualBox

Changeset 32216 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 2, 2010 3:32:04 PM (14 years ago)
Author:
vboxsync
Message:

PCI: device assignment logic

Location:
trunk/src/VBox/Devices/Bus
Files:
2 edited

Legend:

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

    r32152 r32216  
    3333 * PCI Bus instance.
    3434 */
    35 typedef struct
     35typedef struct PCIBus
    3636{
    3737    /** Bus number. */
     
    4040    uint32_t            cBridges;
    4141
    42     /** Array of PCI devices. */
     42    /** Array of PCI devices. We assume 32 slots, each with 8 functions. */
    4343    R3PTRTYPE(PPCIDEVICE) devices[256];
    4444    /** Array of bridges attached to the bus. */
     
    291291}
    292292
     293static DECLCALLBACK(uint32_t) ich9pciConfigRead(PCIDevice *aDev, uint32_t u32Address, unsigned len)
     294{
     295    if (u32Address + len >= 256)
     296    {
     297        Assert(false);
     298        return 0;
     299    }
     300
     301    switch (len)
     302    {
     303        case 1:
     304            return aDev->config[u32Address];
     305        case 2:
     306            return RT_LE2H_U16(*(uint16_t *)(aDev->config + u32Address));
     307        default:
     308        case 4:
     309            return RT_LE2H_U32(*(uint32_t *)(aDev->config + u32Address));
     310    }
     311}
     312
     313
     314static DECLCALLBACK(void) ich9pciConfigWrite(PCIDevice *aDev, uint32_t u32Address, uint32_t val, unsigned len)
     315{
     316    // @todo: write me
     317}
     318
     319/* Slot/functions assignment per table at p. 12 of ICH9 family spec update */
     320static const struct {
     321    const char* pszName;
     322    int32_t     iSlot;
     323    int32_t     iFunction;
     324} PciSlotAssignments[] = {
     325    {
     326        "piix3ide", 1, 1 // do we really need it?
     327    },
     328    {
     329        "lan",      25, 0
     330    },
     331    {
     332        "hda",      27, 0 /* High Definition Audio */
     333    },
     334    {
     335        "i82801",   30, 0 /* Host Controller */
     336    },
     337    {
     338        "lpc",      31, 0 /* Low Pin Count bus */
     339    },
     340    {
     341        "ahci",     31, 2 /* SATA controller */
     342    },
     343    {
     344        "smbus",    31, 3 /* System Management Bus */
     345    },
     346    {
     347        "thermal",  31, 6 /* Thermal controller */
     348    },
     349};
     350static int assignPosition(PPCIBUS pBus, PPCIDEVICE pPciDev, const char *pszName)
     351{
     352    /* Hardcoded slots/functions, per chipset spec */
     353    for (size_t i = 0; i < RT_ELEMENTS(PciSlotAssignments); i++)
     354    {
     355        if (!strcmp(pszName, PciSlotAssignments[i].pszName))
     356        {
     357            pPciDev->Int.s.fRequestedDevFn = true;
     358            return (PciSlotAssignments[i].iSlot << 3) + PciSlotAssignments[i].iFunction;
     359        }
     360    }
     361
     362    /* Otherwise when assigning a slot, we need to make sure all its functions are available */
     363    for (int iPos = 0; iPos < (int)RT_ELEMENTS(pBus->devices); iPos += 8)
     364        if (        !pBus->devices[iPos]
     365                &&  !pBus->devices[iPos + 1]
     366                &&  !pBus->devices[iPos + 2]
     367                &&  !pBus->devices[iPos + 3]
     368                &&  !pBus->devices[iPos + 4]
     369                &&  !pBus->devices[iPos + 5]
     370                &&  !pBus->devices[iPos + 6]
     371                &&  !pBus->devices[iPos + 7])
     372        {
     373            pPciDev->Int.s.fRequestedDevFn = false;
     374            return iPos;
     375        }
     376
     377    return -1;
     378}
     379
     380static bool hasHardAssignedDevsInSlot(PPCIBUS pBus, int iSlot)
     381{
     382    PCIDevice** aSlot = &pBus->devices[iSlot << 3];
     383
     384    return    (aSlot[0] && aSlot[0]->Int.s.fRequestedDevFn)
     385           || (aSlot[1] && aSlot[1]->Int.s.fRequestedDevFn)
     386           || (aSlot[2] && aSlot[2]->Int.s.fRequestedDevFn)
     387           || (aSlot[3] && aSlot[3]->Int.s.fRequestedDevFn)
     388           || (aSlot[4] && aSlot[4]->Int.s.fRequestedDevFn)
     389           || (aSlot[5] && aSlot[5]->Int.s.fRequestedDevFn)
     390           || (aSlot[6] && aSlot[6]->Int.s.fRequestedDevFn)
     391           || (aSlot[7] && aSlot[7]->Int.s.fRequestedDevFn)
     392           ;
     393}
     394
    293395static int ich9pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
    294396{
     397    /*
     398     * Find device position
     399     */
     400    if (iDev < 0)
     401    {
     402        iDev = assignPosition(pBus, pPciDev, pszName);
     403        if (iDev < 0)
     404        {
     405             AssertMsgFailed(("Couldn't find free spot!\n"));
     406             return VERR_PDM_TOO_PCI_MANY_DEVICES;
     407        }
     408    }
     409
     410    /*
     411     * Check if we can really take this slot, possibly by relocating
     412     * its current habitant, if it wasn't hard assigned too.
     413     */
     414    if (pPciDev->Int.s.fRequestedDevFn &&
     415        pBus->devices[iDev]            &&
     416        pBus->devices[iDev]->Int.s.fRequestedDevFn)
     417    {
     418        /*
     419         * Smth like hasHardAssignedDevsInSlot(pBus, iDev >> 3) shall be use to make
     420         * it compatible with DevPCI.cpp version, but this way we cannot assign
     421         * in accordance with the chipset spec.
     422         */
     423        AssertReleaseMsgFailed(("Configuration error:'%s' and '%s' are both configured as device %d\n",
     424                                 pszName, pBus->devices[iDev]->name, iDev));
     425        return VERR_INTERNAL_ERROR;
     426    }
     427
     428    if (pBus->devices[iDev])
     429    {
     430        /* if we got here, we shall (and usually can) relocate the device */
     431        int iRelDev = assignPosition(pBus, pBus->devices[iDev], pBus->devices[iDev]->name);
     432        if (iRelDev < 0 || iRelDev == iDev)
     433        {
     434            AssertMsgFailed(("Couldn't find free spot!\n"));
     435            return VERR_PDM_TOO_PCI_MANY_DEVICES;
     436        }
     437        /* Copy device function by function to its new position */
     438        for (int i = 0; i < 8; i++)
     439        {
     440            if (!pBus->devices[iDev + i])
     441                continue;
     442            Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->devices[iDev + i]->name, iDev + i, iRelDev + i));
     443            pBus->devices[iRelDev + i] = pBus->devices[iDev + i];
     444            pBus->devices[iRelDev + i]->devfn = i;
     445            pBus->devices[iDev + i] = NULL;
     446        }
     447    }
     448
     449    /*
     450     * Fill in device information.
     451     */
     452    pPciDev->devfn                  = iDev;
     453    pPciDev->name                   = pszName;
     454    pPciDev->Int.s.pBusR3           = pBus;
     455    pPciDev->Int.s.pBusR0           = MMHyperR3ToR0(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
     456    pPciDev->Int.s.pBusRC           = MMHyperR3ToRC(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus);
     457    pPciDev->Int.s.pfnConfigRead    = ich9pciConfigRead;
     458    pPciDev->Int.s.pfnConfigWrite   = ich9pciConfigWrite;
     459    pBus->devices[iDev]             = pPciDev;
     460    if (pPciDev->Int.s.fPciToPciBridge)
     461    {
     462        AssertMsg(pBus->cBridges < RT_ELEMENTS(pBus->devices), ("Number of bridges exceeds the number of possible devices on the bus\n"));
     463        AssertMsg(pPciDev->Int.s.pfnBridgeConfigRead && pPciDev->Int.s.pfnBridgeConfigWrite,
     464                  ("device is a bridge but does not implement read/write functions\n"));
     465        pBus->papBridgesR3[pBus->cBridges] = pPciDev;
     466        pBus->cBridges++;
     467    }
     468
     469    Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
     470         iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
     471
    295472    return VINF_SUCCESS;
    296473}
     
    396573    pBus->PciDev.pDevIns              = pDevIns;
    397574    pBus->PciDev.Int.s.fRequestedDevFn= true;
     575    /* We register Host<->PCI controller on the bus */
    398576    ich9pciRegisterInternal(pBus, 0, &pBus->PciDev, "i82801");
     577
     578    /** @todo: ther chipset devices shall be registered too */
     579    /** @todo: bridges? */
    399580
    400581    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Bus/PCIInternal.h

    r28800 r32216  
    6969typedef PFNPCIBRIDGECONFIGWRITE *PPFNPCIBRIDGECONFIGWRITE;
    7070
     71/* Forward declaration */
     72struct PCIBus;
     73
    7174/**
    7275 * PCI Device - Internal data.
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