閱讀474 返回首頁    go 阿裏雲 go 技術社區[雲棲]


PCI設備內存操作函數總結

1.  ExAllocatePool()

函數說明:

ExAllocatePool allocates pool memory of the specified type and returns a pointer to the allocated

block.

函數定義:

PVOID ExAllocatePool(

                            __in  POOL_TYPE PoolType,

                            __in  SIZE_T NumberOfBytes

);

代碼中用來分配設備描述DMA adepter設備的特性(DEVICE_DESCRIPTION),作為參數傳遞給IoGetDmaAdapter()函數。在調用IoGetDmaAdapter()函數之前就要對PDEVICE_DESCRIPTION結構進行指定各種特性。

         實際中這樣使用:

                   PDEVICE_DESCRIPTION DeviceDescription = (PDEVICE_DESCRIPTION) ExAllocatePool

(PagedPool, sizeof(DEVICE_DESCRIPTION));

 

 

2. RtlZeroMemory()

         函數說明:

The RtlZeroMemory routine fills a block of memory with zeros, given a pointer to the block and the length, in bytes, to be filled.

         函數定義:

                  VOID RtlZeroMemory(

                         __in  VOID UNALIGNED *Destination,

                         __in  SIZE_T Length

);

 

 

3. IoGetDmaAdapter()

         函數說明:

The IoGetDmaAdapter routine returns a pointer to the DMA adapter structure for a physical device object.

函數定義:

struct _DMA_ADAPTER* IoGetDmaAdapter(

  __in_opt  PDEVICE_OBJECT PhysicalDeviceObject,

  __in      struct _DEVICE_DESCRIPTION *DeviceDescription,

  __out     PULONG NumberOfMapRegisters

);

實際代碼中這樣使用:

ULONG  NumberOfMapRegisters=100;

pdx->DmaAdapter=IoGetDmaAdapter(pdx->NextStackDevice,DeviceDescription,&NumberOfMapRegisters);// NextStackDevice在AddDevice函數中已經attach了。

 

 

4. AllocateCommonBuffer()

         函數說明:

The AllocateCommonBuffer routine allocates memory and maps it so that it is simultaneously accessible from both the processor and a device for DMA operations。

函數定義:

PVOID AllocateCommonBuffer(

  __in   PDMA_ADAPTER DmaAdapter,

  __in   ULONG Length,

  __out  PPHYSICAL_ADDRESS LogicalAddress,

  __in   BOOLEAN CacheEnabled

);

注:第一個參數是IoGetDmaAdapter()返回的,第三個參數是自己頂一頂一個物理地址類型,用來接收分配得到的物理地址首址。

返回值:返回值為虛擬地址,供上層使用

 

實際代碼中這樣使用:

pdx->descAddress=pdx->allocateCommonBuffer(pdx->DmaAdapter,(ULONG)DESC_ADDRESS*PORT_NUM,&pdx->DescLogicalAddress,FALSE);

 

附:使用該函數必不可少的會使用下麵的函數

pdx->DmaAdapter=IoGetDmaAdapter(pdx->NextStackDevice,DeviceDescription,&NumberOfMapRegisters);

//創建一個DMA適配器

pdx->allocateCommonBuffer=*pdx->DmaAdapter->DmaOperations->AllocateCommonBuffer; 

//分配連續的物理內存DMA函數

pdx->freeCommonBuffer = *pdx->DmaAdapter->DmaOperations->FreeCommonBuffer;

//釋放連續的物理內存DMA函數

pdx->putDmaAdapter=*pdx->DmaAdapter->DmaOperations->PutDmaAdapter;      

//釋放DMA Adapter對象

 

 

當通過AllocateCommonBuffer()分配得到地址之後需要把這個地址分成兩部分來處理,與硬件打交道的需要用LogicAddress 與 應用程序打交道需用 Virtual Address.

最好將AllocateCommonBuffer()函數取得的這兩個地址保存到設備擴展中特定的變量中(根據內存塊的用處),便於以後操作。可以這樣做:

pdx->RxDescVirBase=(PCHAR)pdx->descAddress;

pdx->RxDescPhyBase=(ULONG)(pdx->DescLogicalAddress.LowPart); //物理地址

 

WRITE_REGISTER_ULONG( (PULONG)&pdx->pHBARegs->RxAddr_des_0,pdx->rx_fc_des

c_buf_phy[0]+16);

WRITE_REGISTER_ULONG( (PULONG)&pdx->pHBARegs->RxAddr_des_addr0_ptr,pdx->r

x_fc_desc_buf_phy[0]+4);

                   注意前麵的 +16 和 +4 實際分別代表美一塊內存的的偏移位置,由於我們定義了這塊內存的結構,並在裏麵布局,+16 其實代表了struct rx_fc_ctl_tab 結構中的 struct rx_fc_desc_entity entity[RX_FC_DESC_NUM] 域,這裏又是一個結構,也就是我們最終會用到的“描述符”。注意:我們這裏的操作是將一個地址寫到一個寄存器,這個地址必須是物理地址,也就是前麵說的LogicAddress。這裏pHBARegs是通過pdx->pHBARegs=(PHBA_REGS)pdx->RegsBase;     獲得的,也就是在CmResourceTypeMemory傳過來時解析,代表硬件提供的DMA寄存器首址。

 

 

 

對於硬件的初始化就是通過WRITE_REGISTER_ULONG()函數來完成,針對設備的起始地址來進行偏移,自己定義結構來匹配各個寄存器的內容,注意這個自己定義的結構一定要嚴格跟硬件寄存器相同,一bit都不能差。

最後更新:2017-04-03 08:26:18

  上一篇:go 字符串作為freemarker模板的簡單實現例子
  下一篇:go GNU 簡述