古猫先生 SATA系列博文转载
SATA专题文章列表
SATA系列专题之一:浅析Physical Layer物理层OOB信号
SATA系列专题之二:2.0 Link layer链路层概述
SATA系列专题之二: 2.1 Link layer链路层8b/10b编码解析
SATA系列专题之二: 2.2 Link layer链路层加扰/解扰/CRC解析
SATA系列专题之二: 2.3 Link layer链路层 Frame结构以及Primitive基元解析
SATA系列专题之三:3.0 Transport Layer传输层概述
SATA系列专题之三:3.1 Transport Layer传输层FIS结构解析
SATA系列专题之三:3.2 Transport Layer传输层FIS Retry机制解析
SATA系列专题之三:3.3 Transport Layer传输层Flow Control机制解析
SATA系列专题之三:3.4 Transport Layer传输层Error处理机制解析
SATA系列专题之四:4.0 Command Layer命令层概述
SATA系列专题之四:4.1 Command Layer命令分类详细解析
SATA系列专题之五:Link Power Management解析
SATA系列专题之六:浅析NCQ原生指令序列
----------------------------------------------------------
SATA系列专题之一:浅析Physical Layer物理层OOB信号
一、SATA物理层概述
说OOB之前,首先得了解一下SATA结构以及物理层的含义。
SATA主要包括:应用层(Application Layer), 传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer), SATA结构如下图:

这四个主要部分的作用是什么呢?
Application Layer/Command Layer(可解读为同一层) :
1. 最高层级的Layer,进行ATA或ATAPI command的执行,
2. implementation上很多是用软件处理.
Transport Layer :
1. 将Application Layer要做的Command转化成FIS的handshake,
2. 对FIS的组成和解开.
Link Layer :
1. 将要打出去的data做编码, 将收进来的data做解码,
2. 维持Link Layer的handshake机制.
Physical Layer :
1. Tx和Rx串行流(serial stream),
2. 上电时序,
3. 支持SATA电源管理选项,
4. OOB(Out-of-Band)信号的产生与检测.
从上面的介绍中,我们看到物理层中有一个关键的功能就是OOB(Out-of-Band)信号的产生与检测, 这就是我们今天的主角~
二、OOB(Out of Band)信号解析
SATA信号链结的建立主要是靠OOB(Out Of Band)的检测实现的,并且向上层Link Layer提供了物理层的链结情况。
OOB主要的作用包括以下几点:
- 初始化(initialization),
- 传输速率的协商与对接(Speed negotiation),
---透过OOB handshake,host与device可以决定要在Gen1,Gen2或Gen3做data传输。 - 重置(Reset),
- 从省电状态(Slumer/Partial)的唤醒,
OOB信号实际上主要有COMRESET/COMINIT与COMWAKE三个PHY信号线。
- COMRESET:Host对Device进行硬件重置以及SATA信号的重新建立。
- COMINIT:由Device送往Host,要求信号初始化。
- COMWAKE:Host或是Device装置可以激发该信号来将PHY从省电状态(Slumer/Partial)抽离。
COMRESET/COMINIT由两部分相互间隔构成,一部分是突发长度为160个UI (Unit Interval)约106.7ns的ALIGN,另一部分是长度为480UI约320ns的Idle。

需要注意的是,虽然COMREST和COMINIT形式上是一样的,但COMREST只能从host到device,而COMINIT只能从device到host。
COMWAKE同样是有两部分相互间隔组成,一部分是突发长度为160个UI (Unit Interval)约106.7ns的ALIGN,另一部分是长度为160个UI约106.7ns的Idle。

SATA信号通迅链结建立过程是什么?我们先来看一幅图哈~

看不懂?没关系,我们一步步的来解析一下详细的过程:
- 主机重置,发出COMREST。
- 设备检测到COMRESET后以COMINIT回应。
---COMINIT为重新连接开始信号,设备可以在任意时间发送COMINIT重新建立连接。 - 若没有COMINIT的通知,HOST就会重复步骤1,直到DEVICE回复为止,这也是系统允许热插拔的关键。
- 主机calibrate,发出COMWAKE。
- 设备接收到COMWAKE后,设备连续发送6个COMWAKE信号,接着连续发送ALIGN进行传送速度的协商。
- 主机锁存资料。主机接收到COMWAKE后,以支援的最低速率连续发送D10.2资料,同时锁存检测接收的资料,当检测到设备发送的ALIGN后,以接收的速率将ALIGN转发给设备。
注:D10.2是0101010101...这样0和1交替的波形, 可以让device端更容易做clock recovery的动作. - 主机在发送了COMWAKE后至少要在880ps内接检测到ALIGN,否则主机重启上电序列重新检测设备,直到应用层将其终止。
- 设备锁存资料,检测到ALIGN后发送同步信号SYNC,通讯建立成功,进入到正常操作模式。如在54.6us内未检测到ALlGN,则进入错误处理,等待重新连接。
- 当主机接收到三个非ALIGN后,链结建立完成,进入正常操作。
Device与Host连接是首先从Device支持的最高速开始的,如果最高速不满足则用较低速率再次匹配,直到最低速率也不能匹配后Device将进入error状态; 换速等待时间为54.6us(2048个ALIGN DWORD传输时间);

三、实例分享
我们来看个小编工作中遇到的一个实例--fail现象是正常上电之后SATA SSD无法被识别。
抓取正常上电之后fail sample SATA trace如下:

从上面的SATA trace结合前面SATA通讯链路建立的9个步骤,我们可以发现第六步之后就出问题了:
Device传送最高速度(6.0G)的Align无法顺利被SATA analyzer解析出来,再降速送Align(3.0G, 1.5G)依然无法被SATA analyzer解析, host也没有回应, speed negotiation失败。最终,Host再次发送COMRESET,进入死循环。
正是由于SATA信号通讯链路无法建立,导致SATA SSD在上电之后始终无法被识别到。
最后附上SSD可以被正确识别的SATA trace供各位看官参考:

SATA系列专题之二:2.0 Link layer链路层概述
一、故事前传
在之前的文章中,我们有提到SATA主要包括:应用层(Application Layer), 传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer), SATA结构如下图:

较为详细解释请见之前的文章"浅析SATA Physical Layer物理层OOB信号",我们这里主要解析Link layer相关内容。
二、SATA Link Layer解析
我们先来看看link layer的结构

从上面Link layer的结构,我们可以看到link layer的作用大致可以包括以下几点:
- Frame flow control
- CRC的生成与检测
- 对数据与控制字符的Scrmable/Descramble
- 8b/10b编解码
- 将传输层进来的数据转为Frame
Link layer在SATA通讯中参与的过程可以这样理解:
- 通过插入各种primitive基元(详细解析请见本篇后面内容)进行流量控制,在成功传递完有效资料后,链结层(Linker layer)等待对方的应答,并把结果传给上层;
- 传输层(transport layer)传送进来FIS,链结层(Linker layer)计算CRC值,加扰(Scramble)和8B/10B编码后,加上SOF和EOF封装成frame ,传递给物理层(Physical layer)。
注:SOF=Start of Frame, EOF=End of Frame。 - 从物理层接收到有效资料时,进行8B/10B解码、解扰(Descramble)以及CRC效验,然后将资料提交到传输层。

后续文章对几个关键的部分展开解析,敬请关注!
SATA系列专题之二: 2.1 Link layer链路层8b/10b编码解析
一、故事前传

我们上回说到Link layer的结构,link layer的作用大致可以包括以下几点:
- Frame flow control
- CRC的生成与检测
- 对数据与控制字符的Scrmable/Descramble
- 8b/10b编解码
- 将传输层进来的数据转为Frame
二、8b/10b编解码
8b/10b编码是目前高速串行通信中经常用到的一种编码方式,直观的理解就是把8bit数据编码成10bit来传输。
为什么要引入这种机制呢?其根本目的是“直流平衡”。当高速串行流动逻辑1或逻辑0有多个位没有产生变化时,信号的转换就会因为电压位阶段关系而造成信号错误,直流平衡的最大好处便是可以克服以上问题。
将8bit编码成10bit后,连续的1或者0不能超过5位,所以10b中0和1的位数只可能出现3中情况:
- 有5个0和5个1
- 有6个0和4个1
- 有4个0和6个1
这样引出了一个新术语“不均等性”(Disparity),就是1的位数和0的位数的差值,根据上面3种情况就有对应的3个Disparity0、-2、+2.
在SATA协议中资料值可以统一的表示为Dx.y或Kx.y,其中D表示资料字元,K表示特殊的控制字元, x表示输入的原始资料的低5位元,y表示输入的原始资料的高3位元。 通俗的讲,也就是8bit原始数据会分成两部分,其低5位进行5B/6B编码,高3位则进行3B/4B编码。
对K控制字元的编码方式和D资料字元编码方式一样。
协定中只使用了两个控制字元K28.3和K28.5
- K28.5只用在Primitive基元ALIGNp byte0,
- K28.3用在除ALIGNp之外的其他任何Primitive基元的byte0.

举个栗子:例如一个8bit数据101 10101,x=10101(十进制为21) y=101(十进制为5),我们就把这8bit数据写成D21.5。对照5B/6B以及3B/4B加密对照表(如下表),可以得到10bit数据为101010 1010


SATA系列专题之二: 2.2 Link layer链路层加扰/解扰/CRC解析
一、故事前传

我们之前说到Link layer的结构,link layer的作用大致可以包括以下几点:
- Frame flow control
- CRC的生成与检测
- 对数据与控制字符的Scrmable/Descramble
- 8b/10b编解码(已解析,详细见历史文章)
- 将传输层进来的数据转为Frame
二、加扰(Scramble)/解扰(Descramble)
资料在进行8b/10b 编码之前,必须先行资料加扰(Scramble)的处理,目的是為了降低EMI(Electromagnetic Interference,电磁干扰)。
实现方式是由LFSR(Linear Feedback Shift Register)的方式来实践;
基本原理是将资料的8 位元与LFSR 寄存器的16 位元输出做XOR 的处理。
- 规定LFSR的初始值為0xFFFF,
- LFSR必须在SOF标志前就要被初始化,
- 在SOF与EOF之间的资料,包括CRC值都需要加扰。
- 对于控制基元Primitive是不需要加扰的 。
SATA协议中资料处理流程如下 :
- 对于一个资料包,在SOF后的资料就必须计算其CRC值,同时这个资料必须和扰码器的输出进行XOR操作,操作结果送往8B/10B编码器编码;
- 反之,在接收方,资料先通过10B/8B解码,再与扰码器的输出结果进行XOR操作,最后计算资料的CRC值。
三、CRC(Cyclic Redundancy Check)循环冗余校验码
CRC的计算范围包括SOF和EOF之间的所有资料(即不包括控制基元),以Dword(32-bit)为单位,如果资料的内容不是Dword的整数倍,需要在资料包的后面用‘0’来补充。
- 协议规定CRC的初始值為0x52325032,
- SOF和EOF之间的所有资料不能超过2064个Dwords。

SATA系列专题之二: 2.3 Link layer链路层 Frame结构以及Primitive基元解析
一、故事前传

我们之前说到Link layer的结构,link layer的作用大致可以包括以下几点:
- Frame flow control
- CRC的生成与检测(已解析,详细见历史文章)
- 对数据与控制字符的Scrmable/Descramble(已解析,详细见历史文章)
- 8b/10b编解码(已解析,详细见历史文章)
- 将传输层进来的数据转为Frame
二、Frame结构解析
SATA协议中所有Frame的结构均是包含四个部分:SOF、Payload Data、CRC、EOF。(如下图所示)

三、Primitive基元解析
Primitive基元是用于控制和提供串行线状态的Dword实体。比如ALIGNp, SOFp, EOFp, HOLDp, PMREQ_Pp, PMREQ_Sp, SYNCp, WTRMp, R_RDYp, X_RDYp等。其对应的含义以及DW解析如下表:



理论再多不如实践呐,现以设备接收一个资料包的传输过程来说明基元的作用。首先主机、设备都处于空闲状态(SYNC)。

(1) 主机有资料需要发送,发送X_RDY,通知设备准备接收资料;

(2)设备检查自己的状态,准备好后发送R_RDY告诉主机可以发送数据;

(3)主机开始发送资料, SOF为资料开始标志;

(4)接收方在接收到资料时,以R_IP告诉主机正在接收资料;

(5)主机的资料包没有发送完,可是还有些资料没有准备好,以HOLD告诉设备暂停资料发送;
(6) 设备接收到HOLD后,以HOLDA回应;
(7) 主机准备好了资料可以继续发送,以HOLD结束等待状态;
(8)主机继续传输资料;
(9)设备接收资料,以R_IP告诉主机正在接收资料;

(10) 主机发送完了整个资料包,发送WTRM告诉设备:主机正在等待传输结果;

(11) 设备接收完整个资料包并检验正确,以R_OK告诉主机接收正确;

(12)主机进入空闲状态,发送同步信号SYNC;

(13)设备进入空闲状态,发送同步信号SYNC;

SATA系列专题之三:3.0 Transport Layer传输层概述
一、故事前传
在之前的文章中,我们有提到SATA主要包括:应用层(Application Layer), 传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer), SATA结构如下图:

较为详细解释请见之前的文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link layer链路层解析 2.0-2.3;
我们这里主要解析Transport layer相关内容。
二、SATA Transport Layer传输层概述
当Host下发Command时(如下图),传输层的职责大致有:
- 发送时根据Command的种类及格式构造FIS(Frame Information Structure),接受时检测FIS种类并分解得到有用资讯
- 通知Link Layer传送Frame以及获取Link Layer传来的Frame receipt确认信息,(host收到FIS后也会向device发送确认信息的FIS)
- 管理和流量控制(Flow Control)
- 向Application Layer报告传输完成或者报错(Error Reporting)

简单的讲,传输层不必关心需要传输或接收资讯的多少,只需把要传输的资料封装成FIS 格式,发送到Link Layer,或者把收到的FIS去除封装,提交给Application Layer。
后续文章会针对FIS,Flow Control以及Error Reporting三个部分详细解析,敬请期待呀~Oh, man, Come on!
SATA系列专题之三:3.1 Transport Layer传输层FIS结构解析
一、故事前传
在之前的文章中,我们有提到SATA主要包括:应用层(Application Layer), 传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer),
较为详细解释请见之前的文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link layer链路层解析 2.0-2.3;
我们这里主要解析Transport layer FIS结构相关内容。
二、FIS(Frame Information Structure)解析
FIS是一种用于Host和device之间信息传输的机制,每个FIS的格式都是固定的,并且对应唯一的ID,SATA Spec定义了14类FIS ID。

但是,实际上,我们用到主要是8类:
FIS Type
FIS IDDiscriptionSizeH2D 27hSend command to drive5 DWsD2H34hResponds status to host5 DWsDMA Activate39hActivate a DMA data transfer1 DWDMA Setup41hStart a DMA data transfer7 DWsPIO Setup5Fh
Start a PIO transfer
PIO=Programmed Input/Output
5 DWsDATA46hData packet2049 DWsSDBA1hResponds a command completion for NCQ command2 DWsBIST58h SATA Built-In Self-Test3 DWs
(1) Register FIS-H2D(27h)
用来传输主机的Shadow Register(可以理解为CPU的传达室)的资料到设备,与ATA/ATAPI指令字和寄存器相容。
当Device接收到一个有效的Register FIS - H2D,检查C bit的内容,然后更新命令寄存器 / 控制寄存器中的内容中,
C bit为‘1’,Device按照Command Register中的命令执行命令,
C bit为‘0’,Device按照Control Register中的内容执行控制请求。

(2) Register FIS-D2H(34h)
D2H的作用如下:
- 从Device送往Host端,传送装置的状态变化。
- 当Device完成一个命令,向主机报告指令完成的状态。
- Device用于修改host中shadow block里的command register和control register。

(3) SDB(Set Device Bits)(A1h)
SDB的作用是Device用来改写host 的shadow register中的error或status的某些bits;
这些bits包括Error全部8 bits和Status中的6 bits,
SDB FIS不改变状态寄存器中的bit7 BSY(Busy)、bit3 DRQ(Data Request)。

下表中的“i”表示host在收到该FIS以后,如果shadow status register中BSY和DRQ位都为0时,host进入中断等待状态(实际上表明device进入中断等待状态)

(4) DMA Activate(A1h)--Device to Host
DMA Active FIS的特性主要是:
- Device发送该FIS同意主机以DMA方式向设备发送资料,
- 是Device对主机DMA写命令的一个回应,
- 当发送完FIS后,Device必须进入接收DMA资料接收状态,
- 每发送一个DMA DATA FIS后,要再次收到DMA Activate FIS才能发送下一个DMA DATA FIS;

(5) DMA Setup(41h)--Bidirectional
进行DMA操作的第一步,目的是为了建立DMA操作参数。
发送方通过发送这个FIS,要求对方配置好DMA控制器,同时存储空间必须按要求处于准备状态。
D bit为‘0’,代表发送方传送资料;
D bit为‘1’,代表接收方传送资料, 传输时一方的D为1,另一方的D为0。
DMA Transfer Count表示传输Bytes计数。

(6) PIO Setup(5Fh)--Device to Host
由设备发送给主机,告诉主机相关PIO操作参数,包括了在PIO传输前和传输后shadow register的内容。
- 在PIO传输资料的过程中,Device必须先发送这个FIS给主机,表示Device准备好发送或接受数据。
- 与DMA传输一样,每传一个DATA FIS就要一个PIO SETUP FIS传输下一个DATA FIS;

(7) DATA FIS(46h)--Bidirectional
DATA FIS比较简单,就是用来传输资料,比如说对硬盘的读写操作,
资料包的长度是不定的,除去SOF、EOF、CRC和FIS类型等标志外,最多2048个Dwords。

(8) BIST Activate(58h)--Bidirectional
让对方进入测试模式,是一个双向可用的FIS,接收方以R_OK回应,完成测试工作之后就进入BIST交换状态了。

SATA系列专题之三:3.2 Transport Layer传输层FIS Retry机制解析
一、故事前传
在之前的文章中,已经解析了SATA协议的部分相关内容。
较为详细解释请见之前的文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link layer链路层解析2.0-2.3;
3,SATA Transport layer链路层解析3.0-3.1;
我们这里主要解析Transport layer FIS Retry机制相关内容。
二、FIS Retry机制解析
上回说到,FIS是一种用于Host和device之间信息传输的机制,每个FIS的格式都是固定的,并且对应唯一的ID,SATA Spec定义了14类FIS ID。
其实在很多场景下,FIS的传输会出现Error,那怎么办呢?
不怕不怕,SATA协议给我们准备了Retry机制可以救场~
Transport Layer在Host端和Device分别有一个Buffer: FIS Tx Buffer和FIS Rx Buffer(如下图)。
- 当Host端将FIS从Transport Layer传至Link layer的时候,FIS其实在Transport Layer的FIS Tx Buffer有一个备份。
- 当device Link layer解析到传过来的FIS有错误发生时,会返回一个Primitive基元“R_ERR”,告诉Host端:“您刚才传输的FIS出了点问题,麻烦您发送一遍”。
- Host端收到R_ERR反馈会再讲备份在FIS Tx Buffer的FIS重新发送一遍。

但是,有一点需要注意,并不是所有的FIS都可以用Retry机制修复Error:
- DATA FIS最大长度为2049 DWs, 但是Transport layer并没有这么大Buffer,FIS Tx/Rx Buffer只要7 DWs,所以DATA FIS无法用Retry机制。
- BIST只用在测试诊断场景,所以BIST也无法用Retry机制。
所有FIS Retry机制状态如下表:

SATA系列专题之三:3.3 Transport Layer传输层Flow Control机制解析
一、故事前传
在之前的文章中,已经解析了SATA协议的部分相关内容。
较为详细解释请见之前的文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link layer链路层解析2.0-2.3;
3,SATA Transport layer链路层解析3.0-3.2;
我们这里主要解析Transport layer Flow Control机制相关内容。
二、Flow Control
我们前面有提到传输层中Tx/Rx buffer只有7 DWs,也就是28 Bytes, 而我们Data FIS的最大长度是2049 DWs(8196 Bytes)。在Data传输过程中,如果不加管理和控制的话,就会出现欠载(UnderRuns)和过载(OverRuns)的情况。
在Data flow control的过程中,主要用了两个Primitive基元:HOLD和HOLDA。
- HOLD的作用是告知对方中止FIS传输;
- HOLDA的作用是告知HOLD发送者:“您的HOLD中止指令已收到,并且已中止FIS传输”。
发送端(Tranmitter)和接收端(Reciver)均可以启动Data flow control机制,主要分为以下四种情况:
- 发送端Tx Buffer接近空的时候;
- 发送端Tx Buffer接近满的时候;
- 接收端Rx Buffer接近满的时候;
- 接收端Rx Buffer接近空的时候;
(1)发送端Tx Buffer接近空的时候
Data FIS传输过程中,首先是接收端检测到FIS并且回复Primitive基元"R_IP"(Reception in Progress)给发送端(如下图)。
- 当发送端Tx buffer接近空的时候,发送端会给接收端发送Primitive基元“HOLD”,告知接收端,data传输将会被暂停;
注:发送端会一直发送HOLD,直到data传输被恢复。 - 当接收端接收到HOLD之后,会反馈HOLDA给发送端。

(2)发送端Tx Buffer接近满的时候
前面提到发送端会一直发送HOLD,直到data传输被恢复。一旦发送端Tx Buffer快满了,就会取消HOLD,并恢复data传输。接收端也会在HOLD之后立马检测到数据的传输,并且释放HOLDA。

(3)接收端Rx Buffer接近满的时候
当接收端Rx buffer快满的时候,发送HOLD给接收端,告知发送端"先不要发送数据了,我快承受不来了,呜呜~"。
当发送端接到HOLD之后,会立马发送HOLDA安抚接收端"遵命~传输已中止~"。

(4)接收端Rx Buffer接近空的时候
当接收端Rx buffer快空的时候,会释放HOLD,欢快的告知发送端“快发送数据啦,我现在很空呢~”,同时会发送R_IP。发送端收到接收端R_IP的指示,恢复data传输。

SATA系列专题之三:3.4 Transport Layer传输层Error处理机制解析
一、故事前传
在之前的文章中,已经解析了SATA协议的部分相关内容。
较为详细解释请见之前的文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link layer链路层解析2.0-2.3;
3,SATA Transport layer链路层解析3.0-3.3;
我们这里主要解析Transport layer Error Reporting机制相关内容。
二、Error Reporting
SATA Spec中提到SATA环境支持ATA error以及SATA error的检测。SATA环境中发生的error大致分为四类:
- Command无法正常完成。这部分会记录在ATA的Status/Error register(也可以称为ATA shadow register).
- FIS传输错误。这部分记录在SATA定义的Error register.
- SATA链路传输error。这部分也记录在在SATA定义的Error register.
- HBA(Host Bus Adapter)错误。这部分会记录在SATA定义的Error register或者IO bus register.

从上图我们也可以看到,所有的status和error register都放在HBA。Device也可以检测到Error,但是要上报给Host, 主要途径有两个:
- 在command执行过程中发现错误后,Device通过向Host发送Register FIS-D2H来更新ATA status & error。
- 在FIS传输过程中发生错误,Device向Host发送Primitive基元“R_ERR”。不过,这种情况下,Host不能判断错误的根本原因。
SATA环境下产生的错误可能发生在任何一层,每层检测的status & error类型如下图:

发现了问题,最终还得去解决。对于各层上报的error,根据错误类型以及错误严重程度,应对措施主要有:
- 冻结(Freeze)。这个时候就说明了错误的严重性很高,无法修复,需要做reset才能清除错误;
- 中断(Abort)。表明错误比较持久,相应的cmd已经失败。需要告诉Host作中断处理。
- 重新发送(Retry)。表明错误是短暂并且不影响SATA系统运行,比如CRC error。这个错误如果是在Transport Layer或者以下发生的,由硬件启动retry机制。如果发生在Transport Layer之上了,就要依赖软件启动retry机制。
- 追踪/忽略(Track/ignore)。表明这是个可以纠正的错误,不严重,可以忽略。不过,此类error虽然可以被纠正,但是也会对SATA的整体性能产生不利影响。
(1) ATA Status & Error Register
当有ATA error发生时,ATA status会将ERR bit置"1"。如果ERR bit=0, 那么Error register相应的内容均为无效。

Error Register具体定义如下:

(2) SATA定义的相关Error Register
SATA Status(SStatus) Register:

SATA Error(SError) Register:



SATA系列专题之四:4.0 Command Layer命令层概述
一、故事前传
在之前的文章中, 我们已经介绍了传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer)的相关内容。详见前期文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link Layer链路层解析2.0-2.3;
3,SATA Transport Layer传输层解析3.0-3.4;
我们这里主要解析Command layer命令层相关内容。
二、SATA Command Layer命令层概述
当Host要下发一个command时,步骤大致如下:
- Host软件先初始化Shadow register;
- 软件下发cmd, 将payload content的资讯,先写到shadow command block register和shadow control block register里;
- 应用层将shadow register的内容发送传输层,并产生FIS,,
- 通过FIS传到device的command register block和control register block;

#shadow command block 映射到 command register block;
#shadow control block 映射到 control register block;

这里要先提一下Shadow register:
这其实是个和硬件有关的概念。有些register是2层的,第一层是供CPU访问,第二层供HW访问。

- 这是同一个Register,不是2个Register,只不过分了2层。形象的讲上层是下层的Shadow。
- CPU在写Register的时候,会先写在上层的Shadow Register,硬件update之后才会在下层供HW访问的Register开始执行。
- 因为真正生效的执行HW动作的是下面这层,而上面这层只是将CPU(也就是将软件)的信息获取到,等下个硬件周期才会执行。
SATA系列专题之四:4.1 Command Layer命令分类详细解析
一、故事前传
在之前的文章中, 我们已经介绍了传输层(Transport Layer),链路层(Link Layer)以及物理层(Physical Layer)的相关内容。详见前期文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link Layer链路层解析2.0-2.3;
3,SATA Transport Layer传输层解析3.0-3.4;
4,SATA Command Layer命令层解析4.0;
我们这里主要解析Command layer命令层具体Command相关内容。
二、SATA Command Layer命令层具体解析
SATA Spec定义了12类Command,具体分类与对应的数量如下表:

那么,我们就对这12类Commands中作详细的介绍:
1. Command No Implemented
当Command无法执行时,状态如下图,Device需要做三件事情:
- 在ATA status register中将ERR bit 置为1;
- 在ATA error register中将abort bit置为1;
- 返回Register FIS-D2H更新shadow register.
注:ATA status & error register详细介绍请见历史文章"SATA Transport Layer传输层解析".

2. Non-Data Commands
Non-Data Commands这一类的command sequence比较简单,主要是通过Register FIS在Host与device之间进行交互,如下图:

3. PIO Data-In Commands
PIO data-in command的作用是将device的数据读到host memory中,具体sequence如下:

PIO read SATA trace供参考:

4. PIO Data-Out Commands
PIO data-out command的作用是将host memory数据写入device。具体sequence如下:

5. DMA Data-In(Read) Commands

DMA read SATA trace供参考:

6. DMA Data-Out(Write) Commands

DMA write SATA trace供参考:

7. DMA Data-In(Read) Queued Commands

8. DMA Data-Out(Write) Queued Commands

9. COMRSET Sequence

10. Host Software Reset Sequence

SATA系列专题之五:Link Power Management解析
一、故事前传
在之前的文章中, 我们已经针对SATA的主要结构进行了较为详细的解析,详见前期文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link Layer链路层解析2.0-2.3;
3,SATA Transport Layer传输层解析3.0-3.4;
4,SATA Command Layer命令层解析4.0-4.1;
我们这里主要解析一下SATA Link Power Management的相关内容。
二、SATA Link Power Management解析
一般情况下,SATA Phys会处在Phy Rdy状态(Standby),确保Host与Device之间正常通信。如果SATA host一直处在Idle的情况,并不需要SATA interface处于通信状态,而此时,SATA Phys仍处在Phy Rdy状态(Standby),这样是不是有点浪费呢?
基于降低能效的考虑,SATA Spec定义了两种低功耗的状态:Partial和Slumber。
- Partial: 功耗大约75mW, 比Standby状态功耗约200mW低了一多半, 从Partial状态退回Phy Rdy的时间不能超过10us.
- Slumber: 功耗大约25mW, 比Partial状态功耗更低,从Slumber状态退回Phy Rdy的时间也相对较长,但不能超过10ms。
在Link Power Management协议中有四个关键的Primitive基元参与:
- PMREQ_S: 请求进入Slumber状态, 这个基元会被一直发送,知道收到对方的回应(PMACK或者PMNAK).
- PMREQ_P: 请求进入Partial状态, 这个基元会被一直发送,知道收到对方的回应(PMACK或者PMNAK).
- PMACK:对PMREQ_S或者PMREQ_P的回应,接受进入Slumber或者Partial的请求。
- PMNAK:对PMREQ_S或者PMREQ_P的回应,不接受进入Slumber或者Partial的请求。
生来平等,Host与Device均可以发起请求(HIPM/DIPM),进入Partial/Slumber。
- HIPM = Host Initiated Link Power Management
- DIPM = Device Initiated Link Power Management
我们针对HIPM举例,解析一下Link Power Management Protocol:
- Host应用层初始化Partial/Slumber请求;
- Host传输层收到上层传过来Partial/Slumber请求后,转送至下一层链路层;
- Host链路层收到Partial/Slumber请求后,进入Partial(L_TPMPartial)或者Slumber(L_TPMSlumber),并发送Primitive基元"PMREQ_P"或者"PMREQ_S"至物理层,这个过程中,会一直发送PMREQ,直至收到物理层的回应(PMACK或者PMNAK);
- Host物理层通过物理链接将Primitive基元"PMREQ_P"或者"PMREQ_S"传送至Device物理层;
- Device物理层将收到的信息全部转送至Device链路层;
- Device链路层一旦收到Primitive基元"PMREQ_P"或者"PMREQ_S",就会进入PMOff 状态;
- 进入PMOff状态后,Device链路层会发送Primitive基元PMACK至物理层。这个过程中会发送4~16个PMACK。之后,链路层进入ChkPhyRdy状态,并向物理层发送信号,告知其进入Partial/Slumber状态;
- Device物理层将PMACK发送至Host物理层;
- Device物理层检测到链路层发送的Partial/Slumber信号后,进入Electrical Idle状态(0V, no signal);
- Host物理层收到PMACK后,转送至链路层;
- Host链路层检测到PMACK后,进入ChkPhyRdy状态,并中止发送PMREQ;
- 进入ChkPhyRdy后,Host链路层会向物理层发送信号,告知其进入Partial/Slumber状态。然后Host物理层进入进入Electrical Idle状态(0V, no signal);

从上面的Protocol中,我们可以看到,一旦进入Partial/Slumber状态,Link Phy就会进入electrical idle。如果要从Partial/Slumber状态中唤醒,就需要依赖COMWAKE OOB信号重新建立Link。
有关OOB信号的详细介绍请见之前文章:
浅析SATA Physical Layer物理层OOB信号;
此外,由于Link Power Mangement是选择性的,所以并不要求所有的device一定要支持这个功能。一块SSD是否支持,可以查看其Identity Drive data:

SATA系列专题之六:浅析NCQ原生指令序列
一、故事前传
在之前的文章中, 我们已经针对SATA相关内容进行了较为详细的解析,如果感兴趣的话,请见之前文章:
1,浅析SATA Physical Layer物理层OOB信号;
2,SATA Link Layer链路层解析2.0-2.3;
3,SATA Transport Layer传输层解析3.0-3.4;
4,SATA Command Layer命令层解析4.0-4.1;
5,SATA Link Power Managment解析;
我们这里主要解析一下SATA NCQ(Native Command Queuing)原生指令序列的相关内容。
二、SATA NCQ 原生指令序列
NCQ是SATA中的命令协议,允许同时在Drive中执行多个命令。 当用户的应用程序发送多条指令到用户的硬盘,NCQ可以优化完成这些指令的顺序,从而降低负荷达到提升性能的目的。
此外,SATA Spec中还定义了三个特殊的功能来加强NCQ的性能:
- Race-Free Status Return: 无竞争状态返回机制,允许任何指令任何时间报告执行状态,此外,多个命令执行完毕信息可以打包一起回传。
- Interrupt Aggregation: 在DMA传输模式下,硬盘通知传输结束,会引起一个中断(Interrupt),造成延迟。所以,SATA spec提供中断聚集机制。如果硬盘同时间内完成多组命令,这些命令完成所引起的中断就可以聚集在一起,大幅减少中断的数目,这对于降低中断延迟有极大的贡献。
- First-Party DMA(FPDMA): SATA允许硬盘端通过DMA setup FIS直接对Host控制器送出数据传输请求,DMA引擎就可以直接进行资料传输,这个过程中并不需要Host端软件的介入。
当Drive收到一个Command,是要将其重新排列?还是立即执行呢?这怎么区分呢?
不怕,SATA Spec定义了两个特殊的NCQ指令: - Read FPDMA Queued;

- Write FPDMA Queued;

从上面Read FPMA Queued Inputs和Write FPMA Queued Inputs我们可以看到红色框里面有一个特别的5-bit参数TAG(bit3~bit7). 这个参数就代表了NCQ一次可以最多执行32个Commands(如下图红色框Command List)。

在Device端,当Queued Commands(最多32)中的一个write或者read准备好传输数据时,通过发送DMA setup FIS告知Host已准备好数据传输,其中要附带更新Tag Value(如下图红色框)。

在Device端,当Queued Commands执行完成后, 通过发送Set Device Bits FIS告知Host完成状态,此时SActive区域对应TAG的相关内容(最多32个Command)。

FPDMA Read Command(60h) Protocol如下:

我们抓取了一个FPDMA Read Command(60h)的SATA trace,如下图:

从上面的SATA trace我们可以得到:
- 这个FPDMA read cmd对应的Tag=8;
- 这个FPDMA read cmd要读取32768 bytes的数据;
在之前的文章“SATA Transport Layer传输层解析”中,我们提到过,Data FIS中的数据长度最大为2048 DWs,也就是8192 Bytes。所以,我们可以看到在上面的sata trace中,分4次发送Data FIS来实现32768 bytes数据的传输。
FPDMA Write Command(61h) Protocol如下:

我们抓取了一个FPDMA Write Command(61h)的SATA trace,如下图:

从上面的SATA trace我们可以得到:
- 这个FPDMA write cmd对应的Tag=0xEh=14;
- 这个FPDMA write cmd要写入131072 bytes的数据;
在之前的文章“SATA Transport Layer传输层解析”中,我们提到过:Data FIS中的数据长度最大为2048 DWs,也就是8192 Bytes。所以,我们可以看到在上面的sata trace中,分16次发送Data FIS。但是每发送一个DMA DATA FIS后,要再次收到DMA Activate FIS才能发送下一个DMA DATA FIS;
下面我们再看个完整的例子加深一下对NCQ的理解:
举例:Host向Device发送两个Read FPDMA Queued指令
针对这个例子,我们作两个假设:
假设1:
第一个Read FPDMA Queued指令 Tag=0;
第二个Read FPDMA Queued指令 Tag=5;
假设2:
Device要先执行第二个指令(Tag=5), 然后在执行第一个指令(Tag=0)

上图中指令下发流程如下:
- Host先下发第一个Read FPDMA Queued指令,并且SActive bit0=1, 写入NCQ buffer,这时NCQ队列深度=1;
- Host先下发第二个Read FPDMA Queued指令,并且SActive bit0 & bit5=1, 写入NCQ buffer,这时NCQ队列深度=2;
在假设2中,我们要求先执行第二个指令(Tag=5),那么,这个时候就需要NCQ对这两个指令重新排序,如下图红色框显示:

NCQ对这个两个指令重新排序后,就开始执行依次这两个Read FPDMA Queued指令, 指令执行流程见前面介绍的“FPDMA Read Command(60h) Protocol”内容。
上图是执行Tag=5指令的示意图,下图为执行Tag=0指令的示意图:

————————————————
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理