ISA总线的DMA技术
DMA通道是一种系统全局资源。任何ISA外设想要进行DMA传输,首先都必须取得某个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通道资源的申请
任何ISA卡在使用某个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设备驱动程序都必须遵循一定的框架。
评论