• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > ISA總線的DMA技術

    ISA總線的DMA技術

    作者: 時間:2011-05-20 來源:網絡 收藏
    4 Linux對 通道資源的管理

    本文引用地址:http://www.czjhyjcfj.com/article/150725.htm

      通道是一種系統全局資源。任何外設想要進行傳輸,首先都必須取得某個DMA通道資源的使用權,并在傳輸結束后釋放所使用DMA通道資源。從這個角度看,DMA通道資源是一種共享的獨占型資源。

      Linux在kernel/Dma.c文件中實現了對DMA通道資源的管理。

      4.1 對DMA通道資源的描述

      Linux在kernel/Dma.c文件中定義了數據結構dma_chan來描述DMA通道資源。該結構類型的定義如下:

      struct dma_chan {

      int lock;

      const char *device_id;

      };

      其中,如果成員lock!=0則表示DMA通道正被某個設備所使用;否則該DMA通道就處于free狀態。而成員device_id就指向使用該DMA通道的設備名字字符串。

      基于上述結構類型dma_chan,Linux定義了全局數組dma_chan_busy[],以分別描述8個DMA通道資源各自的使用狀態。如下:

      static struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = {

      { 0, 0 },

      { 0, 0 },

      { 0, 0 },

      { 0, 0 },

      { 1, cascade },

      { 0, 0 },

      { 0, 0 },

      { 0, 0 }

      };

      顯然,在初始狀態時除了DMA通道4外,其余DMA通道皆處于free狀態。

      4.2 DMA通道資源的申請

      任何卡在使用某個DMA通道進行DMA傳輸之前,其設備驅動程序都必須向內核提出DMA通道資源的申請。只有申請獲得成功后才能使用相應的DMA通道。否則就會發生資源沖突。

      函數request_dma()實現DMA通道資源的申請。其源碼如下:

      int request_dma(unsigned int dmanr, const char * device_id)

      {

      if (dmanr >= MAX_DMA_CHANNELS)

      return -EINVAL;

      if (xchg(dma_chan_busy[dmanr].lock, 1) != 0)

      return -EBUSY;

      dma_chan_busy[dmanr].device_id = device_id;

      /* old flag was 0, now contains 1 to indicate busy */

      return 0;

      }

      上述函數的核心實現就是用原子操作xchg()讓成員變量dma_chan_busy[dmanr].lock和值1進行交換操作,xchg()將返回lock成員在交換操作之前的值。因此:如果xchg()返回非0值,這說明dmanr所指定的DMA通道已被其他設備所占用,所以request_dma()函數返回錯誤值-EBUSY表示指定DMA通道正忙;否則,如果xchg()返回0值,說明dmanr所指定的DMA通道正處于free狀態,于是xchg()將其lock成員設置為1,取得資源的使用權。

      4.3 釋放DMA通道資源

      DMA傳輸事務完成后,設備驅動程序一定要記得釋放所占用的DMA通道資源。否則別的外設將一直無法使用該DMA通道。

      函數free_dma()釋放指定的DMA通道資源。如下:

      void free_dma(unsigned int dmanr)

      {

      if (dmanr >= MAX_DMA_CHANNELS) {

      printk(Trying to free DMA%d

      , dmanr);

      return;

      }

      if (xchg(dma_chan_busy[dmanr].lock, 0) == 0) {

      printk(Trying to free free DMA%d

      , dmanr);

      return;

      }

      } /* free_dma */

      顯然,上述函數的核心實現就是用原子操作xchg()將lock成員清零。

      4.4 對/proc/dma文件的實現

      文件/proc/dma將列出當前8個DMA通道的使用狀況。Linux在kernel/Dma.c文件中實現了函數個get_dma_list()函數來至此/proc/dma文件的實現。函數get_dma_list()的實現比較簡單。主要就是遍歷數組dma_chan_busy[],并將那些lock成員為非零值的數組元素輸出到列表中即可。如下:

      int get_dma_list(char *buf)

      {

      int i, len = 0;

      for (i = 0 ; i MAX_DMA_CHANNELS ; i++) {

      if (dma_chan_busy.lock) {

      len += sprintf(buf+len, %2d: %s

      ,

      i,

      dma_chan_busy.device_id);

      }

      }

      return len;

      } /* get_dma_list */

      5 使用DMA的ISA設備驅動程序

      DMA雖然是一種硬件機制,但它離不開軟件(尤其是設備驅動程序)的配合。任何使用DMA進行數據傳輸的ISA設備驅動程序都必須遵循一定的框架。



    關鍵詞: 技術 DMA 總線 ISA

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 水富县| 连山| 黔东| 屏南县| 芜湖市| 波密县| 二连浩特市| 屯门区| 若尔盖县| 大城县| 肥西县| 神农架林区| 东至县| 永宁县| 金寨县| 从江县| 肃北| 铜陵市| 高唐县| 来安县| 伊宁县| 上虞市| 安宁市| 武邑县| 桐城市| 桦甸市| 泸定县| 平塘县| 彩票| 富宁县| 寿阳县| 玉屏| 县级市| 南丹县| 安吉县| 保山市| 封丘县| 海阳市| 宁乡县| 巴彦县| 四子王旗|