 Linux平臺(tai)下pci總線驅(qu)動
							時間:2018-08-16      來(lai)源:未知
							Linux平臺(tai)下pci總線驅(qu)動
							時間:2018-08-16      來(lai)源:未知 
							Pci總線介紹
PCI總線(xian)是(shi)一種高性能(neng)局部總線(xian),是(shi)為了滿(man)足外(wai)設間以(yi)及外(wai)設與主機間高速數據傳(chuan)輸而提出(chu)來(lai)的。
PCI總(zong)線(xian)系統要求有一個PCI控(kong)制卡(ka),它必須安裝在一個PCI插槽內。根據(ju)實現(xian)方(fang)式不同(tong),PCI控(kong)制器可以與CPU一次交換32位或64位數據(ju),它允許智(zhi)能PCI輔(fu)助適配器利(li)用一種總(zong)線(xian)主控(kong)技(ji)術(shu)與CPU并行(xing)地執行(xing)任務。PCI允許多路復用技(ji)術(shu),即(ji)允許一個以上的電子信號同(tong)時存在于(yu)總(zong)線(xian)之上。
每(mei)個(ge)(ge)(ge)(ge)PCI設(she)(she)備(bei)有(you)許多地址配置(zhi)的寄存(cun)器,初始化時(shi)要通過這些寄存(cun)器來配置(zhi)該(gai)設(she)(she)備(bei)的總線地址,一(yi)旦完成(cheng)配置(zhi)以(yi)后,CPU就(jiu)可以(yi)訪問該(gai)設(she)(she)備(bei)的各項資源了。PCI標準規定(ding)每(mei)個(ge)(ge)(ge)(ge)設(she)(she)備(bei)的配置(zhi)寄存(cun)器組多可以(yi)有(you)256個(ge)(ge)(ge)(ge)連續的字(zi)節(jie)空間,開頭64個(ge)(ge)(ge)(ge)字(zi)節(jie)叫頭部,分為0型(xing)(PCI設(she)(she)備(bei))和(he)1型(xing)(PCI橋)頭部,頭部開頭16個(ge)(ge)(ge)(ge)字(zi)節(jie)是(shi)設(she)(she)備(bei)的類型(xing)、型(xing)號(hao)和(he)廠商等。
PCI總線(xian)架構
所(suo)(suo)(suo)有的根總線(xian)都鏈(lian)接(jie)在pci_root_buses鏈(lian)表中。Pci_bus ->device鏈(lian)表鏈(lian)接(jie)著(zhu)該總線(xian)下的所(suo)(suo)(suo)有設備。而pci_bus->children鏈(lian)表鏈(lian)接(jie)著(zhu)它的下層總線(xian),對(dui)于pci_dev來(lai)說,pci_dev->bus指向它所(suo)(suo)(suo)屬的pci_bus. Pci_dev->bus_list鏈(lian)接(jie)在它所(suo)(suo)(suo)屬bus的device鏈(lian)表上。此外,所(suo)(suo)(suo)有pci設備都鏈(lian)接(jie)在pci_device鏈(lian)表中。
Linux下(xia)PCI驅動的代碼模型(xing)
一個(ge)通(tong)過(guo)PCI總線與系統連接(jie)的設(she)(she)備(bei)的驅動主要包括兩部分:第(di)(di)一PCI總線驅動,第(di)(di)二(er),設(she)(she)備(bei)本(ben)身(shen)的驅動,包括字(zi)符設(she)(she)備(bei),網(wang)絡設(she)(she)備(bei),tty設(she)(she)備(bei),音頻設(she)(she)備(bei)等(deng)。PCI驅動的核(he)心是pci_driver,在探測函(han)數中完(wan)成資源的申(shen)請(qing),并(bing)注冊相(xiang)應的字(zi)符設(she)(she)備(bei),網(wang)絡設(she)(she)備(bei),tty設(she)(she)備(bei),音頻設(she)(she)備(bei)等(deng)。以下代碼(ma)以三星平臺s3c24XX為例,
static struct pci_device_id buttons_pci_tbl[] __initdata={
{PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0,}
}; //PCI設備支持項(xiang)
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
//中斷處(chu)理程(cheng)序
}
static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
}
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
}
static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c24xx_buttons_open,
.release = s3c24xx_buttons_close,
.read = s3c24xx_buttons_read,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
static int pci_key__probe (struct pci_dev *pdev, const struct pci_device_id *ent)
{
int ret;
pci_enable_device(pdev); //使(shi)能PCI設備
pci_set_master(pdev);
ret = misc_register(&misc); //注冊雜項(xiang)設備
printk (DEVICE_NAME"\tinitialized\n");
return ret;
}
static int pci_key__remove (struct pci_dev *pdev, const struct pci_device_id *ent)
{
pci_disable_device(pdev);
misc_deregister(&misc);
return 0;
}
static struct pci_driver pci_key_driver = {
.name = "pci_key",
.id_table =buttons_pci_tbl,
.probe = pci_key__probe,
.remove = pci_key__remove,
};
static int __init dev_init(void)
{
return pci_register_driver(&pci_key_driver);
}
static void __exit dev_exit(void)
{
pci_unregister_driver(&pci_key_driver);
}
module_init(dev_init);
module_exit(dev_exit);
PCI I/O和PCI內存地(di)址(zhi)
這(zhe)兩個地址空(kong)間(jian)(jian)用來實現PCI設(she)備(bei)和Linux核心中設(she)備(bei)驅動(dong)程序之間(jian)(jian)的(de)通(tong)訊。例(li)如DEC21141快速以(yi)太網設(she)備(bei)的(de)內部寄(ji)(ji)存器(qi)(qi)被(bei)映射到PIC I/O空(kong)間(jian)(jian)上時,其對應的(de)Linux設(she)備(bei)驅動(dong)可以(yi)通(tong)過對這(zhe)些(xie)寄(ji)(ji)存器(qi)(qi)的(de)讀寫來控(kong)制此設(she)備(bei)。PCI視頻卡通(tong)常使用大(da)量的(de)PCI內存空(kong)間(jian)(jian)來存儲視頻信息。
在(zai)PCI系統建立并(bing)通過用PCI配(pei)(pei)(pei)置(zhi)頭(tou)中(zhong)的命令域來打開(kai)這(zhe)些地(di)(di)址空(kong)間(jian)前(qian),系統決不允許對(dui)它們(men)進行存取。值得注意的是只(zhi)有PCI配(pei)(pei)(pei)置(zhi)代碼讀取和(he)寫(xie)(xie)入PCI配(pei)(pei)(pei)置(zhi)空(kong)間(jian),Linux設(she)(she)備(bei)驅動只(zhi)讀寫(xie)(xie)PCI I/O和(he)PCI內(nei)存地(di)(di)址。 那是因為當系統初始化階段完(wan)成后,每(mei)個PCI設(she)(she)備(bei)的地(di)(di)址空(kong)間(jian)都已經應設(she)(she)在(zai)PCI總線上了,驅動程序直接通過總線地(di)(di)址就(jiu)可(ke)以訪問PCI設(she)(she)備(bei),當然也可(ke)以去讀寫(xie)(xie)配(pei)(pei)(pei)置(zhi)空(kong)間(jian),但這(zhe)沒有必(bi)要。
以(yi)上(shang)只(zhi)是(shi)PCI部分的簡介,可以(yi)參考《linux內核情(qing)景分析》PCI驅(qu)動一章(zhang),講(jiang)得非常詳細。

