DMA操作函数
因为 DMA 控制器是一个系统级的资源,所以内核协助处理这一资源。内核使用 DMA 注册表为 DMA 通道提供了请求/释放机制,并且提供了一组函数在 DMA 控制器中配置通道信息。
DMA 控制器使用函数request_dma和free_dma来获取和释放 DMA 通道的所有权,请求 DMA 通道应在请求了中断线之后,并且在释放中断线之前释放它。每一个使用 DMA 的设备也必须使用中断信号线,否则就无法发出数据传输完成的通知。这两个函数的声明列出如下(在kernel/dma.c中):
int request_dma(unsigned int channel, const char *name);
void free_dma(unsigned int channel);
DMA 控制器被dma_spin_lock 的自旋锁所保护。使用函数claim_dma_lock和release_dma_lock对获得和释放自旋锁。这两个函数的声明列出如下(在kernel/dma.c中):
unsigned long claim_dma_lock(); 获取 DMA 自旋锁,该函数会阻塞本地处理器上的中断,因此,其返回值是"标志"值,在重新打开中断时必须使用该值。
void release_dma_lock(unsigned long flags); 释放 DMA 自旋锁,并且恢复以前的中断状态。
DMA 控制器的控制设置信息由RAM 地址、传输的数据(以字节或字为单位),以及传输的方向三部分组成。下面是i386平台的8237 DMA控制器的操作函数说明(在include/asm-i386/dma.h中),使用这些函数设置DMA控制器时,应该持有自旋锁。但在驱动程序做I/O 操作时,不能持有自旋锁。
void set_dma_mode(unsigned int channel, char mode); 该函数指出通道从设备读(DMA_MODE_WRITE)或写(DMA_MODE_READ)数据方式,当mode设置为DMA_MODE_CASCADE时,表示释放对总线的控制。
void set_dma_addr(unsigned int channel, unsigned int addr);
函数给 DMA 缓冲区的地址赋值。该函数将 addr 的最低 24 位存储到控制器中。参数 addr 是总线地址。
void set_dma_count(unsigned int channel, unsigned int count);该函数对传输的字节数赋值。参数 count 也代表 16 位通道的字节数,在此情况下,这个数字必须是偶数。
除了这些操作函数外,还有些对DMA状态进行控制的工具函数:
void disable_dma(unsigned int channel);
该函数设置禁止使用DMA 通道。这应该在配置 DMA 控制器之前设置。
void enable_dma(unsigned int channel);
在DMA 通道中包含了合法的数据时,该函数激活DMA 控制器。
int get_dma_residue(unsigned int channel);
该函数查询一个 DMA 传输还有多少字节还没传输完。函数返回没传完的字节数。当传输成功时,函数返回值是0。
void clear_dma_ff(unsigned int channel)
该函数清除 DMA 触发器(flip-flop),该触发器用来控制对 16 位寄存器的访问。可以通过两个连续的 8 位操作来访问这些寄存器,触发器被清除时用来选择低字节,触发器被置位时用来选择高字节。在传输 8 位后,触发器会自动反转;在访问DMA 寄存器之前,程序员必须清除触发器(将它设置为某个已知状态)。
|