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

📄 pciautoconfiglib.c

📁 LoPEC Early Access VxWorks BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
    PCI_LOC  pciLoc;		/* PCI bus/device/function structure */    PCI_LOC *pPciList;    PCI_LOC *pRetPciList;   /* 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 32-bit I/O addressing     * (PCI_AUTO_ATTR_BUS_4GB_IO) and prefetchable memory     * (PCI_AUTO_ATTR_BUS_PREFETCH)     */    pciMaxBus = pciAutoDevProbe (pSystem, pciLoc.bus, (UCHAR)0,				(UCHAR)( PCI_AUTO_ATTR_BUS_4GB_IO |					 PCI_AUTO_ATTR_BUS_PREFETCH),				 &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,    UINT primary,    UINT secondary,    UINT subordinate     )    {    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: subordinate bus number.*/LOCAL UINT pciAutoBusProbe    (    PCI_SYSTEM * 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_SYSTEM * 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	*/    short 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) + PCI_SUBCLASS_ISA_BRIDGE):		    pciLoc.attribute |= PCI_AUTO_ATTR_BUS_ISA;		    break;		/* Display Device */		case (PCI_CLASS_DISPLAY_CTLR << 8):		    pciLoc.attribute |= PCI_AUTO_ATTR_DEV_DISPLAY;		    break;		/* PCI-to-PCI Bridge */		case ((PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_P2P_BRIDGE):		    /* Setup and probe this bridge device */		    pciLoc.attribute |= PCI_AUTO_ATTR_BUS_PCI;		    /*		     * Check for 32 bit I/O addressability,		     * but only if the parent bridge supports it		     */		    if (inheritAttrib & PCI_AUTO_ATTR_BUS_4GB_IO)			{			pciConfigInByte (pciLoc.bus,					 pciLoc.device,					 pciLoc.function,					 PCI_CFG_IO_BASE, &btemp);			if ((btemp & 0x0F) == 0x01)			    {			    pciConfigInByte (pciLoc.bus, 					     pciLoc.device, pciLoc.function,					     PCI_CFG_IO_LIMIT, &btemp);			    if ((btemp & 0x0F) == 0x01)				{				pciLoc.attribute |= PCI_AUTO_ATTR_BUS_4GB_IO;				PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: 4G I/O \n",					0, 0, 0, 0, 0, 0);				}			    }			}		    /* Disable prefetch */		    pciConfigModifyLong (pciLoc.bus, 					 pciLoc.device, 					 pciLoc.function,					 PCI_CFG_PRE_MEM_BASE, 					 0xfff0fff0, 0x0000fff0);		    pciConfigOutLong (pciLoc.bus, 				      pciLoc.device,				      pciLoc.function,				      PCI_CFG_PRE_MEM_LIMIT_U, 0);		    pciConfigOutLong (pciLoc.bus,			              pciLoc.device,				      pciLoc.function,				      PCI_CFG_PRE_MEM_BASE_U, 0xffffffff);		    /* Check for Prefetch memory support */		    if (inheritAttrib & PCI_AUTO_ATTR_BUS_PREFETCH)			{			pciConfigInLong  (pciLoc.bus,					  pciLoc.device,					  pciLoc.function,					  PCI_CFG_PRE_MEM_BASE, &temp);			 /* PF Registers return 0 if PF is not implemented */			if (temp != 0)			    { 			    pciLoc.attribute |= PCI_AUTO_ATTR_BUS_PREFETCH;			    PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: PF present\n",						0, 0, 0, 0, 0, 0);			    }			}		    break;		default:		    /* Mask off all but bus attribute bits to inherit */		    inheritAttrib &=   ( PCI_AUTO_ATTR_BUS_4GB_IO |					 PCI_AUTO_ATTR_BUS_PREFETCH );		    /* devices inherit bus attributes from their bridge */		    pciLoc.attribute |= inheritAttrib;		    break;	    }	    /* Add this function to the PCI function list */	    if (*pListSize < PCI_AUTO_MAX_FUNCTIONS)		{		memcpy (*ppPciList, &pciLoc, sizeof (PCI_LOC));		(*ppPciList)++;		(*pListSize)++;		}	    /* If the device is a PCI-to-PCI bridge, then scan behind it */	    if (pciLoc.attribute & PCI_AUTO_ATTR_BUS_PCI)		{		PCI_AUTO_DEBUG_MSG("pciAutoDevProbe: scanning bus[%d]\n",		    (subBus+1), 0, 0, 0, 0, 0 );		subBus = pciAutoBusProbe (pSystem, bus, subBus+1, &pciLoc,					    ppPciList, pListSize);		}	    /* Proceed to next device if this is a single function device */	    if (function == 0)		{		pciConfigInByte (pciLoc.bus, pciLoc.device, pciLoc.function,				 PCI_CFG_HEADER_TYPE, &btemp);		if ((btemp & PCI_HEADER_MULTI_FUNC) == 0)		    {		    break; /* No more functions - proceed to next PCI device */		    }		}	    }	}    return (subBus);    }/******************************************************************************** pciAutoFuncConfigAll - Configure all PCI functions contained in list** This routine initializes all PCI functions within the specified* list.  This may be anything from a full list to a single entry.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -