[Index]


Table of Contents


Title and Copyright Pages

About This Book
Audience
New and Changed Features
Organizational Changes
Miscellaneous Changes
Terminology Changes and Issues
Scope of the Book
Organization
Related Documentation
Hardware Documentation
Bus-Specific Device Driver Documentation
Operating System Overview Documentation
Programming Tools Documentation
Network Programming Documentation
System Management Documentation
Porting Documentation
Kernel Kit Products Documentation
Reference Pages
Reader's Comments
Conventions

Part 1 Overview

1    Introduction to Device Drivers
1.1    Purpose of a Device Driver
1.2    Types of Device Drivers
1.2.1    Block Device Driver
1.2.2    Character Device Driver
1.2.3    Network Device Driver
1.2.4    Pseudodevice Driver
1.3    Single Binary Module
1.4    When a Device Driver Is Called
1.5    Device Driver Configuration
1.6    Place of a Device Driver in Digital UNIX
1.6.1    User Program or Utility
1.6.2    Kernel
1.6.3    Device Driver
1.6.4    Bus
1.6.5    Device Controller
1.6.6    Peripheral Device
1.7    Example of Reading a Character
1.7.1    A Read Request Is Made to the Device Driver
1.7.2    The Character Is Captured by the Hardware
1.7.3    The Interrupt Is Generated
1.7.4    The Interrupt Handler Services the Interrupt
1.7.5    The Character Is Returned
1.7.6    Summary of the Example

Part 2 Anatomy of a Device Driver

2    Developing a Device Driver
2.1    Gathering Information
2.1.1    Specifying Information About the Host System
2.1.1.1    Specifying the Host CPU or CPUs on Which Your Driver Operates
2.1.1.2    Specifying the Operating System or Systems on Which Your Driver Operates
2.1.1.3    Specifying the Bus or Buses to Which Your Driver Connects
2.1.2    Identifying the Standards Used in Writing the Driver
2.1.2.1    Specifying a Naming Scheme
2.1.2.2    Choosing an Approach for Writing Comments and Documentation
2.1.3    Specifying Characteristics of the Device
2.1.3.1    Specifying Whether the Device Is Capable of Block I/O
2.1.3.2    Specifying Whether the Device Supports a File System
2.1.3.3    Specifying Whether the Device Supports Byte Stream Access
2.1.3.4    Specifying Actions to Take on Interrupts
2.1.3.5    Specifying How to Reset the Device
2.1.3.6    Specifying Other Device Characteristics
2.1.4    Describing Device Usage
2.1.4.1    Listing the Device Documentation
2.1.4.2    Specifying the Number of Device Types to Reside on the System
2.1.4.3    Describing the Purpose of the Device
2.1.5    Providing a Description of the Device Registers
2.1.6    Identifying Support in Writing the Driver
2.2    Designing the Device Driver
2.2.1    Specifying the Device Driver Type
2.2.2    Identifying Device Driver Entry Points
2.2.3    Specifying the Locking Method for SMP-Safe Device Drivers
2.3    Understanding System Data and Address Types that Device Drivers Use
2.3.1    I/O Handle Data Type
2.3.2    Kernel-Unmapped Virtual Address
2.3.3    Kernel Physical Address
2.3.4    Sparse Space Address
2.3.5    Dense Space Address
2.3.6    Bus Physical Address
2.3.7    Memory Address
2.3.8    I/O Address
2.4    Specifying the Method for Registering Device Interrupt Handlers
2.5    Specifying the Method for Identifying Bus, Controller, and Device Information
2.6    Determining the Structure Allocation Technique
2.6.1    Static Allocation Model Technique
2.6.2    Dynamic Allocation Technique
2.6.2.1    Determining the Maximum Configuration
2.6.2.2    Statically Declaring an Array of Pointers to the Data Structures
2.6.2.3    Allocating the Data Structures with MALLOC
2.6.2.4    Accessing the Members of the Dynamically Allocated Data Structures
2.6.2.5    Freeing Up the Dynamically Allocated Memory with FREE
2.7    Creating a Device Driver Development Environment

3    Understanding CPU and Bus Issues That Influence Device Driver Design
3.1    CPU Issues That Influence Device Driver Design
3.1.1    Control Status Register Issues
3.1.2    I/O Copy Operation Issues
3.1.3    Direct Memory Access Operation Issues
3.1.4    Memory Mapping Issues
3.1.5    32-Bit Versus 64-Bit Issues
3.1.5.1    Declaring 32-Bit Variables
3.1.5.2    Declaring 32-Bit and 64-Bit Variables
3.1.5.3    Declaring Arguments to C Functions
3.1.5.4    Declaring Register Variables
3.1.5.5    Performing Bit Operations on Constants
3.1.5.6    Using NULL and Zero Values
3.1.5.7    Modifying Type char
3.1.5.8    Declaring Bit Fields
3.1.5.9    Using printf Formats
3.1.5.10    Using mb and wbflush
3.1.5.11    Using the volatile Compiler Keyword
3.1.6    Memory Barrier Issues
3.1.6.1    Forcing a Barrier Between Load/Store Operations
3.1.6.2    After the CPU Has Prepared a Data Buffer in Memory
3.1.6.3    Before Attempting to Read Any Device CSRs
3.1.6.4    Between Writes
3.2    Bus Issues That Influence Device Driver Design

4    Porting Digital UNIX Device Drivers
4.1    Porting ULTRIX Device Drivers to the Digital UNIX Operating System
4.1.1    Writing Test Suites
4.1.2    Checking Header Files
4.1.3    Reviewing Device Driver Configuration
4.1.4    Checking Driver Interfaces
4.1.5    Checking Kernel Interfaces
4.1.6    Checking Data Structures
4.2    Updating Device Drivers to the Current Version of the Digital UNIX Operating System
4.2.1    Method for Registering Interrupt Handlers
4.2.2    Method for Registering Character and Block Device Driver Interfaces
4.2.3    Use of the Bus-Specific Option Structure and Structure Snippet
4.2.4    Device Driver Object Files
4.2.5    Elimination of the stanza.static File Fragment
4.2.6    Elimination of the stanza.loadable File Fragment
4.2.7    Changes to the files File Fragment
4.2.8    Elimination of the config.file File Fragment
4.2.9    Method for Configuring and Unconfiguring Controllers
4.2.10    Method for Identifying Bus, Controller, and Device Information
4.2.11    Use of name_data.c Files
4.2.12    Method for Specifying Device Special File Information
4.2.13    Use of the Device Driver Header File
4.2.14    List of Interfaces to be Retired
4.2.15    List of Data Structures to be Retired
4.2.16    List of stanza Fields to be Retired

5    Analyzing the Structure of a Device Driver
5.1    Include Files Section
5.1.1    Common Driver Header Files
5.1.1.1    The types.h Header File
5.1.1.2    The errno.h Header File
5.1.1.3    The devdriver.h Header File
5.1.1.4    The uio.h Header File
5.1.1.5    The cpu.h Header File
5.1.1.6    The conf.h Header File
5.1.1.7    The sysconfig.h Header File
5.1.2    Device Register Header File
5.1.3    Bus-Specific Header Files
5.1.4    Include Files Section for the /dev/none Device Driver
5.2    Declarations Section
5.2.1    Declarations Section for the /dev/none Device Driver
5.3    The driver Structure
5.3.1    The probe, slave, cattach, dattach, and go Members
5.3.2    The addr_list Member
5.3.3    The dev_name and dev_list Members
5.3.4    The ctlr_name and ctlr_list Members
5.3.5    The xclu Member
5.3.6    The addr1_size, addr1_atype, addr2_size, and addr2_atype Members
5.3.7    The ctlr_unattach and dev_unattach Members
5.4    Device Switch Structure
5.4.1    The d_open and d_close Members
5.4.2    The d_strategy, d_read, and d_write Members
5.4.3    The d_ioctl and d_dump Members
5.4.4    The d_psize and d_stop Members
5.4.5    The d_reset and d_select Members
5.4.6    The d_mmap and d_segmap Members
5.4.7    The d_ttys and d_funnel Members
5.4.8    The d_bflags and d_cflags Members

Part 3 Writing and Testing a Device Driver

6    Implementing a Configure Interface to Support Static and Dynamic Configuration
6.1    Using the cfg_subsys_attr_t Structure
6.2    Using the cfg_attr_t Structure
6.3    Setting Up Configure-Related Declarations and the cfg_subsys_attr_t Data Structure
6.4    Defining Bus-Specific Name Constants
6.5    Setting Up the Configure Interface
6.6    Implementing the CFG_OP_CONFIGURE Operation
6.6.1    Parsing Attributes in the cfg_attr_t Structure Array
6.6.2    Initializing the Device Driver Name
6.6.3    Determining the Configuration State
6.6.4    Registering Controller and Device Information
6.6.4.1    The controller_config Data Structure
6.6.4.2    The device_config Data Structure
6.6.4.3    Using create_controller_struct and create_device_struct to Register Hardware Information
6.6.5    Registering I/O Services Interfaces and Reserving a Major Number
6.6.5.1    The dsent Data Structure
6.6.5.2    Using the devsw_add Interface to Register I/O Services Interfaces and Reserve a Major Number
6.6.6    Implementing Callback Interfaces
6.6.6.1    Implementing the callback_register_configuration Interface
6.6.6.2    Implementing the callback_register_major_number Interface
6.7    Implementing the CFG_OP_UNCONFIGURE Operation
6.8    Implementing the CFG_OP_RECONFIGURE Operation
6.9    Implementing the CFG_OP_QUERY Operation
6.10    Implementing the Default Operation

7    Implementing Device Driver Interfaces That Support Device Autoconfiguration
7.1    Implementing the probe Interface
7.1.1    Resolving Multiple Bus Issues Related to Implementing a probe Interface
7.1.2    Using the I/O Handle
7.1.3    Setting Up the probe Interface
7.1.4    Setting Up the probe Interface to Handle Multiple Buses
7.1.5    Using Data Structures to Register Interrupt Handlers
7.1.5.1    The ihandler_t Data Structure
7.1.5.2    The handler_intr_info Data Structure
7.1.6    Using the handler Interfaces to Register Interrupt Handlers
7.1.7    Using the handler Interfaces to Register Shared Interrupt Handlers
7.1.8    Using BADADDR to Probe the Address
7.1.9    Using read_io_port and write_io_port to Read and Write Data
7.1.10    Using Driver-Specific Macros to Read and Write Data
7.2    Implementing the attach Interface
7.2.1    Setting Up the attach Interface for a Controller
7.2.2    Setting Up the attach Interface for a Device
7.3    Implementing the unattach Interface
7.3.1    Setting Up the unattach Interface for a Controller
7.3.2    Setting Up the unattach Interface for a Device
7.3.3    Using the handler Interfaces to Deregister Interrupt Handlers
7.4    Implementing the slave Interface
7.4.1    Resolving Multiple Bus Issues Related to Implementing a slave Interface
7.4.2    Setting Up the slave Interface

8    Implementing Character Device Driver Interfaces
8.1    Implementing the read Interface
8.1.1    Using the dev_t Data Type
8.1.1.1    Getting the Device Major Number with major
8.1.1.2    Getting the Device Minor Number with minor
8.1.2    Using the uio Structure
8.1.2.1    The uio_iov and uio_iovcnt Members
8.1.2.2    The uio_offset and uio_segflg Members
8.1.2.3    The uio_resid and uio_rw Members
8.1.3    Setting Up the read Interface
8.2    Implementing the write Interface
8.2.1    Setting Up the write Interface
8.2.2    Copying Data to the Device
8.3    Implementing the reset Interface
8.3.1    Setting Up the reset Interface
8.4    Implementing the select Interface
8.4.1    Using the sel_queue Data Structure
8.4.2    Setting Up the select Interface
8.4.3    Using the select Interfaces to poll for Input Reads
8.4.4    Using the select Interfaces to poll for Output Writes
8.5    Implementing the stop Interface
8.5.1    Setting Up the stop Interface
8.6    Implementing the mmap Interface

9    Implementing Block Device Driver Interfaces
9.1    Implementing the dump Interface
9.2    Implementing the psize Interface
9.3    Implementing the strategy Interface
9.3.1    Using the Systemwide Pool of buf Structures
9.3.2    Declaring Locally Defined buf Structures
9.3.3    Using buf Structure Members Related to Device Drivers
9.3.3.1    The b_flags Member
9.3.3.2    The b_forw and b_back Members
9.3.3.3    The av_forw and av_back Members
9.3.3.4    The b_bcount and b_error Members
9.3.3.5    The b_dev Member
9.3.3.6    The b_un.b_addr Member
9.3.3.7    The b_lblkno and b_blkno Members
9.3.3.8    The b_resid and b_iodone Members
9.3.3.9    The b_proc Member
9.3.4    Using Buffer Cache Management
9.3.5    Buffer Cache Interface
9.3.6    Setting Up the strategy Interface

10    Implementing Character and Block Device Driver Interfaces
10.1    Implementing the open Interface
10.1.1    Setting Up the open Interface
10.1.2    Performing the Tasks Associated with Opening the Device
10.2    Implementing the close Interface
10.2.1    Setting Up the close Interface
10.2.2    Performing the Tasks Associated with Closing the Device
10.3    Implementing the ioctl Interface
10.4    Implementing the Interrupt Handler

11    Testing a Device Driver
11.1    Writing the Test Program
11.2    Expanding the Test Program
11.3    Tracking Problems in Testing

Part 4 Delivering Device Drivers

12    Device Driver Kits Delivery Process
12.1    Device Driver Development Phase
12.1.1    Writing the Device Driver
12.1.2    Creating the Device Driver Development Environment
12.1.3    Creating Driver Product-Related Files and File Fragments
12.1.4    Producing the Single Binary Module
12.1.5    Performing Static Configuration of the Driver
12.1.6    Performing Dynamic Configuration of the Driver
12.1.7    Testing the Device Driver Product
12.1.8    Providing Driver Product-Related Files and File Fragments to the Kit Developer
12.2    Device Driver Kit Development Phase
12.2.1    Writing the SCP
12.2.2    Preparing the Device Driver Kit
12.3    Device Driver Installation Phase
12.4    System Management Tools

13    Device Driver Configuration Files and File Fragments
13.1    Target and GENERIC Configuration Files
13.2    The .product.list and NAME.list Files
13.2.1    Format of the NAME.list File
13.2.2    Relationship between NAME.list and .product.list Files
13.3    The files File Fragment
13.4    The sysconfigtab File Fragment
13.5    The BINARY.list File
13.6    Single Binary Module and the Device Method File
13.7    The name.kit File

14    Building a Device Driver
14.1    Producing the Single Binary Module
14.1.1    Step 1: Create a Directory to Contain Driver Product Files
14.1.2    Step 2: Copy Driver Product Files
14.1.3    Step 3: Create a files File Fragment
14.1.4    Step 4: Create a BINARY.list File
14.1.5    Step 5: Create a sysconfigtab File Fragment
14.1.6    Step 6: Run the sourceconfig Program
14.1.7    Step 7: Run the make Program
14.1.8    Step 8: Create a Kernel Configuration Development Area
14.1.9    Step 9: Run the sysconfigdb Utility
14.2    Statically Configuring a Single Binary Module
14.2.1    Statically Configuring a Single Binary Module into a /vmunix Kernel
14.2.1.1    Step 1: Edit or Create the NAME.list File
14.2.1.2    Step 2: Run the doconfig Program
14.2.1.3    Step 3: Copy the New Kernel to the Root Directory
14.2.1.4    Step 4: Shut Down and Boot the System
14.2.2    Statically Configuring a Single Binary Module into a /sysconfigtab Boot-Link Kernel
14.2.2.1    Step 1: Edit or Create the NAME.list File
14.2.2.2    Step 2: Run the doconfig Program
14.2.2.3    Step 3: Copy the sysconfigtab File
14.2.2.4    Step 4: Copy the none.mod, NAME.mod, and EXTRAS.mod Files
14.2.2.5    Step 5: Shut Down and Boot the Boot-Link Kernel
14.3    Dynamically Configuring a Single Binary Module
14.3.1    Step 1: Link to the Single Binary Module
14.3.2    Step 2: Link to the Method File
14.3.3    Step 3: Run the sysconfig Utility

Part 5 Hardware Environment

15    Hardware-Independent Model and Device Drivers
15.1    Hardware-Independent Subsystem
15.2    Hardware-Dependent Subsystem
15.3    Bus Support Subsystem
15.4    Device Driver Subsystem

16    Hardware Components and Hardware Activities
16.1    Hardware Components
16.1.1    Central Processing Unit
16.1.2    Memory
16.1.3    Bus
16.1.3.1    Specifying Which Bus a Device Is On
16.1.3.2    Writing probe and slave Interfaces
16.1.3.3    A Device Does Direct Memory Access
16.1.4    Device
16.1.4.1    Device Registers
16.1.4.2    Block and Character Devices
16.1.4.3    Terminal Devices
16.1.4.4    Network Devices
16.1.4.5    DMA and non-DMA Devices
16.2    Hardware Activities
16.2.1    How a Device Driver Accesses Device Registers
16.2.2    How a Device Uses the Registers
16.2.3    How a Device Driver Interrupts the CPU
16.3    Parts of the System Accessing Hardware

Part 6 Kernel Environment

17    Data Structures That the Autoconfiguration Software Uses
17.1    The bus Structure
17.1.1    The bus_mbox Member
17.1.2    The bus_hd, nxt_bus, ctlr_list, and bus_list Members
17.1.3    The bus_type Member
17.1.4    The bus_name and bus_num Members
17.1.5    The slot, connect_bus, and connect_num Members
17.1.6    The confl1 and confl2 Members
17.1.7    The pname and port Members
17.1.8    The intr Member
17.1.9    The alive Member
17.1.10    The framework and driver_name Members
17.1.11    The bus_bridge_dma Member
17.1.12    The private, conn_priv, and rsvd Members
17.2    The controller Structure
17.2.1    The ctlr_mbox Member
17.2.2    The bus_hd, nxt_ctlr, and dev_list Members
17.2.3    The driver Member
17.2.4    The ctlr_type, ctlr_name, and ctlr_num Members
17.2.5    The bus_name and bus_num Members
17.2.6    The rctlr Member
17.2.7    The slot Member
17.2.8    The alive Member
17.2.9    The pname and port Members
17.2.10    The intr Member
17.2.11    The addr and addr2 Members
17.2.12    The flags Member
17.2.13    The bus_priority Member
17.2.14    The ivnum Member
17.2.15    The priority Member
17.2.16    The cmd Member
17.2.17    The physaddr and physaddr2 Members
17.2.18    The private, conn_priv, and rsvd Members
17.3    The device Structure
17.3.1    The nxt_dev and ctlr_hd Members
17.3.2    The dev_type and dev_name Members
17.3.3    The logunit and unit Members
17.3.4    The ctlr_name and ctlr_num Members
17.3.5    The alive Member
17.3.6    The private, conn_priv, and rsvd Members
17.4    The port Structure

18    Using Kernel Interfaces with Device Drivers
18.1    String Interfaces
18.1.1    Comparing Two Null-Terminated Strings
18.1.2    Comparing Two Strings by Using a Specified Number of Characters
18.1.3    Copying a Null-Terminated Character String
18.1.4    Copying a Null-Terminated Character String with a Specified Limit
18.1.5    Returning the Number of Characters in a Null-Terminated String
18.2    Data Copying Interfaces
18.2.1    Copying a Series of Bytes with a Specified Limit
18.2.2    Zeroing a Block of Memory
18.2.3    Copying Data from User Address Space to Kernel Address Space
18.2.4    Copying Data from Kernel Address Space to User Address Space
18.2.5    Moving Data Between User Virtual Space and System Virtual Space
18.3    Hardware-Related Interfaces
18.3.1    Delaying the Calling Interface a Specified Number of Microseconds
18.3.2    Setting the Interrupt Priority Mask
18.4    Kernel-Related Interfaces
18.4.1    Printing Text to the Console and Error Logger
18.4.2    Putting a Calling Process to Sleep
18.4.3    Waking Up a Sleeping Process
18.4.4    Initializing a Callout Queue Element
18.4.5    Removing the Scheduled Interface from the Callout Queues
18.5    Interfaces Related to the I/O Handle
18.5.1    I/O Copy Interfaces
18.5.1.1    Copying a Block of Memory from I/O Address Space to System Memory
18.5.1.2    Copying a Block of Byte-Contiguous System Memory to I/O Address Space
18.5.1.3    Copying a Memory Block of I/O Address Space to Another Memory Block of I/O Address Space
18.6    Interfaces Related to Direct Memory Access
18.6.1    DMA Handle
18.6.2    The sg_entry Structure
18.6.3    Allocating System Resources for DMA Data Transfers
18.6.4    Loading and Setting Allocated System Resources for DMA Data Transfers
18.6.5    Unloading System Resources for DMA Data Transfers
18.6.6    Releasing and Deallocating Resources for DMA Data Transfers
18.6.7    Returning a Pointer to the Current Bus Address/Byte Count Pair
18.6.8    Putting a New Bus Address/Byte Count Pair into the List
18.6.9    Returning a Kernel Segment Address of a DMA Buffer
18.7    Miscellaneous Interfaces
18.7.1    Indicating That I/O Is Complete
18.7.2    Implementing Raw I/O

Part 7 Appendixes

A    Summary Tables
A.1    List of Header Files
A.2    List of Kernel Support Interfaces
A.3    List of Global Variables
A.4    List of Data Structures
A.5    List of Device Driver Interfaces
A.6    List of Bus Configuration Interfaces

B    Device Driver Example Source Listings
B.1    Source Listing for the /dev/none Device Driver
B.2    Source Listing for the /dev/edpseudo Device Driver

C    Device Driver Development Worksheets
C.1    Filled-In Worksheets for the /dev/none Device Driver
C.2    Worksheets for Device Driver Development

D    Files Related to the Device Driver Kits Delivery Process

Glossary

Figures

1-1    When the Kernel Calls a Device Driver
1-2    Place of a Device Driver in Digital UNIX
1-3    Simple Character Driver Interrupt Example
5-1    Sections of a Character Device Driver and a Block Device Driver
5-2    The probe, slave, cattach, dattach, and go Members Initialized
5-3    The addr_list Member Initialized
5-4    The dev_name and dev_list Members Initialized
5-5    The ctlr_name and ctlr_list Members Initialized
5-6    The xclu Member Initialized
5-7    The addr1_size, addr1_atype, addr2_size, and addr2_atype Members Initialized
5-8    The ctlr_unattach and dev_unattach Members Initialized
6-1    The cfgmgr Framework Filling in Attributes for the /dev/none Driver
6-2    Adding Entries to the dsent Table for Loadable Drivers
11-1    Testing Worksheet for /dev/none
12-1    People and Tasks Associated With the Device Driver Kits Delivery Process
12-2    Tasks for Device Driver Development Phase
12-3    Driver Development Environment for EasyDriver Incorporated
12-4    Tasks for Device Driver Kit Development Phase
12-5    Tasks for Device Driver Kit Installation Phase
13-1    A NAME.list File for EasyDriver Incorporated
13-2    Comparison of .product.list File and NAME.list
13-3    Comparison of files File Fragment and Customer's files File
13-4    Format of the sysconfigtab File Fragment
13-5    Comparison of sysconfigtab File Fragment and sysconfigtab Database
13-6    How osfboot Uses a name.kit File
15-1    Hardware-Independent Model
16-1    Hardware Components of Interest to a Device Driver Writer
18-1    Results of the strcmp Interface
18-2    Results of the strncmp Interface
18-3    Results of the strcpy Interface
18-4    Results of the strncpy Interface
18-5    Results of the strlen Interface
18-6    Results of the bcopy Interface
18-7    Results of the copyin Interface
18-8    Results of the copyout Interface
C-1    Host System Worksheet for /dev/none
C-2    Host System Worksheet for /dev/none (Cont.)
C-3    Device Driver Conventions Worksheet for /dev/none
C-4    Device Driver Conventions Worksheet for /dev/none (Cont.)
C-5    Device Characteristics Worksheet for the none Device
C-6    Device Characteristics Worksheet for the none Device (Cont.)
C-7    Device Usage Worksheet for the none Device
C-8    Device Register Worksheet for /dev/none
C-9    Device Register Worksheet for /dev/none (Cont.)
C-10    Device Driver Support Worksheet for /dev/none
C-11    Device Driver Type Worksheet for /dev/none
C-12    Device Driver Entry Points Worksheet for /dev/none
C-13    Locking Methods

Tables

2-1    Structure Allocation Technique Guidelines
3-1    C Compiler Data Types and Bit Sizes
4-1    Highlights of Differences Between Digital UNIX and ULTRIX Kernel Interfaces
4-2    Highlights of Differences Between Digital UNIX and ULTRIX Data Structures
4-3    Interfaces to be Retired in a Future Release of Digital UNIX
4-4    Data Structures to be Retired in a Future Release of Digital UNIX
5-1    Frequently-Used System Data Types Defined in the types.h File
7-1    Members of the ihandler_t Structure
7-2    Members of the handler_intr_info Structure
8-1    Members of the uio Structure
8-2    Members of the sel_queue Structure
9-1    Members of the buf Structure
9-2    Binary Status Flags Applicable to Device Drivers
12-1    Contents of Device Driver Kit
12-2    Summary of System Management Tools
14-1    The sysconfigtab File Fragment Fields
17-1    Members of the bus Structure
17-2    Members of the controller Structure
17-3    Members of the device Structure
17-4    Member of the port Structure
18-1    Uses for spl Interfaces
18-2    Members of the sg_entry Structure
A-1    Summary Descriptions of Header Files
A-2    Summary Descriptions of Kernel Support Interfaces
A-3    Summary Descriptions of Global Variables
A-4    Summary Descriptions of Data Structures
A-5    Summary of Block and Character Device Driver Interfaces
A-6    Summary Descriptions of Bus Configuration Interfaces
D-1    Contents of Files Related to Static and Dynamic Configuration