摘 要: PCI局部總線具有使用方便,、數(shù)據(jù)傳輸率高等特點,,已成為計算機必備的一種接口。Linux是一種日趨成熟完善的操作系統(tǒng),,越來越多的軟硬件廠商開始使用Linux平臺開發(fā)自己的產(chǎn)品,,因而對基于該平臺的設備驅(qū)動程序的需求也愈來愈多。介紹了Linux驅(qū)動程序開發(fā)的一般方法,,并實現(xiàn)了流媒體數(shù)據(jù)緩存PCI卡在Linux環(huán)境下的驅(qū)動程序,。
關鍵詞: Linux操作系統(tǒng); PCI總線; 設備驅(qū)動; 流媒體數(shù)據(jù)緩存卡
隨著通用處理器和嵌入式技術的迅猛發(fā)展,越來越多的電子設備需要由處理器控制,。目前大多數(shù)CPU和外部設備都會提供PCI總線的接口,,PCI總線已成為計算機系統(tǒng)中一種應用廣泛、通用的總線標準[1],。Linux因其開放源代碼以及穩(wěn)定的性能,,越來越受到廣大用戶青睞。同時,,基于Linux內(nèi)核的嵌入式操作系統(tǒng)應用勢頭強勁,,開發(fā)基于Linux的設備驅(qū)動程序,具有很強的實用性和可移植性[2],。
1 PCI總線概述
PCI(Peripheral Component Interconnect)總線,,即外部設備互連,是現(xiàn)在流行的一種連接PC和外圍設備的總線結構[3],。PCI提供了一組完整的總線接口規(guī)范,,可以在33 MHz時鐘頻率、32 bit數(shù)據(jù)總線寬度的條件下達到峰值132 Mb/s的傳輸速率;它能支持一種稱為線性突發(fā)的數(shù)據(jù)傳輸模式,,可確??偩€不斷滿載數(shù)據(jù);采用總線主控與同步操作,,顯著改善PCI的性能,;PCI獨立于處理器的結構,用戶可隨意增添外圍設備,,以擴展電腦系統(tǒng)而不必擔心在不同時鐘頻率下會導致性能下降,。
2 PCI設備驅(qū)動程序的設計與實現(xiàn)
Linux中將設備分成字符設備、塊設備和網(wǎng)絡設備三種類型,通過主設備號和從設備號實現(xiàn)對設備的描述,。其中主設備號描述控制該設備的驅(qū)動程序,,即驅(qū)動程序與主設備號一一對應,從設備號用來區(qū)分同一個驅(qū)動程序控制的不同設備[5],。
PCI設備屬于字符設備,。本設計采用模塊方式實現(xiàn)PCI卡驅(qū)動程序。驅(qū)動程序主要由設備注冊和注銷,、設備探測和移除,、設備中斷處理和系統(tǒng)調(diào)用等函數(shù)組成。
2.1 設備注冊和注銷
使用一個設備之前,必須保證己經(jīng)對它進行注冊,,這項工作一般是在設備初始化時完成,。設備初始化函數(shù)中調(diào)用函數(shù)register_chrdev()來注冊字符設備。流媒體數(shù)據(jù)緩存PCI卡驅(qū)動程序的注冊代碼如下:
#define MAJOR_NUM 128
register_chrdev(MAJOR_NUM,,"pci_card",,&pci_card_fops);
將設備的主設備號設為128,設備名稱為pci_card。pci_card_fops是一個file_operations結構指針,這個結構是設備驅(qū)動程序所提供的入口點位置,,在設備注冊時向系統(tǒng)進行登記,,以便系統(tǒng)在適當時調(diào)用。pci_card_fops定義如下:
static struct file_operations pci_card_fop={
owner:THIS_MODULE,,
open:pic_card_open,,
release:pic_card_release,
read:pic_card_read,,
write:pic_card_write,,
ioctl:pic_card_ioctl
};
當不再使用此設備時,需調(diào)用unregister_chrdev()函數(shù)注銷驅(qū)動程序,。
2.2 設備探測和移除
在掃描到新的PCI設備后,,系統(tǒng)需要調(diào)用設備驅(qū)動程序?qū)崿F(xiàn)的探測函數(shù)以查找與設備相匹配的PCI驅(qū)動。流媒體數(shù)據(jù)緩存PCI卡設備驅(qū)動的探測函數(shù)pic_card_probe()的主要實現(xiàn)代碼如下:
pci_card = kmalloc(sizeof(struct pci_card),,GFP_KERNEL);
//為設備實例分配存儲空間
pci_enable_device(dev); //激活PCI設備
spin_lock_init(pci_card ->lock);
//初始化特定設備實例的私有化數(shù)據(jù)
pci_read_config_byte(dev,,PCI_REVISION_ID,(u8*)&(pci_
card ->rev_id)); //讀取配置信息
pci_card->mem_base=pci_resource_start(dev,, 0);
//讀取I/O資源的配置信息
pci_request_regions(dev,,"pic_card"); //申請I/O區(qū)域
pci_set_master(dev); //設置成總線主模式
pic_card->mem_start=ioremap(pic_card->mem_base,
pic_card->mem_size); // I/O內(nèi)存映射
設備移除函數(shù)主要完成釋放映射的虛擬地址,、釋放I/O區(qū)域,、關閉PCI設備和釋放為設備實例分配的內(nèi)核空間等功能。
2.3 中斷處理
流媒體數(shù)據(jù)緩存卡驅(qū)動中的中斷處理程序主要負責識別中斷,、響應中斷和喚醒睡眠的進程,,中斷處理代碼如下:
inl(pci_card->iobase+PCI_CARD_INT_STA); // 識別中斷
outl(status&INT_MASK,, pci_card->iobase + PCI_CARD_
INT_STA); //響應中斷
wake_up_interruptible(&pci_card->wq); //喚醒睡眠進程
2.4 系統(tǒng)調(diào)用
用戶進程利用系統(tǒng)調(diào)用對設備文件進行諸如read/write操作時,系統(tǒng)調(diào)用通過設備文件的主設備號找到相應的設備驅(qū)動程序,,然后讀取這個數(shù)據(jù)結構相應的函數(shù)指針,接著把控制權交給該函數(shù),。流媒體數(shù)據(jù)緩存PCI卡的系統(tǒng)調(diào)用函數(shù)主要包括設備的打開、關閉,、讀寫和控制等,。
在使用PCI設備之前,必須先打開所要使用的PCI設備,。當用戶在應用程序中調(diào)用open()函數(shù)時,應用程序就會自動進入驅(qū)動程序中的pci_card_open()函數(shù),。pic_card_open()函數(shù)主要負責增加模塊的使用計數(shù),,并根據(jù)pic_card_probe()讀到的中斷號申請中斷,注冊中斷處理程序,。具體實現(xiàn)如下:
MOD_INC_USE_COUNT
request_irq(pci_card->irq,,pci_card_interrupt,SA_SHIRQ,,"pci_card",,pci_card));
在使用完PCI設備后,必須關閉PCI設備,。當用戶在應用程序中調(diào)用close()函數(shù)時,,應用程序就會自動進入驅(qū)動程序中的pci_card_release()函數(shù)。pci_card_release()函數(shù)的主要工作是釋放中斷和減少模塊的使用計數(shù),。
用戶在應用程序中調(diào)用read()函數(shù)和write()函數(shù)對設備文件進行讀寫操作時,,應用程序就會自動進入驅(qū)動程序中的pci_card_read()函數(shù)和pci_card_write()函數(shù)。pci_card_read()函數(shù)首先會阻塞在以pci_card->wq為隊頭的等待隊列上,。當流媒體數(shù)據(jù)緩存卡上的數(shù)據(jù)準備好,,即pci_card->state變?yōu)镽EADY時,pci_card_read()函數(shù)會被喚醒,。函數(shù)被喚醒后,,會先將數(shù)據(jù)從設備I/O內(nèi)存拷貝到內(nèi)核空間,再從內(nèi)核空間拷貝給用戶進程,,實現(xiàn)方式如下:
wait_event_interruptible(pci_card->wq,,pci_card->state==READY);
memcpy_fromio(pbuf,pci_card->mem_start,,count);
copy_to_user(buf,,pbuf,count)),;
而pci_card_write()函數(shù)的主要工作是將數(shù)據(jù)從用戶進程拷貝到內(nèi)核空間,,再將內(nèi)核空間中的數(shù)據(jù)拷貝到設備I/O內(nèi)存,,實現(xiàn)代碼如下:
copy_from_user(pbuf,buf,,count);
memcpy_toio(pci_card->mem_start,,pbuf,count),;
Linux是一種日趨成熟完善的操作系統(tǒng),,PCI總線已成為計算機系統(tǒng)中一種應用廣泛、通用的總線標準,。本文針對流媒體數(shù)據(jù)緩存卡設備,,結合PCI總線的特點,開發(fā)實現(xiàn)了流媒體數(shù)據(jù)緩存PCI卡在Linux環(huán)境下的設備驅(qū)動程序,,本文介紹的驅(qū)動原理同樣適用其他PCI設備的開發(fā),。
參考文獻
[1] 陳穎,唐超. 基于PCI總線驅(qū)動程序設計方法研究[J].微計算機信息,,2008,,12(1):272-274.
[2] 李善平,劉文峰,,王煥龍. Linux與嵌入式系統(tǒng)[M].北京:清華大學出版社,,2003.
[3] 宋有泉,高小鵬,,龍翔. 嵌入式PCI網(wǎng)卡驅(qū)動程序的設計與優(yōu)化[J]. 計算機工程,,2007,3(2):264-266.
[4] 王峰,,張文軍,,余松煜. PCI設備驅(qū)動程序中幾個關鍵問題的設計與實現(xiàn)[J]. 測控技術,2002,,21(8):58-60.
[5] 錢晨,,徐榮華,王欽若. 基于Linux操作系統(tǒng)的設備驅(qū)動程序開發(fā)[J]. 微計算機信息,,2004,,20(9):131-133.