Skip Navigation Links | |
Exit Print View | |
Writing Device Drivers Oracle Solaris 11.1 Information Library |
Part I Designing Device Drivers for the Oracle Solaris Platform
1. Overview of Oracle Solaris Device Drivers
2. Oracle Solaris Kernel and Device Tree
5. Managing Events and Queueing Tasks
7. Device Access: Programmed I/O
10. Mapping Device and Kernel Memory
13. Hardening Oracle Solaris Drivers
14. Layered Driver Interface (LDI)
Part II Designing Specific Kinds of Device Drivers
15. Drivers for Character Devices
Overview of the Character Driver Structure
Device Access (Character Drivers)
open() Entry Point (Character Drivers)
close() Entry Point (Character Drivers)
Differences Between Synchronous and Asynchronous I/O
Multiplexing I/O on File Descriptors
ioctl() Entry Point (Character Drivers)
I/O Control Support for 64-Bit Capable Device Drivers
32-bit and 64-bit Data Structure Macros
How Do the Structure Macros Work?
Declaring and Initializing Structure Handles
Operations on Structure Handles
18. SCSI Host Bus Adapter Drivers
19. Drivers for Network Devices
Part III Building a Device Driver
22. Compiling, Loading, Packaging, and Testing Drivers
23. Debugging, Testing, and Tuning Device Drivers
24. Recommended Coding Practices
B. Summary of Oracle Solaris DDI/DKI Services
C. Making a Device Driver 64-Bit Ready
The attach(9E) routine should perform the common initialization tasks that all devices require, such as:
Allocating per-instance state structures
Registering device interrupts
Mapping the device's registers
Initializing mutex variables and condition variables
Creating power-manageable components
Creating minor nodes
See attach() Entry Point for code examples of these tasks.
Character device drivers create minor nodes of type S_IFCHR. A minor node of S_IFCHR causes a character special file that represents the node to eventually appear in the /devices hierarchy.
The following example shows a typical attach(9E) routine for character drivers. Properties that are associated with the device are commonly declared in an attach() routine. This example uses a predefined Size property. Size is the equivalent of the Nblocks property for getting the size of partition in a block device. If, for example, you are doing character I/O on a disk device, you might use Size to get the size of a partition. Since Size is a 64-bit property, you must use a 64-bit property interface. In this case, you use ddi_prop_update_int64(9F). See Device Properties for more information about properties.
Example 15-1 Character Driver attach() Routine
static int xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int instance = ddi_get_instance(dip); switch (cmd) { case DDI_ATTACH: /* * Allocate a state structure and initialize it. * Map the device's registers. * Add the device driver's interrupt handler(s). * Initialize any mutexes and condition variables. * Create power manageable components. * * Create the device's minor node. Note that the node_type * argument is set to DDI_NT_TAPE. */ if (ddi_create_minor_node(dip, minor_name, S_IFCHR, instance, DDI_NT_TAPE, 0) == DDI_FAILURE) { /* Free resources allocated so far. */ /* Remove any previously allocated minor nodes. */ ddi_remove_minor_node(dip, NULL); return (DDI_FAILURE); } /* * Create driver properties like "Size." Use "Size" * instead of "size" to ensure the property works * for large bytecounts. */ xsp->Size = size_of_device_in_bytes; maj_number = ddi_driver_major(dip); if (ddi_prop_update_int64(makedevice(maj_number, instance), dip, "Size", xsp->Size) != DDI_PROP_SUCCESS) { cmn_err(CE_CONT, "%s: cannot create Size property\n", ddi_get_name(dip)); /* Free resources allocated so far. */ return (DDI_FAILURE); } /* ... */ return (DDI_SUCCESS); case DDI_RESUME: /* See the "Power Management" chapter in this book. */ default: return (DDI_FAILURE); } }