On Thu, Jan 08, 2009 at 09:32:47AM -0500, Dan Colish wrote: > > The latest patch works great for me. I was not able to write disklabels with > the prior patch, probably due to the block write code missing. As soon as I > get the card up, I'll post some i/o benchmarks.
Well it's an SD card, don't expect miracles. Here is a bonus revised revised patch that lets you use SD cards after SDHC cards by storing the flag state in a better card specific state structure. I'd appreciate it if people testing this stuff could test on a range of SDHC and normal cards and tell me what size cards/ which controllers they are testing against. Thanks Index: sdmmc.c =================================================================== RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v retrieving revision 1.16 diff -u -p -r1.16 sdmmc.c --- sdmmc.c 2 Dec 2008 23:49:54 -0000 1.16 +++ sdmmc.c 8 Jan 2009 12:49:43 -0000 @@ -569,6 +569,32 @@ sdmmc_go_idle_state(struct sdmmc_softc * } /* + * Send the "SEND_IF_COND" command, to check operating condition + */ +int +sdmmc_send_if_cond(struct sdmmc_softc *sc, uint32_t card_ocr) +{ + struct sdmmc_command cmd; + uint8_t pat = 0x23; + uint8_t res; + + bzero(&cmd, sizeof cmd); + + cmd.c_opcode = SD_SEND_IF_COND; + cmd.c_arg = ((card_ocr & SD_OCR_VOL_MASK) != 0) << 8 | pat; + cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R7; + + if (sdmmc_mmc_command(sc, &cmd) != 0) + return 1; + + res = cmd.c_resp[0]; + if (res != pat) + return 1; + else + return 0; +} + +/* * Retrieve (SD) or set (MMC) the relative card address (RCA). */ int Index: sdmmc_mem.c =================================================================== RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v retrieving revision 1.9 diff -u -p -r1.9 sdmmc_mem.c --- sdmmc_mem.c 2 Dec 2008 23:49:54 -0000 1.9 +++ sdmmc_mem.c 8 Jan 2009 12:49:43 -0000 @@ -93,6 +93,9 @@ sdmmc_mem_enable(struct sdmmc_softc *sc) /* Tell the card(s) to enter the idle state (again). */ sdmmc_go_idle_state(sc); + if (sdmmc_send_if_cond(sc, card_ocr) == 0) + host_ocr |= SD_OCR_SDHC_CAP; + /* Send the new OCR value until all cards are ready. */ if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) { DPRINTF(("%s: can't send memory OCR\n", SDMMCDEVNAME(sc))); @@ -224,14 +227,23 @@ sdmmc_decode_csd(struct sdmmc_softc *sc, * specification version 1.0 - 1.10. (SanDisk, 3.5.3) */ csd->csdver = SD_CSD_CSDVER(resp); - if (csd->csdver != SD_CSD_CSDVER_1_0) { + switch (csd->csdver) { + case SD_CSD_CSDVER_2_0: + sf->flags |= SFF_SDHC; + csd->capacity = SD_CSD_V2_CAPACITY(resp); + csd->read_bl_len = SD_CSD_V2_BL_LEN; + break; + case SD_CSD_CSDVER_1_0: + csd->capacity = SD_CSD_CAPACITY(resp); + csd->read_bl_len = SD_CSD_READ_BL_LEN(resp); + break; + default: printf("%s: unknown SD CSD structure version 0x%x\n", SDMMCDEVNAME(sc), csd->csdver); return 1; + break; } - csd->capacity = SD_CSD_CAPACITY(resp); - csd->read_bl_len = SD_CSD_READ_BL_LEN(resp); } else { csd->csdver = MMC_CSD_CSDVER(resp); if (csd->csdver != MMC_CSD_CSDVER_1_0 && @@ -403,7 +415,10 @@ sdmmc_mem_read_block(struct sdmmc_functi cmd.c_blklen = sf->csd.sector_size; cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ? MMC_READ_BLOCK_MULTIPLE : MMC_READ_BLOCK_SINGLE; - cmd.c_arg = blkno << 9; + if (sf->flags & SFF_SDHC) + cmd.c_arg = blkno; + else + cmd.c_arg = blkno << 9; cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1; error = sdmmc_mmc_command(sc, &cmd); @@ -458,7 +473,10 @@ sdmmc_mem_write_block(struct sdmmc_funct cmd.c_blklen = sf->csd.sector_size; cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ? MMC_WRITE_BLOCK_MULTIPLE : MMC_WRITE_BLOCK_SINGLE; - cmd.c_arg = blkno << 9; + if (sf->flags & SFF_SDHC) + cmd.c_arg = blkno; + else + cmd.c_arg = blkno << 9; cmd.c_flags = SCF_CMD_ADTC | SCF_RSP_R1; error = sdmmc_mmc_command(sc, &cmd); Index: sdmmcreg.h =================================================================== RCS file: /cvs/src/sys/dev/sdmmc/sdmmcreg.h,v retrieving revision 1.3 diff -u -p -r1.3 sdmmcreg.h --- sdmmcreg.h 18 Mar 2007 22:21:21 -0000 1.3 +++ sdmmcreg.h 8 Jan 2009 12:49:44 -0000 @@ -38,6 +38,7 @@ /* SD commands */ /* response type */ #define SD_SEND_RELATIVE_ADDR 3 /* R6 */ +#define SD_SEND_IF_COND 8 /* R7 */ /* SD application commands */ /* response type */ #define SD_APP_SET_BUS_WIDTH 6 /* R1 */ @@ -66,6 +67,9 @@ #define MMC_OCR_1_7V_1_8V (1<<5) #define MMC_OCR_1_6V_1_7V (1<<4) +#define SD_OCR_SDHC_CAP (1<<30) +#define SD_OCR_VOL_MASK 0xFF8000 /* bits 23:15 */ + /* R1 response type bits */ #define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */ #define MMC_R1_APP_CMD (1<<5) /* app. commands supported */ @@ -134,6 +138,7 @@ /* SD R2 response (CSD) */ #define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2) #define SD_CSD_CSDVER_1_0 0 +#define SD_CSD_CSDVER_2_0 1 #define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8) #define SD_CSD_TAAC_1_5_MSEC 0x26 #define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8) @@ -150,6 +155,9 @@ #define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12) #define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \ (SD_CSD_C_SIZE_MULT((resp))+2)) +#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22) +#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10) +#define SD_CSD_V2_BL_LEN 0x9 /* 512 */ #define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3) #define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3) #define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3) Index: sdmmcvar.h =================================================================== RCS file: /cvs/src/sys/dev/sdmmc/sdmmcvar.h,v retrieving revision 1.12 diff -u -p -r1.12 sdmmcvar.h --- sdmmcvar.h 2 Dec 2008 23:49:54 -0000 1.12 +++ sdmmcvar.h 8 Jan 2009 12:49:44 -0000 @@ -98,6 +98,7 @@ struct sdmmc_command { #define SCF_RSP_R5 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) #define SCF_RSP_R5B (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX|SCF_RSP_BSY) #define SCF_RSP_R6 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) +#define SCF_RSP_R7 (SCF_RSP_PRESENT|SCF_RSP_CRC|SCF_RSP_IDX) int c_error; /* errno value on completion */ /* Host controller owned fields for data xfer in progress */ @@ -135,6 +136,7 @@ struct sdmmc_function { u_int16_t rca; /* relative card address */ int flags; #define SFF_ERROR 0x0001 /* function is poo; ignore it */ +#define SFF_SDHC 0x0002 /* SD High Capacity card */ SIMPLEQ_ENTRY(sdmmc_function) sf_list; /* SD card I/O function members */ int number; /* I/O function number or -1 */ @@ -200,6 +202,7 @@ void sdmmc_go_idle_state(struct sdmmc_so int sdmmc_select_card(struct sdmmc_softc *, struct sdmmc_function *); int sdmmc_set_relative_addr(struct sdmmc_softc *, struct sdmmc_function *); +int sdmmc_send_if_cond(struct sdmmc_softc *, uint32_t); void sdmmc_intr_enable(struct sdmmc_function *); void sdmmc_intr_disable(struct sdmmc_function *);