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

📄 pciautoconfiglib.c

📁 LoPEC Early Access VxWorks BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
	    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 addrInfo		/* PCI address type information	      */    )    {    UINT register64Bit = 0;	/* 64 bit register flag */    UINT * pBase;    UINT * pAvail;    UINT32 alignedBase;    UINT32 sizeAdj;    STATUS retStat = ERROR;    /* Process address attribute info */    switch (addrInfo & (UINT)PCI_BAR_MEM_TYPE_MASK )	{	case PCI_BAR_MEM_BELOW_1MB:	    break;	case PCI_BAR_MEM_ADDR64:	    /*	     * Check for a 64-bit addressable memory device, currently	     * the PReP address map does not support physical addresses	     * above 4Gb (i.e., 32-bits), so the configuration process	     * will initialize the upper base register to zero (i.e.,	     * the safe thing to do), so for right now we'll skip the	     * next base address register which belongs to the 64-bit	     * pair of 32-bit base address registers.	     */	    register64Bit = 1;	    break;	case PCI_BAR_MEM_ADDR32:	    break;	case PCI_BAR_MEM_RESERVED:	    /* fall through */	default:	    *pAlloc = NO_ALLOCATION;	    return 0;	}    if ( (addrInfo & PCI_BAR_MEM_PREFETCH) &&	  ((pPciFunc->attribute) & PCI_AUTO_ATTR_BUS_PREFETCH) )	{	PCI_AUTO_DEBUG_MSG("pciAutoMemAlloc: PF Mem requested"		"\n", 0, 0, 0, 0, 0, 0);	pBase = &(pPciSys->pciMem32);	pAvail = &(pPciSys->pciMem32Size);	if (*pAvail > 0)	    {	    retStat = pciAutoAddrAlign (*pBase,					(*pBase + *pAvail),					size,					&alignedBase);	    }	if (retStat == ERROR)	    {	    /* If no PF memory available, then try conventional */	    PCI_AUTO_DEBUG_MSG("pciAutoMemAlloc: No PF Mem available"		    "Trying MemIO\n", 0, 0, 0, 0, 0, 0);	    pBase = &(pPciSys->pciMemIo32);	    pAvail = &(pPciSys->pciMemIo32Size);	    if (*pAvail > 0)		{		retStat = pciAutoAddrAlign (*pBase,					    (*pBase + *pAvail),					    size,					    &alignedBase);		}	    if (retStat == ERROR)		{		logMsg("Warning: PCI PF Mem alloc failed\n", 0, 0, 0, 0, 0, 0);		*pAlloc = NO_ALLOCATION;		return 0;		}	    }	}    else	{		/* Use 32-bit Non-Prefetch Mem

⌨️ 快捷键说明

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