亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: pci_request_regions是干啥的,在驅(qū)動中需要調(diào)用嗎? [打印本頁]

作者: Cyberman.Wu    時(shí)間: 2009-02-20 14:59
標(biāo)題: pci_request_regions是干啥的,在驅(qū)動中需要調(diào)用嗎?
今天看Linux內(nèi)核中自帶的e1000網(wǎng)卡驅(qū)動,發(fā)現(xiàn)它在probe中有如下操作:
    if ((err = pci_request_regions(pdev, e1000_driver_name)))
        return err;


但看代碼好像這里主要是把BAR0~BAR5分配到的幾個(gè)物理地址根據(jù)類似掛到iomem_resource或ioport_resource里面,從實(shí)現(xiàn)看感覺就是一個(gè)單向排序的鏈表。這個(gè)是用來干啥的?里面還檢查了地址范圍是否沖突,但這些地址范圍不是BIOS或系統(tǒng)初始化時(shí)PCI設(shè)備枚舉時(shí)映射的嗎,難道還會沖突?
也見過許多實(shí)際應(yīng)用的PCI設(shè)備驅(qū)動不調(diào)用這一操作的,這樣有啥區(qū)別?

關(guān)于這個(gè)函數(shù)用途Manual Page中講得很少,就幾句話,和源代碼中的注釋差不多;內(nèi)核Documentation/pci.txt中沒有提到這一函數(shù)。

[ 本帖最后由 Cyberman.Wu 于 2009-2-20 16:20 編輯 ]
作者: Cyberman.Wu    時(shí)間: 2009-02-27 18:18
自己踢一下,沒人知道?在內(nèi)核自帶的驅(qū)動中發(fā)現(xiàn)許多地方做了這個(gè)操作。
作者: Godbach    時(shí)間: 2009-02-27 19:13
建議LZ先看看LDD3中PCI的那一章啊。里面應(yīng)該講得比較清楚
作者: Cyberman.Wu    時(shí)間: 2009-02-27 19:57
標(biāo)題: 回復(fù) #3 Godbach 的帖子
1. LDD3中提都沒提到這個(gè)函數(shù),我是在看e1000網(wǎng)上驅(qū)動時(shí)看到的。從代碼知道它做了什么操作,但它的作用不怎么清楚,因?yàn)槲乙惨娺^許多驅(qū)動不做這一操作的。
2. 說句實(shí)話,LDD3對于PCI驅(qū)動很是走馬觀花,不怎么樣,我是看了一本PCI Express System Architecture和一些實(shí)際驅(qū)動的代碼,然后再看標(biāo)準(zhǔn)規(guī)范才逐漸理解了的。
作者: albcamus    時(shí)間: 2009-03-02 12:21
原帖由 Cyberman.Wu 于 2009-2-27 19:57 發(fā)表
1. LDD3中提都沒提到這個(gè)函數(shù),我是在看e1000網(wǎng)上驅(qū)動時(shí)看到的。從代碼知道它做了什么操作,但它的作用不怎么清楚,因?yàn)槲乙惨娺^許多驅(qū)動不做這一操作的。
2. 說句實(shí)話,LDD3對于PCI驅(qū)動很是走馬觀花,不怎么樣 ...


我記得ldd3是講了的, 你確信沒有?
作者: Cyberman.Wu    時(shí)間: 2009-03-02 13:03
標(biāo)題: 回復(fù) #5 albcamus 的帖子
我在PDF格式的電子中搜索過的但沒找到,另外后面的索引中也沒找到。
作者: Cyberman.Wu    時(shí)間: 2009-03-09 16:21
自己踢一腳。真的沒人知道?
作者: Godbach    時(shí)間: 2009-03-09 23:04
驅(qū)動板置頂?shù)碾娮訒芯陀蠰DD3的英文和中文版,LZ確實(shí)查找了嗎。我看LDD3的時(shí)候,PCI那一章是講過這個(gè)函數(shù)的。
作者: scutan    時(shí)間: 2009-03-10 02:14
原帖由 Cyberman.Wu 于 2009-2-20 14:59 發(fā)表
今天看Linux內(nèi)核中自帶的e1000網(wǎng)卡驅(qū)動,發(fā)現(xiàn)它在probe中有如下操作:
    if ((err = pci_request_regions(pdev, e1000_driver_name)))
        return err;


但看代碼好像這里主要是把BAR0~BAR5分配到的 ...

Essential Linux Device Drivers 這本書對這個(gè)函數(shù)有講解,而且我覺得講得也很不錯(cuò)。我把那一章都拷貝出來:
Accessing PCI Regions
PCI devices contain three addressable regions: configuration space, I/O ports, and device memory. Let's learn how to access these memory regions from a device driver.

Configuration Space
The kernel offers a set of six functions that your driver can use to operate on PCI configuration space:

pci_read_config_[byte|word|dword](struct pci_dev *pdev,
                                  int offset, int *value);
and
pci_write_config_[byte|word|dword](struct pci_dev *pdev,
                                   int offset, int value);


In the argument list, struct pci_dev is the PCI device structure, and offset is the byte position in the configuration space that you want to access. For read functions, value is a pointer to a supplied data buffer, and for write routines, it contains the data to be written.

Let's consider some examples:

To decipher the IRQ number assigned to a card function, use the following:

unsigned char irq;
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &irq);
As per the PCI specification, offset 60 inside the PCI configuration space holds the IRQ number assigned to the card. All configuration register offsets are expressively defined in include/linux/pci_regs.h, so use PCI_INTERRUPT_LINE rather than 60 to specify this offset. Similarly, to read the PCI status register (two bytes at offset six in the configuration space), do this:

unsigned short status;
pci_read_config_word(pdev, PCI_STATUS, &status);
Only the first 64 bytes of the configuration space are standardized. The device manufacturer defines desired semantics to the rest. The Xircom card used earlier, assigns four bytes at offset 64 for power management purposes. To disable power management, the Xircom CardBus driver, drivers/net/tulip/xircom_cb.c, does this:

#define PCI_POWERMGMT 0x40
pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000);
I/O and Memory
PCI cards have up to six I/O or memory regions. I/O regions contain registers, and memory regions hold data. Video cards, for example, have I/O spaces that accommodate control registers and memory regions that map to frame buffers. Not all cards have addressable memory regions, however. The semantics of I/O and memory spaces are hardware-dependent and can be obtained from the device data sheet.

Like for configuration memory, the kernel offers a set of helpers to operate on I/O and memory regions of PCI devices:

Code View:
unsigned long pci_resource_[start|len|end|flags] (struct pci_dev *pdev, int bar);

                                          


To operate on an I/O region such as the device control registers of a PCI video card, the driver needs to do the following:

  
1.  Get the I/O base address from the appropriate base address register (bar) in the configuration space:


unsigned long io_base = pci_resource_start(pdev, bar);

This assumes that the device control registers for this card are mapped to the memory region associated with bar, whose value can range from 0 through 5, as shown in Table 10.2.


2.  Mark this region as being spoken for, using the kernel's request_region() regulatory mechanism discussed in Chapter 5, "Character Drivers":


request_region(io_base, length, "my_driver");

Here, length is the size of the control register space and my_driver identifies the region's owner. Look for the entry containing my_driver in /proc/ioports to spot this memory region.

You may instead use the wrapper function pci_request_region(), defined in drivers/pci/pci.c.


3.  Add the register's offset obtained from the data-sheet, to the base address gleaned in Step 1. Operate on this address using the inb() and outb() family of functions discussed in Chapter 5:


/* Read */
register_data = inl(io_base + REGISTER_OFFSET);
/* Use */
/* ... */
/* Write */
outl(register_data, iobase + REGISTER_OFFSET);



To operate on a memory region such as the frame buffer on the above PCI video card, follow these steps:

1.  Get the base address, length, and flags associated with the memory region:


unsigned long mmio_base   = pci_resource_start(pdev, bar);
unsigned long mmio_length = pci_resource_length(pdev, bar);
unsigned long mmio_flags  = pci_resource_flags(pdev, bar);

This assumes that this memory is mapped to the base address register, bar.


2.  Mark ownership of this region using the kernel's request_mem_region() regulatory mechanism:


request_mem_region(mmio_base, mmio_length, "my_driver");

You may instead use the wrapper function pci_request_region(), mentioned previously.


  
3.  Obtain CPU access to the device memory obtained in Step 1. Certain memory regions, such as the ones that hold registers, need to guard against side effects, so they are marked as not being prefetchable (or cacheable) by the CPU. Other regions, such as the one used in this example, can be cached. Depending on the access flag, use the appropriate function to obtain kernel virtual addresses corresponding to the mapped region:


void __iomem *buffer;
if (flags & IORESOURCE_CACHEABLE) {
  buffer = ioremap(mmio_base, mmio_length);
} else {
  buffer = ioremap_nocache(mmio_base, mmio_length);
}



To be safe, and to avoid performing the preceding checks, use the services of pci_iomap() defined in lib/iomap.c instead:

buffer = pci_iomap(pdev, bar, mmio_length);

作者: Cyberman.Wu    時(shí)間: 2009-03-10 09:52
標(biāo)題: 回復(fù) #9 scutan 的帖子
Thanks. 這本書我以前下載了,但從來沒看過,只看過LDD3,看來要多看一些不同的書及代碼才行。

不過在實(shí)際的驅(qū)動中還是看到過沒有調(diào)用這一函數(shù)處理的,是一個(gè)錯(cuò)誤,還是不調(diào)用關(guān)系也不大?
作者: scutan    時(shí)間: 2009-03-10 10:08
原帖由 Cyberman.Wu 于 2009-3-10 09:52 發(fā)表
Thanks. 這本書我以前下載了,但從來沒看過,只看過LDD3,看來要多看一些不同的書及代碼才行。

不過在實(shí)際的驅(qū)動中還是看到過沒有調(diào)用這一函數(shù)處理的,是一個(gè)錯(cuò)誤,還是不調(diào)用關(guān)系也不大?


我覺得Essential這本書講得不錯(cuò).

有的驅(qū)動可能不是PCI設(shè)備啊.
作者: Cyberman.Wu    時(shí)間: 2009-03-10 13:20
標(biāo)題: 回復(fù) #11 scutan 的帖子
我看得驅(qū)動就是PCI的,呵呵,是一個(gè)PCIe x4的板子。

LDD3對于具體的硬件相關(guān)部分感覺講得不怎么到位,前一段時(shí)間都是看PCI/PCIe規(guī)范、別人的驅(qū)動加內(nèi)核源碼去理解的。

[ 本帖最后由 Cyberman.Wu 于 2009-3-10 13:21 編輯 ]
作者: emmoblin    時(shí)間: 2009-03-10 13:31
我覺得不掉用這個(gè)函數(shù),除非驅(qū)動不需要直接內(nèi)存訪問硬件。
通過bios接口一樣可以控制硬件,但是對于dma需要直接內(nèi)存訪問。
反正pci設(shè)備有多種訪問方式,不用也成,就是效率低
作者: Cyberman.Wu    時(shí)間: 2009-03-10 19:16
標(biāo)題: 回復(fù) #13 emmoblin 的帖子
我用的那個(gè)驅(qū)動就是用DMA傳數(shù)據(jù)的,用了這么久沒任何問題。從代碼看它主要是把那些地址段根據(jù)是MEM還是IO加到不同的鏈表中了,好像也沒做太多操作吧。
作者: hz5034    時(shí)間: 2018-03-11 17:32
回復(fù) 1# Cyberman.Wu

BIOS或系統(tǒng)初始化時(shí)已經(jīng)把各個(gè)PCI橋和設(shè)備的resource插入ioport/iomem_resource資源樹了,其中PCI設(shè)備的resource是葉子節(jié)點(diǎn),但是這些葉子結(jié)點(diǎn)的flag沒有被設(shè)置為IORESOURCE_BUSY,網(wǎng)卡驅(qū)動調(diào)用pci_request_regions() -> ... -> __request_region(),__request_region()創(chuàng)建一個(gè)resource并把flag設(shè)置為IORESOURCE_BUSY,然后遞歸查詢ioport/iomem_resource資源樹,直到找到相應(yīng)的葉子結(jié)點(diǎn),然后將這個(gè)resource插入葉子結(jié)點(diǎn)的child鏈表,如果有其它的進(jìn)程也來請求同一塊地址,會查到IORESOURCE_BUSY,請求失敗,這就實(shí)現(xiàn)了互斥
作者: hz5034    時(shí)間: 2018-03-11 17:38
回復(fù) 1# Cyberman.Wu

BIOS或系統(tǒng)初始化時(shí)已經(jīng)把各個(gè)PCI橋和設(shè)備的resource插入ioport/iomem_resource資源樹了,其中PCI設(shè)備的resource是葉子節(jié)點(diǎn),但是這些葉子結(jié)點(diǎn)的flag沒有被設(shè)置為IORESOURCE_BUSY,網(wǎng)卡驅(qū)動調(diào)用pci_request_regions() -> ... -> __request_region(),__request_region()創(chuàng)建一個(gè)resource并把flag設(shè)置為IORESOURCE_BUSY,然后遞歸查詢ioport/iomem_resource資源樹,直到找到相應(yīng)的葉子結(jié)點(diǎn),然后將這個(gè)resource插入葉子結(jié)點(diǎn)的child鏈表,如果有其它的進(jìn)程也來請求同一塊地址,會查到IORESOURCE_BUSY,請求失敗,這就實(shí)現(xiàn)了互斥




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2