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 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