On Thu, Jan 8, 2009 at 7:10 AM, Jonathan Gray <j...@goblin.cx> wrote:

> On Thu, Jan 08, 2009 at 10:58:52AM +1100, Jonathan Gray wrote:
> > On Wed, Jan 07, 2009 at 02:49:50PM -0500, STeve Andre' wrote:
> > >    My new Thinkpad W500 has a SD slot, and stuffing a 1G card in
> > > works just fine.
> > >
> > >    I borrowed a 16G SD card, and that gives a "can't enable card"
> > > error.
> > >
> > >    I just found specs for the SD card, and wonder if the current
> > > code works with cards beyond 4G?  Or, do I have a defective 16G
> > > card? (I currently have no way to test that).  I haven't seen much
> > > in the way of discussion about this.
> >
> > This diff should let you use SDHC cards (most cards >= 4GB).
> > Let me know how it goes.
>
> Last one didn't have the change needed for block writes, try this:
>
> 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:05:53 -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:05:53 -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:
> +                       sc->sc_flags |= SMF_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 (sc->sc_flags & SMF_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 (sc->sc_flags & SMF_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:05:54 -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:05:54 -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 */
> @@ -160,6 +161,7 @@ struct sdmmc_softc {
>  #define SMF_MEM_MODE           0x0004  /* host in memory mode (SD or MMC)
> */
>  #define SMF_CARD_PRESENT       0x0010  /* card presence noticed */
>  #define SMF_CARD_ATTACHED      0x0020  /* card driver(s) attached */
> +#define SMF_SDHC               0x0040  /* High Capacity SD memory */
>        int sc_function_count;          /* number of I/O functions (SDIO) */
>        struct sdmmc_function *sc_card; /* selected card */
>        struct sdmmc_function *sc_fn0;  /* function 0, the card itself */
> @@ -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 *);
>
>

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.

Reply via email to