10.7 DMA

   ISA总线中Direct Memory Access (DMA)是通过DMA控制器(实际上是它们 中的两个,但这只是无关细节)实现的。为了使以前的ISA设备简单便宜, 总线控制和地址产生的逻辑都集中在DMA控制器中。幸运的是,FreeBSD 提供了一套函数,这些函数大多把DMA控制器的繁琐细节对设备驱动程序 隐藏了起来。

   最简单情况是那些比较智能的设备。就象PCI上的总线主设备一样, 它们自己能产生总线周期和内存地址。它们真正从DMA控制器需要的 唯一事情是总线仲裁。所以为了此目的,它们假装是级联从DMA控制器。 当连接驱动程序时,系统DMA控制器需要做的唯一事情就是通过调用 如下函数在一个DMA通道上激活级联模式。

   void isa_dmacascade(int channel_number)

   所有进一步的活动通过对设备编程完成。当卸载驱动程序时,不需要 调用DMA相关的函数。

   对于较简单的设备,事情反而变得复杂。使用的函数包括:

nt flags, caddr_t addr, u_int nbytes, int chan)

准备启动DMA传输。实际启动设备上的传输之前必需调用此函数 来设置DMA控制器。它检查缓冲区是否连续的且在ISA内存范围 之内,如果不是则自动使用反弹缓冲区。如果需要反弹缓冲区, 但反弹缓冲区没有用isa_dmainit() 设置,或对于请求的传输大小来说太小,则系统将panic。 写请求且使用反弹缓冲区的情况下,数据将被自动拷贝到反弹 缓冲区。

  • flags - 位掩码,决定将要完成的操作的类型。方向位B_READ和 B_WRITE互斥。

  • addr - 缓冲区的虚地址

  • nbytes - 缓冲区长度。必须小于等于64KB。不允许长度为0:因为 DMA控制器将会理解为64KB,而内核代码把它理解为0,那样就会导致 不可预测的效果。对于通道号等于和高于4的情况,长度必需为偶数, 因为这些通道每次传输2字节。奇数长度情况下,最后一个字节不被 传输。

  • chan - 通道号

  • void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)

    设备报告传输完成后,同步内存。如果是使用反弹缓冲区的读操作, 则将数据从反弹缓冲区拷贝到原始缓冲区。参量与 isa_dmastart()的相同。允许使用B_RAW标志, 但它一点也不会影响isa_dmadone()

  • int isa_dmastatus(int channel_number)

    返回当前传输中剩余的字节数。在 isa_dmastart()中设置了B_READ的情况下, 返回的数字一定不会等于零。传输结束时它会被自动复位到缓冲区的 长度。正式的用法是在设备发信号指示传输已完成时检查剩余的字节数。 如果字节数不为0,则此次传输可能有问题。

  • int isa_dmastop(int channel_number)

    放弃当前的传输并返回剩余未传输的字节数。

  • 本文档和其它文档可从这里下载:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

    如果对于FreeBSD有问题,请先阅读文档,如不能解决再联系<questions@FreeBSD.org>.
    关于本文档的问题请发信联系 <doc@FreeBSD.org>.