Have you forgotten the knowledge of io port and io memory? Come and review it again

(1) The Concept of Address

1) Physical Address: This is the address generated by the CPU's address bus and controlled by hardware circuits. A significant portion of the physical address space is reserved for memory on the RAM module, but it can also be mapped to other memory types like video memory or BIOS. When a program uses virtual addresses, they are translated through segment and page mapping to produce a physical address. This physical address is then placed on the CPU’s address lines.

The physical address space includes both physical RAM and bus devices, determined by hardware design. For example, in a 32-bit x86 processor, the physical address space is 2^32, which equals 4GB. However, the actual RAM usually cannot reach 4GB because part of the space is used for buses and other peripherals. In PCs, lower physical addresses are typically allocated to RAM, while higher ones are used for peripheral devices.

2) Bus Address: This refers to the address line or signal generated during the address phase of the bus. Peripherals use the bus address, while the CPU uses the physical address. On the x86 platform, the physical address is the same as the bus address, as they share the same address space. This concept may be confusing, so further explanation follows under "Independent Addressing." On other platforms, conversion or mapping might be required between physical and bus addresses.

3) Virtual Address: Modern operating systems employ Virtual Memory Management, supported by the MMU (Memory Management Unit), which is usually integrated into the CPU. If the MMU is disabled, the CPU directly sends physical addresses to the memory chips. When the MMU is enabled, the CPU sends virtual addresses to the MMU, which translates them into physical addresses before sending them to the external pins of the CPU chip.

In Linux, each process has a 4GB virtual memory space divided into user space (0–3GB) and kernel space (1GB). Programmers only interact with virtual addresses. Each process has its own private user space, which is invisible to others. When the CPU fetches instructions, it uses the virtual address of the current context, and the MMU translates it to a physical address using the page table.

(2) Addressing Methods

1) Peripheral Addressing

Peripherals are accessed by reading and writing to their registers, known as I/O ports. These ports can be addressed using either unified addressing or independent addressing.

Unified Addressing: In this method, I/O ports are treated like regular memory. They occupy specific memory addresses, and part of the main memory is used for I/O. This reduces available memory space. Unified addressing is also called "I/O memory" mode, where peripheral registers reside in the "memory space."

For example, the Samsung S3C2440 ARM processor divides its 4GB address space among peripherals, RAM, and other components. Specific ranges are assigned for LED, SFRs, keyboard, SDRAM, and IDE devices.

Independent Addressing (Single Addressing): In this approach, I/O ports are addressed separately from memory. The CPU must have dedicated I/O instructions (like IN/OUT) and control logic for input/output operations. Intel x86 uses this method, where some memory addresses overlap with I/O addresses.

Independent Addressing is also referred to as the "I/O port" mode, where peripheral registers are located in the "I/O (address) space."

On x86 systems, I/O ports are accessed via IN/OUT instructions. There are 65536 8-bit I/O ports, forming a 64KB I/O address space. This is different from the CPU's physical address space. For example, a 32-bit CPU has a 4GB physical address space, while the I/O space is only 64KB.

Intel x86 platforms often use Memory-Mapped I/O (MMIO), where I/O devices are mapped into memory. This allows the CPU to access I/O ports as if they were memory locations. The Intel TA 719 documentation provides a typical memory address allocation table for x86/x64 systems.

System Resource Allocation

BIOS - 1MB

Local APIC - 4KB

Chipset Reserved - 2MB

IO APIC - 4KB

PCI Device - 256MB

PCI Express Device - 256MB

Display Frame Buffer - 16MB

TSEG - 1MB

Depending on the CPU architecture, a system may use either independent or unified addressing. For instance, PowerPC and m68k use unified addressing, while x86 uses independent addressing with an I/O space. Most embedded microcontrollers like ARM and PowerPC do not provide an I/O space, accessing memory directly. However, the Linux kernel must handle both methods, using functions like request_resource() and release_resource() to manage I/O regions.

(III) Summary of Different Architecture Addressing Methods

Most peripherals are accessed by reading and writing to their registers, known as I/O ports. These include control, status, and data registers, usually addressed consecutively. CPUs address these ports in two ways: I/O-mapped and memory-mapped. The choice depends on the CPU architecture.

CPUs like PowerPC and m68k implement a single physical address space (RAM), mapping I/O ports into this space. This is called "memory-mapped," allowing direct access without special I/O instructions. In contrast, x86 CPUs use a separate I/O address space, requiring special IN/OUT instructions. This I/O space is smaller, typically 64KB, which is a limitation of the I/O-mapped approach.

Linux refers to both I/O-mapped and memory-mapped I/O ports as "I/O regions." Before discussing how Linux manages these, it's important to understand how the kernel abstracts "I/O resources."

(IV) Difference Between IO Port and IO Memory

During driver development, the distinction between IO ports and IO memory is often overlooked. While non-compliant code may work, it is discouraged.

Consider a scenario where the main memory is 16MB of SDRAM, and a peripheral (e.g., a video capture card) has 16MB of SDRAM as a buffer. Understanding the difference between IO ports and IO memory is essential for proper device access.

1. CPU is i386 Architecture: In this case, memory and external I/O are independently addressed. The memory space is 4GB, while the I/O space is 64KB. Accessing I/O ports requires using specific functions like inb/outb. IO memory is mapped into the kernel's memory space using remap before access.

2. CPU is ARM or PPC Architecture: These embedded processors use memory-mapped I/O, meaning I/O ports are addressed via the memory bus. If the system supports 32-bit addressing, the total I/O and memory space can reach 4GB. Accessing such I/O ports can still use dedicated I/O instructions, though the kernel handles the specifics during porting.

3. IO Port vs. IO Memory: Distinguishing between the two involves hardware knowledge. X86 systems have separate I/O and memory spaces, while RISC-based CPUs like ARM and PowerPC use a single memory space. IO ports are those within the I/O space, while IO memory resides in the memory space.

(V) Summary of Access Methods for IO Ports and IO Memory under Linux

1. Accessing IO Ports under Linux: Depending on the CPU architecture, systems may use either independent or unified addressing. For example, PowerPC and m68k use unified addressing, while x86 uses independent addressing with an I/O space. Most embedded systems like ARM and PowerPC do not support an I/O space, accessing memory directly. However, the Linux kernel must handle both approaches, using functions like request_resource() and release_resource() to manage I/O regions.

There are two main methods to access IO ports: I/O-mapped and memory-mapped. The former uses functions like inb/outb, while the latter maps the port to memory and uses memory-access functions.

1. I/O-Mapped Method: Use IO port operation functions like inb(), outb(), etc., after requesting the port range. Release the range when the device is closed or the driver is unloaded. Kernel helper functions simplify this process, such as inb(), inw(), inl(), and their counterparts with "_p" suffixes.

When accessing IO ports, detecting already-assigned ports can be challenging, especially in ISA systems. To avoid conflicts, the kernel tracks I/O ports using a resource tree. Each resource represents a range of I/O port addresses, stored in a structure with start, end, name, flags, and pointers to parent, sibling, and child nodes.

The kernel provides functions like request_resource(), allocate_resource(), and release_resource() to manage these resources. Additionally, shortcut functions like request_region() and release_region() are commonly used to allocate and free I/O port ranges.

2. Memory-Mapped Method: Map the IO port to memory using ioport_map(), then access it using memory-access functions. After use, unmap the address with ioport_unmap(). For accessing I/O memory, use ioread8(), iowrite8(), etc., along with ioremap() to map physical addresses to kernel virtual addresses.

To access IO memory, first request the memory region with request_mem_region(), then map it using ioremap(). Finally, release the mapping with iounmap() and release the memory region with release_mem_region().

3. ioremap and ioport_map: The ioport_map function maps I/O ports to a virtual address space, while ioport_unmap does nothing. This creates an illusion that I/O ports are memory-mapped, allowing developers to use ioread8/iowrite8 functions. The ioread8 function checks whether the address is an I/O port or memory and uses the appropriate read/write function.

Understanding the implementation of these functions helps clarify how Linux handles I/O port and memory access, ensuring efficient and safe interaction with peripheral devices.

Photovoltaic Bracket

Photovoltaic Bracket,supporting structure ground solar,ground solar mounting structure,solar mounting structure,solar ground mount

Hebei Shuobiao New Energy Technology Co., Ltd. , https://www.pvbracketsystem.com