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發中斷通知這一個命令週期已經結束。 |