日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Linux設(shè)備驅(qū)動程序中的一些具體問題

 lchjczw 2012-04-06

1。 I/O Port

和硬件打交道離不開I/O Port,老的ISA設(shè)備經(jīng)常是占用實際的I/O端口,在linux下,操作系統(tǒng)沒有對I/O口屏蔽,也就是說,任何驅(qū)動程序都可對任意的I/O口操作,這樣就很容易引起混亂。每個驅(qū)動程序應(yīng)該自己避免誤用端口。

有兩個重要的kernel函數(shù)可以保證驅(qū)動程序做到這一點。

1)check_region(int io_port, int off_set)

這個函數(shù)察看系統(tǒng)的I/O表,看是否有別的驅(qū)動程序占用某一段I/O口。

參數(shù)1:io端口的基地址,

參數(shù)2:io端口占用的范圍。

返回值:0 沒有占用, 非0,已經(jīng)被占用。

2)request_region(int io_port, int off_set,char *devname)

如果這段I/O端口沒有被占用,在我們的驅(qū)動程序中就可以使用它。在使用之前,必須向系統(tǒng)登記,以防止被其他程序占用。登記后,在/proc/ioports文件中可以看到你登記的io口。

參數(shù)1:io端口的基地址。

參數(shù)2:io端口占用的范圍。

參數(shù)3:使用這段io地址的設(shè)備名。

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

在一些pci設(shè)備中,I/O端口被映射到一段內(nèi)存中去,要訪問這些端口就相當于訪問一段內(nèi)存。經(jīng)常性的,我們要獲得一塊內(nèi)存的物理地址。

2。內(nèi)存操作

在設(shè)備驅(qū)動程序中動態(tài)開辟內(nèi)存,不是用malloc,而是kmalloc,或者用get_free_pages直接申請頁。釋放內(nèi)存用的是kfree,或free_pages。 請注意,kmalloc等函數(shù)返回的是物理地址!

注意,kmalloc最大只能開辟128k-16,16個字節(jié)是被頁描述符結(jié)構(gòu)占用了。

內(nèi)存映射的I/O口,寄存器或者是硬件設(shè)備的RAM(如顯存)一般占用F0000000以上的地址空間。在驅(qū)動程序中不能直接訪問,要通過kernel函數(shù)vremap獲得重新映射以后的地址。

另外,很多硬件需要一塊比較大的連續(xù)內(nèi)存用作DMA傳送。這塊程序需要一直駐留在內(nèi)存,不能被交換到文件中去。但是kmalloc最多只能開辟128k的內(nèi)存。

這可以通過犧牲一些系統(tǒng)內(nèi)存的方法來解決。

 3。中斷處理

同處理I/O端口一樣,要使用一個中斷,必須先向系統(tǒng)登記。

int request_irq(unsigned int irq ,void(*handle)(int,void *,struct pt_regs *),

unsigned int long flags, const char *device);

irq: 是要申請的中斷。

handle:中斷處理函數(shù)指針。

flags:SA_INTERRUPT 請求一個快速中斷,0 正常中斷。

device:設(shè)備名。

如果登記成功,返回0,這時在/proc/interrupts文件中可以看你請求的中斷。

4。一些常見的問題。

對硬件操作,有時時序很重要。但是如果用C語言寫一些低級的硬件操作的話,gcc往往會對你的程序進行優(yōu)化,這樣時序會發(fā)生錯誤。如果用匯編寫呢,gcc同樣會對匯編代碼進行優(yōu)化,除非用volatile關(guān)鍵字修飾。最保險的辦法是禁止優(yōu)化。這當然只能對一部分你自己編寫的代碼。如果對所有的代碼都不優(yōu)化,你會發(fā)現(xiàn)驅(qū)動程序根本無法裝載。這是因為在編譯驅(qū)動程序時要用到gcc的一些擴展特性,而這些擴展特性必須在加了優(yōu)化選項之后才能體現(xiàn)出來。

 

由于設(shè)備種類繁多,相應(yīng)的設(shè)備驅(qū)動程序也非常之多。盡管設(shè)備驅(qū)動程序是內(nèi)核的一部分,但設(shè)備驅(qū)動程序的開發(fā)往往由很多人來完成,如業(yè)余編程高手、設(shè)備廠商等。為了讓設(shè)備驅(qū)動程序的開發(fā)建立在規(guī)范的基礎(chǔ)上,就必須在驅(qū)動程序和內(nèi)核之間有一個嚴格定義和管理的接口,例如SVR4提出了DDI/DDK規(guī)范,其含義就是設(shè)備與驅(qū)動程序接口/設(shè)備驅(qū)動程序與內(nèi)核接口(Device-Driver Interface/Driver-Kernel Interface)。通過這個規(guī)范,可以規(guī)范設(shè)備驅(qū)動程序與內(nèi)核之間的接口。

 

Linux的設(shè)備驅(qū)動程序與外接的接口與DDI/DKI規(guī)范相似,可以分為三部分:

(1)   驅(qū)動程序與內(nèi)核的接口,這是通過數(shù)據(jù)結(jié)構(gòu)file_operations來完成的。

(2)   驅(qū)動程序與系統(tǒng)引導(dǎo)的接口,這部分利用驅(qū)動程序?qū)υO(shè)備進行初始化。

(3)   驅(qū)動程序與設(shè)備的接口,這部分描述了驅(qū)動程序如何與設(shè)備進行交互,這與具體設(shè)備密切相關(guān)。

 

根據(jù)功能,驅(qū)動程序的代碼可以分為如下幾個部分:

(1)驅(qū)動程序的注冊和注銷

(2)設(shè)備的打開與釋放

(3)設(shè)備的讀和寫操作

(4)設(shè)備的控制操作

(5)設(shè)備的中斷和查詢處理

前三點我們已經(jīng)給予簡單說明,后面我們還會結(jié)合具體程序給出進一步的說明。關(guān)于設(shè)備的控制操作可以通過驅(qū)動程序中的ioctl()來完成,例如,對光驅(qū)的控制可以使用cdrom_ ioctl()。

與讀寫操作不同,ioctl()的用法與具體設(shè)備密切相關(guān),例如,對于軟驅(qū)的控制可以使用floppy_ioctl(),其調(diào)用形式為:

static int floppy_ioctl(struct inode *inode, struct file *filp,

unsigned int cmd, unsigned long param)

其中cmd的取值及含義與軟驅(qū)有關(guān),例如,F(xiàn)DEJECT表示彈出軟盤。

除了ioctl(),設(shè)備驅(qū)動程序還可能有其他控制函數(shù),如lseek()等。

對于不支持中斷的設(shè)備,讀寫時需要輪流查詢設(shè)備的狀態(tài),以便決定是否繼續(xù)進行數(shù)據(jù)傳輸,例如,打印機驅(qū)動程序在缺省時輪流查詢打印機的狀態(tài)。如果設(shè)備支持中斷,則可按中斷方式進行

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多