ISA总线中Direct Memory Access (DMA)是通过DMA控制器(实际上是它们 中的两个,但这只是无关细节)实现的。为了使以前的ISA设备简单便宜, 总线控制和地址产生的逻辑都集中在DMA控制器中。幸运的是,FreeBSD 提供了一套函数,这些函数大多把DMA控制器的繁琐细节对设备驱动程序 隐藏了起来。
最简单情况是那些比较智能的设备。就象PCI上的总线主设备一样, 它们自己能产生总线周期和内存地址。它们真正从DMA控制器需要的 唯一事情是总线仲裁。所以为了此目的,它们假装是级联从DMA控制器。 当连接驱动程序时,系统DMA控制器需要做的唯一事情就是通过调用 如下函数在一个DMA通道上激活级联模式。
void isa_dmacascade(int channel_number)
所有进一步的活动通过对设备编程完成。当卸载驱动程序时,不需要 调用DMA相关的函数。
对于较简单的设备,事情反而变得复杂。使用的函数包括:
int isa_dma_acquire(int chanel_number)
保留一个DMA通道。成功则返回0,如果通道已经被保留或被其它 驱动程序保留则返回EBUSY。大多数的ISA设备都不能共享DMA通道, 因此这个函数通常在连接设备时调用。总线资源的现代接口使得 这种保留成为多余,但目前仍必须使用。如果不使用,则后面其它 DMA例程将会panic。
int isa_dma_release(int chanel_number)
释放先前保留的DMA通道。释放通道时必须不能有正在进行中的 传输(另外,释放通道后设备必须不能再试图发起传输)。
void isa_dmainit(int chan, u_int bouncebufsize)
分配由特定通道使用的反弹缓冲区。请求的缓冲区大小不能超过
64KB。以后,如果传输缓冲区碰巧不是物理连续的,或超出ISA
总线可访问的内存范围,或跨越64KB的边界,则会自动使用反弹
缓冲区。如果传输总是使用符合上述条件的缓冲区(例如,由 bus_dmamem_alloc()
分配的那些),则 不需要调用isa_dmainit()
。但使用此函数
会让通过DMA控制器传输任意数据变得非常方便。
chan - 通道号
bouncebufsize - 以字节计数的反弹 缓冲区的大小