The Nineth chapter of Linux Device Drivers and hardware communication

Source: Internet
Author: User

  • Overview, this chapter formally touches on real hardware.
    • Describes methods and functions that provide I/O access to devices for reading data from or writing data to a device
    • and detailing I/O ports and I/O memory
  • I/O ports and I/O memory
      • Each peripheral is controlled by a read-write register
      • at the hardware level, there is no conceptual difference between the memory area and the I/O area: They are accessed by sending level signals to the address bus and control bus, and then reading and writing data via the data bus
      • i/ The most important difference between the O register and the general memory
        • I/O register and RAM is that I/O operations have marginal effects, whereas memory operations do not have
          • memory writes the only result is to store a value in the specified location
          • memory Read The operation simply returns the value of the last write to the specified position.
        • The problem caused by the hardware's own cache is well resolved: simply configure the underlying hardware to prohibit the hardware cache when accessing the I/O zone
        • compiler optimizations and hardware reordering The solution to the problem is to set the memory barrier between the operations that the hardware must perform in a particular order
        • Linux provides 4 macros to resolve all possible sorting problems
          • <linux/kernel.h>
            • void barrier (void);
          • <asm/system.h>
            • void Rmb (void);
            • void read_barrier_depends (void);
            • void wmb (void);
            • void mb (void);
            • void Smp_rmb (void);
            • void smp_read_barrier_depends (void);
            • void smp_wmb (void);
            • void smp_mb (void);
        • because memory barriers can affect system performance, they should only be used where they really need to be.

  • Using the I/O port
    • The I/O port is the way the driver communicates with many devices
    • I/O port assignment
      • <linux/ioport.h>
        • struct Resource *request_region (unsigned long first, unsigned long n, const char *name);
        • void Release_region (unsigned long start, unsigned long n);
        • int check_region (unsigned long first, unsigned long n);
      • All port assignments can be obtained from the/proc/ioports
    • Operating I/O ports
      • Most hardware separates 8-bit, 16-bit, and 32-bit ports
      • <asm/io.h>
        • Unsigned inb (unsigned port);
        • void Outb (unsigned char byte, unsigned port);
        • Unsigned inw (unsigned port);
        • void outw (unsigned short word, unsigned port);
        • unsigned inl (unsigned port);
        • void Outl (unsigned longword, unsigned port);
      • The port address space uses a maximum of 32-bit data paths even on 64-bit architectures
    • Accessing the I/O port in user space
      • <sys/io.h>
      • If you want to use INB and its related functions in your user space code, you must meet the following criteria
        • You must compile the program with the-O option to force the expansion of the inline function
        • You must use the Ioperm or IOPL system call to obtain permissions to the port for I/O operations. Ioperm is used to obtain operational permissions on a single port, while IOPL is used to gain operational permissions for the entire I/O space
        • The program must be run as root to invoke ioperm or IOPL, or one of the process's ancestor processes has acquired access to the port as root
    • String operations
      • void InSb (unsigned port, void *addr, unsigned long count);
      • void outsb (unsigned port, void *addr, unsigned long count);
      • void Insw (unsigned port, void *addr, unsigned long count);
      • void Outsw (unsigned port, void *addr, unsigned long count);
      • void inSL (unsigned port, void *addr, unsigned long count);
      • void Outsl (unsigned port, void *addr, unsigned long count);
    • Paused I/O
      • Some platforms encounter problems when the processor tries to transfer data quickly from the bus
      • The problem occurs when the processor clock is faster than the peripheral clock and is displayed when the device board is particularly slow
      • The workaround is to insert a small delay after each I/O instruction, if there are other similar instructions
      • On the x86 platform, this pause can be achieved by specifying an out B for Port 0x80, or by using a busy wait implementation
      • Paused I/O functions: inb_p, outb_p, etc.
    • Platform dependencies
      • I/O directives are closely related to the processor
      • IA-32 (x86), x86_64
        • This architecture supports all the functions mentioned in this chapter, the type of port number is unsigned short
      • IA-64 (Itanium)
        • Supports all functions, port type is unsigned long (mapped to memory)
      • Arm
        • Port mapped to memory, all functions supported, port type unsigned int
  • Example of I/O port
    • The most common form of a data I/O port is a byte-width I/O region that is either mapped to memory or mapped to a port
    • Introduction to the same port
      • The minimum configuration of the same port consists of 3 8-bit ports
      • The first I/O port in the PC standard is starting from address 0x378, and the second port starts at address 0x278
      • The first port is a bidirectional data register that is directly connected to the 2-9 pin of the physical connector
      • The second port is a read-only status register that reports the status of the printer when the connector is connected to the printer
      • The third port is a control register for output only, and one of its functions is to control whether interrupts are enabled
      • The level signal used in parallel communication is the standard TTL level: 0 volts and 5 volts with a logic threshold of approximately 1.2 volts
  • Using I/O memory
    • Another major mechanism for communicating with devices is by using a register or device memory mapped to memory
    • I/O memory allocation and mapping
      • <linux/ioport.h>
        • struct Resource *request_mem_region (unsigned long start, unsigned long len, char *name);
        • void Release_mem_region (unsigned long start, unsigned long len);
        • int check_mem_region (unsigned long start, unsigned long len);
      • /proc/iomem
      • Getting I/O memory does not just mean referencing the corresponding pointer, we must first establish the mapping, the mapping is done by the IOREMAP function
      • <asm/io.h>
        • void *ioremap (unsigned long phys_addr, unsigned long size);
        • void *ioremap_nocache (unsigned long phys_addr, unsigned long size);
        • void Iounmap (void *addr);
    • Accessing I/O memory
      • The correct way to access I/O memory is through a set of specialized functions
      • <asm/io.h>
        • unsigned int ioread8 (void *addr);
        • unsigned int ioread16 (void *addr);
        • unsigned int ioread32 (void *addr);
        • void Iowrite8 (U8 value, void *addr);
        • void Iowrite16 (U16 value, void *addr);
        • void Iowrite32 (u32 value, void *addr);
        • 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 8addr, const void *buf, unsigned long count);
        • 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);
        • unsigned readb (address);
        • unsigned readw (address);
        • unsigned readl (address);
        • void Writeb (unsinged value, address);
        • void Writew (unsigned value, address);
        • void Writel (unsigned value, address);
      • Addr should be the address obtained from Ioremap.
    • Use ports like I/O memory
      • void *ioport_map (unsigned long port, unsigned int count);
        • The function remap count I/O ports so that it looks like I/O memory and the driver can use IOREAD8 and its similar functions on the address returned by the function
      • void Ioport_unmap (void *addr);
    • ISA memory under the 1MB address space
      • The memory range of the ISA memory segment is between 640KB and 1MB and appears in the middle of regular ram

The Nineth chapter of Linux Device Drivers and hardware communication

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.