EN JA
PCI(9)
PCI(9) FreeBSD Kernel Developer's Manual PCI(9)

名称

pci, pci_alloc_msi, pci_alloc_msix, pci_disable_busmaster, pci_disable_io, pci_enable_busmaster, pci_enable_io, pci_find_bsf, pci_find_cap, pci_find_dbsf, pci_find_device, pci_find_extcap, pci_find_htcap, pci_get_max_read_req, pci_get_powerstate, pci_get_vpd_ident, pci_get_vpd_readonly, pci_msi_count, pci_msix_count, pci_pending_msix, pci_read_config, pci_release_msi, pci_remap_msix, pci_restore_state, pci_save_state, pci_set_max_read_req, pci_set_powerstate, pci_write_configPCI バスインタフェース

書式

#include < sys/bus.h>
#include < dev/pci/pcireg.h>
#include < dev/pci/pcivar.h>

int
pci_alloc_msi( device_t dev, int *count);

int
pci_alloc_msix( device_t dev, int *count);

int
pci_disable_busmaster( device_t dev);

int
pci_disable_io( device_t dev, int space);

int
pci_enable_busmaster( device_t dev);

int
pci_enable_io( device_t dev, int space);

device_t
pci_find_bsf( uint8_t bus, uint8_t slot, uint8_t func);

int
pci_find_cap( device_t dev, int capability, int *capreg);

device_t
pci_find_dbsf( uint32_t domain, uint8_t bus, uint8_t slot, uint8_t func);

device_t
pci_find_device( uint16_t vendor, uint16_t device);

int
pci_find_extcap( device_t dev, int capability, int *capreg);

int
pci_find_htcap( device_t dev, int capability, int *capreg);

int
pci_get_max_read_req( device_t dev);

int
pci_get_powerstate( device_t dev);

int
pci_get_vpd_ident( device_t dev, const char **identptr);

int
pci_get_vpd_readonly( device_t dev, const char *kw, const char **vptr);

int
pci_msi_count( device_t dev);

int
pci_msix_count( device_t dev);

int
pci_pending_msix( device_t dev, u_int index);

uint32_t
pci_read_config( device_t dev, int reg, int width);

int
pci_release_msi( device_t dev);

int
pci_remap_msix( device_t dev, int count, const u_int *vectors);

void
pci_restore_state( device_t dev);

void
pci_save_state( device_t dev);

int
pci_set_max_read_req( device_t dev, int size);

int
pci_set_powerstate( device_t dev, int state);

void
pci_write_config( device_t dev, int reg, uint32_t val, int width);

解説

pci 関数セットは、PCI デバイスの管理のために使用されます関数は、次のいくつかのグループに分割されます: 生の設定アクセス、デバイスの位置付け、デバイス情報、デバイス設定とメッセージシグナルが起こされた割り込み。

生の設定アクセス

pci_read_config() 関数は、オフセット reg において、アクセスのサイズを指定する width で、デバイス dev の PCI 設定空間からデータを読み込むために使用されます。

pci_write_config() 関数は、オフセット reg において、アクセスのサイズを指定する width で、デバイス dev の PCI 設定空間へ値 val を書き込むために使用されます。

: デバイスドライバは、別の pci() 関数によって利用可能でない機能に関してのみ、これらの関数を使用するべきです。

デバイスの位置付け

pci_find_bsf() 関数は、その bus, slotfunc を与えられ、PCI デバイスの device_t を検索します。 slot 番号は、実際に、物理的なスロットに関して必ずしもその地理的な位置を示さない、バスのデバイスの数を参照します。システムに複数の PCI ドメインがあった場合、 pci_find_bsf() 関数は、最初のものだけを検索することに注意してください。実際に、それは、次と等価です:

pci_find_dbsf(0, bus, slot, func);

pci_find_dbsf() 関数は、その domain, bus, slotfunc を与えられ、PCI デバイスの device_t を検索します。 slot 番号は、実際に、物理的なスロットに関して必ずしもその地理的な位置を示さない、バスのデバイスの数を参照します。

pci_find_device() 関数は、その vendordevice ID を与えられ、PCI デバイスの device_t を検索します。この検索に対して複数の一致があるかもしれないことに注意してください。この関数は、単に最初に一致するデバイスを返します。

デバイス情報

pci_find_cap() 関数は、デバイス dev のための PCI ケーパビリティレジスタのセットの最初のインスタンスを見つけるために使用されます。見つけられるケーパビリティは、 capability を通して ID によって指定されます。標準のケーパビリティ ID のための形式 PCIY_xxx の定数のマクロは、 < dev/pci/pcireg.h> で定義されています。ケーパビリティが見つかったなら、 *capreg が、ケーパビリティレジスタのセットの設定空間のオフセットに設定され、 pci_find_cap() は、0 を返します。ケーパビリティが見つからないか、またはデバイスがケーパビリティをサポートしていないなら、 pci_find_cap() は、エラーを返します。

pci_find_extcap() 関数は、デバイス dev のための PCI-express 拡張ケーパビリティレジスタのセットの最初のインスタンスを見つけるために使用されます。見つけられる拡張ケーパビリティは、 capability を通して ID によって指定されます。標準拡張ケーパビリティ ID のための形式 PCIZ_xxx の定数マクロは、 < dev/pci/pcireg.h> で定義されています。拡張ケーパビリティが見つかるなら、 *capreg は、拡張ケーパビリティレジスタのセットの設定空間のオフセットに設定され、 pci_find_extcap() は、0 を返します。拡張ケーパビリティが見つからないか、またはデバイスが PCI-express デバイスでないなら、 pci_find_extcap() は、エラーを返します。

pci_find_htcap() 関数は、デバイス dev のための HyperTransport ケーパビリティレジスタのセットの最初のインスタンスを見つけるために使用されます。見つけられるケーパビリティは、 capability を通してタイプによって指定されます。標準 HyperTransport ケーパビリティタイプのための形式 PCIM_HTCAP_xxx の定数マクロは、 < dev/pci/pcireg.h> で定義されています。ケーパビリティが見つかるなら、 *capreg は、ケーパビリティレジスタのセットの設定空間のオフセットに設定され、 pci_find_htcap() は、0 を返します。ケーパビリティが見つからないか、またはデバイスが HyperTransport デバイスでないなら、 pci_find_htcap() は、エラーを返します。

pci_get_vpd_ident() 関数は、デバイスの Vital Product Data (VPD) の識別子文字列を取って来るために使用されます。デバイス dev が VPD をサポートし、識別子文字列を提供するなら、 *identptr は、識別子文字列の読み込み専用でヌル文字で終了したコピーを指すように設定され、 pci_get_vpd_ident() は、0 を返します。デバイスが VPD をサポートしないか、または識別子文字列を提供しないなら、 pci_get_vpd_ident() は、エラーを返します。

pci_get_vpd_readonly() 関数は、デバイス dev のための単一の VPD 読み込み専用のキーワードを取って来るために使用されます。取って来るキーワードは、2 つの文字の文字列 kw によって識別されます。デバイスが VPD をサポートし、要求されたキーワードのための読み込み専用の値を提供するなら、 *vptr は、値の込み専用で、ヌル文字で終了したコピーを指すように設定され、 pci_get_vpd_readonly() は、0 を返します。デバイスが VPD をサポートしないか、要求されたキーワードが提供されないなら、 pci_get_vpd_readonly() は、エラーを返します。

デバイス設定

pci_enable_busmaster() 関数は、 PCIR_COMMAND レジスタの中で PCIM_CMD_BUSMASTEREN ビットを設定することにより、デバイス dev のための PCI バスマスタを有効にします。 pci_disable_busmaster() 関数は、このビットをクリアします。

pci_enable_io() 関数は、 PCIR_COMMAND レジスタの中で PCIM_CMD_MEMENPCIM_CMD_PORTEN ビットを適切に設定することにより、デバイス dev のためにメモリまたは I/O ポートアドレスデコード (符号化) を有効にします。 pci_disable_io() 関数は、適切なビットをクリアします。 space 引数は、どのリソース (資源) が影響されるか指定します。必要に応じて、これは、 SYS_RES_MEMORY または SYS_RES_IOPORT のいずれかでありえます。デバイスドライバは、一般的に直接これらのルーチンを使用するべきではありません。 PCI バスは、 SYS_RES_MEMORY または SYS_RES_IOPORT リソースが bus_alloc_resource(9) または bus_activate_resource(9) によって活性化されるとき、自動的なデコードを有効にします。

pci_get_max_read_req() 関数は、PCI-express デバイスのためにバイト単位で現在の最大の読み込み要求サイズを返します。 dev デバイスが PCI-express デバイスでないなら、 pci_get_max_read_req() は、0 を返します。

pci_set_max_read_req() は、 dev のための PCI-express の最大の読み込み要求サイズを設定します。要求された size は、調節され、 pci_set_max_read_req() は、バイト単位で実際のサイズの設定を返します。 dev デバイスが PCI-express デバイスでないなら、 pci_set_max_read_req() は、0 を返します。

pci_get_powerstate() 関数は、デバイス dev の現在の電源状態を返します。デバイスが電源管理ケーパビリティ (能力) をサポートしない場合、 PCI_POWERSTATE_D0 のデフォルト状態が返されます。次の電源状態は、PCI によって定義されます:

PCI_POWERSTATE_D0
デバイスがオンで実行中の状態です。それは、システムから完全な電源を受け取っており、ユーザに全部の機能を提供します。
PCI_POWERSTATE_D1
デバイス状況が失われるかどうかわからない、クラス特有の低電力の状態です。この状態のバスは、状況を見失うことをデバイスに強制するためにバスに何もすることができません。
PCI_POWERSTATE_D2
デバイス状況が失われるかどうか分からない、クラスに特有の低電力の状態です。 PCI_POWERSTATE_D1 より大きなパワーセーブ (節電) に到達します。この状態のバスは、装置にある状況を失わせる場合があります。デバイスは、バスがこの状態か高くなる準備ができていなければなりません。
PCI_POWERSTATE_D3
デバイスがオフで実行していない状態です。デバイス状況は、失われ、デバイスからの電源を落すことができます。
PCI_POWERSTATE_UNKNOWN
デバイスの状況は、不明です。

pci_set_powerstate() 関数は、PCI の電源状態 state へデバイス dev を遷移させるために使用されます。デバイスが電源管理ケーパビリティをサポートしないか、または特定の電源状態 state をサポートしないなら、関数は、 EOPNOTSUPP で失敗します。

pci_save_state() と pci_restore_state() 関数を、標準 PCI 設定レジスタを保存し復元するためにデバイスドライバによって使用することができます。 pci_save_state() 関数は、 pci_restore_state() を使用する前に、デバイスが有効な状態である間に呼び出されなければなりません。 pci_restore_state() が呼び出されるとき、デバイスが完全な電源状態 ( PCI_POWERSTATE_D0) でないなら、デバイスは、あらゆる設定レジスタが復元される前に、 PCI_POWERSTATE_D0 に遷移されます。

Message Signaled Interrupts (割り込みのシグナルを起こすメッセージ)

Message Signaled Interrupts (MSI) (割り込みのシグナルを起こすメッセージ) と Enhanced Message Signaled Interrupts (MSI-X) (増強された割り込みのシグナルを起こすメッセージ) は、割り込みのシグナルを起こす PCI デバイスのために、代替のメソッドを提供する PCI ケーパビリティです。古い INTx 割り込みは、0 のリソース ID がある SYS_RES_IRQ リソースとして PCI デバイスで利用可能です。 MSI と MSI-X 割り込みは、0 を超えるリソース ID がある 1 つ以上の SYS_RES_IRQ リソースとして PCI デバイスで利用可能です。ドライバは、MSI または MSI-X の SYS_RES_IRQ リソースを使用する前に、 pci_alloc_msi() または pci_alloc_msix() を使用して、MSI または MSI-X 割り込みを割り付けるように PCI バスに依頼しなければなりません。ドライバは、MSI または MSI-X 割り込みが割り付けられているなら、古い INTx SYS_RES_IRQ リソースを使用することを許されません、そして MSI または MSI-X 割り込みを割り付ける試みは、ドライバが現在古い INTx SYS_RES_IRQ リソースを使用しているなら、失敗します。ドライバは、両方ではなく、MSI または MSI-X のいずれかのみを使用することを許されています。

pci_msi_count() 関数は、デバイス dev によってサポートされた MSI メッセージの最大数を返します。デバイスが MSI をサポートしないなら、 pci_msi_count() は、0 を返します。

pci_alloc_msi() 関数は、デバイス dev のためのに *count MSI メッセージを割り付けることを試みます。 pci_alloc_msi() 関数は、デバイス dev のサポートより多くのメッセージために要求を含む様々な理由にために、またはシステムに利用可能な MSI メッセージの不足があるなら、要求したものより少ないメッセージを割り付けます。成功すれば、 *count は、割り付けられたメッセージの数を設定し、 pci_alloc_msi() は、0 を返します。割り付けられたメッセージのための SYS_RES_IRQ リソースは、1 で始まる連続するリソース ID で利用可能になります。 pci_alloc_msi() あらゆるメッセージを割り付けることができないなら、エラーを返します。 MSI は、2 のべき乗であるメッセージの数のみをサポートすることに注意してください ;メッセージの 2 のべき乗でない数の割り付け要求は、失敗します。

pci_release_msi() 関数は、システムに戻すためにあらゆる割り付けられた MSI または MSI-X メッセージを解放するために使用されます。あらゆる MSI または MSI-X SYS_RES_IRQ リソースがドライバによって割り付けられるか、または設定された割り込みハンドラがあるなら、この関数は、 EBUSY で失敗します。 pci_release_msi() 関数は、成功すれば、0 を返し、失敗すれば、エラーを返します。

pci_msix_count() 関数は、デバイス dev によってサポートされた MSI-X メッセージの最大数を返します。デバイスが MSI-X をサポートしないなら、 pci_msix_count() は、0 を返します。

pci_alloc_msix() 関数は、デバイス dev のために *count MSI-X メッセージを割り付けることを試みます。 pci_alloc_msix() 関数は、デバイス dev サポートより多くのメッセージのための要求を含む様々な理由のために、またはシステムに利用可能な MSI-X メッセージの不足があるなら、要求されたものより少ないメッセージを割り付けます。成功すれば、 *count は、割り付けらたメッセージの数に設定され、 pci_alloc_msix() は、0 を返します。 MSI-X メッセージについて、各 SYS_RES_IRQ リソースのためのリソース ID は、対応するメッセージの MSI-X テーブル中のインデックスを識別します。 1 のリソース ID は、MSI-X テーブルの最初のインデックスにマップします。リソース ID 2 は、テーブルなどの 2 番目のインデックスを識別します。 pci_alloc_msix() 関数は、最初の *count テーブルインデックスに割り付けられた *count メッセージを割り当てます。 pci_alloc_msix() があらゆるメッセージを割り付けることができないなら、エラーを返します。 MSI と異なり、MSI-X は、2 べき乗であるメッセージの数を要求しません。

pci_pending_msix() 関数は、テーブルインデックス index で MSI-X メッセージの保留中の状態を決定するために dev デバイスの Pending Bit Array (PBA) (ペンディングビットアレイ) を調べます。示されたメッセージが保留中であるなら、この関数は、0 以外を返します、そうでなければ、0 を返します。この関数に無効の index を渡すことは、未定義の振る舞いの結果となります。

pci_alloc_msix() の説明で述べられているように、MSI-X メッセージは、最初に最初の N テーブルエントリに割り当てられます。ドライバは、 pci_remap_msix() 関数を通してテーブルエントリへの利用可能なメッセージの異なる配布を使用するかもしれません。この関数は、 SYS_RES_IRQ リソースのいずれがが割り付けられる前に、 pci_alloc_msix() への成功した呼び出しの後に呼び出されなければならないことに注意してください。 pci_remap_msix() 関数は、成功すれば、0 を返し、失敗すれば、エラーを返します。

vectors 配列は、 count メッセージベクタ (vector) を含んでいるべきです。配列は、MSI-X テーブルの最初のエントリのために使用されるメッセージを指定する配列の最初のエントリ、MSI-X テーブルなどの 2 番目のエントリに対応する配列中の 2 番目のエントリの点において、MSI-X テーブルに直接マップされます。各配列インデックス中のベクタ値は、メッセージが対応する MSI-X テーブルエントリに割り当てられるべきでないことを示す 0 か、または対応する MSI-X テーブルエントリに割り当てられるべきである割り付けられたメッセージのどちらかを示すために、1 から N までの数値のいずれかです、 (ここで、N は、 pci_alloc_msix() への前の呼び出しから返された数です)。

pci_remap_msix() が成功するなら、0 でないベクタがある各 MSI-X テーブルエントリは、 pci_alloc_msix() のために上記で説明されるようなテーブルインデックスに対応するリソース ID である関連する SYS_RES_IRQ リソースがあります。 0 のベクタがある MSI-X テーブルエントリは、関連する SYS_RES_IRQ リソースがありません。さらに、 pci_alloc_msix() によって割り付けられたオリジナルのメッセージのいずれかが、 MSI-X テーブルのメッセージの新しい配布で使用されないなら、それらは、自動的に解放されます。ドライバが pci_alloc_msix() によって割り付けられるより少ないメッセージを使用したいなら、ドライバは、新しい配布のうちの 1 つで始まるメッセージの単一で連続する範囲を使用しなければならないことに注意してください。 pci_remap_msix() 関数は、この条件が満たされないなら、失敗します。

実装に関する注

pci_addr_t タイプは、ターゲットアーキテクチャの PCI バスアドレス空間のサイズによって変わります。

関連項目

pci(4), pciconf(8), bus_alloc_resource(9), bus_dma(9), bus_release_resource(9), bus_setup_intr(9), bus_teardown_intr(9), devclass(9), device(9), driver(9), rman(9) NewBus, FreeBSD Developers' Handbook, http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/developers-handbook/. Shanley and Anderson, PCI System Architecture, Addison-Wesley, 2nd Edition, ISBN 0-201-30974-2.

作者

このマニュアルページは、 Bruce M Simpson <bms@FreeBSD.org>と John Baldwin <jhb@FreeBSD.org>によって書かれました。

バグ

カーネルの PCI コードには、“slot 番号”への多くの参照があります。これらは、PCI デバイスの地理的な位置について参照するのではなく、 PCI IDSEL メカニズムとプラットフォームファームウェアの組み合わせで割り当てられたデバイス番号を参照します。これは、カーネルの PCI コードで動作しているとき、注意するべきです。
March 5, 2012 FreeBSD