Date: Sat, 2 Jun 2012 19:11:45 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r236479 - stable/9/sys/dev/mmc Message-ID: <201206021911.q52JBjdi008303@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marius Date: Sat Jun 2 19:11:44 2012 New Revision: 236479 URL: http://svn.freebsd.org/changeset/base/236479 Log: MFC: r236156 - Fix some typos in mmc_acquire_bus() and mmc_send_csd(). - Fix some math errors in mmc_decode_csd_sd(). - Fix incorrect arguments to mmc_send_app_op_cond() in mmc_go_discovery(). - Add reporting of CSD for debug purposes. - Add detection (and skipping) of password-locked cards. - Add setting of block length on card if necessary. Submitted by: Patrick Kelsey Modified: stable/9/sys/dev/mmc/mmc.c Directory Properties: stable/9/sys/ (props changed) stable/9/sys/amd64/include/xen/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/boot/i386/efi/ (props changed) stable/9/sys/boot/ia64/efi/ (props changed) stable/9/sys/boot/ia64/ski/ (props changed) stable/9/sys/boot/powerpc/boot1.chrp/ (props changed) stable/9/sys/boot/powerpc/ofw/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) stable/9/sys/conf/ (props changed) stable/9/sys/contrib/dev/acpica/ (props changed) stable/9/sys/contrib/octeon-sdk/ (props changed) stable/9/sys/contrib/pf/ (props changed) stable/9/sys/contrib/x86emu/ (props changed) stable/9/sys/dev/ (props changed) stable/9/sys/dev/e1000/ (props changed) stable/9/sys/dev/ixgbe/ (props changed) stable/9/sys/fs/ (props changed) stable/9/sys/fs/ntfs/ (props changed) stable/9/sys/modules/ (props changed) Modified: stable/9/sys/dev/mmc/mmc.c ============================================================================== --- stable/9/sys/dev/mmc/mmc.c Sat Jun 2 19:10:02 2012 (r236478) +++ stable/9/sys/dev/mmc/mmc.c Sat Jun 2 19:11:44 2012 (r236479) @@ -224,7 +224,7 @@ mmc_acquire_bus(device_t busdev, device_ sc = device_get_softc(busdev); MMC_LOCK(sc); if (sc->owner) - panic("mmc: host bridge didn't seralize us."); + panic("mmc: host bridge didn't serialize us."); sc->owner = dev; MMC_UNLOCK(sc); @@ -859,7 +859,7 @@ mmc_decode_csd_sd(uint32_t *raw_csd, str if (v == 0) { m = mmc_get_bits(raw_csd, 128, 115, 4); e = mmc_get_bits(raw_csd, 128, 112, 3); - csd->tacc = exp[e] * mant[m] + 9 / 10; + csd->tacc = (exp[e] * mant[m] + 9) / 10; csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100; m = mmc_get_bits(raw_csd, 128, 99, 4); e = mmc_get_bits(raw_csd, 128, 96, 3); @@ -887,7 +887,7 @@ mmc_decode_csd_sd(uint32_t *raw_csd, str } else if (v == 1) { m = mmc_get_bits(raw_csd, 128, 115, 4); e = mmc_get_bits(raw_csd, 128, 112, 3); - csd->tacc = exp[e] * mant[m] + 9 / 10; + csd->tacc = (exp[e] * mant[m] + 9) / 10; csd->nsac = mmc_get_bits(raw_csd, 128, 104, 8) * 100; m = mmc_get_bits(raw_csd, 128, 99, 4); e = mmc_get_bits(raw_csd, 128, 96, 3); @@ -1002,7 +1002,7 @@ mmc_all_send_cid(struct mmc_softc *sc, u } static int -mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcid) +mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd) { struct mmc_command cmd; int err; @@ -1012,7 +1012,7 @@ mmc_send_csd(struct mmc_softc *sc, uint1 cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.data = NULL; err = mmc_wait_for_cmd(sc, &cmd, 0); - memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t)); + memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t)); return (err); } @@ -1121,6 +1121,35 @@ mmc_send_relative_addr(struct mmc_softc return (err); } +static int +mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status) +{ + struct mmc_command cmd; + int err; + + cmd.opcode = MMC_SEND_STATUS; + cmd.arg = rca << 16; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + cmd.data = NULL; + err = mmc_wait_for_cmd(sc, &cmd, 0); + *status = cmd.resp[0]; + return (err); +} + +static int +mmc_set_blocklen(struct mmc_softc *sc, uint32_t len) +{ + struct mmc_command cmd; + int err; + + cmd.opcode = MMC_SET_BLOCKLEN; + cmd.arg = len; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; + cmd.data = NULL; + err = mmc_wait_for_cmd(sc, &cmd, 0); + return (err); +} + static void mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) { @@ -1144,8 +1173,7 @@ mmc_discover_cards(struct mmc_softc *sc) struct mmc_ivars *ivar = NULL; device_t *devlist; int err, i, devcount, newcard; - uint32_t raw_cid[4]; - uint32_t resp, sec_count; + uint32_t raw_cid[4], resp, sec_count, status; device_t child; uint16_t rca = 2; u_char switch_res[64]; @@ -1194,6 +1222,12 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->rca = resp >> 16; /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + if (bootverbose || mmc_debug) + device_printf(sc->dev, + "%sard detected (CSD %08x%08x%08x%08x)\n", + newcard ? "New c" : "C", ivar->raw_csd[0], + ivar->raw_csd[1], ivar->raw_csd[2], + ivar->raw_csd[3]); mmc_decode_csd_sd(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; if (ivar->csd.csd_structure > 0) @@ -1201,6 +1235,19 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; + + err = mmc_send_status(sc, ivar->rca, &status); + if (err != MMC_ERR_NONE) { + device_printf(sc->dev, + "Error reading card status %d\n", err); + break; + } + if ((status & R1_CARD_IS_LOCKED) != 0) { + device_printf(sc->dev, + "Card is password protected, skipping.\n"); + break; + } + /* Get card SCR. Card must be selected to fetch it. */ mmc_select_card(sc, ivar->rca); mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr); @@ -1228,7 +1275,22 @@ mmc_discover_cards(struct mmc_softc *sc) if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) ivar->bus_width = bus_width_4; + + /* + * Some cards that report maximum I/O block sizes + * greater than 512 require the block length to be + * set to 512, even though that is supposed to be + * the default. Example: + * + * Transcend 2GB SDSC card, CID: + * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=00.2000 + */ + if (ivar->csd.read_bl_len != MMC_SECTOR_SIZE || + ivar->csd.write_bl_len != MMC_SECTOR_SIZE) + mmc_set_blocklen(sc, MMC_SECTOR_SIZE); + mmc_format_card_id_string(ivar); + if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { @@ -1243,11 +1305,31 @@ mmc_discover_cards(struct mmc_softc *sc) mmc_set_relative_addr(sc, ivar->rca); /* Get card CSD. */ mmc_send_csd(sc, ivar->rca, ivar->raw_csd); + if (bootverbose || mmc_debug) + device_printf(sc->dev, + "%sard detected (CSD %08x%08x%08x%08x)\n", + newcard ? "New c" : "C", ivar->raw_csd[0], + ivar->raw_csd[1], ivar->raw_csd[2], + ivar->raw_csd[3]); + mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd); ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE; ivar->tran_speed = ivar->csd.tran_speed; ivar->erase_sector = ivar->csd.erase_sector * ivar->csd.write_bl_len / MMC_SECTOR_SIZE; + + err = mmc_send_status(sc, ivar->rca, &status); + if (err != MMC_ERR_NONE) { + device_printf(sc->dev, + "Error reading card status %d\n", err); + break; + } + if ((status & R1_CARD_IS_LOCKED) != 0) { + device_printf(sc->dev, + "Card is password protected, skipping.\n"); + break; + } + /* Only MMC >= 4.x cards support EXT_CSD. */ if (ivar->csd.spec_vers >= 4) { /* Card must be selected to fetch EXT_CSD. */ @@ -1286,7 +1368,21 @@ mmc_discover_cards(struct mmc_softc *sc) ivar->bus_width = bus_width_1; ivar->timing = bus_timing_normal; } + + /* + * Some cards that report maximum I/O block sizes greater + * than 512 require the block length to be set to 512, even + * though that is supposed to be the default. Example: + * + * Transcend 2GB SDSC card, CID: + * mid=0x1b oid=0x534d pnm="00000" prv=1.0 mdt=00.2000 + */ + if (ivar->csd.read_bl_len != MMC_SECTOR_SIZE || + ivar->csd.write_bl_len != MMC_SECTOR_SIZE) + mmc_set_blocklen(sc, MMC_SECTOR_SIZE); + mmc_format_card_id_string(ivar); + if (bootverbose || mmc_debug) mmc_log_card(sc->dev, ivar, newcard); if (newcard) { @@ -1362,8 +1458,7 @@ mmc_go_discovery(struct mmc_softc *sc) err = mmc_send_if_cond(sc, 1); if ((bootverbose || mmc_debug) && err == 0) device_printf(sc->dev, "SD 2.0 interface conditions: OK\n"); - if (mmc_send_app_op_cond(sc, err ? 0 : MMC_OCR_CCS, &ocr) != - MMC_ERR_NONE) { + if (mmc_send_app_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) { if (bootverbose || mmc_debug) device_printf(sc->dev, "SD probe: failed\n"); /* @@ -1535,7 +1630,6 @@ mmc_write_ivar(device_t bus, device_t ch return (EINVAL); } - static void mmc_delayed_attach(void *xsc) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206021911.q52JBjdi008303>