無限遠まで突撃中

ネット日記書きの徒然。

AHCI奮闘記 - 初期化編

こんにちは、突撃隊です。 最近いじっているAHCIというデバイスについて、な、な、なんと 初期化 が無事終了したので知見を共有したいと思います。

AHCIとはなんぞや

Advanced Host Controller Interface(AHCI)とは、SATAのデバイスコントローラです。 SATAをいい感じに触るためのインターフェースを提供してくれます。

初期化の手順について

しっかり初期化をしないとほとんど使い物にならないかもしれません。 ちゃんと仕様書を読んでしっかり初期化をしましょう。

仕様書の該当箇所

AHCI Specification ver 1.3 では、 10.1.2 System Software Specific Initialization にソフトウェアプログラマがやるべき初期化が書かれています。

初期化手順をまとめた

自分なりにやるべき処理をまとめました。

初期化処理メモ(上から順番)

  • 最初にリセットをしたほうがいいかもしれない
    • リセットはGHC.AE = 1にした後、GHC.HR = 1にしてしばらく待つ
  • PIレジスタを見て実装されているポートを探す
    • 以下の処理はすべて実装されているポートにのみ対して行う
  • ソフトウェア側でPxCMD.STを0にセットしハードウェアがPxCMD.CRを0にするのを待つ
  • 最低500msくらいは待つ
  • (PxCMD.FREが1だった場合、これを0にしてハードウェアがPxCMD.FRを0にするのを待つ(最低500ms))
  • CAP.NCSを読んで対応スロットを探す
  • 各対応スロットにおいて、PxCLBとPxFBのぶんのメモリを確保して0で埋める
  • PxFBのメモリ領域を確保した後、PxCMD.FREを1にする
  • 各対応スロットに対して、PxSERRをクリアする。ビットに'1s'を書き込んでクリアする
  • PxISをクリアした後、IS.IPSをクリアする(順番が重要)
  • PxIEレジスタをenableにする。またGHC.IEも1にセットする

(必要なら追加の初期化をする、その際の注意)

  • バイスが動いている間は、PxCMD.STは1にセットしようとしない
    • 具体的には、PxTFD.STS.BSY=0,PxTFD.STS.DRQ=0,PxSSTS.DET=3hのときである
  • PxTFDレジスタをenableにするために、PxSERR.DIAG.Xは0にクリアされてなければならない

自分の自作OSではどうなっているか

QEMU上で動かしています。

初期化直後は以下のようなフラグの状態です。 多分正常だと思います。

status of Generic Host Control
cap: 0x00000000c0141f05
ghc: 0x0000000080000002
is: 0x0000000000000000
pi: 0x000000000000003f
vs: 0x0000000000010000
ccc_ctl: 0x0000000000000000
ccc_pts: 0x0000000000000000
em_loc: 0x0000000000000000
em_ctl: 0x0000000000000000
cap2: 0x0000000000000000
bohc: 0x0000000000000000

status of HBA Port 0
clb: 0x0000000010000000
clbu: 0x0000000000000000
fb: 0x0000000010008000
fbu: 0x0000000000000000
is: 0x0000000000000000
ie: 0x00000000fdc000ff
cmd: 0x0000000000004016
tfd: 0x0000000000000130
sig: 0x0000000000000101
ssts: 0x0000000000000113
sctl: 0x0000000000000000
serr: 0x0000000000000000
sact: 0x0000000000000000
ci: 0x0000000000000000
sntf: 0x0000000000000000
fbs: 0x0000000000000000

なぐり書きなので

また随時更新します。