天天看點

Linux I/O端口與I/O記憶體

一、IO端口通路 

1、直接使用IO端口操作函數

1)在裝置打開或驅動子產品被加載時申請IO端口區域,之後使用inb(),outb()等進行端口通路,最後在裝置關閉或驅動被解除安裝時釋放IO端口範圍。流程如下:

2)struct resource *request_region(unsigned long first, unsigned long n, const char *name);

        如果這段I/O端口沒有被占用,在我們的驅動程式中就可以使用它。在使用之前,必須向系統登記,以防止被其他程式占用。登記後,在/proc/ioports檔案中可以  看到你登記的io口。

  參數1:io端口的基位址。

  參數2:io端口占用的範圍。

  參數3:使用這段io位址的裝置名。

  在對I/O口登記後,就可以放心地用inb(), outb()之類的函來通路了。

        request_region()用于核心為驅動“配置設定”端口,這裡配置設定的意思是,記錄該端口已經被某個程序使用,要是其它程序試圖通路它,就會産生“忙”錯誤。是以目的在于實作資源的互斥通路。

        反之, 如果一個資源隻被一個程序通路,不會導緻資源的争用,這時request_region()是可選的。

3)void release_region(unsigned long from, unsigned long num)

        這個函數用來釋放一塊輸入輸出區域。

2、将IO端口重新映射

1)使其看起來像I/O記憶體,在裝置打開或驅動子產品被加載時,申請IO端口區域并使用ioport_map()映射到記憶體,之後使用IO記憶體的函數進行端口通路,最後,在裝置關閉或驅動子產品被解除安裝時釋放IO端口并釋放映射,流程如下:

2)void *ioport_unmap(void *addr);

        ioport_map僅僅是将port加上PIO_OFFSET(64k),而ioport_unmap則什麼都不做。這樣portio的64k空間就被映射到虛拟位址的64k~128k之間,而ioremap傳回的虛拟位址則肯定在3G之上。這樣portio和mmio的虛拟位址就被統一起來。

二、IO記憶體通路

1)首先調用request_mem_region()申請資源,接着将寄存器位址通過ioremap()映射到核心空間的虛拟位址,之後就可以Linux裝置通路程式設計接口通路這些虛拟位址了,通路完成後,使用iounmap()對申請的虛拟位址進行釋放,并釋放release_mem_region()申請的IO記憶體資源。流程如下: