#language jp

''このページはWritingPortableDriversセクションの一部です。''<<BR>>

== PCIメモリアクセス ==
原文: [[http://kernelnewbies.org/AccessingPciMemory|AccessingPciMemory]]

デバイスのPCIメモリにアクセスする場合も、メモリに直接アクセスしようとしないで、汎用関数を使用してください。
PCIバスにアクセスする方法には、ハードウェアの種類によりさまざまな方法があるからです。汎用関数を使用すれば、
あなたのPCIドライバはPCIバスを持つどのようなLinuxシステム上でも動作させることができるでしょう。

PCIバスからデータを読み込むには、次の関数を使用してください。

{{{
#!cplusplus
int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val);
int pci_read_config_word(struct pci_dev *dev, int where, u16 *val);
int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val);
}}}

データを書き込むには、次の関数を使用してください。

{{{
#!cplusplus
int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
}}}

これらの関数を使用することで、PCIデバイスに割り当てられた特定のメモリ位置に8ビット、16ビット、32ビットの
データを書き込むことができます。Linux PCIコアによりまだ初期化されていないPCIデバイスのメモリにアクセスしたい
ときは、pci_hotplugコアのコードにある次の関数を使用することができます。

{{{
#!cplusplus
int pci_read_config_byte_nodev(struct pci_ops *ops, u8 bus, u8 device,
                               u8 function, int where, u8 *val);
int pci_read_config_word_nodev(struct pci_ops *ops, u8 bus, u8 device,
                               u8 function, int where, u16 *val);
int pci_read_config_dword_nodev(struct pci_ops *ops, u8 bus, u8 device,
                                u8 function, int where, u32 *val);

int pci_write_config_byte_nodev(struct pci_ops *ops, u8 bus, u8 device,
                                u8 function, int where, u8 val);
int pci_write_config_word_nodev(struct pci_ops *ops, u8 bus, u8 device,
                                u8 function, int where, u16 val);
int pci_write_config_dword_nodev(struct pci_ops *ops, u8 bus, u8 device,
                                 u8 function, int where, u32 val);
}}}

ドライバからPCIメモリを読み書きする例は、{{{drivers/usb/host/usb-ohci.c}}}のUSB OHCIドライバに見ることができます。

{{{
#!cplusplus
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
if (latency) {
        pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
        if (limit && limit < latency) {
                dbg("PCI latency reduced to max %d", limit);
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
                ohci->pci_latency = limit;
        } else {
                /* it might already have been reduced */
                ohci->pci_latency = latency;
        }
}
}}}