• 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
  • An Introduction to Device Drivers
    • The Role of the Device Driver
    • Splitting the Kernel
    • Loadable Modules
    • Classes of Devices and Modules
    • Security Issues
    • Version Numbering
    • License Terms
    • Joining the Kernel Development Community
    • Overview of the Book
  • Building and Running Modules
    • Setting Up Your Test System
    • The Hello World Module
    • Kernel Modules Versus Applications
    • User Space and Kernel Space
    • Concurrency in the Kernel
    • The Current Process
    • A Few Other Details
    • Compiling and Loading
    • Compiling Modules
    • Loading and Unloading Modules
    • Version Dependency
    • Platform Dependency
    • The Kernel Symbol Table
    • Preliminaries
    • Initialization and Shutdown
    • The Cleanup Function
    • Error Handling During Initialization
    • Module-Loading Races
    • Module Parameters
    • Doing It in User Space
    • Quick Reference
  • Char Drivers
    • The Design of scull
    • Major and Minor Numbers
    • The Internal Representation of Device Numbers
    • Allocating and Freeing Device Numbers
    • Dynamic Allocation of Major Numbers
    • Some Important Data Structures
    • File Operations
    • The file Structure
    • The inode Structure
    • Char Device Registration
    • Device Registration in scull
    • The Older Way
    • open and release
    • The open Method
    • The release Method
    • scull's Memory Usage
    • read and write
    • The read Method
    • The write Method
    • readv and writev
    • Playing with the New Devices
    • Quick Reference
  • Debugging Techniques
    • Debugging Support in the Kernel
    • Debugging by Printing
    • printk
    • Redirecting Console Messages
    • How Messages Get Logged
    • Turning the Messages On and Off
    • Rate Limiting
    • Printing Device Numbers
    • Debugging by Querying
    • Using the /proc Filesystem
    • Implementing files in /proc
    • An older interface
    • Creating your /proc file
    • The seq_file interface
    • The ioctl Method
    • Debugging by Watching
    • Debugging System Faults
    • Oops Messages
    • System Hangs
    • Debuggers and Related Tools
    • Using gdb
    • The kdb Kernel Debugger
    • The kgdb Patches
    • The User-Mode Linux Port
    • The Linux Trace Toolkit
    • Dynamic Probes
  • Concurrency and Race Conditions
    • Pitfalls in scull
    • Concurrency and Its Management
    • Semaphores and Mutexes
    • The Linux Semaphore Implementation
    • Using Semaphores in scull
    • Reader/Writer Semaphores
    • Completions
    • Spinlocks
    • Introduction to the Spinlock API
    • Spinlocks and Atomic Context
    • The Spinlock Functions
    • Reader/Writer Spinlocks
    • Locking Traps
    • Ambiguous Rules
    • Lock Ordering Rules
    • Fine- Versus Coarse-Grained Locking
    • Alternatives to Locking
    • Lock-Free Algorithms
    • Atomic Variables
    • Bit Operations
    • seqlocks
    • Read-Copy-Update
    • Quick Reference
  • Advanced Char Driver Operations
    • ioctl
    • Choosing the ioctl Commands
    • The Return Value
    • The Predefined Commands
    • Using the ioctl Argument
    • Capabilities and Restricted Operations
    • The Implementation of the ioctl Commands
    • Device Control Without ioctl
    • Blocking I/O
    • Introduction to Sleeping
    • Simple Sleeping
    • Blocking and Nonblocking Operations
    • A Blocking I/O Example
    • Advanced Sleeping
    • How a process sleeps
    • Manual sleeps
    • Exclusive waits
    • The details of waking up
    • Ancient history: sleep_on
    • Testing the Scullpipe Driver
    • poll and select
    • Interaction with read and write
    • Reading data from the device
    • Writing to the device
    • Flushing pending output
    • The Underlying Data Structure
    • Asynchronous Notification
    • The Driver's Point of View
    • Seeking a Device
    • The llseek Implementation
    • Access Control on a Device File
    • Single-Open Devices
    • Restricting Access to a Single User at a Time
    • Blocking open as an Alternative to EBUSY
    • Cloning the Device on open
    • Quick Reference
  • Time, Delays, and Deferred Work
    • Measuring Time Lapses
    • Using the jiffies Counter
    • Processor-Specific Registers
    • Knowing the Current Time
    • Delaying Execution
    • Long Delays
    • Busy waiting
    • Yielding the processor
    • Timeouts
    • Short Delays
    • Kernel Timers
    • The Timer API
    • The Implementation of Kernel Timers
    • Tasklets
    • Workqueues
    • The Shared Queue
    • Quick Reference
    • Timekeeping
    • Delays
    • Kernel Timers
    • Tasklets
    • Workqueues
  • Allocating Memory
    • The Real Story of kmalloc
    • The Flags Argument
    • Memory zones
    • The Size Argument
    • Lookaside Caches
    • A scull Based on the Slab Caches: scullc
    • Memory Pools
    • get_free_page and Friends
    • A scull Using Whole Pages: scullp
    • The alloc_pages Interface
    • vmalloc and Friends
    • A scull Using Virtual Addresses: scullv
    • Per-CPU Variables
    • Obtaining Large Buffers
    • Acquiring a Dedicated Buffer at Boot Time
    • Quick Reference
  • Communicating with Hardware
    • I/O Ports and I/O Memory
    • I/O Registers and Conventional Memory
    • Using I/O Ports
    • I/O Port Allocation
    • Manipulating I/O ports
    • I/O Port Access from User Space
    • String Operations
    • Pausing I/O
    • Platform Dependencies
    • An I/O Port Example
    • An Overview of the Parallel Port
    • A Sample Driver
    • Using I/O Memory
    • I/O Memory Allocation and Mapping
    • Accessing I/O Memory
    • Ports as I/O Memory
    • Reusing short for I/O Memory
    • ISA Memory Below 1 MB
    • isa_readb and Friends
    • Quick Reference
  • Interrupt Handling
    • Preparing the Parallel Port
    • Installing an Interrupt Handler
    • The /proc Interface
    • Auto-Detecting the IRQ Number
    • Kernel-assisted probing
    • Do-it-yourself probing
    • Fast and Slow Handlers
    • The internals of interrupt handling on the x86
    • Implementing a Handler
    • Handler Arguments and Return Value
    • Enabling and Disabling Interrupts
    • Disabling a single interrupt
    • Disabling all interrupts
    • Top and Bottom Halves
    • Tasklets
    • Workqueues
    • Interrupt Sharing
    • Installing a Shared Handler
    • Running the Handler
    • The /proc Interface and Shared Interrupts
    • Interrupt-Driven I/O
    • A Write-Buffering Example
    • Quick Reference
  • Data Types in the Kernel
    • Use of Standard C Types
    • Assigning an Explicit Size to Data Items
    • Interface-Specific Types
    • Other Portability Issues
    • Time Intervals
    • Page Size
    • Byte Order
    • Data Alignment
    • Pointers and Error Values
    • Linked Lists
    • Quick Reference
  • PCI Drivers
    • The PCI Interface
    • PCI Addressing
    • Boot Time
    • Configuration Registers and Initialization
    • MODULE_DEVICE_TABLE
    • Registering a PCI Driver
    • Old-Style PCI Probing
    • Enabling the PCI Device
    • Accessing the Configuration Space
    • Accessing the I/O and Memory Spaces
    • PCI Interrupts
    • Hardware Abstractions
    • A Look Back: ISA
    • Hardware Resources
    • ISA Programming
    • The Plug-and-Play Specification
    • PC/104 and PC/104+
    • Other PC Buses
    • MCA
    • EISA
    • VLB
    • SBus
    • NuBus
    • External Buses
    • Quick Reference
  • USB Drivers
    • USB Device Basics
    • Endpoints
    • Interfaces
    • Configurations
    • USB and Sysfs
    • USB Urbs
    • struct urb
    • Creating and Destroying Urbs
    • Interrupt urbs
    • Bulk urbs
    • Control urbs
    • Isochronous urbs
    • Submitting Urbs
    • Completing Urbs: The Completion Callback Handler
    • Canceling Urbs
    • Writing a USB Driver
    • What Devices Does the Driver Support?
    • Registering a USB Driver
    • probe and disconnect in Detail
    • Submitting and Controlling a Urb
    • USB Transfers Without Urbs
    • usb_bulk_msg
    • usb_control_msg
    • Other USB Data Functions
    • Quick Reference
  • The Linux Device Model
    • Kobjects, Ksets, and Subsystems
    • Kobject Basics
    • Embedding kobjects
    • Kobject initialization
    • Reference count manipulation
    • Release functions and kobject types
    • Kobject Hierarchies, Ksets, and Subsystems
    • Ksets
    • Operations on ksets
    • Subsystems
    • Low-Level Sysfs Operations
    • Default Attributes
    • Nondefault Attributes
    • Binary Attributes
    • Symbolic Links
    • Hotplug Event Generation
    • Hotplug Operations
    • Buses, Devices, and Drivers
    • Buses
    • Bus registration
    • Bus methods
    • Iterating over devices and drivers
    • Bus attributes
    • Devices
    • Device registration
    • Device attributes
    • Device structure embedding
    • Device Drivers
    • Driver structure embedding
    • Classes
    • The class_simple Interface
    • The Full Class Interface
    • Managing classes
    • Class devices
    • Class interfaces
    • Putting It All Together
    • Add a Device
    • Remove a Device
    • Add a Driver
    • Remove a Driver
    • Hotplug
    • Dynamic Devices
    • The /sbin/hotplug Utility
    • IEEE1394 (FireWire)
    • Networking
    • PCI
    • Input
    • USB
    • SCSI
    • Laptop docking stations
    • S/390 and zSeries
    • Using /sbin/hotplug
    • Linux hotplug scripts
    • udev
    • Dealing with Firmware
    • The Kernel Firmware Interface
    • How It Works
    • Quick Reference
    • Kobjects
    • Sysfs Operations
    • Buses, Devices, and Drivers
    • Classes
    • Firmware
  • Memory Mapping and DMA
    • Memory Management in Linux
    • Address Types
    • Physical Addresses and Pages
    • High and Low Memory
    • The Memory Map and Struct Page
    • Page Tables
    • Virtual Memory Areas
    • The vm_area_struct structure
    • The Process Memory Map
    • The mmap Device Operation
    • Using remap_pfn_range
    • A Simple Implementation
    • Adding VMA Operations
    • Mapping Memory with nopage
    • Remapping Specific I/O Regions
    • Remapping RAM
    • Remapping RAM with the nopage method
    • Remapping Kernel Virtual Addresses
    • Performing Direct I/O
    • Asynchronous I/O
    • An asynchronous I/O example
    • Direct Memory Access
    • Overview of a DMA Data Transfer
    • Allocating the DMA Buffer
    • Do-it-yourself allocation
    • Bus Addresses
    • The Generic DMA Layer
    • Dealing with difficult hardware
    • DMA mappings
    • Setting up coherent DMA mappings
    • DMA pools
    • Setting up streaming DMA mappings
    • Single-page streaming mappings
    • Scatter/gather mappings
    • PCI double-address cycle mappings
    • A simple PCI DMA example
    • DMA for ISA Devices
    • Registering DMA usage
    • Talking to the DMA controller
    • Quick Reference
    • Introductory Material
    • Implementing mmap
    • Implementing Direct I/O
    • Direct Memory Access
  • Block Drivers
    • Registration
    • Block Driver Registration
    • Disk Registration
    • Block device operations
    • The gendisk structure
    • Initialization in sbull
    • A Note on Sector Sizes
    • The Block Device Operations
    • The open and release Methods
    • Supporting Removable Media
    • The ioctl Method
    • Request Processing
    • Introduction to the request Method
    • A Simple request Method
    • Request Queues
    • Queue creation and deletion
    • Queueing functions
    • Queue control functions
    • The Anatomy of a Request
    • The bio structure
    • request structure fields
    • Barrier requests
    • Nonretryable requests
    • Request Completion Functions
    • Working with bios
    • Block requests and DMA
    • Doing without a request queue
    • Some Other Details
    • Command Pre-Preparation
    • Tagged Command Queueing
    • Quick Reference
  • Network Drivers
    • How snull Is Designed
    • Assigning IP Numbers
    • The Physical Transport of Packets
    • Connecting to the Kernel
    • Device Registration
    • Initializing Each Device
    • Module Unloading
    • The net_device Structure in Detail
    • Global Information
    • Hardware Information
    • Interface Information
    • The Device Methods
    • Utility Fields
    • Opening and Closing
    • Packet Transmission
    • Controlling Transmission Concurrency
    • Transmission Timeouts
    • Scatter/Gather I/O
    • Packet Reception
    • The Interrupt Handler
    • Receive Interrupt Mitigation
    • Changes in Link State
    • The Socket Buffers
    • The Important Fields
    • Functions Acting on Socket Buffers
    • MAC Address Resolution
    • Using ARP with Ethernet
    • Overriding ARP
    • Non-Ethernet Headers
    • Custom ioctl Commands
    • Statistical Information
    • Multicast
    • Kernel Support for Multicasting
    • A Typical Implementation
    • A Few Other Details
    • Media Independent Interface Support
    • Ethtool Support
    • Netpoll
    • Quick Reference
  • TTY Drivers
    • A Small TTY Driver
    • struct termios
    • tty_driver Function Pointers
    • open and close
    • Flow of Data
    • Other Buffering Functions
    • No read Function?
    • TTY Line Settings
    • set_termios
    • tiocmget and tiocmset
    • ioctls
    • proc and sysfs Handling of TTY Devices
    • The tty_driver Structure in Detail
    • The tty_operations Structure in Detail
    • The tty_struct Structure in Detail
    • Quick Reference