新闻中心

EEPW首页>嵌入式系统>设计应用> ISA总线的DMA技术

ISA总线的DMA技术

作者: 时间:2011-05-20 来源:网络 收藏
4 Linux对通道资源的管理

本文引用地址://m.amcfsurvey.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

评论


相关推荐

技术专区

关闭