| Almost every type of peripherals is performed by reading and writing registers on the device. A peripheral register, also known as an "I/O port", usually includes three categories: control registers, status registers, and data registers, and a peripheral register is usually continuously edited. The CPU can address the physical address of the peripheral I/O port in two ways: I/O ing (I/O-mapped ), another method is memory-mapped ). The specific method depends on the CPU architecture. Some architecture CPUs (such as PowerPC and m68k) generally only implement one physical address space (RAM ). In this case, the physical address of the peripheral I/O port is mapped to a single physical address space of the CPU and becomes a part of the memory. In this case, the CPU can access the peripheral I/O port as it accesses a memory unit, without the need to set up a dedicated peripheral I/O command. This is the so-called memory ing method (memory-mapped ). In addition, some architecture CPUs (typically x86) provide a dedicated address space for peripherals, it is called "I/O address space" or "I/O port space ". This is an address space different from the physical address space of the CPU. All the peripheral I/O ports are located in this space. The CPU uses dedicated I/O commands (such as x86 In and out commands) to access the address units (I/O Ports) in the space ). This is the so-called "I/O ing mode" (I/O-mapped ). Compared with the ram physical address space, I/O address space is usually relatively small, for example, x86 cpu I/O space is only 64 KB (0-0xffff ). This is a major drawback of the "I/O ing method. In Linux, I/O Ports Based on I/O ing or memory ing are called "I/O Region" (I/O Region ). Before discussing the management of the I/O Region, let's first analyze how Linux implements the abstract concept of "I/O resources. Linux's description of I/O resources -------------------------------------- Linux designs a general data structure resource to describe various I/O resources (such as I/O Ports, peripheral memory, DMA and IRQ ). This structure is defined in the include/Linux/ioport. h header file: Struct resource { Resource_size_t start; Resource_size_t end; Const char * Name; Unsigned long flags; Struct resource * parent, * sibling, * child; }; Linux Management of I/O resources -------------------------------------- Linux uses an inverted tree structure to manage each type of I/O resources (such as I/O Ports, peripheral memory, DMA, and IRQ. Each type of I/O resources corresponds to an inverted Resource Tree. each node in the tree is a resource structure, while the root node of the tree is the whole resource space of the class resources. Based on the above idea, Linux implements operations such as resource application, release, and search in the kernel/resource. c file. Resource application: request_resource () Resource release: release_resource () Find available resources: -- find_resource () Allocate resources: allocate_resource () Managing I/O Region Resources -------------------------------------- In Linux, I/O ing-based I/O port resources and memory ing-based I/O port resources are collectively referred to as "I/O Region" (I/O Region ). I/O Region is still an I/O resource, so it can still be described by the resource structure type. Next, let's take a look at how Linux manages I/O region. I/O Region allocation: _ request_region () Release of I/O Region: _ release_region () Check whether the specified I/O region is occupied: _ check_region () Manage I/O port resources -------------------------------------- We all know that the x86 processor using I/O ing implements a separate address space for the peripherals, that is, the "I/O space" (I/O space) or "I/O port space". Its size is 64 KB (0x0000-0xffff ). Linux implements the concept of "I/O port space" on all platforms it supports. Because I/O space is very small, even if the peripheral bus has a separate I/O port space, not all peripherals place their I/O Ports (registers) maps to "I/O port space. For example, most PCI cards map their I/O ports or peripheral memory to the CPU's Ram physical address space through memory ing. The old ISA cartoon often maps its I/O port to the I/O port space. Linux manages I/O port resources (I/O-mapped or memory-mapped) based on the concept of "I/O region. Definition of the resource Root Node: Linux in the kernel/resource. the global variables ioport_resource and iomem_resource are defined in file C, to describe the entire I/O port space based on the I/O ing method and the I/O memory resource space (including I/O port and peripheral memory) based on the memory ing method ). It is defined as follows: Struct ResourceIoport_ Resource = { . Name = "PCI Io ", . Start-= 0, . End = io_space_limit, . Flags-= ioresource_io, }; Struct ResourceIomem_ Resource = { . Name = "PCI mem ", . Start-= 0, . End =-1, . Flags-= ioresource_mem, }; Here, the macro io_space_limit represents the size of the entire I/O space, for x86 platforms, it is 0 xFFFF (defined in the include/asm-i386/IO. h header file ). Obviously, the size of I/O memory is 4 GB. Operations on the I/O port space: Based on the I/O region operation function _ xxx_region (), Linux defines three interfaces for operating the I/O port space in the header file include/Linux/ioport. h: Request_region () requests to allocate resources for the specified range of I/O Ports in the I/O port space. Check_region () checks whether the specified I/O port resources in the I/O port space are occupied. Release_region () releases the specified I/O port resource in the I/O port space. Operations on I/O memory resources: Based on the I/O region operation function _ xxx_region (), Linux defines three interfaces for operating I/O memory resources in the header file include/Linux/ioport. h: Request_mem_region () requests to allocate the specified I/O memory resources. Check_mem_region () checks whether the specified I/O memory resources are occupied. Release_mem_region () releases the specified I/O memory resource. Access the I/O port Space(I/O-mapped) -------------------------------------- In the driverProgramAfter the port resource in the I/O port space is requested, it can read and write these I/O ports through the CPU Io command. When reading and writing I/O Ports, note that most platforms distinguish between 8-bit, 16-bit, and 32-bit ports, that is, the width of the I/O port. INB () outb () inw () outw () INL () outl () Unsigned char INB (unsigned port ); The port parameter specifies the port address in the I/O port space. On most platforms (such as x86), it is of the unsigned short type, while on other platforms, it is of the unsigned int type. Obviously, the port address type is determined by the size of the I/O port space.
String operation on the I/O port In addition to these single-shot I/O operations, some CPUs also support sequential read/write operations on an I/O port, that is, to read or write a series of bytes, characters, or 32-bit Integers to a single I/O port, this is the so-called "string I/O instruction" (string instruction ). The speed of such commands is obviously much faster than using loops to implement the same function. InSb () outsb () insw () outw () insl () outsl () Pausing I/O On Some platforms (such as x86), for slow peripherals on older bus (such as ISA), if the CPU reads and writes its I/O Ports too fast, data may be lost. The solution to this problem is to insert a small latency between two consecutive I/O operations to wait for the slow peripherals. This is the so-called "Pausing I/O ". For pausing I/O, Linux is also in the IO. the H header file defines its I/O read/write functions, all of which are named after xxx_p, such as inb_p () and outb_p. Access I/O memory resources (I/O memory) -------------------------------------- Although I/O port space was once widely used on the X86 platform, most modern bus devices use the memory ing mode (memory-mapped) because it is very small) to map its I/O Ports (I/O registers) and peripheral memory. Memory ing-based I/O ports are called "I/O memory" Resources (I/O memory ). Because there are hardware implementation differences between I/O based on memory ing and peripherals, the software is completely transparent, therefore, driver developers can regard the I/O port mapped in memory and the peripheral memory as "I/O memory" resources. I/O memory resources are stored in the physical address space of a single CPU memory, that is, they are in the same physical address space as system Ram. Therefore, I/O memory resources can be accessed through the CPU access command. Generally, when the system is running, the physical address of the peripheral I/O memory resources is known, which can be allocated at startup through the system firmware (such as BIOS, alternatively, you can obtain it through the hardware connection (hardwired) of the device. For example, the physical addresses of the I/O memory resources of the PCI Card can access the I/O memory resources, but must be mapped to the core virtual address space (through the page table ), then, the core virtual address range obtained by the ing can be used to access these I/O memory resources through internal access commands. The physical address is allocated by the pci bios at system startup and written to the bar in the configuration space of the PCI Card. The physical addresses of the I/O memory resources of the ISA card are mapped to the 640kb-1mb range through hardware connections. However, the CPU generally does not reserve a virtual address range for the physical addresses of these known peripheral I/O memory resources, because they are known after the system is started (in a sense dynamic), the driver cannot directly pass through Ing I/O memory resources Linux declares the ioremap () function in the IO. h header file to map the physical address of the I/O memory resource to the core virtual address space (3 GB-4 GB ). Ioremap () for X86 architecture is defined in/usr/src/linux-2.6.21.5/include/asm-i386/IO. h Read/write I/O memory resources After ing the physical address of the I/O memory resources into the core virtual address, theoretically we can directly read and write the I/O memory resources like the read/write Ram. However, since I/O memory and system memory are accessed and processed differently on some platforms, to ensure cross-platform compatibility, linux implements a series of functions for reading and writing I/O memory resources. These functions have different implementations on different platforms. However, on the X86 platform, there is no difference between read/write I/O memory and read/write Ram. As shown below (include/asm-i386/IO. h ): Readb () readw () readl () Writeb () writew () writel () Memset_io () memcpy_fromio () memcpytoio () Obviously, there is no difference between accessing I/O memory resources on the X86 platform and accessing the system's primary Memory RAM. However, to ensure the cross-platform portability of the driver, we should use the above function to access the I/O memory resources, instead of accessing it by pointing to the core virtual address.
|