I'm submitting following fast-track on my own behalf. This may be straddling
the boundary of what can pass for a fast-track. If members feel that this
is deserving of a full review, please don't hesitate to derail it. (I won't
take it personally. :-)
Template Version: @(#)sac_nextcase 1.64 07/13/07 SMI
This information is Copyright 2007 Sun Microsystems
1. Introduction
1.1. Project/Component Working Name:
blk2scsa
1.2. Name of Document Author/Supplier:
Author: Garrett D'Amore
1.3 Date of This Document:
14 November, 2007
4. Technical Description
Generic Block Device to SCSA Translation Layer
Functional Specification
Garrett D'Amore (gdamore at sun.com)
Nov 13, 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_hba b2s_hba_t;
The b2s_hba_t structure is an opaque structure that is used as a handle
to the emulated host bus adapter.
typedef struct b2s_target b2s_target_t;
The b2s_target_t structure is a handle to an emulated SCSI disk. It
has the following accessible members:
uint16_t target_number;
void *target_private;
const char *target_vendor;
const char *target_product;
const char *target_revision;
const char *target_serial;
uint32_t target_flags;
boolean_t (*target_request)(void *, struct b2s_request *);
The target_number field is the number to use for the emulated SCSI target.
(For example, if target_number == 1, then the emulated disk will be
addressed as cXt1d0.) Each target on an emulated HBA must have a unique
number.
The target_private field is available for the device driver's own
use, and should point to per-target state.
The target_vendor, target_product, target_revision, and target_serial
fields are ASCIIZ strings used to identify the target. 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.)
The target_flags field can contain one of two flags:
B2S_TARGET_FLAG_REMOVABLE - indicates that the target supports removable
media
B2S_TARGET_FLAG_HOTPLUGGABLE - indicates that the target can be hot
plugged (including either removal or attachment.)
The target_request field is the entry point that the device driver implements
to handle I/O requests. It is passed target_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.
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;
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_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.
Functions
---------
int b2s_hba_init(struct modlinkage *);
int b2s_hba_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_hba_t *b2s_alloc_hba(int version, dev_info_t *dip, ddi_dma_attr_t *attrp);
This allocates an initial emulated HBA structure. The version field
shall be set to B2S_VERSION_0. The dip should be the instance
structure for the device (the first argument to attach(9e).) The
attrp is a pointer to DMA attributes for the IO requests to the
device. If the device cannot support DMA, then it shall use the
value NULL for attrp.
void b2s_free_hba(b2s_hba_t *);
This frees an allocated, unattached emulated HBA structure. It will
also implicitly free any targets that are still registered with the HBA.
b2s_target_t *b2s_alloc_target(void);
This allocates an empty target structure. The driver is responsible
for populating the public members (see b2s_target_t in Types above),
before registering it.
void b2s_free_target(b2s_target_t *);
This frees an unregistered target structure.
int b2s_register_target(b2s_hba_t *hba, b2s_target_t *target);
This registers the target with the HBA. If the HBA has been attached,
this will appear to the system as an emulated hotplug attach of the
disk. It returns DDI_SUCCESS on success, DDI_FAILURE otherwise.
int b2s_unregister_target(b2s_target_t *target);
This unregisters the target from the HBA. If the HBA is attached,
then this will appear to the system as a hotplug removal of the disk.
It returns DDI_SUCCESS on success, DDI_FAILURE otherwise.
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_hba(b2s_hba_t *);
This attaches the HBA (and any registered targets) 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_hba(b2s_hba_t *);
This detaches the HBA from the system. It returns DDI_SUCCESS on success,
DDI_FAILURE otherwise.
Commands
--------
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_target Consolidation Private target structure
struct b2s_hba Consolidation Private hba structure (opaque)
struct b2s_media Consolidation Private media description
b2s_alloc_hba() Consolidation Private HBA allocation
b2s_free_hba() Consolidation Private HBA deallocation
b2s_attach_hba() Consolidation Private HBA attachment
b2s_detach_hba() Consolidation Private HBA detachment
b2s_alloc_target() Consolidation Private target allocation
b2s_free_target() Consolidation Private target deallocation
b2s_target_register() Consolidation Private target registration
b2s_target_unregister() Cons. Private target unregistration
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_hba_init() Consolidation Private modlinkage initialization
b2s_hba_fini() Condolidation Private modlinkage de-initialization
6. Resources and Schedule
6.4. Steering Committee requested information
6.4.1. Consolidation C-team Name:
ON
6.5. ARC review type: FastTrack
6.6. ARC Exposure: open