SDHI_driver patch (mbedOS 5.11.5)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SDHIBlockDevice.cpp Source File

SDHIBlockDevice.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2012 ARM Limited
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020  * SOFTWARE.
00021  */
00022  
00023 #if (defined(TARGET_VK_RZ_A1H) || defined(TARGET_VK_RZ_A1LU))
00024  
00025 #include "SDHIBlockDevice.h"
00026 #include "mbed_debug.h"
00027 #include <errno.h>
00028 
00029 #include "iodefine.h"
00030 #include "PeripheralPins.h"
00031 
00032 /* Required version: 5.6.1 and above */
00033 #ifdef MBED_MAJOR_VERSION
00034 #if (MBED_VERSION < MBED_ENCODE_VERSION(5,6,1))
00035 #error "Incompatible mbed-os version detected! Required 5.5.4 and above"
00036 #endif
00037 #else
00038 #warning "mbed-os version 5.6.1 or above required"
00039 #endif
00040 
00041 
00042 
00043 //#define SD_COMMAND_TIMEOUT                       5000   /*!< Timeout in ms for response */
00044 //#define SD_CMD0_GO_IDLE_STATE_RETRIES            5      /*!< Number of retries for sending CMDO */
00045 #define SD_CMD_TRACE                             0      /*!< 1 - Enable SD command tracing */
00046 
00047 //#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK        -5001    /*!< operation would block */
00048 #define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED        -5002  /*!< unsupported operation */
00049 #define SD_BLOCK_DEVICE_ERROR_PARAMETER          -5003  /*!< invalid parameter */
00050 #define SD_BLOCK_DEVICE_ERROR_NO_INIT            -5004  /*!< uninitialized */
00051 #define SD_BLOCK_DEVICE_ERROR_NO_DEVICE          -5005  /*!< device is missing or not connected */
00052 #define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED    -5006  /*!< write protected */
00053 #define SD_BLOCK_DEVICE_ERROR_UNUSABLE           -5007  /*!< unusable card */
00054 #define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE        -5008  /*!< No response from device */
00055 #define SD_BLOCK_DEVICE_ERROR_CRC                -5009  /*!< CRC error */
00056 #define SD_BLOCK_DEVICE_ERROR_ERASE              -5010  /*!< Erase error: reset/sequence */
00057 #define SD_BLOCK_DEVICE_ERROR_WRITE              -5011  /*!< SPI Write error: !SPI_DATA_ACCEPTED */
00058 
00059 #define BLOCK_SIZE_HC                            512    /*!< Block size supported for SD card is 512 bytes  */
00060 #define WRITE_BL_PARTIAL                         0      /*!< Partial block write - Not supported */
00061 //
00062 // Types
00063 #define SDCARD_NONE              0           /**< No card is present */
00064 #define SDCARD_V1                1           /**< v1.x Standard Capacity */
00065 #define SDCARD_V2                2           /**< v2.x Standard capacity SD card */
00066 #define SDCARD_V2HC              3           /**< v2.x High capacity SD card */
00067 #define CARD_UNKNOWN             4           /**< Unknown or unsupported card */
00068 
00069 /* R3 Response : OCR Register */
00070 #define OCR_HCS_CCS             (0x1 << 30)
00071 #define OCR_LOW_VOLTAGE         (0x01 << 24)
00072 #define OCR_3_3V                (0x1 << 20)
00073 
00074 #define ESD_SECTOR_SIZE         BLOCK_SIZE_HC
00075 
00076 #define REG_CSD_HACK
00077 
00078 #define CSD_CID_LENGTH        16
00079 
00080 #define ARRAYSIZE(arr)  (size_t)(sizeof(arr)/sizeof(arr[0]))
00081 
00082 static uint32_t _sd_workbuf[SD_SIZE_OF_INIT/ sizeof(uint32_t)] __attribute__ ((section ("NC_BSS")));
00083 static uint32_t _sd_rw_buf[ESD_SECTOR_SIZE/sizeof(uint32_t)] __attribute__ ((section ("NC_BSS")));
00084 //static uint8_t  _sectorBuff[ESD_SECTOR_SIZE] __attribute__ ((section ("NC_BSS")));
00085 
00086 
00087 static uint32_t ext_bits(unsigned char *data, size_t datasize, unsigned int msb, unsigned int lsb) {
00088     uint32_t bits = 0;
00089 
00090     if ((datasize > 0) && (msb < (datasize<<3)))
00091     {
00092         uint32_t size = 1 + msb - lsb;
00093         for (uint32_t i = 0; i < size; i++)
00094         {
00095             uint32_t position = lsb + i;
00096             int32_t byte = (datasize-1) - (position >> 3);
00097             if( byte < 0 )
00098                 break;
00099             uint32_t bit = position & 0x7;
00100             uint32_t value = (data[byte] >> bit) & 1;
00101             bits |= value << i;
00102         }
00103     }
00104     return bits;
00105 }
00106 
00107 #if SDHI_DBG
00108 const sderr_t SDHIBlockDevice::_sd_error_msg[]= {
00109         {"SD_OK",                       0},        /* OK */
00110         {"SD_ERR",                     -1},        /* general error */
00111         {"SD_ERR_WP",                  -2},        /* write protect error */
00112         {"SD_ERR_RO",                  -3},        /* read only error */
00113         {"SD_ERR_RES_TOE",             -4},        /* response time out error */
00114         {"SD_ERR_CARD_TOE",            -5},        /* card time out error */
00115         {"SD_ERR_END_BIT",             -6},        /* end bit error */
00116         {"SD_ERR_CRC",                 -7},        /* CRC error */
00117         {"SD_ERR_CARD_RES",            -8},        /* card response error */
00118         {"SD_ERR_HOST_TOE",            -9},        /* host time out error */
00119         {"SD_ERR_CARD_ERASE",         -10},        /* card erase error */
00120         {"SD_ERR_CARD_LOCK",          -11},        /* card lock error */
00121         {"SD_ERR_CARD_UNLOCK",        -12},        /* card unlock error */
00122         {"SD_ERR_HOST_CRC",           -13},        /* host CRC error */
00123         {"SD_ERR_CARD_ECC",           -14},        /* card internal ECC error */
00124         {"SD_ERR_CARD_CC",            -15},        /* card internal error */
00125         {"SD_ERR_CARD_ERROR",         -16},        /* unknown card error */
00126         {"SD_ERR_CARD_TYPE",          -17},        /* non support card type */
00127         {"SD_ERR_NO_CARD",            -18},        /* no card */
00128         {"SD_ERR_ILL_READ",           -19},        /* illegal buffer read */
00129         {"SD_ERR_ILL_WRITE",          -20},        /* illegal buffer write */
00130         {"SD_ERR_AKE_SEQ",            -21},        /* the sequence of authentication process */
00131         {"SD_ERR_OVERWRITE",          -22},        /* CID/CSD overwrite error */
00132     /* 23-29 */
00133         {"SD_ERR_CPU_IF",             -30},        /* target CPU interface function error  */
00134         {"SD_ERR_STOP",               -31},        /* user stop */
00135     /* 32-49 */
00136         {"SD_ERR_CSD_VER",            -50},        /* CSD register version error */
00137         {"SD_ERR_SCR_VER",            -51},        /* SCR register version error */
00138         {"SD_ERR_FILE_FORMAT",        -52},        /* CSD register file format error  */
00139         {"SD_ERR_NOTSUP_CMD",         -53},        /* not supported command  */
00140     /* 54-59 */
00141         {"SD_ERR_ILL_FUNC",           -60},        /* invalid function request error */
00142         {"SD_ERR_IO_VERIFY",          -61},        /* direct write verify error */
00143         {"SD_ERR_IO_CAPAB",           -62},        /* IO capability error */
00144     /* 63-69 */
00145         {"SD_ERR_IFCOND_VER",         -70},        /* Interface condition version error */
00146         {"SD_ERR_IFCOND_VOLT",        -71},        /* Interface condition voltage error */
00147         {"SD_ERR_IFCOND_ECHO",        -72},        /* Interface condition echo back pattern error */
00148     /* 73-79 */
00149         {"SD_ERR_OUT_OF_RANGE",       -80},        /* the argument was out of range */
00150         {"SD_ERR_ADDRESS_ERROR",      -81},
00151         {"SD_ERR_BLOCK_LEN_ERROR",    -82},
00152         {"SD_ERR_ILLEGAL_COMMAND",    -83},
00153         {"SD_ERR_RESERVED_ERROR18",   -84},
00154         {"SD_ERR_RESERVED_ERROR17",   -85},
00155         {"SD_ERR_CMD_ERROR",          -86},
00156         {"SD_ERR_CBSY_ERROR",         -87},
00157         {"SD_ERR_NO_RESP_ERROR",      -88},
00158     /* 89 */
00159     /* 90-95 */
00160         {"SD_ERR_ERROR",              -96},
00161         {"SD_ERR_FUNCTION_NUMBER",    -97},
00162         {"SD_ERR_COM_CRC_ERROR",      -98},
00163         {"SD_ERR_INTERNAL",           -99},        /* driver software internal error */
00164 };
00165 
00166 #endif
00167 
00168 SDHIBlockDevice::SDHIBlockDevice(uint32_t sdport)
00169 {
00170     _init_ref_count = 0;
00171     Initialize(sdport);
00172 //    for( uint32_t n=0; n < ARRAYSIZE(_sd_error_msg); n++ )
00173 //    {
00174 //      _sd_err_map[_sd_error_msg[n].errorno] = _sd_error_msg[n].msg;
00175 //    }
00176 //
00177 //    if ( sdport < SDHI_COUNT )
00178 //    {
00179 //      _sd_channel = sdport;
00180 //      _regbase = (uint32_t)((_sd_channel == 0ul) ? &SDHI0 : &SDHI1);
00181 //
00182 //      _card_type = SDCARD_NONE;
00183 //
00184 //      // Set default to 100kHz for initialisation and 1MHz for data transfer
00185 //      _init_sck = 100000;
00186 //      _transfer_sck = hz;
00187 //
00188 //      // Only HC block size is supported.
00189 //      _block_size = BLOCK_SIZE_HC;
00190 //      _erase_size = BLOCK_SIZE_HC;
00191 //      _mtx_lock = false;
00192 //
00193 //      int32_t sd_err = sd_init( _sd_channel, _regbase, &_sd_workbuf[0], SD_CD_SOCKET );
00194 //      if ( sd_err != SD_OK)
00195 //      {
00196 //          _error(sd_err);
00197 ////            return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
00198 //      }
00199 //
00200 //      void *rw_buff = (void *)&_sd_rw_buf[0];
00201 //
00202 //      sd_err = sd_set_buffer( _sd_channel, rw_buff, (unsigned long)sizeof(_sd_rw_buf) );
00203 //      if ( sd_err != SD_OK )
00204 //      {
00205 //          _error(sd_err);
00206 //      }
00207 //
00208 //    }
00209 //    else
00210 //    {
00211 //      _sd_channel = -1;
00212 //      _regbase = 0ul;
00213 //
00214 //    }
00215 }
00216 
00217 SDHIBlockDevice::SDHIBlockDevice(PinName sd_CLK, PinName sd_CMD, PinName sd_CD, PinName sd_WP,
00218                                  PinName sd_D0, PinName sd_D1, PinName sd_D2, PinName sd_D3 )
00219 {
00220     _init_ref_count = 0;
00221 
00222     uint32_t sd_wp  = pinmap_peripheral(sd_WP, PinMap_SDHI_WP);
00223     uint32_t sd_cd  = pinmap_peripheral(sd_CD, PinMap_SDHI_CD);
00224     uint32_t sd_clk = pinmap_peripheral(sd_CLK, PinMap_SDHI_CLK);
00225     uint32_t sd_cmd = pinmap_peripheral(sd_CMD, PinMap_SDHI_CMD);
00226     uint32_t sd_d0  = pinmap_peripheral(sd_D0, PinMap_SDHI_D0);
00227     uint32_t sd_d1  = pinmap_peripheral(sd_D1, PinMap_SDHI_D1);
00228     uint32_t sd_d2  = pinmap_peripheral(sd_D2, PinMap_SDHI_D2);
00229     uint32_t sd_d3  = pinmap_peripheral(sd_D3, PinMap_SDHI_D3);
00230 
00231     uint32_t sd_cntl_1 = pinmap_merge(sd_wp, sd_cd);
00232     uint32_t sd_cntl_2 = pinmap_merge(sd_clk, sd_cmd);
00233     uint32_t sd_cntl = pinmap_merge(sd_cntl_1, sd_cntl_2);
00234 
00235     uint32_t sd_data_1 = pinmap_merge(sd_d0, sd_d1);
00236     uint32_t sd_data_2 = pinmap_merge(sd_d2, sd_d3);
00237     uint32_t sd_data = pinmap_merge(sd_data_1, sd_data_2);
00238 
00239     uint32_t sdport = pinmap_merge(sd_cntl, sd_data);
00240 
00241     MBED_ASSERT((int)sdport != NC);
00242 
00243     Initialize(sdport);
00244 }
00245 
00246 
00247 
00248 SDHIBlockDevice::~SDHIBlockDevice()
00249 {
00250     if (_is_initialized) {
00251         deinit();
00252     }
00253 }
00254 
00255 void SDHIBlockDevice::Initialize( uint32_t sdport )
00256 {
00257 #if SDHI_DBG
00258     for( uint32_t n=0; n < ARRAYSIZE(_sd_error_msg); n++ )
00259     {
00260         _sd_err_map[_sd_error_msg[n].errorno] = _sd_error_msg[n].msg;
00261     }
00262 #endif
00263     _sectors = 0;
00264     _is_initialized = 0;
00265     if ( sdport < SDHI_COUNT )
00266     {
00267         _sd_channel = sdport;
00268         _regbase = (uint32_t)((_sd_channel == SDHI_0) ? &SDHI0 : &SDHI1);
00269 
00270         _card_type = SDCARD_NONE;
00271 
00272         // Only HC block size is supported.
00273         _block_size = BLOCK_SIZE_HC;
00274         _erase_size = BLOCK_SIZE_HC;
00275 
00276         int32_t sd_err = sd_init( _sd_channel, _regbase, &_sd_workbuf[0], SD_CD_SOCKET );
00277         if ( sd_err != SD_OK)
00278         {
00279             _error(sd_err);
00280         }
00281 
00282         void *rw_buff = (void *)&_sd_rw_buf[0];
00283 
00284         sd_err = sd_set_buffer( _sd_channel, rw_buff, (unsigned long)sizeof(_sd_rw_buf) );
00285         if ( sd_err != SD_OK )
00286         {
00287             _error(sd_err);
00288         }
00289     }
00290     else
00291     {
00292         _sd_channel = -1;
00293         _regbase = 0ul;
00294 
00295     }
00296 
00297 }
00298 
00299 int SDHIBlockDevice::_initialise_card()
00300 {
00301     // Detail debugging is for commands
00302     _dbg = SDHI_DBG ? SD_CMD_TRACE : 0;
00303 
00304     int32_t status = BD_ERROR_OK;
00305 
00306     int32_t sd_err;
00307 
00308     if( _regbase )
00309     {
00310         sd_err = sd_mount(_sd_channel, SDCFG_DRIVER_MODE, SD_VOLT_3_3);
00311 
00312         if ( sd_err != SD_OK )
00313         {
00314             _error(sd_err);
00315             return SD_BLOCK_DEVICE_ERROR_UNUSABLE;
00316         }
00317         uint8_t    card_type;
00318         uint8_t    card_speed;
00319         uint8_t    card_capa;
00320 
00321         sd_err=sd_get_type(_sd_channel, &card_type, &card_speed, &card_capa);
00322         if( sd_err != SD_OK)
00323         {
00324             return _error(sd_err);
00325         }
00326 
00327         if( (card_type & SD_MEDIA_SD) != SD_MEDIA_SD )
00328         {
00329             return SD_BLOCK_DEVICE_ERROR_UNUSABLE;
00330         }
00331 
00332         uint32_t regOCR;
00333         uint8_t regCID[CSD_CID_LENGTH];
00334         uint8_t regCSD[CSD_CID_LENGTH];
00335         uint8_t regDSR[2];
00336         uint8_t regSCR[8];
00337 
00338         sd_err = sd_get_reg(_sd_channel, (uint8_t *)&regOCR, regCID, regCSD, regDSR, regSCR);
00339         if (sd_err != SD_OK)
00340         {
00341             return _error(sd_err);
00342         }
00343         regOCR = __REV(regOCR);
00344         // Check if card supports voltage range: 3.3V
00345         if (!(regOCR & OCR_3_3V)) {
00346             _card_type = CARD_UNKNOWN;
00347             status = SD_BLOCK_DEVICE_ERROR_UNUSABLE;
00348             return status;
00349         }
00350     }
00351     else
00352     {
00353         status = SD_BLOCK_DEVICE_ERROR_NO_INIT;
00354     }
00355 
00356     return status;
00357 }
00358 
00359 
00360 int SDHIBlockDevice::init()
00361 {
00362     vMutex l(&_mutex);
00363 
00364     if(!_is_initialized)
00365         _init_ref_count = 0;
00366 
00367     _init_ref_count++;
00368 
00369     if(_init_ref_count != 1)
00370         return BD_ERROR_OK;
00371 
00372     int err = _initialise_card();
00373     _is_initialized = (err == BD_ERROR_OK);
00374     if (!_is_initialized) {
00375         debug_if(SDHI_DBG, "Fail to initialize card\n");
00376         return err;
00377     }
00378     debug_if(SDHI_DBG, "init card = %d\r\n", _is_initialized);
00379     _sectors = _sd_sectors();
00380 
00381     if (0 == _sectors) {
00382         return BD_ERROR_DEVICE_ERROR;
00383     }
00384 
00385     return BD_ERROR_OK;
00386 }
00387 
00388 int SDHIBlockDevice::deinit()
00389 {
00390     vMutex l(&_mutex);
00391 
00392     if(!_is_initialized)
00393         _init_ref_count = 0;
00394 
00395     _init_ref_count--; //!!!
00396 
00397     if(_init_ref_count)
00398         return BD_ERROR_OK;
00399 
00400     _sectors = 0;
00401     if ( _is_initialized )
00402     {
00403         sd_unmount(_sd_channel);
00404         debug_if(SDHI_DBG, "card deinited![%d]\r\n", _is_initialized);
00405         _is_initialized = false;
00406     }
00407     return 0;
00408 }
00409 
00410 
00411 int SDHIBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
00412 {
00413     if (!is_valid_program(addr, size)) {
00414         return SD_BLOCK_DEVICE_ERROR_PARAMETER;
00415     }
00416 
00417     vMutex l(&_mutex);
00418 
00419     if (!_is_initialized) {
00420         return SD_BLOCK_DEVICE_ERROR_NO_INIT;
00421     }
00422 
00423     uint8_t* buffer = const_cast<uint8_t*>(static_cast<const uint8_t*>(b));
00424     int status = BD_ERROR_OK;
00425 
00426     // Get block count
00427     bd_addr_t blockCnt = size / _block_size;
00428 
00429     addr = addr / _block_size;
00430 
00431     // Send command to perform write operation
00432     int32_t sd_err = sd_write_sect( _sd_channel, buffer, addr, blockCnt, SD_WRITE_OVERWRITE);
00433 
00434     if (sd_err != SD_OK)
00435     {
00436         _error(sd_err);
00437         status = SD_BLOCK_DEVICE_ERROR_WRITE;
00438     }
00439 
00440     return status;
00441 }
00442 
00443 int SDHIBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
00444 {
00445     if (!is_valid_read(addr, size)) {
00446         return SD_BLOCK_DEVICE_ERROR_PARAMETER;
00447     }
00448 
00449     vMutex l(&_mutex);
00450 
00451     if (!_is_initialized) {
00452         return SD_BLOCK_DEVICE_ERROR_NO_INIT;
00453     }
00454     uint8_t *buffer = static_cast<uint8_t*>(b);
00455     int status = BD_ERROR_OK;
00456     bd_addr_t blockCnt =  size / _block_size;
00457 
00458     addr = addr / _block_size;
00459 
00460     int32_t sd_err = sd_read_sect(_sd_channel, buffer, addr, blockCnt);
00461 
00462     if (sd_err != SD_OK)
00463     {
00464         _error(sd_err);
00465         status = SD_BLOCK_DEVICE_ERROR_NO_RESPONSE;
00466     }
00467 
00468     return status;
00469 }
00470 
00471 int SDHIBlockDevice::erase(bd_addr_t addr, bd_size_t size)
00472 {
00473     return 0;
00474 }
00475 
00476 
00477 bool SDHIBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size)
00478 {
00479     return (
00480         addr % _erase_size == 0 &&
00481         size % _erase_size == 0 &&
00482         addr + size <= this->size());
00483 }
00484 
00485 int SDHIBlockDevice::trim(bd_addr_t addr, bd_size_t size)
00486 {
00487     if (!_is_valid_trim(addr, size)) {
00488         return SD_BLOCK_DEVICE_ERROR_PARAMETER;
00489     }
00490 
00491     vMutex l(&_mutex);
00492 
00493     if (!_is_initialized) {
00494         return SD_BLOCK_DEVICE_ERROR_NO_INIT;
00495     }
00496     int status = BD_ERROR_OK;
00497 
00498     size -= _block_size;
00499     // SDSC Card (CCS=0) uses byte unit address
00500     // SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit)
00501     if (SDCARD_V2HC == _card_type) {
00502         size = size / _block_size;
00503         addr = addr / _block_size;
00504     }
00505 
00506     return status;
00507 }
00508 
00509 bd_size_t SDHIBlockDevice::get_read_size() const
00510 {
00511     return _block_size;
00512 }
00513 
00514 bd_size_t SDHIBlockDevice::get_program_size() const
00515 {
00516     return _block_size;
00517 }
00518 
00519 /*
00520 bd_size_t SDHIBlockDevice::get_erase_size() const
00521 {
00522     return _block_size;
00523 }
00524 */
00525 
00526 bd_size_t SDHIBlockDevice::size() const
00527 {
00528     return _block_size*_sectors;
00529 }
00530 
00531 void SDHIBlockDevice::debug(bool dbg)
00532 {
00533     _dbg = dbg;
00534 }
00535 
00536 const char *SDHIBlockDevice::get_type() const
00537 {
00538     return "RZ-SDHI";
00539 }
00540 
00541 // PRIVATE FUNCTIONS
00542 
00543 bd_size_t SDHIBlockDevice::_sd_sectors() {
00544     uint32_t c_size, c_size_mult, read_bl_len;
00545     uint32_t block_len, mult, blocknr;
00546     uint32_t hc_c_size;
00547     bd_size_t blocks = 0, capacity = 0;
00548     uint8_t csd[CSD_CID_LENGTH];
00549 
00550     int32_t sd_err = sd_get_reg(_sd_channel, NULL, NULL, csd, NULL, NULL);
00551     if ( sd_err != SD_OK )
00552     {
00553         debug_if(SDHI_DBG, "Couldn't read csd response from disk\r\n");
00554         _error(sd_err);
00555         return 0;
00556     }
00557     for(int i = 0; i < (CSD_CID_LENGTH-1); i++)
00558     {
00559         csd[i] = csd[i+1];
00560     }
00561 
00562     debug_if(SDHI_DBG,"CSD is ");
00563     for(unsigned int i = 0; i < sizeof(csd); i++)
00564     {
00565         debug_if(SDHI_DBG, "%02X ", csd[i]);
00566     }
00567     debug_if(SDHI_DBG,"\r\n");
00568 
00569     // csd_structure : csd[127:126]
00570     int csd_structure = ext_bits(csd, CSD_CID_LENGTH, 127, 126);
00571     switch (csd_structure) {
00572         case 0:
00573             c_size = ext_bits(csd, CSD_CID_LENGTH, 73, 62);              // c_size        : csd[73:62]
00574             c_size_mult = ext_bits(csd, CSD_CID_LENGTH, 49, 47);         // c_size_mult   : csd[49:47]
00575             read_bl_len = ext_bits(csd, CSD_CID_LENGTH, 83, 80);         // read_bl_len   : csd[83:80] - the *maximum* read block length
00576             block_len = 1 << read_bl_len;                // BLOCK_LEN = 2^READ_BL_LEN
00577             mult = 1 << (c_size_mult + 2);               // MULT = 2^C_SIZE_MULT+2 (C_SIZE_MULT < 8)
00578             blocknr = (c_size + 1) * mult;               // BLOCKNR = (C_SIZE+1) * MULT
00579             capacity = blocknr * block_len;              // memory capacity = BLOCKNR * BLOCK_LEN
00580             blocks = capacity / _block_size;
00581             debug_if(SDHI_DBG, "Standard Capacity: c_size: %lu\r\n", c_size);
00582             debug_if(SDHI_DBG, "Sectors: 0x%llx : %llu\r\n", blocks, blocks);
00583             debug_if(SDHI_DBG, "Capacity: 0x%llx : %llu MB\r\n", capacity, (capacity/(1024U*1024U)));
00584 
00585             // ERASE_BLK_EN = 1: Erase in multiple of 512 bytes supported
00586             if (ext_bits(csd, CSD_CID_LENGTH, 46, 46)) {
00587                 _erase_size = BLOCK_SIZE_HC;
00588             } else {
00589                 // ERASE_BLK_EN = 1: Erase in multiple of SECTOR_SIZE supported
00590                 _erase_size = BLOCK_SIZE_HC * (ext_bits(csd, CSD_CID_LENGTH, 45, 39) + 1);
00591             }
00592             break;
00593 
00594         case 1:
00595             hc_c_size = ext_bits(csd, CSD_CID_LENGTH, 69, 48);            // device size : C_SIZE : [69:48]
00596             blocks = (hc_c_size+1) << 10;                 // block count = C_SIZE+1) * 1K byte (512B is block size)
00597             debug_if(SDHI_DBG, "SDHC/SDXC Card: hc_c_size: %lu\r\n", hc_c_size);
00598             debug_if(SDHI_DBG, "Sectors: 0x%llx : %llu\r\n", blocks, blocks);
00599             debug_if(SDHI_DBG, "Capacity: %llu MB\r\n", (blocks/(2048U)));
00600             // ERASE_BLK_EN is fixed to 1, which means host can erase one or multiple of 512 bytes.
00601             _erase_size = BLOCK_SIZE_HC;
00602             break;
00603 
00604         default:
00605             debug_if(SDHI_DBG, "CSD struct unsupported\r\n");
00606             return 0;
00607     };
00608     return blocks;
00609 }
00610 
00611 const char * SDHIBlockDevice::_sderr_msg(int32_t errorno)
00612 {
00613 #if SDHI_DBG
00614     map<int32_t, const char *>::iterator it = _sd_err_map.find(errorno);
00615 
00616     if ( it != _sd_err_map.end() )
00617         return it->second;
00618     else
00619         return "SD UNKNWON ERROR NO\n";
00620 #else
00621     return (const char *)0;
00622 #endif
00623 }
00624 
00625 int SDHIBlockDevice::_error(int32_t errcode)
00626 {
00627     int32_t sd_err = errcode;
00628     if(_sd_channel >= 0 && _sd_channel < SDHI_COUNT )
00629     {
00630         int32_t err = sd_get_error(_sd_channel);
00631         if ( err != SD_OK)
00632             sd_err = err;
00633         debug_if(SDHI_DBG, _sderr_msg(sd_err));
00634     }
00635     return sd_err;
00636 }
00637 
00638 #endif