"Go" Linux device-driven I/O ports and I/O memory

Source: Internet
Author: User

Original URL: http://www.cnblogs.com/geneil/archive/2011/12/08/2281367.html

I. Unified addressing and independent addressing

This part comes from: http://blog.chinaunix.net/space.php?uid=21347954&do=blog&id=443670, thanks to Mason_hu for sharing.
From the CPU to connect a line: Data bus, address bus, control bus, which hangs on the line n interface, there is the same, there are different, the name is called Memory interface, interrupt control interface, DMA interface, parallel interface, serial interface, AD interface ... For a device to be plugged in, use its own interface and a matching interface on the bus to connect ... So there are various devices on the bus: memory, hard disk, mouse, keyboard, monitor ...
For the CPU, if it is to send data to a device, is actually sent to the corresponding interface, the interface circuit has a plurality of registers (also known as ports), the access device is actually access to the relevant port, all the information will be transferred from the interface to its device. So the CPU will prepare the data to the bus, but a lot of interfaces, who should be sent to? At this point you need to assign an address to each interface, and then put the address on the address bus, the control information needed to put on the control bus, you can communicate with the device.
For a system, there will usually be multiple peripherals, each peripheral interface circuit, there will be more than one port, each port needs an address, for them to identify a specific address value, is the system must solve the matter, at the same time, you also have a memory bar, may be 512M or 1G or greater Kingston, Modern DDR2 and the like, each of their addresses also need to assign an identity value, in addition, many peripherals have their own memory, buffer, like your memory bar, you also need to allocate memory for them ... Your CPU may need to deal with every byte of it, so don't expect to be lazy, and every inch of their land must be planned! This may sound annoying, and doing so could directly lead to brain cells being killed. But there is always someone to do, arm may do this: he designed the CPU is 32-bit, at most can address the 2^32=4g space, so the 4GB space to the memory and port, let them partition. But Intel may have a better way of distributing ...

1, the concept of an address
1) Physical Address : The address that comes from the CPU address bus, controlled by the hardware circuit its specific meaning. A large portion of the physical address is left to memory in the memory bar, but it is often mapped to other storage (such as video memory, BIOS, and so on). After the virtual address in the program instruction passes through the segment map and the page map, the physical address is generated, and the physical address is placed on the address line of the CPU.
Physical address space, part of the physical RAM (memory) used, partly for the bus, which is determined by the hardware design, so in the x86 processor of the three bits address line, the physical address space is 2 of 32 square, that is 4GB, but the physical RAM is generally not up to 4GB, Because there is still a part to be used for the bus (there are many other devices hanging on the bus). In the PC, the low-end physical address is generally used for RAM, high-end physical address to the bus.  
2) bus address : The address line of the bus or the signal generated on the address cycle. The peripheral uses the bus address and the CPU uses the physical address. The relationship between the
Physical address and the bus address is determined by the design of the system. On the x86 platform, the physical address is the bus address because they share the same address space-a bit difficult to understand, as described in the "stand-alone addressing" below. On other platforms, conversion/mapping may be required. For example: The CPU needs to access the physical address is 0xfa000 unit, then on the x86 platform, a PCI bus will be generated on the 0xfa000 address access. Because the physical address and the bus address are the same, it is not possible to see with the eyes where the address is being used, either in memory or in a storage unit on a card, or even there is no corresponding memory on the address.

3) virtual address : The modern operating system generally adopts virtual memory management (Management) mechanism, which requires the support of MMU (Memory Management Unit). The MMU is usually a part of the CPU, if the processor does not have the MMU, or the MMU is not enabled, the memory address emitted by the CPU execution unit is transmitted directly to the chip pin and is received by the memory chip (physical memory), which is called the Physical Address (physical). If the processor enables the memory address of the MMU,CPU execution unit to be intercepted by the MMU, the address from the CPU to the MMU is called the virtual address, and the MMU translates the address to another address on the external address pin of the CPU chip, That is, the virtual address is mapped to a physical address.

In Linux, 4GB (virtual) memory of the process is divided into user space, kernel space. The user space is distributed as 0~3GB (that is, page_offset, which is equal to 0xc0000000 in 0x86), and the remaining 1G is the kernel space. Programmers can only use virtual addresses. Each process in the system has its own private user space (0~3G), which is not visible to other processes in the system.
The address of the CPU when the request is made is the virtual address of the current context, and the MMU finds the physical address of the virtual address from the page table and completes the reference. Also read the data is a virtual address, such as Mov ax, var. compile-time Var is a virtual address, but also through the MMU from the table to find the physical address, and then generate the bus timing, complete fetching data.

2. Address method
1) Peripherals are carried out through the registers on the read-write device, the peripheral register is also called the "I/O port", and the IO port has two ways of addressing: independent addressing and unified programming.
  Unified Addressing: the IO register (i.e. IO port) in the peripheral interface is treated as the main storage unit, and each end share population uses the address of a memory cell, which is used as an IO address space by a portion of the primary memory, for example, in PDP-11, the highest 4K main memory as the IO device register address. The port occupies the memory address space, which reduces the storage capacity.
Unified addressing is also referred to as "I/O memory", where the peripheral registers are in "memory space" (many peripherals have their own memory, buffers, peripheral registers and memory referred to as "I/O space").
For example, Samsung's s3c2440 is a 32-bit ARM processor, and its 4GB address space is partitioned by peripherals, RAM, and so on:
0x8000 the address of the LED 8*8 dot Matrix
0x4800 0000 ~ 0x6000 0000 SFR (Special Register) address space
0x3800 1002 Keyboard Address
0x3000 0000 ~ 0x3400 0000 SDRAM Space
0x2000 0020 ~ 0x2000 002e IDE
0x1900 0300 CS8900

  stand-alone addressing (separate addressing): The IO address is separate from the storage address and the I/O port address does not occupy the address range of the storage space, so that there is another IO address unrelated to the storage address in the system, and the CPU must have an IO instruction (in, out, etc.) and control logic dedicated to the input/output operation. Stand-alone address, the address bus come up with a location, the device is not known to the IO port, or to the memory, so the processor through the MEMR/MEMW and Ior/iow two sets of control signals to achieve the I/O port and memory of different addressing. For example, the Intel 80x86 uses a separate address, CPU memory and I/O are addressed together, that is, the memory portion of the addresses and I/O addresses overlap.
Stand-alone addressing is also known as an I/O port, and the peripheral registers are located in the I/O (address) space.
For the x86 architecture, it is accessed through the In/out directive. PC architecture A total of 65,536 8bit I/O ports, composed of 64K I/O address space, numbered from 0~0XFFFF, there are 16 bits, 80x86 with a low 16-bit address line a0-a15 addressing. Two consecutive 8bit ports can be composed of a 16bit port, 4 consecutive ports composed of a 32bit. The physical address space of the I/O address space and the CPU is two different concepts, such as the I/O address space is 64K, and a 32bit CPU physical address space is 4G. For example, under Intel 8086+redhat9.0, use "More/proc/ioports" to see:
0000-001f:dma1
0020-003f:pic1
0040-005f:timer
0060-006f:keyboard
0070-007f:rtc
0080-008F:DMA Page Reg
00a0-00bf:pic2
00c0-00df:dma2
00f0-00ff:fpu
0170-0177:ide1
......
However, the Intel x86 platform generally uses a technology called Memory Mapping (MMIO), which is part of the PCI specification, the IO device port is mapped to memory space, and after mapping, the CPU accesses the IO port as if it were accessing memory. See the X86/X64 system typical memory address allocation table given by the Intel TA 719 Documentation:
System resource Consumption
------------------------------------------------------------------------
BIOS 1M
Local APIC 4K
Chipset retention 2M
IO APIC 4K
PCI Device 256M
PCI Express Device 256M
PCI device (optional) 256M
Display Frame Cache 16M
Tseg 1M

For a given system, it is either a stand-alone address or a unified address, depending on the CPU's architecture. For example, PowerPC, m68k, such as the use of unified addressing, and X86, such as the use of independent addressing, there is the concept of IO space. Currently, most embedded microcontrollers such as ARM, PowerPC, etc. do not provide I/O space, only memory space, can be directly accessed with the address, pointer. However, for the Linux kernel, it may be used for different CPUs, so it must be considered in both ways, so it takes a new approach, the I/O map-based or memory-mapped I/O port is known as an I/O region (I/O regions), regardless of which way you use, Must first apply IO area: Request_resource (), release it at the end: Release_resource ().

Ii. Linux I/O ports and I/O memory

IO port : When a register or memory is in IO space;
IO memory : When a memory or register is in memory space;

While some CPU manufacturers implement a single address space (unified addressing) on their chips, other CPU manufacturers believe that peripherals are different from memory, there should be a separate address space for the peripheral (separate addressing), the production processor (especially the x86 family) i/ The O port has its own read-write signal line and special CPU instructions to access the port. Because peripherals are matched to the peripheral bus, and most of the popular I/O buses are modeled on a personal computer (primarily the x86 family), even those processors that do not have a separate address space for the I/O port must be emulated as read-write ports when accessing peripherals. This is usually achieved through an external chipset (North-South Bridge in the PC) or additional circuitry attached to the CPU core (embedded application-based processors).
For the same reason, Linux implements the I/O ports on all computer platforms, even on CPU platforms with single address space (analog I/O ports). However, not all devices will map their registers to the I/O ports. Although I/O ports are commonly used by ISA devices, most PCI devices map registers to a memory address area. This I/O memory method is usually preferred because it eliminates the need for special processor instructions, CPU access memory is also more efficient, and the compiler has more freedom in the choice of register allocation and addressing modes when accessing memory.

The main difference between the

1.IO Register and the general memory
I/O register and RAM is that the I/O operation has marginal effect (side effect) and the memory operation does not: access memory simply stores the value in a location in memory. Because memory access speeds heavily affect CPU performance, the compiler might optimize the source code by using caching and re-ordering the read/write instructions. These optimizations are useful for traditional memory (at least on a single-processor system), but for I/O registers this can be a fatal error because they interfere with those "marginal effects" (the driver accesses the I/O register for marginal effects). Therefore, the driver must ensure that the cache cannot be used and the order of read and write instructions cannot be rearranged when the registers are accessed.
side effect means that when accessing an I/O register, not only does it affect the value of the storage unit as it accesses normal memory, but more importantly it can change the CPU's I/O port level, the output timing or the CPU's response to the I/O port level, and so on, thus realizing the CPU control function. The meaning of the CPU in the circuit is to realize its side effect. For example, some device interrupt status registers are automatically zeroed out as soon as they are read. The problem with the

hardware buffering is the most manageable: any hardware buffering (whether I/O or I/O ports) is prohibited when the underlying hardware is configured (or automatically or through the Linux initialization code) for when the I/O area is accessed. The workaround for the

compiler optimization and hardware reconfiguration read-write instruction sequence is to place a memory barrier between the hardware or the processor that must be executed in a particular order (barrier).

2. Operation IO port (request, access, release) :
I/O port is the way to drive communication with many devices.
(1) Request I/O port :
Do not operate on the port until the drive has not been exclusive of the device. The kernel provides a registration interface to allow the driver to declare the port it needs:

/* Request_region tells the kernel: N ports to start with first. The parameter name is the device name. If the assigned success return value is non-null, you cannot use the required port (/proc/ioports contains the allocation information for all current ports on the system, and if the request_region assignment fails, you can view the file to see who used the port you want first) */
struct Resource *request_region (unsigned long first, unsigned long n, const char *name);

(2) Access IO port:

After the driver is successfully requested to the I/O port, the ports can be read and written. Most hardware separates the 8-bit, 16-bit, and 32-bit ports, and is not as confusing as accessing memory. The driver must call different functions to access ports of different sizes.
The Linux kernel header file (System-dependent header file <asm/io.h>) defines the following inline functions to access the I/O ports:

/* INB/OUTB: Read/write section port (8 bits wide). Some systems define the port parameter as unsigned long, while some platforms define it as unsigned short. The return type of INB is also dependent on the system */
Unsigned inb (unsigned port);
void Outb (unsigned char byte, unsigned port);

/* INW/OUTW: Read/write port (16 bit wide) */
Unsigned inw (unsigned port);
void outw (unsigned short word, unsigned port);

/* Inl/outl: Read/write 32-bit port. Longword is also dependent on the system, some systems are unsigned long, and some are unsigned int */
unsigned inl (unsigned port);
void Outl (unsigned longword, unsigned port);

(3) Release IO port:

/* After the I/O port is exhausted (possibly when the module is unloaded), you should call Release_region to return the I/O port to the system. The parameters start and n should be consistent with the previous pass to Request_region */
void Release_region (unsigned long start, unsigned long n);

3. Operating IO memory (request, map, access, release ):
Although I/O ports are popular in the x86 world, the primary mechanism used to communicate with devices is through memory-mapped registers and device memory, both called I/O memory, because the difference between registers and memory is transparent to the software.
I/O memory is just a ram-like area where the processor accesses the zone through the bus for access to the device. Similarly, the reading and writing of this area is a marginal effect.
Depending on the computer system and the bus, I/O memory can be divided into or not accessible through the page table. In the Case of page table access, the kernel must first rearrange the physical address to make it visible to the driver, which means that you must call Ioremap before any I/O is done, and if the page table is not required, the I/O memory area is similar to the I/O port, and you can read and write them directly using the appropriate I/O functions.
Because of the marginal effect, it is discouraged to use I/O memory pointers directly, regardless of whether or not ioremap are required, instead use specialized I/O memory manipulation functions. These I/O memory operation functions are not only secure on all platforms, but also optimize the use of pointers to manipulate I/O memory directly.

(1) Request I/O Memory:
The I/O memory area must be assigned before use. The function interfaces for allocating memory areas are in the <linux/ioport.h> definition:

/* Request_mem_region allocates an I/O memory area that starts at Start,len bytes. The assignment succeeds, returns a non-null pointer, otherwise returns NULL. The system currently all I/O memory allocation information is listed in the/proc/iomem file, when you fail to assign, you can look at the file to see who first occupied the memory area * *
struct Resource *request_mem_region (unsigned long start, unsigned long len, char *name);

(2) Mapping:
Allocating I/O memory is not the only required step before accessing I/O memory, and you must also ensure that the kernel has access to that I/O memory. Accessing I/O memory is not just a simple dereference pointer, and in many systems I/O memory cannot be accessed directly in this way. Therefore, a mapping must also be set through the Ioremap function.

/* Ioremap is used to map the I/O memory area to the virtual address. The parameter phys_addr is the I/O memory start address to be mapped, the size of the I/O memory to be mapped, and the return value to the virtual address to which it is mapped */
void *ioremap (unsigned long phys_addr, unsigned long size);

(3) Accessing IO Memory:
After Ioremap, the device driver can access any I/O memory address. Note that the address returned by Ioremap cannot be directly dereferenced, instead, the access function provided by the kernel should be used. The correct way to access I/O memory is through a series of functions dedicated to this purpose:

#include <asm/io.h>
/* I/O memory read function. The parameter addr should be the address obtained from IOREMAP (which may contain an integer offset); The return value is the value read from the given I/O memory */
unsigned int ioread8 (void *addr);
unsigned int ioread16 (void *addr);
unsigned int ioread32 (void *addr);

/* I/O memory write function. Parameter addr Same as I/O memory read function, parameter value is to write values */
void Iowrite8 (U8 value, void *addr);
void Iowrite16 (U16 value, void *addr);
void Iowrite32 (u32 value, void *addr);

/* These functions read and write a series of values to a given I/O memory address, reading from a given buf or writing count values to a given addr. The parameter count represents the number of data to read and write, not the size of the bytes */
void Ioread8_rep (void *addr, void *buf, unsigned long count);
void Ioread16_rep (void *addr, void *buf, unsigned long count);
void Ioread32_rep (void *addr, void *buf, unsigned long count);
void Iowrite8_rep (void *addr, const void *buf, unsigned long count);
void Iowrite16_rep (void *addr, const void *buf, unsigned long count);
void Iowrite32_rep (void *addr,,onst void *buf,,nsigned long Count);

/* Use the following functions when you need to manipulate an I/O address (these functions behave like their C library-like functions): */
void Memset_io (void *addr, U8 value, unsigned int count);
void Memcpy_fromio (void *dest, void *source, unsigned int count);
void Memcpy_toio (void *dest, void *source, unsigned int count);

/* old I/O memory read/write function, deprecated */
unsigned readb (address);
unsigned readw (address);
unsigned readl (address);
void Writeb (unsigned value, address);
void Writew (unsigned value, address);
void Writel (unsigned value, address);

(4) Release the IO Memory step:

void Iounmap (void * addr); /* Iounmap for releasing mappings that are no longer needed */
void Release_mem_region (unsigned long start, unsigned long len); /* Iounmap for releasing mappings that are no longer needed */

4. Use ports like IO memory

Some of the hardware has an interesting feature: Some versions use I/O ports, while others use I/O memory. The device registers that the processor sees are the same regardless of the I/O port or I/O memory, only the access method is different. To unify the programming interface and make the driver easy to write, the 2.6 kernel provides a ioport_map function:

/* Ioport_map Remap Count of I/O ports so that they look I/O memory. Thereafter, the driver can use IOREAD8 and the same function on the address returned by the Ioport_map. This allows you to eliminate the difference between I/O ports and I/OS memory when programming */
void *ioport_map (unsigned long port, unsigned int count);

void Ioport_unmap (void *addr);/* Ioport_unmap for releasing mappings that are no longer needed */

Note that the I/O port must be assigned the I/O port required by using request_region before remapping.

5. IO operation interface of ARM system
The s3c24x0 processor uses I/O memory , that is, the S3c24x0 processor uses a unified addressing method, the I/O registers and memory use a single address space, and the read-write I/O register and read-write memory instructions are the same. Therefore, it is recommended to use the relevant instructions and functions for I/O memory. However, this does not mean that the I/O port directives are not available in s3c24x0. If you notice the s3c24x0 about the I/O kernel source code, you will find that: actually I/O port instructions are just a shell, internal or using the same as I/O memory. Note the following points:
1) All the read-write instructions (I/O operation functions) assigned to the address must be a virtual address, you have two options: Use the kernel has already defined the address, such as in the include/asm-arm/arch-s3c2410/ Each peripheral register address of the S3C2410 processor is defined in the Regs-xxx.h (other processor chips can also find the virtual address of the kernel-defined peripheral register in a similar path, and the other is to use the virtual address that it maps with its own ioremap. The actual physical address must never be used, or oops will occur because the kernel cannot process the address.
2) When using the I/O directives, you can use request_region and request_mem_region without using the OUTB, Ioread, and other instructions. Because the function of request only tells the kernel port who is occupied, such as request again, the kernel will stop (resource busy). However, this is not recommended, and the code is not standardized, which can cause concurrency problems (many times we need exclusive devices).
3) When using I/O directives, the assigned address data must sometimes be cast to unsigned long by coercion type, otherwise there will be a warning.
4) in the include\asm-arm\arch-s3c2410\hardware.h defined a lot of IO port operation function, it is necessary to be directly used in the drive, very convenient.

"Go" Linux device-driven I/O ports and I/O memory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.