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

📄 pciautoconfiglib.c

📁 MPC8241:本程序是freescale的824*系列的BSP源程序
💻 C
📖 第 1 页 / 共 5 页
字号:

        if ((classCode & mask) == (pciClass & mask))
            {
            *index = i;
            *pPciFunc = pciList[i];
            return (TRUE);
            }

        }
    return (FALSE);
    }

/******************************************************************************
*
* pciAutoDevConfig - Allocate memory and I/O space to PCI function.
*
* This routine allocates memory and I/O space to functions on an
* individual PCI bus.
*
* LIMITATIONS: 
*
* do not sort the include function list before this routine is
* called.  This routine requires each function in the list to be in the
* same order as the probe occurred.
*
* RETURNS: N/A.
*/

LOCAL void pciAutoDevConfig
    (
    PCI_SYSTEM * pSystem,  /* PCI system info */
    UINT bus,		/* Current bus number	   */
    PCI_LOC **ppPciList,	/* Pointer to function list */
    UINT *nSize		/* Number of remaining funcs */
    )
    {
    PCI_LOC *pPciFunc;	/* Pointer to PCI function	   */
    UINT nextBus;		/* Bus where function is located   */
    short pciClass;		/* Class field of function	   */

    /* Process each function within the list */

    while (*nSize > 0)
	{

	/* Setup local variables */

	pPciFunc = *ppPciList;
	nextBus = pPciFunc->bus;

	/* Decrease recursion depth if this function is on a parent bus */

	if (nextBus < bus)
	    {
	    return;
	    }

	/* Allocate and assign space to functions on this bus */

	pciAutoFuncConfig (pSystem, pPciFunc);
	(*nSize)--;
	(*ppPciList)++;

	/* Increase recursion depth if this function is a PCI-PCI bridge */

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

	switch (pciClass)
	    {
	    case (( PCI_CLASS_BRIDGE_CTLR << 8) + PCI_SUBCLASS_P2P_BRIDGE ):

		/* PCI-PCI bridge functions increase recursion depth */

		pciAutoBusConfig (pSystem, pPciFunc, ppPciList, nSize);
		break;

	    default:
		/* Maintain current recursion depth */

		break;
	    }
	}
    }

/******************************************************************************
*
* pciAutoFuncConfig - Assign memory and/or I/O space to single function.
*
* This routine allocates and assigns memory and/or I/O space to a
* single PCI function.	 Allocations are made for each implemented
* base address register (BAR) in the PCI configuration header.
*
* RETURNS: N/A.
*/

LOCAL void pciAutoFuncConfig
    (
    PCI_SYSTEM * pSystem,
    PCI_LOC * pPciFunc	/* input: "Include list" pointer to function */
    )
    {
    UINT baMax;	/* Total number of base addresses    */
    UINT baI;	/* Base address register index	     */
    UINT baseAddr;	/* PCI Offset of base address	     */
    UINT readVar;	/* Contents of base address register */
    UINT addrInfo;	/* PCI address type information	     */
    UINT sizeMask;	/* LSbit for size calculation	     */
    UCHAR headerType;	/* Read from PCI config header	     */
    UINT dev_vend;

    /* If there is a function, then consult the exclusion routine */

    if ( (pSystem->includeRtn) != NULL )
	{
	pciConfigInLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
			 PCI_CFG_VENDOR_ID, &dev_vend);
	if ( ((pSystem->includeRtn) (pSystem, pPciFunc, dev_vend)) == ERROR )
	    {
	    if ((pPciFunc->attribute & PCI_AUTO_ATTR_BUS_PCI) == 0) 
		{
		pPciFunc->attribute |= PCI_AUTO_ATTR_DEV_EXCLUDE;
		PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: exc [%d,%d,%d,0x%02x]\n",
		pPciFunc->bus, pPciFunc->device, pPciFunc->function,
		pPciFunc->attribute,0,0);
		return;
		}
	    }
	}

    /* Disable the function */

    pciAutoFuncDisable (pPciFunc);

    /* Determine the number of base address registers present */

    pciConfigInByte (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
		     PCI_CFG_HEADER_TYPE, &headerType);
    headerType &= 0x7f;

    switch (headerType)
	{
	case PCI_HEADER_TYPE0:
	    baMax = 6;
	    break;

	case PCI_HEADER_PCI_PCI:
	    baMax = 2;
	    break;

	default:
	    baMax = 0;
	    break;
	}

    /* Allocate Memory or I/O space for each implemented base addr register */

    for (baI = 0; baI < baMax; baI++)
	{
	/* Get the base address register contents */

	baseAddr = PCI_CFG_BASE_ADDRESS_0 + (baI * 4);

	pciConfigOutLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
			  baseAddr, 0xFFFFFFFF);

	pciConfigInLong (pPciFunc->bus, pPciFunc->device, pPciFunc->function,
			 baseAddr, &readVar);

	/* Go to the next BAR when an unimplemented one (BAR==0) is found */

	if (readVar == 0)
	    {
	    continue;
	    }

        /* Mask off all but space, memory type, and prefetchable bits */

	addrInfo = readVar & PCI_BAR_ALL_MASK;

	/* Check for type, setup mask variables (based on type) */

	if ((addrInfo & PCI_BAR_SPACE_MASK) == PCI_BAR_SPACE_IO)
	    {
	    PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: IO Space found at BAR[%d]\n",
		    baI, 0, 0, 0, 0, 0);
	    sizeMask = (1 << 2);
	    }
	else
	    {
	    PCI_AUTO_DEBUG_MSG("pciAutoFuncConfig: MemSpace found at BAR[%d]\n",
		    baI, 0, 0, 0, 0, 0);
	    sizeMask = (1 << 4);
	    }

	/* Loop until we find a bit set or until we run out of bits */

	for (; sizeMask; sizeMask <<= 1)
	    {
	    /* is this bit set? if not, keep looking */

	    if (readVar & sizeMask)
		{
		baI += pciAutoRegConfig (pSystem, pPciFunc, baseAddr, sizeMask,
					addrInfo);
		break;
		}
	    }
	}

    }

/******************************************************************************
*
* pciAutoRegConfig - Assign PCI space to a single PCI base address register.
*
* This routine allocates and assigns PCI space (either memory or I/O)
* to a single PCI base address register.
*
* RETURNS: 
* 
* Returns (1) if BAR supports mapping anywhere in 64-bit address space. 
* Returns (0) otherwise.
*/

UINT pciAutoRegConfig
    (
    PCI_SYSTEM * pSystem,	/* Pointer to PCI System structure */
    PCI_LOC *pPciFunc,		/* Pointer to function in device list */
    UINT baseAddr,		/* Offset of base PCI address */
    UINT nSize,			/* Size and alignment requirements */
    UINT addrInfo		/* PCI address type information	*/
    )
    {
    UINT addr;			/* Working address variable */
    UINT spaceEnable = 0;	/* PCI space enable bit */
    UINT baseaddr_mask;		/* Mask for base address register */
    UINT register64Bit;		/* 64 bit register flag */

    /* Select the appropriate PCI address space for this register */

    if ((addrInfo & PCI_BAR_SPACE_MASK) == PCI_BAR_SPACE_IO)
	{

	/* Configure this register for PCI I/O space */

	spaceEnable = PCI_CMD_IO_ENABLE;
	baseaddr_mask = 0xFFFFFFFC;
	register64Bit = pciAutoIoAlloc (pSystem, pPciFunc, &addr, nSize);
	}
    else
	{

	/* Configure this register for PCI memory space */

	spaceEnable = PCI_CMD_MEM_ENABLE;
	baseaddr_mask = 0xFFFFFFF0;
	register64Bit = pciAutoMemAlloc (pSystem, pPciFunc, &addr, nSize,
					  addrInfo);
	}

    /*
     * Do not exceed the upper boundary! If this occurs, all we can
     * do here is return, as this is called early in the initialization
     * process, before I/O is available to print error messages.
     */

    if (addr != NO_ALLOCATION)
	{

	/* Program the base address register */

	PCI_AUTO_DEBUG_MSG("pciAutoRegConfig:[0x%08x] written to BAR[0x%08x]\n",
		addr, baseAddr, 0, 0, 0, 0);

	pciConfigModifyLong (pPciFunc->bus, pPciFunc->device, 
				pPciFunc->function, baseAddr, 
				baseaddr_mask, addr);

	if (register64Bit)
	    {

	    /*
	     * Write the base address for 64-bit addressable memory devices:
	     * initialize the next base address register to zero, the PReP
	     * address map does support physical addresses above 4GB (i.e.,
	     * 32-bit address space)
	     */

	    pciConfigOutLong (pPciFunc->bus, pPciFunc->device, 
		    pPciFunc->function,
		    baseAddr + 4, 0);
	    }

	/* Set the appropriate enable bit, preserve status bits */

	pciConfigModifyLong (pPciFunc->bus, pPciFunc->device,
			 pPciFunc->function, PCI_CFG_COMMAND,
			 (0xffff0000 | spaceEnable), spaceEnable);
	}
    return (register64Bit);
    }

/******************************************************************************
*
* pciAutoIoAlloc - Select appropriate I/O space for device.
*
* This routine determines which PCI I/O space (16-bit or 32-bit) to assign
* to a particular function.  Note that functions located on subordinate
* busses must be  assigned to the 16 bit PCI I/O space due to 16 bit
* decoder limitations of certain bridges and functions.  The PCI
* specification limits each I/O base address register to 256 bytes, so
* this size should not be a problem.
*
* RETURNS: 0, indicating I/O space not located anywhere in 64-bit space.
*/

UINT pciAutoIoAlloc
    (
    PCI_SYSTEM * pPciSys,	/* PCI system structure	  */
    PCI_LOC *pPciFunc,	/* input: Pointer to PCI function element     */
    UINT *pAlloc,		/* output: Pointer to PCI space alloc pointer */
    UINT nSize		/* requested size (power of 2) */
    )
    {
    UINT * pBase;
    UINT32 alignedBase;
    UINT32 sizeAdj;
    UINT * pAvail = NULL;
    STATUS retStat = ERROR;

    /* Assign this register to PCI I/O space */

    if ((pPciFunc->bus == 0) && 
        ((pPciFunc->attribute & PCI_AUTO_ATTR_BUS_4GB_IO) != 0))
	{
	PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: 32-bit I/O\n", 0, 0, 0, 0, 0, 0);
	pBase = &(pPciSys->pciIo32);
	pAvail = &(pPciSys->pciIo32Size);
	}
    else
	{
	PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: 16-bit I/O\n", 0, 0, 0, 0, 0, 0);
	pBase = &(pPciSys->pciIo16);
	pAvail = &(pPciSys->pciIo16Size);
	}

    /* Adjust for alignment */

    if (*pAvail > 0) 
	{
	retStat = pciAutoAddrAlign (*pBase,
				    (*pBase + *pAvail),
				    nSize,
				    &alignedBase);
	}

    /* If the space is exhausted, then return an invalid pointer */

    if (retStat == ERROR)
	{
        logMsg("Warning: PCI I/O allocation failed\n", 0, 0, 0, 0, 0, 0);
	*pAlloc = NO_ALLOCATION;
	return 0;
	}

    PCI_AUTO_DEBUG_MSG("pciAutoIoAlloc: Pre/Post alloc: \n", 0, 0, 0, 0, 0, 0);
    PCI_AUTO_DEBUG_MSG("  Pre: pBase[0x%08x], pAvail[0x%08x]\n",
	    (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);

    *pAlloc  = alignedBase;
    sizeAdj = (alignedBase - *pBase) + nSize;
    *pBase  += sizeAdj;
    *pAvail -= sizeAdj;

    PCI_AUTO_DEBUG_MSG("  Post: pBase[0x%08x], pAvail[0x%08x]\n",
	    (int)(*pBase), (int)(*pAvail), 0, 0, 0, 0);

    return 0; /* can't have 64 bit i/o addresses */
    }

/******************************************************************************
*
* pciAutoMemAlloc - Select appropriate memory space for device.
*
* This routine determines which PCI memory space pool to use for assignment
* to a particular function.  Note that functions located on subordinate
* busses must be  assigned to the 32 bit PCI memory space due to 32 bit
* requirements of functions using more than 1MB memory space.
*
* LIMITATIONS:
*
* Does not support 64-bit Memory space
*
* RETURNS:
*
* Returns 1 if 64-bit addressable memory space.
* Returns zero (0) otherwise.
*/

UINT pciAutoMemAlloc
    (
    PCI_SYSTEM * pPciSys,	/* PCI system structure */
    PCI_LOC * pPciFunc, 	/* Pointer to PCI function element     */
    UINT * pAlloc,   	/* Pointer to PCI space alloc pointer */
    UINT size,		/* space requested (power of 2)  */
    UINT a

⌨️ 快捷键说明

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