阅读:1656回复:2
紧急求助,wince x86下pci我在wince x86 下写PCI2040的设备,现在设备可以找到,但按照下面的方法进行地址映射后, 操作pci2040寄存器,读写结果不对,不知是不是和地址映射有关系,下面是相关的源码,麻烦斑竹看下。 struct PCI9054_INFO{ INTERFACE_TYPE InterfaceType; ULONG BusNumber; PVOID pPci9054Address;//驱动可以访问的虚拟地址,对应着pci Memory Base Address0 PVOID pCtrlAddress;//驱动可以访问的虚拟地址,对应着pci Control Space Base Address DWORD MappedAddress;//ISR可以访问的静态虚拟地址 HANDLE hIsrHandler; WCHAR RegIsrDll[200];// ISR Dll name. WCHAR RegIsrHandler[200];//ISR Handle Name. DWORD dwIrq;// IRQ field DWORD dwSysIntr;// @field System Interrupt number for this peripheral };//pPci9054Info; __declspec(dllexport) BOOL FindPci9054(PUCHAR plx9054Address, PUCHAR pIrq) { int bus=0, device, function; int length; BOOL bFoundIt; ULONG inIoSpace = 0; // PUCHAR pPci9054Address; PHYSICAL_ADDRESS ioPhysicalBase; PCI_SLOT_NUMBER slotNumber; PCI_COMMON_CONFIG pciConfig; bFoundIt = FALSE; if(!pPci9054Info)//调试用 pPci9054Info = (struct PCI9054_INFO *)malloc(sizeof(PCI9054_INFO)); // Scan for the PCI9054 for (bus = 0; bus < PCI_MAX_BUS; bus++) { for (device = 0; device < PCI_MAX_DEVICES; device++) { slotNumber.u.bits.DeviceNumber = device; for (function = 0; function < PCI_MAX_FUNCTION; function++) { slotNumber.u.bits.FunctionNumber = function; length = HalGetBusData(PCIConfiguration, bus, slotNumber.u.AsULONG, &pciConfig, sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific)); if (length == 0 || pciConfig.VendorID == 0xFFFF) break; // If the device is a typical PCI device, see if it is the one we're looking for if ((pciConfig.HeaderType == 0)) { RETAILMSG(1, (TEXT("Found a typical PCI device, VendorId: 0x%X, DeviceId: 0x%X\r\n"), pciConfig.VendorID, pciConfig.DeviceID)); RETAILMSG(1, (TEXT("PCI device config: Irq = 0x%X, Port Base = 0x%X\r\n"), pciConfig.u.type0.InterruptLine, pciConfig.u.type0.BaseAddresses[0])); // If vendor and device IDs match, we have found the PCI bridge we're looking for if ((pciConfig.VendorID == PCI9054_VENDOR_ID) && (pciConfig.DeviceID == PCI9054_DEVICE_ID)) { bFoundIt = TRUE; // Display all the base addresses ULONG index; for (index = 0; index < 2; index++) RETAILMSG(1, (TEXT("Base address %d = 0x%x\r\n"), index, pciConfig.u.type0.BaseAddresses[index])); break; } }//if ((pciConfig.HeaderType == 0)) if (function == 0 && !(pciConfig.HeaderType & 0x80)) break; }//for (function = 0; function < PCI_MAX_FUNCTION; function++) if (bFoundIt || length == 0) break; }//for (bus = 0; bus < PCI_MAX_BUS; bus++) if (bFoundIt || (length == 0 && device == 0)) break; } if (!bFoundIt) { RETAILMSG(1, (TEXT("Find9054Hardware: Error, did not find PCI device\r\n"))); return FALSE; } // We have found the bridge, now map the memory of the daughtercard and NET2890 // RETAILMSG(1, (TEXT("Find9054Hardware: pciConfig.u.type0.InterruptLine = 0x%x...\r\n"), // pciConfig.u.type0.InterruptLine)); *pIrq = pciConfig.u.type0.InterruptLine;// // Now map address to the 9054 ioPhysicalBase.HighPart = 0; ioPhysicalBase.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM]; //负责将与总线相关的地址转化为物理地址(即系统地址) inIoSpace = 0;//AddressSpace 0x0 indicates memory, 0x1 is I/O space bus = 0; if (HalTranslateBusAddress(PCIBus, bus, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) { RETAILMSG(1, (TEXT(" After HalTranslateBusAddress:: Pci9054Address0.high = 0x%x,low=0x%x, inIoSpace=%d\r\n"), ioPhysicalBase.HighPart,ioPhysicalBase.LowPart, inIoSpace)); if (!inIoSpace) { //负责将物理地址映射到驱动程序能够访问的虚拟地址空间中 if ((pPci9054Info->pPci9054Address = (PUCHAR)MmMapIoSpace(ioPhysicalBase, PCI9054_REG_SPACE, FALSE)) == NULL) { RETAILMSG(1, (TEXT("FindPci9054Hardware: Error mapping 9054 I/O Ports.\r\n"))); return FALSE; } } else { pPci9054Info->pPci9054Address = (PVOID) ioPhysicalBase.LowPart; } } else { RETAILMSG(1, (TEXT("FindPci9054Hardware: Error translating 9054 I/O Ports.\r\n"))); return FALSE; } RETAILMSG(1, (TEXT(" Pci9054Address0 = 0x%x,\r\n"),pPci9054Info->pPci9054Address)); // Now map address to the 9054 ioPhysicalBase.HighPart = 0; ioPhysicalBase.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM+1]; //负责将与总线相关的地址转化为物理地址(即系统地址) inIoSpace = 0; if (HalTranslateBusAddress(PCIBus, bus, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)) { if (!inIoSpace) { //负责将物理地址映射到驱动程序能够访问的虚拟地址空间中 if ((pPci9054Info->pCtrlAddress = MmMapIoSpace(ioPhysicalBase, PCI9054_REG_SPACE, FALSE)) == NULL) { RETAILMSG(1, (TEXT("FindPci9054Hardware: Error mapping 9054 I/O Ports.\r\n"))); return FALSE; } } else { pPci9054Info->pCtrlAddress = (PVOID) ioPhysicalBase.LowPart; } } else { RETAILMSG(1, (TEXT("FindPci9054Hardware: Error translating 9054 I/O Ports.\r\n"))); return FALSE; } RETAILMSG(1, (TEXT(" Pci9054Address1 = 0x%x,\r\n"),pPci9054Info->pCtrlAddress)); //OEMRequestSysIntr(*pIrq); if(!RequestSysIntr(*pIrq, &pPci9054Info->dwSysIntr)) { RETAILMSG(1, (TEXT("FindPci9054Hardware: Error RequestSysIntr\r\n"))); //return FALSE; } RETAILMSG(1, (TEXT("FindPci9054Hardware: Pci9054Address = 0x%x, IRQ = %d, SysIntr = %d\r\n"), pPci9054Info->pPci9054Address, *pIrq, pPci9054Info->dwSysIntr)); // WCHAR buf1[] = _T("PCIISR.dll"); // WCHAR buf2[] = _T("ISRHandler"); WCHAR buf1[] = _T("giisr.dll"); WCHAR buf2[] = _T("ISRHandler"); wcscpy(&pPci9054Info->RegIsrDll[0], &buf1[0]); wcscpy(&pPci9054Info->RegIsrHandler[0], &buf2[0]); pPci9054Info->dwIrq = *pIrq; LoadISR(pPci9054Info, pciConfig); ConfigPci2040(); // hpi_reset(); return TRUE; } BOOL LoadISR(struct PCI9054_INFO *pPci9054Info, PCI_COMMON_CONFIG pciConfig) { PHYSICAL_ADDRESS PhysicalAddress; unsigned long dwAddressSpace; RETAILMSG(1, (TEXT("LoadISR::%s, %s, %d\r\n"), pPci9054Info->RegIsrDll, pPci9054Info->RegIsrHandler,pPci9054Info->dwIrq)); //负责注册可安装的ISR pPci9054Info->hIsrHandler = LoadIntChainHandler( pPci9054Info->RegIsrDll, pPci9054Info->RegIsrHandler, pPci9054Info->dwIrq); if (pPci9054Info->hIsrHandler == NULL) { RETAILMSG(1, (TEXT("LoadISR:: LoadIntChainHandler(%s, %s, %d) failed\r\n"), pPci9054Info->RegIsrDll, pPci9054Info->RegIsrHandler,pPci9054Info->dwIrq)); RETAILMSG (1,(TEXT("LoadISR::failed, error code = %d\n\r"),GetLastError())); return FALSE; } // // Translate the base address. // dwAddressSpace = 0x1;//0:in I/O space, 1: in memory space pPci9054Info->InterfaceType = PCIBus; PhysicalAddress.HighPart = 0x00; PhysicalAddress.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM]; //负责将物理地址映射到ISR能够访问的静态虚拟地址空间 if (!TransBusAddrToStatic( pPci9054Info->InterfaceType, 0, PhysicalAddress, PCI9054_REG_SPACE, &dwAddressSpace, (PPVOID)&(pPci9054Info->MappedAddress))) { RETAILMSG(1, (TEXT("LoadISR::TransBusAddrToStatic Failed \r\n"))); return FALSE; } RETAILMSG(1, (TEXT("LoadISR:: MappedAddress=0x%x\r\n"), pPci9054Info->MappedAddress)); // Set up ISR handler GIISR_INFO Pci9054IsrInfo; Pci9054IsrInfo.SysIntr = pPci9054Info->dwSysIntr; Pci9054IsrInfo.CheckPort = TRUE; Pci9054IsrInfo.PortIsIO = FALSE; Pci9054IsrInfo.UseMaskReg = FALSE; Pci9054IsrInfo.PortAddr = pPci9054Info->MappedAddress + 0;//+offsetóD′y???y Pci9054IsrInfo.PortSize = sizeof(DWORD); Pci9054IsrInfo.Mask = 0; //This function is called from a driver to communicate with an interrupt handler if (!KernelLibIoControl( pPci9054Info->hIsrHandler, IOCTL_PCIISR_INFO, (LPVOID)(&Pci9054IsrInfo), sizeof(Pci9054IsrInfo), NULL, 0x00, NULL)) { RETAILMSG(1, (TEXT("LoadISR:: Failed KernelLibIoControl\r\n"))); return FALSE; } RETAILMSG(1, (TEXT("LoadISR:: ok\r\n"))); return true; } 下面是程序执行时的一些打印语句: Found a typical PCI device, VendorId: 0x104C, DeviceId: 0xAC60 PCI device config: Irq = 0x5, Port Base = 0xE8008000 Base address 0 = 0xe8008000 Base address 1 = 0xe8000000 After HalTranslateBusAddress:: Pci9054Address0.high = 0x0,low=0xe8008000, inIoSpace=0 Pci9054Address0 = 0x60000, Pci9054Address1 = 0x70000, RequestSysIntr(5) -> 18 FindPci9054Hardware: Pci9054Address = 0x60000, IRQ = 5, SysIntr = 18 LoadISR::giisr.dll, ISRHandler, 5 LoadISR:: MappedAddress=0xe8008000 LoadISR:: ok 说明: Found a typical PCI device, VendorId: 0x104C, DeviceId: 0xAC60 PCI device config: Irq = 0x5, Port Base = 0xE8008000 Base address 0 = 0xe8008000 Base address 1 = 0xe8000000 这几句是说找到了pci2040设备,并得到了他的一些配置信息,中断号,总线地址。 After HalTranslateBusAddress:: Pci9054Address0.high = 0x0,low=0xe8008000, inIoSpace=0 这句话是在HalTranslateBusAddress转换后打印的,是它的物理地址。 Pci9054Address0 = 0x60000, Pci9054Address1 = 0x70000 这两句话是经过MmMapIoSpace映射后打印的,是驱动能够访问的虚拟地址,分别对应着pciConfig.u.type0.BaseAddresses[0] 和pciConfig.u.type0.BaseAddresses[1].这个地址我总感觉不对,我觉得驱动能够访问的地址应该是在0x80000000以上。 LoadISR:: MappedAddress=0xe8008000 这句话是在经过TransBusAddrToStatic映射后打印的,是ISR能够访问的静态虚拟地址 |
|
|
沙发#
发布于:2007-06-07 20:03
找到问题了,映射得到的地址是以字为单位,而寄存器的偏移量却以字节为单位,所以才导致读写寄存器不对。
|
|
|
板凳#
发布于:2007-06-12 20:52
更正程序中的一些错误
dwAddressSpace = 0x0;//1:in I/O space, 0: in memory space pPci9054Info->InterfaceType = PCIBus; PhysicalAddress.HighPart = 0x00; PhysicalAddress.LowPart = pciConfig.u.type0.BaseAddresses[PCI9054_BASE_ADDR_NUM]; //负责将物理地址映射到ISR能够访问的静态虚拟地址空间 busnum = 1;//通过扫描pci设备时得到的总线号 if (!TransBusAddrToStatic( pPci9054Info->InterfaceType, busnum , PhysicalAddress, PCI9054_REG_SPACE, &dwAddressSpace, (PPVOID)&(pPci9054Info->MappedAddress))) { RETAILMSG(1, (TEXT("LoadISR::TransBusAddrToStatic Failed \r\n"))); return FALSE; } RETAILMSG(1, (TEXT("LoadISR:: MappedAddress=0x%x\r\n"), pPci9054Info->MappedAddress)); 这样经过映射后得到的地址是: LoadISR:: MappedAddress=0xc4008000 不知这个地址映射的对不对 |
|
|