pci.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 928 行 · 第 1/3 页
C
928 行
} /* FindPCIParentDevice() */
/* This function will list all devices that are present on the PCI bus */
int ListPCIDevices( void ) {
PCIDevIDRec TargetPCIDevID;
PCIDevAddrRec CurDevice;
WORD wVendorID, wDeviceID;
WORD wPCIStatus;
/* Initialize search specification record to match anything */
TargetPCIDevID.wVendorID = TargetPCIDevID.wDeviceID = 0;
TargetPCIDevID.wSubsystemVendorID = TargetPCIDevID.wSubsystemID = 0;
/* Initialize search location record to start from beginning */
CurDevice.bParentDevNo = CurDevice.bDevNo = 0xFF;
DbgPrintf( "Searching For PCI Devices...\n" );
do {
if (FindNextPCIDevice( &TargetPCIDevID, &CurDevice )) {
DbgPrintf( "ListPCIDevices() - ERROR: Call To FindNextPCIDevice() Failed\n" );
return 1;
}
if (CurDevice.bDevNo != 0xFF) {
/* Read the Vendor ID */
OEM_ReadConfigWord( CurDevice.bBusNo, CurDevice.bDevNo, CurDevice.bFuncNo, 0x00, &wVendorID );
if ((wPCIStatus = GetPCIBridgeStatus( &CurDevice )) != 0) {
ClearPCIBridgeStatus( &CurDevice );
DbgPrintf( "FindNextPCIDevice() - ERROR: Vendor ID Read Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
/* Read the Device ID */
OEM_ReadConfigWord( CurDevice.bBusNo, CurDevice.bDevNo, CurDevice.bFuncNo, 0x02, &wDeviceID );
if ((wPCIStatus = GetPCIBridgeStatus( &CurDevice )) != 0) {
ClearPCIBridgeStatus( &CurDevice );
DbgPrintf( "FindNextPCIDevice() - ERROR: Device ID Read Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
DbgPrintf( " Vendor ID 0x%04X Device ID 0x%04X at Bus %d, Device %d, Function %d\n",
wVendorID, wDeviceID, CurDevice.bBusNo, CurDevice.bDevNo, CurDevice.bFuncNo );
}
}
while (CurDevice.bDevNo != 0xFF);
DbgPrintf( "PCI Device Search Complete\n" );
return 0;
} /* ListPCIDevices() */
/* This routine will create the memory and I/O windows specified in pPCIMapInfo */
/* through all the bridges between the device specified in pCurDevice and the */
/* device specified in pTargetDevice. You must specify the full configuration */
/* address for pCurDevice unless starting from the host bridge, in which case */
/* you must initialize the pTargetDevice->bParentDevNo to 0xFF to indicate */
/* starting from the host bridge, and initialize pTargetDevice->bDevNo to 0xFF */
/* to indicate starting from device 0. */
int MapPCIWindows( PCIMapInfoRec *pPCIMapInfo, PCIDevAddrRec *pCurDevice, PCIDevAddrRec *pTargetDevice ) {
WORD wPCIStatus;
BYTE bHeaderType, bSecondaryBusNo, bSubordinateBusNo;
DbgPrintf("+MapPCIWindows()\n");
/* If the parent device number is 0xFF, then assume that we are on the */
/* PCI segment that is directly connected to the host bridge. It has */
/* bus number 0. */
if (pCurDevice->bParentDevNo == 0xFF)
pCurDevice->bBusNo = 0;
/* Set the current bridge windows */
if (SetPCIBridgeWindows( pCurDevice, pPCIMapInfo )) {
DbgPrintf( "MapPCIWindows() - ERROR: Call To SetPCIBridgeWindows() Failed\n" );
return 1;
}
DbgPrintf("MapPCIWindows: pCurDevice->bBusNo=%d, pTargetDevice->bBusNo=%d\n",
pCurDevice->bBusNo, pTargetDevice->bBusNo);
/* See if we have arrived on the same bus as the target device yet. */
/* If so, we're done. */
if (pCurDevice->bBusNo == pTargetDevice->bBusNo)
return 0;
if (ScanNextPCIDevice( pCurDevice )) {
DbgPrintf( "MapPCIWindows() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
while( pCurDevice->bDevNo != 0xFF ) {
/* Read the configuration header type in order to determine */
/* whether or not this is a bridge. */
OEM_ReadConfigByte( pCurDevice->bBusNo, pCurDevice->bDevNo, 0x00, 0x0E, &bHeaderType );
if ((wPCIStatus = GetPCIBridgeStatus( pCurDevice )) != 0) {
DbgPrintf( "MapPCIWindows() - ERROR: Configuration Header Type Read Failed\n" );
ClearPCIBridgeStatus( pCurDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* If this is a PCI-PCI bridge we need to determine if the */
/* target device is behind it. */
if ((bHeaderType & 0x7F) == 0x01) {
/* Read the secondary bus number */
OEM_ReadConfigByte( pCurDevice->bBusNo, pCurDevice->bDevNo, pCurDevice->bFuncNo, 0x19, &bSecondaryBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurDevice )) != 0) {
DbgPrintf( "MapPCIWindows() - ERROR: Secondary Bus Number Read Failed\n" );
ClearPCIBridgeStatus( pCurDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Read the subordinate bus number */
OEM_ReadConfigByte( pCurDevice->bBusNo, pCurDevice->bDevNo, pCurDevice->bFuncNo, 0x1A, &bSubordinateBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurDevice )) != 0) {
DbgPrintf( "MapPCIWindows() - ERROR: Subordinate Bus Number Read Failed\n" );
ClearPCIBridgeStatus( pCurDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* If the RIO is behind this bridge, then we need to recursively */
/* call ourselves and set it up. */
if (pTargetDevice->bBusNo >= bSecondaryBusNo && pTargetDevice->bBusNo <= bSubordinateBusNo) {
/* Go look for the RIO on the secondary side of the bridge */
pCurDevice->bParentBusNo = pCurDevice->bBusNo;
pCurDevice->bParentDevNo = pCurDevice->bDevNo;
pCurDevice->bParentFuncNo = pCurDevice->bFuncNo;
pCurDevice->bBusNo = bSecondaryBusNo;
pCurDevice->bDevNo = 0xFF;
if (MapPCIWindows( pPCIMapInfo, pCurDevice, pTargetDevice ))
return 1;
return 0;
}
}
/* Find the next PCI device on this segment */
if (ScanNextPCIDevice( pCurDevice )) {
DbgPrintf( "MapPCIWindows() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
}
DbgPrintf( "MapPCIWindows() - ERROR: Could Not Find Path To Target Device\n" );
return 1;
} /* MapPCIWindows() */
/* This routine will clear the PCI secondary status register flags in the PCI */
/* device indicated. Note that for bus 0 (the PCI host bridge) this will be */
/* the only set of status flags. For any other bus number, we are going */
/* through a PCI-PCI bridge and we will be working with the secondary */
/* interface status register. */
WORD GetPCIBridgeStatus( PCIDevAddrRec *pPCIDevice ) {
WORD wPCIStatus;
if (pPCIDevice->bParentDevNo == 0xFF)
OEM_GetPCIHostBridgeStatus( &wPCIStatus );
else
OEM_ReadConfigWord( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo,
pPCIDevice->bParentFuncNo, 0x1E, &wPCIStatus );
return wPCIStatus & PCIE_MASK;
} /* GetPCIBridgeStatus() */
/* This routine will clear the PCI secondary status register flags in the PCI */
/* device indicated. Note that for bus 0 (the PCI host bridge) this will be */
/* the only set of status flags. For any other bus number, we are going */
/* through a normal PCI-PCI bridge and we will be working with the secondary */
/* interface status register. */
void ClearPCIBridgeStatus( PCIDevAddrRec *pPCIDevice ) {
if (pPCIDevice->bParentDevNo == 0xFF)
OEM_ClearPCIHostBridgeStatus();
else
OEM_WriteConfigWord( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo,
pPCIDevice->bParentFuncNo, 0x1E, PCIE_MASK );
} /* ClearPCIBridgeStatus() */
/* This routine will print a description of each of the PCI error codes */
/* that are flagged in an error code word. */
void PrintPCIError( WORD wPCIErrorCode ) {
if (!wPCIErrorCode) {
DbgPrintf( "No Error" );
return;
}
if (wPCIErrorCode & PCIE_PARITY_ERROR)
DbgPrintf( "PCI Parity Error Detected\n" );
if (wPCIErrorCode & PCIE_SYSTEM_ERROR)
DbgPrintf( "PCI System Error Detected\n" );
if (wPCIErrorCode & PCIE_MASTER_ABORT)
DbgPrintf( "PCI Master Abort Detected\n" );
if (wPCIErrorCode & PCIE_TARGET_ABORT_MASTER)
DbgPrintf( "PCI Target Abort Detected While Interface Was Master\n" );
if (wPCIErrorCode & PCIE_TARGET_ABORT_TARGET)
DbgPrintf( "PCI Target Abort Detected While Interface Was Target\n" );
if (wPCIErrorCode & PCIE_MASTER_PARITY_ERROR)
DbgPrintf( "PCI Parity Error Detect While Interface Was Master\n" );
} /* PrintPCIError() */
/* This function takes the configuration address for a PCI device as the */
/* parameter pPCIDevice. It will then activate the bridge that is */
/* specified as that device's parent and will open memory and I/O windows */
/* specified in pPCIMapInfo. */
int SetPCIBridgeWindows( PCIDevAddrRec *pPCIDevice, PCIMapInfoRec *pPCIMapInfo ) {
WORD wPCIStatus;
DbgPrintf("+SetPCIBridgeWindows(). pPciDevice->bParentDevNo = %d\n", pPCIDevice->bParentDevNo);
/* If the parent bridge addres pointer is NULL, then the parent is the */
/* PCI Host Bridge. Call the OEM function to configure that. */
if (pPCIDevice->bParentDevNo == 0xFF) {
if (OEM_SetPCIHostBridgeWindows( pPCIMapInfo )) {
DbgPrintf( "SetBridgeWindows() - ERROR: Call To OEM_SetPCIHostBridgeWindows() Failed\n" );
return 1;
}
}
else {
/* Fill in the Memory Address range information. */
/* Fill in the Memory Base Register */
OEM_WriteConfigWord( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo, pPCIDevice->bParentFuncNo,
0x20, (WORD)(pPCIMapInfo->dwPCIMemBase >> 16));
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "SetBridgeWindows() - ERROR: PCI Memory Base Write Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Fill in the Memory Range Register */
OEM_WriteConfigByte( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo, pPCIDevice->bParentFuncNo,
0x22, (WORD)(pPCIMapInfo->dwPCIMemLimit >> 16));
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "SetBridgeWindows() - ERROR: PCI Memory Limit Write Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Fill in the I/O Address range information. */
/* Note that this is for 16-bit address range bridges only */
/* and I'll make it generic once I get the full PCI-PCI */
/* bridge specification. 16-bit address bridges only */
/* allow mapping in the lower 64K address range using 4K */
/* pages. */
DbgPrintf("Setting PCI-PCI bridge I/o Base Register. dwPCIIOBase = 0x%x, Limit = 0x%x\n", pPCIMapInfo->dwPCIIOBase,
pPCIMapInfo->dwPCIIOLimit);
/* Fill in the I/O Base Register */
OEM_WriteConfigByte( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo, pPCIDevice->bParentFuncNo,
0x1C, (BYTE)(pPCIMapInfo->dwPCIIOBase >> 8));
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "SetBridgeWindows() - ERROR: PCI I/O Base Write Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Fill in the I/O Range Register */
OEM_WriteConfigByte( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo, pPCIDevice->bParentFuncNo,
0x1D, (BYTE)(pPCIMapInfo->dwPCIIOLimit >> 8));
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "SetBridgeWindows() - ERROR: PCI I/O Limit Write Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Turn on the bridge to accept memory and I/O accesses and */
/* also to act as a PCI master. */
OEM_WriteConfigWord( pPCIDevice->bParentBusNo, pPCIDevice->bParentDevNo, pPCIDevice->bParentFuncNo,
0x04, 0x0157 );
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "SetBridgeWindows() - ERROR: PCI Bridge Command Register Write Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
}
return 0;
} /* SetPCIBridgeWindows() */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?