O'Reilly logo

Linux Device Drivers, Second Edition by Alessandro Rubini, Jonathan Corbet

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Quick Reference

This chapter introduced the following symbols related to memory handling. The list doesn’t include the symbols introduced in the first section, as that section is a huge list in itself and those symbols are rarely useful to device drivers.

#include <linux/mm.h>

All the functions and structures related to memory management are prototyped and defined in this header.

int remap_page_range(unsigned long virt_add, unsigned long phys_add, unsigned long size, pgprot_t prot);

This function sits at the heart of mmap. It maps size bytes of physical addresses, starting at phys_addr, to the virtual address virt_add. The protection bits associated with the virtual space are specified in prot.

struct page *virt_to_page(void *kaddr); , void *page_address(struct page *page);

These macros convert between kernel logical addresses and their associated memory map entries. page_address only works for low-memory pages, or high-memory pages that have been explicitly mapped.

void *__va(unsigned long physaddr); , unsigned long __pa(void *kaddr);

These macros convert between kernel logical addresses and physical addresses.

unsigned long kmap(struct page *page); , void kunmap(struct page *page);

kmap returns a kernel virtual address that is mapped to the given page, creating the mapping if need be. kunmap deletes the mapping for the given page.

#include <linux/iobuf.h> , void kiobuf_init(struct kiobuf *iobuf); , int alloc_kiovec(int number, struct kiobuf **iobuf); , void free_kiovec(int number, struct kiobuf **iobuf);

These functions handle the allocation, initialization, and freeing of kernel I/O buffers. kiobuf_init initializes a single kiobuf, but is rarely used; alloc_kiovec, which allocates and initializes a vector of kiobufs, is usually used instead. A vector of kiobufs is freed with free_kiovec.

int lock_kiovec(int nr, struct kiobuf *iovec[], int wait); , int unlock_kiovec(int nr, struct kiobuf *iovec[]);

These functions lock a kiovec in memory, and release it. They are unnecessary when using kiobufs for I/O to user-space memory.

int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long address, size_t len); , void unmap_kiobuf(struct kiobuf *iobuf);

map_user_kiobuf maps a buffer in user space into the given kernel I/O buffer; unmap_kiobuf undoes that mapping.

#include <asm/io.h> , unsigned long virt_to_bus(volatile void * address); , void * bus_to_virt(unsigned long address);

These functions convert between kernel virtual and bus addresses. Bus addresses must be used to talk to peripheral devices.

#include <linux/pci.h>

The header file required to define the following functions.

int pci_dma_supported(struct pci_dev *pdev, dma_addr_t mask);

For peripherals that cannot address the full 32-bit range, this function determines whether DMA can be supported at all on the host system.

void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *bus_addr) , void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpuaddr, dma_handle_t bus_addr);

These functions allocate and free consistent DMA mappings, for a buffer that will last the lifetime of the driver.

PCI_DMA_TODEVICE , PCI_DMA_FROMDEVICE , PCI_DMA_BIDIRECTIONAL , PCI_DMA_NONE

These symbols are used to tell the streaming mapping functions the direction in which data will be moving to or from the buffer.

dma_addr_t pci_map_single(struct pci_dev *pdev, void *buffer, size_t size, int direction); , void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t size, int direction);

Create and destroy a single-use, streaming DMA mapping.

void pci_sync_single(struct pci_dev *pdev, dma_handle_t bus_addr, size_t size, int direction)

Synchronizes a buffer that has a streaming mapping. This function must be used if the processor must access a buffer while the streaming mapping is in place (i.e., while the device owns the buffer).

struct scatterlist { /* ... */ }; , dma_addr_t sg_dma_address(struct scatterlist *sg); , unsigned int sg_dma_len(struct scatterlist *sg);

The scatterlist structure describes an I/O operation that involves more than one buffer. The macros sg_dma_address and sg_dma_len may be used to extract bus addresses and buffer lengths to pass to the device when implementing scatter-gather operations.

pci_map_sg(struct pci_dev *pdev, struct scatterlist *list, int nents, int direction); , pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *list, int nents, int direction); , pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction)

pci_map_sg maps a scatter-gather operation, and pci_unmap_sg undoes that mapping. If the buffers must be accessed while the mapping is active, pci_dma_sync_sg may be used to synchronize things.

/proc/dma

This file contains a textual snapshot of the allocated channels in the DMA controllers. PCI-based DMA is not shown because each board works independently, without the need to allocate a channel in the DMA controller.

#include <asm/dma.h>

This header defines or prototypes all the functions and macros related to DMA. It must be included to use any of the following symbols.

int request_dma(unsigned int channel, const char *name); , void free_dma(unsigned int channel);

These functions access the DMA registry. Registration must be performed before using ISA DMA channels.

unsigned long claim_dma_lock(); , void release_dma_lock(unsigned long flags);

These functions acquire and release the DMA spinlock, which must be held prior to calling the other ISA DMA functions described later in this list. They also disable and reenable interrupts on the local processor.

void set_dma_mode(unsigned int channel, char mode); , void set_dma_addr(unsigned int channel, unsigned int addr); , void set_dma_count(unsigned int channel, unsigned int count);

These functions are used to program DMA information in the DMA controller. addr is a bus address.

void disable_dma(unsigned int channel); , void enable_dma(unsigned int channel);

A DMA channel must be disabled during configuration. These functions change the status of the DMA channel.

int get_dma_residue(unsigned int channel);

If the driver needs to know how a DMA transfer is proceeding, it can call this function, which returns the number of data transfers that are yet to be completed. After successful completion of DMA, the function returns 0; the value is unpredictable while data is being transferred.

void clear_dma_ff(unsigned int channel)

The DMA flip-flop is used by the controller to transfer 16-bit values by means of two 8-bit operations. It must be cleared before sending any data to the controller.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required