轉自:http://blog.sina.com.cn/s/blog_6405313801012weg.html
A.幾乎每一種外設都是通過讀寫設備上的寄存器來進行的。外設寄存器也稱爲“I/O端口”,通常包括:控制寄存器、狀態寄存器和數據寄存器三大類,而且一個外設的寄存器通常被連續地編址。CPU對外設IO端口物理地址的編址方式有兩種:一種是I/O映射方式(I/O-mapped),另一種是內存映射方式(Memory-mapped)。而具體採用哪一種則取決於CPU的體系結構。
有些體系結構的CPU(如,PowerPC、m68k等)通常只實現一個物理地址空間(RAM)。在這種情況下,外設I/O端口的物理地址就被映射到CPU的單一物理地址空間中,而成爲內存的一部分。此時,CPU可以象訪問一個內存單元那樣訪問外設I/O端口,而不需要設立專門的外設I/O指令。這就是所謂的“內存映射方式”(Memory-mapped)。
而另外一些體系結構的CPU(典型地如X86)則爲外設專門實現了一個單獨地地址空間,稱爲“I/O地址空間”或者“I/O端口空間”。這是一個與CPU地RAM物理地址空間不同的地址空間,所有外設的I/O端口均在這一空間中進行編址。CPU通過設立專門的I/O指令(如X86的IN和OUT指令)來訪問這一空間中的地址單元(也即I/O端口)。這就是所謂的“I/O映射方式”(I/O-mapped)。與RAM物理地址空間相比,I/O地址空間通常都比較小,如x86 CPU的I/O空間就只有64KB(0-0xffff)。這是“I/O映射方式”的一個主要缺點。
Linux將基於I/O映射方式的或內存映射方式的I/O端口通稱爲“I/O區域”(I/O region)。在討論對I/O區域的管理之前,我們首先來分析一下Linux是如何實現“I/O資源”這一抽象概念的.
B.
在驅動程序編寫過程中,很少會注意到IO Port和IO Mem的區別。雖然使用一些不符合規範的代碼可以達到最終目的,這是極其不推薦使用的。
結合下圖,我們徹底講述IO端口和IO內存以及內存之間的關係。主存16M字節的SDRAM,外設是個視頻採集卡,上面有16M字節的SDRAM作爲緩衝區。
1. CPU是i386架構的情況
在i386系列的處理中,內存和外部IO是獨立編址,也是獨立尋址的。MEM的內存空間是32位可以尋址到4G,IO空間是16位可以尋址到64K。
在Linux內核中,訪問外設上的IO Port必須通過IO Port的尋址方式。而訪問IO Mem就比較羅嗦,外部MEM不能和主存一樣訪問,雖然大小上不相上下,可是外部MEM是沒有在系統中註冊的。訪問外部IO MEM必須通過remap映射到內核的MEM空間後才能訪問。
爲了達到接口的同一性,內核提供了IO Port到IO Mem的映射函數。映射後IO Port就可以看作是IO Mem,按照IO Mem的訪問方式即可。
2. CPU是ARM 或PPC架構的情況
在這一類的嵌入式處理器中,IO Port的尋址方式是採用內存映射,也就是IO bus就是Mem bus。系統的尋址能力如果是32位,IO Port+Mem(包括IO Mem)可以達到4G。
訪問這類IO Port時,我們也可以用IO Port專用尋址方式。至於在對IO Port尋址時,內核是具體如何完成的,這個在內核移植時就已經完成。在這種架構的處理器中,仍然保持對IO Port的支持,完全是i386架構遺留下來的問題,在此不多討論。而訪問IO Mem的方式和i386一致。