前几期内容面向的读者为对eSPI毫无概念但是有兴趣了解的工程技术人员,这一期也是本自学笔记的最后一期,所面向的读者为基本已经通读过一遍eSPI Spec,但是对其中一些概念还存在疑虑的朋友们。这一期将为大家介绍两个概念,一个是Virtual Wires Channel,另一个是Posted/Non-Posted Transaction。
Virtual Wires Channel
之前我们已经分别详细介绍过eSPI BUS的Perpheral Channel/Flash Channel/OOB Channel,在Perpheral Channel的讨论中,我们曾说过,之前由LPC负责来处理的Subtructive Decode IO/Memory Cycle,在eSPI中主要是透过Perpheral Channel进行传输的。要知道这些IO/Memory Cycle的目的地其实是挂在LPC/eSPI BUS下的一些Legacy Devcie,比如KB/MS/UART等。熟悉操作这些Legacy Devcie的朋友们应该知道,当这些Devcie有数据需要处理的时候,会往上打一个中断到PIC/APIC。在LPC中,往上送中断这种事情是通过LPC SideBand信号中的Serial IRQ来完成的,时序图如下:
那在eSPI中,是谁来负责往上送中断呢?这时候就需要Virtual Wires Channel出马了。除了中断信息以外,Master和Slave之间其他的SideBand信号也都会通过Virtual Wire Channel从SideBand信号转换成为In-Band Message。例如PCI Power Management所需的PME#信号,SCI#/SMI#硬件中断线,CPU INIT#,无特殊意义的GPIO等。
大致看一下Virtual Wires Channel的Packet格式,会看到显示一个6bit的header,表征在这个packet里要传递多少个Virtul Wire Group。每一个Virtual Wire Group由两部分构成,一个是Spec预先设定好的Virtual Wire Index,通过这个Index可以查询到当前这个Group所传递的是什么类型的Virtual Message,再查询Data Field就可以知道Message里面传递的数值是多少。
比如0x0181的Virtual Wire Group代表IRQ1 is high
Posted and Non-Posted Transaction
这是Perpheral Channel的两个概念,对于4Byte(包括)以内的数据传输,可以使用IO_Short和Memory_Short命令,再长的数据传输就需要用到PUT_NP/PUT_PC/Get_NP/Get_PC这四个命令了。这其中的P就是Post,NP就是Non-Post。
熟悉PCI Express协议的朋友们一定对Post/Non-Post不陌生,PCIE Spec将Requester和Completer之间一次完整的信息传递过程称为事物(Transaction),一次Transaction需要进行一次或者多次数据包传送。这些事物可以分为非报告事物(Non-Posted Transaction)和报告事物(Posted Transaction)。
Post, 这里可以联想为邮局/邮筒,如果你根本不指望对方回复,只是想写封抒发一下,那么把信丢进信箱就好,剩下的交给邮递员,这就是Posted Transaction;如果你期望得到对方的立即响应,那就别磨磨蹭蹭的写信了,该打电话打电话,该见面就见面,这就是Non-Posted Transaction。
在PCIE结构体系中,对于Non-Posted Transaction而言,Requester发送一个TLP请求数据包给Completer。稍后,Completer返回一个TLP完成数据包给请求者。IO空间的数据访问都是要求得到Devcie相应的,Memory Read也要求立即返回得到的数据,所以IO Write和Read/Memory Read都是属于Non-Posted Transaction;对于Posted Transaction而言,Requester发出一个TLP请求数据包给Completer,但是Completer不返回TLP完成数据包给Requester。为了提高Memory的写性能,Memory Write不需要等到上一笔的回复就可以写下去,所以Memory Write是Non-Posted Transaction。
在了解了上述的背景知识后,现在我们集中梳理一下eSPI Master和Slave之间进行数据传输的具体操作流程,分为以下四种情况:
1. Master Read Slave
a. 传输数据小于4Byte,可以使用short命令一次传输1/2/4 Byte数据
b. 传输数据大于4Byte,但是小于Max_Payload_Size,这种情况下Master只要发一笔PUT_NP CMD就可以完成数据传输,可以看到Slave在Response Phase里立即就返回了data
c.传输数据大于Max_Payload_Size,或者Slave无法及时返回数据,Master发出一笔CMD已经无法完成全部的数据传输,这种情况下就需要Slave在Response Phase回应Master一个DEFER,意思是现在数据还没有Ready,
当Slave准备了数据,会Assert Alert通知Master,Master看到Alert拉低后,会主动发起一笔Get_Status查询Slave当前的状态,Master从Slave回复的Status中看到PC_Avail Assert了,表明slave has peripheral posted or completion header and optional data up to maximum payload size available to send, 随后Master再发出一笔Get_PC把数据拿回来。
2. Slave Read Master
Slave只能通过发起Non-Posted Transaction的方式去Read Master,当Slave想要Read Master的时候,先Assert Alert,然后Master就会发出一笔Get Status去查询Slave的状态,得知Slave的Buffer里现在Pending了一笔Non-Posted Transaction Request,随后Master应该发出一笔GET_NP读回Requset,随后再发出一笔PUT_PC将Slave需要的数据返回给Slave。
3. Master Write Slave
a. 对于小于4Byte的数据传输,可以使用Short命令
b. 大于4Byte的数据传输,就需要使用PUT_PC命令了,注意Posted Transaction是不需要Slave返回数据的
4. Slave Write Master
还是一样的,Slave这边有数据传输需求就会拉Alert#,然后Master就会打Get Status查询Slave的状态,看到Slave Status Register里面Pending了一笔Posted Transaction Request,随后Master打出一笔GET_PC,Slave在Response中返回包含Write的Header,传输结束。
更多内容请见我的公众号:第五位面壁者