Linuxのドライバで使われるioread/iowrite
、read/write
、read_relaxed/write_relaxed
の違いをまとめます。
カーネルは、5.16.9を参考にしています。
アーキテクチャによって、内部実装が異なることに注意してください。
ioread/iowrite
memory mapped I/O (I/O memory) or port mapped I/Oにアクセスする際に使用します。
ioread*/iowrite*関数は、与えられたアドレスがmemory mapped I/Oかport mapped I/Oかを判定してレジスタのリード/ライトを行います。
内部的には、read*
or in*
/ write*
or out*
を呼び出しています。
memory mapped I/Oにアクセスする際、addr
にはioremap()で取得したアドレスを与えます。
unsigned int ioread8(const volatile void __iomem *addr);
unsigned int ioread16(const volatile void __iomem *addr);
unsigned int ioread32(const volatile void __iomem *addr);
void iowrite8(u8 value, volatile void __iomem *addr);
void iowrite16(u16 value, volatile void __iomem *addr);
void iowrite32(u32 value, volatile void __iomem *addr);
read/write
型チェックを行っていないこれらの関数の使用は、現在は推奨されていません。
armアーキテクチャの場合、これらの関数はマクロで定義されており、型チェックを行っていません。
内部的には、read*_relaxed
/ write*_relaxed
の呼び出しを行っています。read*_relaxed
の呼出し後にメモリバリアがあり、レジスタの読み込み順序が保護されます。write*_relaxed
を呼び出す前にメモリバリアがあり、レジスタの書き込み順序が保護されます。
unsigned int readb(addr);
unsigned int readw(addr);
unsigned int readl(addr);
void writeb(unsigned value, address);
void writew(unsigned value, address);
void writel(unsigned value, address);
メモリバリア参考:
ハードウェアレベルへのアクセス順序が変わらないことを保証する。ハードウェアは書き出す/読
み込むデータだけでなく、アクセスのタイミング、順序も重要な要素となるため、たとえ非効率で
あったとしてもその順序を維持する必要がある。
read_relaxed/write_relaxed
レジスタの読み込み/書き込み順序が保証されないが、順序を保証しないでデータの読み書きを行いたい場合に使用します。
unsigned int readb_relaxed(addr);
unsigned int readw_relaxed(addr);
unsigned int readl_relaxed(addr);
void writeb_relaxed(unsigned value, address);
void writew_relaxed(unsigned value, address);
void writel_relaxed(unsigned value, address);