pci_enum.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 796 行 · 第 1/3 页
C
796 行
OEM_ReadConfigWord(0, CurSlot, 0, 2, &sval);
pPciDev->DeviceID = sval;
DEBUGMSG(LEVEL5, (TEXT("Device ID from slot %d = 0x%x\r\n"), CurSlot, sval));
// Get The Base Class Code of the device.
OEM_ReadConfigByte(0, CurSlot, 0, BASE_CLASS_CODE, &cval);
if(cval >= 0x0d && cval <= 0xfe) {
cval = PCI_CLASS_RESERVED;
}
if(cval == 0xff) {
cval = PCI_CLASS_UNDEFINED;
}
pPciDev->BaseClassCode = cval;
DEBUGMSG(LEVEL5, (TEXT("Device Base Class Code: %s[%d]\r\n"), DeviceClass[cval], cval));
// Determine whether the device is single function or multi-function
OEM_ReadConfigByte(0, CurSlot, 0, HEADER_TYPE, &cval);
pPciDev->HeaderType = cval;
DEBUGMSG(LEVEL5, (TEXT("Header type = 0x%x\r\n"), (unsigned)cval));
if(cval != 0x00) {
DEBUGMSG(LEVEL5, (TEXT("Multifunction devices not supported yet.\r\n")));
DEBUGMSG(LEVEL5, (TEXT("This device may not work ...\r\n")));
// Also remove this from the list of recognized devices.
// pPciDev->VendorID = 0xffff;
// continue;
}
// Assign the system resources now.
pPciDev->LogInterrupt = 0; // Default value of Logical Interrupt if the device does not
// request for an interrupt line.
// Determine the hardware interrupt line.
OEM_ReadConfigByte(0, CurSlot, 0, INTERRUPT_PIN, &cval);
pPciDev->InterruptPin = cval;
if(cval == 1) {
// All PCI devices share the same PCI interrupt.
// Logical interrupts are unique and depend on the slot which the device occupies.
OEM_WriteConfigByte(0, CurSlot, 0, INTERRUPT_LINE, CurInt);
pPciDev->InterruptLine = CurInt;
// Logical Interrupt Assigned to a device is 0 if the device does not request for
// an interrupt. Else it is pci interrupt of slot 0 + current slot number.
pPciDev->LogInterrupt = SYSINTR_PCI_SLOT0 + CurSlot;
// for Wince 2.0, the Ne2000 driver always registers SYSINTR_NETWORK
// instead of registring for the interrupt which has been assigned
// by the pci driver to it. This problem has been removed in
// Wince 2.1.
// For Wince 2.0, a fix has been made. The network card should
// always be placed in the lower most slot. For that slot, the
// interrupt id returned by PCI is SYSINTR_NETWORK.
// For Wince 2.1 this restriction is not present and you can place
// the ne2000 card in any slot.
#ifndef M1_WINCE210
// For the card in lower slot, always return SYSINTR_NETWORK as
// the logical interrupt. SYSINTR_PCI_SLOT2 is defined as SYSINTR_NETWORK
// for Wince 2.0
if(CurSlot == 2) {
pPciDev->LogInterrupt = SYSINTR_PCI_SLOT2;
}
#endif
DEBUGMSG(LEVEL5, (TEXT("INT PIN = %d. Allocating physical interrupt %d, logical interrupt %d\r\n"), cval, CurInt, pPciDev->LogInterrupt));
}
// Write the LATENCY_TIMER with the default value.
pPciDev->LatencyTimer = DEFAULT_LATENCY;
OEM_WriteConfigByte(0, CurSlot, 0, LATENCY_TIMER, pPciDev->LatencyTimer);
CommandReg = 0;
// Program the Base Address register.
for(i=0x10; i < 0x24; i+=4) {
int RegNum = (i - 0x10) / 4;
OEM_WriteConfigDword(0, CurSlot, 0, i, 0xFFFFFFFF);
OEM_ReadConfigDword(0, CurSlot, 0, i, &uval);
// WRITE_REGISTER_ULONG(ASLONG(PciIoReg+i), 0xffffffff);
pPciDev->BaseAddressRegister[RegNum] = uval;
if(uval == 0)
continue;
DEBUGMSG(LEVEL5, (TEXT("Base address register 0x%x read 0x%x.\r\n"), i, uval));
if((uval & 0x1) == 1) {
// The device needs IO space. Allocate 256 bytes.
DEBUGMSG(LEVEL5, (TEXT("Allocating %d bytes starting at 0x%x to IO Base address reg. 0x%x\r\n"), MAX_IO_ALLOCATE, CurIoBase, i));
OEM_WriteConfigDword(0, CurSlot, 0, i, CurIoBase);
// WRITE_REGISTER_ULONG(ASLONG(PciIoReg+i), CurIoBase);
pPciDev->BaseAddressRegister[RegNum] = CurIoBase;
CurIoBase += MAX_IO_ALLOCATE;
CommandReg |= COMMAND_IO;
}
else {
// It is requesting Memory space.
// Find out the amount of memory asked for. Start with bit 4 and
// find out the first bit which is 1.
int size = 16; // 2 ** 4.
uval >>= 4;
while(uval != 0) {
// DEBUGMSG(LEVEL5, (TEXT("uval = 0x%x, size = %d\r\n"), uval, size));
if ((uval & 0x1) == 1)
break;
uval >>= 1;
size *= 2;
}
if(size > MAX_MEM_REQUEST) {
ERRORMSG(1, (TEXT("PCI: Device asked for too much memory space (%d bytes). Failing to allocate.\r\n"), size));
}
else {
int AllocStart;
CommandReg |= COMMAND_MEM;
// If it's a display driver, allocate it starting from 0.
if((pPciDev->BaseClassCode == PCI_CLASS_DISPLAY_CONTROLLER) && (AllocatedDisplayMemory == FALSE)) {
#ifndef RESERVE_DISPLAY_MEM
ERRORMSG(1, (TEXT("PCI Error: This configuration does not support a display card.\r\n")));
ERRORMSG(1, (TEXT("PCI Error: Define RESERVE_DISPLAY_MEM in the file pci.c if you want to use a display card.\r\n")));
#endif
AllocatedDisplayMemory = TRUE;
AllocStart = DISPLAY_MEM_BASE;
if(size > DISPLAY_MEM_SIZE) {
ERRORMSG(1, (TEXT("PCI Warning: Display Device is requesting for more memory(%d Bytes) than \r\nreserved by the system(%d Bytes)\r\n"), size, DISPLAY_MEM_SIZE, i));
ERRORMSG(1, (TEXT("PCI Warning: Modify the PCI driver to allocate more memory to Display Device.\r\n")));
// still go ahead.
size = DISPLAY_MEM_SIZE;
}
DEBUGMSG(LEVEL5, (TEXT("Allocating %d bytes starting at 0x%x to Display Device Base address \r\nregister 0x%x\r\n"), size, AllocStart, i));
}
else {
// Align CurMemBase to size.
CurMemBase = ALIGN(CurMemBase, size);
AllocStart = CurMemBase;
DEBUGMSG(LEVEL5, (TEXT("Allocating %d bytes starting at 0x%x to Memory Base address register 0x%x\r\n"), size, AllocStart, i));
CurMemBase += size;
}
OEM_WriteConfigDword(0, CurSlot, 0, i, AllocStart);
// WRITE_REGISTER_ULONG(ASLONG(PciIoReg+i), AllocStart);
pPciDev->BaseAddressRegister[RegNum] = AllocStart;
pPciDev->Size[RegNum] = size;
}
}
}
// A display control uses pci io address space but does not request for any io addresses
// thru the base register. So enable io accesses for that device here.
// If there are any other devices which may do the same, put them here.
if((pPciDev->BaseClassCode == PCI_CLASS_DISPLAY_CONTROLLER)) {
CommandReg |= COMMAND_IO;
}
DEBUGMSG(LEVEL5, (TEXT("Setting Command Register to 0x%x, status to 0x%x\r\n"), CommandReg, DEFAULT_STATUS));
// Set the command register now.
OEM_WriteConfigWord(0, CurSlot, 0, COMMAND_REGISTER, CommandReg);
OEM_WriteConfigWord(0, CurSlot, 0, STATUS_REGISTER, DEFAULT_STATUS);
// WRITE_REGISTER_USHORT(ASSHORT(PciIoReg+COMMAND_REGISTER), CommandReg);
// WRITE_REGISTER_USHORT(ASSHORT(PciIoReg+STATUS_REGISTER), DEFAULT_STATUS);
OEM_ReadConfigWord(0, CurSlot, 0, COMMAND_REGISTER, &pPciDev->Command);
OEM_ReadConfigWord(0, CurSlot, 0, STATUS_REGISTER, &pPciDev->Status);
// pPciDev->Command = READ_REGISTER_USHORT(ASSHORT(PciIoReg+COMMAND_REGISTER));
// pPciDev->Status = READ_REGISTER_USHORT(ASSHORT(PciIoReg+STATUS_REGISTER));
// WRITE_REGISTER_ULONG(ASLONG(PciControlReg), SlotDisable);
}
// Disable PCI configuration space before coming out.
// WRITE_REGISTER_ULONG(ASLONG(PciControlReg), SlotDisable);
DEBUGMSG(LEVEL5, (TEXT("(Address of PciDevice Array = 0x%x...)\r\n"), (unsigned)PciDevice));
dummy();
return TRUE;
}
/*****************************************************************************
* Function: PciScan
* Input: Type: type of device you are looking for.
* Instance: instance of the device. eg. the first display controller
* will have Instance = 0.
* Output: PciDeviceType *: Pointer to a structure pointing to the
* DeviceType entry of this device.
* Eg: to get the first instance of the display driver, call this
* function as follows :-
* PciScan(PCI_CLASS_DISPLAY, PCI_FIRST_INSTANCE)
****************************************************************************/
struct PciDeviceType *PciScan(unsigned Type, unsigned Instance)
{
unsigned curInstance = PCI_FIRST_INSTANCE;
unsigned Slot;
unsigned Found = FALSE;
DEBUGMSG(LEVEL1, (TEXT("PCI: PciScan called\r\n")));
// Check whether the Pci bus has been enumerated. If not enumerate it now.
if(!PciEnumerated) {
PciEnumerated = TRUE;
PciEnumerate();
}
// Now look for specified Instance of the specified Type of device.
// eg. : the first Instance of Display controller.
for(Slot = 0; Slot < NO_PCI_SLOTS; Slot ++) {
DEBUGMSG(LEVEL1, (TEXT("PCI: 1PciScan called. DevId = 0x%x\r\n"), PciDevice[Slot].DeviceID));
if(PciDevice[Slot].BaseClassCode == Type) {
if(curInstance == Instance) {
Found = TRUE;
break;
}
else {
curInstance ++;
}
}
}
// Check whether you found it or not.
if(Found) {
DEBUGMSG(LEVEL1, (TEXT("PCI: Found Instance %d of Pci Class 0x%x in Slot %d\r\n"), curInstance, Type, Slot));
return &PciDevice[Slot];
}
else {
DEBUGMSG(LEVEL1, (TEXT("PCI: Unable to locate Instance %d of Pci Class 0x%x in all Slots.\r\n"), Instance, Type));
return (struct PciDeviceType *)NULL;
}
}
#if ((!defined CMON) && (!defined SDBTESTS))
//
// Standard Windows DLL entrypoint.
//
BOOL WINAPI
DllEntry(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
if(pci_called == FALSE) {
pci_called = TRUE;
DEBUGREGISTER(hDLL);
DEBUGMSG(LEVEL1, (TEXT("PCI: DLL_PROCESS_ATTACH\r\n")));
PciEnumerate();
}
else {
DEBUGMSG(LEVEL1, (TEXT("PCI: DLL_PROCESS_ATTACH message received again...\r\n")));
}
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(LEVEL1, (TEXT("PCI: DLL_PROCESS_DETACH\r\n")));
break;
default:
// Just ignore it.
// RETAILMSG(LEVEL1, (TEXT("PCI: called with invalid dwReason=%d\r\n"), dwReason));
break;
}
return TRUE;
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?