天天看點

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都不能差。