Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/sdmmc Correctly read the 512-bit-wide big-endian Swi...



details:   https://anonhg.NetBSD.org/src/rev/2b815c8f06af
branches:  trunk
changeset: 783321:2b815c8f06af
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Sat Dec 15 00:03:00 2012 +0000

description:
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.

diffstat:

 sys/dev/sdmmc/sdmmc_mem.c |  36 ++++++++++++++++++++++++++++--------
 sys/dev/sdmmc/sdmmcreg.h  |   6 +++---
 2 files changed, 31 insertions(+), 11 deletions(-)

diffs (139 lines):

diff -r 5fd56ca982c9 -r 2b815c8f06af sys/dev/sdmmc/sdmmc_mem.c
--- a/sys/dev/sdmmc/sdmmc_mem.c Fri Dec 14 23:53:56 2012 +0000
+++ b/sys/dev/sdmmc/sdmmc_mem.c Sat Dec 15 00:03:00 2012 +0000
@@ -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 @@
 #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_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 @@
        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 @@
                { 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 @@
        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 @@
                }
 
                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 @@
                        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 @@
 
 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 @@
                        free(ptr, M_DEVBUF);
                }
        }
+
+       if (error == 0)
+               sdmmc_be512_to_bitfield512(status);
+
        return error;
 }
 
diff -r 5fd56ca982c9 -r 2b815c8f06af sys/dev/sdmmc/sdmmcreg.h
--- a/sys/dev/sdmmc/sdmmcreg.h  Fri Dec 14 23:53:56 2012 +0000
+++ b/sys/dev/sdmmc/sdmmcreg.h  Sat Dec 15 00:03:00 2012 +0000
@@ -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;



Home | Main Index | Thread Index | Old Index