pci驱动与硬件通信
接上一篇博文,當(dāng)將PCI設(shè)備空間的資源映射出來(lái)之后。只需要做兩件事情,PCI設(shè)備的基本框架就建立起來(lái)了。
首先注冊(cè)驅(qū)動(dòng)程序,調(diào)用如下函數(shù):
int iosDrvInstall() / STATUS iosDevAdd()
先來(lái)講int iosDrvInstall()函數(shù):
Int iosDrvInstall(
FUNCPTR pCreate, FUNCPTR pDelete,
FUNCPTR pOpen, FUNCPTR pClose,
FUNCPTR pRead, FUNCPTR pWrite,
FUNCPTR pIoctl /*pointer to driver ioctl function*/
)
前面的文章已經(jīng)提到過(guò)。除了最后一個(gè)參數(shù)之外,其它參數(shù)都可以為NULL,最后一個(gè)參數(shù)向系統(tǒng)注冊(cè)一個(gè)應(yīng)用程序與驅(qū)動(dòng)通信的函數(shù)。應(yīng)用程序通過(guò)調(diào)用
(
int fd,
int request,
void *data
);
三個(gè)參數(shù)分別代表文件描述符,請(qǐng)求操作碼和需要傳往驅(qū)動(dòng)的數(shù)據(jù)。
假設(shè)我們?cè)诤瘮?shù)iosDrvInstall()最后注冊(cè)的IOCtl函數(shù)為:pci_Ioctl()。
pci_Ioctl(int fd, int request, void *data)
注意:這里這個(gè)函數(shù)也需要包含三個(gè)參數(shù),與ioctl的參數(shù)對(duì)應(yīng),當(dāng)在應(yīng)用層調(diào)用ioctl()函數(shù)的時(shí)候,ioctl()中的第三個(gè)參數(shù)就會(huì)根據(jù)文件描述符來(lái)識(shí)別出正確的設(shè)備并將與驅(qū)動(dòng)通信的數(shù)據(jù)寫入到驅(qū)動(dòng)中的IOCTL函數(shù)中,這里是:pci_Ioctl()。
pci_Ioctl()函數(shù)的大體框架如下:
LOCAL STATUS pci_Ioctl(int DevID,int request, void *arg){
…
Switch(request)
{
case(X1):
…
break;
case(X2):
…
break;
default:
…
}
return 1;
}
在每個(gè)分支針對(duì)傳進(jìn)來(lái)的操作碼進(jìn)行操作。操作碼一般是定義的宏,不同的操作我們定義一個(gè)不同的值來(lái)做標(biāo)識(shí)。
在case語(yǔ)句中一般需要進(jìn)行寄存器的寫入或者讀出,我們會(huì)用到下面的函數(shù):
sysInLong(int port)sysOutLong(int port, long data)
其中sysInLong()函數(shù)用于從寄存器讀出數(shù)據(jù),其中的參數(shù)為寄存器的地址。
sysOutLong()函數(shù)用于向寄存器port中寫入數(shù)據(jù)data。
還記得上面的pci_Ioctl()函數(shù)嗎,這個(gè)函數(shù)中的第三個(gè)參數(shù)就是用于讀出或者寫入數(shù)據(jù)。為了實(shí)現(xiàn)讀出或者寫入并使的這些數(shù)據(jù)能輕松在應(yīng)用程序和驅(qū)動(dòng)之間傳遞,這個(gè)參數(shù)最好入上面一樣申明為void *。
但是請(qǐng)注意:sysInLong (),sysOutLong()函數(shù)中的port參數(shù)雖然都代表寄存器地址,但是不能直接使用芯片手冊(cè)或者是FPGA設(shè)計(jì)者提供的地址,需要加一個(gè)設(shè)備基址,也就是上一篇文章中提到的“ioaddr”,這個(gè)地址是PCI設(shè)備空間的io基址。因此這兩個(gè)讀入和寫入函數(shù)一般會(huì)進(jìn)行封裝,方便操作。
可以這樣做:
#define xxxDevice_Write(reg, value) sysOutLong(ioaddr+(reg), value)#define xxxDevice_Read(reg) ((unsigned int) sysInLong(ioaddr+(reg)))
?
之后就可以直接調(diào)用這兩個(gè)宏,用于寫入或者讀出了。
?
現(xiàn)在可以介紹
iosDevAdd(DEV_HDR *pDevHdr, char *name, int drvnum)
了,我們可以這樣來(lái)調(diào)用該函數(shù):
其中第一個(gè)參數(shù)是設(shè)備抽象中的第一個(gè)參數(shù),也就是內(nèi)核中的數(shù)據(jù)結(jié)構(gòu):DEV_HDR(pDrvCtrl參見前面的文章);第二個(gè)參數(shù)是我們?yōu)樵O(shè)備取的名字,也就是一個(gè)字符串;第三個(gè)參數(shù)為iosDrvInstall()函數(shù)的返回值。因此我們需要先調(diào)用iosDrvInstall()函數(shù),再調(diào)用iosDevAdd函數(shù)。
經(jīng)過(guò)上面的介紹,驅(qū)動(dòng)的大體框架就建立好了。具體的操作就根據(jù)具體情況來(lái)進(jìn)行了。
本博客還會(huì)繼續(xù)介紹Windows下基于WDM的PCI設(shè)備驅(qū)動(dòng)程序開發(fā)和Linux下的PCI驅(qū)動(dòng)程序開發(fā)。如果有可能還會(huì)介紹Windows下WDF的PCI驅(qū)動(dòng)程序的開發(fā)。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的pci驱动与硬件通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring mvc 3.0 入门及应用
- 下一篇: 加密解密技术—对称算法加密