SDcard Stack Phase I
Functional Specification
Garrett D'Amore (gdamore@sun.com)
Nov 16, 2007
CHAPTER 1: Introduction
{{{========================}}}
One of the most popular of a growing number of digital memory formats
is the Secure Digital (SD for short) family. This format is used by
many modern cameras, MP3 players, and readers are readily found in USB
readers and on-board slots on mobile computing devices.
SD is an evolution of MultiMediaCard (MMC), and generally all SD
readers can read MMC media. (Newer media versions of the MMC have
evolved, and it is not clear at this time that MMC/SD compatibility
has been retained, although it is quite likely that at least some form
of electrical compatibility has been retained with only a need for
software changes.)
The latest SD standard also supports high capacity (>2GB) media, and
includes support for general purpose I/O devices such as 802.11
adapters, bluetooth, and even digital cameras.
SD itself specifies a bus with either one or four data pins, and some
additional control pins. All SD cards can also be used on Serial
Peripheral Interface busses, although such interfaces are not commonly
found on consumer grade equipment. (SPI is much too slow for many of
the applications for which SD technology is usually deployed.)
Note that most (all?) USB readers act as translators for SD memory
cards, making thhem appear as USB mass storage devices. Thus such
readers can normally only use memory cards.
CHAPTER 2: SDcard Stack Long Term
{{{==================================}}}
Our long term view is to provide a general purpose SD stack (SDA, for
SD Architecture), with public APIs for SD slot devices (nexus
drivers), as well as target devices for I/O peripherals.
As part of that view, we would supply a reference nexus implementation
for the most common "standard" SD slot controller (SD Standard Host
Controller, identified by PCI class 0x8 and subclass 0x5.) This is the
standard implemented by the controllers found on most modern laptops.
We would also supply a driver for the memory cards (which will not use
the same APIs as generic SD I/O peripherals, due to the very different
nature of how such devices interact with the bus) and one additional
I/O peripheral yet to be determined.
CHAPTER 3: SDcard Stack Near Term
{{{==================================}}}
We desire to get some experience with SD and get the most needed
functionality to market quickly - namely support for memory cards in
slots found on the most common laptop models. To that end, we propose
to deliver a simplified SD stack, with only the following components:
* sda - core framework
* sdhost - nexus driver for SD Standard Host Controller
* sdcard - SD memory card driver, more below
For this delivery, which we will term Phase I, we would make the nexus
driver APIs Consolidation Private. The API between the sdcard and sda
modules will always be Project Private. Later, in Phase II, we would
open up the nexus API and add leaf driver APIs.
This PSARC case only addresses Phase I.
The sdcard driver will make use of (or logically appear to do so, more
below) the blk2scsa project to appear as a SCSI-2 device with
removable media. This will allow SD memory media to participate fully
in Solaris, including support for hot insertion and removal, just like
when they are used in USB readers.
The sdcard driver itself will actually have only a tiny amount of code
in it, as instead the sda module will provide all of the core
functionality needed, including implementing the needed blk2scsa
operations. This is being done to reduce overhead and complexity that
would be caused by a "true" layered approach.
The reason that the sdcard driver exists at all (rather than allowing
sda nexus drivers to act as blk2scsa drivers themselves) is that in
the future we anticipate needing to export different nexus operations
for SDA I/O peripherals. Since a given device info can only have one
set of nexus operations (bus_ops), an additional placeholder is
required to avoid conflict.
Here's a picture of what the architecture will look like in Phase I.
+~--------------+
| pcfs mounted |
+~--------------------+ | filesystem |
| sda common module | +~--------------+
+~--------------+ +~--------------+ ^
| sda nexus |~------------| sda memory | |
+~-- | driver API | | card private | +~----------+
| +~--------------+ +~--- | API +~----------+ | sd |
| sdhost | | +~-----------| blk2scsa | ~--> | emulated |
| nexusr | +~-------+ | sdcard | +~----------+ | target 0 |
| driver | -> | SD | -> | driver | +~----------+
| | | slot | | |
+~--------+ | (bus) | +~----------+
^ +~-------+
|
+~---------+
| PCI bus |
+~---------+
CHAPTER 4: Memory Card API (Phase I)
{{{=====================================}}}
The sda module provides only two functions for the sdcard driver:
int sda_mem_init(struct modlinkage *);
int sda_mem_fini(struct modlinkage *);
The sdcard driver needs only to call these in its _init(9e) and _fini(9e)
entry points. The sdcard driver will supply an unpopulated dev_ops in its
modlinkage. The sda module will populate the dev_ops, including attach,
detach, cb_ops, and any other required supporting functions.
CHAPTER 5: Nexus Driver API (Phase I)
{{{======================================}}}
The nexus driver API is quite a bit more complex. It is provided in the
<sys/sdcard/sda.h> header file, as follows.
5.1 Types
~---------
The nexus API includes the following types.
typedef struct sda_slot sda_slot;
An opaque (to the nexus driver) handle representing an SD slot.
typedef struct sda_cmd sda_cmd_t;
This is structure represents a command to be sent to the SD card.
The SD Simplified Physical Layer Specification[1] outlines some of them.
It has the following members:
uint16_t sc_index;
The "index", or operation code, for the command. E.g. the GO_IDLE
command is 0, the APP_CMD command is 55, etc.
uint32_t sc_argument;
The command-specific argument for the command.
uint8_t sc_rtype;
The response type expected. It will be one of R1, R1b, R2, R3, R4,
R5, R5b, R6, or R7.
uint32_t sc_response[4];
The response data from the command. For R2, the 8-bit prefix is
removed, and the remaining words are stored in native byte order. For
all other response types the 8-bit prefix and 8-bit suffix are removed,
and the remaining 32-bits are stored in native order in sc_response[0].
This field is supplied by the nexus driver.
uint32_t sc_byte_count;
For commands with a data transfer phase, this is the number of bytes to
be transferred.
uint32_t sc_byte_resid;
Upon completion, the nexus driver should indicate any residual number of
bytes that were not transferred here.
uint16_t sc_block_size;
SD uses a blocking factor. This is the block size to use. (Stream
oriented commands can use a value of 1 here.) Memory commands will
generally use 512 or the native card block size here.
caddr_t sc_kvaddr;
If non-zero, then this is the starting address of a kernel buffer
for the data transfer.
uint_t sc_ndmac;
ddi_dma_cookie_t *sc_dmacs;
If sc_ndmac is non-zero, then the buffer has been prepared for DMA
already, and cookies to use are supplied here.
uint32_t sc_flags;
Flags for the operation. SDA_CMDF_READ and SDA_CMDF_WRITE indicate
the direction of any data transfer. SDA_CMDF_AUTO_CMD12 indicates that
a multi-block operation requires a CMD12 to terminate the transfer
when the transfer is complete. SDA_CMDF_POLLED indicates that polled
I/O should be used to complete the transfer, in which case the
xxx_cmd() entry point in the nexus won't return until the command
has completed.
typedef struct sda_ops sda_ops_t;
This structure is the operations vector implemented by the nexus driver.
It contains the following members.
int so_version;
Must be set to SDA_OPS_VERSION for Phase I.
int (*so_cmd)(void *private, sda_cmd_t *);
This is the main submission entry point for SD commands. The private
argument is the nexus driver's private data handle that was established
when the slot was allocated. Unless the command has SDA_CMDF_POLLED
set, the nexus driver will return immediately. Returns 0 on success,
an errno otherwise.
int (*so_getprop)(void *private, int propnum, uint32_t *valp);
int (*so_setprop)(void *private, int propnum, uint32_t val);
These two functions are used to access bus control properties for the
nexus. The following properties are defined:
SDA_PROP_INSERTED - 1 if a card is prsent in the slot, 0 otherwise
SDA_PROP_WPROTECT - 1 if the card has a write protect tab enabled,
0 otherwise.
SDA_PROP_LED - set to 1 to turn an access LED on, 0 to turn off.
SDA_PROP_CLOCK - change the bus speed, argument is given in Hz.
SDA_PROP_BUSWIDTH - set to change the bus width on the controller,
argument is eitehr 1 or 4.
SDA_PROP_OCR - the bit mask of voltages for the slot. On
read returns the set supported by teh slot. On write, a single
bit (only) sets the voltage for the slot. See [1] for
more detail on the specific bits. (sda.h defines values
OCR_35_36V, OCR_34_35V... OCR_17_18V for this purpose. The
other OCR bits (power up bit, CCS, number of functions for IO
cards) are not used with this property.
SDA_PROP_CAP_4BITS - reads as true if the nexus supports 4-bit bus
SDA_PROP_CAP_HIV - indicates the slot can operate between 2.7 and
3.6 volts.
SDA_PROP_CAP_NOPIO - indicates that the nexus never needs to access
kernel virtual memory associated with transfer buffers if the
DMA cookies are provided. (This saves the cost of a bp_mapin()
on buffers being transferred from the filesystem.)
SDA_PROP_CAP_HIGHSPEED - future expansion for high-speed clocking
SDA_PROP_CAP_8BITS - future expansion for 8-bit MMC bus
SDA_PROP_CAP_LOWV - future expansion for low voltage (1.8V) cards
SDA_PROP_CAP_INTR - future expansion for SDIO interrupt support
int (*so_poll)(void *private);
This function is used to poll the device when interrupts have been
disabled, such as when a panic() is in progress. The device must
not sleep, and should attempt to poll for completion on any outstanding
commands.
5.2 Functions
~-------------
The following funcctions are exported by SDA for the nexus driver to use:
void sda_slot_init_ops(struct dev_ops *);
void sda_slot_fini_ops(struct dev_ops *);
The sdhost driver calls these in its _init() and _fini() entry points to
populate the bus_ops entry point in the dev_ops. (There may also be
changes to update cb_ops in the future, though not for Phase I.)
sda_slot_t *sda_slot_alloc(dev_info_t *dip, int num, sda_ops_t *ops,
ddi_dma_attr_t *, void *private);
This allocates a "slot handle", and sdhost calls it once for each slot on
the instance associated with the dip. num is the slot number, normally
starting from zero, on the instance. Its used primarily in formulating
log messages and the address for leaf devices.
ops is a structure of operations that the nexus driver supports. See the
sda_ops_t description in 5.1 above.
void sda_slot_free(sda_slot_t *);
This frees a previously allocated slot structure.
void sda_slot_online(sda_slot_t *);
This marks the SD slot online, and attaches nexus devices.
int sda_slot_offline(sda_slot_t *);
This detaches the slot from the system. It returns DDI_SUCCESS on success,
DDI_FAILURE otherwise.
void sda_cmd_done(sda_cmd_t *cmd, int errno);
The nexus driver calls this when the command phase for cmd has finished.
The errno indicates the completion status of the command. Note that commands
which involve a data transfer phase or use the busy bit (response types R1b
and R5b) may have this called while the DAT lines are still active. (I.e.
the nexus driver shall not wait for the DAT lines to become idle before
calling this.)
If errno is non-zero, then the cmd will not have a data phase associated with
it.
void sda_transfer_done(sda_cmd_t *cmd, int errno);
The nexus driver calls this when a command that was making use of DAT lines
(such as a command with response type R1b or R5b, or a command with a data
transfer associated) has finished completely. The errno is non-zero if
there was any problem with the transfer (e.g. ETIMEDOUT if the operation
took too long, etc.)
void sda_slot_detect(sda_slot_t *);
This is called by the nexus driver when a card has been inserted or removed.
void sda_slot_err(sda_slot_t *slot, const char *format, ...);
void sda_slot_log(sda_slot_t *slot, const char *format, ...);
These are printf-like messaging macros. slot may be NULL. sda_slot_err
indicates an error, and will cauase cmn_err(CE_WARN, ...) to be used.
sda_slot_log is an informational message that is only sent to the system log,
and will not not be displayed on the console.
APPENDIX A: Interface Tables
{{{==============================}}}
Here are the interface tables:
Imported Interfaces
Imported Interface Stability Comments
~----------------------------------------------------------
blk2scsa Consolidation Private PSARC 2007/654
Exported Interface Stability Comments
~----------------------------------------------------------
drv/sdhost Volatile sdhost device driver name
drv/sdcard Volatile sdcard device driver name
misc/sda Consolidation Private sda common API support
sys/sdcard/sda.h Consolidation Private sda common API header
sda_mem_init() Project Private memory card API
sda_mem_fini() Project Private memory card API
sda_slot_init() Consolidation Private nexus API
sda_slot_fini() Consolidation Private nexus API
sda_slot_alloc() Consolidation Private nexus API
sda_slot_free() Consolidation Private nexus API
sda_slot_online() Consolidation Private nexus API
sda_slot_offline() Consolidation Private nexus API
sda_slot_detect() Consolidation Private nexus API
sda_cmd_done() Consolidation Private nexus API
sda_transfer_done() Consolidation Private nexus API
sda_slot_err() Consolidation Private nexus API
sda_slot_log() Consolidation Private nexus API
struct sda_slot Consolidation Private nexus API opaque slot handle
struct sda_ops Consolidation Private nexus API operations vector
struct sda_cmd Consolidation Private nexus API operations
SDA_OPS_VERSION Consolidation Private nexus API operations version
SDA_CMDF_* Consolidation Private nexus API command flags
SDA_PROP_* Consolidation Private nexus API slot properties
APPENDIX B: References
{{{=======================}}}
[1] SD Specifications Part 1: Physical Layer Simplified Specification,
Version 2.00, September 25, 2006 (www.sdcard.org)
[2] SD Specifications Part A2: SD Host Controller Simplified Specification,
Version 2.00, February 8, 2007 (www.sdcard.org)
[3] SD Specifications Part E1: SDIO Simplified Specification, Version 2.00,
February 8, 2007 (www.sdcard.org)
[4] Generic Block Device to SCSA Translation Layer, Functional Specification,
Garrett D'Amore, November 13, 2007, PSARC 2007/654