UIO mechanism of Linux device driver (basic concept)

Source: Internet
Author: User
Tags readable

There are two main tasks for a device driver:
1. Accessing the device's memory
2. Interruption of processing equipment

For the first task. The UIO core implements the Mmap () capable of handling physical memory (physical memory), logical (logical
Virtual memory. The UiO drive is written without the need to consider these tedious details.

For the second task, the answer to the device interrupt must be in kernel space. So there's a small piece of code in the kernel space
Used to answer interrupts and prohibit interrupts, but the rest of the work is left to the user for space processing.

Assuming that the user space waits for a device to break, it simply needs to be plugged in to the read () operation on the/dev/uiox.
The read () operation returns immediately when the device generates an interrupt.

UIO also implements the poll () system call. You can use
Select () to wait for the interrupt to occur. Select () has a timeout parameter that can be used to allow for a limited time to wait for interrupts.

The control of the device can also be completed by reading and writing the various files under the/sys/class/uio. Your UiO device will appear under this folder today.


If your UiO device is uio0 then the mapped device memory file is now/SYS/CLASS/UIO/UIO0/MAPS/MAPX. Reading and writing to this file is
Read and write to device memory.


For example, the following diagram describes the kernel part of the UiO drive. The User space section. The relationship between the UiO framework and the kernel intrinsic functions.


 structUio_portio {structKobject Kobj;structUio_port *port;};/** * struct uio_port-description of a uio Port region * @name: Name of the port region for identification * @  Start:start of Port Region * @size: Size of Port region * @porttype: Type of the port (see uio_port_* below) * @portio: For use by the UIO core only. */structUio_port {Const Char*name;unsigned LongStartunsigned LongSizeintPortTypestructUio_portio *portio;};/ * defines for Uio_port->porttype * /#define Uio_port_none 0#define UIO_PORT_X86 1#define UIO_PORT_GPIO 2#define Uio_port_other 3  /* struct uio_mem-description of a UiO memory region * @name: Name of the memory region for identification  * @addr: Address of the device ' s memory * @size: Size of IO * @memtype: type of memory addr points to * @internal_addr: ioremap-ped version of addr, for driver internal use * @map: for use by the UIO core only. */structUio_mem {Const Char*name;//memory-mapped name    unsigned LongAddr//memory block address    unsigned LongSizeThe size of the memory block pointed to by the//ADDR    intMemtype;//uio_mem_phys,uio_mem_logical (Kmalloc ()), uio_mem_virtual (VIRTUAL memory)    void__iomem *internal_addr;//If you had to access this memory region from within your kernel module,                                                               //You'll want to map it internally by using the something like Ioremap ().    structUio_map *map;};structUio_map {structKobject Kobj;structUio_mem *mem;};Static Const structVm_operations_struct Uio_vm_ops = {. Open= Uio_vma_open,. Close= Uio_vma_close,. Fault= Uio_vma_fault,};Static structDevice_attribute uio_class_attributes[] = {__attr (name, S_irugo, Show_name,NULL), __attr (version, S_irugo, Show_version,NULL), __attr (event, S_irugo, Show_event,NULL),    {}};/ * UIO class infrastructure * /Static structClass Uio_class = {. Name="UiO",///sys/class/uio    . Dev_attrs= Uio_class_attributes,};Static Const structFile_operations Uio_fops = {. Owner= This_module,. Open= Uio_open,. Release= Uio_release,. Read= Uio_read,. Write= Uio_write,. Mmap= Uio_mmap,. Poll= Uio_poll,. Fasync= Uio_fasync,. Llseek= Noop_llseek,};/ * Protect IDR accesses * /StaticDefine_mutex (Minor_lock);StaticDEFINE_IDR (UIO_IDR);//about the IDR mechanism. See http://blog.csdn.net/ganggexiongqi/article/details/6737389structUio_device {structModule *owner;structDevice *dev;//Initialize in __uio_register_device    intMinor//Secondary Device ID number, Uio_get_minoratomic_t event;//Interrupt Event Count    structFasync_struct *async_queue;//Asynchronous wait queue on the device//                                                               //About "Asynchronous notifications"//See LDD3, chapter sixthwait_queue_head_t wait;//Wait queue on the device, initialized when the device is registered (__uio_register_device)    intVma_count;structUio_info *info;//Uio_info to the user's manual, assigned in __uio_register_device    structKobject *map_dir;structKobject *portio_dir;};/* struct Uio_info-uio device capabilities * @uio_dev: The UiO device this info belongs to * @name: D Evice name * @version: Device driver version * @mem: List of mappable memory regions, size==0 for end of Lis T * @port: List of port regions, size==0 for end of list * @irq: Interrupt number or Uio_irq_custom * @irq_fl Ags:flags for REQUEST_IRQ () * @priv: Optional Private Data * @handler: The device ' s IRQ handler * @mmap : mmap operation for the UiO device * @open: Open operation for this UiO device * @release: Release op Eration for the UiO device * @irqcontrol: disable/enable IRQs when 0/1 is written to/dev/uiox */     structUio_info {structUio_device *uio_dev;//Initialize in __uio_register_device    Const Char*name;//must initialize before calling __uio_register_device    Const Char*version;//must initialize before calling __uio_register_device    structUio_mem Mem[max_uio_maps];structUio_port Port[max_uio_port_regions];LongIrq//The interrupt number assigned to the UiO device, which must be initialized before calling __uio_register_device    unsigned LongIrq_flags;//must initialize before calling __uio_register_device    void*priv;//Irqreturn_t (*handler) (intIrqstructUio_info *dev_info);called in//uio_interrupt. For interrupt handling                                                                //must initialize before calling __uio_register_device    int(*mmap) (structUio_info *info,structVm_area_struct *VMA);//is called in Uio_mmap,                                                                    //Run the device to open a specific action    int(*open) (structUio_info *info,structInode *inode);//called in Uio_open to run the device to open a specific action    int(*release) (structUio_info *info,structInode *inode);//is called in Uio_device. Run the device to open a specific action    int(*irqcontrol) (structUio_info *info, S32 irq_on);//is called in the Uio_write method, running the user-driven                                                                                       //specific operation. };
  • 1. function: Static int __init uio_init (void)

    Function: Applies the character device number. Equipment. and register in the system, register uio_class to the system
    Calling module: Init_uio_class ()
    Run the process:
    Request a character device number. equipment, and register in the system, register Uio_class to the system//init_uio_class
    Create "/sys/class/uio"

  • 2, Function: Uio_exit
    Function: Unregister uio_class, unregister character device number, delete device
    Calling module: Release_uio_class
    Run the process:
    Unregisters the Uio_class, unregisters the character device number. Remove Device//release_uio_class

  • 3. Function: static void Release_uio_class (void)
    Function: Unregister uio_class, unregister character device number, delete device
    Run the process:
    Logout Uio_class//class_unregister
    Unregisters the character device number. Remove Device//uio_major_cleanup

  • 4. Function: static int init_uio_class (void)
    Function: Applies the character device number. Equipment and register it in the system. Register Uio_class to the system
    Calling module: Uio_major_init ()
    Class_register ()
    Run the process:
    Request a character device number, device, and initialize//uio_major_init
    Register class type global variable Uio_class to system//class_register
    Ls-l/sys/class View

  • 5. Function: static int uio_major_init (void)
    Function: Request character device number, device, and initialize
    Calling module:
    Alloc_chrdev_region ()
    Cdev_alloc ()
    Kobject_set_name ()
    Cdev_add ()
    Run the process:
    Request character device number (multiple)//alloc_chrdev_region
    2^uio_max_devices a Slave device
    The device's name is "UiO"
    Assigns a CDEV structure that represents a character device//cdev_alloc
    Initializes the File_operations type field of the CDEV structure//controls various operations of the CDEV device.
    such as open, close, read, write ...
    The Kobj field of the CDEV structure is set to the name UiO//kobject_set_name
    Add the character device to the system//cdev_add. After the call succeeds, our device is "alive."
    Cat/proc/devices, ability to view assigned to main device number
    Save main device number to global variable Uio_major
    Save device pointer to global variable Uio_cdev

    Return

  • 6. Function: static void Uio_major_cleanup (void)
    Function: Unregisters the character device number. Remove device
    Calling module: unregister_chrdev_region
    Run the process:
    Logoff character device number//unregister_chrdev_region
    Remove Device Uio_cdev//cdev_del

    File_operations

  • 7, function: static int uio_open (struct inode *inode, struct file *filep)

    Number of parameters: Inode:
    Filep:
    function: Get UI associated with secondary device number O_device the pointer, create a helper variable listener, and call the Open method
    in the Uio_info structure that info points to to run the process:
    Get the lock for the protection Uio_idr//mutex_lock
    from Inode Gets the secondary number//iminor
    to get the Uio_device pointer associated with the secondary number//idr_find where to set it???
    //The secondary device number assigned in Uio_get_minor and the association that is set
    Discard the lock//mutex_unlock
    Add the reference count of the module to which the Uio_device type pointer points//try_module_get
    assigns a Uio_listener Type Listener//kmalloc
    Associate Listener and Uio_device pointers
    Get the event count value that Uio_device points to the device. and deposit listener//atomic_read
    Save listener Pointer to Filep->private_data field
    Call Uio_device's Open method in the Uio_info that the info field points to// *

  • 8. Function: Static int uio_release (struct inode *inode, struct file *filep)
    Function: The release method in the Uio_info that calls the Uio_device field info points
    Releasing the auxiliary structural Body listener
    Run the process:
    Gets the listener pointer saved in Uio_open from Filep->private_data.
    Use listener pointer to find pointer to Uio_device type structure
    This invokes the release method in the Uio_info that uio_device the field info points to.


    Reduces the reference count of the module to which the Uio_device type pointer points//module_put
    Release listener structural Body//kfree

  • 9. function: Static int uio_fasync (int fd, struct file *filep, int on)

    Number of references:
    Fd
    Filep
    on:0, delete, non-zero, join
    Function: Manage the async_queue of Uio_device
    Calling module: Fasync_helper ()
    Run the process:
    Gets the listener pointer saved in Uio_open from Filep->private_data.
    Use listener pointer to find pointer to Uio_device type structure
    Set the async_queue//fasync_helper of Uio_device

  • 10. Function: Static unsigned int uio_poll (struct file *filep, poll_table *wait)
    Function: Causes the process to wait on the corresponding waiting queue for all file descriptor descriptors that are passed to the system call. and returns a bitmask that can run without clogging immediately.
    Run the process:
    Gets the listener pointer saved in Uio_open from Filep->private_data.


    Use listener pointer to find pointer to Uio_device type structure
    If the IRQ member of the Info field (Uio_info type) with the Uio_device type pointer is inferred to be not 0, then continue.
    Otherwise, an IO error is returned
    Add the Uio_device type pointer to the Poll_table type's wait table to the structure's wait queue//poll_wait
    //!!!! Note that poll_wait does not clog
    Assume that the event count values in listener Event_count and Uio_device
    The event count value count is inconsistent when//Uio_interrupt calls the uio_event_notify pair
    Interrupt Event Counter Increment one
    Returns the "usual" data-readable bit mask

  • 11. Function: Static ssize_t uio_read (struct file *filep, char __user *buf,
    size_t count, loff_t *ppos)
    Function: Copy the value of the UiO device interrupt event counter to user space

    Run the process:
    Get the listener pointer saved in Uio_open from Filep->private_data
    Use listener pointer to find pointer to Uio_device type structure
    Create an item waiting for the queue//declare_waitqueue
    Check to confirm that the UiO device's device info interrupt number (0) is nonzero
    Join this process to the waiting queue of the UiO device wait on//Add_wait_queue
    Wake-up call uio_event_notify by Uio_interrupt
    REP: Sets the "Interruptible flag" for the current process
    Check if an interrupt event occurs.
    Suppose there are interrupt events (listener in the Interrupt event count value Event_count) and UiO devices
    Counter value is inconsistent), copy the value of the device interrupt counter to the user space
    and updates the Interrupt event count value in listener to the device's interrupt event count value
    Sets the current process to the task_running State,
    and deletes the current process from the wait queue of the UiO device
    Suppose the O_nonblock flag is set when the file is read,
    Then, set the current process to the task_running state.
    and deletes the current process from the wait queue of the UiO device
    Back to-eagain
    Check if the current process has signal processing//signal_pending
    //

    uid=20746501&do=blog&cuid=1820175 ">http://blog.chinaunix.net/space.php?

    uid=20746501&do=blog&cuid=1820175
    If so, set the current process to the task_running State,
    and deletes the current process from the wait queue of the UiO device
    and return to-erestartsys
    Run Schedule//schedule
    JMP REP

  • 12, Uio_register_device
    Function: Call the handler interrupt handler function in Uio_info, and inform the reading process by adding the interrupt event counter of the device. have data to read
    Run the process:
    Get the listener pointer saved in Uio_open from Filep->private_data
    The handler of the Info field (Uio_info type) that invokes the Uio_device type pointer
    Assumes a disruption to this device and has been processed in handler
    Then the interrupt event counter for the device is incremented by one,
    and inform the reading process, there is data readable//uio_event_notify

  • 13. Function: void uio_event_notify (struct uio_info *info)
    function: "Triggers" an interrupt event. Add one to the interrupt event counter for the device and notify the read process with data readable
    Run the process:
    Get the listener pointer saved in Uio_open from Filep->private_data
    Add one to the interrupt event counter
    Wake up the read process blocking on the device waiting queue wait//wake_up_interruptible
    The processes on this queue are joined in the Uio_read
    Sends a readable signal to the asynchronous wait queue Async_queue//kill_fasync

  • 14. Function: Static ssize_t uio_write (struct file *filep, const char __user
    *buf,size_t count, loff_t *ppos)
    Function: Reads the value of the user space and invokes the Irqcontrol function of the Uio_device register
    Run the process:
    Get the listener pointer saved in Uio_open from Filep->private_data
    The handler of the Info field (Uio_info type) that invokes the Uio_device type pointer
    Verify interrupt number for info field (uio_info type) IRQ
    Read the 32-bit value passed from user space//copy_from_user
    Call the Irqcontrol function of the info field (uio_info type). The 32-bit value passed over by the user space is passed in as a number of parameters.

  • 15. Function: Static int uio_mmap (struct file *filep, struct vm_area_struct

    *VMA)

    Run the process:
    Get the listener pointer saved in Uio_open from Filep->private_data
    The handler of the Info field (Uio_info type) that invokes the Uio_device type pointer
    Save uio_device Type pointer to VMA Vm_private_data
    Returns the index of the mapped area (for example, MapX, x)//uio_find_mem_index
    Calculate the actual number of pages and the number of pages requested
    Assume that the actual number of pages is less than the requested number of pages. Back to-einval
    Assume that the UiO device register has a mmap function. Then call it
    When the type of memory area is Uio_mem_phys,
    Uio_mmap_physical
    When the type of memory area is uio_mem_logical, uio_mem_virtual.
    Set the operation for the virtual memory locale, and tell the memory not to
    The area is swapped out. Access Counter Add a//uio_mmap_logical

Linux device-driven UIO mechanism (basic concept)

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.