Edward Pilatowicz wrote:
> will the /devices/ paths for blk2scsa devices use generic names
> or will the /devices paths contain driver names?
>
> an example of a generic name (for a usb disk device) is:
>       /devices/pci at 0,0/pci104d,81e6 at 1d,7/storage at 3/disk at 0,0:g
>
> an example of a non-generic name (for an ata disk device) is:
>       /devices/pci at 0,0/pci-ide at 1f,2/ide at 0/cmdk at 0,0:h
>   

The portion of the path that blk2scsa controls will use generic 
names.    Actually, I'm using scsi_hba_nodename_compatible_get() to 
generate both the nodename and the compatible names.  (Originally I 
started out with just "disk" for the node name and "sd" for the 
compatible name hardcoded, but a comment from Joerg Schilling convinced 
me that it might be better to offer the other SCSI bindings so that 
folks could associate a driver other than "sd" with a blk2scsa device if 
they really wanted to.)

    -- Garrett


> ed
>
> On Tue, Nov 27, 2007 at 12:50:09AM -0800, Garrett D'Amore wrote:
>   
>> I've found in the course of trying to add support for hotplug properly
>> to the blk2scsa driver, that some changes to the API were necessary.
>> While here, I made some other aesthetic changes which are easy to do
>> now, but would require more annoying casework later.
>>
>> A full updated spec is attached.
>>
>> The main differences here relative to the first spec are:
>>
>> * b2s_hba renamed to b2s_nexus
>> * b2s_target renamed to b2s_leaf
>> * structure passed for nexus allocation, instead of array of pointers
>> * request entry point associated with nexus structure instead of leaf
>> * addition of target and lun members to request structure
>> * support for non-zero lun numbers (multiple luns per target)
>> * inquiry data now handled via separate request command, rather than at
>> registration
>> * no separate allocation/deallocation for leaf structure, done by leaf
>> attach/detach automatically (possibly deferred for hotplug safety).
>>
>> I'm extending the case timer another week to allow for the extra review
>> required.  Sorry, for the late changes, but thanks!
>>
>>
>> Generic Block Device to SCSA Translation Layer
>> Functional Specification
>>
>> Garrett D'Amore (gdamore at sun.com)
>> Nov 27, 2007
>>
>>
>> CHAPTER 1:  Introduction
>>
>> There are an ever growing number of digital memory formats, as well as
>> other kinds of storage media in the market today.  Historically, Solaris
>> has had only limited support for most of them, when connected through a
>> USB or IEEE 1394 media reader.
>>
>> Modern laptops and mobile computing devices are now shipping with slots
>> for these readers that are not connected via USB interfaces.  Solaris needs
>> needs to provide support for media in these slots in a manner similar to
>> how they are presented via USB.
>>
>> Writing a full block device driver is one possible way, but, unfortunately,
>> it also means implementing a number of components besides the block
>> driver itself, as various userland components exist (such as libsmedia)
>> which only know how to talk to certain block devices.
>>
>> The sd(7d) device driver is the most common mass storage block driver, and
>> it is also how most removable media is presented to the system.  Therefore,
>> it already has most of the hooks necessary to support userland volume
>> management, format and VTOC management, etc.
>>
>> Unfortunately, sd(7d) expects to be able to talk to a SCSI disk.  Busses
>> such as USB and IEEE1394 often present mass storage using some subset of
>> the SCSI command set, so combined with thin translation layers such as
>> scsa1394 or scsa2usb, it is possible to emulate a SCSI bus sufficiently
>> that these mass storage devices are usable with sd(7d).
>>
>> Many of the intersting media formats, however, do not use any form of SCSI
>> command set.  Sometimes the access method is quite different, even though
>> the underlying media is still typically block-oriented.
>>
>>
>> CHAPTER 2:  blk2scsa translation layer
>>
>> Our solution to this problem involves the creation of a new kernel/misc
>> module, blk2scsa.  This module provides some straight-forward underlying
>> APIs for block-oriented drivers to implement, and maps those APIs to an
>> emulated SCSI bus and one or more emulated SCSI disk drives, so that these
>> devices are now usable with sd(7d).
>>
>> This frees the block device driver from needing to implement most of the
>> labeling, ioctl, or other complex portions of the block device and instead
>> focus on just the core device access functionality.
>>
>> In a sample system, imagine a block device driver called "nvflash".  This
>> device driver has two independent flash chips per instance, each of which
>> is block oriented using 512 byte blocks, and can have a separate filesystem
>> on it.  The plumbing might look like this:
>>
>>
>> +----------+
>> |  nvflash |
>> |  driver  |
>> |    +----------+      +----------------+        +--------------+
>> +----+    blk2scsa |----> | (emulated bus) | -+---> | sd, target 0 |
>>      +----------+      +----------------+  |     +--------------+
>>                               |
>>                        |     +--------------+
>>                        +---> | sd, target 1 |
>>                              +--------------+
>>
>> In the diagram above, the flash chips would be addressable as
>> /dev/{rdsk,dsk}/cXt0d0 and /dev/{rdsk,dsk}/cXt1d0.
>>
>> Note that the actual flash chips could be removable (perhaps as if they
>> were slots on a physical media reader), and the sd driver would handle
>> them properly.  This would include automatic volume manager support
>> by userland components, so that when a device is inserted it is
>> automatically
>> mounted and presented in a desktop GNOME session, for example.
>>
>> The emulated HBA will support auto-sense-request (cannot be disabled),
>> and emulated targets will support the removable and hotpluggable properties
>> if they were registered with them.
>>
>>
>> CHAPTER 3:  Programming Interface
>> =================================
>>
>> The following API is provided for target devices.
>>
>> Basic setup
>> -----------
>>
>>  The device driver shall #include <sys/scsi/adapters/blk2scsa.h>
>>
>>  The device driver shall add -N misc/blk2scsa to its link line, so
>>  that the run-time kernel loader can resolve the sybmols
>>  appropriately.
>>
>>
>> Types
>> -----
>>
>> typedef struct b2s_nexus b2s_nexus_t;
>>
>>  The b2s_nexus_t structure is an opaque structure that is used as a handle
>>  to the emulated host bus adapter.
>>
>> typedef struct b2s_leaf b2s_leaf_t;
>>
>>  The b2s_leaf_t structure is an opaque structure that is used as a handle
>>  to the emulated disk device.
>>
>> typedef struct b2s_nexus_info b2s_nexus_info_t;
>>
>>  The b2s_nexus_info structure describes the nexus device that should be
>>  allocated.  It has the following members:
>>
>>      int         nexus_version;
>>      dev_info_t     *nexus_dip;
>>      void           *nexus_private;
>>      ddi_dma_attr_t *nexus_dma_attr;
>>      boolean_t         (*nexus_request)(void *, struct b2s_request *);
>>
>>  The nexus_version field is used for versioning, and represents the version
>>  of the API that the device driver is coded for.  It must be B2S_VERSION_0
>>  in this specification.
>>
>>  The nexus_dip is the device node associated with the driver.
>>
>>  The nexus_private field is available for the device driver's own
>>  use, and should point to nexus state.
>>
>>  The nexus_dma_attr is the DMA attributes describing the DMA
>> capabilities of
>>  the driver.  It may be NULL if the driver is incapable of DMA.
>>
>>  The nexus_request field is the entry point that the device driver
>> implements
>>  to handle I/O requests.  It is passed nexus_private as its first argument.
>>  The second argument describes the request in further detail.  If the
>> driver
>>  handles the request (or queues it for handling), then it must return
>>  B_TRUE.  If the driver is unwilling to accept the request, but a future
>>  attempt might be successful, then it should return B_FALSE.  Please see
>>  the description for b2s_request_t below.
>>
>> typedef b2s_leaf_info b2s_leaf_info_t;
>>
>>  The b2s_leaf_info structure describes a leaf device (emulated SCSI
>>  disk) that should be attached to the system.  It has the following
>>  members:
>>
>>      uint_t      leaf_target;
>>      uint_t      leaf_lun;
>>      uint32_t      leaf_flags;
>>      const char  *leaf_unique_id;
>>
>>      uint32_t      target_flags;
>>      boolean_t      (*target_request)(void *, struct b2s_request *);
>>
>>  The leaf_target and leaf_lun fields are target and lun numbers to
>>  use for the emulated SCSI target.  (For example, the disk device node
>>  /dev/dsk/cXtYdZs2, the leaf_target is represented by Y, and the leaf_lun
>>  is represented by Z.)  The combination of these two fields must be unique
>>  for a given leaf node.
>>
>>  The leaf_unique_id field is an ASCIIZ string containing a string that
>>  uniquely identifies the device.  The system uses this to protect against
>>  incorrect hotplug operations.  (I.e. insertion of a different leaf target
>>  at the specified SCSI address, while the previous leaf was still open
>>  by another consumer.)  It may be used in the formulation of device
>>  identifiers and GUIDs as well.
>>
>>  The leaf_flags field can contain one of two flags:
>>
>>      B2S_LEAF_REMOVABLE - indicates that the leaf supports removable
>>      media
>>
>>      B2S_LEAF_HOTPLUGGABLE - indicates that the leaf can be hot
>>      plugged (including either removal or attachment.)
>>
>> typedef struct b2s_request b2s_request_t;
>>
>>  This structure is the fundamental handle used for tracking I/O requests
>>  between the SCSA layer and the device driver.  It has the following
>>  accessible members:
>>
>>      int        br_cmd;
>>      uint64_t        br_lba;
>>      uint64_t        br_nblks;
>>      b2s_media_t    br_media;
>>      b2s_inquiry_t    br_inquiry;
>>      uint32_t        br_flags;
>>
>>  The br_cmd field is the command code for the operation.  See Commands
>>  below for a full explanation.  This field is supplied by the blk2scsa.
>>
>>  The br_lba field is the logical block address associated with the request.
>>  It will be supplied by the blk2scsa framework.  It is only valid when the
>>  br_cmd field is B2S_CMD_READ or B2S_CMD_WRITE.
>>
>>  The br_nblks is the number of logical blocks for the request.  It will be
>>  supplied by the blk2scsa framework.  It is only valid when the br_cmd
>> field
>>  is B2S_CMD_READ or B2S_CMD_WRITE.
>>
>>  The br_media field is a description of the media for the target.  It is
>>  filled out by the driver in response to a B2S_CMD_GETMEDIA request.
>>  See the description of b2s_media_t below.
>>
>>
>>  The br_inquiry field contains inquiry data for the target, to be filled
>>  out by the device driver in response to a B2S_CMD_INQUIRY request.
>>  See the description of b2s_inquiry_t below.
>>
>>  The br_flags field is a bitfield of flags associated the request.  The
>>  public flags, which are read-only supplied by the framework, are
>>
>>      B2S_REQUEST_FLAG_POLL - indicates that a synchronous request without
>>      use of interrupts should be performed.  (Such as when sync()'ing
>>      filesystems or performing a crash dump in response to a panic.)
>>
>>      B2S_REQUEST_FLAG_HEAD - indicates that the request should be placed at
>>      the head of any queue, if possible.
>>
>>      B2S_REQUEST_FLAG_LOAD_EJECT - only valid with the B2S_CMD_STOP or
>>      B2S_CMD_START commands, it indicates that the media should either be
>>      loaded (B2S_CMD_START) or ejected (B2S_CMD_STOP) if possible.
>>
>>      B2S_REQUEST_FLAG_IMMED - if present, indicates that the driver should
>>      not wait for the operation to complete on the device before returning
>>      status with b2s_request_done().  It is only valid with the commands
>>      B2S_CMD_FORMAT, B2S_CMD_START, and B2S_CMD_STOP commands.
>>
>> typedef struct b2s_media b2s_media_t;
>>
>>  This structure is used in response to B2S_CMD_GETMEDIA.  The device driver
>>  shall supply information about the media  in the following fields:
>>
>>      uint64_t media_blksz;
>>      uint64_t media_nblks;
>>      uint64_t media_flags;
>>
>>  The media_blksz and media_nblks fields are used to report the size and
>> total
>>  number of logical blocks on the device.
>>
>>  The media_flags bit field can have the flag B2S_MEDIA_FLAG_READ_ONLY
>> set to
>>  indicate that the media loaded in the target is not writable.
>>
>> typedef struct b2s_inquiry b2s_inquiry_t;
>>
>>  This structure is used in rsponse to B2S_CMD_INQUIRY.  The device driver
>>  shall set the following fields for data to include in a standard SCSI
>>  inquiry:
>>
>>      const char *inq_vendor;
>>      const char *inq_product;
>>      const char *inq_revision;
>>      const char *inq_serial;
>>
>>  The inq_vendor, inq_product, inq_revision, and inq_serial
>>  fields are ASCIIZ strings used to identify the device.  Note that this
>>  is for the target, and not for any removable media that may be present
>>  in the target.  These strings are used to formulate the response to
>>  SCSI inquiries, so if the device driver is able to, it should use
>>  values that are suitable for SCSI-2.  (See ANSI X3.131-1994 for more
>>  information.)  Note that the driver need not pad these strings with
>> spaces.
>>
>>
>> Functions
>> ---------
>>
>> int b2s_mod_init(struct modlinkage *);
>> int b2s_mod_fini(struct modlinkage *);
>>
>>  These routines are called at _init and _fini respectively, to set up
>>  and clean up HBA related entries in the device driver's dev_ops field.
>>  As a consquence, a blk2scsa dependent driver need not supply any cb_ops
>>  or bus_ops structure on its own behalf.
>>
>> b2s_nexus_t *b2s_alloc_nexus(b2s_nexus_info_t *);
>>
>>  This allocates an initial emulated HBA structure, using the supplied
>>  information.
>>
>> void b2s_free_nexus(b2s_nexus_t *);
>>
>>  This frees an unattached emulated HBA structure.
>>
>> b2s_leaf_t *b2s_attach_leaf(b2s_nexus_t *, b2s_leaf_info_t *);
>>
>>  This indicates that a leaf (disk) device has been physically
>>  attached to the nexus (HBA).  Appropriate hotplug actions will be
>>  performed to make the device accessible, if possible.  It returns
>>  an opaque handle to the leaf on success, or NULL on failure.
>>
>> void b2s_detach_leaf(b2s_leaf_t *leaf);
>>
>>  This indicates that a leaf device has been physically detached from
>>  the nexus, and exists solely to support hotplug operation.
>>
>> void b2s_request_mapin(b2s_request_t *req, caddr_t *addrp, size_t *lenp);
>>
>>  This ensures that the buffer associated with the request is mapped into
>>  kernel address space, and returns the address and length of the buffer
>>  associated with the request.
>>
>> void b2s_request_dma(b2s_request_t *req, uint_t *num, ddi_dma_cookie_t **c);
>>
>>  This returns the number of DMA cookies associated with the request, and
>>  a pointer to an array of the actual cookies.  Note that requests are
>>  pre-mapped by the framework if a suitable DMA attribute was supplied at
>>  registration time.  Note also that the buffer will always be fully mapped.
>>  That is, it will never be necessary for a driver to use ddi_dma_getwin().
>>
>> void b2s_request_done(b2s_request_t *req, int errno, size_t resid);
>>
>>  This is called by the driver when it has completed processing for a
>> request.
>>  The errno takes an error code (see Error Codes below), and the resid
>>  indicates the number of residual bytes that were not transferred.
>>
>> int b2s_attach_nexus(b2s_nexus_t *);
>>
>>  This attaches the HBA (and any registered leaves) to the system.  The
>>  target driver should call this as part of its attach(9e) processing.  It
>>  return DDI_SUCCESS on success, DDI_FAILURE otherwise.
>>
>> int b2s_detach_nexus(b2s_nexus_t *);
>>
>>  This detaches the HBA from the system.  It returns DDI_SUCCESS on success,
>>  DDI_FAILURE otherwise.
>>
>>
>> Commands
>> --------
>>
>> B2S_CMD_INQUIRY
>>
>>  This command is sent to the driver to retrieve a description of the
>>  device in response to a SCSI inquiry.  The driver shall provide the
>> details
>>  in the br_inquiry field of the associated request.
>>
>> B2S_CMD_GETMEDIA
>>
>>  This command is sent to the driver to retrieve a description of the
>>  media currently loaded.  The driver shall provide the details in the
>>  br_media field of the associated request.
>>
>> B2S_CMD_START
>>
>>  This command is used to initialize the device for use.  If the
>>  B2S_REQUEST_FLAG_LOAD_EJECT is also present, then the device shall
>>  load any removable media, if possible.
>>
>> B2S_CMD_STOP
>>
>>  This command is used to cease use of the device. (At this point the
>>  device may be powered down.)  If the B2S_REQUEST_FLAG_LOAD_EJECT is
>>  present, then the device should attempt to eject any removable media.
>>  This command also implictly includes the effects of B2S_CMD_SYNC.
>>
>> B2S_CMD_LOCK
>> B2S_CMD_UNLOCK
>>
>>  These commands are used to engage or release any locking mechanism
>>  preventing removal of the media.
>>
>> B2S_CMD_READ
>> B2S_CMD_WRITE
>>
>>  These commands read or write blocks to/from the device.  The block address
>>  to start at is indicated by the br_lba field of the request.  The number
>>  of blocks to transfer is indicated by the br_nblks field.   The actual
>>  data region can be determined using either the b2s_request_mapin() or
>>  b2s_request_dma() functions (depending on whether or not DMA is to be
>> used.)
>>
>> B2S_CMD_FORMAT
>>
>>  This command formats the media.  It shall not be possible to format media
>>  while a reservation set with B2S_CMD_RESERVE is in effect.  No defect
>>  list is supplied, so the driver is responsible to take whatever action
>>  it deems appropriate.  If the B2S_REQUEST_FLAG_IMMED is set, then the
>>  device should not wait for the format to complete before calling
>>  b2s_request_done().
>>
>> B2S_CMD_SYNC
>>
>>  This command flushes any cached write data from the device to media.
>>
>>
>> Errors
>> ------
>>
>> The following error codes can be returned in response to a request using
>> b2s_request_done().
>>
>> B2S_EOK
>>
>>  No error.  The operation completed successfully.
>>
>> B2S_ENOTSUP
>>
>>  The device does not support the requested operation.  (This should be
>>  returned, if the device does not have a door lock, for example.)
>>
>> B2S_EFORMATTING
>>
>>  An attempt to access the device while it was formatting was made.
>>
>> B2S_ENOMEDIA
>>
>>  No media is present in a target with removable media.
>>
>> B2S_EMEDIACHG
>>
>>  The media may have changed since the last request was made.  This is
>>  used to prevent accidental overwrites to changed media.
>>
>> B2S_ESTOPPED
>>
>>  The target has not been started with B2S_CMD_START yet.
>>
>> B2S_EHARDWARE
>>
>>  An unknown hardware error occurred.
>>
>> B2S_ENODEV
>>
>>  The target is not present or has been removed.
>>
>> B2S_EMEDIA
>>
>>  An error on the medium occurred.
>>
>> B2S_EDOORLOCK
>>
>>  The B2S_CMD_STOP failed to eject the media, because the doorlock was
>>  engaged.
>>
>> B2S_EWPROTECT
>>
>>  The media could not be written to because it is not writable.
>>
>> B2S_EBLKADDR
>>
>>  The supplied LBA block address was invalid.
>>
>> B2S_ESTARTING
>>
>>  The target is still starting up.  Try agin later.
>>
>> B2S_EIO
>>
>>  Generic failure.
>>
>> B2S_ERSVD
>>
>>  Target reserved.  (Internal use only.)
>>
>> B2S_EPARM
>>
>>  Bad parameter occurred in the SCSI packet.  (Internal use only.)
>>
>> B2S_EBADMSG
>>
>>  Invalid SCSI message presented to driver.  (Internal use only.)
>>
>> B2S_EINVAL
>>
>>  An invalid parameter was present in the SCSI packet.  (Internal use only.)
>>
>>
>> CHAPER 4:  Interface Table
>> ==========================
>>
>>  Imported Interface    Level            Comments
>>
>>  SCSI-2        Committed        ANSI X1.131-1994
>>  scsi_hba_tran        Committed        SCSI HBA API
>>  scsi_pkt2bp()        Consolidation Private
>>
>>
>>  Exported Interface    Level            Comments
>>
>>  sys/scsi/adapters/blk2scsa.h    Cons. Private    blk2scsa header
>>
>>  misc/blk2scsa        Consolidation Private    kernel module
>>  B2S_CMD_*        Consolidation Private    request command codes
>>  B2S_E*        Consolidation Private    request error codes
>>  B2S_REQUEST_FLAG_*    Consolidation Private    request flags
>>  B2S_VERSION_0      Consolidation Private    API versioning
>>
>>  struct b2s_request    Consolidation Private    request structure
>>  struct b2s_leaf    Consolidation Private    leaf (disk) structure (opaque)
>>  struct b2s_nexus    Consolidation Private    nexus (hba) structure
>> (opaque)
>>  struct b2s_leaf_info  Consolidation Private   leaf (disk) attach
>> information
>>  struct b2s_nexus_info Consolidation Private   nexus (hba) registration
>>  struct b2s_media    Consolidation Private    media description
>>  struct b2s_inquiry    Consolidation Private   SCSI inquiry data
>>
>>  b2s_alloc_nexus()    Consolidation Private    nexus (hba) allocation
>>  b2s_free_nexus()    Consolidation Private    nexus (hba) deallocation
>>  b2s_attach_nexus()    Consolidation Private    nexus (hba) attachment
>>  b2s_detach_nexus()    Consolidation Private    nexus (hba) detachment
>>
>>  b2s_attach_leaf()    Consolidation Private    leaf (disk) connection
>>  b2s_detach_leaf()    Consolidation Private    leaf (disk) disconnection
>>
>>  b2s_request_mapin()    Consolidation Private    request buffer PIO access
>>  b2s_request_dma()    Consolidation Private    request buffer DMA access
>>  b2s_request_done()    Consolidation Private    request buffer completion
>>
>>  b2s_mod_init()    Consolidation Private    modlinkage initialization
>>  b2s_mod_fini()    Condolidation Private    modlinkage de-initialization
>>     


Reply via email to