私が理解した基本的なドキュメントをいくつか読んだ後、ベースアドレスレジスタはPCIe IPからアクセスできるアドレス空間です。 PCIe IPは、ベースアドレスレジスタでデータを送信するか、受信したデータを書き込むことができます。
私は正しいですか?または何か不足していますか?
これは非常に基本的な質問だと思うので、読むことをお勧めします。
ベースアドレスレジスタ(BAR)は次の目的で使用されます。
-デバイスがメインメモリにマップするメモリの量を指定します。
-デバイス列挙後、マップされたメモリブロックが始まる(ベース)アドレスを保持します。
デバイスは、最大6個の32ビットBARを持つか、2つのBARを組み合わせて64ビットBARにすることができます。
Linuxカーネルの観点
何かを学ぶ良い方法は、それと対話することです。そのためにLinuxカーネルを使用しましょう。
QEMUエミュレートデバイスでの最小限のPCIの例を次に示します: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/366b1c1af269f56d6a7e6464f2862ba2bc368062/kernel_module/pci.c
PCI構成の最初の64バイトは、次のように標準化されています。
LDD3からの画像。
したがって、6つのBARがあることがわかります。 wikiページ は各BARのコンテンツを表示します:
ただし、領域の幅にはマジックライトが必要です: PCI/PCIe BARサイズはどのように決定されますか?
このメモリはPCIデバイスによって設定され、カーネルに情報を提供します。
各BARは、PCIデバイスへの個別の通信チャネルとして機能するアドレス範囲に対応しています。
各領域の長さはハードウェアによって定義され、構成レジスタを介してソフトウェアに伝達されます。
各領域には、長さ、特にメモリタイプに加えて、ハードウェアで定義されたプロパティもあります。
IORESOURCE_IO
:inX
およびoutX
でアクセスする必要がありますIORESOURCE_MEM
:ioreadX
およびiowriteX
でアクセスする必要がありますいくつかのLinuxカーネルPCI関数は、BAR
をパラメーターとして使用して、使用する通信チャネルを識別します。例:
mmio = pci_iomap(pdev, BAR, pci_resource_len(pdev, BAR));
pci_resource_flags(dev, BAR);
pci_resource_start(pdev, BAR);
pci_resource_end(pdev, BAR);
QEMUデバイスのソースコードを調べると、QEMUデバイスがこれらの領域を次のように登録していることがわかります。
memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu,
"edu-mmio", 1 << 20);
pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio);
そして、BARのプロパティがハードウェアで定義されていることは明らかです。 BAR番号0
、タイプメモリPCI_BASE_ADDRESS_SPACE_MEMORY
、およびメモリ領域は1MiBの長さ1 << 20
。