Module Name: src Committed By: jakllsch Date: Sat Dec 15 00:03:01 UTC 2012
Modified Files: src/sys/dev/sdmmc: sdmmc_mem.c sdmmcreg.h Log Message: Correctly read the 512-bit-wide big-endian Switch Function Status register. Some of this could/will also be useful for the SD Status register. To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.26 src/sys/dev/sdmmc/sdmmc_mem.c cvs rdiff -u -r1.12 -r1.13 src/sys/dev/sdmmc/sdmmcreg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/sdmmc/sdmmc_mem.c diff -u src/sys/dev/sdmmc/sdmmc_mem.c:1.25 src/sys/dev/sdmmc/sdmmc_mem.c:1.26 --- src/sys/dev/sdmmc/sdmmc_mem.c:1.25 Fri Dec 14 23:22:21 2012 +++ src/sys/dev/sdmmc/sdmmc_mem.c Sat Dec 15 00:03:00 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmc_mem.c,v 1.25 2012/12/14 23:22:21 jakllsch Exp $ */ +/* $NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch Exp $ */ /* $OpenBSD: sdmmc_mem.c,v 1.10 2009/01/09 10:55:22 jsg Exp $ */ /* @@ -45,7 +45,7 @@ /* Routines for SD/MMC memory cards. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.25 2012/12/14 23:22:21 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c,v 1.26 2012/12/15 00:03:00 jakllsch Exp $"); #ifdef _KERNEL_OPT #include "opt_sdmmc.h" @@ -67,6 +67,8 @@ __KERNEL_RCSID(0, "$NetBSD: sdmmc_mem.c, #define DPRINTF(s) do {} while (/*CONSTCOND*/0) #endif +typedef struct { uint32_t _bits[512/32]; } __packed __aligned(4) sdmmc_bitfield512_t; + static int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *); static int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *); static int sdmmc_mem_send_cid(struct sdmmc_softc *, sdmmc_response *); @@ -77,7 +79,7 @@ static int sdmmc_mem_send_scr(struct sdm static int sdmmc_mem_decode_scr(struct sdmmc_softc *, struct sdmmc_function *); static int sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t); static int sdmmc_set_bus_width(struct sdmmc_function *, int); -static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, void *); +static int sdmmc_mem_sd_switch(struct sdmmc_function *, int, int, int, sdmmc_bitfield512_t *); static int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, uint8_t); static int sdmmc_mem_spi_read_ocr(struct sdmmc_softc *, uint32_t, uint32_t *); @@ -574,6 +576,20 @@ sdmmc_mem_set_blocklen(struct sdmmc_soft return error; } +/* make 512-bit BE quantity __bitfield()-compatible */ +static void +sdmmc_be512_to_bitfield512(sdmmc_bitfield512_t *buf) { + size_t i; + uint32_t tmp0, tmp1; + const size_t bitswords = __arraycount(buf->_bits); + for (i = 0; i < bitswords/2; i++) { + tmp0 = buf->_bits[i]; + tmp1 = buf->_bits[bitswords - 1 - i]; + buf->_bits[i] = be32toh(tmp1); + buf->_bits[bitswords - 1 - i] = be32toh(tmp0); + } +} + static int sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf) { @@ -599,7 +615,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc { MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V, 50000 }, }; int host_ocr, support_func, best_func, error, g, i; - char status[64]; + sdmmc_bitfield512_t status; /* Switch Function Status */ error = sdmmc_mem_send_scr(sc, sf, sf->raw_scr); if (error) { @@ -625,7 +641,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 && ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) { DPRINTF(("%s: switch func mode 0\n", SDMMCDEVNAME(sc))); - error = sdmmc_mem_sd_switch(sf, 0, 1, 0, status); + error = sdmmc_mem_sd_switch(sf, 0, 1, 0, &status); if (error) { aprint_error_dev(sc->sc_dev, "switch func mode 0 failed\n"); @@ -633,7 +649,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc } host_ocr = sdmmc_chip_host_ocr(sc->sc_sct, sc->sc_sch); - support_func = SFUNC_STATUS_GROUP(status, 1); + support_func = SFUNC_STATUS_GROUP(&status, 1); best_func = 0; for (i = 0, g = 1; i < __arraycount(switch_group0_functions); i++, g <<= 1) { @@ -647,7 +663,7 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc DPRINTF(("%s: switch func mode 1(func=%d)\n", SDMMCDEVNAME(sc), best_func)); error = - sdmmc_mem_sd_switch(sf, 1, 1, best_func, status); + sdmmc_mem_sd_switch(sf, 1, 1, best_func, &status); if (error) { aprint_error_dev(sc->sc_dev, "switch func mode 1 failed:" @@ -1059,7 +1075,7 @@ sdmmc_set_bus_width(struct sdmmc_functio static int sdmmc_mem_sd_switch(struct sdmmc_function *sf, int mode, int group, - int function, void *status) + int function, sdmmc_bitfield512_t *status) { struct sdmmc_softc *sc = sf->sc; struct sdmmc_command cmd; @@ -1132,6 +1148,10 @@ dmamem_free: free(ptr, M_DEVBUF); } } + + if (error == 0) + sdmmc_be512_to_bitfield512(status); + return error; } Index: src/sys/dev/sdmmc/sdmmcreg.h diff -u src/sys/dev/sdmmc/sdmmcreg.h:1.12 src/sys/dev/sdmmc/sdmmcreg.h:1.13 --- src/sys/dev/sdmmc/sdmmcreg.h:1.12 Sat Jul 28 18:38:03 2012 +++ src/sys/dev/sdmmc/sdmmcreg.h Sat Dec 15 00:03:00 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: sdmmcreg.h,v 1.12 2012/07/28 18:38:03 matt Exp $ */ +/* $NetBSD: sdmmcreg.h,v 1.13 2012/12/15 00:03:00 jakllsch Exp $ */ /* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */ /* @@ -318,14 +318,14 @@ /* Status of Switch Function */ #define SFUNC_STATUS_GROUP(status, group) \ - be16toh(__bitfield((uint32_t *)(status), (7 - (group)) << 4, 16)) + (__bitfield((uint32_t *)(status), 400 + (group - 1) * 16, 16)) /* This assumes the response fields are in host byte order in 32-bit units. */ #define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start)-8, (len)) static inline uint32_t __bitfield(const uint32_t *src, size_t start, size_t len) { - if (start + len > 128 || len == 0 || len > 32) + if (start + len > 512 || len == 0 || len > 32) return 0; src += start / 32;