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