AHCI驱动中的cmd

这两天被AHCI控制器的驱动搞的焦头烂额,当然主要的问题其实不在软件,而是FPGA上的SATA物理层传输不够稳定,现在也没什么很好的办法。先写一下这两天看到的系统软件和AHCI控制器硬件交互的三个核心数据结构:cmd_slot / rx_fis / cmd_tbl

上面这张图是从AHCI规范里面摘出来的,AHCI规范里面定义了在Memory中要使用Command List、Received FIS、Command Table三种数据结构,作为与SATA DMA进行交互的接口。对应到kernel的AHCI驱动代码里,三者的实现分别是cmd_slot[]数组、rx_fis、cmd_tbl,其中&cmd_slot[0]、&rx_fis这两个指针又被保存在AHCI控制器的PxCLB、PxFB这两个寄存器里。下面参照SATA DMA在“取命令-按命令操作硬盘-写回完成状态”这样一个典型操作周期中的行为,来理解上述三个数据结构的作用。

典型操作周期中CPU与SATA DMA的工作流程如下:

  1. CPU inform DMA the addressof cmd_slot& rx_fis, andset PxCI register

  2. DMA read cmd_slot, getaddress of cmd_tbl

  3. DMA read cmd_tbl, getCommand or Data

  4. DMA & SATA execute Command

  5. DMA write some completion flag in cmd_slot/ rx_fis/ cmd_tbl

  6. DMA inform CPU the completion of Command(by interrupt)

  简单归纳一下,三个structure的用法是这样的:cmd_tbl中存储的是CPU希望SATA host对SATA device执行的命令及其参数,Command Table的格式在ATA规范里有详细的定义;cmd_slot[]数组存储的就是指向若干个(最多32个)cmd_tbl的指针;rx_fis中存的就是内存从SATA DMA接收到的数据帧(关于内存将要通过SATA DMA发送出去的数据帧的定义和实现在哪里还不是很清楚,估计应该是Command Table的某个域),Received FIS的格式亦在ATA规范中被定义了。

  SATA控制器里只保存着cmd_slot[]的基地址,并不直接保存cmd_tbl的地址,所以每当CPU通过写PxCI等寄存器向SATA控制器发出执行命令的请求后,SATA DMA会先读取cmd_slot[i],得到相应的cmd_tbl的地址,然后再读cmd_tbl,这样“取命令”阶段就完成了。

  接下来SATA 控制器就会按照命令要求来对硬盘进行操作,比如写入或读出,也就是按照某种具体的方式在内存和SATA device间搬运FIS。在命令执行完之后再对cmd_tbl中的某些完成标志或错误标志进行写入,最后向CPU发中断通知这一个命令周期已经结束。

猜你喜欢

转载自blog.csdn.net/qq_40155300/article/details/82877274