LCOV - code coverage report
Current view: top level - dev/sdmmc - sdmmc_mem.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 538 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: sdmmc_mem.c,v 1.33 2018/06/04 13:33:10 patrick Exp $  */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /* Routines for SD/MMC memory cards. */
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/device.h>
      23             : #include <sys/kernel.h>
      24             : #include <sys/malloc.h>
      25             : #include <sys/systm.h>
      26             : 
      27             : #include <dev/sdmmc/sdmmcchip.h>
      28             : #include <dev/sdmmc/sdmmcreg.h>
      29             : #include <dev/sdmmc/sdmmcvar.h>
      30             : 
      31             : #ifdef HIBERNATE
      32             : #include <uvm/uvm_extern.h>
      33             : #endif
      34             : 
      35             : typedef struct { uint32_t _bits[512/32]; } __packed __aligned(4) sdmmc_bitfield512_t;
      36             : 
      37             : void    sdmmc_be512_to_bitfield512(sdmmc_bitfield512_t *);
      38             : 
      39             : int     sdmmc_decode_csd(struct sdmmc_softc *, sdmmc_response,
      40             :             struct sdmmc_function *);
      41             : int     sdmmc_decode_cid(struct sdmmc_softc *, sdmmc_response,
      42             :             struct sdmmc_function *);
      43             : void    sdmmc_print_cid(struct sdmmc_cid *);
      44             : 
      45             : int     sdmmc_mem_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
      46             : int     sdmmc_mem_set_blocklen(struct sdmmc_softc *, struct sdmmc_function *);
      47             : 
      48             : int     sdmmc_mem_send_scr(struct sdmmc_softc *, uint32_t *);
      49             : int     sdmmc_mem_decode_scr(struct sdmmc_softc *, uint32_t *,
      50             :             struct sdmmc_function *);
      51             : 
      52             : int     sdmmc_mem_send_cxd_data(struct sdmmc_softc *, int, void *, size_t);
      53             : int     sdmmc_mem_set_bus_width(struct sdmmc_function *, int);
      54             : int     sdmmc_mem_mmc_switch(struct sdmmc_function *, uint8_t, uint8_t, uint8_t);
      55             : 
      56             : int     sdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
      57             : int     sdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
      58             : int     sdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *,
      59             :         size_t);
      60             : int     sdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
      61             :         int, u_char *, size_t);
      62             : int     sdmmc_mem_single_write_block(struct sdmmc_function *, int, u_char *,
      63             :         size_t);
      64             : int     sdmmc_mem_write_block_subr(struct sdmmc_function *, bus_dmamap_t,
      65             :         int, u_char *, size_t);
      66             : 
      67             : #ifdef SDMMC_DEBUG
      68             : #define DPRINTF(s)      printf s
      69             : #else
      70             : #define DPRINTF(s)      /**/
      71             : #endif
      72             : 
      73             : /*
      74             :  * Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
      75             :  */
      76             : int
      77           0 : sdmmc_mem_enable(struct sdmmc_softc *sc)
      78             : {
      79             :         u_int32_t host_ocr;
      80           0 :         u_int32_t card_ocr;
      81             : 
      82           0 :         rw_assert_wrlock(&sc->sc_lock);
      83             : 
      84             :         /* Set host mode to SD "combo" card or SD memory-only. */
      85           0 :         SET(sc->sc_flags, SMF_SD_MODE|SMF_MEM_MODE);
      86             : 
      87             :         /* Reset memory (*must* do that before CMD55 or CMD1). */
      88           0 :         sdmmc_go_idle_state(sc);
      89             : 
      90             :         /*
      91             :          * Read the SD/MMC memory OCR value by issuing CMD55 followed
      92             :          * by ACMD41 to read the OCR value from memory-only SD cards.
      93             :          * MMC cards will not respond to CMD55 or ACMD41 and this is
      94             :          * how we distinguish them from SD cards.
      95             :          */
      96             :  mmc_mode:
      97           0 :         if (sdmmc_mem_send_op_cond(sc, 0, &card_ocr) != 0) {
      98           0 :                 if (ISSET(sc->sc_flags, SMF_SD_MODE) &&
      99           0 :                     !ISSET(sc->sc_flags, SMF_IO_MODE)) {
     100             :                         /* Not a SD card, switch to MMC mode. */
     101           0 :                         CLR(sc->sc_flags, SMF_SD_MODE);
     102           0 :                         goto mmc_mode;
     103             :                 }
     104           0 :                 if (!ISSET(sc->sc_flags, SMF_SD_MODE)) {
     105             :                         DPRINTF(("%s: can't read memory OCR\n",
     106             :                             DEVNAME(sc)));
     107           0 :                         return 1;
     108             :                 } else {
     109             :                         /* Not a "combo" card. */
     110           0 :                         CLR(sc->sc_flags, SMF_MEM_MODE);
     111           0 :                         return 0;
     112             :                 }
     113             :         }
     114             : 
     115             :         /* Set the lowest voltage supported by the card and host. */
     116           0 :         host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
     117           0 :         if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
     118             :                 DPRINTF(("%s: can't supply voltage requested by card\n",
     119             :                     DEVNAME(sc)));
     120           0 :                 return 1;
     121             :         }
     122             : 
     123             :         /* Tell the card(s) to enter the idle state (again). */
     124           0 :         sdmmc_go_idle_state(sc);
     125             : 
     126           0 :         host_ocr &= card_ocr; /* only allow the common voltages */
     127             : 
     128           0 :         if (sdmmc_send_if_cond(sc, card_ocr) == 0)
     129           0 :                 host_ocr |= SD_OCR_SDHC_CAP;
     130             : 
     131             :         /* Send the new OCR value until all cards are ready. */
     132           0 :         if (sdmmc_mem_send_op_cond(sc, host_ocr, NULL) != 0) {
     133             :                 DPRINTF(("%s: can't send memory OCR\n", DEVNAME(sc)));
     134           0 :                 return 1;
     135             :         }
     136           0 :         return 0;
     137           0 : }
     138             : 
     139             : /*
     140             :  * Read the CSD and CID from all cards and assign each card a unique
     141             :  * relative card address (RCA).  CMD2 is ignored by SDIO-only cards.
     142             :  */
     143             : void
     144           0 : sdmmc_mem_scan(struct sdmmc_softc *sc)
     145             : {
     146           0 :         struct sdmmc_command cmd;
     147             :         struct sdmmc_function *sf;
     148             :         u_int16_t next_rca;
     149             :         int error;
     150             :         int i;
     151             : 
     152           0 :         rw_assert_wrlock(&sc->sc_lock);
     153             : 
     154             :         /*
     155             :          * CMD2 is a broadcast command understood by SD cards and MMC
     156             :          * cards.  All cards begin to respond to the command, but back
     157             :          * off if another card drives the CMD line to a different level.
     158             :          * Only one card will get its entire response through.  That
     159             :          * card remains silent once it has been assigned a RCA.
     160             :          */
     161           0 :         for (i = 0; i < 100; i++) {
     162           0 :                 bzero(&cmd, sizeof cmd);
     163           0 :                 cmd.c_opcode = MMC_ALL_SEND_CID;
     164           0 :                 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R2;
     165             : 
     166           0 :                 error = sdmmc_mmc_command(sc, &cmd);
     167           0 :                 if (error == ETIMEDOUT) {
     168             :                         /* No more cards there. */
     169             :                         break;
     170           0 :                 } else if (error != 0) {
     171             :                         DPRINTF(("%s: can't read CID\n", DEVNAME(sc)));
     172             :                         break;
     173             :                 }
     174             : 
     175             :                 /* In MMC mode, find the next available RCA. */
     176             :                 next_rca = 1;
     177           0 :                 if (!ISSET(sc->sc_flags, SMF_SD_MODE))
     178           0 :                         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list)
     179           0 :                                 next_rca++;
     180             : 
     181             :                 /* Allocate a sdmmc_function structure. */
     182           0 :                 sf = sdmmc_function_alloc(sc);
     183           0 :                 sf->rca = next_rca;
     184             : 
     185             :                 /*
     186             :                  * Remember the CID returned in the CMD2 response for
     187             :                  * later decoding.
     188             :                  */
     189           0 :                 bcopy(cmd.c_resp, sf->raw_cid, sizeof sf->raw_cid);
     190             : 
     191             :                 /*
     192             :                  * Silence the card by assigning it a unique RCA, or
     193             :                  * querying it for its RCA in the case of SD.
     194             :                  */
     195           0 :                 if (sdmmc_set_relative_addr(sc, sf) != 0) {
     196           0 :                         printf("%s: can't set mem RCA\n", DEVNAME(sc));
     197           0 :                         sdmmc_function_free(sf);
     198           0 :                         break;
     199             :                 }
     200             : 
     201             : #if 0
     202             :                 /* Verify that the RCA has been set by selecting the card. */
     203             :                 if (sdmmc_select_card(sc, sf) != 0) {
     204             :                         printf("%s: can't select mem RCA %d\n",
     205             :                             DEVNAME(sc), sf->rca);
     206             :                         sdmmc_function_free(sf);
     207             :                         break;
     208             :                 }
     209             : 
     210             :                 /* Deselect. */
     211             :                 (void)sdmmc_select_card(sc, NULL);
     212             : #endif
     213             : 
     214             :                 /*
     215             :                  * If this is a memory-only card, the card responding
     216             :                  * first becomes an alias for SDIO function 0.
     217             :                  */
     218           0 :                 if (sc->sc_fn0 == NULL)
     219           0 :                         sc->sc_fn0 = sf;
     220             : 
     221           0 :                 SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
     222             :         }
     223             : 
     224             :         /*
     225             :          * All cards are either inactive or awaiting further commands.
     226             :          * Read the CSDs and decode the raw CID for each card.
     227             :          */
     228           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     229           0 :                 bzero(&cmd, sizeof cmd);
     230           0 :                 cmd.c_opcode = MMC_SEND_CSD;
     231           0 :                 cmd.c_arg = MMC_ARG_RCA(sf->rca);
     232           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R2;
     233             : 
     234           0 :                 if (sdmmc_mmc_command(sc, &cmd) != 0) {
     235           0 :                         SET(sf->flags, SFF_ERROR);
     236           0 :                         continue;
     237             :                 }
     238             : 
     239           0 :                 if (sdmmc_decode_csd(sc, cmd.c_resp, sf) != 0 ||
     240           0 :                     sdmmc_decode_cid(sc, sf->raw_cid, sf) != 0) {
     241           0 :                         SET(sf->flags, SFF_ERROR);
     242           0 :                         continue;
     243             :                 }
     244             : 
     245             : #ifdef SDMMC_DEBUG
     246             :                 printf("%s: CID: ", DEVNAME(sc));
     247             :                 sdmmc_print_cid(&sf->cid);
     248             : #endif
     249             :         }
     250           0 : }
     251             : 
     252             : int
     253           0 : sdmmc_decode_csd(struct sdmmc_softc *sc, sdmmc_response resp,
     254             :     struct sdmmc_function *sf)
     255             : {
     256           0 :         struct sdmmc_csd *csd = &sf->csd;
     257             : 
     258           0 :         if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
     259             :                 /*
     260             :                  * CSD version 1.0 corresponds to SD system
     261             :                  * specification version 1.0 - 1.10. (SanDisk, 3.5.3)
     262             :                  */
     263             :                 csd->csdver = SD_CSD_CSDVER(resp);
     264           0 :                 switch (csd->csdver) {
     265             :                 case SD_CSD_CSDVER_2_0:
     266           0 :                         sf->flags |= SFF_SDHC;
     267           0 :                         csd->capacity = SD_CSD_V2_CAPACITY(resp);
     268           0 :                         csd->read_bl_len = SD_CSD_V2_BL_LEN;
     269           0 :                         break;
     270             :                 case SD_CSD_CSDVER_1_0:
     271           0 :                         csd->capacity = SD_CSD_CAPACITY(resp);
     272           0 :                         csd->read_bl_len = SD_CSD_READ_BL_LEN(resp);
     273           0 :                         break;
     274             :                 default:
     275           0 :                         printf("%s: unknown SD CSD structure version 0x%x\n",
     276           0 :                             DEVNAME(sc), csd->csdver);
     277           0 :                         return 1;
     278             :                         break;
     279             :                 }
     280           0 :                 csd->ccc = SD_CSD_CCC(resp);
     281           0 :         } else {
     282             :                 csd->csdver = MMC_CSD_CSDVER(resp);
     283           0 :                 if (csd->csdver == MMC_CSD_CSDVER_1_0 ||
     284           0 :                     csd->csdver == MMC_CSD_CSDVER_2_0 ||
     285           0 :                     csd->csdver == MMC_CSD_CSDVER_EXT_CSD) {
     286           0 :                         csd->mmcver = MMC_CSD_MMCVER(resp);
     287           0 :                         csd->capacity = MMC_CSD_CAPACITY(resp);
     288           0 :                         csd->read_bl_len = MMC_CSD_READ_BL_LEN(resp);
     289             :                 } else {
     290           0 :                         printf("%s: unknown MMC CSD structure version 0x%x\n",
     291           0 :                             DEVNAME(sc), csd->csdver);
     292           0 :                         return 1;
     293             :                 }
     294             :         }
     295           0 :         csd->sector_size = MIN(1 << csd->read_bl_len,
     296             :             sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
     297           0 :         if (csd->sector_size < (1<<csd->read_bl_len))
     298           0 :                 csd->capacity *= (1<<csd->read_bl_len) /
     299             :                     csd->sector_size;
     300             : 
     301           0 :         return 0;
     302           0 : }
     303             : 
     304             : int
     305           0 : sdmmc_decode_cid(struct sdmmc_softc *sc, sdmmc_response resp,
     306             :     struct sdmmc_function *sf)
     307             : {
     308           0 :         struct sdmmc_cid *cid = &sf->cid;
     309             : 
     310           0 :         if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
     311           0 :                 cid->mid = SD_CID_MID(resp);
     312           0 :                 cid->oid = SD_CID_OID(resp);
     313           0 :                 SD_CID_PNM_CPY(resp, cid->pnm);
     314           0 :                 cid->rev = SD_CID_REV(resp);
     315           0 :                 cid->psn = SD_CID_PSN(resp);
     316           0 :                 cid->mdt = SD_CID_MDT(resp);
     317           0 :         } else {
     318           0 :                 switch(sf->csd.mmcver) {
     319             :                 case MMC_CSD_MMCVER_1_0:
     320             :                 case MMC_CSD_MMCVER_1_4:
     321           0 :                         cid->mid = MMC_CID_MID_V1(resp);
     322           0 :                         MMC_CID_PNM_V1_CPY(resp, cid->pnm);
     323           0 :                         cid->rev = MMC_CID_REV_V1(resp);
     324           0 :                         cid->psn = MMC_CID_PSN_V1(resp);
     325           0 :                         cid->mdt = MMC_CID_MDT_V1(resp);
     326           0 :                         break;
     327             :                 case MMC_CSD_MMCVER_2_0:
     328             :                 case MMC_CSD_MMCVER_3_1:
     329             :                 case MMC_CSD_MMCVER_4_0:
     330           0 :                         cid->mid = MMC_CID_MID_V2(resp);
     331           0 :                         cid->oid = MMC_CID_OID_V2(resp);
     332           0 :                         MMC_CID_PNM_V2_CPY(resp, cid->pnm);
     333           0 :                         cid->psn = MMC_CID_PSN_V2(resp);
     334           0 :                         break;
     335             :                 default:
     336           0 :                         printf("%s: unknown MMC version %d\n",
     337           0 :                             DEVNAME(sc), sf->csd.mmcver);
     338           0 :                         return 1;
     339             :                 }
     340             :         }
     341           0 :         return 0;
     342           0 : }
     343             : 
     344             : #ifdef SDMMC_DEBUG
     345             : void
     346             : sdmmc_print_cid(struct sdmmc_cid *cid)
     347             : {
     348             :         printf("mid=0x%02x oid=0x%04x pnm=\"%s\" rev=0x%02x psn=0x%08x"
     349             :             " mdt=%03x\n", cid->mid, cid->oid, cid->pnm, cid->rev, cid->psn,
     350             :             cid->mdt);
     351             : }
     352             : #endif
     353             : 
     354             : int
     355           0 : sdmmc_mem_send_scr(struct sdmmc_softc *sc, uint32_t *scr)
     356             : {
     357           0 :         struct sdmmc_command cmd;
     358             :         void *ptr = NULL;
     359             :         int datalen = 8;
     360             :         int error = 0;
     361             : 
     362           0 :         ptr = malloc(datalen, M_DEVBUF, M_NOWAIT | M_ZERO);
     363           0 :         if (ptr == NULL)
     364             :                 goto out;
     365             : 
     366           0 :         memset(&cmd, 0, sizeof(cmd));
     367           0 :         cmd.c_data = ptr;
     368           0 :         cmd.c_datalen = datalen;
     369           0 :         cmd.c_blklen = datalen;
     370           0 :         cmd.c_arg = 0;
     371           0 :         cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
     372           0 :         cmd.c_opcode = SD_APP_SEND_SCR;
     373             : 
     374           0 :         error = sdmmc_app_command(sc, &cmd);
     375           0 :         if (error == 0)
     376           0 :                 memcpy(scr, ptr, datalen);
     377             : 
     378             : out:
     379           0 :         if (ptr != NULL)
     380           0 :                 free(ptr, M_DEVBUF, datalen);
     381             : 
     382           0 :         return error;
     383           0 : }
     384             : 
     385             : int
     386           0 : sdmmc_mem_decode_scr(struct sdmmc_softc *sc, uint32_t *raw_scr,
     387             :     struct sdmmc_function *sf)
     388             : {
     389           0 :         sdmmc_response resp;
     390             :         int ver;
     391             : 
     392           0 :         memset(resp, 0, sizeof(resp));
     393             :         /*
     394             :          * Change the raw SCR to a response.
     395             :          */
     396           0 :         resp[0] = be32toh(raw_scr[1]) >> 8;               // LSW
     397           0 :         resp[1] = be32toh(raw_scr[0]);                  // MSW
     398           0 :         resp[0] |= (resp[1] & 0xff) << 24;
     399           0 :         resp[1] >>= 8;
     400             : 
     401           0 :         ver = SCR_STRUCTURE(resp);
     402           0 :         sf->scr.sd_spec = SCR_SD_SPEC(resp);
     403           0 :         sf->scr.bus_width = SCR_SD_BUS_WIDTHS(resp);
     404             : 
     405             :         DPRINTF(("%s: %s: %08x%08x ver=%d, spec=%d, bus width=%d\n",
     406             :             DEVNAME(sc), __func__, resp[1], resp[0],
     407             :             ver, sf->scr.sd_spec, sf->scr.bus_width));
     408             : 
     409           0 :         if (ver != 0) {
     410             :                 DPRINTF(("%s: unknown SCR structure version: %d\n",
     411             :                     DEVNAME(sc), ver));
     412           0 :                 return EINVAL;
     413             :         }
     414           0 :         return 0;
     415           0 : }
     416             : 
     417             : int
     418           0 : sdmmc_mem_send_cxd_data(struct sdmmc_softc *sc, int opcode, void *data,
     419             :     size_t datalen)
     420             : {
     421           0 :         struct sdmmc_command cmd;
     422             :         void *ptr = NULL;
     423             :         int error = 0;
     424             : 
     425           0 :         ptr = malloc(datalen, M_DEVBUF, M_NOWAIT | M_ZERO);
     426           0 :         if (ptr == NULL) {
     427             :                 error = ENOMEM;
     428           0 :                 goto out;
     429             :         }
     430             : 
     431           0 :         memset(&cmd, 0, sizeof(cmd));
     432           0 :         cmd.c_data = ptr;
     433           0 :         cmd.c_datalen = datalen;
     434           0 :         cmd.c_blklen = datalen;
     435           0 :         cmd.c_opcode = opcode;
     436           0 :         cmd.c_arg = 0;
     437           0 :         cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ;
     438           0 :         if (opcode == MMC_SEND_EXT_CSD)
     439           0 :                 SET(cmd.c_flags, SCF_RSP_R1);
     440             :         else
     441           0 :                 SET(cmd.c_flags, SCF_RSP_R2);
     442             : 
     443           0 :         error = sdmmc_mmc_command(sc, &cmd);
     444           0 :         if (error == 0)
     445           0 :                 memcpy(data, ptr, datalen);
     446             : 
     447             : out:
     448           0 :         if (ptr != NULL)
     449           0 :                 free(ptr, M_DEVBUF, datalen);
     450             : 
     451           0 :         return error;
     452           0 : }
     453             : 
     454             : int
     455           0 : sdmmc_mem_set_bus_width(struct sdmmc_function *sf, int width)
     456             : {
     457           0 :         struct sdmmc_softc *sc = sf->sc;
     458           0 :         struct sdmmc_command cmd;
     459             :         int error;
     460             : 
     461           0 :         memset(&cmd, 0, sizeof(cmd));
     462           0 :         cmd.c_opcode = SD_APP_SET_BUS_WIDTH;
     463           0 :         cmd.c_flags = SCF_RSP_R1 | SCF_CMD_AC;
     464             : 
     465           0 :         switch (width) {
     466             :         case 1:
     467           0 :                 cmd.c_arg = SD_ARG_BUS_WIDTH_1;
     468           0 :                 break;
     469             : 
     470             :         case 4:
     471           0 :                 cmd.c_arg = SD_ARG_BUS_WIDTH_4;
     472           0 :                 break;
     473             : 
     474             :         default:
     475           0 :                 return EINVAL;
     476             :         }
     477             : 
     478           0 :         error = sdmmc_app_command(sc, &cmd);
     479           0 :         if (error == 0)
     480           0 :                 error = sdmmc_chip_bus_width(sc->sct, sc->sch, width);
     481           0 :         return error;
     482           0 : }
     483             : 
     484             : int
     485           0 : sdmmc_mem_sd_switch(struct sdmmc_function *sf, int mode, int group,
     486             :     int function, sdmmc_bitfield512_t *status)
     487             : {
     488           0 :         struct sdmmc_softc *sc = sf->sc;
     489           0 :         struct sdmmc_command cmd;
     490             :         void *ptr = NULL;
     491             :         int gsft, error = 0;
     492             :         const int statlen = 64;
     493             : 
     494           0 :         if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 &&
     495           0 :             !ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH))
     496           0 :                 return EINVAL;
     497             : 
     498           0 :         if (group <= 0 || group > 6 ||
     499           0 :             function < 0 || function > 15)
     500           0 :                 return EINVAL;
     501             : 
     502           0 :         gsft = (group - 1) << 2;
     503             : 
     504           0 :         ptr = malloc(statlen, M_DEVBUF, M_NOWAIT | M_ZERO);
     505           0 :         if (ptr == NULL)
     506             :                 goto out;
     507             : 
     508           0 :         memset(&cmd, 0, sizeof(cmd));
     509           0 :         cmd.c_data = ptr;
     510           0 :         cmd.c_datalen = statlen;
     511           0 :         cmd.c_blklen = statlen;
     512           0 :         cmd.c_opcode = SD_SEND_SWITCH_FUNC;
     513           0 :         cmd.c_arg =
     514           0 :             (!!mode << 31) | (function << gsft) | (0x00ffffff & ~(0xf << gsft));
     515           0 :         cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
     516             : 
     517           0 :         error = sdmmc_mmc_command(sc, &cmd);
     518           0 :         if (error == 0)
     519           0 :                 memcpy(status, ptr, statlen);
     520             : 
     521             : out:
     522           0 :         if (ptr != NULL)
     523           0 :                 free(ptr, M_DEVBUF, statlen);
     524             : 
     525           0 :         if (error == 0)
     526           0 :                 sdmmc_be512_to_bitfield512(status);
     527             : 
     528           0 :         return error;
     529           0 : }
     530             : 
     531             : int
     532           0 : sdmmc_mem_mmc_switch(struct sdmmc_function *sf, uint8_t set, uint8_t index,
     533             :     uint8_t value)
     534             : {
     535           0 :         struct sdmmc_softc *sc = sf->sc;
     536           0 :         struct sdmmc_command cmd;
     537             : 
     538           0 :         memset(&cmd, 0, sizeof(cmd));
     539           0 :         cmd.c_opcode = MMC_SWITCH;
     540           0 :         cmd.c_arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
     541           0 :             (index << 16) | (value << 8) | set;
     542           0 :         cmd.c_flags = SCF_RSP_R1B | SCF_CMD_AC;
     543             : 
     544           0 :         return sdmmc_mmc_command(sc, &cmd);
     545           0 : }
     546             : 
     547             : /*
     548             :  * Initialize a SD/MMC memory card.
     549             :  */
     550             : int
     551           0 : sdmmc_mem_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     552             : {
     553             :         int error = 0;
     554             : 
     555           0 :         rw_assert_wrlock(&sc->sc_lock);
     556             : 
     557           0 :         if (sdmmc_select_card(sc, sf) != 0 ||
     558           0 :             sdmmc_mem_set_blocklen(sc, sf) != 0)
     559           0 :                 error = 1;
     560             : 
     561           0 :         if (ISSET(sc->sc_flags, SMF_SD_MODE))
     562           0 :                 error = sdmmc_mem_sd_init(sc, sf);
     563             :         else
     564           0 :                 error = sdmmc_mem_mmc_init(sc, sf);
     565             : 
     566           0 :         return error;
     567             : }
     568             : 
     569             : /* make 512-bit BE quantity __bitfield()-compatible */
     570             : void
     571           0 : sdmmc_be512_to_bitfield512(sdmmc_bitfield512_t *buf) {
     572             :         size_t i;
     573             :         uint32_t tmp0, tmp1;
     574             :         const size_t bitswords = nitems(buf->_bits);
     575           0 :         for (i = 0; i < bitswords/2; i++) {
     576           0 :                 tmp0 = buf->_bits[i];
     577           0 :                 tmp1 = buf->_bits[bitswords - 1 - i];
     578           0 :                 buf->_bits[i] = be32toh(tmp1);
     579           0 :                 buf->_bits[bitswords - 1 - i] = be32toh(tmp0);
     580             :         }
     581           0 : }
     582             : 
     583             : int
     584           0 : sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     585             : {
     586             :         int support_func, best_func, error;
     587           0 :         sdmmc_bitfield512_t status; /* Switch Function Status */
     588           0 :         uint32_t raw_scr[2];
     589             : 
     590             :         /*
     591             :          * All SD cards are supposed to support Default Speed mode
     592             :          * with frequencies up to 25 MHz.  Bump up the clock frequency
     593             :          * now as data transfers don't seem to work on the Realtek
     594             :          * RTS5229 host controller if it is running at a low clock
     595             :          * frequency.  Reading the SCR requires a data transfer.
     596             :          */
     597           0 :         error = sdmmc_chip_bus_clock(sc->sct, sc->sch, SDMMC_SDCLK_25MHZ,
     598             :             SDMMC_TIMING_LEGACY);
     599           0 :         if (error) {
     600           0 :                 printf("%s: can't change bus clock\n", DEVNAME(sc));
     601           0 :                 return error;
     602             :         }
     603             : 
     604           0 :         error = sdmmc_mem_send_scr(sc, raw_scr);
     605           0 :         if (error) {
     606           0 :                 printf("%s: SD_SEND_SCR send failed\n", DEVNAME(sc));
     607           0 :                 return error;
     608             :         }
     609           0 :         error = sdmmc_mem_decode_scr(sc, raw_scr, sf);
     610           0 :         if (error)
     611           0 :                 return error;
     612             : 
     613           0 :         if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
     614           0 :             ISSET(sf->scr.bus_width, SCR_SD_BUS_WIDTHS_4BIT)) {
     615             :                 DPRINTF(("%s: change bus width\n", DEVNAME(sc)));
     616           0 :                 error = sdmmc_mem_set_bus_width(sf, 4);
     617           0 :                 if (error) {
     618           0 :                         printf("%s: can't change bus width\n", DEVNAME(sc));
     619           0 :                         return error;
     620             :                 }
     621             :         }
     622             : 
     623             :         best_func = 0;
     624           0 :         if (sf->scr.sd_spec >= SCR_SD_SPEC_VER_1_10 &&
     625           0 :             ISSET(sf->csd.ccc, SD_CSD_CCC_SWITCH)) {
     626             :                 DPRINTF(("%s: switch func mode 0\n", DEVNAME(sc)));
     627           0 :                 error = sdmmc_mem_sd_switch(sf, 0, 1, 0, &status);
     628           0 :                 if (error) {
     629           0 :                         printf("%s: switch func mode 0 failed\n", DEVNAME(sc));
     630           0 :                         return error;
     631             :                 }
     632             : 
     633           0 :                 support_func = SFUNC_STATUS_GROUP(&status, 1);
     634             : 
     635           0 :                 if (support_func & (1 << SD_ACCESS_MODE_SDR25))
     636           0 :                         best_func = 1;
     637             :         }
     638             : 
     639           0 :         if (best_func != 0) {
     640             :                 DPRINTF(("%s: switch func mode 1(func=%d)\n",
     641             :                     DEVNAME(sc), best_func));
     642             :                 error =
     643           0 :                     sdmmc_mem_sd_switch(sf, 1, 1, best_func, &status);
     644           0 :                 if (error) {
     645           0 :                         printf("%s: switch func mode 1 failed:"
     646             :                             " group 1 function %d(0x%2x)\n",
     647           0 :                             DEVNAME(sc), best_func, support_func);
     648           0 :                         return error;
     649             :                 }
     650             : 
     651             :                 /* Wait 400KHz x 8 clock (2.5us * 8 + slop) */
     652           0 :                 delay(25);
     653             : 
     654             :                 /* High Speed mode, Frequency up to 50MHz. */
     655           0 :                 error = sdmmc_chip_bus_clock(sc->sct, sc->sch,
     656             :                     SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED);
     657           0 :                 if (error) {
     658           0 :                         printf("%s: can't change bus clock\n", DEVNAME(sc));
     659           0 :                         return error;
     660             :                 }
     661             :         }
     662             : 
     663           0 :         return 0;
     664           0 : }
     665             : 
     666             : int
     667           0 : sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     668             : {
     669             :         int width, value;
     670             :         int card_type;
     671             :         int error = 0;
     672           0 :         u_int8_t ext_csd[512];
     673             :         int speed = 20000;
     674             :         int timing = SDMMC_TIMING_LEGACY;
     675             :         u_int32_t sectors = 0;
     676             : 
     677           0 :         error = sdmmc_chip_bus_clock(sc->sct, sc->sch, speed, timing);
     678           0 :         if (error) {
     679           0 :                 printf("%s: can't change bus clock\n", DEVNAME(sc));
     680           0 :                 return error;
     681             :         }
     682             : 
     683           0 :         if (sf->csd.mmcver >= MMC_CSD_MMCVER_4_0) {
     684             :                 /* read EXT_CSD */
     685           0 :                 error = sdmmc_mem_send_cxd_data(sc,
     686           0 :                     MMC_SEND_EXT_CSD, ext_csd, sizeof(ext_csd));
     687           0 :                 if (error != 0) {
     688           0 :                         SET(sf->flags, SFF_ERROR);
     689           0 :                         printf("%s: can't read EXT_CSD\n", DEVNAME(sc));
     690           0 :                         return error;
     691             :                 }
     692             : 
     693           0 :                 card_type = ext_csd[EXT_CSD_CARD_TYPE];
     694             : 
     695           0 :                 if (card_type & EXT_CSD_CARD_TYPE_F_52M_1_8V &&
     696           0 :                     ISSET(sc->sc_caps, SMC_CAPS_MMC_DDR52)) {
     697             :                         speed = 52000;
     698             :                         timing = SDMMC_TIMING_MMC_DDR52;
     699           0 :                 } else if (card_type & EXT_CSD_CARD_TYPE_F_52M &&
     700           0 :                     ISSET(sc->sc_caps, SMC_CAPS_MMC_HIGHSPEED)) {
     701             :                         speed = 52000;
     702             :                         timing = SDMMC_TIMING_HIGHSPEED;
     703           0 :                 } else if (card_type & EXT_CSD_CARD_TYPE_F_26M) {
     704             :                         speed = 26000;
     705           0 :                 } else {
     706           0 :                         printf("%s: unknown CARD_TYPE 0x%x\n", DEVNAME(sc),
     707           0 :                             ext_csd[EXT_CSD_CARD_TYPE]);
     708             :                 }
     709             : 
     710           0 :                 if (timing != SDMMC_TIMING_LEGACY) {
     711             :                         /* switch to high speed timing */
     712           0 :                         error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
     713             :                             EXT_CSD_HS_TIMING, EXT_CSD_HS_TIMING_HS);
     714           0 :                         if (error != 0) {
     715           0 :                                 printf("%s: can't change high speed\n",
     716           0 :                                     DEVNAME(sc));
     717           0 :                                 return error;
     718             :                         }
     719             : 
     720           0 :                         sdmmc_delay(10000);
     721           0 :                 }
     722             : 
     723           0 :                 error = sdmmc_chip_bus_clock(sc->sct, sc->sch, speed, SDMMC_TIMING_HIGHSPEED);
     724           0 :                 if (error != 0) {
     725           0 :                         printf("%s: can't change bus clock\n", DEVNAME(sc));
     726           0 :                         return error;
     727             :                 }
     728             : 
     729           0 :                 if (timing != SDMMC_TIMING_LEGACY) {
     730             :                         /* read EXT_CSD again */
     731           0 :                         error = sdmmc_mem_send_cxd_data(sc,
     732             :                             MMC_SEND_EXT_CSD, ext_csd, sizeof(ext_csd));
     733           0 :                         if (error != 0) {
     734           0 :                                 printf("%s: can't re-read EXT_CSD\n", DEVNAME(sc));
     735           0 :                                 return error;
     736             :                         }
     737           0 :                         if (ext_csd[EXT_CSD_HS_TIMING] != EXT_CSD_HS_TIMING_HS) {
     738           0 :                                 printf("%s, HS_TIMING set failed\n", DEVNAME(sc));
     739           0 :                                 return EINVAL;
     740             :                         }
     741             :                 }
     742             : 
     743           0 :                 if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
     744             :                         width = 8;
     745             :                         value = EXT_CSD_BUS_WIDTH_8;
     746           0 :                 } else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
     747             :                         width = 4;
     748             :                         value = EXT_CSD_BUS_WIDTH_4;
     749           0 :                 } else {
     750             :                         width = 1;
     751             :                         value = EXT_CSD_BUS_WIDTH_1;
     752             :                 }
     753             : 
     754           0 :                 if (width != 1) {
     755           0 :                         error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
     756           0 :                             EXT_CSD_BUS_WIDTH, value);
     757           0 :                         if (error == 0)
     758           0 :                                 error = sdmmc_chip_bus_width(sc->sct,
     759             :                                     sc->sch, width);
     760             :                         else {
     761             :                                 DPRINTF(("%s: can't change bus width"
     762             :                                     " (%d bit)\n", DEVNAME(sc), width));
     763           0 :                                 return error;
     764             :                         }
     765             : 
     766             :                         /* XXXX: need bus test? (using by CMD14 & CMD19) */
     767           0 :                         sdmmc_delay(10000);
     768           0 :                 }
     769             : 
     770           0 :                 if (timing == SDMMC_TIMING_MMC_DDR52) {
     771           0 :                         switch (width) {
     772             :                         case 4:
     773             :                                 value = EXT_CSD_BUS_WIDTH_4_DDR;
     774           0 :                                 break;
     775             :                         case 8:
     776             :                                 value = EXT_CSD_BUS_WIDTH_8_DDR;
     777           0 :                                 break;
     778             :                         }
     779             : 
     780           0 :                         error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
     781           0 :                             EXT_CSD_BUS_WIDTH, value);
     782           0 :                         if (error) {
     783           0 :                                 printf("%s: can't switch to DDR\n",
     784           0 :                                     DEVNAME(sc));
     785           0 :                                 return error;
     786             :                         }
     787             : 
     788           0 :                         sdmmc_delay(10000);
     789             : 
     790           0 :                         error = sdmmc_chip_signal_voltage(sc->sct, sc->sch,
     791             :                             SDMMC_SIGNAL_VOLTAGE_180);
     792           0 :                         if (error) {
     793           0 :                                 printf("%s: can't switch signalling voltage\n",
     794           0 :                                     DEVNAME(sc));
     795           0 :                                 return error;
     796             :                         }
     797             : 
     798           0 :                         error = sdmmc_chip_bus_clock(sc->sct, sc->sch, speed, timing);
     799           0 :                         if (error != 0) {
     800           0 :                                 printf("%s: can't change bus clock\n", DEVNAME(sc));
     801           0 :                                 return error;
     802             :                         }
     803             : 
     804           0 :                         sdmmc_delay(10000);
     805           0 :                 }
     806             : 
     807           0 :                 sectors = ext_csd[EXT_CSD_SEC_COUNT + 0] << 0 |
     808           0 :                     ext_csd[EXT_CSD_SEC_COUNT + 1] << 8  |
     809           0 :                     ext_csd[EXT_CSD_SEC_COUNT + 2] << 16 |
     810           0 :                     ext_csd[EXT_CSD_SEC_COUNT + 3] << 24;
     811             : 
     812           0 :                 if (sectors > (2u * 1024 * 1024 * 1024) / 512) {
     813           0 :                         sf->flags |= SFF_SDHC;
     814           0 :                         sf->csd.capacity = sectors;
     815           0 :                 }
     816             :         }
     817             : 
     818           0 :         return error;
     819           0 : }
     820             : 
     821             : /*
     822             :  * Get or set the card's memory OCR value (SD or MMC).
     823             :  */
     824             : int
     825           0 : sdmmc_mem_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr,
     826             :     u_int32_t *ocrp)
     827             : {
     828           0 :         struct sdmmc_command cmd;
     829             :         int error;
     830             :         int i;
     831             : 
     832           0 :         rw_assert_wrlock(&sc->sc_lock);
     833             : 
     834             :         /*
     835             :          * If we change the OCR value, retry the command until the OCR
     836             :          * we receive in response has the "CARD BUSY" bit set, meaning
     837             :          * that all cards are ready for identification.
     838             :          */
     839           0 :         for (i = 0; i < 100; i++) {
     840           0 :                 bzero(&cmd, sizeof cmd);
     841           0 :                 cmd.c_arg = ocr;
     842           0 :                 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R3;
     843             : 
     844           0 :                 if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
     845           0 :                         cmd.c_opcode = SD_APP_OP_COND;
     846           0 :                         error = sdmmc_app_command(sc, &cmd);
     847           0 :                 } else {
     848           0 :                         cmd.c_arg &= ~MMC_OCR_ACCESS_MODE_MASK;
     849           0 :                         cmd.c_arg |= MMC_OCR_SECTOR_MODE;
     850           0 :                         cmd.c_opcode = MMC_SEND_OP_COND;
     851           0 :                         error = sdmmc_mmc_command(sc, &cmd);
     852             :                 }
     853           0 :                 if (error != 0)
     854             :                         break;
     855           0 :                 if (ISSET(MMC_R3(cmd.c_resp), MMC_OCR_MEM_READY) ||
     856           0 :                     ocr == 0)
     857             :                         break;
     858             :                 error = ETIMEDOUT;
     859           0 :                 sdmmc_delay(10000);
     860             :         }
     861           0 :         if (error == 0 && ocrp != NULL)
     862           0 :                 *ocrp = MMC_R3(cmd.c_resp);
     863             : 
     864           0 :         return error;
     865           0 : }
     866             : 
     867             : /*
     868             :  * Set the read block length appropriately for this card, according to
     869             :  * the card CSD register value.
     870             :  */
     871             : int
     872           0 : sdmmc_mem_set_blocklen(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     873             : {
     874           0 :         struct sdmmc_command cmd;
     875             : 
     876           0 :         rw_assert_wrlock(&sc->sc_lock);
     877             : 
     878           0 :         bzero(&cmd, sizeof cmd);
     879           0 :         cmd.c_opcode = MMC_SET_BLOCKLEN;
     880           0 :         cmd.c_arg = sf->csd.sector_size;
     881           0 :         cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
     882             :         DPRINTF(("%s: read_bl_len=%d sector_size=%d\n", DEVNAME(sc),
     883             :             1 << sf->csd.read_bl_len, sf->csd.sector_size));
     884             : 
     885           0 :         return sdmmc_mmc_command(sc, &cmd);
     886           0 : }
     887             : 
     888             : int
     889           0 : sdmmc_mem_read_block_subr(struct sdmmc_function *sf, bus_dmamap_t dmap,
     890             :     int blkno, u_char *data, size_t datalen)
     891             : {
     892           0 :         struct sdmmc_softc *sc = sf->sc;
     893           0 :         struct sdmmc_command cmd;
     894             :         int error;
     895             : 
     896             : 
     897           0 :         if ((error = sdmmc_select_card(sc, sf)) != 0)
     898             :                 goto err;
     899             : 
     900           0 :         bzero(&cmd, sizeof cmd);
     901           0 :         cmd.c_data = data;
     902           0 :         cmd.c_datalen = datalen;
     903           0 :         cmd.c_blklen = sf->csd.sector_size;
     904           0 :         cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ?
     905             :             MMC_READ_BLOCK_MULTIPLE : MMC_READ_BLOCK_SINGLE;
     906           0 :         if (sf->flags & SFF_SDHC)
     907           0 :                 cmd.c_arg = blkno;
     908             :         else
     909           0 :                 cmd.c_arg = blkno << 9;
     910           0 :         cmd.c_flags = SCF_CMD_ADTC | SCF_CMD_READ | SCF_RSP_R1;
     911           0 :         cmd.c_dmamap = dmap;
     912             : 
     913           0 :         error = sdmmc_mmc_command(sc, &cmd);
     914           0 :         if (error != 0)
     915             :                 goto err;
     916             : 
     917           0 :         if (ISSET(sc->sc_flags, SMF_STOP_AFTER_MULTIPLE) &&
     918           0 :             cmd.c_opcode == MMC_READ_BLOCK_MULTIPLE) {
     919           0 :                 bzero(&cmd, sizeof cmd);
     920           0 :                 cmd.c_opcode = MMC_STOP_TRANSMISSION;
     921           0 :                 cmd.c_arg = MMC_ARG_RCA(sf->rca);
     922           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B;
     923           0 :                 error = sdmmc_mmc_command(sc, &cmd);
     924           0 :                 if (error != 0)
     925             :                         goto err;
     926             :         }
     927             : 
     928           0 :         do {
     929           0 :                 bzero(&cmd, sizeof cmd);
     930           0 :                 cmd.c_opcode = MMC_SEND_STATUS;
     931           0 :                 cmd.c_arg = MMC_ARG_RCA(sf->rca);
     932           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
     933           0 :                 error = sdmmc_mmc_command(sc, &cmd);
     934           0 :                 if (error != 0)
     935             :                         break;
     936             :                 /* XXX time out */
     937           0 :         } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA));
     938             : 
     939             : err:
     940           0 :         return (error);
     941           0 : }
     942             : 
     943             : int
     944           0 : sdmmc_mem_single_read_block(struct sdmmc_function *sf, int blkno, u_char *data,
     945             :     size_t datalen)
     946             : {
     947             :         int error = 0;
     948             :         int i;
     949             : 
     950           0 :         for (i = 0; i < datalen / sf->csd.sector_size; i++) {
     951           0 :                 error = sdmmc_mem_read_block_subr(sf, NULL,  blkno + i,
     952           0 :                     data + i * sf->csd.sector_size, sf->csd.sector_size);
     953           0 :                 if (error)
     954             :                         break;
     955             :         }
     956             : 
     957           0 :         return (error);
     958             : }
     959             : 
     960             : int
     961           0 : sdmmc_mem_read_block(struct sdmmc_function *sf, int blkno, u_char *data,
     962             :     size_t datalen)
     963             : {
     964           0 :         struct sdmmc_softc *sc = sf->sc;
     965             :         int error;
     966             : 
     967           0 :         rw_enter_write(&sc->sc_lock);
     968             : 
     969           0 :         if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) {
     970           0 :                 error = sdmmc_mem_single_read_block(sf, blkno, data, datalen);
     971           0 :                 goto out;
     972             :         }
     973             : 
     974           0 :         if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
     975           0 :                 error = sdmmc_mem_read_block_subr(sf, NULL, blkno,
     976             :                     data, datalen);
     977           0 :                 goto out;
     978             :         }
     979             : 
     980             :         /* DMA transfer */
     981           0 :         error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, data, datalen,
     982             :             NULL, BUS_DMA_NOWAIT|BUS_DMA_READ);
     983           0 :         if (error)
     984             :                 goto out;
     985             : 
     986           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
     987             :             BUS_DMASYNC_PREREAD);
     988             : 
     989           0 :         error = sdmmc_mem_read_block_subr(sf, sc->sc_dmap, blkno, data,
     990             :             datalen);
     991           0 :         if (error)
     992             :                 goto unload;
     993             : 
     994           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
     995             :             BUS_DMASYNC_POSTREAD);
     996             : unload:
     997           0 :         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
     998             : 
     999             : out:
    1000           0 :         rw_exit(&sc->sc_lock);
    1001           0 :         return (error);
    1002             : }
    1003             : 
    1004             : int
    1005           0 : sdmmc_mem_write_block_subr(struct sdmmc_function *sf, bus_dmamap_t dmap,
    1006             :     int blkno, u_char *data, size_t datalen)
    1007             : {
    1008           0 :         struct sdmmc_softc *sc = sf->sc;
    1009           0 :         struct sdmmc_command cmd;
    1010             :         int error;
    1011             : 
    1012           0 :         if ((error = sdmmc_select_card(sc, sf)) != 0)
    1013             :                 goto err;
    1014             : 
    1015           0 :         bzero(&cmd, sizeof cmd);
    1016           0 :         cmd.c_data = data;
    1017           0 :         cmd.c_datalen = datalen;
    1018           0 :         cmd.c_blklen = sf->csd.sector_size;
    1019           0 :         cmd.c_opcode = (datalen / cmd.c_blklen) > 1 ?
    1020             :             MMC_WRITE_BLOCK_MULTIPLE : MMC_WRITE_BLOCK_SINGLE;
    1021           0 :         if (sf->flags & SFF_SDHC)
    1022           0 :                 cmd.c_arg = blkno;
    1023             :         else
    1024           0 :                 cmd.c_arg = blkno << 9;
    1025           0 :         cmd.c_flags = SCF_CMD_ADTC | SCF_RSP_R1;
    1026           0 :         cmd.c_dmamap = dmap;
    1027             : 
    1028           0 :         error = sdmmc_mmc_command(sc, &cmd);
    1029           0 :         if (error != 0)
    1030             :                 goto err;
    1031             : 
    1032           0 :         if (ISSET(sc->sc_flags, SMF_STOP_AFTER_MULTIPLE) &&
    1033           0 :             cmd.c_opcode == MMC_WRITE_BLOCK_MULTIPLE) {
    1034           0 :                 bzero(&cmd, sizeof cmd);
    1035           0 :                 cmd.c_opcode = MMC_STOP_TRANSMISSION;
    1036           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1B;
    1037           0 :                 error = sdmmc_mmc_command(sc, &cmd);
    1038           0 :                 if (error != 0)
    1039             :                         goto err;
    1040             :         }
    1041             : 
    1042           0 :         do {
    1043           0 :                 bzero(&cmd, sizeof cmd);
    1044           0 :                 cmd.c_opcode = MMC_SEND_STATUS;
    1045           0 :                 cmd.c_arg = MMC_ARG_RCA(sf->rca);
    1046           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
    1047           0 :                 error = sdmmc_mmc_command(sc, &cmd);
    1048           0 :                 if (error != 0)
    1049             :                         break;
    1050             :                 /* XXX time out */
    1051           0 :         } while (!ISSET(MMC_R1(cmd.c_resp), MMC_R1_READY_FOR_DATA));
    1052             : 
    1053             : err:
    1054           0 :         return (error);
    1055           0 : }
    1056             : 
    1057             : int
    1058           0 : sdmmc_mem_single_write_block(struct sdmmc_function *sf, int blkno, u_char *data,
    1059             :     size_t datalen)
    1060             : {
    1061             :         int error = 0;
    1062             :         int i;
    1063             : 
    1064           0 :         for (i = 0; i < datalen / sf->csd.sector_size; i++) {
    1065           0 :                 error = sdmmc_mem_write_block_subr(sf, NULL, blkno + i,
    1066           0 :                     data + i * sf->csd.sector_size, sf->csd.sector_size);
    1067           0 :                 if (error)
    1068             :                         break;
    1069             :         }
    1070             : 
    1071           0 :         return (error);
    1072             : }
    1073             : 
    1074             : int
    1075           0 : sdmmc_mem_write_block(struct sdmmc_function *sf, int blkno, u_char *data,
    1076             :     size_t datalen)
    1077             : {
    1078           0 :         struct sdmmc_softc *sc = sf->sc;
    1079             :         int error;
    1080             : 
    1081           0 :         rw_enter_write(&sc->sc_lock);
    1082             : 
    1083           0 :         if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) {
    1084           0 :                 error = sdmmc_mem_single_write_block(sf, blkno, data, datalen);
    1085           0 :                 goto out;
    1086             :         }
    1087             : 
    1088           0 :         if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
    1089           0 :                 error = sdmmc_mem_write_block_subr(sf, NULL, blkno,
    1090             :                     data, datalen);
    1091           0 :                 goto out;
    1092             :         }
    1093             : 
    1094             :         /* DMA transfer */
    1095           0 :         error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, data, datalen,
    1096             :             NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
    1097           0 :         if (error)
    1098             :                 goto out;
    1099             : 
    1100           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
    1101             :             BUS_DMASYNC_PREWRITE);
    1102             : 
    1103           0 :         error = sdmmc_mem_write_block_subr(sf, sc->sc_dmap, blkno, data,
    1104             :             datalen);
    1105           0 :         if (error)
    1106             :                 goto unload;
    1107             : 
    1108           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
    1109             :             BUS_DMASYNC_POSTWRITE);
    1110             : unload:
    1111           0 :         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
    1112             : 
    1113             : out:
    1114           0 :         rw_exit(&sc->sc_lock);
    1115           0 :         return (error);
    1116             : }
    1117             : 
    1118             : #ifdef HIBERNATE
    1119             : int
    1120           0 : sdmmc_mem_hibernate_write(struct sdmmc_function *sf, daddr_t blkno,
    1121             :     u_char *data, size_t datalen)
    1122             : {
    1123           0 :         struct sdmmc_softc *sc = sf->sc;
    1124             :         int i, error;
    1125           0 :         struct bus_dmamap dmamap;
    1126           0 :         paddr_t phys_addr;
    1127             : 
    1128           0 :         if (ISSET(sc->sc_caps, SMC_CAPS_SINGLE_ONLY)) {
    1129           0 :                 for (i = 0; i < datalen / sf->csd.sector_size; i++) {
    1130           0 :                         error = sdmmc_mem_write_block_subr(sf, NULL, blkno + i,
    1131           0 :                             data + i * sf->csd.sector_size,
    1132             :                             sf->csd.sector_size);
    1133           0 :                         if (error)
    1134           0 :                                 return (error);
    1135             :                 }
    1136           0 :         } else if (!ISSET(sc->sc_caps, SMC_CAPS_DMA)) {
    1137           0 :                 return (sdmmc_mem_write_block_subr(sf, NULL, blkno, data,
    1138             :                     datalen));
    1139             :         }
    1140             : 
    1141             :         /* pretend we're bus_dmamap_load */
    1142           0 :         bzero(&dmamap, sizeof(dmamap));
    1143           0 :         pmap_extract(pmap_kernel(), (vaddr_t)data, &phys_addr);
    1144           0 :         dmamap.dm_mapsize = datalen;
    1145           0 :         dmamap.dm_nsegs = 1;
    1146           0 :         dmamap.dm_segs[0].ds_addr = phys_addr;
    1147           0 :         dmamap.dm_segs[0].ds_len = datalen;
    1148           0 :         return (sdmmc_mem_write_block_subr(sf, &dmamap, blkno, data, datalen));
    1149           0 : }
    1150             : #endif

Generated by: LCOV version 1.13