Writing Device Drivers

kadbMacros

kadb(1M) supports macros that are used for displaying kernel data structures. kadb macros can be displayed with $M. Macros are used in the form:

    [ address ] $<macroname

Note –

Neither the information displayed by these macros, nor the format in which the information is displayed constitute an interface. Therefore, the information and format can change at any time.


Device Macros

This section describes the kadb(1M) macros that can be used to retrieve information from the kernel about a device during a debugging session.

devinfo_brief

Prints a brief summary of a dev_info_t structure; the name and addr fields are shown in string form and are used in the /devices path to the node

devinfo

Prints devinfo_brief information for a dev_info_t structure followed by an in-order dump of all fields

devinfo.parent

Prints devinfo_brief information for the specified node and its parents all the way back to the root of the devinfo tree

devinfo.sibling

Prints devinfo_brief information for all siblings of the specified node; you see all sibling nodes if you start at the parent's child

devinfo.minor

Prints the ddi_minor_data structure for all minor name nodes associated with the specified device node

devinfo.prop

Prints all the property lists associated with the specified device node 

devinfo_major

Prints devinfo_brief information for all device nodes associated with the specified driver major number

devt

Breaks a dev_t into its major and minor parts and prints the values in hexadecimal and decimal

devnames

Prints the contents of the specified devnames structure

devnames_major

Prints the contents of the devnames structure for the specified major number

bus_op

Prints the contents of a bus_ops structure

The devinfo commands, such as devinfo and devinfo_brief, return a node_state value, which may be one of the following:

DS_LINKED

This device node has been linked into the kernel's device tree, but the system has not yet found a driver for it.

DS_BOUND

The node is bound to a driver, but the driver's probe(9E) routine has not yet been called.

DS_INITIALIZED

The parent nexus has assigned a bus address for the driver and completed implementation-specific initializations, but the driver's probe(9E) routine has not yet been called.

DS_PROBED

The driver's probe(9E) routine returned successfully.

DS_ATTACHED

The driver's attach(9E) routine returned successfully.

DS_READY

The device is fully configured.

Examples: Use of Device Macros

The examples in this section show how some of the device-related macros can be used to debug a driver.

The following ls -l command shows how the /devices path fits into the devinfo structure:

# ls -l /dev/ttya
lrwxrwxrwx   1 root   root   6 Aug 17 17:50 /dev/ttya -> term/a
# ls -l /dev/term/a
lrwxrwxrwx   1 root   root   32 Aug 17 17:42 /dev/term/a -> 
    ../../devices/obio/zs@0,100000:a

Example 18–1 shows how to obtain information about the /dev/ttya device from the devinfo structure and other kernel structures, beginning with devinfo_major.


Example 18–1 The devinfo_major Macro

# ls -lL /dev/ttya
crw-rw-rw-   1 root     sys    29,  0 Aug 17 17:42 /dev/ttya
# ~stopped      at:
edd000d8:       ta      %icc,%g0 + 125
kadb[0]: 0t29$<devinfo_major
                ============== devinfo  f5f0dcd0
                                binding_name
0xf5bb38f8:                       zs
                                node_name
0xf5bb38f8:                       zs
                                addr
0xf5f8d6a0:                       0,100000
                                node_state
                                  6                 DS_READY
                                major (hex)
                                  1d
                                instance
                                  0

0xf5f0dcd0:     parent          child           sibling
                f5f0f380        0               f5f0dba8

                ============== devinfo  f5f0dba8
                                binding_name
0xf5bb3a18:                       zs
                                node_name
0xf5bb3a18:                       zs
                                addr
0xf5f90560:                       0,0
                                node_state
                                  6                 DS_READY
                                major (hex)
                                  1d
                                instance
                                  1

0xf5f0dba8:     parent          child           sibling
                f5f0f380        0               f5f0da80


Example 18–2 shows the use of the devinfo_brief macro. It also shows the use of top_devinfo. top_devinfo is a pointer to the root of the devinfo tree (rootnexus)—all other devinfo nodes are descendants of this node. If you want to look at the device tree top-down in the debugger, this is where you start.


Example 18–2 The devinfo_brief Macro

kadb[0]: *top_devinfo$<devinfo_brief

                ============== devinfo  f5f0fde8
                                binding_name
0xf5bc6a30:                       SUNW,SPARCstation-10
                                node_name
0xf5bc6af8:                       SUNW,SPARCstation-10
                                addr
0xf5f90950:
                                node_state
                                  6                 DS_READY
                                major (hex)
                                  1

0xf5f0fde8:     parent          child           sibling
                0               f5f0fcc0        0

Thread Macros

threadlist is a useful macro that displays the stacks of all the threads in the system.


Example 18–3 The threadlist Macro

kadb[0]: $<threadlist

                ============== thread_id        10404000
p0+0x300:
                process args    sched

t0+0xa8:        lwp             procp           wchan
                1041b810        10424688        0
t0+0x24:
                pc              sp
                sched+0x4f4     10403be8
?(10404000,1040c000,2,10424604,0,6e)
_start(10006ef4,1041adb0,1041adb0,1041adb0,10462910,50) + 15c

...

                ============== thread_id        40043e60
p0+0x300:
                process args    sched

40043f08:       lwp             procp           wchan
                0               10424688        10473c56
40043e84:
                pc              sp
                cv_wait+0x60    40043c08
?(10473c56,10473c5c,0,40043cd0,40043e60,10093084)
ufs_thread_idle(10471e80,0,10473c5c,10424688,81010100,0) + bc
thread_start(0,0,0,0,0,0) + 4
...

Another useful macro is thread. Given a thread ID, this macro prints the corresponding thread structure. This can be used to look at a certain thread found with the threadlist macro, to look at the owner of a mutex, or to look at the current thread, as shown here:


Example 18–4 The thread Macro

kadb[0]: <g7$<thread
70e87ac0:       link            stk             startpc
                0               4026bc80        0
70e87acc:       bound_cpu       affinitycnt     bind_cpu
                0               0               -1
70e87ad4:       flag    proc_flag       schedflag
                0       4               3
70e87ada:       preempt preempt_lk      state
                0       0               4
70e87ae0:       pri     epri
                40      0
70e87ae4:
                pc              sp
                10098350        4026b618
70e87aec:       wchan0          wchan           sobj_ops
                0               0               0
70e87af8:       cid             clfuncs         cldata
                1               10470ffc        702c0488
70e87b04:       ctx             lofault         onfault
                0               0               0
...


Note –

No type information is maintained by kadb, so using a macro on an inappropriate address results in garbage output.


Macros do not necessarily output all the fields of the structures, nor is the output necessarily in the order given in the structure definition. Occasionally, memory needs to be dumped for certain structures and then matched with the structure definition in the kernel header files.


Caution – Caution –

Drivers should never reference system header files or structures not listed in man pages section 9S: DDI and DKI Data Structures. However, examining non-DDI-compliant structures (such as thread structures) can be useful in debugging drivers.