⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciautoconfiglib.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /*     * 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 + -