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 + -
显示快捷键?