xref: /illumos-gate/usr/src/man/man9f/Intro.9f (revision aaceae985c2e78cadef76bf0b7b50ed887ccb3a6)
1.\"
2.\" This file and its contents are supplied under the terms of the
3.\" Common Development and Distribution License ("CDDL"), version 1.0.
4.\" You may only use this file in accordance with the terms of version
5.\" 1.0 of the CDDL.
6.\"
7.\" A full copy of the text of the CDDL should have accompanied this
8.\" source.  A copy of the CDDL is also available via the Internet at
9.\" http://www.illumos.org/license/CDDL.
10.\"
11.\"
12.\" Copyright 2024 Oxide Computer Company
13.\" Copyright 2023 Peter Tribble
14.\"
15.Dd October 27, 2024
16.Dt INTRO 9F
17.Os
18.Sh NAME
19.Nm Intro
20.Nd Introduction to kernel and device driver functions
21.Sh SYNOPSIS
22.In sys/ddi.h
23.In sys/sunddi.h
24.Sh DESCRIPTION
25Section 9F of the manual page describes functions that are used for device
26drivers, kernel modules, and the implementation of the kernel itself.
27This first provides an overview for the use of kernel functions and portions of
28the manual that are specific to the kernel.
29After that, we have grouped together most functions that are available by use,
30with some brief commentary and introduction.
31.Pp
32Most manual pages are similar to those in other sections.
33They have common fields such as the NAME, a SYNOPSIS to show which header files
34to include and prototypes, an extended DESCRIPTION discussing its use, and the
35common combination of RETURN VALUES and ERRORS.
36Some manuals will have examples and additional manuals to reference in the SEE
37ALSO section.
38.Ss RETURN VALUES and ERRORS
39One major difference when programming in the kernel versus userland is that
40there is no equivalent to
41.Va errno .
42Instead, there are a few common patterns that are used throughout the kernel
43that we'll discuss.
44While there are common patterns, please be aware that due to the natural
45evolution of the system, you will need to read the specifics of the
46section.
47.Bl -bullet
48.It
49Many functions will return a specific DDI
50.Pq Device Driver Interface
51value, which is commonly one of
52.Dv DDI_SUCCESS
53or
54.Dv DDI_FAILURE ,
55indicating success and failure respectively.
56Some functions will return additional error codes to indicate why something
57failed.
58In general, when checking a response code is always preferred to compare that
59something equals or does not equal
60.Dv DDI_SUCCESS
61as there can be many different error cases and additional ones can be added over
62time.
63.It
64Many routines explicitly return
65.Sy 0
66on success and will return an explicit error number.
67.Xr Intro 2
68has a list of error numbers.
69.It
70There are classes of functions that return either a pointer or a boolean type,
71either the C99
72.Vt bool
73or the system's traditional type
74.Vt boolean_t .
75In these cases, sometimes a more detailed error is provided via an additional
76argument such as a
77.Vt "int *" .
78Absent such an argument, there is generally no more detailed information
79available.
80.El
81.Ss CONTEXT
82The CONTEXT section of a manual page describes the times in which this function
83may be called.
84In generally there are three different contexts that come up:
85.Bl -tag -width Ds
86.It Sy User
87User context implies that the thread of execution is operating because a user
88thread has entered the kernel for an operation.
89When an application issues a system call such as
90.Xr open 2 ,
91.Xr read 2 ,
92.Xr write 2 ,
93or
94.Xr ioctl 2
95then we are said to be in user context.
96When in user context, one can copy in or out data from a user's address space.
97When writing a character or block device driver, the majority of the time that a
98character device operation such as the corresponding
99.Xr open 9E ,
100.Xr read 9E ,
101.Xr write 9E ,
102and
103.Xr ioctl 9E
104entry point being called, it is executing in user context.
105It is possible to call those entry points through the kernel's layered device
106interface, so drivers cannot assume those entry points will always have a user
107process present, strictly speaking.
108.It Sy Interrupt
109Interrupt context refers to when the operating system is handling an interrupt
110.Po
111See
112.Sx Interrupt Related Functions
113.Pc
114and executing a registered interrupt handler.
115Interrupt context is split into two different sets: high-level and low-level
116interrupts.
117Most device drivers are always going to be executing low-level interrupts.
118To determine whether an interrupt is considered high level or not, you should
119pass the interrupt handle to the
120.Xr ddi_intr_get_pri 9F
121function and compare the resulting priority with
122.Xr ddi_intr_get_hilevel_pri 9F .
123.Pp
124When executing high-level interrupts, the thread may only execute a limited
125number of functions.
126In particular, it may call
127.Xr ddi_intr_trigger_softint 9F ,
128.Xr mutex_enter 9F ,
129and
130.Xr mutex_exit 9F .
131It is critical that the mutex being used be properly initialized with the
132driver's interrupt priority.
133The system will transparently pick the correct implementation of a mutex based
134on the interrupt type.
135Aside from the above, one must not block while in high-level interrupt context.
136.Pp
137On the other hand, when a thread is not in high-level interrupt context, most of
138these restrictions are lifted.
139Kernel memory may be allocated
140.Po
141if using a non-blocking allocation such as
142.Dv KM_NOSLEEP
143or
144.Dv KM_NOSLEEP_LAZY
145.Pc ,
146and many of the other documented functions may be called.
147.Pp
148Regardless of whether a thread is in high-level or low-level interrupt context,
149it will never have a user context associated with it and therefore cannot use
150routines like
151.Xr ddi_copyin 9F
152or
153.Xr ddi_copyout 9F .
154.It Sy Kernel
155Kernel context refers to all other times in the kernel.
156Whenever the kernel is executing something on a thread that is not associated
157with a user process, then one is in kernel context.
158The most common situation for writers of kernel modules are things like timeout
159callbacks, such as
160.Xr timeout 9F
161or
162.Xr ddi_periodic_add 9F ,
163cases where the kernel is invoking a driver's device operation routines such as
164.Xr attach 9E
165and
166.Xr detach 9E ,
167or many of the device driver's registered callbacks from frameworks such as the
168.Xr mac 9E ,
169.Xr usba_hcdi 9E ,
170and various portions of SCSI, USB, and block devices.
171.It Sy Framework-specific Contexts
172Some manuals will discuss more specific constraints about when they can be used.
173For example, some functions may only be called while executing a specific entry
174point like
175.Xr attach 9E .
176Another example of this is that the
177.Xr mac_transceiver_info_set_present 9F
178function is only meant to be used while executing a networking driver's
179.Xr mct_info 9E
180entry point.
181.El
182.Ss PARAMETERS
183In kernel manual pages
184.Pq section 9 ,
185each function and entry point description generally has a separate list
186of parameters which are arguments to the function.
187The parameters section describes the basic purpose of each argument and
188should explain where such things often come from and any constraints on
189their values.
190.Sh INTERFACES
191Functions below are organized into categories that describe their purpose.
192Individual functions are documented in their own manual pages.
193For each of these areas, we discuss high-level concepts behind each area and
194provide a brief discussion of how to get started with it.
195Note, some deprecated functions or older frameworks are not listed here.
196.Pp
197Every function listed below has its own manual page in section 9F and
198can be read with
199.Xr man 1 .
200In addition, some corresponding concepts are documented in section 9 and
201some groups of functions are present to support a specific type of
202device driver, which is discussed more in section 9E .
203.Ss Logging Functions
204Through the kernel there are often needs to log messages that either
205make it into the system log or on the console.
206These kinds of messages can be performed with the
207.Xr cmn_err 9F
208function or one of its more specific variants that operate in the
209context of a device
210.Po
211.Xr dev_err 9F
212.Pc
213or a zone
214.Po
215.Xr zcmn_err 9F
216.Pc .
217.Pp
218The console should be used sparingly.
219While a notice may be found there, one should assume that it may be
220missed either due to overflow, not being connected to say a serial
221console at the time, or some other reason.
222While the system log is better than the console, folks need to take care
223not to spam the log.
224Imagine if someone logged every time a network packet was generated or
225received, you'd quickly potentially run out of space and make it harder
226to find useful messages for bizarre behavior.
227It's also important to remember that only system administrators and
228privileged users can actually see this log.
229Where possible and appropriate use programmatic errors in routines that
230allow it.
231.Pp
232The system also supports a structured event log called a system event
233that is processed by
234.Xr syseventd 8 .
235This is used by the OS to provide notifications for things like device
236insertion and removal or the change of a data link.
237These are driven by the
238.Xr ddi_log_sysevent 9F
239function and allow arbitrary additional structured metadata in the form
240of a
241.Vt nvlist_t .
242.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
243.It Xr cmn_err 9F Ta Xr dev_err 9F
244.It Xr vcmn_err 9F Ta Xr vzcmn_err 9F
245.It Xr zcmn_err 9F Ta Xr ddi_log_sysevent 9F
246.El
247.Ss Memory Allocation
248At the heart of most device drivers is memory allocation.
249The primary kernel allocator is called
250.Qq kmem
251.Pq kernel memory
252and it is based on the
253.Qq vmem
254.Pq virtual memory
255subsystem.
256Most of the time, device drivers should use
257.Xr kmem_alloc 9F
258and
259.Xr kmem_zalloc 9F
260to allocate memory and free it with
261.Xr kmem_free 9F .
262Based on the original kmem and subsequent vmem papers, the kernel is
263internally using object caches and magazines to allow high-throughput
264allocation in a multi-CPU environment.
265.Pp
266When allocating memory, an important choice must be made: whether or not
267to block for memory.
268If one opts to perform a sleeping allocation, then the caller can be
269guaranteed that the allocation will succeed, but it may take some time
270and the thread will be blocked during that entire duration.
271This is the
272.Dv KM_SLEEP
273flag.
274On the other hand, there are many circumstances where this is not
275appropriate, especially because a thread that is inside a memory
276allocation function cannot currently be cancelled.
277If the thread corresponds to a user process, then it will not be
278killable.
279.Pp
280Given that there are many situations where this is not appropriate, the
281kernel offers an allocation mode where it will not block for memory to
282be available:
283.Dv KM_NOSLEEP
284and
285.Dv KM_NOSLEEP_LAZY .
286These allocations can fail and return
287.Dv NULL
288when they do fail.
289Even though these are said to be no sleep operations, that does not mean
290that the caller may not end up temporarily blocked due to mutex
291contention or due to trying a bit more aggressively to reclaim memory in
292the case of
293.Dv KM_NOSLEEP .
294Unless operating in special circumstances, using
295.Dv KM_NOSLEEP_LAZY
296should be preferred to
297.Dv KM_NOSLEEP .
298.Pp
299If a device driver has its own complex object that has more significant
300set up and tear down costs, then the kmem cache function family should
301be considered.
302To use a kmem cache, it must first be created using the
303.Xr kmem_cache_create 9F
304function, which requires specifying the size, alignment, and
305constructors and destructors.
306Individual objects are allocated from the cache with the
307.Xr kmem_cache_alloc 9F
308function.
309An important constraint when using the caches is that when an object is
310freed with
311.Xr kmem_cache_free 9F ,
312it is the callers responsibility to ensure that the object is returned
313to its constructed state prior to freeing it.
314If the object is reused, prior to the kernel reclaiming the memory for
315other uses, then the constructor will not be called again.
316Most device drivers do not need to create a kmem cache for their
317own allocations.
318.Pp
319If you are writing a device driver that is trying to interact with the
320networking, STREAMS, or USB subsystems, then they are generally using
321the
322.Vt mblk_t
323data structure which is managed through a different set of APIs, though
324they are leveraging kmem under the hood.
325.Pp
326The vmem set of interfaces allows for the management of abstract regions
327of integers, generally representing memory or some other object, each
328with an offset and length.
329While it is not common that a device driver needs to do their own such
330management,
331.Xr vmem_create 9F
332and
333.Xr vmem_alloc 9F
334are what to reach for when the need arises.
335Rather than using vmem, if one needs to model a set of integers where
336each is a valid identifier, that is you need to allocate every integer
337between 0 and 1000 as a distinct identifier, instead use
338.Xr id_space_create 9F
339which is discussed in
340.Sx Identifier Management .
341For more information on vmem, see
342.Xr vmem 9 .
343.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
344.It Xr kmem_alloc 9F Ta Xr kmem_cache_alloc 9F
345.It Xr kmem_cache_create 9F Ta Xr kmem_cache_destroy 9F
346.It Xr kmem_cache_free 9F Ta Xr kmem_cache_set_move 9F
347.It Xr kmem_free 9F Ta Xr kmem_zalloc 9F
348.It Xr vmem_add 9F Ta Xr vmem_alloc 9F
349.It Xr vmem_contains 9F Ta Xr vmem_create 9F
350.It Xr vmem_destroy 9F Ta Xr vmem_free 9F
351.It Xr vmem_size 9F Ta Xr vmem_walk 9F
352.It Xr vmem_xalloc 9F Ta Xr vmem_xcreate 9F
353.It Xr vmem_xfree 9F Ta Xr bufcall 9F
354.It Xr esbbcall 9F Ta Xr qbufcall 9F
355.It Xr qunbufcall 9F Ta Xr unbufcall 9F
356.El
357.Ss String and libc Analogues
358The kernel has many analogues for classic libc functions that deal with
359string processing, memory copying, bit manipulation, and related.
360For the most part, these behave similarly to their userland analogues,
361but there can be some differences in return values and for example, in
362the set of supported format characters in the case of
363.Xr snprintf 9F
364and related.
365.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
366.It Xr ASSERT 9F Ta Xr bcmp 9F
367.It Xr bzero 9F Ta Xr bcopy 9F
368.It Xr ddi_strdup 9F Ta Xr ddi_strtol 9F
369.It Xr ddi_strtoll 9F Ta Xr ddi_strtoul 9F
370.It Xr ddi_strtoull 9F Ta Xr ddi_ffs 9F
371.It Xr ddi_fls 9F Ta Xr max 9F
372.It Xr memchr 9F Ta Xr memcmp 9F
373.It Xr memcpy 9F Ta Xr memmove 9F
374.It Xr memset 9F Ta Xr min 9F
375.It Xr numtos 9F Ta Xr snprintf 9F
376.It Xr sprintf 9F Ta Xr stoi 9F
377.It Xr stdc_bit_ceil 9F Ta Xr stdc_bit_floor 9F
378.It Xr stdc_bit_width 9F Ta Xr stdc_count_ones 9F
379.It Xr stdc_count_zeros 9F Ta Xr stdc_first_leading_one 9F
380.It Xr stdc_first_leading_zero 9F Ta Xr stdc_first_trailing_one 9F
381.It Xr stdc_first_trailing_zero 9F Ta Xr stdc_has_single_bit 9F
382.It Xr stdc_leading_ones 9F Ta Xr stdc_leading_zeros 9F
383.It Xr stdc_trailing_ones 9F Ta Xr stdc_trailing_zeros 9F
384.It Xr strcasecmp 9F Ta Xr strcat 9F
385.It Xr strchr 9F Ta Xr strcmp 9F
386.It Xr strcpy 9F Ta Xr strdup 9F
387.It Xr strfree 9F Ta Xr string 9F
388.It Xr strlcat 9F Ta Xr strlcpy 9F
389.It Xr strlen 9F Ta Xr strlog 9F
390.It Xr strncasecmp 9F Ta Xr strncat 9F
391.It Xr strncmp 9F Ta Xr strncpy 9F
392.It Xr strnlen 9F Ta Xr strqget 9F
393.It Xr strqset 9F Ta Xr strrchr 9F
394.It Xr strspn 9F Ta Xr swab 9F
395.It Xr vsnprintf 9F Ta Xr va_arg 9F
396.It Xr va_copy 9F Ta Xr va_end 9F
397.It Xr va_start 9F Ta Xr vsprintf 9F
398.El
399.Ss Tree Data Structures
400These functions provide access to an intrusive self-balancing binary
401tree that is generally used throughout illumos.
402The primary type here is the
403.Vt avl_tree_t .
404Structures can be present in multiple trees and there are built-in
405walkers for the data structure in
406.Xr mdb 1 .
407.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
408.It Xr avl_add 9F Ta Xr avl_create 9F
409.It Xr avl_destroy_nodes 9F Ta Xr avl_destroy 9F
410.It Xr avl_find 9F Ta Xr avl_first 9F
411.It Xr avl_insert_here 9F Ta Xr avl_insert 9F
412.It Xr avl_is_empty 9F Ta Xr avl_last 9F
413.It Xr avl_nearest 9F Ta Xr AVL_NEXT 9F
414.It Xr avl_numnodes 9F Ta Xr AVL_PREV 9F
415.It Xr avl_remove 9F Ta Xr avl_swap 9F
416.El
417.Ss Linked Lists
418These functions provide a standard, intrusive doubly-linked list whose
419type is the
420.Vt list_t .
421This list implementation is used extensively throughout illumos, has
422debugging support through
423.Xr mdb 1
424walkers, and is generally recommended rather than creating your own
425list.
426Due to its intrusive nature, a given structure can be present on
427multiple lists.
428.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
429.It Xr list_create 9F Ta Xr list_destroy 9F
430.It Xr list_head 9F Ta Xr list_insert_after 9F
431.It Xr list_insert_before 9F Ta Xr list_insert_head 9F
432.It Xr list_insert_tail 9F Ta Xr list_is_empty 9F
433.It Xr list_link_active 9F Ta Xr list_link_init 9F
434.It Xr list_link_replace 9F Ta Xr list_move_tail 9F
435.It Xr list_next 9F Ta Xr list_prev 9F
436.It Xr list_remove_head 9F Ta Xr list_remove_tail 9F
437.It Xr list_remove 9F Ta Xr list_tail 9F
438.El
439.Ss Name-Value Pairs
440The kernel often uses the
441.Vt nvlist_t
442data structure to pass around a list of typed name-value pairs.
443This data structure is used in diverse areas, particularly because of
444its ability to be serialized in different formats that are suitable not
445only for use between userland and the kernel, but also persistently to a
446file.
447.Pp
448A
449.Vt nvlist_t
450structure is initialized with the
451.Xr nvlist_alloc 9F
452function and can operate with two different degrees of uniqueness: a
453mode where only names are unique or that every name is qualified to a
454type.
455The former means that if I have an integer name
456.Dq foo
457and then add a string, array, or any other value with the same name, it
458will be replaced.
459However, if were using the name and type as unique, then the value would
460only be replaced if both the pair's type and the name
461.Dq foo
462matched a pair that was already present.
463Otherwise, the two different entries would co-exist.
464.Pp
465When constructing an nvlist, it is normally backed by the normal kmem
466allocator and may either use sleeping or non-sleeping allocations.
467It is also possible to use a custom allocator, though that generally has
468not been necessary in the kernel.
469.Pp
470Specific keys and values can be looked up directly with the
471nvlist_lookup family of functions, but the entire list can be iterated
472as well, which is especially useful when trying to validate that no
473unknown keys are present in the list.
474The iteration API
475.Xr nvlist_next_nvpair 9F
476allows one to then get both the key's name, the type of value of the
477pair, and then the value itself.
478.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
479.It Xr nv_alloc_fini 9F Ta Xr nv_alloc_init 9F
480.It Xr nvlist_add_boolean_array 9F Ta Xr nvlist_add_boolean_value 9F
481.It Xr nvlist_add_boolean 9F Ta Xr nvlist_add_byte_array 9F
482.It Xr nvlist_add_byte 9F Ta Xr nvlist_add_int16_array 9F
483.It Xr nvlist_add_int16 9F Ta Xr nvlist_add_int32_array 9F
484.It Xr nvlist_add_int32 9F Ta Xr nvlist_add_int64_array 9F
485.It Xr nvlist_add_int64 9F Ta Xr nvlist_add_int8_array 9F
486.It Xr nvlist_add_int8 9F Ta Xr nvlist_add_nvlist_array 9F
487.It Xr nvlist_add_nvlist 9F Ta Xr nvlist_add_nvpair 9F
488.It Xr nvlist_add_string_array 9F Ta Xr nvlist_add_string 9F
489.It Xr nvlist_add_uint16_array 9F Ta Xr nvlist_add_uint16 9F
490.It Xr nvlist_add_uint32_array 9F Ta Xr nvlist_add_uint32 9F
491.It Xr nvlist_add_uint64_array 9F Ta Xr nvlist_add_uint64 9F
492.It Xr nvlist_add_uint8_array 9F Ta Xr nvlist_add_uint8 9F
493.It Xr nvlist_alloc 9F Ta Xr nvlist_dup 9F
494.It Xr nvlist_exists 9F Ta Xr nvlist_free 9F
495.It Xr nvlist_lookup_boolean_array 9F Ta Xr nvlist_lookup_boolean_value 9F
496.It Xr nvlist_lookup_boolean 9F Ta Xr nvlist_lookup_byte_array 9F
497.It Xr nvlist_lookup_byte 9F Ta Xr nvlist_lookup_int16_array 9F
498.It Xr nvlist_lookup_int16 9F Ta Xr nvlist_lookup_int32_array 9F
499.It Xr nvlist_lookup_int32 9F Ta Xr nvlist_lookup_int64_array 9F
500.It Xr nvlist_lookup_int64 9F Ta Xr nvlist_lookup_int8_array 9F
501.It Xr nvlist_lookup_int8 9F Ta Xr nvlist_lookup_nvlist_array 9F
502.It Xr nvlist_lookup_nvlist 9F Ta Xr nvlist_lookup_nvpair 9F
503.It Xr nvlist_lookup_pairs 9F Ta Xr nvlist_lookup_string_array 9F
504.It Xr nvlist_lookup_string 9F Ta Xr nvlist_lookup_uint16_array 9F
505.It Xr nvlist_lookup_uint16 9F Ta Xr nvlist_lookup_uint32_array 9F
506.It Xr nvlist_lookup_uint32 9F Ta Xr nvlist_lookup_uint64_array 9F
507.It Xr nvlist_lookup_uint64 9F Ta Xr nvlist_lookup_uint8_array 9F
508.It Xr nvlist_lookup_uint8 9F Ta Xr nvlist_merge 9F
509.It Xr nvlist_next_nvpair 9F Ta Xr nvlist_pack 9F
510.It Xr nvlist_remove_all 9F Ta Xr nvlist_remove 9F
511.It Xr nvlist_size 9F Ta Xr nvlist_t 9F
512.It Xr nvlist_unpack 9F Ta Xr nvlist_xalloc 9F
513.It Xr nvlist_xdup 9F Ta Xr nvlist_xpack 9F
514.It Xr nvlist_xunpack 9F Ta Xr nvpair_name 9F
515.It Xr nvpair_type 9F Ta Xr nvpair_value_boolean_array 9F
516.It Xr nvpair_value_byte_array 9F Ta Xr nvpair_value_byte 9F
517.It Xr nvpair_value_int16_array 9F Ta Xr nvpair_value_int16 9F
518.It Xr nvpair_value_int32_array 9F Ta Xr nvpair_value_int32 9F
519.It Xr nvpair_value_int64_array 9F Ta Xr nvpair_value_int64 9F
520.It Xr nvpair_value_int8_array 9F Ta Xr nvpair_value_int8 9F
521.It Xr nvpair_value_nvlist_array 9F Ta Xr nvpair_value_nvlist 9F
522.It Xr nvpair_value_string_array 9F Ta Xr nvpair_value_string 9F
523.It Xr nvpair_value_uint16_array 9F Ta Xr nvpair_value_uint16 9F
524.It Xr nvpair_value_uint32_array 9F Ta Xr nvpair_value_uint32 9F
525.It Xr nvpair_value_uint64_array 9F Ta Xr nvpair_value_uint64 9F
526.It Xr nvpair_value_uint8_array 9F Ta Xr nvpair_value_uint8 9F
527.El
528.Ss Identifier Management
529A common challenge in the kernel is the management of a series of
530different IDs.
531There are three different families of routines for managing identifiers
532presented here, but we recommend the use of the
533.Xr id_space_create 9F
534and
535.Xr id_alloc 9F
536family for new use cases.
537The ID space can cover all or a subset of the 32-bit integer space and
538provides different allocation strategies for this.
539.Pp
540Due to the current implementation, callers should generally prefer the
541non-sleeping variants because the sleeping ones are not cancellable
542.Po
543currently this is backed by vmem, but this should not be assumed and may
544change in the future
545.Pc .
546.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
547.It Xr id_alloc_nosleep 9F Ta Xr id_alloc_specific_nosleep 9F
548.It Xr id_alloc 9F Ta Xr id_allocff_nosleep 9F
549.It Xr id_allocff 9F Ta Xr id_free 9F
550.It Xr id_space_create 9F Ta Xr id_space_destroy 9F
551.It Xr id_space_extend 9F Ta Xr id_space 9F
552.It Xr id32_alloc 9F Ta Xr id32_free 9F
553.It Xr id32_lookup 9F Ta Xr rmalloc_wait 9F
554.It Xr rmalloc 9F Ta Xr rmallocmap_wait 9F
555.It Xr rmallocmap 9F Ta Xr rmfree 9F
556.It Xr rmfreemap 9F Ta
557.El
558.Ss Bit Manipulation Routines
559Many device drivers that are working with registers often need to get a
560specific range of bits out of an integer.
561These functions provide safe ways to set
562.Pq bitset
563and extract
564.Pq bitx
565bit ranges, as well
566as modify an integer to remove a set of bits entirely
567.Pq bitdel .
568Using these functions is preferred to constructing manual masks and
569shifts particularly when a programming manual for a device is specified
570in ranges of bits.
571On debug builds, these provide extra checking to try and catch
572programmer error.
573.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
574.It Xr bitdel64 9F Ta Xr bitset8 9F
575.It Xr bitset16 9F Ta Xr bitset32 9F
576.It Xr bitset64 9F Ta Xr bitx8 9F
577.It Xr bitx16 9F Ta Xr bitx32 9F
578.It Xr bitx64 9F Ta
579.El
580.Ss Synchronization Primitives
581The kernel provides a set of basic synchronization primitives that can
582be used by the system.
583These include mutexes, condition variables, reader/writer locks, and
584semaphores.
585When creating mutexes and reader/writer locks, the kernel requires that
586one pass in the interrupt priority of a mutex if it will be used in
587interrupt context.
588This is required so the kernel can determine the correct underlying type
589of lock to use.
590This ensures that if for some reason a mutex needs to be used in
591high-level interrupt context, the kernel will use a spin lock, but
592otherwise can use the standard adaptive mutex that might block.
593For developers familiar with other operating systems, this is somewhat
594different in that the consumer does not need to generally figure out
595this level of detail and this is why this is not present.
596.Pp
597In addition, condition variables provide means for waiting and detecting
598that a signal has been delivered.
599These variants are particularly useful when writing character device
600operations for device drivers as it allows users the chance to cancel an
601operation and not be blocked indefinitely on something that may not
602occur.
603These _sig variants should generally be preferred where applicable.
604.Pp
605The kernel also provides memory barrier primitives.
606See the
607.Sx Memory Barriers
608section for more information.
609There is no need to use manual memory barriers when using the
610synchronization primitives.
611The synchronization primitives contain that the appropriate barriers are
612present to ensure coherency while the lock is held.
613.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
614.It Xr cv_broadcast 9F Ta Xr cv_destroy 9F
615.It Xr cv_init 9F Ta Xr cv_reltimedwait_sig 9F
616.It Xr cv_reltimedwait 9F Ta Xr cv_signal 9F
617.It Xr cv_timedwait_sig 9F Ta Xr cv_timedwait 9F
618.It Xr cv_wait_sig 9F Ta Xr cv_wait 9F
619.It Xr ddi_enter_critical 9F Ta Xr ddi_exit_critical 9F
620.It Xr mutex_destroy 9F Ta Xr mutex_enter 9F
621.It Xr mutex_exit 9F Ta Xr mutex_init 9F
622.It Xr mutex_owned 9F Ta Xr mutex_tryenter 9F
623.It Xr rw_destroy 9F Ta Xr rw_downgrade 9F
624.It Xr rw_enter 9F Ta Xr rw_exit 9F
625.It Xr rw_init 9F Ta Xr rw_read_locked 9F
626.It Xr rw_tryenter 9F Ta Xr rw_tryupgrade 9F
627.It Xr sema_destroy 9F Ta Xr sema_init 9F
628.It Xr sema_p_sig 9F Ta Xr sema_p 9F
629.It Xr sema_tryp 9F Ta Xr sema_v 9F
630.It Xr semaphore 9F Ta
631.El
632.Ss Atomic Operations
633This group of functions provides a general way to perform atomic
634operations on integers of different sizes and explicit types.
635The
636.Xr atomic_ops 9F
637manual page describes the different classes of functions in more detail,
638but there are functions that take care of using the CPU's instructions
639for addition, compare and swap, and more.
640If data is being protected and only accessed under a synchronization
641primitive such as a mutex or reader-writer lock, then there isn't a
642reason to use an atomic operation for that data, generally speaking.
643.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
644.It Xr atomic_add_8_nv 9F Ta Xr atomic_add_8 9F
645.It Xr atomic_add_16_nv 9F Ta Xr atomic_add_16 9F
646.It Xr atomic_add_32_nv 9F Ta Xr atomic_add_32 9F
647.It Xr atomic_add_64_nv 9F Ta Xr atomic_add_64 9F
648.It Xr atomic_add_char_nv 9F Ta Xr atomic_add_char 9F
649.It Xr atomic_add_int_nv 9F Ta Xr atomic_add_int 9F
650.It Xr atomic_add_long_nv 9F Ta Xr atomic_add_long 9F
651.It Xr atomic_add_ptr_nv 9F Ta Xr atomic_add_ptr 9F
652.It Xr atomic_add_short_nv 9F Ta Xr atomic_add_short 9F
653.It Xr atomic_and_8_nv 9F Ta Xr atomic_and_8 9F
654.It Xr atomic_and_16_nv 9F Ta Xr atomic_and_16 9F
655.It Xr atomic_and_32_nv 9F Ta Xr atomic_and_32 9F
656.It Xr atomic_and_64_nv 9F Ta Xr atomic_and_64 9F
657.It Xr atomic_and_uchar_nv 9F Ta Xr atomic_and_uchar 9F
658.It Xr atomic_and_uint_nv 9F Ta Xr atomic_and_uint 9F
659.It Xr atomic_and_ulong_nv 9F Ta Xr atomic_and_ulong 9F
660.It Xr atomic_and_ushort_nv 9F Ta Xr atomic_and_ushort 9F
661.It Xr atomic_cas_16 9F Ta Xr atomic_cas_32 9F
662.It Xr atomic_cas_64 9F Ta Xr atomic_cas_8 9F
663.It Xr atomic_cas_ptr 9F Ta Xr atomic_cas_uchar 9F
664.It Xr atomic_cas_uint 9F Ta Xr atomic_cas_ulong 9F
665.It Xr atomic_cas_ushort 9F Ta Xr atomic_clear_long_excl 9F
666.It Xr atomic_dec_8_nv 9F Ta Xr atomic_dec_8 9F
667.It Xr atomic_dec_16_nv 9F Ta Xr atomic_dec_16 9F
668.It Xr atomic_dec_32_nv 9F Ta Xr atomic_dec_32 9F
669.It Xr atomic_dec_64_nv 9F Ta Xr atomic_dec_64 9F
670.It Xr atomic_dec_ptr_nv 9F Ta Xr atomic_dec_ptr 9F
671.It Xr atomic_dec_uchar_nv 9F Ta Xr atomic_dec_uchar 9F
672.It Xr atomic_dec_uint_nv 9F Ta Xr atomic_dec_uint 9F
673.It Xr atomic_dec_ulong_nv 9F Ta Xr atomic_dec_ulong 9F
674.It Xr atomic_dec_ushort_nv 9F Ta Xr atomic_dec_ushort 9F
675.It Xr atomic_inc_8_nv 9F Ta Xr atomic_inc_8 9F
676.It Xr atomic_inc_16_nv 9F Ta Xr atomic_inc_16 9F
677.It Xr atomic_inc_32_nv 9F Ta Xr atomic_inc_32 9F
678.It Xr atomic_inc_64_nv 9F Ta Xr atomic_inc_64 9F
679.It Xr atomic_inc_ptr_nv 9F Ta Xr atomic_inc_ptr 9F
680.It Xr atomic_inc_uchar_nv 9F Ta Xr atomic_inc_uchar 9F
681.It Xr atomic_inc_uint_nv 9F Ta Xr atomic_inc_uint 9F
682.It Xr atomic_inc_ulong_nv 9F Ta Xr atomic_inc_ulong 9F
683.It Xr atomic_inc_ushort_nv 9F Ta Xr atomic_inc_ushort 9F
684.It Xr atomic_or_8_nv 9F Ta Xr atomic_or_8 9F
685.It Xr atomic_or_16_nv 9F Ta Xr atomic_or_16 9F
686.It Xr atomic_or_32_nv 9F Ta Xr atomic_or_32 9F
687.It Xr atomic_or_64_nv 9F Ta Xr atomic_or_64 9F
688.It Xr atomic_or_uchar_nv 9F Ta Xr atomic_or_uchar 9F
689.It Xr atomic_or_uint_nv 9F Ta Xr atomic_or_uint 9F
690.It Xr atomic_or_ulong_nv 9F Ta Xr atomic_or_ulong 9F
691.It Xr atomic_or_ushort_nv 9F Ta Xr atomic_or_ushort 9F
692.It Xr atomic_set_long_excl 9F Ta Xr atomic_swap_8 9F
693.It Xr atomic_swap_16 9F Ta Xr atomic_swap_32 9F
694.It Xr atomic_swap_64 9F Ta Xr atomic_swap_ptr 9F
695.It Xr atomic_swap_uchar 9F Ta Xr atomic_swap_uint 9F
696.It Xr atomic_swap_ulong 9F Ta Xr atomic_swap_ushort 9F
697.El
698.Ss Memory Barriers
699The kernel provides general purpose memory barriers that can be used
700when required.
701In general, when using items described in the
702.Sx Synchronization Primitives
703section, these are not required.
704.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
705.It Xr membar_consumer 9F Ta Xr membar_enter 9F
706.It Xr membar_exit 9F Ta Xr membar_producer 9F
707.El
708.Ss Virtual Memory and Pages
709All platforms that the operating system supports have some form of
710virtual memory which is managed in units of pages.
711The page size varies between architectures and platforms.
712For example, the smallest x86 page size is 4 KiB while SPARC
713traditionally used 8 KiB pages.
714These functions can be used to convert between pages and bytes.
715.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
716.It Xr btop 9F Ta Xr btopr 9F
717.It Xr ddi_btop 9F Ta Xr ddi_btopr 9F
718.It Xr ddi_ptob 9F Ta Xr ptob 9F
719.El
720.Ss Module and Device Framework
721These functions are used as part of implementing kernel modules and
722register device drivers with the various kernel frameworks.
723There are also functions here that are suitable for use in the
724.Xr dev_ops 9S ,
725.Xr cb_ops 9S ,
726etc.
727structures and for interrogating module information.
728.Pp
729The
730.Xr mod_install 9F
731and
732.Xr mod_remove 9F
733functions are used during a driver's
734.Xr _init 9E
735and
736.Xr _fini 9E
737functions.
738.Pp
739There are two different ways that drivers often manage their instance
740state which is created during
741.Xr attach 9E .
742The first is the use of
743.Xr ddi_set_driver_private 9F
744and
745.Xr ddi_get_driver_private 9F .
746This stores a driver-specific value on the
747.Vt dev_info_t
748structure which allows it to be used during other operations.
749Some device driver frameworks may use this themselves, making this
750unavailable to the driver.
751.Pp
752The other path is to use the soft state suite of functions which
753dynamically grows to cover the number of instances of a device that
754exist.
755The soft state is generally initialized in the
756.Xr _init 9E
757entry point with
758.Xr ddi_soft_state_init 9F
759and then instances are allocated and freed during
760.Xr attach 9E
761and
762.Xr detach 9E
763with
764.Xr ddi_soft_state_zalloc 9F
765and
766.Xr ddi_soft_state_free 9F ,
767and then retrieved with
768.Xr ddi_get_soft_state 9F .
769.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
770.It Xr ddi_get_driver_private 9F Ta Xr ddi_get_soft_state 9F
771.It Xr ddi_modclose 9F Ta Xr ddi_modopen 9F
772.It Xr ddi_modsym 9F Ta Xr ddi_no_info 9F
773.It Xr ddi_report_dev 9F Ta Xr ddi_set_driver_private 9F
774.It Xr ddi_soft_state_fini 9F Ta Xr ddi_soft_state_free 9F
775.It Xr ddi_soft_state_init 9F Ta Xr ddi_soft_state_zalloc 9F
776.It Xr mod_info 9F Ta Xr mod_install 9F
777.It Xr mod_modname 9F Ta Xr mod_remove 9F
778.It Xr nochpoll 9F Ta Xr nodev 9F
779.It Xr nulldev 9F Ta
780.El
781.Ss Device Tree Information
782Devices are organized into a tree that is partially seeded by the
783platform based on information discovered at boot and augmented with
784additional information at runtime.
785Every instance of a device driver is given a
786.Vt "dev_info_t *"
787.Pq device information
788data structure which corresponds to information about an instance and
789has a place in the tree.
790When a driver requests operations like to allocate memory for DMA, that
791request is passed up the tree and modified.
792The same is true for other things like interrupts, event notifications,
793or properties.
794.Pp
795There are many different informational properties about a device driver.
796For example,
797.Xr ddi_driver_name 9F
798returns the name of the device driver,
799.Xr ddi_get_name 9F
800returns the name of the node in the tree,
801.Xr ddi_get_parent 9F
802returns a node's parent, and
803.Xr ddi_get_instance 9F
804returns the instance number of a specific driver.
805.Pp
806There are a series of properties that exist on the tree, the exact set
807of which depend on the class of the device and are often documented in a
808specific device class's manual.
809For example, the
810.Dq reg
811property is used for PCI and PCIe devices to describe the various base
812address registers, their types, and related, which are documented in
813.Xr pci 5 .
814.Pp
815When getting a property one can constrain it to the current instance or
816you can ask for a parent to try to look up the property.
817Which mode is appropriate depends on the specific class of driver, its
818parent, and the property.
819.Pp
820Using a
821.Vt "dev_info_t *"
822pointer has to be done carefully.
823When a device driver is in any of its
824.Xr dev_ops 9S ,
825.Xr cb_ops 9S ,
826or similar callback functions that it has registered with the kernel,
827then it can always safely use its own
828.Vt "dev_info_t"
829and those of any parents it discovers through
830.Xr ddi_get_parent 9F .
831However, it cannot assume the validity of any siblings or children
832unless there are other circumstances that guarantee that they will not
833disappear.
834In the broader kernel, one should not assume that it is safe to use a
835given
836.Vt "dev_info_t *"
837structure without the appropriate NDI
838.Pq nexus driver interface
839hold having been applied.
840.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
841.It Xr ddi_binding_name 9F Ta Xr ddi_dev_is_sid 9F
842.It Xr ddi_driver_major 9F Ta Xr ddi_driver_name 9F
843.It Xr ddi_get_devstate 9F Ta Xr ddi_get_instance 9F
844.It Xr ddi_get_name 9F Ta Xr ddi_get_parent 9F
845.It Xr ddi_getlongprop_buf 9F Ta Xr ddi_getlongprop 9F
846.It Xr ddi_getprop 9F Ta Xr ddi_getproplen 9F
847.It Xr ddi_node_name 9F Ta Xr ddi_prop_create 9F
848.It Xr ddi_prop_exists 9F Ta Xr ddi_prop_free 9F
849.It Xr ddi_prop_get_int 9F Ta Xr ddi_prop_get_int64 9F
850.It Xr ddi_prop_lookup_byte_array 9F Ta Xr ddi_prop_lookup_int_array 9F
851.It Xr ddi_prop_lookup_int64_array 9F Ta Xr ddi_prop_lookup_string_array 9F
852.It Xr ddi_prop_lookup_string 9F Ta Xr ddi_prop_lookup 9F
853.It Xr ddi_prop_modify 9F Ta Xr ddi_prop_op 9F
854.It Xr ddi_prop_remove_all 9F Ta Xr ddi_prop_remove 9F
855.It Xr ddi_prop_undefine 9F Ta Xr ddi_prop_update_byte_array 9F
856.It Xr ddi_prop_update_int_array 9F Ta Xr ddi_prop_update_int 9F
857.It Xr ddi_prop_update_int64_array 9F Ta Xr ddi_prop_update_int64 9F
858.It Xr ddi_prop_update_string_array 9F Ta Xr ddi_prop_update_string 9F
859.It Xr ddi_prop_update 9F Ta Xr ddi_root_node 9F
860.It Xr ddi_slaveonly 9F Ta
861.El
862.Ss Copying Data to and from Userland
863The kernel operates in a different context from userland.
864One does not simply access user memory.
865This is enforced either by the architecture's memory model, where user
866address space isn't even present in the kernel's virtual address space
867or by architectural mechanisms such as Supervisor Mode Access Protect
868.Pq SMAP
869on x86.
870.Pp
871To facilitate accessing memory, the kernel provides a few routines that
872can be used.
873In most contexts the main thing to use is
874.Xr ddi_copyin 9F
875and
876.Xr ddi_copyout 9F .
877These will safely dereference addresses and ensure that the address is
878appropriate depending on whether this is coming from the user or kernel.
879When operating with the kernel's
880.Vt uio_t
881structure which is for mostly used when processing read and write
882requests, instead
883.Xr uiomove 9F
884is the goto function.
885.Pp
886When reading data from userland into the kernel, there is another
887concern: the data model.
888The most common place this comes up is in an
889.Xr ioctl 9E
890handler or other places where the kernel is operating on data that isn't
891fixed size.
892Particularly in C, though this applies to other languages, structures
893and unions vary in the size and alignment requirements between 32-bit
894and 64-bit processes.
895The same even applies if one uses pointers or the
896.Vt long ,
897.Vt size_t ,
898or similar types in C.
899In supported 32-bit and 64-bit environments these types are 4 and 8
900bytes respectively.
901To account for this, when data is not fixed size between all data
902models, the driver must look at the data model of the process it is
903copying data from.
904.Pp
905The simplest way to solve this problem is to try to make the data
906structure the same across the different models.
907It's not sufficient to just use the same structure definition and fixed
908size types as the alignment and padding between the two can vary.
909For example, the alignment of a 64-bit integer like a
910.Vt uint64_t
911can change between a 32-bit and 64-bit data model.
912One way to check for the data structures being identical is to leverage
913the
914.Xr ctfdiff 1
915program, generally with the
916.Fl I
917option.
918.Pp
919However, there are times when a structure simply can't be the same, such
920as when we're encoding a pointer into the structure or a type like the
921.Vt size_t .
922When this happens, the most natural way to accomplish this is to use the
923.Xr ddi_model_convert_from 9F
924function which can determine the appropriate model from the ioctl's
925arguments.
926This provides a natural way to copy a structure in and out in the
927appropriate data model and convert it at those points to the kernel's
928native form.
929.Pp
930An alternate way to approach the data model is to use the
931.Xr STRUCT_DECL 9F
932functions, but as this requires wrapping every access to every member,
933often times the
934.Xr ddi_model_convert_from 9F
935approach and taking care of converting values and ensuring that limits
936aren't exceeded at the end is preferred.
937.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
938.It Xr bp_copyin 9F Ta Xr bp_copyout 9F
939.It Xr copyin 9F Ta Xr copyout 9F
940.It Xr ddi_copyin 9F Ta Xr ddi_copyout 9F
941.It Xr ddi_model_convert_from 9F Ta Xr SIZEOF_PTR 9F
942.It Xr SIZEOF_STRUCT 9F Ta Xr STRUCT_BUF 9F
943.It Xr STRUCT_DECL 9F Ta Xr STRUCT_FADDR 9F
944.It Xr STRUCT_FGET 9F Ta Xr STRUCT_FGETP 9F
945.It Xr STRUCT_FSET 9F Ta Xr STRUCT_FSETP 9F
946.It Xr STRUCT_HANDLE 9F Ta Xr STRUCT_INIT 9F
947.It Xr STRUCT_SET_HANDLE 9F Ta Xr STRUCT_SIZE 9F
948.It Xr uiomove 9F Ta Xr ureadc 9F
949.It Xr uwritec 9F Ta
950.El
951.Ss Device Register Setup and Access
952The kernel abstracts out accessing registers on a device on behalf of
953drivers.
954This allows a similar set of interfaces to be used whether the registers
955are found within a PCI BAR, utilizing I/O ports, memory mapped
956registers, or some other scheme.
957Devices with registers all have a
958.Dq regs
959property that is set up by their parent device, generally a kernel
960framework as is the case for PCIe devices, and the meaning is a contract
961between the two.
962Register sets are identified by a numeric ID, which varies on the device
963type.
964For example, the first BAR of a PCI device is defined as register set 1.
965On the other hand, the AMD GPIO controller might have three register sets
966because of how the hardware design splits them up.
967The meaning of the registers and their semantics is still
968device-specific.
969The kernel doesn't know how to interpret the actual registers of a PCIe
970device say, just that they exist.
971.Pp
972To begin with register setup, one often first looks at the number of
973register sets that exist and their size.
974Most PCI-based device drivers will skip calling
975.Xr ddi_dev_nregs 9F
976and will just move straight to calling
977.Xr ddi_dev_regsize 9F
978to determine the size of a register set that they are interested in.
979To actually map the registers, a device driver will call
980.Xr ddi_regs_map_setup 9F
981which requires both a register set and a series of attributes and
982returns an access handle that is used to actually read and write the
983registers.
984When setting up registers, one must have a corresponding
985.Vt ddi_device_acc_attr_t
986structure which is used to define what endianness the register set is
987in, whether any kind of reordering is allowed
988.Po
989if in doubt specify
990.Dv DDI_STRICTORDER_ACC
991.Pc ,
992and whether any particular error handling is being used.
993The structure and all of its different options are described in
994.Xr ddi_device_acc_attr 9S .
995.Pp
996Once a register handle is obtained, then it's easy to read and write the
997register space.
998Functions are organized based on the size of the access.
999For the most part, most situations call for the use of the
1000.Xr ddi_get8 9F ,
1001.Xr ddi_get16 9F ,
1002.Xr ddi_get32 9F ,
1003and
1004.Xr ddi_get64 9F
1005functions to read a register and the
1006.Xr ddi_put8 9F ,
1007.Xr ddi_put16 9F ,
1008.Xr ddi_put32 9F ,
1009and
1010.Xr ddi_put64 9F
1011functions to set a register value.
1012While there are the ddi_io_ and ddi_mem_ families of functions below,
1013these are not generally needed and are generally present for
1014compatibility.
1015The kernel will automatically perform the appropriate type of register
1016read for the device type in question.
1017.Pp
1018Once a register set is no longer being used, the
1019.Xr ddi_regs_map_free 9F
1020function should be used to release resources.
1021In most cases, this happens while executing the
1022.Xr detach 9E
1023entry point.
1024.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1025.It Xr ddi_dev_nregs 9F Ta Xr ddi_dev_regsize 9F
1026.It Xr ddi_device_copy 9F Ta Xr ddi_device_zero 9F
1027.It Xr ddi_regs_map_free 9F Ta Xr ddi_regs_map_setup 9F
1028.It Xr ddi_get8 9F Ta Xr ddi_get16 9F
1029.It Xr ddi_get32 9F Ta Xr ddi_get64 9F
1030.It Xr ddi_io_get8 9F Ta Xr ddi_io_get16 9F
1031.It Xr ddi_io_get32 9F Ta Xr ddi_io_put8 9F
1032.It Xr ddi_io_put16 9F Ta Xr ddi_io_put32 9F
1033.It Xr ddi_io_rep_get8 9F Ta Xr ddi_io_rep_get16 9F
1034.It Xr ddi_io_rep_get32 9F Ta Xr ddi_io_rep_put8 9F
1035.It Xr ddi_io_rep_put16 9F Ta Xr ddi_io_rep_put32 9F
1036.It Xr ddi_map_regs 9F Ta Xr ddi_mem_get8 9F
1037.It Xr ddi_mem_get16 9F Ta Xr ddi_mem_get32 9F
1038.It Xr ddi_mem_get64 9F Ta Xr ddi_mem_put8 9F
1039.It Xr ddi_mem_put16 9F Ta Xr ddi_mem_put32 9F
1040.It Xr ddi_mem_put64 9F Ta Xr ddi_mem_rep_get8 9F
1041.It Xr ddi_mem_rep_get16 9F Ta Xr ddi_mem_rep_get32 9F
1042.It Xr ddi_mem_rep_get64 9F Ta Xr ddi_mem_rep_put8 9F
1043.It Xr ddi_mem_rep_put16 9F Ta Xr ddi_mem_rep_put32 9F
1044.It Xr ddi_mem_rep_put64 9F Ta Xr ddi_peek8 9F
1045.It Xr ddi_peek16 9F Ta Xr ddi_peek32 9F
1046.It Xr ddi_peek64 9F Ta Xr ddi_poke8 9F
1047.It Xr ddi_poke16 9F Ta Xr ddi_poke32 9F
1048.It Xr ddi_poke64 9F Ta Xr ddi_put8 9F
1049.It Xr ddi_put16 9F Ta Xr ddi_put32 9F
1050.It Xr ddi_put64 9F Ta Xr ddi_rep_get8 9F
1051.It Xr ddi_rep_get16 9F Ta Xr ddi_rep_get32 9F
1052.It Xr ddi_rep_get64 9F Ta Xr ddi_rep_put8 9F
1053.It Xr ddi_rep_put16 9F Ta Xr ddi_rep_put32 9F
1054.It Xr ddi_rep_put64 9F Ta
1055.El
1056.Ss DMA Related Functions
1057Most high-performance devices provide first-class support for DMA
1058.Pq direct memory access .
1059DMA allows a transfer between a device and memory to occur
1060asynchronously and generally without a thread's specific involvement.
1061Today, most DMA is provided directly by devices and the corresponding
1062device scheme.
1063Take PCI and PCI Express for example.
1064The idea of DMA is built into the PCIe standard and therefore basic
1065support for it exists and therefore there isn't a lot of special
1066programming required.
1067However, this hasn't always been true and still exists in some cases
1068where there is a 3rd party DMA engine.
1069If we consider the PCIe example, the PCIe device directly performs reads
1070and writes to main memory on its own.
1071However, in the 3rd party case, there is a distinct controller that is
1072neither the device nor memory that facilitates this, which is called a
1073DMA engine.
1074For most part, DMA engines are not something that needs to be thought
1075about for most platforms that illumos is present on; however, they still
1076exist in some embedded and related contexts.
1077.Pp
1078The first thing that a driver needs to do to set up DMA is to understand
1079the constraints of the device and bus.
1080These constraints are described in a series of attributes in the
1081.Vt ddi_dma_attr_t
1082structure which is defined in
1083.Xr ddi_dma_attr 9S .
1084The reason that attributes exist is because different devices, and
1085sometimes different memory uses with a device, have different
1086requirements for memory.
1087A simple example of this is that not all devices can accept memory
1088addresses that are 64-bits wide and may have to be constrained to the
1089lower 32-bits of memory.
1090Another common constraint is how this memory is chunked up.
1091Some devices may require that all of the DMA memory be contiguous, while
1092others can allow that to be broken up into say up to 4 or 8 different
1093regions.
1094.Pp
1095When memory is allocated for DMA it isn't immediately mapped into the
1096kernel's address space.
1097The addresses that describe a DMA address are defined in a DMA cookie,
1098several of which may make up a request.
1099However, those addresses are always physical addresses or addresses that
1100are virtualized by an IOMMU.
1101There are some cases were the kernel or a driver needs to be able to
1102access that memory, such as memory that represents a networking packet.
1103The IP stack will expect to be able to actually read the data it's
1104given.
1105.Pp
1106To begin with allocating DMA memory, a driver first fills out its
1107attribute structure.
1108Once that's ready, the DMA allocation process can begin.
1109This starts off by a driver calling
1110.Xr ddi_dma_alloc_handle 9F .
1111This handle is used through the lifetime of a given DMA memory buffer,
1112but it can be used across multiple operations that a device or the
1113kernel may perform.
1114The next step is to actually request that the kernel allocate some
1115amount of memory in the kernel for this DMA request.
1116This phase actually allocates addresses in virtual address space for the
1117activity and also requires a register attribute object that is discussed
1118in
1119.Sx Device Register Setup and Access .
1120Armed with this a driver can now call
1121.Xr ddi_dma_mem_alloc 9F
1122to specify how much memory they are looking for.
1123If this is successful, a virtual address, the actual length of the
1124region, and an access handle will be returned.
1125.Pp
1126At this point, the virtual address region is present.
1127Most drivers will access this virtual address range directly and will
1128ignore the register access handle.
1129The side effect of this is that they will handle all endianness issues
1130with the memory region themselves.
1131If the driver would prefer to go through the handle, then it can use the
1132register access functions discussed earlier.
1133.Pp
1134Before the memory can be programmed into the device, it must be bound to
1135a series of physical addresses or addresses virtualized by an IOMMU.
1136While the kernel presents the illusion of a single consistent virtual
1137address range for applications, the physical reality can be quite
1138different.
1139When the driver is ready it calls
1140.Xr ddi_dma_addr_bind_handle 9F
1141to create the mapping to well known physical addresses.
1142.Pp
1143These addresses are stored in a series of cookies.
1144A driver can determine the number of cookies for a given request by
1145utilizing its DMA handle and calling
1146.Xr ddi_dma_ncookies 9F
1147and then pairing that with
1148.Xr ddi_dma_cookie_get 9F .
1149These DMA cookies will not change and can be used time and time again
1150until
1151.Xr ddi_dma_unbind_handle 9F
1152is called.
1153With this information in hand, a physical device can be programmed with
1154these addresses and let loose to perform I/O.
1155.Pp
1156When performing I/O to and from a device, synchronization is a vitally
1157important thing which ensures that the actual state in memory is
1158coherent with the rest of the CPU's internal structures such as caches.
1159In general, a given DMA request is only going in one direction: for a
1160device or for the local CPU.
1161In either case, the
1162.Xr ddi_dma_sync 9F
1163function must be called after the kernel is done writing to a region of
1164DMA memory and before it triggers the device or the kernel must call it
1165after the device has told it that some activity has completed that it is
1166going to check.
1167.Pp
1168Some DMA operations utilize what are called DMA windows.
1169The most common consumer is something like a disk device where DMA
1170operations to a given series of sectors can be split up into different
1171chunks where as long as all the transfers are performed, the
1172intermediate states are acceptable.
1173Put another way, because of how SCSI and SAS commands are designed,
1174block devices can basically take a given I/O request and break it into
1175multiple independent I/Os that will equate to the same final item.
1176.Pp
1177When a device supports this mode of operation and it is opted into, then
1178a DMA allocation may result in the use of DMA windows.
1179This allows for cases where the kernel can't perform a DMA allocation
1180for the entire request, but instead can allocate a partial region and
1181then walk through each part one at a time.
1182This is uncommon outside of block devices and usually also is related to
1183calling
1184.Xr ddi_dma_buf_bind_handle 9F .
1185.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1186.It Xr ddi_dma_addr_bind_handle 9F Ta Xr ddi_dma_alloc_handle 9F
1187.It Xr ddi_dma_buf_bind_handle 9F Ta Xr ddi_dma_burstsizes 9F
1188.It Xr ddi_dma_cookie_get 9F Ta Xr ddi_dma_cookie_iter 9F
1189.It Xr ddi_dma_cookie_one 9F Ta Xr ddi_dma_free_handle 9F
1190.It Xr ddi_dma_getwin 9F Ta Xr ddi_dma_mem_alloc 9F
1191.It Xr ddi_dma_mem_free 9F Ta Xr ddi_dma_ncookies 9F
1192.It Xr ddi_dma_nextcookie 9F Ta Xr ddi_dma_numwin 9F
1193.It Xr ddi_dma_set_sbus64 9F Ta Xr ddi_dma_sync 9F
1194.It Xr ddi_dma_unbind_handle 9F Ta Xr ddi_dmae_1stparty 9F
1195.It Xr ddi_dmae_alloc 9F Ta Xr ddi_dmae_disable 9F
1196.It Xr ddi_dmae_enable 9F Ta Xr ddi_dmae_getattr 9F
1197.It Xr ddi_dmae_getcnt 9F Ta Xr ddi_dmae_prog 9F
1198.It Xr ddi_dmae_release 9F Ta Xr ddi_dmae_stop 9F
1199.It Xr ddi_dmae 9F Ta
1200.El
1201.Ss Interrupt Handler Related Functions
1202Interrupts are a central part of the role of device drivers and one of
1203the things that's important to get right.
1204Interrupts come in different types: fixed, MSI, and MSI-X.
1205The kinds that are available depend on the device and the rest of the
1206system.
1207For example, MSI and MSI-X interrupts are generally specific to PCI and
1208PCI Express devices.
1209To begin the interrupt allocation process, the first thing a driver
1210needs to do is to discover what type of interrupts it supports with
1211.Xr ddi_intr_get_supported_types 9F .
1212Then, the driver should work through the supported types, preferring
1213MSI-X, then MSI, and finally fixed interrupts, and try to allocate
1214interrupts.
1215.Pp
1216Drivers first need to know how many interrupts that they require.
1217For example, a networking driver may want to have an interrupt made
1218available for each ring that it has.
1219To discover the number of interrupts available, the driver should call
1220.Xr ddi_intr_get_navail 9F .
1221If there are sufficient interrupts, it can proceed to actually
1222allocate the interrupts with
1223.Xr ddi_intr_alloc 9F .
1224When allocating interrupts, callers need to check to see how many
1225interrupts the system actually gave them.
1226Just because an interrupt is allocated does not mean that it will fire
1227or be ready to use, there are a series of additional steps that the
1228driver must take.
1229.Pp
1230To go through and enable the interrupt, the driver should go through and
1231get the interrupt capabilities with
1232.Xr ddi_intr_get_cap 9F
1233and the priority of the interrupt with
1234.Xr ddi_intr_get_pri 9F .
1235The priority must be used while creating mutexes and related
1236synchronization primitives that will be used during the interrupt
1237handler.
1238At this point, the driver can go ahead and register the functions that
1239will be called with each allocated interrupt with the
1240.Xr ddi_intr_add_handler 9F
1241function.
1242The arguments can vary for each allocated interrupt.
1243It is common to have an interrupt-specific data structure passed in one
1244of the arguments or an interrupt number, while the other argument is
1245generally the driver's instance-specific data structure.
1246.Pp
1247At this point, the last step for the interrupt to be made active from
1248the kernel's perspective is to enable it.
1249This will use either the
1250.Xr ddi_intr_block_enable 9F
1251or
1252.Xr ddi_intr_enable 9F
1253functions depending on the interrupt's capabilities.
1254The reason that these are different is because some interrupt types
1255.Pq MSI
1256require that all interrupts in a group be enabled and disabled at the
1257same time.
1258This is indicated with the
1259.Dv DDI_INTR_FLAG_BLOCK
1260flag found in the interrupt's capabilities.
1261Once that is called, interrupts that are generated by a device will be
1262delivered to the registered function.
1263.Pp
1264It's important to note that there is often device-specific interrupt
1265setup that is required.
1266While the kernel takes care of updating any pieces of the processor's
1267interrupt controller, I/O crossbar, or the PCI MSI and MSI-X
1268capabilities, many devices have device-specific registers that are used
1269to manage, set up, and acknowledge interrupts.
1270These registers or other controls are often capable of separately
1271masking interrupts and are generally what should be used if there are
1272times that you need to separately enable or disable interrupts such as
1273to poll an I/O ring.
1274.Pp
1275When unwinding interrupts, one needs to work in the reverse order here.
1276Until
1277.Xr ddi_intr_block_disable 9F
1278or
1279.Xr ddi_intr_disable 9F
1280is called, one should assume that their interrupt handler will be
1281called.
1282Due to cases where an interrupt is shared between multiple devices, this
1283can happen even if the device is quiesced!
1284Only after that is done is it safe to then free the interrupts with a
1285call to
1286.Xr ddi_intr_free 9F .
1287.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1288.It Xr ddi_add_intr 9F Ta Xr ddi_add_softintr 9F
1289.It Xr ddi_get_iblock_cookie 9F Ta Xr ddi_get_soft_iblock_cookie 9F
1290.It Xr ddi_intr_add_handler 9F Ta Xr ddi_intr_add_softint 9F
1291.It Xr ddi_intr_alloc 9F Ta Xr ddi_intr_block_disable 9F
1292.It Xr ddi_intr_block_enable 9F Ta Xr ddi_intr_clr_mask 9F
1293.It Xr ddi_intr_disable 9F Ta Xr ddi_intr_dup_handler 9F
1294.It Xr ddi_intr_enable 9F Ta Xr ddi_intr_free 9F
1295.It Xr ddi_intr_get_cap 9F Ta Xr ddi_intr_get_hilevel_pri 9F
1296.It Xr ddi_intr_get_navail 9F Ta Xr ddi_intr_get_nintrs 9F
1297.It Xr ddi_intr_get_pending 9F Ta Xr ddi_intr_get_pri 9F
1298.It Xr ddi_intr_get_softint_pri 9F Ta Xr ddi_intr_get_supported_types 9F
1299.It Xr ddi_intr_hilevel 9F Ta Xr ddi_intr_remove_handler 9F
1300.It Xr ddi_intr_remove_softint 9F Ta Xr ddi_intr_set_cap 9F
1301.It Xr ddi_intr_set_mask 9F Ta Xr ddi_intr_set_nreq 9F
1302.It Xr ddi_intr_set_pri 9F Ta Xr ddi_intr_set_softint_pri 9F
1303.It Xr ddi_intr_trigger_softint 9F Ta Xr ddi_remove_intr 9F
1304.It Xr ddi_remove_softintr 9F Ta Xr ddi_trigger_softintr 9F
1305.El
1306.Ss Minor Nodes
1307For a device driver to be accessed by a program in user space
1308.Pq or with the kernel layered device interface
1309then it must create a minor node.
1310Minor nodes are created under
1311.Pa /devices
1312.Pq Xr devfs 4FS
1313and are tied to the instance of a device driver via its
1314.Vt dev_info_t .
1315The
1316.Xr devfsadm 8
1317daemon and the
1318.Pa /dev
1319file system
1320.Po
1321sdev,
1322.Xr dev 4FS
1323.Pc
1324are responsible for creating a coherent set of names that user programs
1325access.
1326Drivers create these minor nodes using the
1327.Xr ddi_create_minor_node 9F
1328function listed below.
1329.Pp
1330In UNIX tradition, character, block, and STREAMS device special files
1331are identified by a major and minor number.
1332All instances of a given driver share the same major number, which means
1333that a device driver must coordinate the minor number space across
1334.Em all
1335instances.
1336While a minor node is created with a fixed minor number, it is possible
1337to change the minor number while processing an
1338.Xr open 9E
1339call, allowing subsequent character device operations to uniquely
1340identify a particular caller.
1341This is usually referred to as a driver that
1342.Dq clones .
1343.Pp
1344When drivers aren't performing cloning, then usually the minor number
1345used when creating the minor node is some fixed offset or multiple of
1346the driver's instance number.
1347When cloning and a driver needs to allocate and manage a minor number
1348space, usually an ID space is leveraged whose IDs are usually in the
1349range from 0 through
1350.Dv MAXMIN32 .
1351There are several different strategies for tracking data structures as
1352they relate to minor numbers.
1353Sometimes, the soft state functionality is used.
1354Others might keep an AVL tree around or tie the data to some other data
1355structure.
1356The method chosen often varies on the specifics of the implementation
1357and its broader context.
1358.Pp
1359The
1360.Vt dev_t
1361structure represents the combined major and minor number.
1362It can be taken apart with the
1363.Xr getmajor 9F
1364and
1365.Xr getminor 9F
1366functions and then reconstructed with the
1367.Xr makedevice 9F
1368function.
1369.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1370.It Xr ddi_create_minor_node 9F Ta Xr ddi_remove_minor_node 9F
1371.It Xr getmajor 9F Ta Xr getminor 9F
1372.It Xr devfs_clean 9F Ta Xr makedevice 9F
1373.El
1374.Ss Accessing Time, Delays, and Periodic Events
1375The kernel provides a number of ways to understand time in the system.
1376In particular it provides a few different clocks and time measurements:
1377.Bl -tag -width Ds
1378.It High-resolution monotonic time
1379The kernel provides access to a high-resolution monotonic clock that is
1380tracked in nanoseconds.
1381This clock is perfect for measuring durations and is accessed via
1382.Xr gethrtime 9F .
1383Unlike the real-time clock, this clock is not subject to adjustments by
1384a time synchronization daemon and is the preferred clock that drivers
1385should be using for tracking events.
1386The high-resolution clock is consistent across CPUs, meaning that you
1387may call
1388.Xr gethrtime 9F
1389on one CPU and the value will be consistent with what is returned, even
1390if a thread is migrated to another CPU.
1391.Pp
1392The high-resolution clock is implemented using an architecture and
1393platform-specific means.
1394For example, on x86 it is generally backed by the TSC
1395.Pq time stamp counter .
1396.It Real-time
1397The real-time clock tracks time as humans perceive it.
1398This clock is accessed using
1399.Xr ddi_get_time 9F .
1400If the system is running a time synchronization daemon that leverages
1401the network time protocol, then this time may be in sync with other
1402systems
1403.Pq subject to some amount of variance ;
1404however, it is critical that this is not assumed.
1405.Pp
1406In general, this time should not be used by drivers for any purpose.
1407It can jump around, drift, and most aspects in the kernel are not based
1408on the real-time clock.
1409For any device timing activities, the high-resolution clock should be
1410used.
1411.It Tick-based monotonic time
1412The kernel has a running periodic function that fires based on the rate
1413dictated by the
1414.Va hz
1415variable, generally operating at 100 or 1000 kHz.
1416The current number of ticks since boot is accessible through the
1417.Xr ddi_get_lbolt 9F
1418function.
1419When functions operate in units of ticks, this is what they are
1420tracking.
1421This value can be converted to and from microseconds using the
1422.Xr drv_usectohz 9F
1423and
1424.Xr drv_hztousec 9F
1425functions.
1426.Pp
1427In general, drivers should prefer the high-resolution monotonic clock
1428for tracking events internally.
1429.El
1430.Pp
1431With these different timing mechanisms, the kernel provides a few
1432different ways to delay execution or to get a callback after some
1433amount of time passes.
1434.Pp
1435The
1436.Xr delay 9F
1437and
1438.Xr drv_usecwait 9F
1439functions are used to block the execution of the current thread.
1440.Xr delay 9F
1441can be used in conditions where sleeping and blocking is allowed where
1442as
1443.Xr drv_usecwait 9F
1444is a busy-wait, which is appropriate for some device drivers,
1445particularly when in high-level interrupt context.
1446.Pp
1447The kernel also allows a function to be called after some time has
1448elapsed.
1449This callback occurs on a different thread and will be executed in
1450.Sy kernel
1451context.
1452A timeout can be scheduled in the future with the
1453.Xr timeout 9F
1454function and cancelled with the
1455.Xr untimeout 9F
1456function.
1457There is also a STREAMs-specific version that can be used if the
1458circumstances are required with the
1459.Xr qtimeout 9F
1460function.
1461.Pp
1462These are all considered one-shot events.
1463That is, they will only happen once after being scheduled.
1464If instead, a driver requires periodic behavior, such as needing
1465something to occur every second, then it should use the
1466.Xr ddi_periodic_add 9F
1467function to establish that.
1468.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1469.It Xr delay 9F Ta Xr ddi_get_lbolt 9F
1470.It Xr ddi_get_lbolt64 9F Ta Xr ddi_get_time 9F
1471.It Xr ddi_periodic_add 9F Ta Xr ddi_periodic_delete 9F
1472.It Xr drv_hztousec 9F Ta Xr drv_usectohz 9F
1473.It Xr drv_usecwait 9F Ta Xr gethrtime 9F
1474.It Xr qtimeout 9F Ta Xr quntimeout 9F
1475.It Xr timeout 9F Ta Xr untimeout 9F
1476.El
1477.Ss Task Queues
1478A task queue provides an asynchronous processing mechanism that can be
1479used by drivers and the broader system.
1480A task queue can be created with
1481.Xr ddi_taskq_create 9F
1482and sized with a given number of threads and a relative priority of those
1483threads.
1484Once created, tasks can be dispatched to the queue with
1485.Xr ddi_taskq_dispatch 9F .
1486The different functions and arguments dispatched do not need to be the
1487same and can vary from invocation to invocation.
1488However, it is the caller's responsibility to ensure that any reference
1489memory is valid until the task queue is done processing.
1490It is possible to create a barrier for a task queue by using the
1491.Xr ddi_taskq_wait 9F
1492function.
1493.Pp
1494While task queues are a flexible mechanism for handling and processing
1495events that occur in a well defined context, they do not have an
1496inherent backpressure mechanism built in.
1497This means it is possible to add events to a task queue faster than they
1498can be processed.
1499For high-volume events, this must be considered before just dispatching
1500an event.
1501Do not rely on a non-sleeping allocation in the task queue dispatch
1502context.
1503.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1504.It Xr ddi_taskq_create 9F Ta Xr ddi_taskq_destroy 9F
1505.It Xr ddi_taskq_dispatch 9F Ta Xr ddi_taskq_resume 9F
1506.It Xr ddi_taskq_suspend 9F Ta Xr ddi_taskq_suspended 9F
1507ddi_taskq_wait
1508.El
1509.Ss Credential Management and Privileges
1510Not everything in the system has the same power to impact it.
1511To determine the permissions and context of a caller, the
1512.Vt cred_t
1513data structure encapsulates a number of different things including the
1514traditional user and group IDs, but also the zone that one is operating
1515in the context of and the associated privileges that the caller has.
1516While this concept is more often thought of due to userland processes being
1517associated with specific users, these same principles apply to different
1518threads in the kernel.
1519Not all kernel threads are allowed to indiscriminately do what they
1520want, they can be constrained by the same privilege model that processes
1521are, which is discussed in
1522.Xr privileges 7 .
1523.Pp
1524Most operations that device drivers implement are given a credential.
1525However, from within the kernel, a credential can be obtained that
1526refers to a specific zone, the current process, or a generic kernel
1527credential.
1528.Pp
1529It is up to drivers and the kernel writ-large to check whether a given
1530credential is authorized to perform a given operation.
1531This is encapsulated by the various privilege checks that exist.
1532The most common check used is
1533.Xr drv_priv 9F
1534which checks for
1535.Dv PRIV_SYS_DEVICES .
1536.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1537.It Xr CRED 9F Ta Xr crdup 9F
1538.It Xr crfree 9F Ta Xr crget 9F
1539.It Xr crgetgid 9F Ta Xr crgetgroups 9F
1540.It Xr crgetngroups 9F Ta Xr crgetrgid 9F
1541.It Xr crgetruid 9F Ta Xr crgetsgid 9F
1542.It Xr crgetsuid 9F Ta Xr crgetuid 9F
1543.It Xr crgetzoneid 9F Ta Xr crhold 9F
1544.It Xr ddi_get_cred 9F Ta Xr drv_priv 9F
1545.It Xr kcred 9F Ta Xr priv_getbyname 9F
1546.It Xr priv_policy_choice 9F Ta Xr priv_policy_only 9F
1547.It Xr priv_policy 9F Ta Xr zone_kcred 9F
1548.El
1549.Ss Device ID Management
1550Device IDs are a means of establishing a unique ID for a device in the
1551kernel.
1552These unique IDs are generally tied to something from the device's
1553hardware such as a serial number or related, but can also be fabricated
1554and stored on the device.
1555These device IDs are used by other subsystems like ZFS to record
1556information about a device as the actual
1557.Pa /devices
1558path that a device resides at may change because it is moved around in
1559the system.
1560.Pp
1561For device drivers, particularly those that represent block devices,
1562they should first call
1563.Xr ddi_devid_init 9F
1564to initialize the device ID data structure.
1565After that is done, it is then safe to call
1566.Xr ddi_devid_register 9F
1567to notify the kernel about the ID.
1568.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1569.It Xr ddi_devid_compare 9F Ta Xr ddi_devid_free 9F
1570.It Xr ddi_devid_get 9F Ta Xr ddi_devid_init 9F
1571.It Xr ddi_devid_register 9F Ta Xr ddi_devid_sizeof 9F
1572.It Xr ddi_devid_str_decode 9F Ta Xr ddi_devid_str_encode 9F
1573.It Xr ddi_devid_str_free 9F Ta Xr ddi_devid_unregister 9F
1574.It Xr ddi_devid_valid 9F Ta
1575.El
1576.Ss Message Block Functions
1577The
1578.Vt "mblk_t"
1579data structure is used to chain together messages which are used through
1580the kernel for different subsystems including all of networking,
1581terminals, STREAMS, USB, and more.
1582.Pp
1583Message blocks are chained together by a series of two different
1584pointers:
1585.Fa b_cont
1586and
1587.Fa b_next .
1588When a message is split across multiple data buffers, they are linked by
1589the
1590.Fa b_cont
1591pointer.
1592However, multiple distinct messages can be chained together and linked
1593by the
1594.Fa b_next
1595pointer.
1596Let's look at this in the context of a series of networking packets.
1597If we had a chain of say 10 UDP packets that we were given, each UDP
1598packet is considered an independent message and would be linked from one
1599to the next based on the order they should be transmitted with the
1600.Fa b_next
1601pointer.
1602However, an individual message may be entirely in one message block, in
1603which case its
1604.Fa b_cont
1605pointer would be
1606.Dv NULL ,
1607but if say the packet were split into a 100 byte data buffer that
1608contained the headers and then a 1000 byte data buffer that contained
1609the actual packet data, those two would be linked together by
1610.Fa b_cont .
1611A continued message would never have its next pointer used to link it to
1612a wholly different message.
1613Visually you might see this as:
1614.Bd -literal
1615  +---------------+
1616  | UDP Message 0 |
1617  | Bytes 0-1100  |
1618  | b_cont     ---+--> NULL
1619  | b_next  +     |
1620  +---------|-----+
1621            |
1622            v
1623  +---------------+    +----------------+
1624  | UDP Message 1 |    | UDP Message 1+ |
1625  | Bytes 0-100   |    | Bytes 100-1100 |
1626  | b_cont     ---+--> | b_cont     ----+->NULL
1627  | b_next  +     |    | b_next     ----+->NULL
1628  +---------|-----+    +----------------+
1629            |
1630           ...
1631            |
1632            v
1633  +---------------+
1634  | UDP Message 9 |
1635  | Bytes 0-1100  |
1636  | b_cont     ---+--> NULL
1637  | b_next     ---+--> NULL
1638  +---------------+
1639.Ed
1640.Pp
1641Message blocks all have an associated data block which contains the
1642actual data that is present.
1643Multiple message blocks can share the same data block as well.
1644The data block has a notion of a type, which is generally
1645.Dv M_DATA
1646which signifies that they operate on data.
1647.Pp
1648To allocate message blocks, one generally uses the
1649.Xr allocb 9F
1650function to create one; however, you can also create message blocks
1651using your own source of data through functions like
1652.Xr desballoc 9F .
1653This is generally used when one wants to use memory that was originally
1654used for DMA to pass data back into the kernel, such as in a networking
1655device driver.
1656When this happens, a callback function will be called once the last user
1657of the data block is done with it.
1658.Pp
1659The functions listed below often end in either
1660.Dq msg
1661or
1662.Dq b
1663to indicate that they will operate on an entire message and follow the
1664.Fa b_cont
1665pointer or they will not respectively.
1666.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1667.It Xr adjmsg 9F Ta Xr allocb 9F
1668.It Xr copyb 9F Ta Xr copymsg 9F
1669.It Xr datamsg 9F Ta Xr desballoc 9F
1670.It Xr desballoca 9F Ta Xr dupb 9F
1671.It Xr dupmsg 9F Ta Xr esballoc 9F
1672.It Xr esballoca 9F Ta Xr freeb 9F
1673.It Xr freemsg 9F Ta Xr linkb 9F
1674.It Xr mcopymsg 9F Ta Xr msgdsize 9F
1675.It Xr msgpullup 9F Ta Xr msgsize 9F
1676.It Xr pullupmsg 9F Ta Xr rmvb 9F
1677.It Xr testb 9F Ta Xr unlinkb 9F
1678.El
1679.Ss Upgradable Firmware Modules
1680The UFM
1681.Pq Upgradable Firmware Module
1682subsystem is used to grant the system observability into firmware that
1683exists persistently on a device.
1684These functions are intended for use by drivers that are participating in
1685the kernel's UFM framework, which is discussed in
1686.Xr ddi_ufm 9E .
1687.Pp
1688The
1689.Xr ddi_ufm_init 9F
1690and
1691.Xr ddi_ufm_fini 9F
1692functions are used to indicate support of the subsystem to the kernel.
1693The driver is required to use the
1694.Xr ddi_ufm_update 9F
1695function to indicate both that it is ready to receive UFM requests and
1696to indicate that any data that the kernel may have previously received
1697has changed.
1698Once that's completed, then the other functions listed here are
1699generally used as part of implementing specific callback functions that
1700are registered.
1701.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1702.It Xr ddi_ufm_fini 9F Ta Xr ddi_ufm_image_set_desc 9F
1703.It Xr ddi_ufm_image_set_misc 9F Ta Xr ddi_ufm_image_set_nslots 9F
1704.It Xr ddi_ufm_init 9F Ta Xr ddi_ufm_slot_set_attrs 9F
1705.It Xr ddi_ufm_slot_set_imgsize 9F Ta Xr ddi_ufm_slot_set_misc 9F
1706.It Xr ddi_ufm_slot_set_version 9F Ta Xr ddi_ufm_update 9F
1707.El
1708.Ss Firmware Loading
1709Some hardware devices have firmware that is not stored as part of the
1710device itself and must instead be sent to the device each time it is
1711powered on.
1712These routines help drivers that need to perform this read such data
1713from the file system from well-known locations in the operating system.
1714To begin with, a driver should call
1715.Xr firmware_open 9F
1716to open a handle to the firmware file.
1717At that point, one can determine the size of the file with the
1718.Xr firmware_get_size 9F
1719function and allocate the appropriate sized memory buffer to read it in.
1720Callers should always check what the size of the returned file is and
1721should not just blindly pass that size off to the kernel memory
1722allocator.
1723For example, if a file was over 100 MiB in size, then one should not
1724assume that they're going to just blindly allocate 100 MiB of kernel
1725memory and should instead perform incremental reads and sends to a
1726device that are smaller in size.
1727.Pp
1728A driver can then go through and perform arbitrary reads of the firmware
1729file through the
1730.Xr firmware_read 9F
1731interface until they have read everything that they need.
1732Once complete, the corresponding handle needs to be released through the
1733.Xr firmware_close 9F
1734function.
1735.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1736.It Xr firmware_close 9F Ta Xr firmware_get_size 9F
1737.It Xr firmware_open 9F Ta Xr firmware_read 9F
1738.El
1739.Ss Fault Management Handling
1740These functions allow device drivers to harden themselves against errors
1741that might occur while interfacing with devices and tie into the broader
1742fault management architecture.
1743.Pp
1744To begin, a driver must declare which capabilities it implements during
1745its
1746.Xr attach 9E
1747function by calling
1748.Xr ddi_fm_init 9F .
1749The set of capabilities it receives back may be less than what was
1750requested because the capabilities are dependent on the overall chain of
1751drivers present.
1752.Pp
1753If
1754.Dv DDI_FM_EREPORT_CAPABLE
1755was negotiated, then the driver is expected to generate error events
1756when certain conditions occur using the
1757.Xr ddi_fm_ereport_post 9F
1758function or the more specific
1759.Xr pci_ereport_post 9F
1760function.
1761If a caller has negotiated
1762.Dv DDI_FM_ACCCHK_CAPABLE ,
1763then it is allowed to set up its register attributes to indicate that it
1764will check for errors on the register handle after using functions like
1765.Xr ddi_get8 9F
1766and
1767.Xr ddi_put8 9F
1768by calling
1769.Xr ddi_fm_acc_err_get 9F
1770and reacting accordingly.
1771Similarly, if a driver has negotiated
1772.Dv DDI_FM_DMACHK_CAPABLE ,
1773then it will use
1774.Xr ddi_check_dma_handle 9F
1775to check the results of DMA activity and handle the results
1776appropriately.
1777Similar to register accesses, the DMA attributes must be updated to set
1778that error handling is anticipated on this handle.
1779The
1780.Xr ddi_fm_init 9F
1781manual page has an overview of the other types of flags that can be
1782negotiated and how they are used.
1783.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1784.It Xr ddi_check_acc_handle 9F Ta Xr ddi_check_dma_handle 9F
1785.It Xr ddi_dev_report_fault 9F Ta Xr ddi_fm_acc_err_clear 9F
1786.It Xr ddi_fm_acc_err_get 9F Ta Xr ddi_fm_capable 9F
1787.It Xr ddi_fm_dma_err_clear 9F Ta Xr ddi_fm_dma_err_get 9F
1788.It Xr ddi_fm_ereport_post 9F Ta Xr ddi_fm_fini 9F
1789.It Xr ddi_fm_handler_register 9F Ta Xr ddi_fm_handler_unregister 9F
1790.It Xr ddi_fm_init 9F Ta Xr ddi_fm_service_impact 9F
1791.It Xr pci_ereport_post 9F Ta Xr pci_ereport_setup 9F
1792.It Xr pci_ereport_teardown 9F Ta
1793.El
1794.Ss SCSI and SAS Device Driver Functions
1795These functions are for use by SCSI and SAS device drivers that leverage
1796the kernel's frameworks.
1797Other device drivers should not use these.
1798For more background on these, some of the general concepts are discussed
1799in
1800.Xr iport 9 ,
1801.Xr phymap 9 ,
1802and
1803.Xr tgtmap 9 .
1804.Pp
1805Device drivers register initially with the kernel by using the
1806.Xr scsi_hba_init 9F
1807function and then, in their attach routine, register specific instances,
1808using functions like
1809.Xr scsi_hba_iport_register 9F
1810or instead
1811.Xr scsi_hba_tran_alloc 9F
1812and
1813.Xr scsi_hba_attach_setup 9F .
1814New drivers are encouraged to use the target map and iports framework to
1815simplify the device driver writing process.
1816.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1817.It Xr makecom_g0_s 9F Ta Xr makecom_g0 9F
1818.It Xr makecom_g1 9F Ta Xr makecom_g5 9F
1819.It Xr makecom 9F Ta Xr sas_phymap_create 9F
1820.It Xr sas_phymap_destroy 9F Ta Xr sas_phymap_lookup_ua 9F
1821.It Xr sas_phymap_lookup_uapriv 9F Ta Xr sas_phymap_phy_add 9F
1822.It Xr sas_phymap_phy_rem 9F Ta Xr sas_phymap_phy2ua 9F
1823.It Xr sas_phymap_phys_free 9F Ta Xr sas_phymap_phys_next 9F
1824.It Xr sas_phymap_ua_free 9F Ta Xr sas_phymap_ua2phys 9F
1825.It Xr sas_phymap_uahasphys 9F Ta Xr scsi_abort 9F
1826.It Xr scsi_address_device 9F Ta Xr scsi_alloc_consistent_buf 9F
1827.It Xr scsi_cname 9F Ta Xr scsi_destroy_pkt 9F
1828.It Xr scsi_device_hba_private_get 9F Ta Xr scsi_device_hba_private_set 9F
1829.It Xr scsi_device_unit_address 9F Ta Xr scsi_dmafree 9F
1830.It Xr scsi_dmaget 9F Ta Xr scsi_dname 9F
1831.It Xr scsi_errmsg 9F Ta Xr scsi_ext_sense_fields 9F
1832.It Xr scsi_find_sense_descr 9F Ta Xr scsi_free_consistent_buf 9F
1833.It Xr scsi_free_wwnstr 9F Ta Xr scsi_get_device_type_scsi_options 9F
1834.It Xr scsi_get_device_type_string 9F Ta Xr scsi_hba_attach_setup 9F
1835.It Xr scsi_hba_detach 9F Ta Xr scsi_hba_fini 9F
1836.It Xr scsi_hba_init 9F Ta Xr scsi_hba_iport_exist 9F
1837.It Xr scsi_hba_iport_find 9F Ta Xr scsi_hba_iport_register 9F
1838.It Xr scsi_hba_iport_unit_address 9F Ta Xr scsi_hba_iportmap_create 9F
1839.It Xr scsi_hba_iportmap_destroy 9F Ta Xr scsi_hba_iportmap_iport_add 9F
1840.It Xr scsi_hba_iportmap_iport_remove 9F Ta Xr scsi_hba_lookup_capstr 9F
1841.It Xr scsi_hba_pkt_alloc 9F Ta Xr scsi_hba_pkt_comp 9F
1842.It Xr scsi_hba_pkt_free 9F Ta Xr scsi_hba_probe 9F
1843.It Xr scsi_hba_tgtmap_create 9F Ta Xr scsi_hba_tgtmap_destroy 9F
1844.It Xr scsi_hba_tgtmap_scan_luns 9F Ta Xr scsi_hba_tgtmap_set_add 9F
1845.It Xr scsi_hba_tgtmap_set_begin 9F Ta Xr scsi_hba_tgtmap_set_end 9F
1846.It Xr scsi_hba_tgtmap_set_flush 9F Ta Xr scsi_hba_tgtmap_tgt_add 9F
1847.It Xr scsi_hba_tgtmap_tgt_remove 9F Ta Xr scsi_hba_tran_alloc 9F
1848.It Xr scsi_hba_tran_free 9F Ta Xr scsi_ifgetcap 9F
1849.It Xr scsi_ifsetcap 9F Ta Xr scsi_init_pkt 9F
1850.It Xr scsi_log 9F Ta Xr scsi_mname 9F
1851.It Xr scsi_pktalloc 9F Ta Xr scsi_pktfree 9F
1852.It Xr scsi_poll 9F Ta Xr scsi_probe 9F
1853.It Xr scsi_resalloc 9F Ta Xr scsi_reset_notify 9F
1854.It Xr scsi_reset 9F Ta Xr scsi_resfree 9F
1855.It Xr scsi_rname 9F Ta Xr scsi_sense_asc 9F
1856.It Xr scsi_sense_ascq 9F Ta Xr scsi_sense_cmdspecific_uint64 9F
1857.It Xr scsi_sense_info_uint64 9F Ta Xr scsi_sense_key 9F
1858.It Xr scsi_setup_cdb 9F Ta Xr scsi_slave 9F
1859.It Xr scsi_sname 9F Ta Xr scsi_sync_pkt 9F
1860.It Xr scsi_transport 9F Ta Xr scsi_unprobe 9F
1861.It Xr scsi_unslave 9F Ta Xr scsi_validate_sense 9F
1862.It Xr scsi_vu_errmsg 9F Ta Xr scsi_wwn_to_wwnstr 9F
1863scsi_wwnstr_to_wwn
1864.El
1865.Ss Block Device Buffer Handling
1866Block devices operate with a data structure called the
1867.Vt struct buf
1868which is described in
1869.Xr buf 9S .
1870This structure is used to represent a given block request and is used
1871heavily in block devices, the SCSI/SAS framework, and the blkdev
1872framework.
1873The functions described here are used to manipulate these structures in
1874various ways such as copying them around, indicating error conditions,
1875or indicating when the I/O operation is done.
1876By default, this memory is not mapped into the kernel's address space so
1877several functions such as
1878.Xr bp_mapin 9F
1879are present to allow for that to happen when required.
1880.Pp
1881To initially obtain a
1882.Vt struct buf ,
1883drivers should begin by calling
1884.Xr getrbuf 9F
1885at which point, the caller can fill in the structure.
1886Once that's done, the
1887.Xr physio 9F
1888function can be used to actually perform the I/O and wait until it's
1889complete.
1890.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1891.It Xr bioclone 9F Ta Xr biodone 9F
1892.It Xr bioerror 9F Ta Xr biofini 9F
1893.It Xr bioinit 9F Ta Xr biomodified 9F
1894.It Xr bioreset 9F Ta Xr biosize 9F
1895.It Xr biowait 9F Ta Xr bp_mapin 9F
1896.It Xr bp_mapout 9F Ta Xr clrbuf 9F
1897.It Xr disksort 9F Ta Xr freerbuf 9F
1898.It Xr geterror 9F Ta Xr getrbuf 9F
1899.It Xr minphys 9F Ta Xr physio 9F
1900.El
1901.Ss Networking Device Driver Functions
1902These functions are for networking device drivers that implant the MAC,
1903GLDv3 interfaces.
1904The full framework and how to use it is described in
1905.Xr mac 9E .
1906.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1907.It Xr mac_alloc 9F Ta Xr mac_fini_ops 9F
1908.It Xr mac_free 9F Ta Xr mac_hcksum_get 9F
1909.It Xr mac_hcksum_set 9F Ta Xr mac_init_ops 9F
1910.It Xr mac_link_update 9F Ta Xr mac_lso_get 9F
1911.It Xr mac_maxsdu_update 9F Ta Xr mac_prop_info_set_default_fec 9F
1912.It Xr mac_prop_info_set_default_link_flowctrl 9F Ta Xr mac_prop_info_set_default_str 9F
1913.It Xr mac_prop_info_set_default_uint32 9F Ta Xr mac_prop_info_set_default_uint64 9F
1914.It Xr mac_prop_info_set_default_uint8 9F Ta Xr mac_prop_info_set_perm 9F
1915.It Xr mac_prop_info_set_range_uint32 9F Ta Xr mac_prop_info 9F
1916.It Xr mac_register 9F Ta Xr mac_rx 9F
1917.It Xr mac_rx_ring 9F Ta Xr mac_transceiver_info_set_present 9F
1918.It Xr mac_transceiver_info_set_usable 9F Ta Xr mac_transceiver_info 9F
1919.It Xr mac_tx_ring_update 9F Ta Xr mac_tx_update 9F
1920.It Xr mac_unregister 9F Ta
1921.El
1922.Ss USB Device Driver Functions
1923These functions are designed for USB device drivers.
1924To first initialize with the kernel, a device driver must call
1925.Xr usb_client_attach 9F
1926and then
1927.Xr usb_get_dev_data 9F .
1928The latter call is required to get access to the USB-level
1929descriptors about the device which describe what kinds of USB endpoints
1930.Pq control, bulk, interrupt, or isochronous
1931exist on the device as well as how many different interfaces and
1932configurations are present.
1933.Pp
1934Once a given configuration, sometimes the default, is selected, then the
1935driver can proceed to opening up what the USB architecture calls a pipe,
1936which provides a way to send requests to a specific USB endpoint.
1937First, specific endpoints can be looked up using the
1938.Xr usb_lookup_ep_data 9F
1939function which gets information from the parsed descriptors and then
1940that gets filled into an extended descriptor with
1941.Xr usb_ep_xdescr_fill 9F .
1942With that in hand, a pipe can be opened with
1943.Xr usb_pipe_xopen 9F .
1944.Pp
1945Once a pipe has been opened, which most often happens in a driver's
1946.Xr attach 9E
1947entry point, then requests can be allocated and submitted.
1948There is a different allocation for each type of request
1949.Po
1950e.g.
1951.Xr usb_alloc_bulk_req 9F
1952.Pc
1953and a different submission function for each type as well.
1954Each request structure has a corresponding page in section 9S that
1955describes the structure, its members, and how to work with it.
1956.Pp
1957One other major concern for USB devices, which isn't as common with
1958other types of devices, is that they can be yanked out and reinserted
1959at any time.
1960To help determine when this happens, the kernel offers the
1961.Xr usb_register_event_cbs 9F
1962function which allows a driver to register for callbacks when a device
1963is disconnected, reconnected, or around checkpoint suspend/resume
1964behavior.
1965.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
1966.It Xr usb_alloc_bulk_req 9F Ta Xr usb_alloc_ctrl_req 9F
1967.It Xr usb_alloc_intr_req 9F Ta Xr usb_alloc_isoc_req 9F
1968.It Xr usb_alloc_request 9F Ta Xr usb_client_attach 9F
1969.It Xr usb_client_detach 9F Ta Xr usb_clr_feature 9F
1970.It Xr usb_create_pm_components 9F Ta Xr usb_ep_xdescr_fill 9F
1971.It Xr usb_free_bulk_req 9F Ta Xr usb_free_ctrl_req 9F
1972.It Xr usb_free_descr_tree 9F Ta Xr usb_free_dev_data 9F
1973.It Xr usb_free_intr_req 9F Ta Xr usb_free_isoc_req 9F
1974.It Xr usb_get_addr 9F Ta Xr usb_get_alt_if 9F
1975.It Xr usb_get_cfg 9F Ta Xr usb_get_current_frame_number 9F
1976.It Xr usb_get_dev_data 9F Ta Xr usb_get_if_number 9F
1977.It Xr usb_get_max_pkts_per_isoc_request 9F Ta Xr usb_get_status 9F
1978.It Xr usb_get_string_descr 9F Ta Xr usb_handle_remote_wakeup 9F
1979.It Xr usb_lookup_ep_data 9F Ta Xr usb_owns_device 9F
1980.It Xr usb_parse_data 9F Ta Xr usb_pipe_bulk_xfer 9F
1981.It Xr usb_pipe_close 9F Ta Xr usb_pipe_ctrl_xfer_wait 9F
1982.It Xr usb_pipe_ctrl_xfer 9F Ta Xr usb_pipe_drain_reqs 9F
1983.It Xr usb_pipe_get_max_bulk_transfer_size 9F Ta Xr usb_pipe_get_private 9F
1984.It Xr usb_pipe_get_state 9F Ta Xr usb_pipe_intr_xfer 9F
1985.It Xr usb_pipe_isoc_xfer 9F Ta Xr usb_pipe_open 9F
1986.It Xr usb_pipe_reset 9F Ta Xr usb_pipe_set_private 9F
1987.It Xr usb_pipe_stop_intr_polling 9F Ta Xr usb_pipe_stop_isoc_polling 9F
1988.It Xr usb_pipe_xopen 9F Ta Xr usb_print_descr_tree 9F
1989.It Xr usb_register_hotplug_cbs 9F Ta Xr usb_reset_device 9F
1990.It Xr usb_set_alt_if 9F Ta Xr usb_set_cfg 9F
1991.It Xr usb_unregister_hotplug_cbs 9F Ta
1992.El
1993.Ss PCI Device Driver Functions
1994These functions are specific for PCI and PCI Express based device
1995drivers and are intended to be used to get access to PCI configuration
1996space.
1997For normal PCI base address registers
1998.Pq BARs
1999instead see
2000.Sx Register Setup and Access .
2001.Pp
2002To access PCI configuration space, a device driver should first call
2003.Xr pci_config_setup 9F .
2004Generally, drivers will call this in their
2005.Xr attach 9E
2006entry point and then tear down the configuration space access with the
2007.Xr pci_config_teardown 9F
2008entry point in
2009.Xr detach 9E .
2010After setting up access to configuration space, the returned handle can
2011be used in all of the various configuration space routines to get and
2012set specific sized values in configuration space.
2013.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2014.It Xr pci_config_get8 9F Ta Xr pci_config_get16 9F
2015.It Xr pci_config_get32 9F Ta Xr pci_config_get64 9F
2016.It Xr pci_config_put8 9F Ta Xr pci_config_put16 9F
2017.It Xr pci_config_put32 9F Ta Xr pci_config_put64 9F
2018.It Xr pci_config_setup 9F Ta Xr pci_config_teardown 9F
2019.It Xr pci_report_pmcap 9F Ta Xr pci_restore_config_regs 9F
2020.It Xr pci_save_config_regs 9F Ta
2021.El
2022.Ss USB Host Controller Interface Functions
2023These routines are used for device drivers which implement the USB
2024host controller interfaces described in
2025.Xr usba_hcdi 9E .
2026Other types of devices drivers and modules should not call these
2027functions.
2028In particular, if one is writing a device driver for a USB device, these
2029are not the routines you're looking for and you want to see
2030.Sx USB Device Driver Functions .
2031These are what the
2032.Xr ehci 4D
2033or
2034.Xr xhci 4D
2035drivers use to provide services that USB drivers use via the kernel USB
2036architecture.
2037.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2038.It Xr usba_alloc_hcdi_ops 9F Ta Xr usba_free_hcdi_ops 9F
2039.It Xr usba_hcdi_cb 9F Ta Xr usba_hcdi_dup_intr_req 9F
2040.It Xr usba_hcdi_dup_isoc_req 9F Ta Xr usba_hcdi_get_device_private 9F
2041.It Xr usba_hcdi_register 9F Ta Xr usba_hcdi_unregister 9F
2042.It Xr usba_hubdi_bind_root_hub 9F Ta Xr usba_hubdi_cb_ops 9F
2043.It Xr usba_hubdi_close 9F Ta Xr usba_hubdi_dev_ops 9F
2044.It Xr usba_hubdi_ioctl 9F Ta Xr usba_hubdi_open 9F
2045.It Xr usba_hubdi_root_hub_power 9F Ta Xr usba_hubdi_unbind_root_hub 9F
2046.El
2047.Ss Functions for PCMCIA Drivers
2048These functions exist for older PCMCIA device drivers.
2049These should not otherwise be used by the system.
2050.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2051.It Xr csx_AccessConfigurationRegister 9F Ta Xr csx_ConvertSize 9F
2052.It Xr csx_ConvertSpeed 9F Ta Xr csx_CS_DDI_Info 9F
2053.It Xr csx_DeregisterClient 9F Ta Xr csx_DupHandle 9F
2054.It Xr csx_Error2Text 9F Ta Xr csx_Event2Text 9F
2055.It Xr csx_FreeHandle 9F Ta Xr csx_Get16 9F
2056.It Xr csx_Get32 9F Ta Xr csx_Get64 9F
2057.It Xr csx_Get8 9F Ta Xr csx_GetEventMask 9F
2058.It Xr csx_GetFirstClient 9F Ta Xr csx_GetFirstTuple 9F
2059.It Xr csx_GetHandleOffset 9F Ta Xr csx_GetMappedAddr 9F
2060.It Xr csx_GetNextClient 9F Ta Xr csx_GetNextTuple 9F
2061.It Xr csx_GetStatus 9F Ta Xr csx_GetTupleData 9F
2062.It Xr csx_MakeDeviceNode 9F Ta Xr csx_MapLogSocket 9F
2063.It Xr csx_MapMemPage 9F Ta Xr csx_ModifyConfiguration 9F
2064.It Xr csx_ModifyWindow 9F Ta Xr csx_Parse_CISTPL_BATTERY 9F
2065.It Xr csx_Parse_CISTPL_BYTEORDER 9F Ta Xr csx_Parse_CISTPL_CFTABLE_ENTRY 9F
2066.It Xr csx_Parse_CISTPL_CONFIG 9F Ta Xr csx_Parse_CISTPL_DATE 9F
2067.It Xr csx_Parse_CISTPL_DEVICE_A 9F Ta Xr csx_Parse_CISTPL_DEVICE_OA 9F
2068.It Xr csx_Parse_CISTPL_DEVICE_OC 9F Ta Xr csx_Parse_CISTPL_DEVICE 9F
2069.It Xr csx_Parse_CISTPL_DEVICEGEO_A 9F Ta Xr csx_Parse_CISTPL_DEVICEGEO 9F
2070.It Xr csx_Parse_CISTPL_FORMAT 9F Ta Xr csx_Parse_CISTPL_FUNCE 9F
2071.It Xr csx_Parse_CISTPL_FUNCID 9F Ta Xr csx_Parse_CISTPL_GEOMETRY 9F
2072.It Xr csx_Parse_CISTPL_JEDEC_A 9F Ta Xr csx_Parse_CISTPL_JEDEC_C 9F
2073.It Xr csx_Parse_CISTPL_LINKTARGET 9F Ta Xr csx_Parse_CISTPL_LONGLINK_A 9F
2074.It Xr csx_Parse_CISTPL_LONGLINK_C 9F Ta Xr csx_Parse_CISTPL_LONGLINK_MFC 9F
2075.It Xr csx_Parse_CISTPL_MANFID 9F Ta Xr csx_Parse_CISTPL_ORG 9F
2076.It Xr csx_Parse_CISTPL_SPCL 9F Ta Xr csx_Parse_CISTPL_SWIL 9F
2077.It Xr csx_Parse_CISTPL_VERS_1 9F Ta Xr csx_Parse_CISTPL_VERS_2 9F
2078.It Xr csx_ParseTuple 9F Ta Xr csx_Put16 9F
2079.It Xr csx_Put32 9F Ta Xr csx_Put64 9F
2080.It Xr csx_Put8 9F Ta Xr csx_RegisterClient 9F
2081.It Xr csx_ReleaseConfiguration 9F Ta Xr csx_ReleaseIO 9F
2082.It Xr csx_ReleaseIRQ 9F Ta Xr csx_ReleaseSocketMask 9F
2083.It Xr csx_ReleaseWindow 9F Ta Xr csx_RemoveDeviceNode 9F
2084.It Xr csx_RepGet16 9F Ta Xr csx_RepGet32 9F
2085.It Xr csx_RepGet64 9F Ta Xr csx_RepGet8 9F
2086.It Xr csx_RepPut16 9F Ta Xr csx_RepPut32 9F
2087.It Xr csx_RepPut64 9F Ta Xr csx_RepPut8 9F
2088.It Xr csx_RequestConfiguration 9F Ta Xr csx_RequestIO 9F
2089.It Xr csx_RequestIRQ 9F Ta Xr csx_RequestSocketMask 9F
2090.It Xr csx_RequestWindow 9F Ta Xr csx_ResetFunction 9F
2091.It Xr csx_SetEventMask 9F Ta Xr csx_SetHandleOffset 9F
2092.It Xr csx_ValidateCIS 9F Ta
2093.El
2094.Ss STREAMS related functions
2095These functions are meant to be used when interacting with STREAMS
2096devices or when implementing one.
2097When a STREAMS driver is opened, it receives messages on a queue which
2098are then processed and can be sent back.
2099As different queues are often linked together, the most common thing is
2100to process a message and then pass the message onto the next queue using
2101the
2102.Xr putnext 9F
2103function.
2104.Pp
2105STREAMS messages are passed around using message blocks, which use the
2106.Vt mblk_t
2107type.
2108See
2109.Sx Message Block Functions
2110for more about how the data structure and functions that manipulate
2111message blocks.
2112.Pp
2113These functions should generally not be used when implementing a
2114networking device driver today.
2115See
2116.Xr mac 9E
2117instead.
2118.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2119.It Xr backq 9F Ta Xr bcanput 9F
2120.It Xr bcanputnext 9F Ta Xr canput 9F
2121.It Xr canputnext 9F Ta Xr enableok 9F
2122.It Xr flushband 9F Ta Xr flushq 9F
2123.It Xr freezestr 9F Ta Xr getq 9F
2124.It Xr insq 9F Ta Xr merror 9F
2125.It Xr mexchange 9F Ta Xr noenable 9F
2126.It Xr put 9F Ta Xr putbq 9F
2127.It Xr putctl 9F Ta Xr putctl1 9F
2128.It Xr putnext 9F Ta Xr putnextctl 9F
2129.It Xr putnextctl1 9F Ta Xr putq 9F
2130.It Xr mt-streams 9F Ta Xr qassociate 9F
2131.It Xr qenable 9F Ta Xr qprocsoff 9F
2132.It Xr qprocson 9F Ta Xr qreply 9F
2133.It Xr qsize 9F Ta Xr qwait_sig 9F
2134.It Xr qwait 9F Ta Xr qwriter 9F
2135.It Xr OTHERQ 9F Ta Xr RD 9F
2136.It Xr rmvq 9F Ta Xr SAMESTR 9F
2137.It Xr unfreezestr 9F Ta Xr WR 9F
2138.El
2139.Ss STREAMS ioctls
2140The following functions are used when a STREAMS-based device driver is
2141processing its
2142.Xr ioctl 9E
2143entry point.
2144Unlike character and block devices, STREAMS ioctls are passed around in
2145message blocks and copying data in and out of userland as STREAMS
2146ioctls are generally always processed in
2147.Sy kernel
2148context.
2149This means that the normal functions like
2150.Xr ddi_copyin 9F
2151and
2152.Xr ddi_copyout 9F
2153cannot be used.
2154Instead, when a message block has a type of
2155.Dv M_IOCTL ,
2156then these routines can often be used to convert the structure into one
2157that asks for data to be copied in, copied out, or to finally
2158acknowledge the ioctl as successful or to terminate the processing in
2159error.
2160.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2161.It Xr mcopyin 9F Ta Xr mcopyout 9F
2162.It Xr mioc2ack 9F Ta Xr miocack 9F
2163.It Xr miocnak 9F Ta Xr miocpullup 9F
2164.It Xr mkiocb 9F Ta
2165.El
2166.Ss chpoll(9E) Related Functions
2167These functions are present in service of the
2168.Xr chpoll 9E
2169interface which is used to support the traditional
2170.Xr poll 2 ,
2171and
2172.Xr select 3C
2173interfaces as well as event ports through the
2174.Xr port_get 3C
2175interface.
2176See
2177.Xr chpoll 9E
2178for the specific cases this should be called.
2179If a device driver does not implement the
2180.Xr chpoll 9E
2181character device entry point, then these functions should not be used.
2182.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2183.It Xr pollhead_clean 9F Ta Xr pollwakeup 9F
2184.El
2185.Ss Kernel Statistics
2186The kernel statistics or kstat framework provides an easy way of
2187exporting statistic information to be consumed outside of the kernel.
2188Users can interface with this data via
2189.Xr kstat 8
2190and the corresponding kstat library discussed in
2191.Xr kstat 3KSTAT .
2192.Pp
2193Kernel statistics are grouped using a tuple of four identifiers,
2194separated by colons when using
2195.Xr kstat 8 .
2196These are, in order, the statistic module name, instance, a name
2197which covers a group of statistics, and an individual name for a
2198statistic.
2199In addition, kernel statistics have a class which is used to group
2200similar named groups of statistics together across devices.
2201When using
2202.Xr kstat_create 9F ,
2203drivers specify the first three parts of the tuple and the class.
2204The naming of individual statistics, the last part of the tuple, varies
2205based upon the type of the statistic.
2206For the most part, drivers will use the kstat type
2207.Dv KSTAT_TYPE_NAMED ,
2208which allows multiple name-value pairs to exist within the statistic.
2209For example, the kernel's layer 2 networking framework,
2210.Xr mac 9E ,
2211creates a kstat with the driver's name and instance and names it
2212.Dq mac .
2213Within this named group, there are statistics for all of the different
2214individual stats that the kernel and devices track such as bytes
2215transmitted and received, the state and speed of the link, and
2216advertised and enabled capabilities.
2217.Pp
2218A device driver can initialize a kstat with the
2219.Xr kstat_create 9F
2220function.
2221It will not be made accessible to users until the
2222.Xr kstat_install 9F
2223function is called.
2224The device driver must perform additional initialization of the kstat
2225before proceeding and calling
2226.Xr kstat_install 9F .
2227The kstat structure that drivers see is discussed in
2228.Xr kstat 9S .
2229.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2230.It Xr kstat_create 9F Ta Xr kstat_delete 9F
2231.It Xr kstat_install 9F Ta Xr kstat_named_init 9F
2232.It Xr kstat_named_setstr 9F Ta Xr kstat_queue 9F
2233.It Xr kstat_runq_back_to_waitq 9F Ta Xr kstat_runq_enter 9F
2234.It Xr kstat_runq_exit 9F Ta Xr kstat_waitq_enter 9F
2235.It Xr kstat_waitq_exit 9F Ta Xr kstat_waitq_to_runq 9F
2236.El
2237.Ss NDI Events
2238These functions are used to allow a device driver to register for
2239certain events that might occur to its device or a parent in the tree
2240and receive a callback function when they occur.
2241A good example of this is when a device has been removed from the system
2242such as someone just pulling out a USB device or NVMe U.2 device.
2243The event handlers work by first getting a cookie that names the type of
2244event with
2245.Xr ddi_get_eventcookie 9F
2246and then registering the callback with
2247.Xr ddi_add_event_handler 9F .
2248.Pp
2249The
2250.Xr ddi_cb_register 9F
2251function is used to collect over classes of events such as when
2252participating in dynamic interrupt sharing.
2253.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2254.It Xr ddi_add_event_handler 9F Ta Xr ddi_cb_register 9F
2255.It Xr ddi_cb_unregister 9F Ta Xr ddi_get_eventcookie 9F
2256.It Xr ddi_remove_event_handler 9F Ta
2257.El
2258.Ss Layered Device Interfaces
2259The LDI
2260.Pq Layered Device Interface
2261provides a mechanism for a driver to open up another device in the
2262kernel and begin calling basic operations on the device as though the
2263calling driver were a normal user process.
2264Through the LDI, drivers can perform equivalents to the basic file
2265.Xr read 2
2266and
2267.Xr write 2
2268calls, look up properties on the device, perform networking style calls
2269ala
2270.Xr getmsg 2
2271and
2272.Xr putmsg 2 ,
2273and register callbacks to be called when something happens to the
2274underlying device.
2275For example, the ZFS file system uses the LDI to open and operate on
2276block devices.
2277.Pp
2278Before opening a device itself, callers must obtain a notion of their
2279identity which is used when making subsequent calls.
2280The simplest form is often to use the device's
2281.Vt dev_info_t
2282and call
2283.Xr ldi_ident_from_dip 9F ;
2284however, there are also methods available based upon having a
2285.Vt dev_t
2286or a STREAMS
2287.Vt struct queue .
2288.Pp
2289Once that identity is established, there are several ways to open a
2290device such as
2291.Xr ldi_open_by_dev 9F ,
2292.Xr ldi_open_by_devid 9F ,
2293or
2294.Xr ldi_open_by_name 9F .
2295Once an LDI device has been opened, then all of the other functions may
2296be used to operate on the device; however, consumers of the LDI must
2297think carefully about what kind of device they are opening.
2298While a kernel pseudo-device driver cannot disappear while it is open,
2299when the device represents an actual piece of hardware, it is possible
2300for it to be physically removed and no longer be accessible.
2301Consumers should not assume that a layered device will always be
2302present.
2303.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2304.It Xr ldi_add_event_handler 9F Ta Xr ldi_aread 9F
2305.It Xr ldi_awrite 9F Ta Xr ldi_close 9F
2306.It Xr ldi_devmap 9F Ta Xr ldi_dump 9F
2307.It Xr ldi_ev_finalize 9F Ta Xr ldi_ev_get_cookie 9F
2308.It Xr ldi_ev_get_type 9F Ta Xr ldi_ev_notify 9F
2309.It Xr ldi_ev_register_callbacks 9F Ta Xr ldi_ev_remove_callbacks 9F
2310.It Xr ldi_get_dev 9F Ta Xr ldi_get_devid 9F
2311.It Xr ldi_get_eventcookie 9F Ta Xr ldi_get_minor_name 9F
2312.It Xr ldi_get_otyp 9F Ta Xr ldi_get_size 9F
2313.It Xr ldi_getmsg 9F Ta Xr ldi_ident_from_dev 9F
2314.It Xr ldi_ident_from_dip 9F Ta Xr ldi_ident_from_stream 9F
2315.It Xr ldi_ident_release 9F Ta Xr ldi_ioctl 9F
2316.It Xr ldi_open_by_dev 9F Ta Xr ldi_open_by_devid 9F
2317.It Xr ldi_open_by_name 9F Ta Xr ldi_poll 9F
2318.It Xr ldi_prop_exists 9F Ta Xr ldi_prop_get_int 9F
2319.It Xr ldi_prop_get_int64 9F Ta Xr ldi_prop_lookup_byte_array 9F
2320.It Xr ldi_prop_lookup_int_array 9F Ta Xr ldi_prop_lookup_int64_array 9F
2321.It Xr ldi_prop_lookup_string_array 9F Ta Xr ldi_prop_lookup_string 9F
2322.It Xr ldi_putmsg 9F Ta Xr ldi_read 9F
2323.It Xr ldi_remove_event_handler 9F Ta Xr ldi_strategy 9F
2324.It Xr ldi_write 9F Ta
2325.El
2326.Ss Signal Manipulation
2327These utility functions all relate to understanding whether or not a
2328process can receive a signal an actually delivering one to a process
2329from a driver.
2330This interface is specific to device drivers and should not be used by
2331the broader kernel.
2332These interfaces are not recommended and should only be used after
2333consultation.
2334.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2335.It Xr ddi_can_receive_sig 9F Ta Xr proc_ref 9F
2336.It Xr proc_signal 9F Ta Xr proc_unref 9F
2337.El
2338.Ss Getting at Surrounding Context
2339These functions allow a driver to better understand its current context.
2340For example, some drivers have to deal with providing polled I/O or take
2341special care as part of creating a kernel crash dump.
2342These cases may need to call the
2343.Xr ddi_in_panic 9F
2344function.
2345The other functions generally provide a way to get at information such as
2346the process ID or other information from the system; however, this
2347generally should not be needed or used.
2348Almost all values exposed by say
2349.Xr drv_getparm 9F
2350have more usable first-class methods of getting at the data.
2351.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2352.It Xr ddi_get_kt_did 9F Ta Xr ddi_get_pid 9F
2353.It Xr ddi_in_panic 9F Ta Xr drv_getparm 9F
2354.El
2355.Ss Driver Memory Mapping
2356These functions are present for device drivers that implement the
2357.Xr devmap 9E
2358or
2359.Xr segmap 9E
2360entry points.
2361The
2362.Xr ddi_umem_alloc 9F
2363routines are used to allocate and lock memory that can later be used as
2364part of passing this memory to userland through the mapping entry
2365points.
2366.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2367.It Xr ddi_devmap_segmap 9F Ta Xr ddi_mmap_get_model 9F
2368.It Xr ddi_segmap_setup 9F Ta Xr ddi_segmap 9F
2369.It Xr ddi_umem_alloc 9F Ta Xr ddi_umem_free 9F
2370.It Xr ddi_umem_iosetup 9F Ta Xr ddi_umem_lock 9F
2371.It Xr ddi_umem_unlock 9F Ta Xr ddi_unmap_regs 9F
2372.It Xr devmap_default_access 9F Ta Xr devmap_devmem_setup 9F
2373.It Xr devmap_do_ctxmgt 9F Ta Xr devmap_load 9F
2374.It Xr devmap_set_ctx_timeout 9F Ta Xr devmap_setup 9F
2375.It Xr devmap_umem_setup 9F Ta Xr devmap_unload 9F
2376.El
2377.Ss UTF-8, UTF-16, UTF-32, and Code Set Utilities
2378These routines provide the ability to work with and deal with text in
2379different encodings and code sets.
2380Generally the kernel does not assume that much about the type of the text
2381that it is operating in, though some subsystems will require that the
2382names of things be ASCII only.
2383.Pp
2384The primary other locales that the system supports are generally UTF-8
2385based and so the kernel provides a set of routines to deal with UTF-8
2386and Unicode normalization.
2387However, there are still cases where different character encodings are
2388required or conversation between UTF-8 and some other type is required.
2389This is provided by the kernel iconv framework, which provides a
2390subset of the traditional userland iconv conversions.
2391.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2392.It Xr kiconv_close 9F Ta Xr kiconv_open 9F
2393.It Xr kiconv 9F Ta Xr kiconvstr 9F
2394.It Xr u8_strcmp 9F Ta Xr u8_textprep_str 9F
2395.It Xr u8_validate 9F Ta Xr uconv_u16tou32 9F
2396.It Xr uconv_u16tou8 9F Ta Xr uconv_u32tou16 9F
2397.It Xr uconv_u32tou8 9F Ta Xr uconv_u8tou16 9F
2398.It Xr uconv_u8tou32 9F Ta
2399.El
2400.Ss Raw I/O Port Access
2401This group of functions provides raw access to I/O ports on architecture
2402that support them.
2403These functions do not allow any coordination with other callers nor is
2404the validity of the port assured in any way.
2405In general, device drivers should use the normal register access
2406routines to access I/O ports.
2407See
2408.Sx Device Register Setup and Access
2409for more information on the preferred way to setup and access registers.
2410.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2411.It Xr inb 9F Ta Xr inw 9F
2412.It Xr inl 9F Ta Xr outb 9F
2413.It Xr outw 9F Ta Xr outl 9F
2414.El
2415.Ss Power Management
2416These functions are used to raise and lower the internal power levels of
2417a device driver or to indicate to the kernel that the device is busy and
2418therefore cannot have its power changed.
2419See
2420.Xr power 9E
2421for additional information.
2422.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2423.It Xr ddi_removing_power 9F Ta Xr pm_busy_component 9F
2424.It Xr pm_idle_component 9F Ta Xr pm_lower_power 9F
2425.It Xr pm_power_has_changed 9F Ta Xr pm_raise_power 9F
2426.It Xr pm_trans_check 9F Ta
2427.El
2428.Ss Network Packet Hooks
2429These functions are intended to be used by device drivers that wish to
2430inspect and potentially modify packets along their path through the
2431networking stack.
2432The most common use case is for implementing something like a network
2433firewall.
2434Otherwise, if looking to add support for a new protocol or other network
2435processing feature, one is better off more directly integrating with the
2436networking stack.
2437.Pp
2438To get started, drivers generally will need to first use
2439.Xr net_protocol_lookup 9F
2440to get a handle to say that they're interested in looking at IPv4 or
2441IPv6 traffic and then can allocate an actual hook object with
2442.Xr hook_alloc 9F .
2443After filling out the hook, the hook can be inserted into the actual
2444system with
2445.Xr net_hook_register 9F .
2446.Pp
2447Hooks operate in the context of a networking stack.
2448Every networking stack in the system is independent and therefore has
2449its own set of interfaces, routing tables, settings, and related.
2450Most zones have their own networking stack.
2451This is the exclusive-IP option that is described in
2452.Xr zoneadm 8 .
2453.Pp
2454Drivers can register to get a callback for every netstack in the system
2455and be notified when they are created and destroyed.
2456This is done by calling the
2457.Xr net_instance_alloc 9F
2458function, filling out its data structure, and then finally calling
2459.Xr net_instance_register 9F .
2460Like other callback interfaces, the moment the callback functions are
2461registered, drivers need to expect that they're going to be called.
2462.Bl -column -offset indent "net_instance_protocol_unregister" "net_instance_protocol_unregister"
2463.It Xr hook_alloc 9F Ta Xr hook_free 9F
2464.It Xr net_event_notify_register 9F Ta Xr net_event_notify_unregister 9F
2465.It Xr net_getifname 9F Ta Xr net_getlifaddr 9F
2466.It Xr net_getmtu 9F Ta Xr net_getnetid 9F
2467.It Xr net_getpmtuenabled 9F Ta Xr net_hook_register 9F
2468.It Xr net_hook_unregister 9F Ta Xr net_inject_alloc 9F
2469.It Xr net_inject_free 9F Ta Xr net_inject 9F
2470.It Xr net_instance_alloc 9F Ta Xr net_instance_free 9F
2471.It Xr net_instance_notify_register 9F Ta Xr net_instance_notify_unregister 9F
2472.It Xr net_instance_protocol_unregister 9F Ta Xr net_instance_register 9F
2473.It Xr net_instance_unregister 9F Ta Xr net_ispartialchecksum 9F
2474.It Xr net_isvalidchecksum 9F Ta Xr net_kstat_create 9F
2475.It Xr net_kstat_delete 9F Ta Xr net_lifgetnext 9F
2476.It Xr net_netidtozonid 9F Ta Xr net_phygetnext 9F
2477.It Xr net_phylookup 9F Ta Xr net_protocol_lookup 9F
2478.It Xr net_protocol_notify_register 9F Ta Xr net_protocol_release 9F
2479.It Xr net_protocol_walk 9F Ta Xr net_routeto 9F
2480.It Xr net_zoneidtonetid 9F Ta Xr netinfo 9F
2481.El
2482.Sh SEE ALSO
2483.Xr Intro 2 ,
2484.Xr Intro 9 ,
2485.Xr Intro 9E ,
2486.Xr Intro 9S
2487.Rs
2488.%T illumos Developer's Guide
2489.%U https://www.illumos.org/books/dev/
2490.Re
2491.Rs
2492.%T Writing Device Drivers
2493.%U https://www.illumos.org/books/wdd/
2494.Re
2495