diff options
author | Sylvestre Gallon <syl@cvs.openbsd.org> | 2013-10-22 16:49:28 +0000 |
---|---|---|
committer | Sylvestre Gallon <syl@cvs.openbsd.org> | 2013-10-22 16:49:28 +0000 |
commit | 057f39c26c9b61ab7665a5bd36d179535ac02f6c (patch) | |
tree | 46ba98b4cf2bcca24a47411534decdc18c740d0e /sys/dev/sdmmc | |
parent | 1e8e86830088bc4916f73acb3ff1c803a22d0711 (diff) |
Add code for SMC_CAPS_SINGLE_ONLY capability.
This capability force the sdmmc stack to only issue
single blocks transfers.
tested by rapha@ and I on ommmc(4).
tested by rapha@ on pxammc(4).
ok rapha@
Diffstat (limited to 'sys/dev/sdmmc')
-rw-r--r-- | sys/dev/sdmmc/sdmmc_mem.c | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c index 39940e26158..f06f5ac2d15 100644 --- a/sys/dev/sdmmc/sdmmc_mem.c +++ b/sys/dev/sdmmc/sdmmc_mem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdmmc_mem.c,v 1.17 2013/09/12 11:54:04 rapha Exp $ */ +/* $OpenBSD: sdmmc_mem.c,v 1.18 2013/10/22 16:49:27 syl Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -42,6 +42,14 @@ int sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, uint8_t); int sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *); int sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *); +int sdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *, + size_t); +int sdmmc_mem_read_block_subr(struct sdmmc_function *, int, u_char *, + size_t); +int sdmmc_mem_single_write_block(struct sdmmc_function *, int, u_char *, + size_t); +int sdmmc_mem_write_block_subr(struct sdmmc_function *, int, u_char *, + size_t); #ifdef SDMMC_DEBUG #define DPRINTF(s) printf s @@ -551,14 +559,13 @@ sdmmc_mem_set_blocklen(struct sdmmc_softc *sc, struct sdmmc_function *sf) } int -sdmmc_mem_read_block(struct sdmmc_function *sf, int blkno, u_char *data, +sdmmc_mem_read_block_subr(struct sdmmc_function *sf, int blkno, u_char *data, size_t datalen) { struct sdmmc_softc *sc = sf->sc; struct sdmmc_command cmd; int error; - rw_enter_write(&sc->sc_lock); if ((error = sdmmc_select_card(sc, sf)) != 0) goto err; @@ -602,20 +609,53 @@ sdmmc_mem_read_block(struct sdmmc_function *sf, int blkno, u_char *data, } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA)); err: - rw_exit(&sc->sc_lock); - return error; + return (error); } int -sdmmc_mem_write_block(struct sdmmc_function *sf, int blkno, u_char *data, +sdmmc_mem_single_read_block(struct sdmmc_function *sf, int blkno, u_char *data, + size_t datalen) +{ + int error; + int i; + + for (i = 0; i < datalen / sf->csd.sector_size; i++) { + error = sdmmc_mem_read_block_subr(sf, blkno + i, data + i * + sf->csd.sector_size, sf->csd.sector_size); + if (error) + break; + } + + return (error); +} + +int +sdmmc_mem_read_block(struct sdmmc_function *sf, int blkno, u_char *data, size_t datalen) { struct sdmmc_softc *sc = sf->sc; - struct sdmmc_command cmd; int error; rw_enter_write(&sc->sc_lock); + if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) { + error = sdmmc_mem_single_read_block(sf, blkno, data, datalen); + } else { + error = sdmmc_mem_read_block_subr(sf, blkno, data, datalen); + } + + rw_exit(&sc->sc_lock); + return (error); +} + +int +sdmmc_mem_write_block_subr(struct sdmmc_function *sf, int blkno, u_char *data, + size_t datalen) +{ + struct sdmmc_softc *sc = sf->sc; + struct sdmmc_command cmd; + int error; + if ((error = sdmmc_select_card(sc, sf)) != 0) goto err; @@ -657,6 +697,41 @@ sdmmc_mem_write_block(struct sdmmc_function *sf, int blkno, u_char *data, } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA)); err: + return (error); +} + +int +sdmmc_mem_single_write_block(struct sdmmc_function *sf, int blkno, u_char *data, + size_t datalen) +{ + int error; + int i; + + for (i = 0; i < datalen / sf->csd.sector_size; i++) { + error = sdmmc_mem_write_block_subr(sf, blkno + i, data + i * + sf->csd.sector_size, sf->csd.sector_size); + if (error) + break; + } + + return (error); +} + +int +sdmmc_mem_write_block(struct sdmmc_function *sf, int blkno, u_char *data, + size_t datalen) +{ + struct sdmmc_softc *sc = sf->sc; + int error; + + rw_enter_write(&sc->sc_lock); + + if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) { + error = sdmmc_mem_single_write_block(sf, blkno, data, datalen); + } else { + error = sdmmc_mem_write_block_subr(sf, blkno, data, datalen); + } + rw_exit(&sc->sc_lock); - return error; + return (error); } |