Welcome to Vista Banter. You are currently viewing our boards as a guest which gives you limited access to view most discussions, articles and access our other FREE features. By joining our free community you will have access to ask questions and reply to others posts, upload your own photos and access many other special features. Registration is fast, simple and absolutely free so please, join our community today! If you have any problems with the registration process or your account login, please contact contact support. |
|
Hardware and Windows Vista Hardware issues in relation to Windows Vista. (microsoft.public.windows.vista.hardware_devices) |
|
LinkBack | Thread Tools | Display Modes |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Hi
I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
"Leon Huang" wrote:
Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif This code is completely wrong, as the documentation makes clear. The setting of Dma32BitAddresses and Dma64BitAddresses have ABSOLUTELY NOTHING to do with the operating system. They are not software-related settings in any way at all. They should never be wrapped in any #ifdefs. You are describing YOUR DEVICE here. If your hardware can handle 64-bit addresses when bus mastering, then you set Dma64BitAddresses to TRUE and Dma32Bitaddresses to FALSE. If not, you set Dma64BitAddresses to FALSE, and Dma32BitAddresses to TRUE. It's just that simple. Your hardware doesn't change based on the operating system, so you will use the same settings on every system. My guess is that your device does NOT support 64-bit addressing, but on an AMD64 system with more that 4G of RAM, you are saying that it does. That's a recipe for disaster. -- Tim Roberts, Providenza & Boekelheide, Inc. |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Hi Tim
Thanks for your reply. My driver works well under Windows XP x64 operating system and 4G RAM hardware platform, moreover, it works well under Windows Vista x64 operating system and less than 4G RAM hardware platform, but can not work under Windows Vista x64 operating system and 4G RAM hardware platform, the hardware platform is the same. In the case of Vista x64 operating system and 4G RAM, the driver succeed to allocate DMA resource, but it can not receive the DMA interrupt.That is make me confused. Regards "Tim Roberts" wrote in message ... "Leon Huang" wrote: Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif This code is completely wrong, as the documentation makes clear. The setting of Dma32BitAddresses and Dma64BitAddresses have ABSOLUTELY NOTHING to do with the operating system. They are not software-related settings in any way at all. They should never be wrapped in any #ifdefs. You are describing YOUR DEVICE here. If your hardware can handle 64-bit addresses when bus mastering, then you set Dma64BitAddresses to TRUE and Dma32Bitaddresses to FALSE. If not, you set Dma64BitAddresses to FALSE, and Dma32BitAddresses to TRUE. It's just that simple. Your hardware doesn't change based on the operating system, so you will use the same settings on every system. My guess is that your device does NOT support 64-bit addressing, but on an AMD64 system with more that 4G of RAM, you are saying that it does. That's a recipe for disaster. -- Tim Roberts, Providenza & Boekelheide, Inc. |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
The first thing that I find odd is that you only support 64 bit addresses if
the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Hi Peter
I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements[i].Address.LowPart)); KdPrint(("ScatterGatherList-Elements[i].Length 0x%X \n", i, ScatterGatherList-Elements[i].Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
There is no such thing as "DMA interrupt".
DMA is one thing, interrupt is another, and the association between them is only logical and not hardwired in any CPU/motherboard chip, nor coded in kernel/HAL. So, look at your interrupt code in the driver and the interrupt logic in the hardware, DMA is OK. -- Maxim Shatskih, Windows DDK MVP StorageCraft Corporation http://www.storagecraft.com "Leon Huang" wrote in message ...[i] Hi Peter I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements[i].Address.LowPart)); KdPrint(("ScatterGatherList-Elements[i].Length 0x%X \n", i, ScatterGatherList-Elements.Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
My concern was that I would think your driver should ALWAYS say that it can
do 64-bit DMA since your hardware can apparently handle it. If you say that you do 32-bit DMA on a 64-bit system then you'll be double buffering. In that case you won't see the right data for the DMA transfer show up in KspDMABuf until after you call PutScatterGatherList at the end of the transfer. Did you wait until after calling PutScatterGatherList (after the completion of the DMA transfer) before checking to see if you had the right data? GetScatterGatherList would return that error if you ask it to map more pages than the number of map registers you got back from GetDmaAdapter. I notice you don't bother to check that number until after the GetScatterGatherList callback ... how many map registers are you getting and how does it compare to the size of your buffer? There should not be that significant of a difference between DMA in Server 2003 (or XP 64 bit) and Vista. -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ...[i] Hi Peter I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements[i].Address.LowPart)); KdPrint(("ScatterGatherList-Elements[i].Length 0x%X \n", i, ScatterGatherList-Elements.Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Hi
my PCI DMA device only support 32bit addressing, so, the Dma64BitAddresses must be FALSE. On Vista x64 + 4G RAM platform, The DMA call GetScatterGatherList, the ScatterGatherList-Elements[].Length is 0x1000(4 KB), all elements length are not more than 4 KB, but on Vista x64 + 3G RAM platform, the ScatterGatherList-Elements[].Length is much large, and the element is only one. Why is that? I don't know how to handle double buffer 32bit DMA on Vista x64 OS. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ...[i] My concern was that I would think your driver should ALWAYS say that it can do 64-bit DMA since your hardware can apparently handle it. If you say that you do 32-bit DMA on a 64-bit system then you'll be double buffering. In that case you won't see the right data for the DMA transfer show up in KspDMABuf until after you call PutScatterGatherList at the end of the transfer. Did you wait until after calling PutScatterGatherList (after the completion of the DMA transfer) before checking to see if you had the right data? GetScatterGatherList would return that error if you ask it to map more pages than the number of map registers you got back from GetDmaAdapter. I notice you don't bother to check that number until after the GetScatterGatherList callback ... how many map registers are you getting and how does it compare to the size of your buffer? There should not be that significant of a difference between DMA in Server 2003 (or XP 64 bit) and Vista. -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ...[i] Hi Peter I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements[i].Address.LowPart)); KdPrint(("ScatterGatherList-Elements.Length 0x%X \n", i, ScatterGatherList-Elements.Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Ah. I assumed way down below that you were setting Dma64BitAddresses
because your device supported them. If your device does not support them then you should not set that flag. You will have to deal with double buffering. You see one large SG entry on the 64-bit OS because the OS is double buffering your request into a single contiguous buffer. The original buffer very likely included one or more physical addresses that were not addressable by your controller. If the double buffering provided by the OS results in requests that are too small you could allocate some common buffer and double buffer the requests yourself. Then you could control how large they were and how many to do at one time. Or update your device. -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ...[i] Hi my PCI DMA device only support 32bit addressing, so, the Dma64BitAddresses must be FALSE. On Vista x64 + 4G RAM platform, The DMA call GetScatterGatherList, the ScatterGatherList-Elements[].Length is 0x1000(4 KB), all elements length are not more than 4 KB, but on Vista x64 + 3G RAM platform, the ScatterGatherList-Elements[].Length is much large, and the element is only one. Why is that? I don't know how to handle double buffer 32bit DMA on Vista x64 OS. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ...[i] My concern was that I would think your driver should ALWAYS say that it can do 64-bit DMA since your hardware can apparently handle it. If you say that you do 32-bit DMA on a 64-bit system then you'll be double buffering. In that case you won't see the right data for the DMA transfer show up in KspDMABuf until after you call PutScatterGatherList at the end of the transfer. Did you wait until after calling PutScatterGatherList (after the completion of the DMA transfer) before checking to see if you had the right data? GetScatterGatherList would return that error if you ask it to map more pages than the number of map registers you got back from GetDmaAdapter. I notice you don't bother to check that number until after the GetScatterGatherList callback ... how many map registers are you getting and how does it compare to the size of your buffer? There should not be that significant of a difference between DMA in Server 2003 (or XP 64 bit) and Vista. -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ...[i] Hi Peter I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements.Address.LowPart)); KdPrint(("ScatterGatherList-Elements.Length 0x%X \n", i, ScatterGatherList-Elements.Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |
|
|||
a DMA PCI Device Driver doesn't work in Vista x64 + more 4GRAM platform!!
Hi Peter
If the driver call AllocateCommonBuffer to allocate a continuous physical memory, the driver use this block physical buffer for receiving the data from DMA device, in this case, the driver work well on Vista x64 + 4G (or more than) platform. However, the driver doesn't work via scatter/gather way. I think this may be resulted from that, the DMA device is 32 bits addressing, the Dma64BitAddresses flag is FALSE, when calling GetScatterGatherList, the system may allocate physical memory beyond 4G space, so, the system may use double buffer for supporting it. if the driver is in Scatter/Gather way, how can make Scatter/Gather work well on Vista x64 + 4G platform. Thanks Regards "Peter Wieland [MSFT]" wrote in message ...[i] Ah. I assumed way down below that you were setting Dma64BitAddresses because your device supported them. If your device does not support them then you should not set that flag. You will have to deal with double buffering. You see one large SG entry on the 64-bit OS because the OS is double buffering your request into a single contiguous buffer. The original buffer very likely included one or more physical addresses that were not addressable by your controller. If the double buffering provided by the OS results in requests that are too small you could allocate some common buffer and double buffer the requests yourself. Then you could control how large they were and how many to do at one time. Or update your device. -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ...[i] Hi my PCI DMA device only support 32bit addressing, so, the Dma64BitAddresses must be FALSE. On Vista x64 + 4G RAM platform, The DMA call GetScatterGatherList, the ScatterGatherList-Elements[].Length is 0x1000(4 KB), all elements length are not more than 4 KB, but on Vista x64 + 3G RAM platform, the ScatterGatherList-Elements[].Length is much large, and the element is only one. Why is that? I don't know how to handle double buffer 32bit DMA on Vista x64 OS. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ...[i] My concern was that I would think your driver should ALWAYS say that it can do 64-bit DMA since your hardware can apparently handle it. If you say that you do 32-bit DMA on a 64-bit system then you'll be double buffering. In that case you won't see the right data for the DMA transfer show up in KspDMABuf until after you call PutScatterGatherList at the end of the transfer. Did you wait until after calling PutScatterGatherList (after the completion of the DMA transfer) before checking to see if you had the right data? GetScatterGatherList would return that error if you ask it to map more pages than the number of map registers you got back from GetDmaAdapter. I notice you don't bother to check that number until after the GetScatterGatherList callback ... how many map registers are you getting and how does it compare to the size of your buffer? There should not be that significant of a difference between DMA in Server 2003 (or XP 64 bit) and Vista. -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi Peter I remove the #ifdef, as the following desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; The driver can receive the DMA interrupt, but the DMA buffer the driver received is not the correct data. The ASIC team analyzed the DMA transfer processing via logic analyzer on Vista x64 and 4G RAM platform, they proved that the DMA chipsets transferred correct package by the physical address and length which the driver wrote into the DMA controller registers. This modified driver(remove the #ifdef) can work well on Vista x64 and less than 4G RAM platform, also work well on Windows XP x64 and 4G platform. It looks as if this problem results from the driver, but I don't know the difference of DMA transfer between Vista x64 and XP x64. The following codes are about initializing DMA transfer. //allocate DMA resource #define TABLE_SIZE 0x8000 StartDevice() { ... ... DEVICE_DESCRIPTION desc; RtlZeroMemory(&desc, sizeof(DEVICE_DESCRIPTION)); desc.Version = DEVICE_DESCRIPTION_VERSION; desc.DmaChannel = ((ULONG) ~0); desc.InterfaceType = PCIBus; desc.DmaWidth = Width32Bits; desc.DmaSpeed = Compatible; desc.ScatterGather = TRUE; desc.Master = TRUE; desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; if (m_pDMAObject == NULL) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! For (index = 0; index DMA_INT_CNT; index++) { m_DMAPara[index].KsDMA_Table_VA = (PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(m_DMAPara[index].KsDMA_Table_VA == NULL) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } .. .. } NTSTATUS KS_InitDMA () { m_DMAPara[index].KspDMABuf = (PBYTE)ExAllocatePoolWithTag( NonPagedPool, m_DMAPara[index].KsdwDMABufSize, 'MpaM'); if(m_DMAPara[index].KspDMABuf == NULL) { KdPrint(("@@@KS_InitDMA%d List:Allocate DMA buffer memory Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES;; } //Allocate an MDL m_DMAPara[index].KspMDL = IoAllocateMdl( m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, FALSE, FALSE, NULL); if(m_DMAPara[index].KspMDL == NULL) { ExFreePool(m_DMAPara[index].KspDMABuf); m_DMAPara[index].KspDMABuf=NULL; KdPrint(("@@@KS_InitDMA%d List:Allocate MDL Fail!\n",index)); return STATUS_INSUFFICIENT_RESOURCES; } //Build the MDL to describe the memory pages MmBuildMdlForNonPagedPool(m_DMAPara[index].KspMDL); //scathergather list return KS_DmaProgramTransfer(index); } NTSTATUS KS_DmaProgramTransfer(int index) { NTSTATUS ntStatus=STATUS_SUCCESS; KIRQL oldIrql; KdPrint(("KS_DmaProgramTransfer: DMA%d!\n",index)); //KeFlushIoBuffers(m_DMAPara[index].KspMDL, TRUE, TRUE); //Get ScatterGather resource! m_KsDmaCallContext.pKSDevice=m_pKSDevice; m_KsDmaCallContext.index=index; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); ntStatus=m_pDMAObject-DmaOperations-GetScatterGatherList( m_pDMAObject, m_pKSDevice-FunctionalDeviceObject, m_DMAPara[index].KspMDL, m_DMAPara[index].KspDMABuf, m_DMAPara[index].KsdwDMABufSize, KS_DmaCallBack, &m_KsDmaCallContext, FALSE ); KdPrint(("GetScatterGatherList Status = 0x%X \n", ntStatus)); //ntStatus = STATUS_INSUFFICIENT_RESOURCES; KeLowerIrql(oldIrql); //////////////////////////////////////////// return ntStatus; } KS_DmaCallBack() { m_DMAPara[index].ScatterGatherList=ScatterGatherList; ULONG TotalPages=ScatterGatherList-NumberOfElements; if(TotalPagesm_MaxMapRegisters) { TotalPages=m_MaxMapRegisters; KdPrint(("@@@Error: The DMA buffer PageCnt is too largem_MaxMapRegisters!\n")); } KdPrint(("TotalPages=%d\n",TotalPages)); for(unsigned long i=0;iTotalPages;++i) { m_DMAPara[index].KsDMA_Table_VA[2*i]= ScatterGatherList-Elements[i].Address.LowPart; m_DMAPara[index].KsDMA_Table_VA[2*i+1]= (ScatterGatherList-Elements[i].Length 2); KdPrint(("ScatterGatherList-Elements[%d].Address 0x%X \n", i, ScatterGatherList-Elements.Address.LowPart)); KdPrint(("ScatterGatherList-Elements.Length 0x%X \n", i, ScatterGatherList-Elements.Length)); } m_DMAPara[index].KsTotalEntry=TotalPages; m_DMAPara[index].KsdwCurDMAUsed=0; } calling GetScatterGatherList failed, return STATUS_INSUFFICIENT_RESOURCES. Thanks Regards Leon "Peter Wieland [MSFT]" wrote in message ... The first thing that I find odd is that you only support 64 bit addresses if the system supports them. Why is that? Does your card change to only supporting 32-bit addressing if it's running on an X86 machine? Do you not support an x86 machine with 4GB of memory? What error are you seeing and where are you seeing it come from? -p -- This posting is provided "AS IS" with no warranties, and confers no rights. "Leon Huang" wrote in message ... Hi I writed a BDA driver for a PCI TV card device,I found that my driver can work well on Vista32/XP32/XPx64 + 4GRAM platform, and work well on Vista x64 + less than 4G RAM, but can't work on Vista x64 + 4G RAM, this problem make me confused. I guess that this problem maybe result from the DMA addressing in Vista x64, or MS change the DMA addressing in Vista x64 after XP x64,so,the DMA configuration of my driver doesn't compatible with Vista x64. the following codes is config DMA. #if defined(_AMD64_)||defined(_IA64_) if (Mm64BitPhysicalAddress) //if system support 64-bit physical addressing { desc.Dma64BitAddresses = TRUE; desc.Dma32BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is TRUE \n")); } else { desc.Dma32BitAddresses = TRUE; desc.Dma64BitAddresses = FALSE; KdPrint(("Mm64BitPhysicalAddress is FALSE \n")); } #else desc.Dma64BitAddresses = FALSE; desc.Dma32BitAddresses = TRUE; #endif desc.AutoInitialize = FALSE; desc.MaximumLength = (ULONG) -1; m_MaxMapRegisters = (desc.MaximumLength / PAGE_SIZE) + 1; m_pDMAObject = IoGetDmaAdapter( pKSDevice-PhysicalDeviceObject, &desc, &m_MaxMapRegisters); m_MaxMapRegisters=(TABLE_SIZE)/8; KdPrint(("DMA MaxMap Cnt=%d\n",m_MaxMapRegisters)); if(!m_pDMAObject) { KdPrint(("@@@Couldn't GetDMA adapter resource!\n")); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } ////Allocate DMA Table memory! for(index=0;indexDMA_INT_CNT;index++) { m_DMAPara[index].KsDMA_Table_VA=(PULONG)(m_pDMAObject-DmaOperations)- AllocateCommonBuffer(m_pDMAObject, TABLE_SIZE, &m_DMAPara[index].KsDMA_Table_PA, FALSE); if(!m_DMAPara[index].KsDMA_Table_VA) { KdPrint(("@@@Allocate DMA%d Table Fail!\n",index)); CleanUpResources(); return STATUS_INSUFFICIENT_RESOURCES; } m_DMAPara[index].KsdwDMATableSize=TABLE_SIZE; } can you give me a idea? thanks best regards Leon Huang |