pci.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 928 行 · 第 1/3 页
C
928 行
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995, 1996, 1997, 1998 Microsoft Corporation
Module Name:
pci.c
Abstract:
Function implementations for high level PCI configuration.
Functions:
Notes:
--*/
#include "platform.h"
#include "common.h"
#include "stdio.h"
/* This function will search a PCI bus segment for devices starting from a given */
/* configuration address. The pPCIDevice structure contains the address of the */
/* last device found (set pPCIDevice->bDevNo to 0xFF to start from the beginning). */
/* It then searches through the remainder of the devices, function by function, */
/* device by device. When it finds the next device, it returns the configuration */
/* address in the pPCIDevice structure. If no more devices are found, the */
/* structure is returned with pPCIDevice->bDevNo set to 0xFF. pParentBridge is */
/* the PCI configuration address of the parent bridge for the PCI bus segment */
/* being searched. This is necessary to allow error detection on that segment. */
int ScanNextPCIDevice( PCIDevAddrRec *pPCIDevice ) {
WORD wPCIStatus;
BYTE bData;
// DbgPrintf("+ScanNextPCIDevice(pPCIDevice=0x%x, bParentDevNo=0x%x, bDevNo=0x%x)\n", pPCIDevice, pPCIDevice->bParentDevNo, pPCIDevice->bDevNo );
/* If the parent bridge is the host bridge, assume that this is bus 0 */
if (pPCIDevice->bParentDevNo == 0xFF)
pPCIDevice->bBusNo = 0;
/* If the starting device address is invalid, start in the beginning */
if (pPCIDevice->bDevNo == 0xFF) {
pPCIDevice->bDevNo = 0;
pPCIDevice->bFuncNo = 0;
}
/* Otherwise, see if this is a multifunction device. If it is, then */
/* we may need to increment through the function numbers. */
else {
OEM_ReadConfigByte( pPCIDevice->bBusNo, pPCIDevice->bDevNo, 0, 0x0E, &bData );
if ((wPCIStatus = GetPCIBridgeStatus( pPCIDevice )) != 0) {
DbgPrintf( "ScanNextPCIDevice() - ERROR: Configuration Header Type Read Failed\n" );
ClearPCIBridgeStatus( pPCIDevice );
PrintPCIError( wPCIStatus );
return 1;
}
if (bData & 0x80 && pPCIDevice->bFuncNo < 7)
pPCIDevice->bFuncNo++;
else {
pPCIDevice->bDevNo++;
pPCIDevice->bFuncNo = 0;
}
}
/* The bDevNo and bFuncNo now give the address of the NEXT device to try */
do {
/* Determine if the current device is single or multi-function. */
/* If this is a multi-function device, the upper bit will be set. */
OEM_ReadConfigByte( pPCIDevice->bBusNo, pPCIDevice->bDevNo, pPCIDevice->bFuncNo, 0x0E, &bData );
wPCIStatus = GetPCIBridgeStatus( pPCIDevice );
ClearPCIBridgeStatus( pPCIDevice );
/* If I get a master abort, go to the next device */
if (wPCIStatus & PCIE_MASTER_ABORT) {
pPCIDevice->bFuncNo = 0;
pPCIDevice->bDevNo++;
}
/* If I get an error other than master abort, report it */
else if ((wPCIStatus & ~PCIE_MASTER_ABORT) != 0) {
DbgPrintf( "ScanNextPCIDevice() - ERROR: Configuration Header Type Read Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
}
while(wPCIStatus != 0 && pPCIDevice->bDevNo < 21);
/* If we hit the end without finding any more devices, set the device number to 0xFF */
/* to flag the end. */
if (wPCIStatus) {
/* Clear any left over errors on the parent bridge */
ClearPCIBridgeStatus( pPCIDevice );
pPCIDevice->bDevNo = 0xFF;
}
return 0;
} /* ScanNextPCIDevice() */
/* This function will recursively number the PCI bus segments. It will give */
/* the bus connected to the host bridge number 0, and then will scan the bus */
/* segment for PCI-PCI bridges. It will recurse behind any it finds, giving */
/* bus numbers to all segments behind each. */
int EnumeratePCIBuses( PCIDevAddrRec *pCurBridge, BYTE *pbLastBusNo ) {
PCIDevAddrRec NewBridge;
BYTE bHeaderType;
WORD wPCIStatus;
DbgPrintf("+EnumeratePCIBuses(pCurBridge=0x%x, pbLastBusNo=0x%x)\n", pCurBridge, pbLastBusNo);
/* Clear any pre-existing errors on the parent bridge */
ClearPCIBridgeStatus( pCurBridge );
/* First I need to go through all the bridges on this bus and disable their */
/* Type 1 to Type 0 configuration cycle translation. If the bus has been */
/* previously configured, the old mappings could mess things up this time. */
pCurBridge->bDevNo = 0xFF;
if (ScanNextPCIDevice( pCurBridge )) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
while( pCurBridge->bDevNo != 0xFF ) {
/* Read the PCI header type */
OEM_ReadConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x0E, &bHeaderType );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
ClearPCIBridgeStatus( pCurBridge );
DbgPrintf( "EnumeratePCIBuses() - ERROR: Configuration Header Type Read Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
/* If this is a PCI-PCI bridge */
if ((bHeaderType & 0x7F) == 0x01) {
DbgPrintf("+found PCI-PCI bridge. bHeaderType = 0x%x\n", bHeaderType);
/* Assign it a primary bus number */
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x18, pCurBridge->bBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Primary Bus Number Write Failed\n" );
ClearPCIBridgeStatus( pCurBridge );
PrintPCIError( wPCIStatus );
return 1;
}
/* Assign it secondary and subordinate bus numbers that are the same as the */
/* primary bus number so that it will not translate Type 1 bus accesses to */
/* Type 0 on the secondary side. */
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x19, pCurBridge->bBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Secondary Bus Number Write Failed\n" );
ClearPCIBridgeStatus( pCurBridge );
PrintPCIError( wPCIStatus );
return 1;
}
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x1A, pCurBridge->bBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Subordinate Bus Number Write 1 Failed\n" );
ClearPCIBridgeStatus( pCurBridge );
PrintPCIError( wPCIStatus );
return 1;
}
}
if (ScanNextPCIDevice( pCurBridge )) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
}
/* Now I'll go through the bridges again and this time I'll assign secondary */
/* and subordinate bus numbers using recursive calls. */
pCurBridge->bDevNo = 0xFF;
if (ScanNextPCIDevice( pCurBridge )) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
while( pCurBridge->bDevNo != 0xFF ) {
/* Read the PCI header type */
OEM_ReadConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x0E, &bHeaderType );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
ClearPCIBridgeStatus( pCurBridge );
DbgPrintf( "EnumeratePCIBuses() - ERROR: Configuration Header Type Read Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
/* If this is a PCI-PCI bridge */
if ((bHeaderType & 0x7F) == 0x01) {
/* Assign it a secondary bus number */
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x19, ++(*pbLastBusNo) );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
ClearPCIBridgeStatus( pCurBridge );
DbgPrintf( "EnumeratePCIBuses() - ERROR: Secondary Bus Number Write Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
/* For now, set the subordinate bus number to 0xFF so that the */
/* bridge will intercept all Type 1 configuration accesses */
/* for bridges behind it. After the recursive call I'll */
/* update the subordinate number with the greatest bus number */
/* that was actually assigned. */
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x1A, 0xFF );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
ClearPCIBridgeStatus( pCurBridge );
DbgPrintf( "EnumeratePCIBuses() - ERROR: Subordinate Bus Number Write 1 Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
/* Now make the recursive call to look for bridges behind the */
/* one that I just found. */
NewBridge.bParentBusNo = pCurBridge->bBusNo;
NewBridge.bParentDevNo = pCurBridge->bDevNo;
NewBridge.bParentFuncNo = pCurBridge->bFuncNo;
NewBridge.bBusNo = *pbLastBusNo;
NewBridge.bDevNo = 0xFF;
if (EnumeratePCIBuses( &NewBridge, pbLastBusNo ))
return 1;
/* PCI-PCI bridges do not appear to be entirely consistent for the default */
/* error reporting behavior to the initiating master when a master abort */
/* is detected on the secondary side of another attached bridge. To avoid */
/* reporting spurious errors that may have been propagated back to this */
/* bridge while searching for devices on another bus, I'll just clear them */
/* here now. */
/*
ClearPCIBridgeStatus( pCurBridge );
*/
/* Now that all buses behind this bridge have been enumerated, */
/* I'll update the subordinate bus number with the right value.*/
OEM_WriteConfigByte( pCurBridge->bBusNo, pCurBridge->bDevNo, pCurBridge->bFuncNo, 0x1A, *pbLastBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurBridge )) != 0) {
ClearPCIBridgeStatus( pCurBridge );
DbgPrintf( "EnumeratePCIBuses() - ERROR: Subordinate Bus Number Write 2 Failed\n" );
PrintPCIError( wPCIStatus );
return 1;
}
}
/* Find the next PCI device on this segment */
if (ScanNextPCIDevice( pCurBridge )) {
DbgPrintf( "EnumeratePCIBuses() - ERROR: Call To ScanNextPCIDevice() Failed\n" );
return 1;
}
}
return 0;
} /* EnumeratePCIBuses() */
/* This routine will search for PCI device given the Device and Vendor IDs and */
/* the Subsystem and Subsystem Vendor IDs. It starts from the position */
/* indicated in pTargetDevice and finds the next occurance of that device in */
/* the system. If any of these fields is 0, it will not be used as part of */
/* the search criteria. The full starting address must be specified, unless */
/* starting from the beginning, 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. When found, the full configuration address for the target */
/* device will be returned in pTargetDevice. If pTargetDevice->bDevNo = 0xFF, */
/* then no more matches were found. */
int bFindNextPCIDevice( PCIDevIDRec *pPCIDevID, PCIDevAddrRec *pCurDevice ) {
PCIDevAddrRec NewBridge;
WORD wVendorID, wDeviceID, wSubsystemVendorID, wSubsystemID;
WORD wPCIStatus;
BYTE bHeaderType, bSecondaryBusNo;
do {
/* If the current device is valid, I will check to see if it is a bridge. */
/* If so I will recursively look behind it for the target device. */
if (pCurDevice->bDevNo != 0xFF) {
/* Determine whether or not this is a bridge */
OEM_ReadConfigByte( pCurDevice->bBusNo, pCurDevice->bDevNo, 0x00, 0x0E, &bHeaderType );
if ((wPCIStatus = GetPCIBridgeStatus( pCurDevice )) != 0) {
DbgPrintf( "FindNextPCIDevice() - ERROR: Configuration Header Type Read Failed\n" );
ClearPCIBridgeStatus( pCurDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* If this is a PCI-PCI bridge we need to recursively call */
/* ourselves so that we can look behind it. */
if ((bHeaderType & 0x7F) == 0x01) {
/* Read the secondary bus number. This will be the bus */
/* number that is searched next. */
OEM_ReadConfigByte( pCurDevice->bBusNo, pCurDevice->bDevNo, pCurDevice->bFuncNo, 0x19, &bSecondaryBusNo );
if ((wPCIStatus = GetPCIBridgeStatus( pCurDevice )) != 0) {
DbgPrintf( "FindNextPCIDevice() - ERROR: Secondary Bus Number Read Failed\n" );
ClearPCIBridgeStatus( pCurDevice );
PrintPCIError( wPCIStatus );
return 1;
}
/* Go look for the target device on the secondary side of the bridge */
NewBridge.bParentBusNo = pCurDevice->bBusNo;
NewBridge.bParentDevNo = pCurDevice->bDevNo;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?