Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
.\"	$NetBSD: scsipi.9,v 1.31 2017/07/03 21:28:48 wiz Exp $
.\"
.\"
.\" Copyright (c) 2001 Manuel Bouyer.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
.Dd November 20, 2016
.Dt SCSIPI 9
.Os
.Sh NAME
.Nm scsipi
.Nd SCSI/ATAPI middle-layer interface
.Sh SYNOPSIS
.In dev/scsipi/atapiconf.h
.In dev/scsipi/scsiconf.h
.Ft void
.Fn scsipi_async_event "struct scsipi_channel *chan" "scsipi_async_event_t event" "void *arg"
.Ft void
.Fn scsipi_channel_freeze "struct scsipi_channel *chan" "int count"
.Ft void
.Fn scsipi_channel_thaw "struct scsipi_channel *chan" "int count"
.Ft void
.Fn scsipi_channel_timed_thaw "void *arg"
.Ft void
.Fn scsipi_periph_freeze "struct scsipi_periph *periph" "int count"
.Ft void
.Fn scsipi_periph_thaw "struct scsipi_periph *periph" "int count"
.Ft void
.Fn scsipi_periph_timed_thaw "void *arg"
.Ft void
.Fn scsipi_done "struct scsipi_xfer *xs"
.Ft void
.Fn scsipi_printaddr "struct scsipi_periph *periph"
.Ft int
.Fn scsipi_target_detach "struct scsipi_channel *chan" "int target" "int lun" "int flags"
.Ft int
.Fn scsipi_thread_call_callback "struct scsipi_channel *chan" "void (*callback)(struct scsipi_channel *, void *)" "void *arg"
.Ft int
.Fn scsipi_adapter_addref "struct scsipi_adapter *adapt"
.Ft void
.Fn scsipi_adapter_delref "struct scsipi_adapter *adapt"
.Sh DESCRIPTION
The
.Nm
system is the middle layer interface between SCSI/ATAPI host bus
adapters (HBA) and high-level SCSI/ATAPI drivers.
This document describes the interfaces provided by the
.Nm
layer towards the HBA layer.
An HBA has to provide a pointer to a
.Va struct scsipi_adapter
and one pointer per channel to a
.Va struct scsipi_channel .
Once the SCSI or ATAPI bus is attached, the
.Nm
system will scan the bus and allocate a
.Va struct scsipi_periph
for each device found on the bus.
A high-level command (command sent from the high-level SCSI/ATAPI
layer to the low-level HBA layer) is described by a
.Va struct scsipi_xfer .
.Pp
A request is sent to the HBA driver through the
.Fn adapt_request
callback.
The HBA driver signals completion (with or without errors) of the
request through
.Fn scsipi_done .
.Nm
knows the resource's limits of the HBA (max number of concurrent requests per
adapter of channel, and per periph), and will make sure the HBA won't receive
more requests than it can handle.
.Pp
The mid-layer can also handle
.Dv QUEUE FULL
and
.Dv CHECK CONDITION
events.
.Ss INITIALISATION
An HBA driver has to allocate and initialize to 0 a
.Va struct scsipi_adapter
and fill in the following members:
.Bl -tag -width "struct_device *adapt_dev" -compact -offset indent
.It Va struct device *adapt_dev
pointer to the HBA's
.Va struct device
.It Va int adapt_nchannels
number of channels (or busses) of the adapter
.It Va int adapt_openings
total number of commands the adapter can handle (may be replaced by
.Va chan_openings ,
see below)
.It Va int adapt_max_periph
number of commands the adapter can handle per device
.It Va int adapt_flags
adapter properties
.Bl -tag -width SCSIPI_ADAPT_POLL_ONLY -compact
.It Dv SCSIPI_ADAPT_POLL_ONLY
the HBA can't do interrupts
.It Dv SCSIPI_ADAPT_MPSAFE
don't acquire the kernel lock when doing HBA callbacks
.El
.El
.Pp
The following callbacks should be provided through the
.Va struct scsipi_adapter :
.Bl -tag -width someverylongword -compact -offset indent
.It void Fn (*adapt_request) "struct scsipi_channel *" "scsipi_adapter_req_t" "void *"
mandatory
.It void Fn (*adapt_minphys) "struct buf *"
mandatory
.It int Fn (*adapt_ioctl) "struct scsipi_channel *" "u_long" "void *" "int" "struct lwp *"
optional
.It int Fn (*adapt_enable) "struct device *" "int"
optional, set to
.Dv NULL
if not used
.It int Fn (*adapt_getgeom) "struct scsipi_periph *" "struct disk_parms *" "u_long"
optional, set to
.Dv NULL
if not used
.It int Fn (*adapt_accesschk) "struct scsipi_periph *" "struct scsipi_inquiry_pattern *"
optional, set to
.Dv NULL
if not used
.El
.Pp
The HBA driver has to allocate and initialize to 0 one
.Va struct scsipi_channel
per channel and fill in the following members:
.Bl -tag -width struct_scsipi_adapter -compact -offset indent
.It Va struct scsipi_adapter *chan_adapter
Pointer to the HBA's
.Fa struct scsipi_adapter
.It Va struct scsipi_bustype *chan_bustype
should be initialized to either
.Va bus_atapi
or
.Va bus_scsi ,
both defined in the
.Nm
code.
.It Va int chan_channel
channel number (starting at 0)
.It Va int chan_flags
channel flags:
.Bl -tag -width SCSIPI_CHAN_OPENINGS -compact
.It Dv SCSIPI_CHAN_OPENINGS
Use per-channel max number of commands
.Va chan_openings
instead of per-adapter
.Va adapt_openings
.It Dv SCSIPI_CHAN_CANGROW
This channel can grow its
.Va chan_openings
or
.Va adapt_openings
on request (via the
.Fn adapt_request
callback)
.It Dv SCSIPI_CHAN_NOSETTLE
Do not wait SCSI_DELAY seconds for devices to settle before probing (usually
used by adapters that provide an \*qabstracted\*q view of the bus).
.El
.It Va int chan_openings
total number of commands the adapter can handle for this channel (used only
if the
.Dv SCSIPI_CHAN_OPENINGS
flag is set)
.It Va chan_max_periph
number of commands per device the adapter can handle on this
channel (used only if the
.Va SCSIPI_CHAN_OPENINGS
flag is set)
.It Va int chan_ntargets
number of targets
.It Va int chan_nluns
number of LUNs per target
.It Va int chan_id
adapter's ID on this channel
.It Va int chan_defquirks
default device quirks.
Quirks are defined in
.In dev/scsipi/scsipiconf.h
and are usually set in the middle layer based on the device's inquiry
data.
For some kinds of adapters it may be convenient to have a set of
quirks applied to all devices, regardless of the inquiry data.
.El
.Pp
The HBA driver attaches the SCSI or ATAPI bus (depending on the setting of
.Va chan_bustype )
by passing a pointer to the
.Va struct scsipi_channel
to the
.Xr autoconf 9
machinery.
The print function shall be either
.Fn scsiprint
or
.Fn atapiprint .
.Ss OTHER DATA STRUCTURES
When scanning the bus, the
.Nm
system allocates a
.Va struct scsipi_periph
for each device probed.
The interesting fields are:
.Bl -tag -width int_periph_openings -compact -offset indent
.It Va struct device *periph_dev
pointer to the device's
.Va struct device
.It Va struct scsipi_channel *periph_channel
pointer to the channel the device is connected to
.It Va int periph_quirks
device quirks, defined in
.In dev/scsipi/scsipiconf.h
.It Va int periph_target
target ID, or drive number on ATAPI
.It Va int periph_lun
LUN (currently not used on ATAPI)
.El
.Pp
A SCSI or ATAPI request is passed to the HBA through a
.Va struct scsipi_xfer .
The HBA driver has access to the following data:
.Bl -tag -width "int xs_callout" -compact -offset indent
.It Va struct callout xs_callout
callout for adapter use, usually for command timeout
.It Va int xs_control
control flags (only flags of interest for HBA drivers are described):
.Bl -tag -width XS_CTL_DISCOVERY -compact
.It Dv XS_CTL_POLL
poll in the HBA driver for request completion (most likely because interrupts
are disabled)
.It Dv XS_CTL_RESET
reset the device
.It Dv XS_CTL_DATA_UIO
xs_data points to a
.Fa struct uio
buffer
.It Dv XS_CTL_DATA_IN
data is transferred from HBA to memory
.It Dv XS_CTL_DATA_OUT
data is transferred from memory to HBA
.It Dv XS_CTL_DISCOVERY
this xfer is part of a device discovery done by the middle layer
.It Dv XS_CTL_REQSENSE
xfer is a request sense
.El
.Pp
.It Va int xs_status
status flags:
.Bl -tag -width XS_STS_PRIVATE -compact
.It Va XS_STS_DONE
xfer is done (set by
.Fn scsipi_done )
.It Va XS_STS_PRIVATE
mask of flags reserved for HBA's use (0xf0000000)
.El
.Pp
.It Va struct scsipi_periph *xs_periph
periph doing the xfer
.It Va int timeout
command timeout, in milliseconds.
The HBA should start the timeout at the time the command is accepted
by the device.
If the timeout happens, the HBA shall terminate the command through
.Fn scsipi_done
with a XS_TIMEOUT error
.It Va struct scsipi_generic *cmd
scsipi command to execute
.It Va int cmdlen
len (in bytes) of the cmd buffer
.It Va u_char *data
data buffer (this is either a DMA or uio address)
.It Va int datalen
data length (in bytes, zero if uio)
.It Va int resid
difference between
.Fa datalen
and how much data was really transferred
.It Va scsipi_xfer_result_t error
error value returned by the HBA driver to mid-layer.
See description of
.Fn scsipi_done
for valid values
.It Va union {struct scsipi_sense_data scsi_sense; uint32_t atapi_sense;} sense
where to store sense info if
.Fa error
is
.Dv XS_SENSE
or
.Dv XS_SHORTSENSE
.It Va uint8_t status
SCSI status; checked by middle layer when
.Fa error is
.Dv XS_BUSY
(the middle layer handles
.Dv SCSI_CHECK
and
.Dv SCSI_QUEUE_FULL )
.It Va uint8_t xs_tag_type
SCSI tag type, set to 0 if untagged command
.It Va uint8_t xs_tag_id
tag ID, used for tagged commands
.El
.Ss FUNCTIONS AND CALLBACKS
.Bl -tag -width xxxxxxxx -compact
.It Fn (*adapt_request) "struct scsipi_channel *chan" "scsipi_adapter_req_t req" "void *arg"
Used by the mid-layer to transmit a request to the adapter.
.Va req
can be one of:
.Bl -tag -width xxxxxxxx -compact
.It Dv ADAPTER_REQ_RUN_XFER
request the adapter to send a command to the device.
.Fa arg
is a pointer to the
.Va struct scsipi_xfer .
Once the xfer is complete the HBA driver shall call
.Fn scsipi_done
with updated status and error information.
.It Dv ADAPTER_REQ_GROW_RESOURCES
ask the adapter to increase resources of the channel (grow
.Va adapt_openings
or
.Va chan_openings )
if possible.
Support of this feature is optional.
This request is called from the kernel completion thread.
.Fa arg
must be ignored.
.It Dv ADAPTER_REQ_SET_XFER_MODE
set the xfer mode for a I_T Nexus.
This will be called once all LUNs of a target have been probed.
.Fa arg
points to a
.Va struct scsipi_xfer_mode
defined as follows:
.Bl -tag -width int_xm_target -compact
.It Va int xm_target
target for I_T Nexus
.It Va int xm_mode
bitmask of device capabilities
.It Va int xm_period
sync period
.It Va int xm_offset
sync offset
.El
.Pp
.Va xm_period
and
.Va xm_offset
shall be ignored for
.Dv ADAPTER_REQ_SET_XFER_MODE .
.Va xm_mode
holds the following bits:
.Bl -tag -width xxxxxxxx -compact
.It Dv PERIPH_CAP_SYNC
ST synchronous transfers
.It Dv PERIPH_CAP_WIDE16
ST 16 bit wide transfers
.It Dv PERIPH_CAP_WIDE32
ST 32 bit wide transfers
.It Dv PERIPH_CAP_DT
DT transfers
.It Dv PERIPH_CAP_TQING
tagged queuing
.El
Whenever the xfer mode changes, the driver should call
.Fn scsipi_async_event
to notify the mid-layer.
.El
.Pp
.Fn adapt_request
may be called from interrupt context.
.It Fn adapt_minphys
pointer to the driver's minphys function.
If the driver can handle transfers of size
.Dv MAXPHYS ,
this can point to
.Fn minphys .
.It Fn adapt_ioctl
ioctl function for the channel.
The only ioctl supported at this level is
.Dv SCBUSIORESET
for which the HBA driver shall issue a SCSI reset on the channel.
.It int Fn adapt_enable "struct device *dev" "int enable"
Disable the adapter if
.Va enable
is zero, or enable it if non-zero.
Returns 0 if operation is successful, or error from
.Pa <sys/errno.h> .
This callback is optional, and is useful mostly for hot-plug devices.
For example, this callback would power on or off
the relevant PCMCIA socket for a PCMCIA controller.
.Fn scsipi_adapter_addref
and
.Fn scsipi_adapter_delref
maintain a reference count, the enable callback is called appropriately
for the first reference and the last reference.
.It int Fn adapt_getgeom "struct scsipi_periph *periph" "struct disk_parms *params" "u_long sectors"
Optional callback, used by high-level drivers to get the fictitious geometry
used by the controller's firmware for the specified periph.
Returns 0 if successful.
See Adaptec drivers for details.
.It int Fn adapt_accesschk "struct scsipi_periph *periph" "struct scsipi_inquiry_pattern *inqbuf"
Optional callback; if present the mid-layer uses it to check if it can
attach a driver to the specified periph.
If the callback returns a non-zero value, the periph is ignored by the
.Nm
code.
This callback is used by adapters which want to drive some devices
themselves, for example hardware RAID controllers.
.It Fn scsipi_async_event "struct scsipi_channel *chan" "scsipi_async_event_t event" "void *arg"
Asynchronous event notification for the mid-layer.
.Fa event
can be one of:
.Bl -tag -width xxxxxxxx -compact
.It Dv ASYNC_EVENT_MAX_OPENINGS
set max openings for a periph.
Argument is a
.Va struct scsipi_max_openings
with at least the following members:
.Bl -tag -width xxxxxxxx -compact
.It Va int mo_target
.It Va int mo_lun
.It Va int mo_openings
.El
.Pp
Not all periphs may allow openings to increase; if not allowed the request is
silently ignored.
.It Dv ASYNC_EVENT_XFER_MODE
update the xfer mode for an I_T nexus.
Argument is a
.Va struct scsipi_xfer_mode
properly filled in.
An
.Dv ASYNC_EVENT_XFER_MODE
call with
.Dv PERIPH_CAP_TQING
set in
.Va xm_mode
is mandatory to activate tagged queuing.
.It Dv ASYNC_EVENT_RESET
channel has been reset.
No argument.
HBA drivers have to issue
.Dv ASYNC_EVENT_RESET events if they rely on the
mid-layer for SCSI CHECK CONDITION handling.
.El
.Pp
.It Fn scsipi_done "struct scsipi_xfer *xs"
shall be called by the HBA when the xfer is complete, or when it needs to
be requeued by the mid-layer.
.Va error
in the scsipi_xfer shall be set to one of the following:
.Bl -tag -width xxxxxxxx -compact
.It Dv XS_NOERROR
xfer completed without error.
.It Dv XS_SENSE
Check the returned SCSI sense for the error.
.It Dv XS_SHORTSENSE
Check the ATAPI sense for the error.
.It Dv XS_DRIVER_STUFFUP
Driver failed to perform operation.
.It Dv XS_RESOURCE_SHORTAGE
Adapter resource shortage.
The mid-layer will retry the command after some delay.
.It Dv XS_SELTIMEOUT
The device timed out while trying to send the command
.It Dv XS_TIMEOUT
The command was accepted by the device, but it didn't complete in allowed time.
.It Dv XS_BUSY
The mid-layer will check
.Va status
for additional details:
.Bl -tag -width SCSI_QUEUE_FULL -compact
.It Dv SCSI_CHECK
SCSI check condition.
The mid-layer will freeze the periph queue and issue a REQUEST SENSE command.
If the HBA supports tagged queuing, it shall remove and requeue any command
not yet accepted by the HBA (or at last make sure no more commands will
be sent to the device before the REQUEST SENSE is complete).
.It Dv SCSI_QUEUE_FULL
The mid layer will adjust the periph's openings and requeue the command.
.It Dv SCSI_BUSY
The mid-layer will requeue the xfer after delay.
.El
.It Dv XS_RESET
xfer destroyed by a reset; the mid-layer will requeue it.
.It Dv XS_REQUEUE
Ask the mid-layer to requeue this command immediately.
.El
.Pp
The adapter should not reference an
.Fa xfer
once
.Fn scsipi_done "xfer"
has been called, unless the
.Fa xfer
had
.Dv XS_CTL_POLL
set.
.Pp
.Fn scsipi_done
will call the
.Fn adapt_request
callback again only if called with
.Fa xs->error
set to
.Dv XS_NOERROR ,
and
.Fa xfer
doesn't have
.Dv XS_CTL_POLL
set.
All other error conditions are handled by a kernel thread
(once the HBA's interrupt handler has returned).
.It Fn scsipi_printaddr "struct scsipi_periph *periph"
print a kernel message with the periph's name, in the form
device(controller:channel:target:lun).
.It Fn scsipi_channel_freeze "struct scsipi_channel *chan" "int count"
Freeze the specified channel (requests are queued but not sent to HBA).
The channel's freeze counter is increased by
.Fa count .
.It Fn scsipi_channel_thaw "struct scsipi_channel *chan" "int count"
Decrement the channel's freeze counter by
.Fa count
and process the queue if the counter goes to 0.
In order to preserve command ordering, HBA drivers should not call
.Fn scsipi_channel_thaw
before calling
.Fn scsipi_done
for all commands in the HBA's queue which need to be requeued.
.It Fn scsipi_periph_timed_thaw "void *arg"
Call
.Fn scsipi_channel_thaw "arg" "1" .
Intended to be used as
.Xr callout 9
callback.
.It Fn scsipi_periph_freeze "struct scsipi_periph *periph" "int count"
.It Fn scsipi_periph_thaw "struct scsipi_periph *periph"
.It Fn scsipi_periph_timed_thaw "void *arg"
Same as the channel counterparts, but only for one specific peripheral.
.It Fn scsipi_target_detach "struct scsipi_channel *chan" "int target" "int lun" "int flags"
detach the periph associated with this I_T_L nexus.
Both
.Fa target
and
.Fa lun
may be wildcarded using the magic value -1.
.Fa flags
is passed to
.Fn config_detach ""
\&.
Returns 0 if successful, or error code if a device couldn't be removed.
.It Fn scsipi_thread_call_callback "struct scsipi_channel *chan" "void (*callback)(struct scsipi_channel *, void *)" "void *arg"
.Fn callback
will be called with
.Fa chan
and
.Fa arg
as arguments, from the channel completion thread.
The callback is run at
.Dv IPL_BIO
with the channel lock held.
.Fn scsipi_thread_call_callback
will freeze the channel by one, it's up to the caller to thaw it when
appropriate.
Returns 0 if the callback was properly recorded, or EBUSY if the
channel has already a callback pending.
.El
.Sh FILES
.Bl -tag -width sys/dev/atapiconf.h
.It Pa sys/dev/scsiconf.h
header file for use by SCSI HBA drivers
.It Pa sys/dev/atapiconf.h
header file for use by ATAPI HBA drivers
.El
.Pp
Both header files include
.Pa sys/dev/scsipiconf.h
which contains most structure definitions, function prototypes and macros.
.Sh EXAMPLES
The best examples are existing HBA drivers.
Most of them sit in the
.Pa sys/dev/ic
directory.
.Sh HISTORY
The
.Nm
interface appeared in
.Nx 1.6 .
.Sh AUTHORS
.An -nosplit
The
.Nm
interface was designed and implemented by
.An Jason R. Thorpe .
.An Manuel Bouyer
converted most drivers to the new interface.