我用的是Xilinx的ML505这块开发板,Xilinx提供的硬件代码、驱动和应用软件PCI_express_DMA_Freeware_Virtex。
这个驱动要分配一段连续的内存来读写。下面两个函数是在EvtDeviceAdd调用。 EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager
DevExt->BufferLogicalAddress = MmAllocateContiguousMemory(DevExt->BufferSize, physicalAddress);
physicalAddress = MmGetPhysicalAddress((PVOID)DevExt->BufferLogicalAddress);
下面的函数是在PCIEIOCtrlCode调用。
case IOCTL_GET_BUFFERADDRESS:
{
phyAddress.HighPart = 0;
phyAddress.LowPart = (ULONG)devExt->BufferPhysicalAddress;
devExt->BufferSystemVirtualAddress = MmMapIoSpace(phyAddress, PCIE_BUFFER_SIZE, MmNonCached);
devExt->BufferMdl = IoAllocateMdl(devExt->BufferSystemVirtualAddress, PCIE_BUFFER_SIZE, FALSE, FALSE, NULL);
MmBuildMdlForNonPagedPool(devExt->BufferMdl);
devExt->BufferUserVirtualAddress = (PVOID)(((ULONG)PAGE_ALIGN(MmMapLockedPages(devExt->BufferMdl, UserMode))) + MmGetMdlByteOffset(devExt->BufferMdl));
}
这个驱动在windows xp下可以正常使用,但是在windows server 2003下就会出现蓝屏,错误的地方是这样一个函数:
MmMapLockedPages(devExt->Buffer2Mdl, UserMode),我用windbg调试,显示:MmUnmapLockedPages called when not at APC_LEVEL or below.
我把usermode改为kernelmode就可以,我还用MmMapLockedPagesSpecifyCache(devExt->BufferMdl, UserMode,MmNonCached,NULL,FALSE,NormalPagePriority)
来代替,也是usermode的问题,为什么一样的函数在xp下可以用,在server下就不能用呢?
但是改为kernelmode后函数返回的地址是内核地址,用户态不能用,所以不知道该怎么办啊。
我还用了另外一种方法:
physicalAddress.LowPart = 0x80000000;
physicalAddress.HighPart = 0x0;
SkipBytes.LowPart=0x00001000;
SkipBytes.LowPart=0x0;
DevExt->BufferMdl = MmAllocatePagesForMdl(LowAddress,
physicalAddress,
SkipBytes,
DevExt->BufferSize);
if(!DevExt->BufferMdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
DevExt->BufferPhysicalAddress = MmGetSystemAddressForMdlSafe(
DevExt->BufferMdl,
NormalPagePriority);
DevExt->BufferUserVirtualAddress= MmMapLockedPagesSpecifyCache(DevExt->BufferMdl,
UserMode,
MmNonCached,
NULL,
FALSE,
NormalPagePriority);
还是在MmMapLockedPagesSpecifyCache这个函数处出现蓝屏。
后来在OSR上查了,MmAllocateContiguousMemory+MmMapLockedPages不是一个很好的方法,在不同的平台上可能会有问题,算了,结贴~~~~