Linux Driver Technology (I I) _Accessing I/O Memory

Keywords: Linux

ARM addresses memory space and IO space uniformly, so controlling hardware by reading and writing SFR becomes controlling hardware by reading and writing corresponding SFR address. This part of the address is also known as I/O memory. In x86, I/O addresses and memory addresses are separately addressed. Such IO addresses are called I/O ports. This article only discusses IO memory access.

IO memory access process

We know that in order to manage the most important system resources and make the physical address transparent to the process, Linux uses the memory mapping mechanism, that is, if a process wants to access a physical memory address (eg.SFR address), it first maps it to a virtual address.

IO Memory Request/Return

Linux provides a set of functions for requesting and releasing the scope of IO memory. These two API s are not necessary when accessing IO memory, but it is recommended to use them. They can check whether the requested resources are available and increase the security of IO access. If available, the application succeeds and is marked as used. Other drivers will fail to apply before the process returns the resources.

The request_mem_region() macro function requests n memory addresses from memory. These addresses start at first, len is long, name is the name of the device, and successfully returns non-NULL failures to return NULL.

/**
 * request_mem_region - create a new busy resource region
 * @start: resource start address
 * @n: resource region size
 * @name: reserving caller's ID string
 */

struct resource * request_mem_region(resource_size_t start, resource_size_t n,const char *name)

The release_mem_region() macro function, as its name implies, returns the IO memory resources requested by request_mem_region() to the kernel so that other processes can access the IO memory as well.

/**
 * release_mem_region - release a previously reserved resource region
 * @start: resource start address
 * @n: resource region size
 */
void release_mem_region(resource_size_t start, resource_size_t n,const char *name)

IO memory mapping/de-mapping

I applied for IO resources, and then I mapped the physical address to the virtual address. The API provided by the kernel is as follows

static inline void __iomem *ioremap(unsigned long port, unsigned long size)
static inline void iounmap(volatile void __iomem *addr)

IO Memory Access API

ARM's SFR is 32 bits. After ioremap, we can actually read the acquired virtual address directly by forcing type conversion. But this method is not safe enough. If we do not read it carefully, we will misplace it. Therefore, the standard API provided by the kernel to read and write IO memory is not only more secure, but also more readable.

Read IO

unsigned int ioread8(void *addr)
unsigned int ioread16(void *addr)
unsigned int ioread32(void *addr)

Write IO

void iowrite8(u8 val,void *addr)
void iowrite16(u8 val,void *addr)
void iowrite32(u8 val,void *addr)

Read a bunch of IO memory

void ioread8_rep(void *addr,void *buf,unsigned long len)
void ioread16_rep(void *addr,void *buf,unsigned long len)
void ioread32_rep(void *addr,void *buf,unsigned long len)

Write a bunch of IO memory

void iowrite8_rep(void *addr,const void *buf,unsigned long len)
void iowrite16_rep(void *addr,const void *buf,unsigned long len)
void iowrite32_rep(void *addr,const void *buf,unsigned long len)

Copy IO memory

void memcpy_fromio(void *dest,void *source,unsigned long len)
void memcpy_toio(void *dest,void *source,unsigned long len)

Setting up IO memory

void memset_io(void *addr,u8 value,unsigned int len)

Posted by damien@damosworld.com on Fri, 29 Mar 2019 22:48:29 -0700