Specifications

This is the Title of the Book, eMatter Edition
Copyright © 2005 O’Reilly & Associates, Inc. All rights reserved.
424
|
Chapter 15: Memory Mapping and DMA
video memory; mapping the graphic display to user space dramatically improves the
throughput, as opposed to an lseek/write implementation. Another typical example
is a program controlling a PCI device. Most PCI peripherals map their control regis-
ters to a memory address, and a high-performance application might prefer to have
direct access to the registers instead of repeatedly having to call ioctl to get its work
done.
The mmap method is part of the
file_operations structure and is invoked when the
mmap system call is issued. With mmap, the kernel performs a good deal of work
before the actual method is invoked, and, therefore, the prototype of the method is
quite different from that of the system call. This is unlike calls such as ioctl and poll,
where the kernel does not do much before calling the method.
The system call is declared as follows (as described in the mmap(2) manual page):
mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
On the other hand, the file operation is declared as:
int (*mmap) (struct file *filp, struct vm_area_struct *vma);
The filp argument in the method is the same as that introduced in Chapter 3, while
vma contains the information about the virtual address range that is used to access
the device. Therefore, much of the work has been done by the kernel; to implement
mmap, the driver only has to build suitable page tables for the address range and, if
necessary, replace
vma->vm_ops with a new set of operations.
There are two ways of building the page tables: doing it all at once with a function
called
remap_pfn_range or doing it a page at a time via the nopage VMA method.
Each method has its advantages and limitations. We start with the “all at once”
approach, which is simpler. From there, we add the complications needed for a real-
world implementation.
Using remap_pfn_range
The job of building new page tables to map a range of physical addresses is handled
by remap_pfn_range and io_remap_page_range, which have the following prototypes:
int remap_pfn_range(struct vm_area_struct *vma,
unsigned long virt_addr, unsigned long pfn,
unsigned long size, pgprot_t prot);
int io_remap_page_range(struct vm_area_struct *vma,
unsigned long virt_addr, unsigned long phys_addr,
unsigned long size, pgprot_t prot);
,ch15.13676 Page 424 Friday, January 21, 2005 11:04 AM