数据包接收
在一般情况下,数据包接收包括识别线路上是否存在数据包、执行地址过滤、将数据包存储到接收数据 FIFO 中、将数据传输到主机内存中的接收缓冲区,以及更新接收描述符的状态。
数据包地址过滤
硬件根据以下过滤模式将接收到的数据包存储到主机内存中。如果接收 FIFO 中的空间不足,硬件会丢弃这些数据包,并在相应的统计寄存器中指示丢失的数据包。
支持以下过滤模式:
- 精确单播/多播 —— 目的地址必须与 16 个已存储地址之一完全匹配。这些地址可以是单播或多播地址。
- 混杂单播 —— 接收所有单播数据包。
- 多播 —— 使用接收数据包目的地址的高位索引一个位向量,用于指示是否接收该数据包;如果该位为 1,则接收数据包,否则拒绝。控制器提供一个 4096 位的位向量。软件可以选择以下四种方式之一作为索引位:[47:36]、[46:35]、[45:34] 或 [43:32],这些位来自于目的地址在内部存储的表示形式。
- 混杂多播 —— 接收所有多播数据包。
- VLAN —— 接收所有属于本工作站且在 VLAN 过滤表中设置了相应位的 VLAN 数据包。有关 VLAN 数据包过滤的详细讨论和说明,请参见 第 9.3 节。
通常情况下,只接收良好数据包。良好数据包定义为:没有 CRC 错误、符号错误、序列错误、长度错误、对齐错误,且未检测到载波扩展或接收错误。然而,如果在设备控制寄存器中设置了 store–bad–packet 位(RCTL.SBP),那么通过过滤功能的错误数据包也会被存储到主机内存中。数据包错误通过接收描述符中的错误位(RDESC.ERRORS)指示。通过同时设置混杂模式使能(RCTL.UPE/MPE)和 store–bad–packet 位(RCTL.SBP),可以接收所有数据包,无论其是否存在错误。
不适用于 82541ER。
接收与发送描述
如果启用了可管理性功能,并且启用了 RCMCP,则 ARP 请求数据包可以通过 SMBus 定向传输,或者由 ASF 控制器 在内部处理,而不是传递到主机内存中(不适用于 82544GC/EI 或 82541ER)。
接收数据存储
由描述符指向的内存缓冲区用于存储数据包数据。硬件支持 七种接收缓冲区大小。
缓冲区大小通过接收控制寄存器中的位设置(RCTL.BSIZE 和 RCTL.BSEX)来选择。详细信息请参见 第 13.4.22 节。
以太网控制器对数据包缓冲区地址没有对齐限制。这在接收缓冲区由网络软件栈的更高层分配时尤为重要,因为这些高层通常不了解特定以太网控制器的缓冲区对齐要求。
尽管对齐完全不受限制,但强烈建议软件在可能的情况下,至少按照 缓存行边界 分配接收缓冲区。
接收描述符格式
接收描述符是一种数据结构,包含接收数据缓冲区地址以及供硬件存储数据包信息的字段。表 3-1 列出了该结构,其中阴影区域表示在接收数据包时由硬件修改的字段。
表 3-1 接收描述符(RDESC)布局

注意:此处指示的校验和是数据包的未经调整的“16 位一补码”。在将其传递给上层软件之前,可能需要软件辅助以回退出适当的信息。数据包校验和始终在第一个描述符中报告(即使在多描述符数据包的情况下也是如此)。
在以太网控制器接收到数据包后,硬件会将数据包数据存储到指定的缓冲区中,并写入长度、数据包校验和、状态、错误以及状态字段。长度字段涵盖写入接收缓冲区的数据,包括 CRC 字节(如果存在)。对于跨越多个接收缓冲区的数据包,软件必须读取多个描述符才能确定完整的数据包长度。
对于标准的 802.3 数据包(非 VLAN),默认情况下,数据包校验和从目的地址(DA)的第一个字节开始,一直到 CRC 的最后一个字节结束进行计算,其中包括以太网头和 IP 头。软件可以通过接收控制寄存器修改数据包校验和计算的起始偏移量。该寄存器在 第 13.4.22 节 中进行了描述。为了使用数据包校验和来验证 TCP 校验和,软件必须对数据包校验和值进行调整,以去除不属于真实 TCP 校验和的字节。
接收描述符状态字段
状态信息用于指示描述符是否已被使用,以及所引用的缓冲区是否为该数据包的最后一个缓冲区。状态字段的布局请参见 表 3-2。错误状态信息如 表 3-3 所示。
对于多描述符数据包,数据包状态仅在该数据包的最后一个描述符中提供(即 EOP 位被置位)。如果某个描述符的 EOP 位未置位,则只有 Address、Length 和 DD 位是有效的。
表 3-2:接收状态(RDESC.STATUS)布局

注意:有关接收校验和卸载所支持的数据包类型说明,请参见 表 3-5。不受支持的数据包类型要么 IXSM 位被置位,要么 TCPCS 位未被置位。
接收描述符错误字段
大多数错误信息仅在存储错误数据包位(RCTL.SBP)被置位并且接收到错误数据包时才会出现。可能的错误类型及其位位置定义请参见 表 3-3。
仅当描述符状态字段(RDESC.STATUS)中的 EOP 和 DD 位均被置位时,错误位才是有效的。
表 3-3: 接收错误字段布局

接收描述符特殊字段
硬件会在接收描述符中为 802.1q 数据包存储附加信息。如果数据包类型为 802.1q(当数据包类型字段与 VLAN1 Ethernet Register(VET)匹配且 RCTL.VME = 1b 时确定),则特殊字段记录 VLAN 信息,并且 4 字节 的 VLAN 信息会从数据包数据存储中被剥离。
以太网控制器会将 802.1q 标签中的标签控制信息(TCI)存储在特殊字段中。否则,特殊字段的内容为 0000h。
表 3-4:特殊描述符字段布局

接收描述符获取
描述符获取策略的设计目标是支持 PCI 总线上的大突发传输。这是通过使用 64 个片上接收描述符以及优化的获取算法实现的。该获取算法尝试在每次突发传输中获取一个(或多个)缓存行的描述符,以最大化 PCI 带宽的利用率。下面的段落简要描述了描述符获取算法及其提供的软件控制方式。
当片上缓冲区为空时,只要有任何描述符变为可用(软件写入尾指针),就会立即发生一次获取操作。当片上缓冲区接近为空(RXDCTL.PTHRESH)时,只要主机内存中存在足够数量的有效描述符(RXDCTL.HTHRESH),并且没有其他更高优先级的 PCI 活动正在等待(描述符获取、回写或数据包数据传输),就会执行一次预取操作。
当主机内存中的描述符数量大于片上可用的描述符存储空间时,芯片可能会选择执行一次非缓存行大小倍数的获取操作。如果这样做能够使下一次描述符获取操作在缓存行边界上对齐,硬件就会执行这种非对齐获取机制。该机制在获取操作落后于软件的情况下可以提供最高的效率。
注意:以太网控制器绝不会获取超过描述符 TAIL 指针之外的描述符。
图 3-1:接收描述符获取算法

接收描述符回写
处理器的缓存行大小通常大于接收描述符大小(16 字节)。因此,如果为每个接收到的数据包都回写一次描述符信息,将会导致代价高昂的部分缓存行更新。为尽量减少部分缓存行回写的发生,采用了两种机制:
- 接收描述符打包
- 空描述符填充
以下各节将对这些机制进行说明。
接收描述符打包
为了最大化内存效率,接收描述符在可能的情况下会被“打包”在一起,并以缓存行为单位进行回写。描述符会在以下三种条件之一满足时累积并写回:
- 使用的描述符数量达到
RXDCTL.WTHRESH(即未回写的已用描述符达到指定的最大阈值) - 接收定时器到期(
RADV或RDTR) - 软件显式刷新(
RDTR.FPD)
在第一种情况下,当使用的描述符数量达到 RXDCTL.WTHRESH 时,这些描述符将被回写,不考虑缓存行对齐。因此,建议将 WTHRESH 设置为缓存行大小的整数倍。
在第二种情况下,定时器(RDTR 或 RADV)到期会在触发中断之前,将所有已使用的描述符回写。
对于 82544GC/EI,第二种情况下包含一个定时器(RDTR),用于强制及时回写描述符。定时器初始化后的第一个数据包会启动该定时器。定时器到期时,会刷新所有已累积的描述符,并设置一个中断事件(接收器定时器中断)。通常,在负载条件下,数据包到达速率足够快,因此打包是最常见的情况。
在最后一种情况下,软件可以通过将定时器寄存器的高位写为 1,来显式刷新已累积的描述符。
空描述符填充
硬件不会在数据地址为空的描述符中存储任何数据。软件可以利用这一特性,使接收描述符打包中的第一种条件更早发生。硬件在回写空描述符时,会将状态字节中的 DD 位设置为 1,而其余位保持不变。
接收描述符队列结构
图 3-2:接收描述符环结构

硬件维护一个循环的描述符环,并在推进头指针之前回写已使用的描述符。当处理了“size”个描述符后,头指针和尾指针会回绕到基地址。
软件通过写入尾指针,将最后一个有效描述符之后的条目索引写入,从而添加接收描述符。随着数据包的到达,它们会被存储到内存中,并由硬件递增头指针。当头指针等于尾指针时,描述符环为空。此时,硬件会停止向系统内存存储数据包,直到软件推进尾指针,从而提供更多可用的接收缓冲区。
接收描述符的头指针和尾指针引用的是 16 字节 的内存块。图中阴影框表示已经存储了接收数据包、但尚未被软件识别的描述符。软件可以通过读取内存中的描述符而非 I/O 读取来判断接收缓冲区是否有效。任何状态字节非零的描述符都已被硬件处理,且已准备好由软件进行处理。
注意:头指针指向下一个将被回写的描述符。在描述符回写操作完成后,该指针会按照回写的描述符数量进行递增。硬件拥有 [HEAD, TAIL] 范围内的所有描述符。任何不在该范围内的描述符均由软件拥有。
接收描述符环由以下寄存器描述:
-
接收描述符基地址寄存器(
RDBAL和RDBAH) 这些寄存器指示描述符环缓冲区的起始位置。该 64 位地址按 16 字节边界对齐,并存储在两个连续的 32 位寄存器中。RDBAL包含低 32 位,RDBAH包含高 32 位。硬件会忽略RDBAL中的低 4 位。 -
接收描述符长度寄存器(
RDLEN) 该寄存器决定分配给循环缓冲区的字节数。该值必须是 128 的倍数(最大缓存行大小)。由于每个描述符长度为 16 字节,因此接收描述符的总数始终是 8 的倍数。 -
接收描述符头寄存器(
RDH) 该寄存器保存一个相对于基地址的偏移值,用于指示正在处理中的描述符。循环缓冲区中最多可包含 64K 个描述符。硬件维护一个影子副本,其中包含已完成但尚未存储到内存中的描述符。 -
接收描述符尾寄存器(
RDT) 该寄存器保存一个相对于基地址的偏移值,用于标识硬件可以处理的最后一个描述符之后的位置。需要注意的是,尾指针仍应指向描述符环中的某个位置(介于RDBA与RDBA + RDLEN之间),因为尾指针指向的是软件写入第一个新描述符的位置。
如果软件静态分配缓冲区,并使用内存读取来检查已完成的描述符,那么只需将描述符中的状态字节清零,即可使其重新可供硬件使用。这并非硬件要求(硬件所需的是移动尾指针),但对于执行内存扫描而言是必要的。
接收中断
以太网控制器可以生成四种与接收相关的中断:
- 接收器定时器中断(
ICR.RXT0) - 小接收数据包检测(
ICR.SRPD) - 接收描述符最小阈值(
ICR.RXDMT0) - 接收器 FIFO 溢出(
ICR.RX0)
接收器定时器中断
接收器定时器中断用于指示大多数数据包接收事件(在某些情况下也会使用后文描述的小接收数据包检测中断)。为了尽量减少单位工作量对应的中断次数,以太网控制器提供了两个定时器来控制中断的生成频率。
接收中断延迟定时器 / 数据包定时器(RDTR)
数据包定时器用于在短时间内接收到大量数据包时,减少中断数量。当一个数据包被接收并传输到主机内存后(具体来说,在最后一个数据包数据字节写入内存之后),数据包定时器即被启动。每当有新的数据包被接收并传输到主机内存时,定时器都会被重新初始化(初始化为 RDTR 中定义的值)并重新启动。
当数据包定时器到期时(例如,在 RDTR 定义的时间内没有新的数据包被接收并传输到主机内存),将生成接收器定时器中断。
将数据包定时器设置为 0b 会同时禁用数据包定时器和绝对定时器(见下文),并导致每当有新的数据包被存储到内存中时就生成接收器定时器中断。
在向 RDTR 写入时,如果其高位(FPD)被置位,将强制对已消耗的描述符执行一次显式回写(可能只回写部分缓存行大小的描述符),并使数据包定时器立即到期,从而生成接收器定时器中断。
当由于绝对定时器到期或小接收数据包检测中断而生成接收器定时器中断时,数据包定时器会被重新初始化(但不会启动)。
有关数据包定时器的更多细节,请参见 第 13.4.30 节。
图 3-3:数据包延迟定时器操作(状态图)

接收中断绝对延迟定时器(RADV)
绝对定时器用于确保在接收到第一个数据包之后的预定义时间间隔内,一定会生成一次接收中断。绝对定时器在数据包被接收并传输到主机内存后启动(同样是在最后一个数据包数据字节写入内存之后),但不会在每次接收到新数据包时重新初始化或重新启动。
当绝对定时器到期时(即在 RADV 定义的时间内未生成接收中断),将生成接收器定时器中断。
将 RADV 设置为 0b 或将 RDTR 设置为 0b 都会禁用绝对定时器。若仅希望禁用数据包定时器,应将 RDTR 设置为 RADV + 1b。
当由于数据包定时器到期或小接收数据包检测中断而生成接收器定时器中断时,绝对定时器会被重新初始化(但不会启动)。
下图展示了数据包定时器与绝对定时器如何配合使用。

小接收数据包检测
当启用小数据包检测(RSRPD 被设置为非零值),并且一个大小小于或等于 RSRPD.SIZE 的数据包被传输到主机内存时,将触发小接收数据包检测中断(ICR.SRPD)。
在进行大小比较时,会包含报头和 CRC(如果未启用 CRC 剥离)。如果 CRC 或 VLAN 报头已被剥离,则它们不参与大小计算。当发生小数据包检测中断时,也会同时记录一个接收器定时器中断原因(ICR.RXT0)。
对于 82541xx 和 82547GI/EI,接收小数据包不会清除绝对定时器或数据包延迟定时器,因此一个数据包可能会生成两个中断:一个由于小数据包接收,另一个由于定时器到期。
接收描述符最小阈值
最小描述符阈值用于通过在空闲描述符数量等于 RCTL.RDMTS 中定义的最小数量时生成中断,从而避免描述符下溢。该阈值以接收描述符环大小的分数来度量。
接收器 FIFO 溢出
当硬件尝试向一个已满的 FIFO 写入字节时,就会发生 FIFO 溢出。溢出可能表明软件未及时更新尾指针以提供足够的描述符或缓冲区,或者 PCI 总线速度过慢,无法及时清空接收 FIFO。
导致 FIFO 溢出的入站数据包将被丢弃,并且不会影响后续的数据包接收。
数据包发送
常规数据包(非 TCP 分段数据包)的发送过程包括:
-
协议栈从应用程序接收一块需要发送的数据。
-
协议栈根据介质的 MTU 大小以及所需的数据包报头,计算发送该数据块所需的数据包数量。
-
对于数据块中的每一个数据包:
- 协议栈准备 Ethernet、IP 以及 TCP/UDP 报头。
- 协议栈与软件设备驱动程序交互,并命令驱动程序发送单个数据包。
- 驱动程序获取帧并与硬件进行交互。
- 硬件通过 DMA 传输从主机内存中读取数据包。
- 当硬件完成帧的 DMA 传输后(由中断指示),驱动程序将该数据包的所有权返回给网络操作系统(NOS)。
输出数据包由指针–长度对组成,构成一个描述符链(即所谓的基于描述符的发送)。软件通过组装指针–长度对列表来形成发送数据包,将这些信息存储在发送描述符中,然后更新片上发送尾指针以指向该描述符。发送描述符及其缓冲区存储在主机内存中。
硬件通常在完全获取所有数据包数据并将其存放到片上发送 FIFO 之后才发送数据包。这种方式支持 TCP 或 UDP 校验和计算,并避免 PCI 下溢问题。
发送数据存储
数据存储在由描述符指向的缓冲区中。数据对齐可以位于任意字节边界,单个描述符的最大大小仅受最大允许数据包大小限制(16288 字节)。一个数据包通常由两个或多个描述符组成:一个或多个用于报头,一个用于实际数据。一些软件实现会将报头和数据包数据复制到同一个缓冲区中,并对每个发送的数据包仅使用一个描述符。
发送描述符
以太网控制器提供了三种发送描述符格式。
最初的描述符称为“传统(legacy)”描述符格式。另外两种描述符统称为扩展描述符。其中一种与传统描述符类似,用于指向一块数据包数据,称为 TCP/IP 数据描述符,它作为传统描述符的替代方案,提供了对新型卸载功能的支持。另一种描述符在本质上完全不同,它不指向数据包数据,仅包含控制信息,这些信息会被加载到控制器寄存器中,并影响后续数据包的处理。
以下各节将描述这三种描述符格式。
通过将 TDESC.DEXT 位设置为 1b 来访问扩展描述符类型。如果该位被设置,硬件将检查 TDESC.DTYP 字段,以确定如何解释描述符其余位。表 3-7 给出了所有扩展描述符的通用布局。标记为 NR 的字段未保留用于特定功能,其定义因描述符类型而异。需要注意的是,DEXT 与 DTYP 字段并非连续,以便兼容传统模式操作。对于传统模式操作,位 29 被设置为 0b,描述符定义见 第 3.3.3 节。
表 3-7:发送描述符(TDESC)布局

传统发送描述符格式
要选择传统模式操作,应将位 29(TDESC.DEXT)设置为 0b。此时,描述符格式如 表 3-8 所示。地址和长度必须由软件提供。命令字节中的各个位是可选的,校验和偏移(CSO)和校验和起始(CSS)字段也是可选的。
表 3-8:发送描述符(TDESC)布局 —— 传统模式

表 3-9:发送描述符传统模式说明


注释:
- 尽管 CSO 和 CSS 的单位是字节,但校验和计算通常基于 16 位字。硬件不会强制要求偶数字节对齐。
- 硬件不会将 802.1Q EtherType 或紧随其后的 VLAN 字段纳入校验和计算。因此,对于 VLAN 数据包,软件只需针对封装后的数据包计算回退值,而无需考虑新增字段。
- 虽然以太网控制器可以按上述方式使用传统描述符格式来计算并插入 TCP 校验和,但仍建议软件使用更新的 TCP/IP 上下文发送描述符格式。该新格式允许硬件同时计算 IP 和 TCP 校验和。有关如何使用新描述符格式完成该任务的更多信息,请参见 第 3.3.5 节。
发送描述符命令字段格式
CMD 字节存储适用的命令,其字段如 表 3-10 所示。
表 3-10:发送命令(TDESC.CMD)布局


注释:
- VLE、IFCS 和 IC 位受 EOP 限定,即硬件仅在 EOP 被置位时才解释这些位。
- 硬件仅会为 RS 被置位的描述符设置 DD 位。
- 地址为空(
0b)或长度为零的描述符不会传输任何数据。如果其 RS 位被置位,则在硬件处理这些描述符时,会写回状态字中的 DD 字段。 - 尽管发送中断可能被延迟,但通过设置 RS 位请求的描述符回写操作不会被延迟,除非启用了描述符回写突发机制。
发送描述符状态字段格式
STATUS 字段存储适用的发送描述符状态,其字段如 表 3-11 所示。
仅当命令字段中的 RS 位(或仅针对 82544GC/EI 的 RPS 位)被置位时,发送描述符状态字段才会存在。
表 3-11:发送状态布局


注意:DD 位反映了直到并包括设置了 RS 位(或针对 82544GC/EI 的 RPS 位)的描述符在内的所有描述符状态。
发送描述符特殊字段格式
SPECIAL 字段用于提供 802.1q / 802.1ac 标记信息。
当 CTRL.VME 被设置为 1b 时,所有从以太网控制器发送、且在 TDESC.CMD 中 VLE 位被置位的数据包,都会在发送时向数据包中添加一个 802.1Q 报头。该报头的内容来自发送描述符的 SPECIAL 字段以及 VLAN 类型寄存器。
如果发送描述符命令字段中的 VLE 位为 0b,则 SPECIAL 字段将被忽略。并且,SPECIAL 字段仅对在 TDESC.CMD 中 EOP 位被设置为 1b 的描述符有效。
表 3-12:特殊字段(TDESC.SPECIAL)布局

发送描述符环结构
发送描述符环结构如 图 3-4 所示。一对硬件寄存器维护发送队列。通过将描述符写入循环缓冲区内存区域并移动环的尾指针,可以向环中添加新的描述符。尾指针指向最后一个由硬件拥有的描述符之后的一个条目(但该位置仍位于描述符环内部)。发送过程会持续进行,直到头指针等于尾指针,此时队列为空。
在头指针推进越过这些描述符之前,不应由软件操作已交付给硬件的描述符。
图 3-4:发送描述符环结构

图 3-4 中的阴影框表示已经发送但尚未被软件回收的描述符。回收过程包括释放与这些描述符相关联的缓冲区。
发送描述符环由以下寄存器描述:
-
发送描述符基地址寄存器(
TDBAL和TDBAH) 这些寄存器指示描述符环缓冲区的起始位置。该 64 位地址按 16 字节边界对齐,并存储在两个连续的 32 位寄存器中。TDBAL包含低 32 位,TDBAH包含高 32 位。硬件会忽略TDBAL中的低 4 位。 -
发送描述符长度寄存器(
TDLEN) 该寄存器决定分配给循环缓冲区的字节数。该值必须 128 字节对齐。 -
发送描述符头寄存器(
TDH) 该寄存器保存一个相对于基地址的偏移值,用于指示正在处理中的描述符。循环缓冲区中最多可包含 64K 个描述符。读取该寄存器会返回与已加载到输出 FIFO 中的描述符对应的头指针值。 -
发送描述符尾寄存器(
TDT) 该寄存器保存一个相对于基地址的偏移值,用于指示硬件可以处理的最后一个描述符之后的位置。该位置也是软件写入第一个新描述符的位置。
基地址寄存器指示循环描述符队列的起始位置,而长度寄存器指示描述符环的最大尺寸。长度寄存器的低 7 位被硬件固定为 0b。描述符缓冲区内的字节地址按如下方式计算:
address = base + (ptr * 16)
其中 ptr 为硬件头寄存器或尾寄存器中的值。
头指针和尾指针寄存器的大小支持最多 64K 个描述符;假设每个数据包平均使用 4 个描述符,则发送队列最多可支持约 16K 个数据包。
一旦激活,硬件会获取由硬件头寄存器指示的描述符。硬件尾寄存器指向最后一个有效描述符之后的位置。
软件可以通过在发送描述符命令字段中设置 RS 位(或仅针对 82544GC/EI 的 RPS 位)来判断数据包是否已发送。通过检查内存中发送描述符的 DD 位,可以避免潜在的竞争条件。在递增头寄存器之前,所有描述符数据都会被写入 I/O 总线;但在执行 I/O 写缓冲的系统中,对头寄存器的读取可能会“越过”数据写入。发送描述符的更新使用相同的 I/O 写路径,并且发生在所有数据写入之后,因此不受该竞争条件影响。此外,其他潜在条件也会限制软件读取头指针。
通常,硬件会在发送之前预取数据包数据。硬件一般会在将数据存入发送 FIFO 之后更新头指针的值。
检查已完成数据包的过程包括以下方式之一:
- 扫描内存以查找描述符状态回写。
- 接收中断。当发送队列变为空时,可以生成一个中断条件(
ICR.TXQE)。中断也可以通过其他方式触发。
发送描述符获取
发送描述符的处理策略在本质上与接收描述符相同,只是使用了不同的一组阈值。与接收路径一样,片上发送描述符缓冲区的容量为 64 个描述符。
当片上缓冲区为空时,只要有任何描述符变为可用(软件写入尾指针),就会立即发生一次获取操作。当片上缓冲区接近为空(TXDCTL.PTHRESH)时,只要主机内存中存在足够数量的有效描述符(TXDCTL.HTHRESH),并且没有其他更高优先级的 DMA 活动正在等待(描述符获取、回写或数据包数据传输),就会执行一次预取操作。
描述符预取策略较为激进,以最大化性能。如果描述符位于外部缓存中,系统在改变尾指针之前必须确保缓存一致性。
当主机内存中的描述符数量大于片上可用的描述符存储空间时,芯片可能会选择执行一次非缓存行大小倍数的获取操作。如果这样做能够使下一次描述符获取在缓存行边界上对齐,硬件就会执行这种非对齐获取。该机制在获取进度落后于软件时,能够使描述符获取机制达到最高效率。
发送描述符回写
发送描述符的回写策略与接收描述符类似,但包含一些额外因素。首先,由于发送描述符回写是可选的(由发送描述符中的 RS 位控制),只有设置了其中一个(或两个)相关位的描述符才会开始进入回写描述符的累积过程。其次,为了保持与 82542 的向后兼容性,如果 TXDCTL.WTHRESH 的值为 0b,以太网控制器仅回写描述符中的一个字节(TDESC.STA),而描述符中的其他字节保持不变。
由于延迟并批量回写发送描述符所带来的收益非常有限,通常会将阈值保持在默认值(0b),以强制立即回写发送描述符,并保持向后兼容性。
描述符会在以下三种条件之一满足时被回写:
TXDCTL.WTHRESH = 0b,且一个设置了 RS 位的描述符已准备好回写- 发送中断延迟定时器到期
TXDCTL.WTHRESH > 0b,且已累积TXDCTL.WTHRESH个可回写描述符
在第一种情况下,回写是立即进行的。这是默认操作方式,并且具有向后兼容性。在这种情况下,发送中断延迟功能按 第 3.4.3.1 节 所述方式工作。
后两种条件仅在启用了描述符突发回写时才有效(参见 第 13.4.44 节)。在第二种情况下,使用发送中断延迟定时器(TIDV)来强制及时回写描述符。定时器初始化后的第一个数据包会启动该定时器。定时器到期时,会刷新所有已累积的描述符,并设置一个中断事件(TXDW)。
在最后一种情况下,如果已有 TXDCTL.WTHRESH 个描述符准备好回写,则会执行回写操作。
发送中断
硬件提供了三种发送中断。这些中断由以下条件触发:
-
发送队列为空(TXQE) 所有描述符均已处理,头指针等于尾指针。
-
描述符完成[发送描述符回写(TXDW)] 当硬件回写一个设置了 RS 位的描述符时置位。该中断通常用于如下场景:例如,数据流接口耗尽了描述符,并希望在每次有处理进展时都接收中断通知。
-
发送延迟中断(TXDW) 与 IDE(中断延迟使能)配合使用时,TXDW 指示会根据
TIDV寄存器定义的时间进行延迟。当一个设置了 RS 位和 IDE 位的发送描述符被回写时,发送中断倒计时寄存器会被加载为TIDV寄存器中 IDV 字段的值。当倒计时寄存器到期时,就会触发发送延迟中断。发生发送延迟中断时,TXDW 中断原因位会被置位(与发送描述符回写中断相同)。该中断可以与 TXDW 中断以相同方式被屏蔽。该中断常被执行动态发送链的软件使用,通过一次向发送链中添加一个数据包来工作。
注意:发送延迟中断与发送回写中断使用相同的中断位 TXDW 进行指示。发送延迟中断仅在时间上被延迟,其余行为如上所述。
-
链路状态变化(LSC)——当链路状态发生变化时被置位。使用内部 PHY 时,链路状态变化由 PHY 通过其 LINK 指示的变化来判定并上报。 当使用外部 TBI 设备(仅适用于 82544GC/EI)时,设备可能通过其 LOS(同步丢失)指示来表明链路状态变化。在这种 TBI 模式下,如果启用了硬件自动协商,当接收到 Configuration Base Page 寄存器(
0b),或者当 LRST 或 ANE 位被软件修改时,MAC 也可以检测并上报链路状态变化。 -
发送描述符环低阈值命中(TXD_LOW)(不适用于 82544GC/EI)——当可用发送描述符的总数(通过发送描述符环 Head 与 Tail 指针之差来衡量)达到
TXDCTL.LWTHRESH字段中指定的低阈值时被置位。
延迟发送中断
该机制允许软件在一段时间内不再向发送链中添加描述符之后再触发发送中断,而不是在以太网控制器的头指针追上尾指针时立即触发。当以太网控制器处理数据包的速度略快于软件时(这是千兆操作中很可能出现的情况),就会发生这种情况。
软件驱动通常无法预知何时会被要求发送下一个帧。从性能角度考虑,在一批数据包发送完成后,只生成一次发送中断是最佳选择。
有关具体细节,请参见 第 3.3.3.1 节。