linux device drivers
TRANSCRIPT
![Page 1: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/1.jpg)
Team Emertxe
Linux Device DriversDeep dive into leveraging devices
![Page 2: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/2.jpg)
Introduction
![Page 3: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/3.jpg)
Familiarity Check
● Good C & Programming Skills
● Linux & the Filesytem
– Root, User Space Headers & Libraries
● Files
– Regular, Special, Device
● Toolchain
– gcc & friends
● Make & Makefiles
● Kernel Sources (Location & Building)
![Page 4: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/4.jpg)
Linux Driver Ecosystem
bash gvim X Server gcc firefox
`
`
ProcessManagement
ssh
MemoryManagement File Systems
DeviceControl Networking
ArchitectureDependent
Code
CharacterDevices
MemoryManager
FilesystemTypes
BlockDevices
NetworkSubsystem
IFDevices
ConcurrencyMultiTasking
VirtualMemory
Files & Dirs:The VFS
Ttys &Device Access
Connectivity
CPU Memory Disks &CDs
Consoles,etc
NetworkInterfaces
![Page 5: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/5.jpg)
The Flow
● Introduction
● Character Drivers
● Memory & Hardware
● Time & Timings
● USB Drivers
● Interrupt Handling
● Block Drivers
● PCI Drivers
![Page 6: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/6.jpg)
Hands-On
● Your First Driver
● Character Drivers
– Null Driver
– Memory Driver
– UART Driver for Customized Hardware
● USB Drivers
– USB Device Hot-plug-ability
– USB to Serial Hardware Driver
● Filesystem Modules
– VFS Interfacing
– “Pseudo” File System with Memory Files
![Page 7: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/7.jpg)
Kernel Source Organization
Kernel Source
include
net
drivers
block
fs
mm
kernel
arch/<arch>
char mtd/ide net pci ...usbserial
asm-<arch>linux
![Page 8: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/8.jpg)
The Locations & Config Files
● Kernel Source Path: /usr/src/linux
● Std Modules Path:
– /lib/modules/<kernel version>/kernel/...
● Module Configuration: /etc/modprobe.conf
● Kernel Windows:
– /proc
– /sys
● System Logs: /var/log/messages
![Page 9: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/9.jpg)
The Commands
● lsmod
● insmod
● modprobe
● rmmod
● dmesg
● objdump
● nm
● cat /proc/<file>
![Page 10: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/10.jpg)
The Kernel's C
● ctor & dtor
– init_module, cleanup_module
● printf
– printk
● Libraries
– <kernel src>/kernel
● Headers
– <kernel src>/include
![Page 11: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/11.jpg)
The Init Code
static int __init mfd_init(void){
printk(KERN_INFO "mfd registered");
...
return 0;
}module_init(mfd_init);
![Page 12: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/12.jpg)
The Cleanup Code
static void __exit mfd_exit(void){
printk(KERN_INFO "mfd deregistered");
...
}module_exit(mfd_exit);
![Page 13: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/13.jpg)
Usage of printk
● <linux/kernel.h>
● Constant String for Log Level– KERN_EMERG "<0>" /* system is unusable */
– KERN_ALERT "<1>" /* action must be taken immediately */
– KERN_CRIT "<2>" /* critical conditions */
– KERN_ERR "<3>" /* error conditions */
– KERN_WARNING "<4>" /* warning conditions */
– KERN_NOTICE "<5>" /* normal but significant condition */
– KERN_INFO "<6>" /* informational */
– KERN_DEBUG "<7>" /* debug-level messages */
● printf like arguments
![Page 14: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/14.jpg)
The Other Basics & Ornaments
● Headers
– #include <linux/module.h>
– #include <linux/version.h>
– #include <linux/kernel.h>● MODULE_LICENSE("GPL");
● MODULE_AUTHOR("Emertxe");
● MODULE_DESCRIPTION("First Device Driver");
![Page 15: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/15.jpg)
Building the Module
● Our driver needs– The Kernel Headers for Prototypes
– The Kernel Functions for Functionality
– The Kernel Build System & the Makefile for Building
● Two options– Building under Kernel Source Tree
● Put our driver under drivers folder● Edit Kconfig(s) & Makefile to include our driver
– Create our own Makefile to do the right invocation
![Page 16: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/16.jpg)
Our Makefile
ifneq (${KERNELRELEASE},)obj-m += <module>.o
elseKERNEL_SOURCE := <kernel source directory path>
PWD := $(shell pwd)
default:$(MAKE) -C ${KERNEL_SOURCE} SUBDIRS=$(PWD) modules
clean:$(MAKE) -C ${KERNEL_SOURCE} SUBDIRS=$(PWD) clean
endif
![Page 17: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/17.jpg)
Try Out your First Driver
![Page 18: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/18.jpg)
Character Drivers
![Page 19: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/19.jpg)
Major & Minor Number
● ls -l /dev
● Major is to Driver; Minor is to Device
● <linux/types.h> (>= 2.6.0)
– dev_t: 12 & 20 bits for major & minor● <linux/kdev_t.h>
– MAJOR(dev_t dev)
– MINOR(dev_t dev)
– MKDEV(int major, int minor)
![Page 20: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/20.jpg)
Registering & Unregistering
● Registering the Device Driver
– int register_chrdev_region(dev_t first, unsigned int count, char *name);
– int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int cnt, char *name);
● Unregistering the Device Driver
– void unregister_chrdev_region(dev_t first, unsigned int count);
● Header: <linux/fs.h>
![Page 21: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/21.jpg)
The file operations
● #include <linux/fs.h>
● struct file_operations– int (*open)(struct inode *, struct file *);
– int (*release)(struct inode *, struct file *);
– ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
– ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
– struct module owner = THIS_MODULE; / linux/module.h> */
– loff_t (*llseek)(struct file *, loff_t, int);
– int (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
![Page 22: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/22.jpg)
User level I/O
● int open(const char *path, int oflag, ... )
● int close(int fd);
● ssize_t write(int fd, const void *buf, size_t nbyte)
● ssize_t read(int fd, void *buf, size_t nbyte)
● int ioctl(int d, int request, ...)
– The ioctl() function manipulates the underlying device parameters of special files.
– The argument d must be an open file descriptor.
– The second argument is a device-dependent request code.
![Page 23: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/23.jpg)
The file & inode structures
● struct file
– mode_t f_mode
– loff_t f_pos
– unsigned int f_flags
– struct file_operations *f_op
– void * private_data● struct inode
– unsigned int iminor(struct inode *);
– unsigned int imajor(struct inode *);
![Page 24: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/24.jpg)
Registering the file operations
● #include <linux/cdev.h>
● 1st way initialization:
– struct cdev *my_cdev = cdev_alloc();
– my_cdev->owner = THIS_MODULE;
– my_cdev->ops = &my_fops;● 2nd way initialization:
– struct cdev my_cdev;
– cdev_init(&my_cdev, &my_fops);
– my_cdev.owner = THIS_MODULE;
– my_cdev.ops = &my_fops;
![Page 25: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/25.jpg)
Registering the file operations...
● The Registration– int cdev_add(struct cdev *cdev, dev_t num,
unsigned int count);
● The Unregistration– void cdev_del(struct cdev *cdev);
![Page 26: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/26.jpg)
Registering/UnregisteringOld Way
● Registering the Device Driver
– int register_chrdev(undigned int major, const char *name, struct file_operations *fops);
● Unregistering the Device Driver
– int unregister_chrdev(undigned int major, const char *name);
![Page 27: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/27.jpg)
The read flow
struct file-------------------------
f_countf_flagsf_mode
-------------------------f_pos
-------------------------......
ssize_t my_read(struct file *f, char __user *buf, size_t cnt, loff_t *off)
Buffer(in the driver)
Buffer(in the
applicationor libc)
Kernel Space (Non-swappable) User Space (Swappable)
copy_to_user
![Page 28: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/28.jpg)
The /dev/null read & write
ssize_t my_read(struct file *f, char __user *buf, size_t cnt, loff_t *off)
{...
return read_cnt;
}ssize_t my_write(struct file *f, char __user *buf, size_t cnt, loff_t
*off){
...
return wrote_cnt;
}
![Page 29: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/29.jpg)
The mem device read
ssize_t my_read(struct file *f, char __user *buf, size_t cnt, loff_t *off)
{...
if (copy_to_user(buf, from, cnt) != 0)
{
return -EFAULT;
}
...
return read_cnt;
}
![Page 30: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/30.jpg)
The mem device write
ssize_t my_write(struct file *f, char __user *buf, size_t cnt, loff_t *off)
{...
if (copy_from_user(to, buf, cnt) != 0)
{
return -EFAULT;
}
...
return wrote_cnt;
}
![Page 31: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/31.jpg)
Dynamic Device Node & Classes
● Class Operations– struct class *class_create(struct module *owner, char
*name);
– void class_destroy(struct class *cl);
● Device into & Out of Class– struct class_device *device_create(struct class *cl, NULL,
dev_t devnum, NULL, const char *fmt, ...);
– void device_destroy(struct class *cl, dev_t devnum);
![Page 32: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/32.jpg)
The I/O Control API
● int (*ioctl)(struct inode *, struct file *, unsigned int cmd, unsigned long arg)
● Command
– <linux/ioctl.h> -> ... -> <asm-generic/ioctl.h>
– Macros● _IO, _IOR, _IOW, _IOWR
– Parameters● type (character) [15:8]● number (index) [7:0]● size (param type) [29:16]
![Page 33: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/33.jpg)
Module Parameters
● <linux/moduleparam.h>
– Macros● module_param(name, type, perm)● module_param_array(name, type, num, perm)● Perm (is a bitmask)
– 0– S_IRUGO– S_IWUSR | S_IRUGO
– Loading● insmod driver.ko name=10
![Page 34: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/34.jpg)
x86 Architecture
AB
![Page 35: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/35.jpg)
Memory Access
![Page 36: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/36.jpg)
Physical Vs Virtual Memory
● The kernel Organizes Physical memory in to pages
– Page size Depends on Arch● X86-based 4096 bytes
● On 32-bit X86 system Kernel total Virtual address space
– Total 4GB (pointer size)
– Kernel Configuration Splits 4GB in to● 3BG Virtual Sp for US● 1GB Virtual Sp for Kernel
– 128MB KDS– Virtual Address also called “Logical Address”
![Page 37: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/37.jpg)
Memory Access fromKernel Space● Virtual Address on Physical Address
– #include <linux/gfp.h>● unsigned long __get_free_pages(flags, order); etc● void free_pages(addr, order); etc
– #include <linux/slab.h>● void *kmalloc(size_t size, gfp_t flags);
– GFP_ATOMIC, GFP_KERNEL, GFP_DMA
● void kfree(void *obj);
– #include <linux/vmalloc.h>● void *vmalloc(unsigned long size);● void vfree(void *addr);
![Page 38: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/38.jpg)
Memory Access from Kernel Space...● Virtual Address for Bus/IO Address
– #include <asm/io.h>● void *ioremap(unsigned long offset, unsigned long size);● void iounmap(void *addr);
● I/O Memory Access
– #include <asm/io.h>● unsigned int ioread[8|16|32](void *addr);
● unsigned int iowrite[8|16|32](u[8|16|32] value, void *addr);
● Barriers– #include <linux/kernel.h>: void barrier(void);
– #include <asm/system.h>: void [r|w|]mb(void);
![Page 39: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/39.jpg)
Hardware Access
![Page 40: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/40.jpg)
I/O Accesses from Kernel Space
● I/O Port Access– #include <asm/io.h>
● unsigned in[b|w|l](unsigned port);● void out[b|w|l](unsigned [char|short|int] value,
unsigned port);
![Page 41: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/41.jpg)
Hands-On the Hardware
![Page 42: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/42.jpg)
Debugging
![Page 43: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/43.jpg)
Debugging Options
● Printing & syslogd
● Querying
– /proc
– Using ioctl
– sysfs
● Watching
– strace
– Oops
![Page 44: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/44.jpg)
Creating /proc entry's
● Creating read-only /proc entry's– #include <linux/pros_fs.h>
– proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);
– remove_proc_entry(const char *name, struct proc_dir_entry *parent)
![Page 45: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/45.jpg)
Advanced Debugging
● Debuggers– gdb <kernel src>/vmlinux /proc/kcore
– Non-official Kernel Debugger kdb (oss.sgi.com)
– kgdb & Remote Debugging
● Use Mode Linux (UML)● LTT (http://www.opersys.com/LTT)
![Page 46: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/46.jpg)
Concurrency
![Page 47: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/47.jpg)
Concurrency & Locking
● Semaphore: <asm/semaphore.h>– Type: struct semaphore
– DECLARE_*, init_MUTEX, down[_trylock], up
● Spin Locks: <linux/spinlock.h>– Type: spinlock_t
– spin_lock_init, spin_[try]lock, spin_unlock
![Page 48: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/48.jpg)
Concurrency without Locking
● Atomic Variables: <asm/atomic.h>– Type: atomic_t
– ATOMIC_INIT, atomic_*
● Atomic Bit Operations: <asm/bitops.h>– [set|clear|change|test*]_bit(nr, void *addr)
![Page 49: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/49.jpg)
Time Keeping
![Page 50: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/50.jpg)
Time since Bootup
● <linux/param.h> - HZ
● <linux/jiffies.h> - jiffies & jiffies_64
– time_after, time_before, ...
– get_jiffies_64, ...
– timespec/timeval vs jiffies
● Platform specific “Time Stamp Counter”
– <asm/msr.h> - rdtsc
– <linux/timex.h> - get_cycles
![Page 51: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/51.jpg)
Absolute Time
● <linux/time.h>– mktime(y, m, d, h, m, s) – Seconds since Epoch
– void do_gettimeofday(struct timeval *tv);
– struct timespec current_kernel_time(void);
![Page 52: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/52.jpg)
Delays
![Page 53: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/53.jpg)
Busy Wait & Yielding
● Busy wait: cpu_relaxwhile (time_before(jiffies, j1))
cpu_relax();
● Yielding: schedule/schedule_timeoutwhile (time_before(jiffies, j1))
schedule();
● <linux/wait.h>: Wait Qs– wait_event_timeout
– wait_event_interruptible_timeout
![Page 54: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/54.jpg)
The WaitQ Example
wait_queue_head_t wait;
init_waitqueue_head(&wait);
wait_event_interruptible_timeout(wait, 0, delay)
![Page 55: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/55.jpg)
More Precise Busy Waiting
● #include <linux/delay.h>● Architecture specific impl. in <asm/delay.h>● void ndelay(unsigned long ndelays);● void udelay(unsigned long udelays);● void mdelay(unsigned long mdelays);
![Page 56: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/56.jpg)
Back to Yielding
● #include <linux/delay.h>● void msleep(unsigned int millisecs);● unsigned long msleep_interruptible(unsigned
int millisecs);● void ssleep(unsigned int secs);
![Page 57: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/57.jpg)
Timers
![Page 58: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/58.jpg)
Kernel Timers
● Back end of the various delays
● <linux/timer.h>
● void init_timer(struct timer_list *);
● struct timer_list TIMER_INITIALIZER(f, t, p);
● void add_timer(struct timer_list *);
● void del_timer(struct timer_list *);
● int mod_timer(struct timer_list *, unsigned long);
● int del_timer_sync(struct timer_list *);
![Page 59: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/59.jpg)
Tasklets
● Timers without specific Timing
● <linux/interrupt.h>
● void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
● DECLARE_TASKLET(name, func, data);
● tasklet_disable/enable(t);
● tasklet_[hi_|]_schedule(t);
● tasklet_kill(t);
![Page 60: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/60.jpg)
Work Queues
In context of “Special Kernel Process”
<linux/workqueue.h>● struct workqueue_struct *q = create_workqueue(name);
● struct workqueue_struct *q = create_singlethread_workqueue(name);
● DECLARE_WORK(w, void (*function)(void *), void *data);
● int queue_work(q, &w);
● int queue_delayed_work(q, &w, d); / int cancel_delayed_work(&w);
● flush/destroy_workqueue(q);
![Page 61: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/61.jpg)
Context Specific Functions
● <asm/hardirq.h>● in_interrupt()● in_atomic()
![Page 62: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/62.jpg)
USB Drivers
![Page 63: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/63.jpg)
USB Key Features
● Single Master on Host
● Polls the Peripheral Slaves
● Started as a Unified Bus for Slow Devices
● High Speed Specifications
● Bandwidth Allocation Ability
● Linux Device Driver Support– USB Host Driver
– USB Gadget Driver
![Page 64: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/64.jpg)
USB In PC Env
![Page 65: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/65.jpg)
USB Device Overview
Device
Config Interface
Endpoint
Endpoint
Endpoint
Endpoint
Endpoint
Endpoint
Interface
USBDriver
USBDriver
![Page 66: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/66.jpg)
USB Endpoints
● Also called Pipes
● Direction– OUT (host->device)
– IN (device->host)
● Types
– Control
– Interrupt
– Bulk
– Isochronous
![Page 67: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/67.jpg)
USB Data Structures
● struct usb_host_endpoint– struct usb_endpoint_descriptor
● struct usb_interface● struct usb_host_config● struct usb_device
– interface_to_usbdev
![Page 68: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/68.jpg)
USB Driver Overview
VFSLayer
USB Device Drivers
USB Core
USB Host Controllers
...TTYLayer
CharLayer
NetLayer
BlockLayer
Kernel Space
User
USB Hardware
Hardware
User Space}
}
![Page 69: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/69.jpg)
USB Core Driver
● Sysfs● USB Driver Registration / Unregistration● USB Device Hot Plugability
– probe: USB Device Registration
– disconnect: USB Device Unregistration
● USB Transfers through URBs
![Page 70: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/70.jpg)
USB & Sysfs
● /sbin/lspci– <dom>:<bus>:<dev>:<fn> for <usbhubid>
● /sys/devices/pci0000:00/<usbhubid>/usb<hub>– usb_device fields
– roothub-hubport:config.interface● usb_interface fields
![Page 71: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/71.jpg)
USB Driver Registration
● struct usb_driver
– struct module *owner
– const char *name
– const struct usb_device_id *id_table
– int (*probe)(struct usb_interface *, struct usb_device_id *)
– int (*disconnect)(struct usb_interface *)
● int usb_register(struct usb_driver *)
● int usb_deregister(struct usb_driver *)
![Page 72: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/72.jpg)
USB Device Hot-plug-ability
● Callback probe– int usb_register_dev(intf, class)
● Callback disconnect– int usb_deregister_dev(intf, class)
● void usb_set_intfdata(intf, void *data)● void *usb_get_intfdata(intf)
![Page 73: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/73.jpg)
USB Request Block
● struct urb
– struct usb_device *dev
– unsigned int pipe
– unsigned int transfer_flags
– void *transfer_buffer
– int transfer_buffer_length
– usb_complete_t complete
– int actual_length
– int status
– Pipe type specific fields
![Page 74: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/74.jpg)
URB Operations
● usb_alloc_urb / usb_free_urb● usb_fill_[int|bulk|control]_urb● usb_submit_urb● usb_unlink_urb / usb_kill_urb
![Page 75: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/75.jpg)
USB Transfer Wrappers
● usb_bulk_msg(dev, pipe, data, len, &act_len, timeout);
● usb_control_msg(dev, pipe, req, req_type, value, index, data, size, timeout);
![Page 76: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/76.jpg)
The Real USB Device
![Page 77: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/77.jpg)
USB to Serial Hardware
![Page 78: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/78.jpg)
Interrupts
![Page 79: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/79.jpg)
LSPs
● Architecture Specific Code:– arch/<arch>
– include/asm
● Machine Specific Code:– arch/<arch>/mach-*
– include/asm/mach-*
● Linux Support Package– Machine or Board Specific Code
– include/asm/mach-default
![Page 80: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/80.jpg)
IRQs
● Numbers derived by CPU & Board● Programmed in Interrupt Controller● x86 Specific: 0x00 to 0x1F● Board Specific: 0x20 to 0xFF
– <asm/interrupt.h> -> <asm/irq.h> -> irq_vectors.h
![Page 81: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/81.jpg)
The APIs
<asm/interrupt.h>
● typedef irqreturn_t (*irq_handler_t)(int, void *);
● int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev_id);
● void free_irq(unsigned int irq, void *dev_id);
● int can_request_irq(irq, flags);
● Flags– IRQF_TRIGGER_RISING , IRQF_TRIGGER_FALLING, IRQF_SHARED, ...
![Page 82: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/82.jpg)
The Additional Info
● IRQ Control– enable_irq(irq)
– disable_irq(irq)
● Autoprobing IRQs– irqs = probe_irq_on();
– irq = probe_irq_off(irqs);
● IRQ Handler returns– IRQ_NONE
– IRQ_HANDLED
![Page 83: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/83.jpg)
Soft IRQs
● Timer● Network● Block● Tasklet● Scheduler● High Resolution Timer
![Page 84: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/84.jpg)
Top & Bottom Halves
● Top Half– Registered through request_irq
● Bottom Half– Tasklet
● Soft IRQ Context● Fast & Atomic
– Workqueue● Special Kernel Process Context● Allowed to sleep
![Page 85: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/85.jpg)
Block Drivers
![Page 86: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/86.jpg)
How the Block Device fits in Linux Kernel
![Page 87: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/87.jpg)
Registration
● Driver Registration
– <linux/fs.h>
– int register_blkdev(major, name);
– int unregister_blkdev(major, name);
● Disk Drive Registration
– <linux/genhd.h>
– struct gendisk *gd = alloc_disk(minors);
– del_gendisk(gd);
– add_disk(gd);
![Page 88: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/88.jpg)
struct gendisk
● int major
● int first_minor
● int minors
● char disk_name[32]
● struct block_device_operations *fops
● struct request_queue *queue
● int flags (GENHD_FL_REMOVABLE, ...)
● sector_t capacity
● void *private_data
![Page 89: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/89.jpg)
Block Device Operations
● int open(struct block_device *, fmode_t);
● int close(struct gendisk *, fmode_t);
● int ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
● int compat_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
● int media_changed(struct gendisk *);
● int revalidate_disk(struct gendisk *gd);
● int getgeo(struct block_device *, struct hd_geometry *);
● struct module *owner;
![Page 90: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/90.jpg)
Request Queues & Processing
<linux/blkdev.h>
● typedef void (*request_fn_proc)(request_queue_t *queue);
● request_queue_t *q = blk_init_queue(rqf, lock);
● blk_cleanup_queue(q);
● struct request *req = blk_fetch_request(q);
● __blk_end_request(req);
● __blk_end_request_all(req, ret);
![Page 91: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/91.jpg)
struct request
● sector_t sector● unsigned long nr_sectors● char *buffer● rq_data_dir(req)
– zero: read from device
– non-zero: write to the device
● ...
![Page 92: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/92.jpg)
FileSystem Modules
![Page 93: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/93.jpg)
Virtual File System Interfaces
vfat
VFS
ext2
BufferCache
DiskDrives
DirectoryCache
InodeCache
![Page 94: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/94.jpg)
Virtual File System Internals
Super Block
Directory Entry Table
Inode Table
> File Name> Inode Number
> File Meta Data> File Data Block Nos
![Page 95: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/95.jpg)
Registration
● <linux/fs.h>● register_filesystem(file_system_type *)● unregister_filesystem(file_system_type *)● Filesystem Operations
– mount: (Invoked by mount)● fill_super -> Fill the Super Block
– kill_sb: (Invoked by umount)
![Page 96: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/96.jpg)
Fill the Super Block
● Block Size & Bits
● Magic Number
● Super Block Operations
● File System type
● Root Inode
– Inode Operations
– Inode Mode
– File Operations
![Page 97: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/97.jpg)
Super Block Operations
● read_inode: Get the Address Operations● write_inode: Update File Meta Data● statfs: Get the File Status (Invoked by stat)
– simple_statfs (Handler from libfs)
![Page 98: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/98.jpg)
Address Space Operations
● Page Cache
● Page Operations– readpage (Invoked by generic_file_read)
– write_start
– writepage (Invoked by generic_file_write)
– write_end
● Page Functions– PageUptodate/Dirty/Writeback/Locked
– SetPageUptodate, ClearPageDirty, unlock_page, ...
– page_address, ...
![Page 99: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/99.jpg)
Inode Operations
● lookup
– Search the file name by absolute path
– Traverse the inode chain
– if found matching inode, then populate the dentry with the inode information
● Inode Information
– Size
– Mode
– File Operations
– ...
![Page 100: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/100.jpg)
File Operations
● The Usual Ones
– open -> generic_file_open
– read -> generic_file_read
– write -> generic_file_write
– release
● The New Ones
– readdir: Change Directory (cd). List Directory (ls)● Directory Entry● Fill Function
– fsync: Sync the File (sync)● simple_sync_file
![Page 101: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/101.jpg)
Experiments with our File System
![Page 102: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/102.jpg)
PCI Drivers
![Page 103: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/103.jpg)
PCI Interface
● Replacement for ISA– Fast & Platform independent
● Addressing– Buses (upto 256)
● Devices (upto 32)– Functions (Upto 8)
● Viewing the Interface Structure– lspci
– cat /proc/bus/pci/devices
– tree /sys/bus/pci/devices
![Page 104: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/104.jpg)
PCI Device Configuration Space
VendorID
BISTHeaderType
LatTimer
CacheLine
Class CodeRevID
StatusRegister
CommandRegister
DeviceID
0x0 0xF
Base Address 0
CardBus CIS pointerBase Address 5Base Address 4
Base Address 3Base Address 2Base Address 1
SubsystemVendor ID
SubsystemDevice ID
Expansion ROMBase Address
IRQLine
IRQPin
MinGnt
MaxLat
0x00
0x30
0x20
0x10
Reserved
![Page 105: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/105.jpg)
PCI Configuration Space...
● During Bootup– By BIOS
– By PCI Core (Bootloader or Kernel)
● <linux/pci.h>● pci_read_config_byte/word/dword(struct
pci_dev *dev, int where, u8/16/32 *val);● pci_write_config_byte/word/dword(struct
pci_dev *dev, int where, u8/16/32 *val);
![Page 106: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/106.jpg)
PCI Driver Registration
● int pci_register_driver(struct pci_driver *drv);
● int pci_unregister_driver(struct pci_driver *drv);
● struct pci_driver
– const char *name
– const struct pci_dev_id *id_table;● PCI_DEVICE(vendor, device);● PCI_DEVICE_CLASS(dev_class, dev_class_mask);
– int (*probe)(pci_dev, id_table);
– void (*remove)(pci_dev);
![Page 107: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/107.jpg)
The 'probe' Function
int probe(struct pci_dev *d, struct pci_dev_id *id){
/* Initialize the PCI Device */
...
/* Enable the PCI Device */
pci_enable_device(d);
...
return 0; /* Claimed. Negative for not Claimed */
}
![Page 108: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/108.jpg)
Old-style PCI Probing & Getting
● struct pci_dev *pci_find_*(vendor, device, from);
● struct pci_dev *pci_get_device(v, d, from);● struct pci_dev *pci_get_subsys(v, d, ssv, ssd,
f);● struct pci_dev *pci_get_slot(bus, devfn);● pci_dev_put(pci_dev);
![Page 109: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/109.jpg)
PCI Device Access & Operations
● Upto 6 Memory or I/O regions● unsigned long pci_resource_start(dev, bar);● unsigned long pci_resource_end(dev, bar);● unsigned long pci_resource_flags(dev, bar);
– <linux/ioport.h>
– IORESOURCE_IO
– IORESOURCE_MEM
![Page 110: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/110.jpg)
References
● Kernel 3.x Source
● LDD Slides– http://www.slideshare.net/EmertxeSlides
● Linux Device Drivers (3rd Edition) by– Jonathan Corbet
– Alessandro Rubini
– Greg Kroah-Hartman
● Email Address: [email protected]
![Page 111: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/111.jpg)
Feedback Time
![Page 112: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/112.jpg)
Test Yourself
![Page 113: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/113.jpg)
Stay connected
About us: Emertxe is India’s one of the top IT finishing schools & self learning kits provider. Our primary focus is on Embedded with diversification focus on Java, Oracle and Android areas
Branch Office: Corporate Headquarters:Emertxe Information Technologies, Emertxe Information Technologies,No-1, 9th Cross, 5th Main, 83, Farah Towers, 1st Floor,Jayamahal Extension, MG Road,Bangalore, Karnataka 560046 Bangalore, Karnataka - 560001 T: +91 809 555 7333 (M), +91 80 41289576 (L)
https://www.facebook.com/Emertxe https://twitter.com/EmertxeTweet https://www.slideshare.net/EmertxeSlides
![Page 114: Linux device drivers](https://reader031.vdocument.in/reader031/viewer/2022032113/55a626061a28ab1e3c8b4861/html5/thumbnails/114.jpg)
Thank You