pci bus tree
pci bus scan
pci bus をscanする方法。
Config Access Type
pciのbus scanには2種類のConfig accessが使われる。
- Type0 / T0: Bridgeが透過不可のアクセス
- Type 1 / T2 : Bridgeが透過可のアクセス
Type 0
31-11 | 10-8 | 7-2 | 1 | 0 |
---|---|---|---|---|
Devsel | func | reg | 0 | 0 |
Type 1
31-24 | 23-16 | 15-11 | 10-8 | 7-2 | 1 | 0 |
---|---|---|---|---|---|---|
reserved | Bus | Dev | func | reg | 0 | 1 |
BridgeのConfig Access処理
Bridgeは、a) ホスト側のPrimary Bus番号PBN、b)ホストから遠い側のSecondary Bus番号SBN、c) Bridge配下の最大のBus番号Subordinate Bus番号/OBNの3つを使いConfig accessの透過を判断する。
Bridgeが2.透過可能アクセスを受けた時、アクセスのBus番号/ABNがa) PBN以下の場合、あるいはOBNを超える場合、破棄する。b) SBNの場合、アクセスを1.透過不可アクセスに変更してSBN側に透過する。c) SBNを超え、OBN以下の場合、2.透過可能アクセスのまま透過する。まとめると、
- ABN=SBN, T0に変更し透過。
- SBN<ABN<=OBN: T1のまま透過。
- 上記以外: 破棄
Bus scan 方法
上記Config Access TypeとBridge挙動から下記の方法にてBus scanする。
Step 1. 最もcpuに近いホストブリッジ(bus=0,dev=0)が、T0アクセスによりDev=0からMAXDEVまでデバイスを探索する。
Step 2. ブリッジが見つかったら、PBN/SBN/OBN=0xffを設定し、ブリッジ配下を探索する。
Step 3. ブリッジ配下のデバイス探索結果、最大のバス番号をOBNに設定し、SBNをOBN+1とし、中断していたStep 1のバス探索を再開する。
上記は再帰的深さ優先探索になっているが、仮のOBNを付けた幅優先探索の方が良い?
Bus scanをコードにする
int scan_bridge(int pbn){ sbn = pbn + 1 obn = sbn for (dev = 0 ;dev < MAXDEV;dev++){ id = t0(dev) if( id == 0xffffffff ) return obn if( id.class == bridge ){ set((pbn,dev), pbn, sbn, 0xff) obn = scan_bridge( sbn ) sbn = obn + 1 setobn((pbn, dev), obn) } return obn } do_main(){ config( hostbridge ) scan_bridge(1) }
ref
http://archive.linux.or.jp/JF/JFdocs/The-Linux-Kernel-7.html