Home   |   Jungo Corporate Web Site   |   Connectivity Software Store   |   Contact us   |   Search:
Home Connectivity Software Support WinDriver Support Technical Documents

Technical Document #41



Doc ID: 41
Product: WinDriver
Version:  --

How do I share a memory buffer between Kernel PlugIn and user mode projects for DMA or other purposes?

Sharing a memory buffer between Kernel PlugIn and user mode is done using a common buffer, allocated in the kernel mode and mapped to the user mode. 

Call WD_DMALock() from the user mode to allocate a buffer in the kernel. To allocate a contiguous kernel buffer, set the DMA_KERNEL_BUFFER_ALLOC flag in the dwOptions field of the WD_DMA structure. WD_DMALock() returns a mapping of the physical address of the allocated buffer to both the kernel and user-mode address space. 

Note: Beginning with version 6.00 of WinDriver, for Contiguous Buffer DMA allocation WD_DMALock() also returns the kernel mapping of the allocated buffer - within dma.pKernelAddr. In previous versions of WinDriver, the kernel address was not obtainable via WD_DMALock() and there was need in an additional step, calling  WD_CardRegister()


You can access the allocated memory from your user mode application using the returned user mode mapped address (dma.pUserAddr) as if it was the result of a malloc() call. 

To access the shared memory buffer from the Kernel PlugIn application, you need to pass the kernel mapping of the allocated buffer to the Kernel PlugIn. This address is returned by WD_DMALock() in dma.pKernelAddr

[Do not try to access the kernel mapped address directly in the user mode. Since this is a kernel mode address, you will generate a protection violation exception if you try to access it from the user mode. For direct user mode access, use the user mode mapping - dma.pUserAddr].

Now you should pass the kernel virtual address to the Kernel PlugIn.
In order to do this, create a WD_KERNEL_PLUGIN_CALL structure and set the pData field to hold the virtual kernel address - dma.pKernelAddr.

You can then pass this structure to the Kernel PlugIn in one of the following ways:

  1. A call to WD_KernelPlugInCall(). In this case you will be able to access the kernel virtual address address from within the KP_Call() call-back function in the Kernel PlugIn.
  2. A call to WD_IntEnable() \ InterruptEnable() (or InterruptThreadEnable() - in version 5.22 and below). In this case, in the user mode you will store the WD_KERNEL_PLUGIN_CALL structure in the kpCall field of the WD_INTERRUPT structure that is passed to the function. You will then be able to access the kernel virtual address from within the KP_IntEnable() call-back function in the Kernel PlugIn.
After retrieving the kernel virtual buffer address in the Kernel PlugIn, store it in the Kernel PlugIn module (in a global variable or an allocated memory location). Now, you can access the same memory buffer in both kernel mode and user mode.

Note: The access to the common buffer is not synchronized by WinDriver. You may add access synchronization.

 
  *********************************************************************

  // sample user mode code:

  HANDLE hWD;
  WD_DMA dma;
  WD_KERNEL_PLUGIN kerPlug;
  WD_KERNEL_PLUGIN_CALL kpCall;
  WD_CARD_REGISTER cardReg;  // For version 5.22 or below
  
  hWD = WD_Open();

  BZERO(dma);
  dma.pUserAddr = NULL;
  dma.dwBytes = 0x10000;  // allocate 16K
  dma.dwOptions = DMA_KERNEL_BUFFER_ALLOC; // kernel contiguous buffer
  WD_DMALock(hWD, &dma);
  if (!dma.hDma)
  {
     printf("failed allocating dma buffer\n");
     // exit
  }
  
  // At this point, dma.pUserAddr holds the 
  // user mode mapping of the allocated memory, 
  // dma.pKernelAddr holds the kernel mapping of  
  // the memory.
  ////////////////////////////////////////////////////////////////

 
  // pass the kernel address to the Kernel PlugIn:

  BZERO (kerPlug);
  kerPlug.pcDriverName = KP_DRIVER_NAME;
  WD_KernelPlugInOpen(hWD, &kerPlug);
  if (!kerPlug.hKernelPlugIn)
  {
      printf("failed opening a handle to the Kernel PlugIn\n");
      // exit
  }

  BZERO (kpCall);
  kpCall.hKernelPlugIn = kerPlug.hKernelPlugIn;
  kpCall.dwMessage = YOUR_MESSAGE;
  kpCall.pData = dma.pKernelAddr;  
  WD_KernelPlugInCall(hWD, &kpCall);
  
  *********************************************************************
 
For a detailed description of the relevant WinDriver APIs, used above, please refer to the Function Reference section in the WinDriver User's Manual.
For further clarifications regarding DMA allocation with WinDriver, refer to the relevant section in the manual, under the "Advanced Issues".

Back to Top

WinDriver, Kernel PlugIn, PCI, PCMCIA, ISA, DMA, contiguous buffer DMA, memory, WD_DMALock, pKernelAddr, pUserAddr, data sharing, DMA_KERNEL_BUFFER_ALLOC, dwTrans, WD_CardRegister, WD_KernelPlugInOpen, WD_KernelPlugInCall