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

📄 pciautoconfiglib.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	    break;
        else if ( pSystem->pciRollcallRtn () == TRUE )
            break;
        }

    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

    }

/******************************************************************************
*
* 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: pointer to newly populated PCI device list
*/

LOCAL PCI_LOC * pciAutoListCreate
    (
    PCI_SYSTEM * pSystem,
    int *pListSize
    )
    {
    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 is the 
     * first Pci-To-Pci Bridge to be discovered, 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 += (secBus > 1) ? (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",

⌨️ 快捷键说明

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