Updated: 2022/Sep/29

Please read Privacy Policy. It's for your privacy.


SCSIPI(9)                  Kernel Developer's Manual                 SCSIPI(9)

NAME
     scsipi - SCSI/ATAPI middle-layer interface

SYNOPSIS
     #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);

DESCRIPTION
     The 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.

   INITIALISATION
     An HBA driver has to allocate and initialize to 0 a struct scsipi_adapter
     and fill in the following members:
           struct device *adapt_dev  pointer to the HBA's struct device
           int adapt_nchannels       number of channels (or busses) of the
                                     adapter
           int adapt_openings        total number of commands the adapter can
                                     handle (may be replaced by chan_openings,
                                     see below)
           int adapt_max_periph      number of commands the adapter can handle
                                     per device
           int adapt_flags           adapter properties
                                     SCSIPI_ADAPT_POLL_ONLY  the HBA can't do
                                                             interrupts
                                     SCSIPI_ADAPT_MPSAFE     don't acquire the
                                                             kernel lock when
                                                             doing HBA
                                                             callbacks

     The following callbacks should be provided through the struct
     scsipi_adapter:
           void (*adapt_request)(struct scsipi_channel *,
                             scsipi_adapter_req_t, void *)
                             mandatory
           void (*adapt_minphys)(struct buf *)
                             mandatory
           int (*adapt_ioctl)(struct scsipi_channel *, u_long, void *, int,
                             struct lwp *)
                             optional
           int (*adapt_enable)(struct device *, int)
                             optional, set to NULL if not used
           int (*adapt_getgeom)(struct scsipi_periph *, struct disk_parms *,
                             u_long)
                             optional, set to NULL if not used
           int (*adapt_accesschk)(struct scsipi_periph *, struct
                             scsipi_inquiry_pattern *)
                             optional, set to NULL if not used

     The HBA driver has to allocate and initialize to 0 one struct
     scsipi_channel per channel and fill in the following members:
           struct scsipi_adapter *chan_adapter
                                  Pointer to the HBA's struct scsipi_adapter
           struct scsipi_bustype *chan_bustype
                                  should be initialized to either bus_atapi or
                                  bus_scsi, both defined in the scsipi code.
           int chan_channel       channel number (starting at 0)
           int chan_flags         channel flags:
                                  SCSIPI_CHAN_OPENINGS  Use per-channel max
                                                        number of commands
                                                        chan_openings instead
                                                        of per-adapter
                                                        adapt_openings
                                  SCSIPI_CHAN_CANGROW   This channel can grow
                                                        its chan_openings or
                                                        adapt_openings on
                                                        request (via the
                                                        adapt_request()
                                                        callback)
                                  SCSIPI_CHAN_NOSETTLE  Do not wait SCSI_DELAY
                                                        seconds for devices to
                                                        settle before probing
                                                        (usually used by
                                                        adapters that provide
                                                        an "abstracted" view
                                                        of the bus).
           int chan_openings      total number of commands the adapter can
                                  handle for this channel (used only if the
                                  SCSIPI_CHAN_OPENINGS flag is set)
           chan_max_periph        number of commands per device the adapter
                                  can handle on this channel (used only if the
                                  SCSIPI_CHAN_OPENINGS flag is set)
           int chan_ntargets      number of targets
           int chan_nluns         number of LUNs per target
           int chan_id            adapter's ID on this channel
           int chan_defquirks     default device quirks.  Quirks are defined
                                  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.

     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().

   OTHER DATA STRUCTURES
     When scanning the bus, the scsipi system allocates a struct scsipi_periph
     for each device probed.  The interesting fields are:
           struct device *periph_dev
                                pointer to the device's struct device
           struct scsipi_channel *periph_channel
                                pointer to the channel the device is connected
                                to
           int periph_quirks    device quirks, defined in
                                <dev/scsipi/scsipiconf.h>
           int periph_target    target ID, or drive number on ATAPI
           int periph_lun       LUN (currently not used on ATAPI)

     A SCSI or ATAPI request is passed to the HBA through a struct
     scsipi_xfer.  The HBA driver has access to the following data:
           struct callout xs_callout
                           callout for adapter use, usually for command
                           timeout
           int xs_control  control flags (only flags of interest for HBA
                           drivers are described):
                           XS_CTL_POLL       poll in the HBA driver for
                                             request completion (most likely
                                             because interrupts are disabled)
                           XS_CTL_RESET      reset the device
                           XS_CTL_DATA_UIO   xs_data points to a struct uio
                                             buffer
                           XS_CTL_DATA_IN    data is transferred from HBA to
                                             memory
                           XS_CTL_DATA_OUT   data is transferred from memory
                                             to HBA
                           XS_CTL_DISCOVERY  this xfer is part of a device
                                             discovery done by the middle
                                             layer
                           XS_CTL_REQSENSE   xfer is a request sense

           int xs_status   status flags:
                           XS_STS_DONE     xfer is done (set by scsipi_done())
                           XS_STS_PRIVATE  mask of flags reserved for HBA's
                                           use (0xf0000000)

           struct scsipi_periph *xs_periph
                           periph doing the xfer
           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
                           scsipi_done() with a XS_TIMEOUT error
           struct scsipi_generic *cmd
                           scsipi command to execute
           int cmdlen      len (in bytes) of the cmd buffer
           u_char *data    data buffer (this is either a DMA or uio address)
           int datalen     data length (in bytes, zero if uio)
           int resid       difference between datalen and how much data was
                           really transferred
           scsipi_xfer_result_t error
                           error value returned by the HBA driver to mid-
                           layer.  See description of scsipi_done() for valid
                           values
           union {struct scsipi_sense_data scsi_sense; uint32_t atapi_sense;}
                           sense
                           where to store sense info if error is XS_SENSE or
                           XS_SHORTSENSE
           uint8_t status  SCSI status; checked by middle layer when error is
                           XS_BUSY (the middle layer handles SCSI_CHECK and
                           SCSI_QUEUE_FULL)
           uint8_t xs_tag_type
                           SCSI tag type, set to 0 if untagged command
           uint8_t xs_tag_id
                           tag ID, used for tagged commands

   FUNCTIONS AND CALLBACKS
     (*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.
               req can be one of:
               ADAPTER_REQ_RUN_XFER
                         request the adapter to send a command to the device.
                         arg is a pointer to the struct scsipi_xfer.  Once the
                         xfer is complete the HBA driver shall call
                         scsipi_done() with updated status and error
                         information.
               ADAPTER_REQ_GROW_RESOURCES
                         ask the adapter to increase resources of the channel
                         (grow adapt_openings or chan_openings) if possible.
                         Support of this feature is optional.  This request is
                         called from the kernel completion thread.  arg must
                         be ignored.
               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.
                         arg points to a struct scsipi_xfer_mode defined as
                         follows:
                         int xm_target  target for I_T Nexus
                         int xm_mode    bitmask of device capabilities
                         int xm_period  sync period
                         int xm_offset  sync offset

                         xm_period and xm_offset shall be ignored for
                         ADAPTER_REQ_SET_XFER_MODE.  xm_mode holds the
                         following bits:
                         PERIPH_CAP_SYNC
                                   ST synchronous transfers
                         PERIPH_CAP_WIDE16
                                   ST 16 bit wide transfers
                         PERIPH_CAP_WIDE32
                                   ST 32 bit wide transfers
                         PERIPH_CAP_DT
                                   DT transfers
                         PERIPH_CAP_TQING
                                   tagged queuing
                         Whenever the xfer mode changes, the driver should
                         call scsipi_async_event() to notify the mid-layer.

               adapt_request() may be called from interrupt context.
     adapt_minphys()
               pointer to the driver's minphys function.  If the driver can
               handle transfers of size MAXPHYS, this can point to minphys().
     adapt_ioctl()
               ioctl function for the channel.  The only ioctl supported at
               this level is SCBUSIORESET for which the HBA driver shall issue
               a SCSI reset on the channel.
     int adapt_enable(struct device *dev, int enable)
               Disable the adapter if enable is zero, or enable it if non-
               zero.  Returns 0 if operation is successful, or error from
               <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.
               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.
     int 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.
     int 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
               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)
               Asynchronous event notification for the mid-layer.  event can
               be one of:
               ASYNC_EVENT_MAX_OPENINGS
                         set max openings for a periph.  Argument is a struct
                         scsipi_max_openings with at least the following
                         members:
                         int mo_target
                         int mo_lun
                         int mo_openings

                         Not all periphs may allow openings to increase; if
                         not allowed the request is silently ignored.
               ASYNC_EVENT_XFER_MODE
                         update the xfer mode for an I_T nexus.  Argument is a
                         struct scsipi_xfer_mode properly filled in.  An
                         ASYNC_EVENT_XFER_MODE call with PERIPH_CAP_TQING set
                         in xm_mode is mandatory to activate tagged queuing.
               ASYNC_EVENT_RESET
                         channel has been reset.  No argument.  HBA drivers
                         have to issue ASYNC_EVENT_RESET events if they rely
                         on the mid-layer for SCSI CHECK CONDITION handling.

     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.  error in the
               scsipi_xfer shall be set to one of the following:
               XS_NOERROR
                         xfer completed without error.
               XS_SENSE  Check the returned SCSI sense for the error.
               XS_SHORTSENSE
                         Check the ATAPI sense for the error.
               XS_DRIVER_STUFFUP
                         Driver failed to perform operation.
               XS_RESOURCE_SHORTAGE
                         Adapter resource shortage.  The mid-layer will retry
                         the command after some delay.
               XS_SELTIMEOUT
                         The device timed out while trying to send the command
               XS_TIMEOUT
                         The command was accepted by the device, but it didn't
                         complete in allowed time.
               XS_BUSY   The mid-layer will check status for additional
                         details:
                         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).
                         SCSI_QUEUE_FULL  The mid layer will adjust the
                                          periph's openings and requeue the
                                          command.
                         SCSI_BUSY        The mid-layer will requeue the xfer
                                          after delay.
               XS_RESET  xfer destroyed by a reset; the mid-layer will requeue
                         it.
               XS_REQUEUE
                         Ask the mid-layer to requeue this command
                         immediately.

               The 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)
               print a kernel message with the periph's name, in the form
               device(controller:channel:target:lun).
     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 count.
     scsipi_channel_thaw(struct scsipi_channel *chan, int count)
               Decrement the channel's freeze counter by count and process the
               queue if the counter goes to 0.  In order to preserve command
               ordering, HBA drivers should not call 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)
               Call 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)
               Same as the channel counterparts, but only for one specific
               peripheral.
     scsipi_target_detach(struct scsipi_channel *chan, int target, int lun,
               int flags)
               detach the periph associated with this I_T_L nexus.  Both
               target and lun may be wildcarded using the magic value -1.
               flags is passed to 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.

FILES
     sys/dev/scsiconf.h   header file for use by SCSI HBA drivers

     sys/dev/atapiconf.h  header file for use by ATAPI HBA drivers

     Both header files include sys/dev/scsipiconf.h which contains most
     structure definitions, function prototypes and macros.

EXAMPLES
     The best examples are existing HBA drivers.  Most of them sit in the
     sys/dev/ic directory.

HISTORY
     The scsipi interface appeared in NetBSD 1.6.

AUTHORS
     The scsipi interface was designed and implemented by Jason R. Thorpe.
     Manuel Bouyer converted most drivers to the new interface.

NetBSD 10.99                   November 20, 2016                  NetBSD 10.99