CPU通過硬件設(shè)備的寄存器讀寫設(shè)備IO。
對(duì)X86平臺(tái),這些寄存器位于專門的IO空間中,稱為IO端口;而對(duì)于其他大多是CPU,IO寄存器是映射到普通內(nèi)存中,沒有劃出特別的空間,因此稱作IO內(nèi)存。
對(duì)IO端口的操作流程
op1=>operation: request_region
op2=>operation: inb(),outb()等
op3=>operation: release_region
op1->op2->op3
對(duì)IO內(nèi)存操作
op1=>operation: request_mem_region
op2=>operation: ioremap()
op3=>operation: inb(),outb()等
op4=>operation:
op5=>operation: release_mem_region
op1->op2->op3->op4->op5
可見IO內(nèi)存操作比IO端口多一個(gè)io映射的動(dòng)作:
void *ioremap(unsigend long *add, unsigned long size)
對(duì)IO端口的操作函數(shù)主要是inb/w/l,outb/w/l等。
以及連續(xù)讀寫 insb/w/l、outsb/w/l等。
對(duì)于非x86的CPU,一般都是用IO內(nèi)存方法,讀寫接口如下:
unsigned int readb/w/l(addr)
writeb/w/l(value, addr)
//LDD中建議使用下面接口,因?yàn)闀?huì)進(jìn)行類型檢查,更加安全
unsigned int ioread8/16/32(addr)
void iowrite8/16/32(value, addr)
void ioread8/16/32/_rep(addr, buf, count) //連續(xù)讀寫
void iowrite8/16/32/_rep(addr, buf, count)
//整塊操作, 與對(duì)應(yīng)C庫函數(shù)意義相似
void memset_io(addr, value, count)
void memcpy_fromio(dest, source, count)
void memcpy_toio(dest, source, count)
關(guān)于IO屏障的問題,
為了防止硬件優(yōu)化帶來的讀寫亂序而是用內(nèi)存屏障
相關(guān)函數(shù)有 rmb() wmb() mb()等。
參考內(nèi)核源碼,readb,writeb等函數(shù)已經(jīng)使用了屏障,因此不需要再寫一次:
linux-3.18.27\arch\arm\include\asm\io.h
/* IO barriers */
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#include <asm/barrier.h>
#define __iormb() rmb()
#define __iowmb() wmb()
#else
#define __iormb() do { } while (0)
#define __iowmb() do { } while (0)
#endif
//-----------------------------------------------------------------------------
#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
#define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); })
上面 CONFIG_ARM_DMA_MEM_BUFFERABLE 這個(gè)宏,是在內(nèi)核編譯時(shí)配置的,有相關(guān)說明:
Historically, the kernel has used strongly ordered mappings to
provide DMA coherent memory. With the advent of ARMv7, mapping
memory with differing types results in unpredictable behaviour,
so on these CPUs, this option is forced on.
大概是說對(duì)arm中采用strongly ordered mappings的cpu不需要內(nèi)存壁障,否則就要增加 內(nèi)存壁障來保證安全。