CH.8 硬體管理
Outline 1. I/O 埠 v.s I/O 記憶體 2. 使用I/O 埠 3. 數位I/O 埠 (並列埠) 4. 使用I/O 記憶體 5. Kernel版本相容性
I/O 埠 v.s I/O 記憶體 I/O 暫存器 & 傳統記憶體 (RAM) 最大差別: I/O 操作有副作用 ,記憶體操作沒有 記憶體存取速度對CPU 效能影響致為關鍵(ex: Cache,重新安排read/ write 指令順序) for 傳統記憶體: 最佳化存取速度是有益的 for I/O暫存器: 干擾到I/O指令的副作用,可能發生錯誤 Solution: 設 memory barrier ,讓compiler知道這段程式 不要最佳化
Memory barrier #include <linux/kernel.h> void barrier (void); #include <asm/system.h> void rmb (void); /保證在barrier前的read動作都完成/ void wmb (void);/保證在barrier前的write動作都完成/ void mb (void); P.S memory barrier會影響效率,真正需要才使用
Memory barrier的用法 writel (dev->registers.addr, io_destination_address); writel (dev->registers.size, io_size); writel (dev->registers.operation, DEV_READ); wmb (); writel (dev->registers.control, DEV_GO); 確認所有動作皆完成 write memory barrier
使用I/O 埠(1/3) 驅動程式用I/O埠前,必須先配置他們,才可讀or寫埠 <asm/io.h>定義用來存取I/O埠的內插函式 #include <linux/ioport.h> int check_region(unsigned long start,unsigned long len); struct resource *request_region(unsigned long start,unsigned long len,char *name); void release_region(unsigned long start,unsigned long len);
使用I/O 埠(2/3) For 1 byte 埠 unsigned inb(unsigned port); void outb(unsigned char byte,unsigned port); For 16bits埠 (word寬度) unsigned inw(unsigned port); void outw(unsigned short word,unsigned port); For 32bits埠 (longword寬度) unsigned inl(unsigned port); void outl(unsigned longword,unsigned port);
使用I/O 埠(3/3) String instruction 暫停I/O 平台相依性 有些processor 有提供字串指令,讓一連串同大小的bytes,words,long 讀or寫到I/O埠, 達到迴圈效果 暫停I/O 舊裝置如ISA跟不上處理器的傳輸速度,需要暫停函式,如: inb_p() ,outb_p() 平台相依性 I/O指令和處理器有高度相依性,必須針對特定平台(ex: Alpha ,ARM, PowerPC, SPARC…)
範例程式demo 範例: ~/ldd2/misc-progs/inp.c 目的: 示範在user-space 讀出I/O port Step1: make all Step2: cat /proc/ioports Step3: 比較和我們在user-space讀出來的資訊是否一樣
數位I/O 埠(1/2) 把值寫出到輸出埠,會被轉換成對應輸出腳位的電子信號 每台PC 都有兩個並列埠,第一個介面從0X378開始;第二個從0X278開始 每個並列埠都有三個暫存器: 資料暫存器(bidirectional to pin2~pin9) 狀態暫存器(read-only) 控制暫存器(output-only) 唯一與腳位信號無關:控制埠的 bit4 (0x10),可發出irq See figure below…
數位I/O 埠(2/2)
使用I/O記憶體 I/O記憶體只是類似RAM的特殊區域,不同的是處理器可從其匯流排存取特定硬體裝置 Driver必須要求kernel將實體位址搬入driver的可見範圍,所以要先呼叫ioremap() 直接映射記憶體 ex: PDA用的MIPS處理器,內有兩段位置範圍(各512 Mb)直接映射到實體位址,在此區MMU不會理會,也無Cache. 軟體映射I/O記憶體 PCI裝置的位置是由系統軟體指派,每次開機都會不同,所以要用ioremap()將虛擬位址指向裝置
Kernel版本相容性 Linux 2.0 無硬體memory barrier ,但只要引入sysdep.h,將硬體屏障定義成跟軟體屏障一樣 只要引入sysdep.h,就可在舊kernel上使用ioremap Memory management的三個函式 check_mem_region() request_mem_region() release_mem_region()