pci_enum.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 796 行 · 第 1/3 页
C
796 行
struct PciDeviceType PciDevice[NO_PCI_SLOTS] = { 0 };
// Has the PciBus already been enumerated.
int PciEnumerated = FALSE;
int pci_called=FALSE; // Whether an attempt to load the driver was made earlier.
#pragma data_seg()
/*********** END OF SHARED DATA SECTION VALUES *******************************/
/*****************************************************************************
* The following should not be shared data.
****************************************************************************/
// This structure will contain the Mapped PCI Io/Mem/Control Addresses.
// If any of the members is 0, it means that the particular memory
// range is not mapped.
struct PciBaseAddresses_Type PciBaseAddresses;
int RegistersMapped = FALSE; // Have the registers been mapped.
// Mapped addresses of the Pci Registers.
unsigned char *PciIoReg, *PciControlReg, *PciMemReg;
/****************************************************************************/
#if ((!defined CMON) && (!defined SDBTESTS))
#ifdef DEBUG
//
// These defines must match the ZONE_* defines in NE2000SW.H
//
#define DBG_ERROR 1
#define DBG_WARN 2
#define DBG_FUNCTION 4
#define DBG_INIT 8
DBGPARAM dpCurSettings = {
TEXT("PCI"), {
TEXT("Errors"),TEXT("Warnings"),TEXT("Functions"),TEXT("Init"),
TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined") },
0xffff
};
#endif // DEBUG
#endif
#ifndef SDBTESTS
#ifdef TEST_PCI
void dummy() { }
#else
#define dummy()
#endif
#endif SDBTESTS
/* Function prototypes. */
int OEM_InitPCIHostBridge( void );
void OEM_ReadConfigByte( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, BYTE *pbData );
void OEM_WriteConfigByte( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, BYTE bData );
void OEM_ReadConfigWord( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, WORD *pwData );
void OEM_WriteConfigWord( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, WORD wData );
void OEM_ReadConfigDword( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD *pdwData );
void OEM_WriteConfigDword( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD dwData );
/******************************************************************************
* Notes:
*
* 1. Some of the PCI cards do not implement the IO Base Addresses registers
* properly. The IO Base Address register when written with 0xff... and
* read back should indicate the amount of IO space it needs. But sometimes
* they do not. So i'm allocating 256 bytes to each of the IO device.
* This IS a terrible waste on the IO space, but since the number of devices
* for M1 is limited, one can live with it.
* 2. Some PCI card request an exhorbitant amount of Memory Space. One example
* is the S3 Trio64V+ card which i'm working on. The damned thing requests
* 64 Mb of Memory Space. Well it won't get it all. I restrict the max.
* allocated size to 16 Mb. This is because if i allocate the whole range
* of memory to this card, the address range allocated to other cards
* will be more than 0xb9000000 can handle. In that case for the subsequent
* memory addresses, i'll have to do a very dirty thing. For every memory
* access, first write to the Control register, and then write to the memory
* register.
* 3. I have reserved the first 4 Mb of Memory space for the first display card.
* The reason for doing this is that the existing drivers for Display card
* do not inquire the start of the display memory from the registry. So
* instead of designing my own mechanism to communicate the start address to
* the display driver, i just reserve the first 4 Mb for it. There's nothing
* wrong in this approach except that those 4 Mb go waste in case there is
* no display driver, or if the display device needs more than 4 Mb. In the
* latter case the system would still work if there are not PCI memory cards
* installed. Another approach would have been to scan for all PCI display
* devices and allocate them memory first and then scan for other devices.
* There are not too many merits in favor of this approach, so i'm not using
* it.
* 4. Presently it maps only DISP_MEM_SIZE of Pci Memory space into it's
virtual address space.
*****************************************************************************/
#if 0
/*****************************************************************************
* Map registers needs to be called once in the address space of each of the
* calling processes.
* It will map the physical register to the virtual address space for CE.
****************************************************************************/
int MapRegisters()
{
// If the registers have already been mapped, just return.
if(RegistersMapped) {
return TRUE;
}
RegistersMapped = TRUE;
#if ((defined CMON) || (defined SDBTESTS))
PciIoReg = (unsigned char *)PHYSICAL_PCI_IO;
PciMemReg = (unsigned char *)PHYSICAL_PCI_MEM;
PciControlReg = (unsigned char *)PHYSICAL_PCI_CONTROL;
// Fill in the members of PciBaseAddresses.
PciBaseAddresses.PciIoReg = (ULONG)PciIoReg;
PciBaseAddresses.PciMemReg = (ULONG)PciMemReg;
PciBaseAddresses.PciControlReg = (ULONG)PciControlReg;
return TRUE;
#else
DEBUGMSG(LEVEL1, (TEXT("PCI: MapRegisters called\r\n")));
// Map I/O board base address
PciControlReg = VirtualAlloc(0, 0x100, MEM_RESERVE, PAGE_NOACCESS);
if ( PciControlReg == NULL ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualAlloc 1 failed!\r\n")));
goto Error1;
}
if ( !VirtualCopy((PVOID)PciControlReg, (PVOID)PHYSICAL_PCI_CONTROL, 0x100, PAGE_READWRITE|PAGE_NOCACHE) ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualCopy 1 failed!\r\n")));
goto Error1;
}
// PCI Memory is not allocated any more in the pci driver. Any driver which
// needs pci memory must map it on it's own. This helps in saving virtual
// address space in the device drivers that don't need it.
// ALLOCATE_PCI_MEM would not be defined in the final version.
#ifdef PCI_DRIVER_ALLOCATES_PCI_MEM
// Only DISPLAY_MEM_SIZE bytes are mapped at present. This may be changed later.
PciMemReg = VirtualAlloc(0, PCI_MEM_SIZE, MEM_RESERVE, PAGE_NOACCESS);
if ( PciMemReg == NULL ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualAlloc 2 failed!\r\n")));
goto Error1;
}
if ( !VirtualCopy((PVOID)PciMemReg, (PVOID)PHYSICAL_PCI_MEM, PCI_MEM_SIZE, PAGE_READWRITE|PAGE_NOCACHE) ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualCopy 2 failed!\r\n")));
goto Error1;
}
#else
PciMemReg = 0;
#endif
PciIoReg = VirtualAlloc(0, MAX_IO_ADDRESS, MEM_RESERVE, PAGE_NOACCESS);
if ( PciIoReg == NULL ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualAlloc 3 failed!\r\n")));
goto Error1;
}
if ( !VirtualCopy((PVOID)PciIoReg, (PVOID)PHYSICAL_PCI_IO, MAX_IO_ADDRESS, PAGE_READWRITE|PAGE_NOCACHE) ) {
ERRORMSG(1, (TEXT("PCI: MapRegisters: VirtualCopy 3 failed!\r\n")));
goto Error1;
}
DEBUGMSG(LEVEL1, (TEXT("PCI: MapRegisters returning PciControlReg=0x%x, PciMemReg=0x%x, PciIoReg=0x%x\r\n"), PciControlReg, PciMemReg, PciIoReg));
DEBUGMSG(LEVEL1, (TEXT("PCI: MapRegisters returning TRUE\r\n")));
// Fill in the members of PciBaseAddresses.
PciBaseAddresses.PciIoReg = (ULONG)PciIoReg;
PciBaseAddresses.PciMemReg = (ULONG)PciMemReg;
PciBaseAddresses.PciControlReg = (ULONG)PciControlReg;
return TRUE;
Error1:
if ( PciControlReg )
VirtualFree((PVOID)PciControlReg, 0, MEM_RELEASE);
if ( PciMemReg )
VirtualFree((PVOID)PciMemReg, 0, MEM_RELEASE);
if ( PciIoReg )
VirtualFree((PVOID)PciIoReg, 0, MEM_RELEASE);
PciControlReg = 0;
PciMemReg = 0;
PciIoReg = 0;
// Fill in the members of PciBaseAddresses.
PciBaseAddresses.PciIoReg = (ULONG)PciIoReg;
PciBaseAddresses.PciMemReg = (ULONG)PciMemReg;
PciBaseAddresses.PciControlReg = (ULONG)PciControlReg;
DEBUGMSG(LEVEL1, (TEXT("PCI: MapRegisters returning FALSE\r\n")));
return FALSE;
#endif
}
#endif 0
/***************************************************************************
* Function: PciGetMappedBaseAddresses
* Input : None
* Output : pointer to a Structure of type PciBaseAddresses_Type which
* contains the Mapped Pci Io/Mem/Control Addresses.
* Synopsis: If i call Virtual Copy in the Ne2000 driver, it fails. So i need
* some mechanism to pass on the mapped base addresses to the driver.
* This is one of the approaches that can be used. The benefit of
* this approach is that once the addresses are mapped in this
* Dll, they can be used by any of the other dlls which use services
* from it. So you don't need to call VirtualCopy in the Dlls which
* sit on this Dll.
* Note: I'm returning the structure itself and not a pointer to it.
***************************************************************************/
struct PciBaseAddresses_Type *PciGetMappedBaseAddresses()
{
MapRegisters();
return &PciBaseAddresses;
}
unsigned PhysicalPciIoBase,
PhysicalPciMemBase;
unsigned PciEnumerate(void)
{
// short forms for the registers.
unsigned char cval;
unsigned short sval;
unsigned short CommandReg;
unsigned uval, i;
BOOL AllocatedDisplayMemory=FALSE; // Have i allocated display memory.
struct PciDeviceType *pPciDev;
unsigned CurIoBase = IOBASE,
CurMemBase = MEMBASE,
CurInt = INTBASE, // All PCI devices share this interrupt on current hardware.
CurSlot = 0,
SlotDisable = 0;
#ifdef CMON
// Set FRQCR
// WRITE_REGISTER_USHORT(WCR2, 0x8359);
#endif
OEM_InitPCIHostBridge();
// Map the Pci Registers first.
// MapRegisters();
for(CurSlot = 0; CurSlot < NO_PCI_SLOTS; CurSlot ++) {
pPciDev = &PciDevice[CurSlot];
DEBUGMSG(LEVEL5, (TEXT("PCI Enumerator scanning slot %d..."), CurSlot));
// Perform full PCI enumeration on card in slot CurSlot.
// WRITE_REGISTER_ULONG(ASLONG(PciControlReg), SlotEnable[CurSlot]);
// Step 1: VENDOR ID CHECK
OEM_ReadConfigWord(0, CurSlot, 0, 0, &sval);
pPciDev->VendorID = sval;
DEBUGMSG(LEVEL5, (TEXT("Vendor ID from slot %d = 0x%x\r\n"), CurSlot, sval));
if((sval == 0xffff) || (sval == 0x0))
continue;
// Assign Physical address values to the members of the pPciDev structure.
pPciDev ->PhysicalPciIoReg = PhysicalPciIoBase;
pPciDev ->PhysicalPciMemReg = PhysicalPciMemBase;
// pPciDev ->PhysicalPciControlReg = PHYSICAL_PCI_CONTROL;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?