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

          Line data    Source code
       1             : /*      $OpenBSD: sdmmc.c,v 1.51 2018/08/09 13:52:36 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             : /*
      20             :  * Host controller independent SD/MMC bus driver based on information
      21             :  * from SanDisk SD Card Product Manual Revision 2.2 (SanDisk), SDIO
      22             :  * Simple Specification Version 1.0 (SDIO) and the Linux "mmc" driver.
      23             :  */
      24             : 
      25             : #include <sys/param.h>
      26             : #include <sys/device.h>
      27             : #include <sys/kernel.h>
      28             : #include <sys/kthread.h>
      29             : #include <sys/malloc.h>
      30             : #include <sys/rwlock.h>
      31             : #include <sys/systm.h>
      32             : 
      33             : #include <scsi/scsi_all.h>
      34             : #include <scsi/scsiconf.h>
      35             : 
      36             : #include <dev/sdmmc/sdmmc_scsi.h>
      37             : #include <dev/sdmmc/sdmmcchip.h>
      38             : #include <dev/sdmmc/sdmmcreg.h>
      39             : #include <dev/sdmmc/sdmmcvar.h>
      40             : 
      41             : #ifdef SDMMC_IOCTL
      42             : #include "bio.h"
      43             : #if NBIO < 1
      44             : #undef SDMMC_IOCTL
      45             : #endif
      46             : #include <dev/biovar.h>
      47             : #endif
      48             : 
      49             : int     sdmmc_match(struct device *, void *, void *);
      50             : void    sdmmc_attach(struct device *, struct device *, void *);
      51             : int     sdmmc_detach(struct device *, int);
      52             : int     sdmmc_activate(struct device *, int);
      53             : 
      54             : void    sdmmc_create_thread(void *);
      55             : void    sdmmc_task_thread(void *);
      56             : void    sdmmc_discover_task(void *);
      57             : void    sdmmc_card_attach(struct sdmmc_softc *);
      58             : void    sdmmc_card_detach(struct sdmmc_softc *, int);
      59             : int     sdmmc_enable(struct sdmmc_softc *);
      60             : void    sdmmc_disable(struct sdmmc_softc *);
      61             : int     sdmmc_scan(struct sdmmc_softc *);
      62             : int     sdmmc_init(struct sdmmc_softc *);
      63             : #ifdef SDMMC_IOCTL
      64             : int     sdmmc_ioctl(struct device *, u_long, caddr_t);
      65             : #endif
      66             : 
      67             : #ifdef SDMMC_DEBUG
      68             : int sdmmcdebug = 0;
      69             : extern int sdhcdebug;   /* XXX should have a sdmmc_chip_debug() function */
      70             : void sdmmc_dump_command(struct sdmmc_softc *, struct sdmmc_command *);
      71             : #define DPRINTF(n,s)    do { if ((n) <= sdmmcdebug) printf s; } while (0)
      72             : #else
      73             : #define DPRINTF(n,s)    do {} while (0)
      74             : #endif
      75             : 
      76             : struct cfattach sdmmc_ca = {
      77             :         sizeof(struct sdmmc_softc), sdmmc_match, sdmmc_attach, sdmmc_detach,
      78             :         sdmmc_activate
      79             : };
      80             : 
      81             : struct cfdriver sdmmc_cd = {
      82             :         NULL, "sdmmc", DV_DULL
      83             : };
      84             : 
      85             : int
      86           0 : sdmmc_match(struct device *parent, void *match, void *aux)
      87             : {
      88           0 :         struct cfdata *cf = match;
      89           0 :         struct sdmmcbus_attach_args *saa = aux;
      90             : 
      91           0 :         return strcmp(saa->saa_busname, cf->cf_driver->cd_name) == 0;
      92             : }
      93             : 
      94             : void
      95           0 : sdmmc_attach(struct device *parent, struct device *self, void *aux)
      96             : {
      97           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
      98           0 :         struct sdmmcbus_attach_args *saa = aux;
      99             :         int error;
     100             : 
     101           0 :         if (ISSET(saa->caps, SMC_CAPS_8BIT_MODE))
     102           0 :                 printf(": 8-bit");
     103           0 :         else if (ISSET(saa->caps, SMC_CAPS_4BIT_MODE))
     104           0 :                 printf(": 4-bit");
     105             :         else
     106           0 :                 printf(": 1-bit");
     107           0 :         if (ISSET(saa->caps, SMC_CAPS_SD_HIGHSPEED))
     108           0 :                 printf(", sd high-speed");
     109           0 :         if (ISSET(saa->caps, SMC_CAPS_MMC_HIGHSPEED))
     110           0 :                 printf(", mmc high-speed");
     111           0 :         if (ISSET(saa->caps, SMC_CAPS_DMA))
     112           0 :                 printf(", dma");
     113           0 :         printf("\n");
     114             : 
     115           0 :         sc->sct = saa->sct;
     116           0 :         sc->sch = saa->sch;
     117           0 :         sc->sc_dmat = saa->dmat;
     118           0 :         sc->sc_dmap = saa->dmap;
     119           0 :         sc->sc_flags = saa->flags;
     120           0 :         sc->sc_caps = saa->caps;
     121           0 :         sc->sc_max_xfer = saa->max_xfer;
     122           0 :         memcpy(&sc->sc_cookies, &saa->cookies, sizeof(sc->sc_cookies));
     123             : 
     124           0 :         if (ISSET(sc->sc_caps, SMC_CAPS_DMA) && sc->sc_dmap == NULL) {
     125           0 :                 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SDMMC_MAXNSEGS,
     126             :                     MAXPHYS, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmap);
     127           0 :                 if (error) {
     128           0 :                         printf("%s: can't create DMA map\n", DEVNAME(sc));
     129           0 :                         return;
     130             :                 }
     131             :         }
     132             : 
     133           0 :         SIMPLEQ_INIT(&sc->sf_head);
     134           0 :         TAILQ_INIT(&sc->sc_tskq);
     135           0 :         TAILQ_INIT(&sc->sc_intrq);
     136           0 :         sdmmc_init_task(&sc->sc_discover_task, sdmmc_discover_task, sc);
     137           0 :         sdmmc_init_task(&sc->sc_intr_task, sdmmc_intr_task, sc);
     138           0 :         rw_init(&sc->sc_lock, DEVNAME(sc));
     139             : 
     140             : #ifdef SDMMC_IOCTL
     141             :         if (bio_register(self, sdmmc_ioctl) != 0)
     142             :                 printf("%s: unable to register ioctl\n", DEVNAME(sc));
     143             : #endif
     144             : 
     145             :         /*
     146             :          * Create the event thread that will attach and detach cards
     147             :          * and perform other lengthy operations.  Enter config_pending
     148             :          * state until the discovery task has run for the first time.
     149             :          */
     150           0 :         SET(sc->sc_flags, SMF_CONFIG_PENDING);
     151           0 :         config_pending_incr();
     152           0 :         kthread_create_deferred(sdmmc_create_thread, sc);
     153           0 : }
     154             : 
     155             : int
     156           0 : sdmmc_detach(struct device *self, int flags)
     157             : {
     158           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
     159             : 
     160           0 :         sc->sc_dying = 1;
     161           0 :         while (sc->sc_task_thread != NULL) {
     162           0 :                 wakeup(&sc->sc_tskq);
     163           0 :                 tsleep(sc, PWAIT, "mmcdie", 0);
     164             :         }
     165             : 
     166           0 :         if (sc->sc_dmap)
     167           0 :                 bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap);
     168             : 
     169           0 :         return 0;
     170             : }
     171             : 
     172             : int
     173           0 : sdmmc_activate(struct device *self, int act)
     174             : {
     175           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
     176             :         int rv = 0;
     177             : 
     178           0 :         switch (act) {
     179             :         case DVACT_SUSPEND:
     180           0 :                 rv = config_activate_children(self, act);
     181             :                 /* If card in slot, cause a detach/re-attach */
     182           0 :                 if (ISSET(sc->sc_flags, SMF_CARD_PRESENT))
     183           0 :                         sc->sc_dying = -1;
     184             :                 break;
     185             :         case DVACT_RESUME:
     186           0 :                 rv = config_activate_children(self, act);
     187           0 :                 wakeup(&sc->sc_tskq);
     188           0 :                 break;
     189             :         default:
     190           0 :                 rv = config_activate_children(self, act);
     191           0 :                 break;
     192             :         }
     193           0 :         return (rv);
     194             : }
     195             : 
     196             : void
     197           0 : sdmmc_create_thread(void *arg)
     198             : {
     199           0 :         struct sdmmc_softc *sc = arg;
     200             : 
     201           0 :         if (kthread_create(sdmmc_task_thread, sc, &sc->sc_task_thread,
     202           0 :             DEVNAME(sc)) != 0)
     203           0 :                 printf("%s: can't create task thread\n", DEVNAME(sc));
     204             : 
     205           0 : }
     206             : 
     207             : void
     208           0 : sdmmc_task_thread(void *arg)
     209             : {
     210           0 :         struct sdmmc_softc *sc = arg;
     211             :         struct sdmmc_task *task;
     212           0 :         int s;
     213             : 
     214             : restart:
     215           0 :         sdmmc_needs_discover(&sc->sc_dev);
     216             : 
     217           0 :         s = splsdmmc();
     218           0 :         while (!sc->sc_dying) {
     219           0 :                 for (task = TAILQ_FIRST(&sc->sc_tskq); task != NULL;
     220           0 :                      task = TAILQ_FIRST(&sc->sc_tskq)) {
     221           0 :                         splx(s);
     222           0 :                         sdmmc_del_task(task);
     223           0 :                         task->func(task->arg);
     224           0 :                         s = splsdmmc();
     225             :                 }
     226           0 :                 tsleep(&sc->sc_tskq, PWAIT, "mmctsk", 0);
     227             :         }
     228           0 :         splx(s);
     229             : 
     230           0 :         if (ISSET(sc->sc_flags, SMF_CARD_PRESENT)) {
     231           0 :                 rw_enter_write(&sc->sc_lock);
     232           0 :                 sdmmc_card_detach(sc, DETACH_FORCE);
     233           0 :                 rw_exit(&sc->sc_lock);
     234           0 :         }
     235             : 
     236             :         /*
     237             :          * During a suspend, the card is detached since we do not know
     238             :          * if it is the same upon wakeup.  Go re-discover the bus.
     239             :          */
     240           0 :         if (sc->sc_dying == -1) {
     241           0 :                 CLR(sc->sc_flags, SMF_CARD_PRESENT);
     242           0 :                 sc->sc_dying = 0;
     243           0 :                 goto restart;
     244             :         }
     245           0 :         sc->sc_task_thread = NULL;
     246           0 :         wakeup(sc);
     247           0 :         kthread_exit(0);
     248             : }
     249             : 
     250             : void
     251           0 : sdmmc_add_task(struct sdmmc_softc *sc, struct sdmmc_task *task)
     252             : {
     253             :         int s;
     254             : 
     255           0 :         s = splsdmmc();
     256           0 :         TAILQ_INSERT_TAIL(&sc->sc_tskq, task, next);
     257           0 :         task->onqueue = 1;
     258           0 :         task->sc = sc;
     259           0 :         wakeup(&sc->sc_tskq);
     260           0 :         splx(s);
     261           0 : }
     262             : 
     263             : void
     264           0 : sdmmc_del_task(struct sdmmc_task *task)
     265             : {
     266           0 :         struct sdmmc_softc *sc = task->sc;
     267             :         int s;
     268             : 
     269           0 :         if (sc == NULL)
     270           0 :                 return;
     271             : 
     272           0 :         s = splsdmmc();
     273           0 :         task->sc = NULL;
     274           0 :         task->onqueue = 0;
     275           0 :         TAILQ_REMOVE(&sc->sc_tskq, task, next);
     276           0 :         splx(s);
     277           0 : }
     278             : 
     279             : void
     280           0 : sdmmc_needs_discover(struct device *self)
     281             : {
     282           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
     283             : 
     284           0 :         if (!sdmmc_task_pending(&sc->sc_discover_task))
     285           0 :                 sdmmc_add_task(sc, &sc->sc_discover_task);
     286           0 : }
     287             : 
     288             : void
     289           0 : sdmmc_discover_task(void *arg)
     290             : {
     291           0 :         struct sdmmc_softc *sc = arg;
     292             : 
     293           0 :         if (sdmmc_chip_card_detect(sc->sct, sc->sch)) {
     294           0 :                 if (!ISSET(sc->sc_flags, SMF_CARD_PRESENT)) {
     295           0 :                         SET(sc->sc_flags, SMF_CARD_PRESENT);
     296           0 :                         sdmmc_card_attach(sc);
     297           0 :                 }
     298             :         } else {
     299           0 :                 if (ISSET(sc->sc_flags, SMF_CARD_PRESENT)) {
     300           0 :                         CLR(sc->sc_flags, SMF_CARD_PRESENT);
     301           0 :                         rw_enter_write(&sc->sc_lock);
     302           0 :                         sdmmc_card_detach(sc, DETACH_FORCE);
     303           0 :                         rw_exit(&sc->sc_lock);
     304           0 :                 }
     305             :         }
     306             : 
     307           0 :         if (ISSET(sc->sc_flags, SMF_CONFIG_PENDING)) {
     308           0 :                 CLR(sc->sc_flags, SMF_CONFIG_PENDING);
     309           0 :                 config_pending_decr();
     310           0 :         }
     311           0 : }
     312             : 
     313             : /*
     314             :  * Called from process context when a card is present.
     315             :  */
     316             : void
     317           0 : sdmmc_card_attach(struct sdmmc_softc *sc)
     318             : {
     319             :         DPRINTF(1,("%s: attach card\n", DEVNAME(sc)));
     320             : 
     321           0 :         rw_enter_write(&sc->sc_lock);
     322           0 :         CLR(sc->sc_flags, SMF_CARD_ATTACHED);
     323             : 
     324             :         /*
     325             :          * Power up the card (or card stack).
     326             :          */
     327           0 :         if (sdmmc_enable(sc) != 0) {
     328           0 :                 printf("%s: can't enable card\n", DEVNAME(sc));
     329           0 :                 goto err;
     330             :         }
     331             : 
     332             :         /*
     333             :          * Scan for I/O functions and memory cards on the bus,
     334             :          * allocating a sdmmc_function structure for each.
     335             :          */
     336           0 :         if (sdmmc_scan(sc) != 0) {
     337           0 :                 printf("%s: no functions\n", DEVNAME(sc));
     338           0 :                 goto err;
     339             :         }
     340             : 
     341             :         /*
     342             :          * Initialize the I/O functions and memory cards.
     343             :          */
     344           0 :         if (sdmmc_init(sc) != 0) {
     345           0 :                 printf("%s: init failed\n", DEVNAME(sc));
     346           0 :                 goto err;
     347             :         }
     348             : 
     349             :         /* Attach SCSI emulation for memory cards. */
     350           0 :         if (ISSET(sc->sc_flags, SMF_MEM_MODE))
     351           0 :                 sdmmc_scsi_attach(sc);
     352             : 
     353             :         /* Attach I/O function drivers. */
     354           0 :         if (ISSET(sc->sc_flags, SMF_IO_MODE))
     355           0 :                 sdmmc_io_attach(sc);
     356             : 
     357           0 :         SET(sc->sc_flags, SMF_CARD_ATTACHED);
     358           0 :         rw_exit(&sc->sc_lock);
     359           0 :         return;
     360             : err:
     361           0 :         sdmmc_card_detach(sc, DETACH_FORCE);
     362           0 :         rw_exit(&sc->sc_lock);
     363           0 : }
     364             : 
     365             : /*
     366             :  * Called from process context with DETACH_* flags from <sys/device.h>
     367             :  * when cards are gone.
     368             :  */
     369             : void
     370           0 : sdmmc_card_detach(struct sdmmc_softc *sc, int flags)
     371             : {
     372             :         struct sdmmc_function *sf, *sfnext;
     373             : 
     374           0 :         rw_assert_wrlock(&sc->sc_lock);
     375             : 
     376             :         DPRINTF(1,("%s: detach card\n", DEVNAME(sc)));
     377             : 
     378           0 :         if (ISSET(sc->sc_flags, SMF_CARD_ATTACHED)) {
     379             :                 /* Detach I/O function drivers. */
     380           0 :                 if (ISSET(sc->sc_flags, SMF_IO_MODE))
     381           0 :                         sdmmc_io_detach(sc);
     382             : 
     383             :                 /* Detach the SCSI emulation for memory cards. */
     384           0 :                 if (ISSET(sc->sc_flags, SMF_MEM_MODE))
     385           0 :                         sdmmc_scsi_detach(sc);
     386             : 
     387           0 :                 CLR(sc->sc_flags, SMF_CARD_ATTACHED);
     388           0 :         }
     389             : 
     390             :         /* Power down. */
     391           0 :         sdmmc_disable(sc);
     392             : 
     393             :         /* Free all sdmmc_function structures. */
     394           0 :         for (sf = SIMPLEQ_FIRST(&sc->sf_head); sf != NULL; sf = sfnext) {
     395           0 :                 sfnext = SIMPLEQ_NEXT(sf, sf_list);
     396           0 :                 sdmmc_function_free(sf);
     397             :         }
     398           0 :         SIMPLEQ_INIT(&sc->sf_head);
     399           0 :         sc->sc_function_count = 0;
     400           0 :         sc->sc_fn0 = NULL;
     401           0 : }
     402             : 
     403             : int
     404           0 : sdmmc_enable(struct sdmmc_softc *sc)
     405             : {
     406             :         u_int32_t host_ocr;
     407             :         int error;
     408             : 
     409           0 :         rw_assert_wrlock(&sc->sc_lock);
     410             : 
     411             :         /*
     412             :          * Calculate the equivalent of the card OCR from the host
     413             :          * capabilities and select the maximum supported bus voltage.
     414             :          */
     415           0 :         host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
     416           0 :         error = sdmmc_chip_bus_power(sc->sct, sc->sch, host_ocr);
     417           0 :         if (error != 0) {
     418           0 :                 printf("%s: can't supply bus power\n", DEVNAME(sc));
     419           0 :                 goto err;
     420             :         }
     421             : 
     422             :         /*
     423             :          * Select the minimum clock frequency.
     424             :          */
     425           0 :         error = sdmmc_chip_bus_clock(sc->sct, sc->sch,
     426             :             SDMMC_SDCLK_400KHZ, SDMMC_TIMING_LEGACY);
     427           0 :         if (error != 0) {
     428           0 :                 printf("%s: can't supply clock\n", DEVNAME(sc));
     429           0 :                 goto err;
     430             :         }
     431             : 
     432             :         /* XXX wait for card to power up */
     433           0 :         sdmmc_delay(250000);
     434             : 
     435             :         /* Initialize SD I/O card function(s). */
     436           0 :         if ((error = sdmmc_io_enable(sc)) != 0)
     437             :                 goto err;
     438             : 
     439             :         /* Initialize SD/MMC memory card(s). */
     440           0 :         if (ISSET(sc->sc_flags, SMF_MEM_MODE) &&
     441           0 :             (error = sdmmc_mem_enable(sc)) != 0)
     442             :                 goto err;
     443             : 
     444             :  err:
     445           0 :         if (error != 0)
     446           0 :                 sdmmc_disable(sc);
     447             : 
     448           0 :         return error;
     449             : }
     450             : 
     451             : void
     452           0 : sdmmc_disable(struct sdmmc_softc *sc)
     453             : {
     454             :         /* XXX complete commands if card is still present. */
     455             : 
     456           0 :         rw_assert_wrlock(&sc->sc_lock);
     457             : 
     458             :         /* Make sure no card is still selected. */
     459           0 :         (void)sdmmc_select_card(sc, NULL);
     460             : 
     461             :         /* Turn off bus power and clock. */
     462           0 :         (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
     463             :             SDMMC_SDCLK_OFF, SDMMC_TIMING_LEGACY);
     464           0 :         (void)sdmmc_chip_bus_power(sc->sct, sc->sch, 0);
     465           0 : }
     466             : 
     467             : /*
     468             :  * Set the lowest bus voltage supported by the card and the host.
     469             :  */
     470             : int
     471           0 : sdmmc_set_bus_power(struct sdmmc_softc *sc, u_int32_t host_ocr,
     472             :     u_int32_t card_ocr)
     473             : {
     474             :         u_int32_t bit;
     475             : 
     476           0 :         rw_assert_wrlock(&sc->sc_lock);
     477             : 
     478             :         /* Mask off unsupported voltage levels and select the lowest. */
     479             :         DPRINTF(1,("%s: host_ocr=%x ", DEVNAME(sc), host_ocr));
     480           0 :         host_ocr &= card_ocr;
     481           0 :         for (bit = 4; bit < 23; bit++) {
     482           0 :                 if (ISSET(host_ocr, 1<<bit)) {
     483           0 :                         host_ocr &= 3<<bit;
     484           0 :                         break;
     485             :                 }
     486             :         }
     487             :         DPRINTF(1,("card_ocr=%x new_ocr=%x\n", card_ocr, host_ocr));
     488             : 
     489           0 :         if (host_ocr == 0 ||
     490           0 :             sdmmc_chip_bus_power(sc->sct, sc->sch, host_ocr) != 0)
     491           0 :                 return 1;
     492           0 :         return 0;
     493           0 : }
     494             : 
     495             : struct sdmmc_function *
     496           0 : sdmmc_function_alloc(struct sdmmc_softc *sc)
     497             : {
     498             :         struct sdmmc_function *sf;
     499             : 
     500           0 :         sf = (struct sdmmc_function *)malloc(sizeof *sf, M_DEVBUF,
     501             :             M_WAITOK | M_ZERO);
     502           0 :         sf->sc = sc;
     503           0 :         sf->number = -1;
     504           0 :         sf->cis.manufacturer = SDMMC_VENDOR_INVALID;
     505           0 :         sf->cis.product = SDMMC_PRODUCT_INVALID;
     506           0 :         sf->cis.function = SDMMC_FUNCTION_INVALID;
     507           0 :         sf->cur_blklen = sdmmc_chip_host_maxblklen(sc->sct, sc->sch);
     508           0 :         return sf;
     509             : }
     510             : 
     511             : void
     512           0 : sdmmc_function_free(struct sdmmc_function *sf)
     513             : {
     514           0 :         free(sf, M_DEVBUF, sizeof *sf);
     515           0 : }
     516             : 
     517             : /*
     518             :  * Scan for I/O functions and memory cards on the bus, allocating a
     519             :  * sdmmc_function structure for each.
     520             :  */
     521             : int
     522           0 : sdmmc_scan(struct sdmmc_softc *sc)
     523             : {
     524             : 
     525           0 :         rw_assert_wrlock(&sc->sc_lock);
     526             : 
     527             :         /* Scan for I/O functions. */
     528           0 :         if (ISSET(sc->sc_flags, SMF_IO_MODE))
     529           0 :                 sdmmc_io_scan(sc);
     530             : 
     531             :         /* Scan for memory cards on the bus. */
     532           0 :         if (ISSET(sc->sc_flags, SMF_MEM_MODE))
     533           0 :                 sdmmc_mem_scan(sc);
     534             : 
     535             :         /* There should be at least one function now. */
     536           0 :         if (SIMPLEQ_EMPTY(&sc->sf_head)) {
     537           0 :                 printf("%s: can't identify card\n", DEVNAME(sc));
     538           0 :                 return 1;
     539             :         }
     540           0 :         return 0;
     541           0 : }
     542             : 
     543             : /*
     544             :  * Initialize all the distinguished functions of the card, be it I/O
     545             :  * or memory functions.
     546             :  */
     547             : int
     548           0 : sdmmc_init(struct sdmmc_softc *sc)
     549             : {
     550             :         struct sdmmc_function *sf;
     551             : 
     552           0 :         rw_assert_wrlock(&sc->sc_lock);
     553             : 
     554             :         /* Initialize all identified card functions. */
     555           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     556           0 :                 if (ISSET(sc->sc_flags, SMF_IO_MODE) &&
     557           0 :                     sdmmc_io_init(sc, sf) != 0)
     558           0 :                         printf("%s: i/o init failed\n", DEVNAME(sc));
     559             : 
     560           0 :                 if (ISSET(sc->sc_flags, SMF_MEM_MODE) &&
     561           0 :                     sdmmc_mem_init(sc, sf) != 0)
     562           0 :                         printf("%s: mem init failed\n", DEVNAME(sc));
     563             :         }
     564             : 
     565             :         /* Any good functions left after initialization? */
     566           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     567           0 :                 if (!ISSET(sf->flags, SFF_ERROR))
     568           0 :                         return 0;
     569             :         }
     570             :         /* No, we should probably power down the card. */
     571           0 :         return 1;
     572           0 : }
     573             : 
     574             : void
     575           0 : sdmmc_delay(u_int usecs)
     576             : {
     577           0 :         int nticks = usecs / (1000000 / hz);
     578             : 
     579           0 :         if (!cold && nticks > 0)
     580           0 :                 tsleep(&sdmmc_delay, PWAIT, "mmcdly", nticks);
     581             :         else
     582           0 :                 delay(usecs);
     583           0 : }
     584             : 
     585             : int
     586           0 : sdmmc_app_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
     587             : {
     588           0 :         struct sdmmc_command acmd;
     589             :         int error;
     590             : 
     591           0 :         rw_assert_wrlock(&sc->sc_lock);
     592             : 
     593           0 :         bzero(&acmd, sizeof acmd);
     594           0 :         acmd.c_opcode = MMC_APP_CMD;
     595           0 :         acmd.c_arg = 0;
     596           0 :         if (sc->sc_card != NULL) {
     597           0 :                 acmd.c_arg = sc->sc_card->rca << 16;
     598           0 :         }
     599           0 :         acmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
     600             : 
     601           0 :         error = sdmmc_mmc_command(sc, &acmd);
     602           0 :         if (error != 0) {
     603           0 :                 return error;
     604             :         }
     605             : 
     606           0 :         if (!ISSET(MMC_R1(acmd.c_resp), MMC_R1_APP_CMD)) {
     607             :                 /* Card does not support application commands. */
     608           0 :                 return ENODEV;
     609             :         }
     610             : 
     611           0 :         error = sdmmc_mmc_command(sc, cmd);
     612           0 :         return error;
     613           0 : }
     614             : 
     615             : /*
     616             :  * Execute MMC command and data transfers.  All interactions with the
     617             :  * host controller to complete the command happen in the context of
     618             :  * the current process.
     619             :  */
     620             : int
     621           0 : sdmmc_mmc_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
     622             : {
     623             :         int error;
     624             : 
     625           0 :         rw_assert_wrlock(&sc->sc_lock);
     626             : 
     627           0 :         sdmmc_chip_exec_command(sc->sct, sc->sch, cmd);
     628             : 
     629             : #ifdef SDMMC_DEBUG
     630             :         sdmmc_dump_command(sc, cmd);
     631             : #endif
     632             : 
     633           0 :         error = cmd->c_error;
     634           0 :         if (!cold)
     635           0 :                 wakeup(cmd);
     636             : 
     637           0 :         return error;
     638             : }
     639             : 
     640             : /*
     641             :  * Send the "GO IDLE STATE" command.
     642             :  */
     643             : void
     644           0 : sdmmc_go_idle_state(struct sdmmc_softc *sc)
     645             : {
     646           0 :         struct sdmmc_command cmd;
     647             : 
     648           0 :         rw_assert_wrlock(&sc->sc_lock);
     649             : 
     650           0 :         bzero(&cmd, sizeof cmd);
     651           0 :         cmd.c_opcode = MMC_GO_IDLE_STATE;
     652           0 :         cmd.c_flags = SCF_CMD_BC | SCF_RSP_R0;
     653             : 
     654           0 :         (void)sdmmc_mmc_command(sc, &cmd);
     655           0 : }
     656             : 
     657             : /*
     658             :  * Send the "SEND_IF_COND" command, to check operating condition
     659             :  */
     660             : int
     661           0 : sdmmc_send_if_cond(struct sdmmc_softc *sc, uint32_t card_ocr)
     662             : {
     663           0 :         struct sdmmc_command cmd;
     664             :         uint8_t pat = 0x23;     /* any pattern will do here */
     665             :         uint8_t res;
     666             : 
     667           0 :         rw_assert_wrlock(&sc->sc_lock);
     668             : 
     669           0 :         bzero(&cmd, sizeof cmd);
     670             : 
     671           0 :         cmd.c_opcode = SD_SEND_IF_COND;
     672           0 :         cmd.c_arg = ((card_ocr & SD_OCR_VOL_MASK) != 0) << 8 | pat;
     673           0 :         cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R7;
     674             : 
     675           0 :         if (sdmmc_mmc_command(sc, &cmd) != 0)
     676           0 :                 return 1;
     677             : 
     678           0 :         res = cmd.c_resp[0];
     679           0 :         if (res != pat)
     680           0 :                 return 1;
     681             :         else
     682           0 :                 return 0;
     683           0 : }
     684             : 
     685             : /*
     686             :  * Retrieve (SD) or set (MMC) the relative card address (RCA).
     687             :  */
     688             : int
     689           0 : sdmmc_set_relative_addr(struct sdmmc_softc *sc,
     690             :     struct sdmmc_function *sf)
     691             : {
     692           0 :         struct sdmmc_command cmd;
     693             : 
     694           0 :         rw_assert_wrlock(&sc->sc_lock);
     695             : 
     696           0 :         bzero(&cmd, sizeof cmd);
     697             : 
     698           0 :         if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
     699             :                 cmd.c_opcode = SD_SEND_RELATIVE_ADDR;
     700           0 :                 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R6;
     701           0 :         } else {
     702             :                 cmd.c_opcode = MMC_SET_RELATIVE_ADDR;
     703           0 :                 cmd.c_arg = MMC_ARG_RCA(sf->rca);
     704           0 :                 cmd.c_flags = SCF_CMD_AC | SCF_RSP_R1;
     705             :         }
     706             : 
     707           0 :         if (sdmmc_mmc_command(sc, &cmd) != 0)
     708           0 :                 return 1;
     709             : 
     710           0 :         if (ISSET(sc->sc_flags, SMF_SD_MODE))
     711           0 :                 sf->rca = SD_R6_RCA(cmd.c_resp);
     712           0 :         return 0;
     713           0 : }
     714             : 
     715             : int
     716           0 : sdmmc_select_card(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     717             : {
     718           0 :         struct sdmmc_command cmd;
     719             :         int error;
     720             : 
     721           0 :         rw_assert_wrlock(&sc->sc_lock);
     722             : 
     723           0 :         if (sc->sc_card == sf || (sf && sc->sc_card &&
     724           0 :             sc->sc_card->rca == sf->rca)) {
     725           0 :                 sc->sc_card = sf;
     726           0 :                 return 0;
     727             :         }
     728             : 
     729           0 :         bzero(&cmd, sizeof cmd);
     730           0 :         cmd.c_opcode = MMC_SELECT_CARD;
     731           0 :         cmd.c_arg = sf == NULL ? 0 : MMC_ARG_RCA(sf->rca);
     732           0 :         cmd.c_flags = SCF_CMD_AC | (sf == NULL ? SCF_RSP_R0 : SCF_RSP_R1);
     733           0 :         error = sdmmc_mmc_command(sc, &cmd);
     734           0 :         if (error == 0 || sf == NULL)
     735           0 :                 sc->sc_card = sf;
     736           0 :         return error;
     737           0 : }
     738             : 
     739             : #ifdef SDMMC_IOCTL
     740             : int
     741             : sdmmc_ioctl(struct device *self, u_long request, caddr_t addr)
     742             : {
     743             :         struct sdmmc_softc *sc = (struct sdmmc_softc *)self;
     744             :         struct sdmmc_command *ucmd;
     745             :         struct sdmmc_command cmd;
     746             :         void *data;
     747             :         int error = 0;
     748             : 
     749             :         switch (request) {
     750             : #ifdef SDMMC_DEBUG
     751             :         case SDIOCSETDEBUG:
     752             :                 sdmmcdebug = (((struct bio_sdmmc_debug *)addr)->debug) & 0xff;
     753             :                 sdhcdebug = (((struct bio_sdmmc_debug *)addr)->debug >> 8) & 0xff;
     754             :                 break;
     755             : #endif
     756             : 
     757             :         case SDIOCEXECMMC:
     758             :         case SDIOCEXECAPP:
     759             :                 ucmd = &((struct bio_sdmmc_command *)addr)->cmd;
     760             : 
     761             :                 /* Refuse to transfer more than 512K per command. */
     762             :                 if (ucmd->c_datalen > 524288)
     763             :                         return ENOMEM;
     764             : 
     765             :                 /* Verify that the data buffer is safe to copy. */
     766             :                 if ((ucmd->c_datalen > 0 && ucmd->c_data == NULL) ||
     767             :                     (ucmd->c_datalen < 1 && ucmd->c_data != NULL) ||
     768             :                     ucmd->c_datalen < 0)
     769             :                         return EINVAL;
     770             : 
     771             :                 bzero(&cmd, sizeof cmd);
     772             :                 cmd.c_opcode = ucmd->c_opcode;
     773             :                 cmd.c_arg = ucmd->c_arg;
     774             :                 cmd.c_flags = ucmd->c_flags;
     775             :                 cmd.c_blklen = ucmd->c_blklen;
     776             : 
     777             :                 if (ucmd->c_data) {
     778             :                         data = malloc(ucmd->c_datalen, M_TEMP,
     779             :                             M_WAITOK | M_CANFAIL);
     780             :                         if (data == NULL)
     781             :                                 return ENOMEM;
     782             :                         error = copyin(ucmd->c_data, data, ucmd->c_datalen);
     783             :                         if (error != 0)
     784             :                                 goto exec_done;
     785             : 
     786             :                         cmd.c_data = data;
     787             :                         cmd.c_datalen = ucmd->c_datalen;
     788             :                 }
     789             : 
     790             :                 rw_enter_write(&sc->sc_lock);
     791             :                 if (request == SDIOCEXECMMC)
     792             :                         error = sdmmc_mmc_command(sc, &cmd);
     793             :                 else
     794             :                         error = sdmmc_app_command(sc, &cmd);
     795             :                 rw_exit(&sc->sc_lock);
     796             :                 if (error && !cmd.c_error)
     797             :                         cmd.c_error = error;
     798             : 
     799             :                 bcopy(&cmd.c_resp, ucmd->c_resp, sizeof cmd.c_resp);
     800             :                 ucmd->c_flags = cmd.c_flags;
     801             :                 ucmd->c_error = cmd.c_error;
     802             : 
     803             :                 if (ucmd->c_data)
     804             :                         error = copyout(data, ucmd->c_data, ucmd->c_datalen);
     805             :                 else
     806             :                         error = 0;
     807             : 
     808             : exec_done:
     809             :                 if (ucmd->c_data)
     810             :                         free(data, M_TEMP, ucmd->c_datalen);
     811             :                 break;
     812             : 
     813             :         default:
     814             :                 return ENOTTY;
     815             :         }
     816             :         return error;
     817             : }
     818             : #endif
     819             : 
     820             : #ifdef SDMMC_DEBUG
     821             : void
     822             : sdmmc_dump_command(struct sdmmc_softc *sc, struct sdmmc_command *cmd)
     823             : {
     824             :         int i;
     825             : 
     826             :         rw_assert_wrlock(&sc->sc_lock);
     827             : 
     828             :         DPRINTF(1,("%s: cmd %u arg=%#x data=%p dlen=%d flags=%#x "
     829             :             "proc=\"%s\" (error %d)\n", DEVNAME(sc), cmd->c_opcode,
     830             :             cmd->c_arg, cmd->c_data, cmd->c_datalen, cmd->c_flags,
     831             :             curproc ? curproc->p_p->ps_comm : "", cmd->c_error));
     832             : 
     833             :         if (cmd->c_error || sdmmcdebug < 1)
     834             :                 return;
     835             : 
     836             :         printf("%s: resp=", DEVNAME(sc));
     837             :         if (ISSET(cmd->c_flags, SCF_RSP_136))
     838             :                 for (i = 0; i < sizeof cmd->c_resp; i++)
     839             :                         printf("%02x ", ((u_char *)cmd->c_resp)[i]);
     840             :         else if (ISSET(cmd->c_flags, SCF_RSP_PRESENT))
     841             :                 for (i = 0; i < 4; i++)
     842             :                         printf("%02x ", ((u_char *)cmd->c_resp)[i]);
     843             :         printf("\n");
     844             : }
     845             : #endif

Generated by: LCOV version 1.13