device
play

Device From kernel-level code Drivers Interact with device(s) - PowerPoint PPT Presentation

Universit degli studi di Udine Universit degli studi di Udine Device Driver Receive requests From user-level code (through syscalls) Device From kernel-level code Drivers Interact with device(s) Send commands Read responses Handle


  1. Università degli studi di Udine Università degli studi di Udine Device Driver Receive requests From user-level code (through syscalls) Device From kernel-level code Drivers Interact with device(s) Send commands Read responses Handle IRQs Send data/result to requester Università degli studi di Udine Università degli studi di Udine Device Driver Driver request Handled in the same context of requester I/O result I/O request Chain of function calls I/O Subsystem Some call can be a syscall Simple I/O result I/O request Device Device Device Driver Driver Driver Device Device Device Handled in a different context SW commands response IRQ HW One or more task devoted to handle requests HW HW HW controller controller controller Interprocess communication Flexible

  2. Università degli studi di Udine Università degli studi di Udine Implementation - objectives Device Drivers Abstraction Simplified interface to devices Driver interface Flexibility Same interface for different devices Modularity Drivers added at: Compile-time (without changes at I/O subsystem) run-time Università degli studi di Udine Università degli studi di Udine Interface Interface Drivers must inform kernel that some new function group exists Drivers expose a set of functions Through global variables Driver exposes its function pointers in initialized data Drivers must register their exposed interface to OS e.g., eCos an exported struct contains: I/O subsystem provides mechanisms to register interface device name Function pointer to a function table pointers read, write, select, get_config, set_config req1 init function req2 Interface req3 lookup function req4 private_info: argument for lookup, init, and functions in table Registered Device Driver drivers I/O Subsystem

  3. Università degli studi di Udine Università degli studi di Udine Interface Interface Drivers must inform kernel that some new function group exists Drivers must inform kernel that some new function group exists Through initialization function Through initialization function Kernel invokes a module initialization function Kernel invokes a module initialization function e.g., Windows e.g., Linux initialization function is exported as driver's entry point initialization function is indicated as “ entry point ” in the binary header default name: “ DriverEntry ” int my_driver_init(void); module_init(my_driver_init); NTSTATUS DriverEntry( struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath); the initialization function the initialization function prepare a structure with function pointers Implicit registration fills a struct (received by kernel) with driver function pointers Explicit registration invoke the kernel registration function to add the new function group DriverObject->DriverUnload = My_Drv_Unload; DriverObject->MajorFunction[IRP_MJ_READ] = My_Drv_Read; kernel can set the value of some “exported” variables as parameters DriverObject->MajorFunction[IRP_MJ_WRITE] = My_Drv_Write; receives a registry path to check for persistent parameters Università degli studi di Udine Università degli studi di Udine Explicit registration Explicit registration I/O subsystem provides functions to Function pointers Register/unregister interfaces req1 Register an IRQ handler req2 Interface req3 Assign a function to an IRQ req4 Allocate resources Registered drivers Device Driver I/O addresses, GPIOs, memory, ... I/O Subsystem Initialization: register driver interface

  4. Università degli studi di Udine Università degli studi di Udine Device Drivers Linux drivers interfaces File-based driver interface Driver interface Character devices Linux drivers interface Block devices Network driver interface Università degli studi di Udine Università degli studi di Udine Linux character-devices interface Linux drivers interfaces implementation Driver structure File-based driver interface Pointer to the module that implements the driver Other driver (NULL if the driver is built-in in kernel) data fields Character devices cdev Interface: kobj kobj file_operations open, release, read, write, llseek, unlocked_ioctl, mmap, ... owner Device major and owner ops ops minor numbers llseek llseek Structures: list list read read dev dev write write struct cdev Usage count count count struct file_operations Registration: Other driver data fields alloc_chrdev_region Driver functions cdev_alloc cdev_add cdev structure: list of cdev structures allocated by driver, managed by kernel

  5. Università degli studi di Udine Università degli studi di Udine Linux character-devices: Linux drivers interfaces open function Prototype: File-based driver interface void open (struct inode *, struct file *); Block devices Driver structure Interface: pointer set by driver struct inode (if needed) open, release, ioctl, ... i_cdev request_fn, make_request_fn, ... i_cdev cdev No read and write functions kobj kobj Structures: owner file_operations owner ops ops struct gendisk list driver can change the f_op llseek llseek list struct file dev read read dev struct block_device_operations count write write count pointer during device struct request_queue private_data private_data opening if needed Registration: f_op f_op register_blkdev alloc_disk Arguments (from kernel) blk_init_queue struct file argument will be used by next function calls (read, write, etc.) add_disk Università degli studi di Udine Linux drivers interfaces Network driver interface Interface: ndo_init, ndo_uninit, ndo_open, ndo_stop, ndo_start_xmit, ndo_tx_timeout, ndo_do_ioctl, ndo_change_mtu, ndo_get_stats, ... No receive function Structures: struct net_device struct net_device_ops Registration: alloc_netdev register_netdev

  6. Università degli studi di Udine Università degli studi di Udine Device Drivers Linux kernel-level coding Concurrency - use reentrant code Current process (if appliable): current Linux current->comm (command name) current->pid kernel coding Limited stack size No large automatic variables No floating point Floating point context is not saved No standard headers and standard libs N.B.: facilities are available to kernel just after registration Università degli studi di Udine Università degli studi di Udine Other info Device Drivers Syscalls in kernel: sys_ Linux kernel coding Low level kernel interface: names start with __ Use with caution Symbols /proc/kallsyms Loaded modules /proc/modules Init / Cleanup Devices and major number /proc/devices Resources /proc/interrupts /proc/iomem /proc/ioports Memory access /dev/kmem (Kernel virtual memory access) /dev/mem (Physical memory access) Kernel core /proc/kcore

  7. Università degli studi di Udine Università degli studi di Udine Initialization code Cleanup code Require resources Release resources Memory, device numbers, address ranges, synchronization, ... De-register features Register features Interfaces, irq handlers, ... Typically no result value is needed Return a result Typically: 0: success negative: error code Handle failure Check returned codes Release resources on failure De-register features on failure Università degli studi di Udine Università degli studi di Udine Init code example Cleanup code example int init_func(void) void cleanup_func(void) { { int res; release_resource_C ( ... ); release_resource_B ( ... ); res = require_resource_A ( ... ); release_resource_A ( ... ); if (res < 0) } goto fail_A; res = require_resource_B ( ... ); If called, all resources are allocated if (res < 0) goto fail_B; res = require_resource_C ( ... ); if (res < 0) goto fail_C; return 0; /* success */ /* release_resource_C (...); */ Regular code, fail_C: release_resource_B ( ... ); no duplicated calls, fail_B: release_resource_A ( ... ); easy to maintain. fail_A: Uses goto return res; }

  8. Università degli studi di Udine Università degli studi di Udine Device Drivers Integer types Exact-width integer types: Linux kernel coding kernel space user space C99 s8 __s8 int8_t 8 bit u8 __u8 uint8_t s16 __s16 int16_t 16 bit u16 __u16 uint16_t Data types s32 __s32 int32_t 32 bit u32 __u32 uint32_t s64 __s64 int64_t 64 bit u64 __u64 uint64_t Integer for pointers types: kernel space C99 intptr_t unsigned long uintptr_t Università degli studi di Udine Università degli studi di Udine Doubly linked list Doubly linked list: reference LIST_HEAD (list_name) struct list_head compile-time initialization: defines list_name as an empty list (of type struct list_head) next next prev prev void INIT_LIST_HEAD (struct list_head *list) next next next next next next next next run-time initialization prev prev prev prev prev prev prev prev e.g., struct list_head mylist; INIT_LIST_HEAD(&mylist); custom struct custom struct custom struct custom struct void list_add (struct list_head *new, struct list_head *head) add a new entry: new is inserted as first element of head (used for implementing stacks) void list_add_tail (struct list_head *new, struct list_head *head) add a new entry: new is inserted as last element of head (used for implementing queues)

Recommend


More recommend