Log In
Or create an account ->
Imperial Library
Home
About
News
Upload
Forum
Help
Login/SignUp
Index
Linux Device Drivers, 3rd Edition
A Note Regarding Supplemental Files
Preface
Jon's Introduction
Alessandro's Introduction
Greg's Introduction
Audience for This Book
Organization of the Material
Background Information
Online Version and License
Conventions Used in This Book
Using Code Examples
We'd Like to Hear from You
Safari Enabled
Acknowledgments
Jon
Alessandro
Greg
1. An Introduction to Device Drivers
1.1. The Role of the Device Driver
1.2. Splitting the Kernel
1.2.1. Loadable Modules
1.3. Classes of Devices and Modules
1.4. Security Issues
1.5. Version Numbering
1.6. License Terms
1.7. Joining the Kernel Development Community
1.8. Overview of the Book
2. Building and Running Modules
2.1. Setting Up Your Test System
2.2. The Hello World Module
2.3. Kernel Modules Versus Applications
2.3.1. User Space and Kernel Space
2.3.2. Concurrency in the Kernel
2.3.3. The Current Process
2.3.4. A Few Other Details
2.4. Compiling and Loading
2.4.1. Compiling Modules
2.4.2. Loading and Unloading Modules
2.4.3. Version Dependency
2.4.4. Platform Dependency
2.5. The Kernel Symbol Table
2.6. Preliminaries
2.7. Initialization and Shutdown
2.7.1. The Cleanup Function
2.7.2. Error Handling During Initialization
2.7.3. Module-Loading Races
2.8. Module Parameters
2.9. Doing It in User Space
2.10. Quick Reference
3. Char Drivers
3.1. The Design of scull
3.2. Major and Minor Numbers
3.2.1. The Internal Representation of Device Numbers
3.2.2. Allocating and Freeing Device Numbers
3.2.3. Dynamic Allocation of Major Numbers
3.3. Some Important Data Structures
3.3.1. File Operations
3.3.2. The file Structure
3.3.3. The inode Structure
3.4. Char Device Registration
3.4.1. Device Registration in scull
3.4.2. The Older Way
3.5. open and release
3.5.1. The open Method
3.5.2. The release Method
3.6. scull's Memory Usage
3.7. read and write
3.7.1. The read Method
3.7.2. The write Method
3.7.3. readv and writev
3.8. Playing with the New Devices
3.9. Quick Reference
4. Debugging Techniques
4.1. Debugging Support in the Kernel
4.2. Debugging by Printing
4.2.1. printk
4.2.2. Redirecting Console Messages
4.2.3. How Messages Get Logged
4.2.4. Turning the Messages On and Off
4.2.5. Rate Limiting
4.2.6. Printing Device Numbers
4.3. Debugging by Querying
4.3.1. Using the /proc Filesystem
4.3.1.1. Implementing files in /proc
4.3.1.2. An older interface
4.3.1.3. Creating your /proc file
4.3.1.4. The seq_file interface
4.3.2. The ioctl Method
4.4. Debugging by Watching
4.5. Debugging System Faults
4.5.1. Oops Messages
4.5.2. System Hangs
4.6. Debuggers and Related Tools
4.6.1. Using gdb
4.6.2. The kdb Kernel Debugger
4.6.3. The kgdb Patches
4.6.4. The User-Mode Linux Port
4.6.5. The Linux Trace Toolkit
4.6.6. Dynamic Probes
5. Concurrency and Race Conditions
5.1. Pitfalls in scull
5.2. Concurrency and Its Management
5.3. Semaphores and Mutexes
5.3.1. The Linux Semaphore Implementation
5.3.2. Using Semaphores in scull
5.3.3. Reader/Writer Semaphores
5.4. Completions
5.5. Spinlocks
5.5.1. Introduction to the Spinlock API
5.5.2. Spinlocks and Atomic Context
5.5.3. The Spinlock Functions
5.5.4. Reader/Writer Spinlocks
5.6. Locking Traps
5.6.1. Ambiguous Rules
5.6.2. Lock Ordering Rules
5.6.3. Fine- Versus Coarse-Grained Locking
5.7. Alternatives to Locking
5.7.1. Lock-Free Algorithms
5.7.2. Atomic Variables
5.7.3. Bit Operations
5.7.4. seqlocks
5.7.5. Read-Copy-Update
5.8. Quick Reference
6. Advanced Char Driver Operations
6.1. ioctl
6.1.1. Choosing the ioctl Commands
6.1.2. The Return Value
6.1.3. The Predefined Commands
6.1.4. Using the ioctl Argument
6.1.5. Capabilities and Restricted Operations
6.1.6. The Implementation of the ioctl Commands
6.1.7. Device Control Without ioctl
6.2. Blocking I/O
6.2.1. Introduction to Sleeping
6.2.2. Simple Sleeping
6.2.3. Blocking and Nonblocking Operations
6.2.4. A Blocking I/O Example
6.2.5. Advanced Sleeping
6.2.5.1. How a process sleeps
6.2.5.2. Manual sleeps
6.2.5.3. Exclusive waits
6.2.5.4. The details of waking up
6.2.5.5. Ancient history: sleep_on
6.2.6. Testing the Scullpipe Driver
6.3. poll and select
6.3.1. Interaction with read and write
6.3.1.1. Reading data from the device
6.3.1.2. Writing to the device
6.3.1.3. Flushing pending output
6.3.2. The Underlying Data Structure
6.4. Asynchronous Notification
6.4.1. The Driver's Point of View
6.5. Seeking a Device
6.5.1. The llseek Implementation
6.6. Access Control on a Device File
6.6.1. Single-Open Devices
6.6.2. Restricting Access to a Single User at a Time
6.6.3. Blocking open as an Alternative to EBUSY
6.6.4. Cloning the Device on open
6.7. Quick Reference
7. Time, Delays, and Deferred Work
7.1. Measuring Time Lapses
7.1.1. Using the jiffies Counter
7.1.2. Processor-Specific Registers
7.2. Knowing the Current Time
7.3. Delaying Execution
7.3.1. Long Delays
7.3.1.1. Busy waiting
7.3.1.2. Yielding the processor
7.3.1.3. Timeouts
7.3.2. Short Delays
7.4. Kernel Timers
7.4.1. The Timer API
7.4.2. The Implementation of Kernel Timers
7.5. Tasklets
7.6. Workqueues
7.6.1. The Shared Queue
7.7. Quick Reference
7.7.1. Timekeeping
7.7.2. Delays
7.7.3. Kernel Timers
7.7.4. Tasklets
7.7.5. Workqueues
8. Allocating Memory
8.1. The Real Story of kmalloc
8.1.1. The Flags Argument
8.1.1.1. Memory zones
8.1.2. The Size Argument
8.2. Lookaside Caches
8.2.1. A scull Based on the Slab Caches: scullc
8.2.2. Memory Pools
8.3. get_free_page and Friends
8.3.1. A scull Using Whole Pages: scullp
8.3.2. The alloc_pages Interface
8.4. vmalloc and Friends
8.4.1. A scull Using Virtual Addresses: scullv
8.5. Per-CPU Variables
8.6. Obtaining Large Buffers
8.6.1. Acquiring a Dedicated Buffer at Boot Time
8.7. Quick Reference
9. Communicating with Hardware
9.1. I/O Ports and I/O Memory
9.1.1. I/O Registers and Conventional Memory
9.2. Using I/O Ports
9.2.1. I/O Port Allocation
9.2.2. Manipulating I/O ports
9.2.3. I/O Port Access from User Space
9.2.4. String Operations
9.2.5. Pausing I/O
9.2.6. Platform Dependencies
9.3. An I/O Port Example
9.3.1. An Overview of the Parallel Port
9.3.2. A Sample Driver
9.4. Using I/O Memory
9.4.1. I/O Memory Allocation and Mapping
9.4.2. Accessing I/O Memory
9.4.3. Ports as I/O Memory
9.4.4. Reusing short for I/O Memory
9.4.5. ISA Memory Below 1 MB
9.4.6. isa_readb and Friends
9.5. Quick Reference
10. Interrupt Handling
10.1. Preparing the Parallel Port
10.2. Installing an Interrupt Handler
10.2.1. The /proc Interface
10.2.2. Autodetecting the IRQ Number
10.2.2.1. Kernel-assisted probing
10.2.2.2. Do-it-yourself probing
10.2.3. Fast and Slow Handlers
10.2.3.1. The internals of interrupt handling on the x86
10.3. Implementing a Handler
10.3.1. Handler Arguments and Return Value
10.3.2. Enabling and Disabling Interrupts
10.3.2.1. Disabling a single interrupt
10.3.2.2. Disabling all interrupts
10.4. Top and Bottom Halves
10.4.1. Tasklets
10.4.2. Workqueues
10.5. Interrupt Sharing
10.5.1. Installing a Shared Handler
10.5.2. Running the Handler
10.5.3. The /proc Interface and Shared Interrupts
10.6. Interrupt-Driven I/O
10.6.1. A Write-Buffering Example
10.7. Quick Reference
11. Data Types in the Kernel
11.1. Use of Standard C Types
11.2. Assigning an Explicit Size to Data Items
11.3. Interface-Specific Types
11.4. Other Portability Issues
11.4.1. Time Intervals
11.4.2. Page Size
11.4.3. Byte Order
11.4.4. Data Alignment
11.4.5. Pointers and Error Values
11.5. Linked Lists
11.6. Quick Reference
12. PCI Drivers
12.1. The PCI Interface
12.1.1. PCI Addressing
12.1.2. Boot Time
12.1.3. Configuration Registers and Initialization
12.1.4. MODULE_DEVICE_TABLE
12.1.5. Registering a PCI Driver
12.1.6. Old-Style PCI Probing
12.1.7. Enabling the PCI Device
12.1.8. Accessing the Configuration Space
12.1.9. Accessing the I/O and Memory Spaces
12.1.10. PCI Interrupts
12.1.11. Hardware Abstractions
12.2. A Look Back: ISA
12.2.1. Hardware Resources
12.2.2. ISA Programming
12.2.3. The Plug-and-Play Specification
12.3. PC/104 and PC/104+
12.4. Other PC Buses
12.4.1. MCA
12.4.2. EISA
12.4.3. VLB
12.5. SBus
12.6. NuBus
12.7. External Buses
12.8. Quick Reference
13. USB Drivers
13.1. USB Device Basics
13.1.1. Endpoints
13.1.2. Interfaces
13.1.3. Configurations
13.2. USB and Sysfs
13.3. USB Urbs
13.3.1. struct urb
13.3.2. Creating and Destroying Urbs
13.3.2.1. Interrupt urbs
13.3.2.2. Bulk urbs
13.3.2.3. Control urbs
13.3.2.4. Isochronous urbs
13.3.3. Submitting Urbs
13.3.4. Completing Urbs: The Completion Callback Handler
13.3.5. Canceling Urbs
13.4. Writing a USB Driver
13.4.1. What Devices Does the Driver Support?
13.4.2. Registering a USB Driver
13.4.3. probe and disconnect in Detail
13.4.4. Submitting and Controlling a Urb
13.5. USB Transfers Without Urbs
13.5.1. usb_bulk_msg
13.5.2. usb_control_msg
13.5.3. Other USB Data Functions
13.6. Quick Reference
14. The Linux Device Model
14.1. Kobjects, Ksets, and Subsystems
14.1.1. Kobject Basics
14.1.1.1. Embedding kobjects
14.1.1.2. Kobject initialization
14.1.1.3. Reference count manipulation
14.1.1.4. Release functions and kobject types
14.1.2. Kobject Hierarchies, Ksets, and Subsystems
14.1.2.1. Ksets
14.1.2.2. Operations on ksets
14.1.2.3. Subsystems
14.2. Low-Level Sysfs Operations
14.2.1. Default Attributes
14.2.2. Nondefault Attributes
14.2.3. Binary Attributes
14.2.4. Symbolic Links
14.3. Hotplug Event Generation
14.3.1. Hotplug Operations
14.4. Buses, Devices, and Drivers
14.4.1. Buses
14.4.1.1. Bus registration
14.4.1.2. Bus methods
14.4.1.3. Iterating over devices and drivers
14.4.1.4. Bus attributes
14.4.2. Devices
14.4.2.1. Device registration
14.4.2.2. Device attributes
14.4.2.3. Device structure embedding
14.4.3. Device Drivers
14.4.3.1. Driver structure embedding
14.5. Classes
14.5.1. The class_simple Interface
14.5.2. The Full Class Interface
14.5.2.1. Managing classes
14.5.2.2. Class devices
14.5.2.3. Class interfaces
14.6. Putting It All Together
14.6.1. Add a Device
14.6.2. Remove a Device
14.6.3. Add a Driver
14.6.4. Remove a Driver
14.7. Hotplug
14.7.1. Dynamic Devices
14.7.2. The /sbin/hotplug Utility
14.7.2.1. IEEE1394 (FireWire)
14.7.2.2. Networking
14.7.2.3. PCI
14.7.2.4. Input
14.7.2.5. USB
14.7.2.6. SCSI
14.7.2.7. Laptop docking stations
14.7.2.8. S/390 and zSeries
14.7.3. Using /sbin/hotplug
14.7.3.1. Linux hotplug scripts
14.7.3.2. udev
14.8. Dealing with Firmware
14.8.1. The Kernel Firmware Interface
14.8.2. How It Works
14.9. Quick Reference
14.9.1. Kobjects
14.9.2. Sysfs Operations
14.9.3. Buses, Devices, and Drivers
14.9.4. Classes
14.9.5. Firmware
15. Memory Mapping and DMA
15.1. Memory Management in Linux
15.1.1. Address Types
15.1.2. Physical Addresses and Pages
15.1.3. High and Low Memory
15.1.4. The Memory Map and Struct Page
15.1.5. Page Tables
15.1.6. Virtual Memory Areas
15.1.6.1. The vm_area_struct structure
15.1.7. The Process Memory Map
15.2. The mmap Device Operation
15.2.1. Using remap_pfn_range
15.2.2. A Simple Implementation
15.2.3. Adding VMA Operations
15.2.4. Mapping Memory with nopage
15.2.5. Remapping Specific I/O Regions
15.2.6. Remapping RAM
15.2.6.1. Remapping RAM with the nopage method
15.2.7. Remapping Kernel Virtual Addresses
15.3. Performing Direct I/O
15.3.1. Asynchronous I/O
15.3.1.1. An asynchronous I/O example
15.4. Direct Memory Access
15.4.1. Overview of a DMA Data Transfer
15.4.2. Allocating the DMA Buffer
15.4.2.1. Do-it-yourself allocation
15.4.3. Bus Addresses
15.4.4. The Generic DMA Layer
15.4.4.1. Dealing with difficult hardware
15.4.4.2. DMA mappings
15.4.4.3. Setting up coherent DMA mappings
15.4.4.4. DMA pools
15.4.4.5. Setting up streaming DMA mappings
15.4.4.6. Single-page streaming mappings
15.4.4.7. Scatter/gather mappings
15.4.4.8. PCI double-address cycle mappings
15.4.4.9. A simple PCI DMA example
15.4.5. DMA for ISA Devices
15.4.5.1. Registering DMA usage
15.4.5.2. Talking to the DMA controller
15.5. Quick Reference
15.5.1. Introductory Material
15.5.2. Implementing mmap
15.5.3. Implementing Direct I/O
15.5.4. Direct Memory Access
16. Block Drivers
16.1. Registration
16.1.1. Block Driver Registration
16.1.2. Disk Registration
16.1.2.1. Block device operations
16.1.2.2. The gendisk structure
16.1.3. Initialization in sbull
16.1.4. A Note on Sector Sizes
16.2. The Block Device Operations
16.2.1. The open and release Methods
16.2.2. Supporting Removable Media
16.2.3. The ioctl Method
16.3. Request Processing
16.3.1. Introduction to the request Method
16.3.2. A Simple request Method
16.3.3. Request Queues
16.3.3.1. Queue creation and deletion
16.3.3.2. Queueing functions
16.3.3.3. Queue control functions
16.3.4. The Anatomy of a Request
16.3.4.1. The bio structure
16.3.4.2. Request structure fields
16.3.4.3. Barrier requests
16.3.4.4. Nonretryable requests
16.3.5. Request Completion Functions
16.3.5.1. Working with bios
16.3.5.2. Block requests and DMA
16.3.5.3. Doing without a request queue
16.4. Some Other Details
16.4.1. Command Pre-Preparation
16.4.2. Tagged Command Queueing
16.5. Quick Reference
17. Network Drivers
17.1. How snull Is Designed
17.1.1. Assigning IP Numbers
17.1.2. The Physical Transport of Packets
17.2. Connecting to the Kernel
17.2.1. Device Registration
17.2.2. Initializing Each Device
17.2.3. Module Unloading
17.3. The net_device Structure in Detail
17.3.1. Global Information
17.3.2. Hardware Information
17.3.3. Interface Information
17.3.4. The Device Methods
17.3.5. Utility Fields
17.4. Opening and Closing
17.5. Packet Transmission
17.5.1. Controlling Transmission Concurrency
17.5.2. Transmission Timeouts
17.5.3. Scatter/Gather I/O
17.6. Packet Reception
17.7. The Interrupt Handler
17.8. Receive Interrupt Mitigation
17.9. Changes in Link State
17.10. The Socket Buffers
17.10.1. The Important Fields
17.10.2. Functions Acting on Socket Buffers
17.11. MAC Address Resolution
17.11.1. Using ARP with Ethernet
17.11.2. Overriding ARP
17.11.3. Non-Ethernet Headers
17.12. Custom ioctl Commands
17.13. Statistical Information
17.14. Multicast
17.14.1. Kernel Support for Multicasting
17.14.2. A Typical Implementation
17.15. A Few Other Details
17.15.1. Media Independent Interface Support
17.15.2. Ethtool Support
17.15.3. Netpoll
17.16. Quick Reference
18. TTY Drivers
18.1. A Small TTY Driver
18.1.1. struct termios
18.2. tty_driver Function Pointers
18.2.1. open and close
18.2.2. Flow of Data
18.2.3. Other Buffering Functions
18.2.4. No read Function?
18.3. TTY Line Settings
18.3.1. set_termios
18.3.2. tiocmget and tiocmset
18.4. ioctls
18.5. proc and sysfs Handling of TTY Devices
18.6. The tty_driver Structure in Detail
18.7. The tty_operations Structure in Detail
18.8. The tty_struct Structure in Detail
18.9. Quick Reference
19. Bibliography
19.1. Books
19.1.1. Linux Kernel
19.1.2. Unix Design and Internals
19.2. Web Sites
Index
About the Authors
Copyright
← Prev
Back
Next →
← Prev
Back
Next →