📄 pciautoconfiglib.c
字号:
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 + -