| SCSIPI(9) | Kernel Developer's Manual | SCSIPI(9) |
scsipi —
#include
<dev/scsipi/atapiconf.h>
#include <dev/scsipi/scsiconf.h>
void
scsipi_async_event(struct
scsipi_channel *chan,
scsipi_async_event_t
event, void
*arg);
void
scsipi_channel_freeze(struct
scsipi_channel *chan, int
count);
void
scsipi_channel_thaw(struct
scsipi_channel *chan, int
count);
void
scsipi_channel_timed_thaw(void
*arg);
void
scsipi_periph_freeze(struct
scsipi_periph *periph,
int count);
void
scsipi_periph_thaw(struct
scsipi_periph *periph,
int count);
void
scsipi_periph_timed_thaw(void
*arg);
void
scsipi_done(struct
scsipi_xfer *xs);
void
scsipi_printaddr(struct
scsipi_periph *periph);
int
scsipi_target_detach(struct
scsipi_channel *chan, int
target, int lun,
int flags);
int
scsipi_thread_call_callback(struct
scsipi_channel *chan,
void (*callback)(struct
scsipi_channel *, void *),
void *arg);
int
scsipi_adapter_addref(struct
scsipi_adapter *adapt);
void
scsipi_adapter_delref(struct
scsipi_adapter *adapt);
scsipi 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
scsipi layer towards the HBA layer. An HBA has to
provide a pointer to a struct scsipi_adapter and one
pointer per channel to a struct scsipi_channel. Once the
SCSI or ATAPI bus is attached, the scsipi system will
scan the bus and allocate a 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
struct scsipi_xfer.
A request is sent to the HBA driver through the
adapt_request() callback. The HBA driver signals
completion (with or without errors) of the request through
scsipi_done(). scsipi 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.
The mid-layer can also handle QUEUE FULL
and CHECK CONDITION events.
SCSIPI_ADAPT_POLL_ONLYSCSIPI_ADAPT_MPSAFEThe following callbacks should be provided through the struct scsipi_adapter:
(*adapt_request)(struct
scsipi_channel *, scsipi_adapter_req_t,
void *)(*adapt_minphys)(struct buf
*)(*adapt_ioctl)(struct
scsipi_channel *, u_long, void
*, int, struct lwp *)(*adapt_enable)(struct device
*, int)NULL if not used(*adapt_getgeom)(struct
scsipi_periph *, struct disk_parms *,
u_long)NULL if not used(*adapt_accesschk)(struct
scsipi_periph *, struct scsipi_inquiry_pattern
*)NULL if not usedThe HBA driver has to allocate and initialize to 0 one struct scsipi_channel per channel and fill in the following members:
scsipi code.SCSIPI_CHAN_OPENINGSSCSIPI_CHAN_CANGROWadapt_request() callback)SCSIPI_CHAN_NOSETTLESCSIPI_CHAN_OPENINGS flag is set)<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.The HBA driver attaches the SCSI or ATAPI bus (depending on the
setting of chan_bustype) by passing a pointer to the
struct scsipi_channel to the
autoconf(9) machinery. The
print function shall be either scsiprint() or
atapiprint().
scsipi system allocates a
struct scsipi_periph for each device probed. The
interesting fields are:
<dev/scsipi/scsipiconf.h>A SCSI or ATAPI request is passed to the HBA through a struct scsipi_xfer. The HBA driver has access to the following data:
XS_CTL_POLLXS_CTL_RESETXS_CTL_DATA_UIOXS_CTL_DATA_INXS_CTL_DATA_OUTXS_CTL_DISCOVERYXS_CTL_REQSENSEscsipi_done())scsipi_done() with a XS_TIMEOUT errorscsipi_done() for valid valuesXS_SENSE or
XS_SHORTSENSEXS_BUSY (the middle layer handles
SCSI_CHECK and
SCSI_QUEUE_FULL)(*adapt_request)(struct
scsipi_channel *chan, scsipi_adapter_req_t req,
void *arg)ADAPTER_REQ_RUN_XFERscsipi_done() with updated status and error
information.ADAPTER_REQ_GROW_RESOURCESADAPTER_REQ_SET_XFER_MODExm_period and
xm_offset shall be ignored for
ADAPTER_REQ_SET_XFER_MODE.
xm_mode holds the following bits:
PERIPH_CAP_SYNCPERIPH_CAP_WIDE16PERIPH_CAP_WIDE32PERIPH_CAP_DTPERIPH_CAP_TQINGscsipi_async_event() to notify the
mid-layer.adapt_request() may be called from
interrupt context.
adapt_minphys()MAXPHYS, this can point to
minphys().adapt_ioctl()SCBUSIORESET for which the HBA driver shall issue
a SCSI reset on the channel.adapt_enable(struct device
*dev, int enable)scsipi_adapter_addref() and
scsipi_adapter_delref() maintain a reference
count, the enable callback is called appropriately for the first reference
and the last reference.adapt_getgeom(struct
scsipi_periph *periph, struct disk_parms
*params, u_long sectors)adapt_accesschk(struct
scsipi_periph *periph, struct scsipi_inquiry_pattern
*inqbuf)scsipi code. This callback is used by adapters
which want to drive some devices themselves, for example hardware RAID
controllers.scsipi_async_event(struct
scsipi_channel *chan, scsipi_async_event_t
event, void *arg)ASYNC_EVENT_MAX_OPENINGSNot all periphs may allow openings to increase; if not allowed the request is silently ignored.
ASYNC_EVENT_XFER_MODEASYNC_EVENT_XFER_MODE call with
PERIPH_CAP_TQING set in
xm_mode is mandatory to activate tagged
queuing.ASYNC_EVENT_RESETASYNC_EVENT_RESET events if they rely on the
mid-layer for SCSI CHECK CONDITION handling.scsipi_done(struct scsipi_xfer
*xs)XS_NOERRORXS_SENSEXS_SHORTSENSEXS_DRIVER_STUFFUPXS_RESOURCE_SHORTAGEXS_SELTIMEOUTXS_TIMEOUTXS_BUSYSCSI_CHECKSCSI_QUEUE_FULLSCSI_BUSYXS_RESETXS_REQUEUEThe adapter should not reference an xfer
once scsipi_done(xfer) has
been called, unless the xfer had
XS_CTL_POLL set.
scsipi_done() will call the
adapt_request() callback again only if called
with xs->error set to
XS_NOERROR, and xfer
doesn't have XS_CTL_POLL set. All other error
conditions are handled by a kernel thread (once the HBA's interrupt
handler has returned).
scsipi_printaddr(struct
scsipi_periph *periph)scsipi_channel_freeze(struct
scsipi_channel *chan, int count)scsipi_channel_thaw(struct
scsipi_channel *chan, int count)scsipi_channel_thaw() before calling
scsipi_done() for all commands in the HBA's queue
which need to be requeued.scsipi_periph_timed_thaw(void
*arg)scsipi_channel_thaw(arg,
1). Intended to be used as
callout(9) callback.scsipi_periph_freeze(struct
scsipi_periph *periph, int count)scsipi_periph_thaw(struct
scsipi_periph *periph)scsipi_periph_timed_thaw(void
*arg)scsipi_target_detach(struct
scsipi_channel *chan, int target,
int lun, int flags)config_detach() . Returns
0 if successful, or error code if a device couldn't be removed.scsipi_thread_call_callback(struct
scsipi_channel *chan, void (*callback)(struct
scsipi_channel *, void *), void *arg)callback() will be called with
chan and arg as arguments,
from the channel completion thread. The callback is run at
IPL_BIO with the channel lock held.
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.Both header files include sys/dev/scsipiconf.h which contains most structure definitions, function prototypes and macros.
scsipi interface appeared in NetBSD
1.6.
scsipi interface was designed and implemented by
Jason R. Thorpe. Manuel Bouyer
converted most drivers to the new interface.
| November 20, 2016 | NetBSD 9.0 |