直接内存存储 (Direct Memory Access - DMA) 是一种计算机内数据传输的模式,它不需要中央处理器 (CPU) 的干涉。
DMA 的工作方式在不同架构的计算机内是以不同的形式被实现的。因此此篇文章将把讨论限制在对 IBM 个人计算机 (PC) 和 IBM PC/AT 以及其他所有后继者和兼容产品 的 DMA 子系统的实现以及工作方式上。
PC 的 DMA 子系统是建立在 Intel? 8237 控制器上的。这个 8237 控制器包含 了四个 DMA 通道,每个通道都可以被独立的编程控制而且任何一个通道在任何时候都可以是活动的。这些通道被编号为 0, 1, 2 和 3。从 PC/AT 开始,IBM 加入了第二个 8237 芯片,然后把加入的通道命名为 4, 5, 6 和 7。
原来的 DMA 控制器 (0, 1, 2 和 3) 每次传输一个字节。第二个 DMA 控制器 (4, 5, 6 和 7) 每次传输两个连续内存块内的 16 比特数据,而且前 8 个比特一定是来自一个奇数位的地址。这两个控制器完全是相同的。传输的不同是由第二个控制器连接到系统的方式来决定的。
8237 每个通道有两种电信号,叫 DRQ 和 -DACK。还有一些附加的信号如 HRG (Hold Request),HLDA (Hold Acknowledge),-EOP (End of Process),和总线控制信 号 -MEMR (Memory Read),-MEMW (Memory Write),-IOR (I/O Read),和 -IOW (I/O Write)。
8237 DMA 也叫 “fly-by” DMA 控制器。这意味着被传输的数据即 不通过 DMA 芯片,也不存储在 DMA 芯片中。因此,DMA 只能在 I/O 端口和内存地址 间传输数据,而不是在两个 I/O 端口或者两块内存间。
注意: 8237 允许非 “fly-by” 模式,即连接两个通道来完成内存你到内存的数据传输。但在 PC 工业中没人使用这种模式,因为在内存中移动数据使用 CPU 要更快。
在 PC 架构中,当使用一个给定 DMA 通道的硬件对这个通道发出 DRQ 信号以后, 这个 DMA 通道才会被激活。
9.1.1 一个 DMA 传输的例子
这个例子展示了 DMA 传输的触发和执行。在这个例子里,软盘控制器 (FDC) 从软盘读入了一个字节,然后需要 DMA 把这个字节放到内存的 0x00123456 处。整 个过程由 FDC 对 DMA 控制器发出 DRQ2 (对第二个通道发出 DRQ 信号)信号开始。
DMA 控制器会注意到接收到了一个 DRQ2信号。然后控制器会确定第二个 DMA 通道已经被编程而且被标记为 unmasked (开启)。然后控制器也会确定其他的通道是活动的而且有更高的优先权。一旦这些工作完成,DMA 就要求 CPU 把总线放开,以便自己可以使用。DMA 通过总线发出 HRQ 信号直达 CPU。
依靠处理器,CPU 在空闲的时候就可以执行一些附加的指令。但是最终 CPU 在执行从内部处理器缓存或管道读取内容的命令的时候, 还是要等待。
既然 DMA “取得了管理权”,那么 DMA 就会激活 -MEMR,-MEMW, -IOR,-IOW 输出信号,来自 DMA 的地址输出也会被设定为 0x3456。这个输出将用来引导将被传输的字节到确定的内存地址。
DMA 然后让需求 DMA 传输数据的设备知道传输就要开始了。这个开始的信号 就是 -DACK,如果这个设备是软盘控制器, 那么就使用 -DACK2 信号。
软盘控制器会负责把要传输的字节放到总线数据线上。除非软盘控制器需要更多的时间从总线上获取数据(而且,如果外围设备的确需要更多的时间,这个设备会 使用 READY 信号警告 DMA。),DMA 就会等待一个 DMA 时钟周期,然后去除掉 -MEMW 和 -IOR 信号以便内存可以关闭和保存总线上的字节,然后软盘控制器就知道 那个字节已经被传输。
因为 DMA 周期一次只传输一个字节,软盘控制器现在就会丢掉 DRQ2 信号, 因此 DMA 就知道这个不再需要了。DMA 也丢掉 -DACK2 信号,以便软盘控制器知道它必须停止往总线上传输数据。
DMA 会检查任何一个 DMA 通道有没有动静。如果任意通道都没有 DRQ 信号,那 么 DMA 控制器就会第三次发出 -MEMR,-MEMW,-IOR,-IOW 和地址信号。
最后,DMA 会去掉 HRQ 信号。CPU 看见这个信号后,也会去掉 HOLDA 信号。 然后 CPU 激活 -MEMR,-MEMW,-IOR,-IOW 和地址信息,然后再回去执行命令并访 问内存和外围设备。
对于一个典型的软盘区段,上述过程会重复 512 次,每次一个字节。每个字节传输的时候,DMA 中的地址寄存器会增加一,显示还有多少字节要传输的数据计数器则会减一。
当这个计数器变为 0 的时候,DMA 会发出 EOP 信号,意味着 DMA 知道计数 器为 0,没有数据需要传输了,并等待再次被 CPU 召唤执行其他任务。这个事件也 叫作 终端计数 (Terminal Count, or TC)。只有一个 EOP 信号,而且,既然每次只 会有一个 DMA 通道是活动的,那么这个活动的通道就只可能是刚刚完成任务的通道。
当缓存的传输结束以后,如果一个外围设备需要发出中断信号,就可以试验一 下把 -DACKn 信号和 EOP信号一起发出去。如果有这样的情况发生,就意味着 DMA 在没有 CPU 干预的情况下,不会再给那个设备传送任何的数据了。外围设备就可以发出中断信号来取得处理器的注意。在 PC 架构下,DMA 芯片自己是不能发出中断信号的。只有外围设备以及相应的硬件才负责发送中断信号。因此,就有可能有使用 DMA 而不使用中断的外围设备。
应该懂得,尽管 CPU 在 DMA 需要的时候,总是把总线释放给 DMA,这个动作在应用程序和操作系统里面是不可见的,只是当 DMA 是活动的时候,CPU 执行指令的时间会有一点点的差别。因此,处理器会不时的探测外围设备的状态,探测 DMA 芯片中的寄存器,或者,当 DMA 传输结束的时候,从外围设备接收中断信号以确定 情况。
9.1.2 DMA 页面存储器和 16 兆比特地址空间限制
可能你早就注意到,我们先前说过 DMA 会把地址线设置为 0x00123456。实际 上 DMA 只设置为 0x3456。这样做的原因还需要一点点解释。
当初 IBM PC 被设计出来的时候, IBM 选择同时使用 DMA 和中断控制器芯片,后者是专门为 8085 设计的。8085 是一种 8 比特的处理器,地址空间只有16比特 (64K) 。既然 IBM PC 支持超过 64K 的内存,就需要做一些工作来让 DMA 读写 64K 标记 以上的内存。IBM 的解决方案是给每个 DMA 通道加了一个数据门栅,每个门栅的作用就是存储每个地址的上半部分以便读与写。只要某个 DMA 通道有活动迹象,那个通道的数据门栅所保存的内容就会被写到地址总线上,并且一直被保存在那里直到 DMA 操作结束。IBM 把这种门栅叫作 “页面寄存器”。
因此,对于上面的例子,DMA 会把 0x3456 处的地址放到总线上。然后 DMA 通道2 上的页面寄存器会把 0x0012xxxx 放到总线上。最后,这两个部分结合到一起构成一个完整的地址以便被访问。
因为数据寄存器门栅独立于 DMA 的控制芯片,能够被读写的内存就不能跨越 64K 的物理限制。例如,如果 DMA 访问地址 0xffff,在传输结束后 DMA 会增加地址寄存器。然后再去访问 0x0000,而不是 0x10000。这样做的后果可能不是故意的。
注意: 不能把 64K 的 “物理” 限制和 8086 模式下的 64K “Segments” 混淆了。后者的存在纯粹是附加了一个 segment 寄存 器和一个 offset 寄存器。页面寄存器没有地址重叠而且是被 “或” (OR-ed)在 一起的。
更加复杂的是,PC/AT 架构的外部 DMA 地址存储只有八个比特,一起只有 8+16=24 个比特。这就意味着 DMA 只能寻址到 16 兆空间的内存。对于新一些的 有超过 16 兆内存的计算机,标准的 PC 兼容的 DMA 不能访问高于 16 兆的内 存。
要绕过这个限制,操作系统在内存中保留了一个缓冲,这个缓冲的地址小于 16 兆,而且这个缓冲的大小不超过 64 K。然后 DMA 会被编程从外部设备传送数据到这个缓冲,操作系统则把数据从这个缓冲传送到数据的真正目的地。
当把数据从高于 16 兆的地址传送到外设的时候,数据首先被复制到一个 低于 16 兆地址的缓冲,然后 DMA 就可以把这个数据传送到外部的硬件。在 FreeBSD 中,这些保留的缓冲叫作 “Bounce Buffers”。在 MS-DOS? 的世界里,这些缓冲则叫作 “Smart Buffers”。
注意: 一种新的 8237 的实现,叫作 82374,允许 16 bit 的页面寄存器而且可以 访问 32 bit 地址空间。不需要中继缓冲(bounce buffers)。
9.1.3 DMA 操作模式和设定
8237 DMA 可以在不同的模式下操作。主要的有:
- Single
- 一个 byte (或者 word)被传输。DMA 必须释放然后再次获取总线来 完成每一个 byte。通常是那些不能一次传输一整块数据的设备使用的模式。 这种外设在每次传输的时候都会联络 DMA。
标准的 PC 兼容的软盘控制器(NEC 765)只有一个 1 byte 大小的缓冲,因此它需要这种模式。
- Block/Demand
- 一旦 DMA 获取系统总线,一整块数据将被传输,直到 64K 的上限。如果外部设备需要额外的时间,外设可以简单传送一个 READY 信号挂起数据的 传送。READY 不能过多的使用,对于速度慢的外部设备,就应该选择 Single Transfer Mode。
Block 和 Demand 的区别就是:一旦一个数据块 (Block) 的传输开始,就会一直持续到传输记数器到 0 为止。DRQ 只需要在 -DACK 发送以后再发送。 Demand 模式中,DRQ 发送后,此时 DMA 会把数据传输挂起,释放总线给 CPU。 再次发送 DRQ 后,被挂起的传输将继续。
老旧的硬盘控制器使用 Demand 模式,这种情况一直持续到 CPU 发展 到足够快以至于用 CPU 控制传输数据更有效率。特别是如果传输数据用的内 存位置在 16 兆以上。
- Cascade
- 这种机制允许 DMA 通道请求控制总线,但是随后接入的外设将负责把地址控制信息放到总线上,而不是 DMA 自己。这也可以用来实现 “Bus Mastering”。
在 Cascade 模式下,DMA 通道接受总线控制权,但不会把地址和 I/O 控制信号发送到总线,就像 DMA 通常在活动情况下那样。相反,DMA 只会发 送 -DACK 信号给活动的 DMA 通道。
在这个时候是连接到这个活动 DMA 通道的外部设备发出地址和总线控制信息。此外部设备对总线有绝对的控制权,而且对 16 兆比特地址以下的地址有读和或者写的权力。当外设的任务完成,就停止发送 DRQ 信号,然后 DMA 控制器把控制权返回给 CPU 或者其他的 DMA 通道。
Cascade 模式可以用来把多个 DMA 控制器链接在一起,而且这正好就 是 PC 架构中 DMA 通道 4 的用途。当一个外设在 DMA 通道 0,1,2,3 上 请求使用总线,从属 DMA 控制器就发送 HLDREQ,但这个信号是发往 主 DMA 控制 器上而不是 CPU 上的。主 DMA 控制器认为在通道 4 上有工作要做,就用 HLDREQ 信号向 CPU 请求使用总线。一旦 CPU 把总线控制权交给主 DMA 控制器,-DACK 信号就被发送了,然后直接送到从属 DMA 控制器激发 HLDA 信 号。从属 DMA 控制器就把数据发送给需要的 DMA 通道 (0, 1 2 或 3),或者 从属 DMA 控制器可以把总线控制权转让给想要的外设,例如 SCSI 控制器。
由于这种连接操作,在 PC/AT 系统中只有 DMA 通道 0,1,2,3,5, 6 和 7 是可以使用的。
注意: 在早期的 IBM PC 计算机中,DMA 通道 0 专门执行刷新操作。
当外部设备控制系统总线的时候,重要的是外设一定要持续不断的传输数据。如果不能持续不断,外设就必须经常释放总线以便系统能刷新主存。
所有 PC 内存使用的挥发性 RAM 必须被经常性的访问以便让存储在里 面一些数据保持 “charged” 的状态。挥发性内存主要由上百万个电容组成,每个电容里面存贮了一个比特的数据。这些电容充满电表示 1, 而没电的时候表示 0。因为所有的电容都会漏电,就必 须不断的给电容充电让所有的 1 不变。实际上这个工作是 RAM 的芯片来执行的。但是系统的其他部分必须让 RAM 芯片知道何时该做这个工作,以便系统能够正常的访问内存。如果计算机不能刷新内存,内存中的数据将在很短的时间内崩溃。
因为内存读写循环 “算”刷新循环(一个动态 RAM 刷新实际上是一个不完整的内存读操作),只要外部控制器继续读或写数据到连续的内存地址,就会刷新整个内存。
总线控制在一些 SCSI 设备和高性能外部控制器上可以找到。
- Autoinitialize
- 这个模式将导致 DMA 进行 字节,块,或者 需求 传输操作,但是当 DMA 传输计数器为 0 的时候,计数器和地址都会被设置为 DMA 被编程时的初始状态。这就意味着只要外设要求传输数据,就会被授权。
在只有小的硬件 “取样” 缓冲或者没有硬件缓冲的音频 设备上这种方法经常使用。要处理 “循环”缓冲会加重 CPU 的 负担,但是在某些情况下当 DMA 计数器为 0 而且 DMA 停止传输被再次编程 的时候,这是唯一消除延迟的方法。
9.1.4 DMA 编程
被编程的 DMA 通道在装载任何设定之前应该总是被“屏蔽”。因为硬件可能会意想不到的给那个通道发送 DRQ 信号,而且 DMA 会回应,甚至在全部参数还没有被装载或者更新之前。
一旦被屏蔽,主机必须指出数据传输的方向(内存到 I/O 或者 I/O 到内存), DMA 操作使用什么模式(Single, Block, Demand, Cascade 等等),而且最后还要明确地址和数据的长度。数据的长度比你希望 DMA 传输的数据的长度要短。地址和 数据长度的 LSB 和 MSB被写到同一个 8比特的 I/O 端口,因此另一个必须被提前 写入数据以保证 DMA 能接受第一个字节为 LSB 而第二个字节为 MSB。
然后,确认更新页面计数器,这个计数器不在 DMA 里面而且也必须从不同的 I/O 端口去访问。
一旦所有的设定准备好了,DMA 通道就会被打开。DMA 通道已经被确认 “武装”好了,将回应通道上传来的 DRQ 信号。
请参考硬件数据书籍以获得详细的 8237 编程细节。可能你还要参考一些 PC 系统 I/O 端口映射的资料。这些资料描述了 DMA 和页面寄存器的具体位置。以下是一个完整的端口映射表格。
9.1.5 DMA 端口映射
所有基于 IBM-PC 和 PC/AT 的系统的 DMA 都位于相同的 I/O端口。以下是一个完整的列表。在非 AT 的设计中的 DMA 控制器 2 使用的端口是未定义的。
9.1.5.1 0x00-0x1f DMA 控制器 1 (通道 0, 1, 2 和 3)
DMA 地址和计数寄存器
0x00 | 写 | 通道 0 开始地址 |
0x00 | 读 | 通道 0 目前地址 |
0x01 | 写 | 通道 0 初始字数统计 |
0x01 | 读 | 通道 0 剩余字数统计 |
0x02 | 写 | 通道 1 开始地址 |
0x02 | 读 | 通道 1 目前地址 |
0x03 | 写 | 通道 1 初始字数统计 |
0x03 | 读 | 通道 1 剩余字数统计 |
0x04 | 写 | 通道 2 开始地址 |
0x04 | 读 | 通道 2 目前地址 |
0x05 | 写 | 通道 2 初始字数统计 |
0x05 | 读 | 通道 2 剩余字数统计 |
0x06 | 写 | 通道 3 开始地址 |
0x06 | 读 | 通道 3 目前地址 |
0x07 | 写 | 通道 3 初始字数统计 |
0x07 | 读 | 通道 3 剩余字数统计 |
DMA 指令寄存器
0x08 | 写 | 指令寄存器 |
0x08 | 读 | 状态寄存器 |
0x09 | 写 | 需求寄存器 |
0x09 | 读 | - |
0x0a | 写 | 单屏蔽寄存比特位 |
0x0a | 读 | - |
0x0b | 写 | 模式寄存器 |
0x0b | 读 | - |
0x0c | 写 | 清除 LSB/MSB Flip-Flop |
0x0c | 读 | - |
0x0d | 写 | 主 清除/重置 |
0x0d | 读 | 临时寄存器 (在较新的版本中没有) |
0x0e | 写 | 清除屏蔽寄存器 |
0x0e | 读 | - |
0x0f | 写 | 写入所有屏蔽寄存器比特位 |
0x0f | 读 | 读出所有屏蔽寄存器比特位 (只有 Intel 82374 有) |
9.1.5.2 0xc0-0xdf DMA 控制器 2 (通道 4, 5, 6 和 7)
DMA 地址和计数寄存器
0xc0 | 写 | 通道 4 开始地址 |
0xc0 | 读 | 通道 4 目前地址 |
0xc2 | 写 | 通道 4 初始字数统计 |
0xc2 | 读 | 通道 4 剩余字数统计 |
0xc4 | 写 | 通道 5 开始地址 |
0xc4 | 读 | 通道 5 目前地址 |
0xc6 | 写 | 通道 5 初始字数统计 |
0xc6 | 读 | 通道 5 剩余字数统计 |
0xc8 | 写 | 通道 6 开始地址 |
0xc8 | 读 | 通道 6 目前地址 |
0xca | 写 | 通道 6 初始字数统计 |
0xca | 读 | 通道 6 剩余字数统计 |
0xcc | 写 | 通道 7 开始地址 |
0xcc | 读 | 通道 7 目前地址 |
0xce | 写 | 通道 7 初始字数统计 |
0xce | 读 | 通道 7 剩余字数统计 |
DMA 指令寄存器
0xd0 | 写 | 指令寄存器 |
0xd0 | 读 | 状态 |
0xd2 | 写 | 需求寄存器 |
0xd2 | 读 | - |
0xd4 | 写 | 单屏蔽寄存器比特位 |
0xd4 | 读 | - |
0xd6 | 写 | 模式寄存器 |
0xd6 | 读 | - |
0xd8 | 写 | 清除 LSB/MSB Flip-Flop |
0xd8 | 读 | - |
0xda | 写 | 主 清除/重置 |
0xda | 读 | 临时寄存器 (Intel 82374 没有) |
0xdc | 写 | 清楚屏蔽寄存器 |
0xdc | 读 | - |
0xde | 写 | 写所有屏蔽寄存器比特位 |
0xdf | 读 | 读所有屏蔽寄存器比特位 (只有 Intel 82374 有) |
9.1.5.3 0x80-0x9f DMA 页面寄存器
0x87 | 读/写 | 通道 0 低位 (23-16) 页面寄存器 |
0x83 | 读/写 | 通道 1 低位 (23-16) 页面寄存器 |
0x81 | 读/写 | 通道 2 低位 (23-16) 页面寄存器 |
0x82 | 读/写 | 通道 3 低位 (23-16) 页面寄存器 |
0x8b | 读/写 | 通道 5 低位 (23-16) 页面寄存器 |
0x89 | 读/写 | 通道 6 低位 (23-16) 页面寄存器 |
0x8a | 读/写 | 通道 7 低位 (23-16) 页面寄存器 |
0x8f | 读/写 | 低位页面刷新 |
9.1.5.4 0x400-0x4ff 82374 增强 DMA 寄存器
Intel 82374 EISA 系统组件 (ESC) 在 1996 年出现,并在一个单一的包 中包括了 8237 功能的超集和其他兼容 PC 的核心组件。这个芯片致力于 EISA 和 PCI 平台,也提供现代的 DMA 特性,像 scatter-gather,环形缓冲,系统级 DMA 对所有 32 比特地址空间的直接访问。
如果这些特性被使用,就必须附上代码给前 16 年的那些兼容 PC 的电脑提供类似地功能。为了兼容,必须在为每次传输给传统的 8237 寄存器编程之后给 82374 编程。向一个传统的 8237 寄存器写入数据将迫使某些 82374 增强型寄存器内容被清零以便提供向后软件兼容。
0x401 | 读/写 | 通道 0 高位 (bits 23-16) 字数统计 |
0x403 | 读/写 | 通道 1 高位 (bits 23-16) 字数统计 |
0x405 | 读/写 | 通道 2 高位 (bits 23-16) 字数统计 |
0x407 | 读/写 | 通道 3 高位 (bits 23-16) 字数统计 |
0x4c6 | 读/写 | 通道 5 高位 (bits 23-16) 字数统计 |
0x4ca | 读/写 | 通道 6 高位 (bits 23-16) 字数统计 |
0x4ce | 读/写 | 通道 7 高位 (bits 23-16) 字数统计 |
0x487 | 读/写 | 通道 0 高位 (bits 31-24) 页面寄存器 |
0x483 | 读/写 | 通道 1 高位 (bits 31-24) 页面寄存 |
0x481 | 读/写 | 通道 2 高位 (bits 31-24) 页面寄存 |
0x482 | 读/写 | 通道 3 高位 (bits 31-24) 页面寄存 |
0x48b | 读/写 | 通道 5 高位 (bits 31-24) 页面寄存 |
0x489 | 读/写 | 通道 6 高位 (bits 31-24) 页面寄存 |
0x48a | 读/写 | 通道 6 高位 (bits 31-24) 页面寄存 |
0x48f | 读/写 | 高位页面刷新 |
0x4e0 | 读/写 | 通道 0 停止寄存器 (bits 7-2) |
0x4e1 | 读/写 | 通道 0 停止寄存器 (bits 15-8) |
0x4e2 | 读/写 | 通道 0 停止寄存器 (bits 23-16) |
0x4e4 | 读/写 | 通道 1 停止寄存器 (bits 7-2) |
0x4e5 | 读/写 | Channel 1 Stop Register (bits 15-8) |
0x4e6 | 读/写 | 通道 1 停止寄存器 (bits 23-16) |
0x4e8 | 读/写 | 通道 2 停止寄存器 (bits 7-2) |
0x4e9 | 读/写 | 通道 2 停止寄存器 (bits 15-8) |
0x4ea | 读/写 | 通道 2 停止寄存器 (bits 23-16) |
0x4ec | 读/写 | 通道 3 停止寄存器 (bits 7-2) |
0x4ed | 读/写 | 通道 3 停止寄存器 (bits 15-8) |
0x4ee | 读/写 | 通道 3 停止寄存器 (bits 23-16) |
0x4f4 | 读/写 | 通道 5 停止寄存器 (bits 7-2) |
0x4f5 | 读/写 | 通道 5 停止寄存器 (bits 15-8) |
0x4f6 | 读/写 | 通道 5 停止寄存器 (bits 23-16) |
0x4f8 | 读/写 | 通道 6 停止寄存器 (bits 5-2) |
0x4f9 | 读/写 | 通道 6 停止寄存器 (bits 15-8) |
0x4fa | 读/写 | 通道 6 停止寄存器 (bits 23-16) |
0x4fc | 读/写 | 通道 7 停止寄存器 (bits 7-2) |
0x4fd | 读/写 | 通道 7 停止寄存器 (bits 15-8) |
0x4fe | 读/写 | 通道 7 停止寄存器 (bits 23-16) |
0x40a | 写 | 通道 0 至 3 链接模式寄存器 |
0x40a | 读 | 通道中断状态寄存器 |
0x4d4 | 写 | 通道 4 至 7 链接模式寄存器 |
0x4d4 | 读 | 链接模式状态 |
0x40c | 读 | 链式缓冲过期控制寄存器 |
0x410 | 写 | 通道 0 Scatter-Gather 指令控制器 |
0x411 | 写 | 通道 1 Scatter-Gather 指令控制器 |
0x412 | 写 | 通道 2 Scatter-Gather 指令寄存器 |
0x413 | 写 | 通道 3 Scatter-Gather 指令寄存器 |
0x415 | 写 | 通道 5 Scatter-Gather 指令寄存器 |
0x416 | 写 | 通道 6 Scatter-Gather 指令寄存器 |
0x417 | 写 | 通道 7 Scatter-Gather 指令寄存器 |
0x418 | 读 | 通道 0 Scatter-Gather 状态寄存器 |
0x419 | 读 | 通道 1 Scatter-Gather 状态寄存器 |
0x41a | 读 | 通道 2 Scatter-Gather 状态寄存器 |
0x41b | 读 | 通道 3 Scatter-Gather 状态寄存器 |
0x41d | 读 | 通道 5 Scatter-Gather 状态寄存器 |
0x41e | 读 | 通道 5 Scatter-Gather 状态寄存器 |
0x41f | 读 | 通道 7 Scatter-Gather 状态寄存器 |
0x420-0x423 | 读/写 | 通道 0 Scatter-Gather 描述符表指针寄存器 |
0x424-0x427 | 读/写 | 通道 1 Scatter-Gather 描述符表指针寄存器 |
0x428-0x42b | 读/写 | 通道 2 Scatter-Gather 描述符表指针寄存器 |
0x42c-0x42f | 读/写 | 通道 3 Scatter-Gather 描述符表指针寄存器 |
0x434-0x437 | 读/写 | 通道 5 Scatter-Gather 描述符表指针寄存器 |
0x438-0x43b | 读/写 | 通道 6 Scatter-Gather 描述符表指针寄存器 |
0x43c-0x43f | 读/写 | 通道 7 Scatter-Gather 描述符表指针寄存器 |