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

📄 pciautoconfiglib.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
						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.
*
* RETURNS: N/A.
*/

LOCAL void pciAutoFuncConfigAll
    (
    PCI_SYSTEM * pSystem,	/* PCI system info */
    PCI_LOC *pPciList,		/* input: Pointer to first function   */
    UINT nSize			/* input: Number of functions to init */
    )
    {
    PCI_LOC *pPciFunc;		/* Pointer to next function */
    UINT nLoop;			/* Loop control variable    */
    UINT nEnd;			/* End of function list     */

    /* Disable all devices before we initialize any */

    /* Allocate and assign PCI space to each device */

    pPciFunc = pPciList;
    nEnd = nSize;
    pciAutoDevConfig (pSystem, pPciList->bus, &pPciFunc, &nEnd);

    /* Enable each device on the device list */

    pPciFunc = pPciList;
    for (nLoop = 0; nLoop < nSize; nLoop++)
        {
        pciAutoFuncEnable (pSystem, pPciFunc);
        pPciFunc++;
        }

    }

/******************************************************************************
*
* pciAutoFuncDisable - Disable a specific PCI function.
*
* This routine clears the I/O, mem, master, & ROM space enable bits
* for a single PCI function.
*
* The PCI spec says that devices should normally clear these by default after
* reset but in actual practice, some PCI devices do not fully comply. This
* routine ensures that the devices have all been disabled before configuration
* is started.
*
* RETURNS: N/A.
*
*/

void pciAutoFuncDisable
    (
    PCI_LOC *pPciFunc		/* input: Pointer to PCI function struct */
    )
    {
    UCHAR cTemp;			/* Temporary storage */
    UINT16 wTemp;

    if ((pPciFunc->attribute) & PCI_AUTO_ATTR_DEV_EXCLUDE)
	{
	return;
	}
 
    PCI_AUTO_DEBUG_MSG("pciAutoFuncDisable: disable device [%d,%d,%d,0x%02x]\n",
	    (pPciFunc->bus),
	    (pPciFunc->device),
	    (pPciFunc->function),
	    (pPciFunc->attribute),
	    0,
	    0
	    );

    /* Disable Memory, I/O, and Bus Mastering, save status bits */

    wTemp = (PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE );

    pciConfigModifyLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
		        PCI_CFG_COMMAND, (0xffff0000 | wTemp), 0x0);

    /* Disable header dependent fields */

    pciConfigInByte (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
		     PCI_CFG_HEADER_TYPE, &cTemp);
    cTemp &= PCI_HEADER_TYPE_MASK;

    switch (cTemp)
	{
	case PCI_HEADER_TYPE0:	/* non PCI-PCI bridge */

	    /*
	     * Disable Expansion ROM address decode for the device.
	     * Note that no mem space is allocated for the Expansion
	     * ROM, so a re-enable later should NOT be done.
	     */

	    pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
				 pPciFunc->function, PCI_CFG_EXPANSION_ROM,
				 0x1, 0);
	    break;

	case PCI_HEADER_PCI_PCI:	/* PCI-PCI bridge */

	    pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
				 pPciFunc->function, PCI_CFG_ROM_BASE,
				 0x1, 0);
	    break;

	default:
	    break;
	}

    return;
    }


/******************************************************************************
*
* pciAutoFuncEnable - Perform final configuration and enable a function
*
* Depending upon whether the device is included, this routine initializes
* a single PCI function as follows:
*
* Initialize the cache line size register
* Initialize the PCI-PCI bridge latency timers
* Enable the master PCI bit for non-display devices
* Set the interrupt line value with the value from the BSP.
*
* RETURNS: N/A.
*
*/

void pciAutoFuncEnable
    (
    PCI_SYSTEM * pSystem, /* PCI system info */
    PCI_LOC * pFunc       /* input: Pointer to PCI function structure */
    )
    {
    short pciClass;	  /* PCI class/subclass contents */
    UCHAR intLine = 0xff; /* Interrupt "Line" value           */
    UCHAR intPin  = 0xff; /* Interrupt "Pin" value            */

    if ((pFunc->attribute) & PCI_AUTO_ATTR_DEV_EXCLUDE)
        {
        return;
        }

   PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: enable device [%d,%d,%d,0x%02x]\n",
	(pFunc->bus),
	(pFunc->device),
	(pFunc->function),
	(pFunc->attribute),
	0,
	0
	);

    /* Initialize the cache line size register */

    pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
		    PCI_CFG_CACHE_LINE_SIZE, pSystem->cacheSize);

    /* Initialize the latency timer */

    pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
		      PCI_CFG_LATENCY_TIMER, pSystem->maxLatency);

    /* Get the PCI class code */

    pciConfigInWord (pFunc->bus, pFunc->device, pFunc->function,
		    PCI_CFG_SUBCLASS, &pciClass);

   /* Enable Bus Mastering (preserve status bits) */

    pciConfigModifyLong (pFunc->bus, pFunc->device, pFunc->function,
			 PCI_CFG_COMMAND,
			 (0xffff0000 | PCI_CMD_MASTER_ENABLE),
			 PCI_CMD_MASTER_ENABLE);

    /* 
     * If an interrupt assignment routine is registered, assign the 
     * interrupt and record interrupt line in config header, else 
     * write 0xff (default value) to the interrupt line reg
     */

    pciConfigInByte (pFunc->bus, pFunc->device, pFunc->function,
                     PCI_CFG_DEV_INT_PIN, &intPin);

    intLine = pciAutoIntAssign (pSystem, pFunc, intPin);

    pciConfigOutByte (pFunc->bus, pFunc->device, pFunc->function,
		      PCI_CFG_DEV_INT_LINE, intLine);

    /* Reset all writeable status bits */

    pciConfigOutWord (pFunc->bus, pFunc->device, pFunc->function,
                      PCI_CFG_STATUS, (UINT16)0xFFFF);

    return;
    }

/******************************************************************************
*
* pciAutoIntAssign - Compute the interrupt number for a given PCI device.
*
* This routine computes the interrupt number for a PCI device identified
* by the parameter <pFunc>.
*
* The algorithm used is the following: if the device is on the PCI bus 0,
* then the bsp interrupt assign routine (if any) is called to get the 
* actual IRQ number used. In adddition, if the device is a Pci-To-Pci 
* Bridge, then this routine populates a routing table that will be used 
* later for all of the PCI devices on its every subourdinate buses.
* Conversely, if the device sits on any PCI bus other than bus 0, this
* routines only looks at that table. The index used depends not
* only on the device's location on the bus, but also on the routing offset
* of the most immediate Pci-To-Pci Bridge. This offset, in turn, is based
* on its location in the PCI hierarchy and was computed earlier by the 
* PCI configuration process. However, the user may skip this automatic 
* interrupt assignment process by simply setting the variable autoIntRouting
* in the relevant PCI_SYSTEM structure to FALSE. In this case the bsp 
* interrupt assign routine will be called to get the IRQ number for the device.
*
* RETURNS: the interrupt number associated with the device.
*/
 
UCHAR pciAutoIntAssign
    (
    PCI_SYSTEM * pSystem, /* PCI system info */
    PCI_LOC * pFunc,      /* input: Pointer to PCI function structure */
    UCHAR        intPin   /* Interrupt "Pin" value            */
    )
    {
    UCHAR retVal = 0xFF;
 
    /* 
     * if the bsp provides interrupt routing for all PCI devices, 
     * then there's no need of any computation whatsoever 
     */

    if ((!(pSystem->autoIntRouting)) && (intPin != 0))
        {
        if ((pSystem->intAssignRtn) != NULL )
            {
            retVal = (pSystem->intAssignRtn) (pSystem, pFunc, intPin);

            return (retVal);
            }

        }

    /* default interrupt routing: let's find out the IRQ for this device */

    switch (pFunc->bus)
        {
        case 0:

            if (((pSystem->intAssignRtn) != NULL) && (intPin != 0))
                {
                retVal = (pSystem->intAssignRtn) (pSystem, pFunc, intPin);
                }

            /* 
             * if this is a P2P Bridge, then populate its interrupt
             * routing table. This will be used later for all the devices
             * belonging to its every subourdinate bus
             */

            if (((pFunc->attribute) & PCI_AUTO_ATTR_BUS_PCI) > 0)
                {
                int i = 0;

                for (i = 0; i < 4; i++)
                    {
                    if ((pSystem->intAssignRtn) != NULL )
                        {
                        pciAutoIntRoutingTable [i]  = (pSystem->intAssignRtn) 
                                                      (pSystem, pFunc, (i+1));
                        }
                    }

                }

            break;

        default:

            retVal = pciAutoIntRoutingTable [(((pFunc->device) + (intPin - 1) 
                                              + (pFunc->offset)) % 4)];
            break;
        }

    PCI_AUTO_DEBUG_MSG("pciAutoIntAssign: int for [%d,%d,%d] pin %d is [%d]\n",
              pFunc->bus, pFunc->device, pFunc->function, intPin, retVal, 0);

    return retVal;
    }

/******************************************************************************
*
* pciAutoGetNextClass - find the next device of specific type from probe list
*
* The function uses the probe list which was built during the probing
* process.  Using configuration accesses, it searches for the
* occurrence of the device subject to the 'class' and 'mask'
* restrictions outlined below.  Setting 'class' to zero and 'mask' to
* zero allows searching the entire set of devices found regardless of
* class.
*
* RETURNS: TRUE if a device was found, else FALSE
*
*/

STATUS pciAutoGetNextClass
    (
    PCI_SYSTEM *pPciSystem,
    PCI_LOC *pPciFunc,  /* output: Contains the BDF of the device found */
    UINT *index,        /* Zero-based device instance number */
    UINT pciClass,      /* class code field from the PCI header */
    UINT mask           /* mask is ANDed with the class field */
    )
    {
    UINT i;
    UINT idx = *index;
    UINT classCode;
    UINT nSize;
    PCI_LOC *pciList;
  
    nSize = (UINT)lastPciListSize;
    pciList = pLastPciList;

    PCI_AUTO_DEBUG_MSG("\npciAutoGetNextClass: index[%d] listSiz[%d]\n",
	*index, nSize, 0, 0, 0, 0);
    PCI_AUTO_DEBUG_MSG("                     pciClass[0x%08x], mask[0x%08x]\n",
	pciClass, mask, 0, 0, 0, 0);

    if ((nSize <= idx) || (pciList == NULL))
        return (FALSE);             /* No more devices */
 
    for (i = idx; i < nSize; i++)
        {

        /* Grab the class code 24-bit field */
 
        pciConfigInLong ((UINT)pciList[i].bus, (UINT)pciList[i].device,
                         (UINT)pciList[i].function, (PCI_CFG_CLASS & 0xfc),
                         &classCode);

        classCode >>= 8;        /* Isolate class code in low order bits */

⌨️ 快捷键说明

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