dma.cs
上传用户:huajielb
上传日期:2022-07-29
资源大小:626k
文件大小:10k
源码类别:

驱动编程

开发平台:

Visual C++

  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Jungo.wdapi_dotnet;
  4. using wdc_err = Jungo.wdapi_dotnet.WD_ERROR_CODES;
  5. using WDC_DEVICE_HANDLE = System.IntPtr;
  6. using DWORD = System.UInt32;
  7. using UINT32 = System.UInt32;
  8. using BOOL = System.Boolean;
  9. namespace Jungo.plx_lib
  10. {
  11.     public struct DmaDesc 
  12.     {
  13.         public uint u32PADR;
  14.         public uint u32LADR;
  15.         public uint u32SIZ;
  16.         public uint u32DPR;
  17.     };
  18.     public abstract class DmaBuffer
  19.     {  
  20.         internal WDC_DEVICE_HANDLE m_hDev;
  21.         internal IntPtr m_pDma;
  22.         internal DWORD m_dwBuffSize;
  23.         internal UINT32 m_u32LocalAddr; 
  24.         internal WDC_ADDR_MODE m_mode;
  25.         internal bool m_bIsRead;
  26.         internal bool m_bAutoInc; 
  27.         internal DmaBuffer(PLX_MasterDevice dev)
  28.         {
  29.             m_hDev = dev.Handle;
  30.         }
  31.         public WDC_DEVICE_HANDLE DeviceHandle
  32.         {
  33.             get
  34.             {
  35.                 return m_hDev;
  36.             }                        
  37.         }
  38.         public IntPtr pWdDma
  39.         {
  40.             get
  41.             {
  42.                 return m_pDma;
  43.             }
  44.         }
  45.         public BOOL IsRead
  46.         {
  47.             get
  48.             {
  49.                 return m_bIsRead;
  50.             }
  51.         }
  52.         public BOOL IsAutoInc
  53.         {
  54.             get
  55.             {
  56.                 return m_bAutoInc;
  57.             }
  58.         }
  59.         public DWORD BuffSize
  60.         {
  61.             get
  62.             {
  63.                 return m_dwBuffSize;
  64.             }
  65.         }
  66.         internal UINT32 LocalAddress
  67.         {
  68.             get
  69.             {
  70.                 return m_u32LocalAddr;
  71.             }
  72.         }
  73.         public WDC_ADDR_MODE Mode
  74.         {
  75.             get
  76.             {
  77.                 return m_mode;
  78.             }
  79.         }
  80.         public BOOL IsDMAOpen()
  81.         {
  82.             return (m_pDma != IntPtr.Zero);
  83.         }        
  84.         internal WD_DMA MarshalDMA(IntPtr pDma)
  85.         {
  86.             MarshalWdDma m_wdDmaMarshaler = new MarshalWdDma(); 
  87.             return (WD_DMA)m_wdDmaMarshaler.MarshalNativeToManaged(pDma);
  88.         }
  89.         public abstract DWORD Open(uint u32LocalAddr, bool bIsRead, DWORD dwBytes, 
  90.             ref IntPtr pBuffer, bool bAutoIncrement, WDC_ADDR_MODE mode);
  91.         public abstract void Close();
  92.         protected virtual void CommonClose()
  93.         {
  94.             DWORD dwStatus;
  95.             if (m_pDma != IntPtr.Zero)
  96.             {
  97.                 dwStatus = wdc_lib_decl.WDC_DMABufUnlock(m_pDma);
  98.                 if ((DWORD)wdc_err.WD_STATUS_SUCCESS != dwStatus)
  99.                 {
  100.                     Log.ErrLog("DmaBuffer.Close: Failed unlocking DMA buffer. " +
  101.                         "Error 0x" + dwStatus.ToString("X") + ": " +
  102.                         utils.Stat2Str(dwStatus)); 
  103.                 }
  104.                 m_pDma = IntPtr.Zero;
  105.             }
  106.             else
  107.                 Log.ErrLog("DmaBuffer.Close: DMA is not currently open ... ");  
  108.         }  
  109.         public virtual void Dispose()
  110.         {
  111.                 Close();
  112.         }
  113.     }
  114.     public class DmaBufferSG: DmaBuffer
  115.     {
  116.         private IntPtr m_pDmaList;
  117.         public DmaBufferSG(PLX_MasterDevice dev)
  118.             : base(dev){}
  119.         public IntPtr pWdDmaList
  120.         {
  121.             get
  122.             {
  123.                 return m_pDmaList;
  124.             }
  125.         }
  126.                 
  127.         public override DWORD Open(uint u32LocalAddr, bool bIsRead, DWORD dwBytes, 
  128.             ref IntPtr pBuffer, bool bAutoIncrement, WDC_ADDR_MODE mode)
  129.         {
  130.             DWORD dwStatus;
  131.             WD_DMA wdDma = new WD_DMA();
  132.             WD_DMA wdDmaList = new WD_DMA();
  133.             m_u32LocalAddr = u32LocalAddr;
  134.             m_bAutoInc = bAutoIncrement;
  135.             m_mode = mode;
  136.             m_dwBuffSize = dwBytes;
  137.             m_bIsRead = bIsRead;
  138.             DWORD dwOptions = (DWORD)((m_bIsRead)?
  139.                 WD_DMA_OPTIONS.DMA_FROM_DEVICE: 
  140.                 WD_DMA_OPTIONS.DMA_TO_DEVICE);
  141.             if(pBuffer == IntPtr.Zero)
  142.             {
  143.                 Log.ErrLog("DmaBuffer.Open: Scatter/Gather DMA data buffer is null");
  144.                 return (DWORD)wdc_err.WD_INVALID_PARAMETER;
  145.             }  
  146.             
  147.             dwStatus = wdc_lib_decl.WDC_DMASGBufLock(m_hDev, pBuffer, dwOptions,
  148.                 m_dwBuffSize, ref m_pDma);
  149.             if ((DWORD)wdc_err.WD_STATUS_SUCCESS != dwStatus) 
  150.             {
  151.                 Log.ErrLog("DmaBuffer.Open: Failed locking a DMA buffer. " +
  152.                     "Error 0x" + dwStatus.ToString("X") +": " + 
  153.                     utils.Stat2Str(dwStatus));
  154.                 goto Error;
  155.             }
  156.             /* marshaling WD_DMA */
  157.             wdDma = MarshalDMA(m_pDma);
  158.             /* DMA of one page ==> block DMA */
  159.             if (wdDma.dwPages == 1)
  160.                 return (DWORD)wdc_err.WD_STATUS_SUCCESS;
  161.             /* DMA of more then one page ==> chain DMA */
  162.             IntPtr pList = IntPtr.Zero;
  163.             DmaDesc[] list;
  164.             DWORD dwPageNumber;
  165.             uint u32StartOfChain, u32AlignShift, u32MemoryCopied;
  166.             /* Allocate a kernel buffer to hold the chain of DMA descriptors
  167.                includes extra 0x10 bytes for quadword alignment */
  168.             dwStatus = wdc_lib_decl.WDC_DMAContigBufLock(m_hDev, ref pList,
  169.                 (DWORD)WD_DMA_OPTIONS.DMA_TO_DEVICE,
  170.                 wdDma.dwPages * (DWORD)Marshal.SizeOf(typeof(DmaDesc)) + 0x10,
  171.                 ref m_pDmaList);
  172.             if ((DWORD)wdc_err.WD_STATUS_SUCCESS != dwStatus)
  173.             {
  174.                 Log.ErrLog("DmaBuffer.Open: Failed locking DMA list buffer" +
  175.                     " Error 0x" + dwStatus.ToString("X") + ": " + 
  176.                     utils.Stat2Str(dwStatus));
  177.                 goto Error;
  178.             }
  179.             /* marshaling WD_DMA wdDmaList*/
  180.             wdDmaList = (WD_DMA)MarshalDMA(m_pDmaList);
  181.             /* Verification that bits 0-3 are zero (QUADWORD aligned) */
  182.             u32AlignShift = 0x10 - ((uint)wdDma.pUserAddr.ToInt64()
  183.                 & 0xF);
  184.             pList = new IntPtr((uint)pList.ToInt64() + u32AlignShift);
  185.             u32StartOfChain = (uint)wdDmaList.Page[0].pPhysicalAddr +
  186.                 u32AlignShift;
  187.             list = new DmaDesc[wdDma.dwPages];
  188.             /* Setting chain of DMA pages in the memory */
  189.             for (dwPageNumber = 0, u32MemoryCopied = 0;
  190.                 dwPageNumber < wdDma.dwPages; dwPageNumber++)
  191.             {
  192.                 list[dwPageNumber].u32PADR = 
  193.                     (uint)wdDma.Page[dwPageNumber].pPhysicalAddr;
  194.                 list[dwPageNumber].u32LADR = 
  195.                     (u32LocalAddr + (m_bAutoInc ? u32MemoryCopied : 0));
  196.                 list[dwPageNumber].u32SIZ = 
  197.                     (uint)wdDma.Page[dwPageNumber].dwBytes;
  198.                 list[dwPageNumber].u32DPR = 
  199.                     (uint)(u32StartOfChain + 
  200.                         Marshal.SizeOf(typeof(DmaDesc)) * (dwPageNumber
  201.                         + 1)) |(uint)(BITS.BIT0 | (m_bIsRead ? BITS.BIT3 
  202.                         : 0));
  203.                 if(dwPageNumber == wdDma.dwPages-1)
  204.                     /* Mark end of chain */
  205.                     list[dwPageNumber].u32DPR |= (uint)BITS.BIT1; 
  206.                 Marshal.StructureToPtr(list[dwPageNumber], pList, false);
  207.                 pList = new IntPtr(pList.ToInt64() +
  208.                     Marshal.SizeOf(typeof(DmaDesc)));
  209.                 u32MemoryCopied += wdDma.Page[dwPageNumber].dwBytes;
  210.             }
  211.             /* flush the list of DMA descriptors from CPU cache to system
  212.              * memory */
  213.             wdc_lib_decl.WDC_DMASyncCpu(m_pDmaList);
  214.             return (DWORD)wdc_err.WD_STATUS_SUCCESS;
  215. Error:
  216.             Close();
  217.             return dwStatus;
  218.         }
  219.         public override void Close()
  220.         {
  221.             CommonClose();
  222.             if (m_pDmaList != IntPtr.Zero)
  223.             {
  224.                 DWORD dwStatus = wdc_lib_decl.WDC_DMABufUnlock(m_pDmaList);
  225.                 if ((DWORD)wdc_err.WD_STATUS_SUCCESS != dwStatus)
  226.                 {
  227.                     Log.TraceLog("DmaBuffer.Close: Failed unlocking DMA list " +
  228.                         "buffer. Error 0x" + dwStatus.ToString("X") + ": " + 
  229.                         utils.Stat2Str(dwStatus));
  230.                 }
  231.                 m_pDmaList = IntPtr.Zero;
  232.             }
  233.         }
  234.     }
  235.     public class DmaBufferContig: DmaBuffer
  236.     {
  237.         public DmaBufferContig(PLX_MasterDevice dev):base(dev){}
  238.                 
  239.         public override DWORD Open(uint u32LocalAddr, bool bIsRead, DWORD dwBytes, 
  240.             ref IntPtr pBuffer, bool bAutoIncrement, WDC_ADDR_MODE mode)
  241.         {
  242.             DWORD dwStatus;
  243.             WD_DMA wdDma = new WD_DMA();
  244.             WD_DMA wdDmaList = new WD_DMA();
  245.             m_u32LocalAddr = u32LocalAddr;
  246.             m_bAutoInc = bAutoIncrement;
  247.             m_mode = mode;
  248.             m_bIsRead = bIsRead;
  249.             m_dwBuffSize = dwBytes;
  250.             DWORD dwOptions = (DWORD)((m_bIsRead)? 
  251.                 WD_DMA_OPTIONS.DMA_FROM_DEVICE:
  252.                 WD_DMA_OPTIONS.DMA_TO_DEVICE) | 
  253.                 (DWORD)WD_DMA_OPTIONS.DMA_KERNEL_BUFFER_ALLOC;
  254.             /* Allocate and lock a DMA buffer */
  255.             dwStatus = wdc_lib_decl.WDC_DMAContigBufLock(m_hDev, ref pBuffer,
  256.                 dwOptions, dwBytes, ref m_pDma);
  257.             if ((DWORD)wdc_err.WD_STATUS_SUCCESS != dwStatus) 
  258.             {
  259.                 Log.ErrLog("DmaBuffer.Open: Failed locking a DMA buffer. " +
  260.                     "Error 0x" + dwStatus.ToString("X") +": " + 
  261.                     utils.Stat2Str(dwStatus));
  262.                 goto Error;
  263.             }
  264.             /* marshaling WD_DMA */
  265.             wdDma = MarshalDMA(m_pDma);
  266.             /* DMA of one page ==> block DMA */
  267.             if (wdDma.dwPages == 1)
  268.                 return (DWORD)wdc_err.WD_STATUS_SUCCESS;
  269. Error:
  270.             Close();
  271.             return dwStatus;
  272.         }
  273.         public override void Close()
  274.         {
  275.             CommonClose();
  276.         }   
  277.     }
  278. }