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

📄 pciautoconfiglib.c

📁 LoPEC Early Access VxWorks BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
** 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 */        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;

⌨️ 快捷键说明

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