Linux 驅動程式的 I/O, #2: I/O 存取相關函數

jollen 發表於 December 20, 2006 10:57 PM

I/O 存取相關函數

要提到「I/O 處理」當然要整理 Linux 提供的相關函數,以下分 3 大類來整理:

1. I/O port
2. I/O memory
3. PCI configuration space
4. ioremap

I/O Port

以下是 Linux 提供最原始的 I/O port 存取函數:

˙ unsigned inb(unsigned port);
˙ unsigned inw(unsigned port);
˙ unsigned inl(unsigned port);
˙ void outb(unsigned char byte, unsigned port);
˙ void outw(unsigned short word, unsigned port);
˙ void outl(unsigned long word, unsigned port);

I/O Memory

以下是 Linux 提供最原始的 I/O memory 存取函數:

˙ unsigned readb(unsigned port);
˙ unsigned readw(unsigned port);
˙ unsigned readl(unsigned port);
˙ void writeb(unsigned char byte, unsigned port);
˙ void writew(unsigned short word, unsigned port);
˙ void writel(unsigned long word, unsigned port);

對於 I/O memory 的操作,Linux 也提供 memory copy 系列函數如下:

˙ memset_io(address, value, count);
˙ memcpy_fromio(dest, source, num);
˙ memcpy_toio(dest, source, num);

以上在「Linux 驅動程式觀念解析, #6: 依流程來實作 -- Physical Device Driver」介紹過一次,並且也搭配了一個簡單範例做說明,您可參考該文。

PCI Configuration Space

Linux 也提供讀寫 PCI configuration space(PCI BIOS)的函數:

˙ int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val);
˙ int pci_read_config_word(struct pci_dev *dev, int where, u16 *val);
˙ int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val);
˙ int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
˙ int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
˙ int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);

有些朋友可能看過開頭是 pcibios_* 的函數版本,「不過這是舊的函數,請勿再使用」。

ioremap()

這個 API 就重要到不行了,任何時候,Linux device driver 都「不能直接存取 physical address」。所以,「使用以上的 I/O 相關函數時,只能傳 virtual address,不能傳入 physical address」,ioremap() 就是用來將 physical address 對應到 virtual address 的 API。

小結

對於 I/O 函數的使用,應該在「深諳」Linux驅動程式架構與Linux作業系統原理的情況下使用,「單純的 kernel module + IO APIs」並不叫做 Linux 驅動程式,再更進一步的「kernel module + read/write/ioctl + IO APIs」也只是小聰明(編註),還是稱不上 Linux「驅動程式」。建構在作業系統裡的驅動程式,90% 都是在實作良好的機制與行為,因此「OS 原理與機制的研究」,才是正確的思考方向。與大家分享自己的心得,希望對您的學習有幫助。

編註:這是 Linux device driver 的「開始」但不是全部,也只是冰山一角。但是許多教育訓練機構的課程卻是以此為做為規劃方向,並不是很妥當。

Also See

讀者留言 (1)

  • 小頑童 於 October 27, 2014 02:23:

    您好,
    想請問一下

    我本身只有USB mini driver的經驗
    當這樣的driver想跟USB device溝通
    除了知道OS可跟底層bus driver溝通的usb R/W API函數外
    最重要的還要知道該USB device的command格式(各家公司格式不同)
    這樣才能拼出合法的command buffer來跟底層device做R/W reg溝通

    請問這樣的觀念在PCI device是否有不同呢?
    因為我看PCI device driver都會使用
    ioremap的方式, 將PCI之記憶體印射到本機端
    直接對該Register操作
    完全沒所謂的command格式...

    請問這樣的觀念是正確的嗎
    勞煩您解惑了
    感謝

留言功能維護中。將於近日重新開放。

連絡作者

Jollen Chen,Moko365(仕橙3G教室)講師,熱愛研究 Linux 與 Android 技術。曾為 Motorola、HTC、Foxconn、LG、OPPO、騰迅、廣達電腦、緯創、仁寶等超過 50 家企業講授課程。目前在 MokoVersity 擔任軟體工程師,撰寫 Node.js 程式,也在幾家科技廠兼任 Android Framework 研發顧問。您可透過電子郵件 <jollen (at) jollen (dot) org> 或這裡與我連絡。