MMIO in PCIe
static struct pci_device_id test_ids[] = { { PCI_DEVICE(0x vendorID, 0x deviceID) }, { 0 } }; static struct pci_driver test_driver = { .name = "test", .id_table = test_ids, .probe = test_probe, .remove = test_remove }; |
static int __init test_init (void){ rc = pci_register_driver(&test_driver); } static void __exit test_exit (void){ pci_unregister_driver(&test_driver); } |
static int test_probe (struct pci_dev *pdev, const struct pci_device_id *id) { pci_enable_device_mem(pdev) pci_select_bars(pdev,IORESOURCE_MEM) start = pci_resource_start(pdev,0) size = pci_resource_len(pdev,0) io_va = ioremap/_wt/_nocache(start,size) ... } |
Accessing the I/O and Memory Spaces
Original Source: http://www.oreilly.com/openbook/linuxdrive3/book/ch12.pdf
A PCI device implements up to six I/O address regions. Each region consists of either memory or I/O locations. Most devices implement their I/O registers in memory regions, because it’s generally a saner approach (as explained in the section “I/O Ports and I/O Memory,” in Chapter 9). However, unlike normal memory, I/O registers should not be cached by the CPU because each access can have side effects. The PCI device that implements I/O registers as a memory region marks the difference by setting a “memory-is-prefetchable” bit in its configuration register.* If the memory region is marked as prefetchable, the CPU can cache its contents and do all sorts of optimization with it; nonprefetchable memory access, on the other hand, can’t be optimized because each access can have side effects, just as with I/O ports. Peripherals that map their control registers to a memory address range declare that range as nonprefetchable, whereas something like video memory on PCI boards is prefetchable.
In this section, we use the word region to refer to a generic I/O address space that is memory-mapped or port-mapped. An interface board reports the size and current location of its regions using configuration registers—the six 32-bit registers shown in Figure 12-2, whose symbolic names are PCI_BASE_ADDRESS_0 through PCI_BASE_ADDRESS_5. Since the I/O space defined by PCI is a 32-bit address space, it makes sense to use the same configuration interface for memory and I/O. If the device uses a 64-bit address bus, it can declare regions in the 64-bit memory space by using two consecutive PCI_BASE_ADDRESS registers for each region, low bits first. It is possible for one device to offer both 32-bit regions and 64-bit regions.
In the kernel, the I/O regions of PCI devices have been integrated into the generic resource management. For this reason, you don’t need to access the configuration variables in order to know where your device is mapped in memory or I/O space. The preferred interface for getting region information consists of the following functions:
커널에서 PCI 장치의 IO 영역은 범용 자원 관리자로 통합되었다. 따라서, 메모리나 입출력 공간의 어디에 장치가 매핑되었는지를 알기 위해 configuration variable을 엑세스 할 필요가 없다. 그냥 매핑이 일단 이루어지고, 연속된 해당 영역에 대해 시작과 크기 주소공간만 알면, 엑세스가 가능하다.
unsigned long pci_resource_start(struct pci_dev *dev, int bar);
The function returns the first address (memory address or I/O port number) associated with one of the six PCI I/O regions. The region is selected by the integer bar (the base address register), ranging from 0–5 (inclusive).
unsigned long pci_resource_end(struct pci_dev *dev, int bar);
The function returns the last address that is part of the I/O region number bar. Note that this is the last usable address, not the first address after the region.unsigned long pci_resource_flags(struct pci_dev *dev, int bar);
This function returns the flags associated with this resource. Resource flags are used to define some features of the individual resource. For PCI resources associated with PCI I/O regions, the information is extracted from the base address registers, but can come from elsewhere for resources not associated with PCI devices.
All resource flags are defined in <linux/ioport.h>; the most important are:
IORESOURCE_IO
IORESOURCE_MEM
If the associated I/O region exists, one and only one of these flags is set.
IORESOURCE_PREFETCH
IORESOURCE_READONLY
These flags tell whether a memory region is prefetchable and/or write protected. The latter flag is never set for PCI resources. By making use of the pci_resource_ functions, a device driver can completely ignore the underlying PCI registers, since the system already used them to structure resource information.
pci_resource 함수는 디바이스 드라이버가 PIC 레지스터를 무시할 수 있도록 해주는데, 시스템이 리소스 정보를 구조화 하는데 이미 그것들을 사용하고 있기 때문이다.
'Linux Kernel' 카테고리의 다른 글
glibc Malloc (0) | 2016.08.27 |
---|---|
LD_PRELOAD example (0) | 2016.08.27 |
JEMALLOC: A Scalable Concurrent malloc(3) Implementation for FreeBSD (0) | 2016.08.18 |
malloc 소개 (0) | 2016.08.18 |
posix_fallocate (0) | 2016.08.16 |