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 *);

Reply via email to