LINUX設備驅動之PCI設備驅動_第1頁
LINUX設備驅動之PCI設備驅動_第2頁
LINUX設備驅動之PCI設備驅動_第3頁
LINUX設備驅動之PCI設備驅動_第4頁
LINUX設備驅動之PCI設備驅動_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、LINUX設備驅動之PCI設備wan gxy該文檔是整理PCI驅動時參考網(wǎng)上資料編寫,供大家參考交流學習。1) PCI總線總線由電氣接口和編程接口組成。先介紹PCI總線的電氣接口。該總線具有 以下特性: 總線位寬為32位,可擴充到64位,數(shù)據(jù)總線和地址總線復用。 總線的時鐘頻率為33MHz隨著PCI總線的發(fā)展,總線的時鐘頻率在提 高,PCI-X 1.0 總線的時鐘頻率為 66MHz/100MHz/133MH到 PCI-X 2.0 的時候,總線的時鐘頻率發(fā)展到 266MHz/533MHz/1066M,不過PCI總 線和PCI-X總線硬件結構上完全兼容。 支持全自動配置,資源分配,即插即用。 總線

2、規(guī)范獨立于微處理器,通用性好。 PCI設備可以完全作為主控設備控制總線。 采用中央集中式總線仲裁。2) PCI設備引腳介紹AID|i AR|PARPAH.M付擴充(RbVD卜、£1丄IDSELSIX*Ni:伸尿(只有總it匸擰同iltvtCLKH5T11)1Tlx、TCKTKsT圖(一) PCI兼容設備引腳示意圖在一個PCI應用系統(tǒng)中,如果某個PCI設備獲得了 PCI總線的控制權,就稱 該設備是主設備,被主設備選中以進行數(shù)據(jù)傳輸?shù)腜CI設備稱為從設備,對于PCI兼容設備的引腳主要分為兩部分:必需引腳和可選引腳。對應主設 備至少需要49個引腳,對應從設備至少需要 47個引腳。必需部分對

3、應圖(一) 中的左側部分,可選部分對應圖(一)中右側部分。PCI兼容設備引腳共有100根,下面對這些信號進行 介紹,介紹前先對 引腳信號的類型做一個簡介。PCI引腳信號按照數(shù)據(jù)傳輸?shù)姆较蚝碗娐夫寗拥奶?性分為五種類型。 in:輸入信號 out:輸出信號 t/s:雙向三態(tài)I/O驅動信號(三態(tài):高電平、低電平和高阻抗) s/t/s:持續(xù)雙向三態(tài)I/O驅動信號,表示持續(xù)且低電平有效的三態(tài)信號。在某個時刻只可屬于一個主設備,并被其驅動。這種信號從低電平到高阻 抗之前,必需保證至少在一個時鐘周期處于高電平狀態(tài),即低電平-> 至少一個時鐘周期高電平-> 高阻抗。另一個主設備要驅動該信號,至少要

4、 等該信號的原有驅動者將其釋放(變?yōu)楦咦杩範顟B(tài))一個時鐘周期后,才能 開始。如果這種信號處于非驅動狀態(tài),在有新主設備驅動它之前應采取上拉措施, o/d:漏極開路即高阻狀態(tài),適用于輸入/輸出,其可獨立輸入/輸出低電 平和高阻狀態(tài),若需要產(chǎn)生高電平,則需使用外部上拉電阻??勺骶€或,允許多個設備共同使用。F面對各個引腳信號做介紹信號標識信號名稱信號類型概述CLK時鐘in為PCI兼容設備上的接口提供時鐘信 號及總線的仲裁提供時序,PCI-2.2規(guī) 范中最高時鐘頻率33MHz,除了 RST 和四個中斷引腳外,其它引腳信號都 是在CLK上升沿采樣,所有的時間參 數(shù)都是基于這個上升沿而定義的。CLK最小頻率

5、0Hz。RST復位信號in使PCI特定的寄存器、配置寄存器和 定時器相關的信號置于一個固定的狀 態(tài)。所有的PCI引腳信號驅動到它的 起始狀態(tài)。通常情況下,意味著這些引腳處 于高阻態(tài),SERR被浮空,REQ和GNT 都必須是高阻態(tài),如果不能提供高阻 態(tài)輸出的話,就把SBO和SDONE驅 動到低電平狀態(tài)。為防止數(shù)據(jù)地址線 ADxx、C/BEx、PAR 引腳在復位 期間被浮空,如果要使用,也只能驅 動到低電平。REQ64在復位結束后有 效。AD31-0地址數(shù)據(jù)線t/s在FRAME有效時,是地址周期, AD31-0包含一個總線地址,對于配 置空間和儲存器空間,這是一個雙字 地址,對于I/O空間,這是一

6、個字節(jié) 地址,高位 AD31-24低位 AD7-0; 在IRDY和TRDY同時有效時,是數(shù)據(jù)周期,一次PCI總線的傳輸中包含 了一個地址信號周期和1個數(shù)據(jù)周 期。C/BE3-0總線命令和 字節(jié)使能信 號t/s在地址周期內(nèi),這四條線上傳輸?shù)氖?總線命令,在數(shù)據(jù)周期,傳輸?shù)氖亲?節(jié)使能信號,表示在整個數(shù)據(jù)周期, AD31-0上哪些字節(jié)為有效數(shù)據(jù)。PAR奇偶校驗 信號t/sAD31-0和C/BE3-0上的數(shù)據(jù)奇偶 校驗,通常PCI傳輸時要求奇偶校驗。PAR與AD31-0有相同的時序,但延 時一個時鐘周期,在地址周期后一個 時鐘周期,PAR穩(wěn)定且有效。對于數(shù) 據(jù)周期,在寫傳輸過程中,PAR在IRDY有

7、效后延遲一個時鐘周期穩(wěn)定 且有效,一旦PAR有效,在數(shù)據(jù)周期 完成后的一個時鐘周期內(nèi)它必須保持 有效。在讀傳輸中,PAR在TRDY有 效后延遲一個時鐘周期穩(wěn)定且有效, 一旦PAR有效,在數(shù)據(jù)周期完成后的 一個時鐘周期內(nèi)它必須保持有效。 在地址周期和寫數(shù)據(jù)周期,總線的主 設備驅動PAR,在讀數(shù)據(jù)周期,目標 設備驅動PAR。FRAME幀周期信號s/t/s由總線的主設備驅動,表示一次 PCI 傳輸?shù)拈_始和持續(xù)時間,F(xiàn)RAME有 效表示總線傳輸開始,當FRAME持 續(xù)有效說明總線傳輸繼續(xù)進行。當 FRAME無效表示正在傳輸?shù)淖詈笠?個字節(jié)。IRDY主設備準備 好信號s/t/s該信號有效表明主設備已經(jīng)具

8、有完成 一次PCI傳輸?shù)哪芰?,該信號需與 TRDY信號配合使用,這二者都有效 才能進行數(shù)據(jù)傳輸,否則即為等待周 期,在寫周期,該信號有效表示 AD31-0線上數(shù)據(jù)已經(jīng)建立,在讀周 期,該信號有效表示主設備已經(jīng)準備 好接收數(shù)據(jù)。TRDY從設備準備 好信號s/t/s該信號有效表明從設備已經(jīng)做好完成 當前數(shù)據(jù)傳輸?shù)臏蕚涔ぷ?,同樣該?號需與IRDY配合使用,二者同時有 效才能進行數(shù)據(jù)傳輸,在寫周期,該 信號有效表示從設備做好接收數(shù)據(jù)準 備,在讀周期,該信號有效表示數(shù)據(jù) 已經(jīng)送到AD31-0線上,同理,二者任何一個無效時都為等待周期。STOP從設備要求 停止當前數(shù) 據(jù)傳輸信號s/t/s該信號有效,表示

9、從設備要求主設備 停止當前數(shù)據(jù)傳輸操作。LOCK總線鎖定信 號s/t/s鎖定操作只針對PCI橋設備,鎖定表 明一個需要多次傳輸才能完成的原子 操作。該信號有效,對一個沒有處于 鎖疋狀態(tài)的PCI橋設備來說表示 個 非獨占的傳輸正在進行。在PCI總線 上,允許開始一次傳輸并不代表擁有 對LOCK信號的控 制權。取得對 LOCK信號的控制權要遵循一些協(xié)議 和GNT信號的配合。DEVSEL從設備選中信號s/t/s該信號有效,從設備已經(jīng)解碼主設備 發(fā)出的地址。IDSEL初始化設備 選擇信號in配置空間讀寫時的片選信號。PERR數(shù)據(jù)奇偶校 驗錯誤報告 信號s/t/s該引腳只用于反饋在除特殊周期外的 其它傳

10、輸過程中的數(shù)據(jù)奇偶校驗錯 誤,PERR維持三態(tài),在檢測到傳輸 數(shù)據(jù)中的奇偶校驗錯誤后,在傳輸數(shù) 據(jù)結束后的兩個時鐘周期內(nèi),由接收 數(shù)據(jù)的單元驅動PERR有效,至少要 持續(xù)一個時鐘周期。在被釋放到三態(tài) 前,PERR必須驅動到高電平一個時 鐘周期,只有發(fā)出DEVSEL的單元才 能發(fā)出PERR。SERR系統(tǒng)出錯信 號o/d用于反饋地址奇偶錯誤、特殊周期命 令中的數(shù)據(jù)奇偶錯誤和將引起重大事 故的其它災難行的系統(tǒng)錯誤,如果一 個設備不想產(chǎn)生不可屏蔽(NMI),就 可以用SERR信號反饋給總線。SERR 是單純的漏極開路信號,由反饋錯誤 的設備驅動,在一個總線時鐘周期內(nèi) 有效,SERR與總線時鐘同步,并滿

11、 足所有總線信號的建立與保持時間的 要求,SERR信號釋放到無效狀態(tài)由 系統(tǒng)設計者提供上拉電阻實現(xiàn),從無 效狀態(tài)恢復到有效狀態(tài)需2-3個時鐘 周期,支持SERR的設備在采樣到 SERR有效時,就向操作系統(tǒng)報告系 統(tǒng)錯誤。REQ總線請求信 號t/s該信號只對主設備有效,是一個點對 點信號,用于向仲裁器說明某個主設備想使用總線。GNT總線允許信 號t/s該信號僅對主設備有效,也是一個點 對點信號,仲裁器想申請總線的主設 備說明其對總線的操作已經(jīng)得到批 準。INTA中斷A信號o/d常用于單一功能設備請求一次中斷。INTB中斷B信號o/d用于多功能設備請求一次中斷。備注一INTC中斷C信號o/d:用于

12、多功能設備請求一次中斷。INTD中斷D信號o/d用于多功能設備請求一次中斷。SBO監(jiān)視補償信 號in /out該信號有效,說明對某修改行的一次 命中,所訪問的數(shù)據(jù)無效,當SBO信 號無效而SDONE信號有效,說明PCI 主設備正在訪冋存儲器的有效行并可 進行高速緩存的操作。SDONE監(jiān)視完成信 號in /out表示處理器CACHE對主存的監(jiān)視狀 態(tài),無效表示監(jiān)視仍在進行,否則便 是監(jiān)視已完成。AD63-32地址數(shù)據(jù)復 用硬件t/s提供32個附加位,在地址周期(使用 DAC指令且REQ64已有效)傳輸64 位地址的咼32位,如果沒有咼32位 地址,這些引腳就被保留,其上的數(shù) 據(jù)是穩(wěn)疋的,但值是不

13、確疋的,在數(shù) 據(jù)周期,當REQ64和ACK64都有效 時,傳輸64位數(shù)據(jù)中的高32位。C/BE7-4總線命令和 字節(jié)允許復 用信號t/s在一個地址周期(使用DAC指令且 REQ64已有效)在C/BE7-4傳輸?shù)氖?有效的總線命令;如無,這些引腳被 保留,其值不確定,在數(shù)據(jù)周期當REQ64和 ACK64都有效時, C/BE7-4是字節(jié)允許,說明哪些字節(jié)上含有有效數(shù)據(jù)。REQ64請求傳輸 64位數(shù)據(jù) 信號t/s當其被當前總線的主設備有效驅動 時,說明該總線的主設備想做64位的 傳輸,REQ64和FRAME有相同的時 序,復位結束后,若REQ64有效,該 設備就已連接64位通道上,否則無。ACK64

14、64位傳輸 的應答信號s/t/s從設備驅動該信號,說明從設備能夠 進行64位數(shù)據(jù)傳輸,ACK64和 DEVSEL有相同的時序。PAR64高偶校驗信 號t/s是 AD63-32和 C/BE7-4的偶校驗 位,當REQ64有效且C/BE7-4上有DAC命令時,第一地址周期后的一個 時鐘周期PAR64有效,DAC命令的 第二個地址周期后的那一個時鐘周期PAR64也有效,在數(shù)據(jù)周期中,當 REQ64和ACK64都有效時,讀操作 中,TRDY有效后,PAR64穩(wěn)定且有 效,在寫操作中,IRDY有效后,PAR64 穩(wěn)定且有效。一旦PAR64 有效,必須 保持有效指導數(shù)據(jù)周期完成后一個時 鐘周期的時間。(P

15、AR64時序與 AD63-32相同但延遲一個時鐘周 期),在地址周期和寫數(shù)據(jù)周期內(nèi),總 線主設備驅動PAR64,在讀數(shù)據(jù)周期 內(nèi),從設備驅動 PAR64。備注二TDI測試數(shù)據(jù)輸 入信號in將測試數(shù)據(jù)和測試指令串行移入到設 備中。TDO測試輸出信 號out將測試數(shù)據(jù)和測試指令串行移出到設 備。TCK測試時鐘信 號in記錄狀態(tài)信息和測試設備的輸入輸出 數(shù)據(jù)。TMS測試模式選 擇in控制設備中的JTAG控制器狀態(tài)。TRST測試復位信 號in異步初始化JTAG控制器備注一多功能設備的任何一種功能都能連接到任何一條中短線上,中斷引腳寄存器決定該功能用那一條中斷線去請求中斷。如果一個設備只用了一條中斷線,

16、就是用INTA,如果用兩條就使用INTA和INTB,依,此類推。對于多功能設備,可以是所有功能用一條中斷線,也可以每種功能使用自己的中斷線,最多四種 功能。備注二在總線主設備和從設備之間,64位傳輸是動態(tài)協(xié)商的,在每個地址周期進行一次,而且,只有主存命令支持64位傳輸,總線主設備使 REQ64有效,從設備則通過使 ACK64有效加以應答,REQ64和ACK64都 是外部上拉的,保證 64位和32位單元混用,一旦64位傳輸建立,就一直保持到這次傳輸結束。3) PCI總線上的操作總線命令總線命令是由主設備發(fā)向從設備,其作用是規(guī)定主設備正在請求的傳輸類型,在地址周期,被編碼的總線命它出現(xiàn)在C/BE3

17、-0引腳上,從設備的地址出現(xiàn)在AD地址數(shù)據(jù)復用引腳上。C/BE3-0命令類型命令作用0000中斷應答是一個讀命令,主設備從申請中斷的從設備中讀取中斷向量。0001特殊周期通報處理器狀態(tài)或在各個從設備之間傳遞信息。0010I/O讀從一個映射到I/O地址空間的設備中讀取數(shù)據(jù)。0011I/O寫向一個映射到I/O地址空間的設備中讀取數(shù)據(jù)。0100保留留作將來使用,任何設備也不允許對保留命令做出反應。0101保留留作將來使用,任何設備也不允許對保留命令做出反應。0110存儲器讀從一個映射到內(nèi)存空間的設備上讀取數(shù)據(jù)。0111存儲器寫向一個映射到內(nèi)存空間的設備上寫入數(shù)據(jù)。1000保留留作將來使用,任何設備也

18、不允許對保留命令做出反應。1001保留留作將來使用,任何設備也不允許對保留命令做出反應。1010配置讀從每個設備的配置空間讀取數(shù)據(jù)。1011配置寫向每個設備的配置空間寫入數(shù)據(jù)。1100儲存器多行讀試圖在主設備斷開連接之前讀取多行高速緩存的數(shù)據(jù),內(nèi)存控制器應保證,只要FRAM有效,就連續(xù)不斷地發(fā)內(nèi)存讀取請求,該命令預定用于大塊連續(xù)數(shù)據(jù)的傳輸。1101雙地址周期該命令用于傳輸 64位地址給支持64位尋址的設備,只支持 32位尋址的設備 不對該命令做岀反應。1110存儲器一行讀該命令與內(nèi)存讀命令不同之處在于它還表示主設備要求讀取多于2個32位的數(shù)據(jù)周期,即一次讀取緩存范圍內(nèi)一行上的所有數(shù)據(jù)。1111

19、存儲器寫和無效該命令與內(nèi)存寫命令的不同之處是它要保證最小的傳輸量是一個高速緩存行, 主設備要在一次PCI傳輸中,寫完被尋址的高速緩存行的全部字節(jié)。命令的使用規(guī)則所有PCI設備都是配置(讀和寫)命令的目標設備,必須做出應答。對 其他的命令則有選擇余地,I/O讀或寫命令是可選的。命令執(zhí)行規(guī)則 保證I/O讀或寫命令的執(zhí)行順序。有重定位功能或寄存器的目標設備 要求能通過配置寄存器映射到存儲器空間,并響應基本的存儲器讀或 寫命令,這就為沒有I/O空間(僅X86處理器有)設備的使用提供了一 種選擇。當這種映射實現(xiàn)時,無論設備映射到I/O空間還是存儲器命令執(zhí)行規(guī)則都由系統(tǒng)設計者來保證。總線主設備可以根據(jù)需要

20、使用任選指令,從設備也可根據(jù)需要而選 用指令,但如果選用了基本指令,就必須支持所有存儲器命令,包括 高速緩存寫命令、高速緩存行讀命令和存儲器多行讀命令。如果不能 全部使用,這些為優(yōu)化性能而設的命令必需轉化為基本的存儲器命令。例如,一個從設備可以不實現(xiàn)存儲器行讀命令,但是它必須能接 受該命令的請求 ,并按存儲器讀命令來處理。同理,一個從設備可 以不實現(xiàn)存儲器寫但它必須能接受該命令的請求, 并按存儲器寫命令 來處理。對于進/ 出系統(tǒng)存儲器的塊數(shù)據(jù)傳輸,對能支持高速緩存寫和高速 緩存行讀命令的主設備,建議采用這兩天命令,如果由于某種原因, 總線主設備不能使用性能已優(yōu)化的命令, 就用存儲器讀和存儲器寫

21、命 令。對于使用存儲器讀命令的總線主設備,對所有命令都可作任意長 度的操作, 但最優(yōu)方法如下, 如果高速緩存寫命令要求實現(xiàn)高速緩存 行范圍寄存器,存儲器讀命令也使用它, 使用高速緩存行范圍寄存器時的最優(yōu)方法: 存儲器讀命令:當突發(fā)傳輸少于半條高速緩存行數(shù)據(jù)時使用。 高速緩存行存儲器讀命令: 當突發(fā)傳輸半條到三條高速緩存行數(shù)據(jù)時 使用。 存儲器重復讀命令:當突發(fā)傳輸三條以上高速緩存行數(shù)據(jù)時使用。 不使用高速緩存行范圍寄存器時的最優(yōu)方法: 存儲器讀命令:當突發(fā)傳輸兩個或更少數(shù)據(jù)時使用。 高速緩存行存儲器讀命令:當突發(fā)傳輸三到 12 個數(shù)據(jù)時使用。 存儲器重復讀命令:長突發(fā)傳輸數(shù)據(jù)時使用。PCI 協(xié)

22、議基礎在 PCI 總線上, 總線的基本傳輸機制是突發(fā)傳輸, 一個突發(fā)傳輸由一 個地址周期和大于等于一個數(shù)據(jù)周期組成。 PCI 總線支持內(nèi)存空間和I/O地址空間的突發(fā)傳輸。PCJ pr*durlCompofinri &«3b F maiq5V 32-bil PCI Cardc3 3V&1U PCI Card】ii川川 iriiiiiiiiiii【川川汕川iiiiiiiiiiiiiii川riiuiiiiiiiiiiiii川jmumu miuminimm F5V &4-W PCi CardLw mnmnim umiUnivsal I3 3V & 5V) 64

23、巾ii PCI Cax川iiniiL川丄一;iru小ii川川hi川川3.3V 34-btl PClSlol5V 32-brt PCI Slot5V54-bi1 PCI Slot編程接口:每個PCI設備由一個總線編號、一個設備編號及一個功能編號來標識, PCI規(guī)范 允許單個系統(tǒng)擁有高達256個總線,linux目前支持PCI域,每個PCI域可擁有 最多256個總線,每個總線可支持32個設備,每個設備可具有最多8個功能。每種功能都可以在硬件級由一個16位的地址來標識。驅 動程序使用pci_dev 數(shù)據(jù)結構來訪問設備??偩€上每個外設擁有三個地址空間:內(nèi)存位置、I/O端口和配置寄存器,內(nèi)存位 置和I/O

24、端口由同一 PCI總線上的所有設備共享,大多數(shù)PCI總線上的外設會把寄存器映射到某個內(nèi)存地址區(qū)段,此時的內(nèi)存地址 區(qū)段就是I/O內(nèi)存。分析I/O端口和I/O內(nèi)存的區(qū)別:MIPS、ARM和 PowerPC等平臺的I/O和主存采用的是統(tǒng)一編址的方式,它們將 I/O空間映射到內(nèi)存,采用與內(nèi)存相同的匯編指令(load和store)來讀寫設備, 這種方式稱為I/O內(nèi)存;x86平臺的I/O和主存采用的是獨立編址的方式,CPU 有專門的線路來訪問I/O,而且有專門的匯編 指令(in和out)來讀寫設備,這 種方式稱為I/O端口。每種外設都是通過讀寫寄存器進行控制。 在硬件層,內(nèi)存區(qū)域和I/O區(qū)域沒有概 念上

25、的區(qū)別,他們都是通過向地址總線和控制總線發(fā)送電平信號進行訪問, 再通 過數(shù)據(jù)總線讀寫數(shù)據(jù)。每個PCI槽有四個中斷引腳,每個外設功能可使用一個,中斷線共享,PCI總線中的I/O空間使用32位地址總線,PCI配置空間中每個設備功能有256個字節(jié)組成(PCI-E有4KB的配置空間),配置寄存器的布 局是標準化的(64)注意是小端模式。vendorlD :用于表示硬件制造商的16位寄存器。Device ID :由制造商選擇,該ID通常與Ven dor ID生成一個唯一的32位硬件 設備標識符,class :每個外設都屬于一個類.類寄存器是一個16-位值,它的高8位標識" 基類"(或

26、者群).例如,"ethernet" 和"token ring" 是2個類都屬于"network" 群,而"serial" 和"parallel"屬于"communication"群.一些驅動可支持幾個類似的設備,每個都有一個不同的簽名但是都屬于同樣的類;這些驅動可依賴類 寄存器標識它們的外設。subsystem ven dorIDsubsystem deviceID這些字段可用來進一步標識一個設備.如果芯片對于本地總線是一個通 用接口芯片,它常常被用在幾個完全不同的地方,并且

27、驅動必須標識出 它在與之通話的實際設備.子系統(tǒng)標志用作此目的.使用這些不同的標識符,一個PCI驅動可告知內(nèi)核它支持什么類型的設備. struct pci_device_id結構被用來定義一個驅動支持的不同類型PCI設備的列表這個結構包含不同的成員:u32 ven dor;u32 device;這些指定一個設備的PCI供應商和設備ID.如果驅動可處理任何供應 商或者設備ID,值PCI_ANY_ID應當用作這些成員上.u32 subvendor;u32 subdevice;這些指定一個設備的 PCI 子系統(tǒng)供應商和子系統(tǒng)設備 ID. 如果驅動可 處理任何類型的子系統(tǒng) ID, 值 PCI_ANY_I

28、D 應當用作這些成員上 ._u32 class;_u32 class_mask;這 2 個值允許驅動來指定它支持一類 PCI 類設備 . 不同的 PCI 設備類 ( 一個 VAG 控制器是一個例子 ) 在 PCI 規(guī)范里被描述 . 如果一個驅動 可處理任何子系統(tǒng) ID, 值 PCI_ANY_ID 應當用作這些字段 .kernel_ulong_t driver_data;這個值不用來匹配一個設備 , 但是用來持有信息 , PCI 驅動可用來區(qū)分 不同的設備 , 如果它想這樣 .有 2 個幫助宏定義應當被用來初始化一個 struct pci_device_id 結構 :PCI_DEVICE(ven

29、dor, device)這個創(chuàng)建一個 struct pci_device_id ,它只匹配特定的供應商和設備ID. 這個宏設置這個結構的子供應商和子設備成員為 PCI_ANY_ID.PCI_DEVICE_CLASS(device_class, device_class_mask)這個創(chuàng)建一個 struct pci_device_id, 它匹配一個特定的 PCI 類.一個使用這些宏來定義一個驅動支持的設備類型的例子 , 在下面的內(nèi)核 文件中可找到 :drivers/usb/host/ehci-hcd.c:static const struct pci_device_id pci_ids = /*

30、 handle any USB 2.0 EHCI controller */PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB << 8) | 0x20), 0), .driver_data = (unsigned long) &ehci_driver, /* end: all zeroes */ ;drivers/i2c/busses/i2c-i810.c: static struct pci_device_id i810_ids = PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810

31、_IG1) , PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) , PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) , PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) , PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) , 0, , ;這些例子創(chuàng)建一個 struct pci_device

32、_id 結構的列表 , 列表中最后一 個是被設置為全零的的空結構 . 這個 ID 的數(shù)組用在 struct pci_driver ( 下面講述 ), 并且它還用來告訴用戶空間這個特定的驅動支 持哪個設備 .這個 pci_device_id 結構需要被輸出到用戶空間 , 來允許熱插拔和模塊 加載系統(tǒng)知道什么模塊使用什么硬件設備宏MODULE_DEVICE_TAB完E 成這個.例如:MODULE_DEVICE_TABLE(pci, i810_ids);這個語句創(chuàng)建一個局部變量稱為 _mod_pci_device_table,它指向struct pci_device_id 的列表. 稍后在內(nèi)核建立過

33、程中 , depmod 程序在 所有的模塊中尋找 _mod_pci_device_table.如果找到這個符號 , 它將數(shù)據(jù)拉出模塊并且添加到文件 /lib/modules/KERNEL_VERSION/modules.pcimap. 在 depmod 完成后 , 所有的被內(nèi)核中的模塊支持的 PCI 設備被列出 , 帶有它們的模塊名子 , 在那個文件中 . 當內(nèi)核告知熱插拔系統(tǒng)有新的 PCI 設備已找到 , 熱插拔 系統(tǒng)使用 moudles.pcimap 文件來找到正確的驅動來加載 .注冊一個 PCI 驅動為了被正確注冊到內(nèi)核 , 所有的 PCI 驅動必須創(chuàng)建的主結構是 struct pci_

34、driver 結構 . 這個結構包含許多函數(shù)回調(diào)和變量 , 來描述 PCI 驅 動給 PCI 核心 . 這里是這個結構的一個 PCI 驅動需要知道的成員 :const char *name;驅動的名子 . 它必須是唯一的 , 在內(nèi)核中所有 PCI 驅動里面 . 通常被設 置為和驅動模塊名子相同的名子 . 它顯示在 sysfs 中在 /sys/bus/pci/drivers/下, 當驅動在內(nèi)核時 .const struct pci_device_id *id_table;指向 struct pci_device_id 表的指針 , 在本章后面描述它 .int (*probe) (struct p

35、ci_dev *dev, const struct pci_device_id *id);指向 PCI 驅動中 probe 函數(shù)的指針 . 這個函數(shù)被 PCI 核心調(diào)用 , 當它 有一個它認為這個驅動想控制的 struct pci_dev 時. 一個指向 struct pci_device_id 的指針 , PCI 核心用來做這個決定的 , 也被傳遞給這個 函數(shù). 如果這個 PCI 驅動需要這個傳遞給它的 struct pci_dev, 它應 當正確初始化這個設備并且返回 0. 如果這個驅動不想擁有這個設備 , 或者產(chǎn)生一個錯誤 , 它應當返回一個負的錯誤值 . 關于這個函數(shù)的更多 的細節(jié)在本

36、章后面 .void (*remove) (struct pci_dev *dev);指向 PCI 核心在 struct pci_dev被從系統(tǒng)中去除時調(diào)用的函數(shù)的指針或者當 PCI 驅動被從內(nèi)核中卸載時 . 關于這個函數(shù)的更多的細節(jié)在本章 后面.int (*suspend) (struct pci_dev *dev, u32 state);當 struct pci_dev 被掛起時 PCI 核心調(diào)用的函數(shù)的指針 . 掛起狀態(tài)在 state 變量里傳遞 . 這個函數(shù)是可選的 ; 一個驅動不必提供它 .int (*resume) (struct pci_dev *dev);當 pci_dev 被恢

37、復時 PCI 核心調(diào)用的函數(shù)的指針 . 它一直被調(diào)用在調(diào) 用掛起之后 . 這個函數(shù)時可選的 ; 一個驅動不必提供它 .總之, 為創(chuàng)建一個正確的 struct pci_driver 結構, 只有 4 個字段需 要被初始化 :例如:static struct pci_device_id wctdm_pci_tbl = 0xe159, 0x0001, 0xb100, PCI_ANY_ID, 0, 0, (unsigned long)&wctdmi , 0 ;MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);static struct pci_driver wct

38、dm_driver = .name = "ax4g",.probe = wctdm_init_one,.remove =_devexit_p(wctdm_remove_one),.suspend = NULL,.resume = NULL,.id_table = wctdm_pci_tbl,;注冊驅動程序, 注意 , pci_register_driver函數(shù)要么返回一個負的錯誤碼, 要么是 0 當所有都成功注冊 . 它不返回綁定到驅動上的設備號 , 或 者一個錯誤碼如果沒有設備被綁定到驅動上。static int _ _init wctdm_init(void) int

39、res;res = pci_register_driver(&wctdm_driver); if (res)return -ENODEV;return 0;注銷驅動程序,當 PCI 驅動被卸載 , struct pci_drive 需要從內(nèi)核中注 銷. 這通過調(diào)用 pci_unregister_driver完成 . 當發(fā)生這個調(diào)用 , 任何當前綁定到這個驅動的 PCI 設備都被去除 , 并且這個 PCI 驅動的 remove 函數(shù)在 pci_unregister_driver 函數(shù)返回之前被調(diào)用 .static void _exit wctdm_cleanup(void) pci_un

40、register_driver(&wctdm_driver); 在 PCI 驅動的探測函數(shù)中 , 驅動可存取 PCI 設備的任何設備資源 (I/O 區(qū)或者 中斷) 前, 驅動必須調(diào)用 pci_enable_device 函數(shù):int pci_enable_device(struct pci_dev *dev);這個函數(shù)實際上使能設備 . 它喚醒設備以及在某些情況下也分配它的中 斷線和 I/O 區(qū) .在驅動已探測到設備后 , 它常常需要讀或寫 3 個地址空間 : 內(nèi)存 , 端口, 和配置 . 特別地, 存取配置空間對驅動是至關重要的 , 因為這是唯一的 找到設備被映射到內(nèi)存和 I/O 空

41、間的位置的方法 .因為微處理器無法直接存取配置空間 , 計算機供應商不得不提供一個方 法來完成它 . 為存取配置空間 , CPU 必須寫和讀 PCI 控制器中的寄存器 , 但是確切的實現(xiàn)是依賴于供應商的 , 并且和這個討論無關 , 因為 Linux 提供了一個標準接口來存取配置空間 .對于驅動, 配置空間可通過 8-位, 16- 位, 或者 32- 位數(shù)據(jù)傳輸來存取 . 相關的函數(shù)原型定義于 <linux/pci.h>:int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val); int pci_read_co

42、nfig_word(struct pci_dev *dev, int where, u16 *val);int pci_read_config_dword(struct pci_dev *dev, int where, u32*val);從由 dev 所標識出的設備的配置空間讀 1 個, 2 個或者 4 個字節(jié). where 參數(shù)是從配置空間開始的字節(jié)偏移 . 從配置空間取得的值通過 val 指針返回 , 并且這個函數(shù)的返回值是一個錯誤碼 . word 和 dword 函數(shù)轉換剛剛讀的值從小端到處理器的本地字節(jié)序 , 因此你不必處理字 節(jié)序.int pci_write_config_byte(

43、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, u32val);寫 1 個 , 2 個或者 4 個字節(jié)到配置空間 . 象通常一樣 , 設備由 dev 所 標識, 并且象通常一樣被寫的值被傳遞 . word 和 dword 函數(shù)轉換這個 值到小端 , 在寫到外設之前 .所有的之前的函數(shù)被實現(xiàn)為真正調(diào)用下列函數(shù)的內(nèi)聯(lián)

44、函數(shù) . 可自由使用 這些函數(shù)代替上面這些 , 如果這個驅動在任何特別時刻不能及時存取 struct pci_dev :int pci_bus_read_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 *val);int pci_bus_read_config_word (struct pci_bus *bus, unsigned intdevfn, int where, u16 *val);int pci_bus_read_config_dword (struct pci_bus *bus, unsign

45、ed intdevfn, int where, u32 *val);就象 pci_read_function 一樣 , 但是 struct pci_bus * 和 devfn 變量 需要來代替 struct pci_dev *.int pci_bus_write_config_byte (struct pci_bus *bus, unsigned int devfn, int where, u8 val);int pci_bus_write_c on fig_word (struct pci_bus *bus, un sig ned int devfn, int where, u16 val);int pci_bus_write_config_dword(struct pci_bus *bus, unsigned intdevfn, int where, u32 val);如同pci_write_ 函數(shù),但是struct pci_bus * 和devfn 變量需要來 替代 struct pci_dev *使用pci_read_函數(shù)尋址配置變量的最好方法是通過定義在<linux/pci.h>中的符號名.例如,下面的小函數(shù)獲取一個設

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論