📄 pciautoconfiglib.c
字号:
/* * If a roll-call routine has been configured, call the roll-call * routine repeatedly until it returns TRUE. A return value * of TRUE indicates that either (1) the specified number and * type of devices named in the roll call list have been found * during PCI bus enumeration or (2) the timeout has expired * without finding all of the specified number and type of * devices. In either case, we will assume that all of the PCI * devices which are going to appear on the busses have appeared * and we can proceed with PCI bus configuration. */ if (pSystem->pciRollcallRtn != NULL) { rollcallSuccess = FALSE; while ( ! rollcallSuccess ) { /* * Probe all PCI busses dynamically creating a function list * of all functions found. Excluded devices are skipped over. */ pPciList = pciAutoListCreate (pSystem, &listSize); /* Perform roll call function, if we pass, exit the loop */ if ( (*pSystem->pciRollcallRtn)() == OK ) rollcallSuccess = TRUE;#ifdef PCI_AUTO_RECLAIM_LIST free(pPciList);#endif /* PCI_AUTO_RECLAIM_LIST */ if ( rollcallSuccess == TRUE ) break; } } /* * Probe all PCI busses dynamically creating a function list * of all functions found. Excluded devices are skipped over. */ pPciList = pciAutoListCreate (pSystem, &listSize); pciAutoFuncConfigAll (pSystem, pPciList, listSize); lastPciListSize = listSize; pLastPciList = pPciList; /* If the function list is malloc'ed at runtime, then release it */#if defined(PCI_AUTO_RECLAIM_LIST)# if defined(PCI_AUTO_STATIC_LIST)# error "Can't do PCI_AUTO_RECLAIM_LIST with PCI_AUTO_STATIC_LIST"# endif free(pPciList); lastPciListSize = 0; pLastPciList = NULL;#endif return(OK); }/******************************************************************************** pciAutoListCreate - probe for all functions and make a PCI probe list.** This routine creates a dynamic probelist containing all PCI functions* located in the PCI configuration hierarchy. In addition, it assigns* base addresses for the 32-bit prefetchable memory allocation pool,* the 32-bit non-prefetchable memory allocation pool, the 32-bit I/O* allocation pool, and the 16-bit I/O allocation pool. When I/O space* or memory space is actually assigned (not in this routine), the space* allocation will begin with the base address in each of these categories* and proceed to higher numbered addresses.** Note that 20-bit memory space is not currently handled as a special case.** RETURNS: A pointer to a newly populated PCI device list.*/LOCAL PCI_LOC * pciAutoListCreate ( PCI_AUTO_CONFIG_OPTS * pSystem, /* cookie returned by pciAutoConfigLibInit() */ int *pListSize /* size of the PCI_LOC list */ ) { PCI_LOC pciLoc; /* PCI bus/device/function structure */ PCI_LOC *pPciList; PCI_LOC *pRetPciList; UCHAR busAttr; /* Initialize the list pointer in preparation for probing */#if defined(PCI_AUTO_STATIC_LIST) pPciList = pciAutoLocalFuncList; pRetPciList = pPciList;#else pPciList = malloc(sizeof(PCI_LOC) * PCI_AUTO_MAX_FUNCTIONS); if (pPciList == NULL) { return NULL; } pRetPciList = pPciList;#endif lastPciListSize = 0; *pListSize = 0; /* Begin the scanning process at [0,0,0] */ pciLoc.bus = (UINT8)0; pciLoc.device = (UINT8)0; pciLoc.function = (UINT8)0; /* * Note that the host bridge is assumed to support prefetchable memory * (PCI_AUTO_ATTR_BUS_PREFETCH) and only assumed to support 32-bit I/O * addressing (PCI_AUTO_ATTR_BUS_4GB_IO) if pciIo32Size is non-zero. */ if (pSystem->pciIo32Size == 0) busAttr = PCI_AUTO_ATTR_BUS_PREFETCH; else busAttr = PCI_AUTO_ATTR_BUS_4GB_IO | PCI_AUTO_ATTR_BUS_PREFETCH; pciMaxBus = pciAutoDevProbe (pSystem, pciLoc.bus, (UCHAR)0, busAttr, &pPciList, pListSize); pSystem->maxBus = pciMaxBus; return (pRetPciList); }/******************************************************************************** pciAutoDevReset - Quiesce a PCI device and reset all writeable status bits.** This routine turns 'off' a PCI device by disabling the Memory decoders, I/O* decoders, and Bus Master capability. The routine also resets all writeable* status bits in the status word that follows the command word sequentially* in PCI config space by performing a longword access.** RETURNS: OK, always.*/STATUS pciAutoDevReset ( PCI_LOC * pPciLoc /* device to be reset */ ) { /* Disable the device and reset all writeable status bits */ pciConfigOutLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function, PCI_CFG_COMMAND, 0xffff0000); return OK; }/******************************************************************************** pciAutoBusNumberSet - Set the primary, secondary, and subordinate bus number.** This routine sets the primary, secondary, and subordinate bus numbers for* a device that implements the Type 1 PCI Configuration Space Header.** This routine has external visibility to enable it to be used by BSP* Developers for initialization of PCI Host Bridges that may implement* registers similar to those found in the Type 1 Header.** RETURNS: OK, always.*/STATUS pciAutoBusNumberSet ( PCI_LOC * pPciLoc, /* device affected */ UINT primary, /* primary bus specification */ UINT secondary, /* secondary bus specification */ UINT subordinate /* subordinate bus specification */ ) { UINT workvar = 0; /* Working variable */ workvar = (subordinate << 16) + (secondary << 8) + primary; /* longword write */ pciConfigModifyLong (pPciLoc->bus, pPciLoc->device, pPciLoc->function, PCI_CFG_PRIMARY_BUS, 0x00ffffff, workvar); return OK; }/******************************************************************************** pciAutoBusProbe - Configure a bridge and probe all devices behind it.** This routine assigns an initial range of subordinate busses to a* PCI bridge, searches for functions under this bridge, and then* updates the range assignment to the correct value. It calls* pciAutoDevProbe() which in turn calls this function in a recursive* manner. In addition to actually programming the PCI-PCI bridge* headers with correct bus numbers, the 'pciLoc' list of functions* is extended as each new PCI function is found.** RETURNS: The subordinate bus number.*/LOCAL UINT pciAutoBusProbe ( PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system information */ UINT priBus, /* Primary PCI bus */ UINT secBus, /* Secondary PCI bus */ PCI_LOC* pPciLoc, /* PCI address of this bridge */ PCI_LOC** ppPciList, /* Pointer to next PCI location */ /* entry pointer */ int * pListSize /* number of PCI_LOC entries */ ) { UINT subBus = 0xff; /* Highest subordinate PCI bus */ UCHAR offset = 0; /* Interrupt routing offset for this bus*/ /* Disable I/O, Mem, and upstream transactions / reset status bits */ pciAutoDevReset (pPciLoc); /* Set the bus numbers, subordinate bus is 0xff */ pciAutoBusNumberSet (pPciLoc, priBus, secBus, 0xff); PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: using bridge [%d,%d,%d,0x%02x]\n", (pPciLoc->bus), (pPciLoc->device), (pPciLoc->function), (pPciLoc->attribute), 0, 0 ); /* Probe all devices on this bus */ PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: calling pciAutoDevProbe on bus [%d]\n", secBus, 0, 0, 0, 0, 0); /* * Compute the route offset for this bridge: if this bridge is * on bus zero (primary bus = zero) then its contribution is null, * otherwise it depends on its location on the bus and on the * contribution of all of the upper Pci-To-Pci Bridges. */ pPciLoc->offset += (priBus > 0) ? (pPciLoc->device % 4) : 0; offset = pPciLoc->offset; PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: int route offset for bridge is [%d]\n", offset, 0, 0, 0, 0, 0); subBus = pciAutoDevProbe (pSystem, secBus, offset, (pPciLoc->attribute), ppPciList, pListSize); /* Set the range assignment to cover the correct range of busses */ PCI_AUTO_DEBUG_MSG("pciAutoBusProbe: post-config subordinate bus as [%d]\n", subBus, 0, 0, 0, 0, 0); pciAutoBusNumberSet (pPciLoc, priBus, secBus, subBus); /* Return the highest subordinate bus */ return subBus; }/******************************************************************************** pciAutoDevProbe - Probe all devices on a single PCI bus.** This routine probes a single PCI bus and adds each detected PCI function* to the function list. In case a PCI-PCI bridge is found, pciAutoBusProbe()* is called to probe that bus. pciAutoBusProbe() in turn calls this function* in a recursive manner until all busses have been probed.** RETURNS: Highest subordinate bus number found during probing process.*/LOCAL UINT pciAutoDevProbe ( PCI_AUTO_CONFIG_OPTS * pSystem, /* PCI system info */ UINT bus, /* current bus number to probe */ UCHAR offset, /* bridge contrib to int vector xlation */ UCHAR inheritAttrib, /* attributes inherited from bridge */ PCI_LOC **ppPciList, /* Pointer to next PCI location entry */ int * pListSize /* Number of PCI_LOC's currently in list*/ ) { PCI_LOC pciLoc; /* PCI bus/device/function structure */ UINT16 pciclass; /* PCI class/subclass contents */ UINT dev_vend; /* Device/Vendor identifier */ int device; /* Device location */ int function; /* Function location */ int subBus; /* Highest subordinate PCI bus */ UCHAR btemp; /* Temporary holding area */ UINT temp; /* Initialize variables */ bzero ((char *)&pciLoc, sizeof (PCI_LOC)); pciLoc.bus = bus; subBus = bus; /* if attributes indicate a host bus, then set equal to pciLoc.attrib */ /* Locate each active function on the current bus */ for (device = 0; device < PCI_MAX_DEV; device++) { pciLoc.device = device; /* Check each function until an unused one is detected */ for (function = 0; function < PCI_MAX_FUNC; function++) { pciLoc.function = function; /* Check for a valid device/vendor number */ pciConfigInLong (pciLoc.bus, pciLoc.device, pciLoc.function, PCI_CFG_VENDOR_ID, &dev_vend); /* If function 0 then check next dev else check next function */ if ( ((dev_vend & 0x0000ffff) == PCI_CONFIG_ABSENT_F) || ((dev_vend & 0x0000ffff) == PCI_CONFIG_ABSENT_0) ) { if (function == 0) { break; /* non-existent device, goto next device */ } else { continue; /* function empty, try the next function */ } } /* store the translation offset for the int routing */ pciLoc.offset = offset; pciLoc.attribute = 0; /* Check to see if this function belongs to a PCI-PCI bridge */ pciConfigInWord (pciLoc.bus, pciLoc.device, pciLoc.function, PCI_CFG_SUBCLASS, &pciclass); /* Set Bridge device attributes for this device */ switch(pciclass) { /* PCI Host Bridge */ case ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_HOST_PCI_BRIDGE): pciLoc.attribute |= ( PCI_AUTO_ATTR_DEV_EXCLUDE | PCI_AUTO_ATTR_BUS_HOST ); break; /* ISA Bridge */ case ((PCI_CLASS_BRIDGE_CTLR << 8)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -