UIO mechanism of Linux device driver (ii.)

Source: Internet
Author: User

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 () to handle the physical memory (physical memory), the logical RAM (logical memories),
Virtual memory. UiO driver Writing is no need to consider these cumbersome 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.

If the user space waits for a device to break, it simply needs to be blocked on 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, which 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 registered UiO device will appear in this directory.
If your UiO device is uio0 then the mapped device memory file appears in/SYS/CLASS/UIO/UIO0/MAPS/MAPX, which reads and writes to the file
Read and write to device memory.
The following figure depicts the kernel portion of the UiO drive, the user-space section, and the UiO framework and the kernel intrinsics.

 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;//Waiting queue on the device, initializing when registering the device (__uio_register_device)    intVma_count;structUio_info *info;//point to the user registered Uio_info, in the __uio_register_device is assigned the value of the    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 processing                                                                //must initialize before calling __uio_register_device    int(*mmap) (structUio_info *info,structVm_area_struct *VMA);//is called in Uio_mmap,                                                                    //Perform device to open specific actions    int(*open) (structUio_info *info,structInode *inode);//called in Uio_open to perform device open specific operation    int(*release) (structUio_info *info,structInode *inode);//called in Uio_device to perform device open specific operation    int(*irqcontrol) (structUio_info *info, S32 irq_on);//is called in the Uio_write method to perform a user-driven                                                                                       //specific operation. };
  1. function: Static int __init uio_init (void)
    Function: Apply the character device number, device, and register to the system, register uio_class to the system
    Calling module: Init_uio_class ()
    Execution process:
    Apply the character device number, device, and register to the system, register Uio_class to the system//init_uio_class
    Create "/sys/class/uio"


    1. Function: Uio_exit
      Parameters:
      return value:
      Function: Unregister uio_class, unregister character device number, delete device
      Calling module: Release_uio_class
      Execution process:
      Unregister Uio_class, unregister character device number, remove device//release_uio_class

    2. function: static void Release_uio_class (void)
      Parameters:
      return value:
      Function: Unregister uio_class, unregister character device number, delete device
      Calling module:
      Execution process:
      Logout Uio_class//class_unregister
      Unregister character device number, delete device//uio_major_cleanup
  2. function: static int init_uio_class (void)
    Parameters:
    return value:
    Function: Apply the character device number, device, and register to the system, register uio_class to the system
    Calling module: Uio_major_init ()
    Class_register ()
    Execution 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

  3. function: static int uio_major_init (void)
    Parameters:
    return value:
    Function: Request character device number, device, and initialize
    Calling module: Alloc_chrdev_region ()
    Cdev_alloc ()
    Kobject_set_name ()
    Cdev_add ()
    Execution 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
    Adding a character device to the system//cdev_add, when the call succeeds, our device is "alive".
    Cat/proc/devices, you can view the assigned to main device number
    Save main device number to global variable Uio_major
    Save device pointer to global variable Uio_cdev

    Return

  4. function: static void Uio_major_cleanup (void)
    Parameters:
    return value:
    Function: Unregister character device number, delete device
    Calling module: unregister_chrdev_region
    Execution 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)
parameter: inode:
Filep:
return Value:
Function: Get and secondary device number off Uio_device pointer, create an auxiliary variable listener, and call the Open method in the UIO_INFO structure that
Info points to
Call module:
Execution flow:
Get lock for protection UIO_IDR//mutex_ The lock
Gets the secondary number//iminor
from the inode structure to get the Uio_device pointer associated with the secondary number//idr_find where to set it up???
//Assign the secondary device number in Uio_get_minor and set the association
discard the lock//mutex_unlock
Increase the reference count of the module that the Uio_device type pointer points to//try_module_get
assigns a Uio_listener Type Listener//kmalloc
Associate Listener and Uio_device pointers
Get Uio_device point to device event count values and deposit listener//atomic_read
Save the Listener pointer to the Filep->private_data field
Call the Open method in the Uio_info that the info field of the Uio_device refers to// *

  1. function: Static int uio_release (struct inode *inode, struct file *filep)
    Parameters: Inode
    Filep
    return value:
    Function: The release method in the Uio_info that calls the Uio_device field info points
    Releasing the auxiliary structural Body listener
    Calling module:
    Execution 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.
    Reduce the reference count of the module that the Uio_device type pointer points to//module_put
    Release listener structural Body//kfree

  2. function: Static int uio_fasync (int fd, struct file *filep, int on)
    Parameters:
    Fd
    Filep
    on:0, delete, non-zero, add
    return value:
    Function: Manage the async_queue of Uio_device
    Calling module: Fasync_helper ()
    Execution 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

    1. function: Static unsigned int uio_poll (struct file *filep, poll_table *wait)
      Parameter: Filep
      Wait
      return value:
      Function: Causes the process to wait on the waiting queue that corresponds to all file descriptors that are passed to the system call.
      and returns a bitmask that can be executed immediately without blocking
      Calling module:
      Execution process:
      Gets the listener pointer saved in Uio_open from Filep->private_data.
      Use listener pointer to find pointer to Uio_device type structure
      The IRQ member that determines the info field (Uio_info type) with the Uio_device type pointer is not 0, then continues,
      Otherwise, an IO error is returned
      Add the Uio_device type pointer to the wait table of the poll_table type to the wait queue for the structure//poll_wait
      //!!!! Note that Poll_wait does not block
      If the event count value 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

    2. function: Static ssize_t uio_read (struct file *filep, char __user *buf,
      size_t count, loff_t *ppos)
      Parameters:
      Filep
      Buf
      Count
      PPOs
      return value:
      Function: Copy the value of the UiO device interrupt event counter to user space
      Calling module:
      Execution 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
      Add this process to the wait queue on 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 to see if an interrupt event occurs,
      If there is an interrupt event (listener in the Interrupt event count value Event_count) and the UiO device
      Counter value is inconsistent), the value of the device interrupt counter is copied 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
      If 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
      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
      Execution Schedule//schedule
      JMP REP

.
Function: Static irqreturn_t uio_interrupt (int irq, void *dev_id) is called by Who??? __uio_register_device
Parameter: IRQ
dev_id
Return value:
Function: Call the handler interrupt handler that is registered in Uio_info, increase the interrupt event counter for the device by one
and notify the read-in A data-readable
Calling module:
Execution process:
Get listener pointer saved in Uio_open from Filep->private_data
Call the info field of the Uio_device type pointer (uio_ Info Type Handler
If it is an interrupt for this device and has already been processed in handler
then increase the interrupt event counter for the device by one,
and notify the read process, with data readable//uio_event_notify

.
Function: void uio_event_notify (struct uio_info *info)
Parameter:
return value:
Function: "Trigger" an interrupt event, add one to the interrupt event counter of the device, and notify the read process, there is Data
Readable
Call module:
Execution Flow:
Get listener pointer saved in Uio_open from Filep->private_data
Add one
to interrupt event counter wake up blocking on device wait queue Wai The read process on T//wake_up_interruptible
//The process on the queue is added in Uio_read
to the asynchronous wait queue async_queue emit a readable signal//kill_fasync
14.
Function: Static ssize_t uio_write (struct file *filep, const char __user *buf,
size_t count, loff_t *ppos)
Parameters:
return value:
Function: Reads the value of the user space and calls the Uio_device registered Irqcontrol function
Call module:
Execution Flow:
Get Uio_ from Filep->private_data The listener pointer saved in open
calls the handler
of the Info field (uio_info type) of the Uio_device type pointer to verify the interrupt number of the Info field (uio_info type) IRQ
Read the 32-bit value passed from user space//copy_from_user
calls the Irqcontrol function of the info field (uio_info type) to pass in the 32-bit value passed by user space
as a parameter.


    1. function: Static int uio_mmap (struct file *filep, struct vm_area_struct *vma)
      Parameters:
      return value:
      Function:
      Calling module:
      Execution 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
      Returns-einval if the actual number of pages is less than the requested number of pages
      If the UiO device is registered with a mmap function, 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, and the access counter increases by one//uio_mmap_logical

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

UIO mechanism of Linux device driver (ii.)

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.