root/dev/sdmmc/sdmmc_io.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdmmc_io_enable
  2. sdmmc_io_scan
  3. sdmmc_io_init
  4. sdmmc_io_function_ready
  5. sdmmc_io_function_enable
  6. sdmmc_io_function_disable
  7. sdmmc_io_attach
  8. sdmmc_submatch
  9. sdmmc_print
  10. sdmmc_io_detach
  11. sdmmc_io_rw_direct
  12. sdmmc_io_rw_extended
  13. sdmmc_io_read_1
  14. sdmmc_io_write_1
  15. sdmmc_io_read_2
  16. sdmmc_io_write_2
  17. sdmmc_io_read_4
  18. sdmmc_io_write_4
  19. sdmmc_io_read_multi_1
  20. sdmmc_io_write_multi_1
  21. sdmmc_io_xchg
  22. sdmmc_io_reset
  23. sdmmc_io_send_op_cond
  24. sdmmc_intr_enable
  25. sdmmc_intr_disable
  26. sdmmc_intr_establish
  27. sdmmc_intr_disestablish
  28. sdmmc_card_intr
  29. sdmmc_intr_task

    1 /*      $OpenBSD: sdmmc_io.c,v 1.9 2007/06/02 01:48:37 uwe 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 I/O cards. */
   20 
   21 #include <sys/param.h>
   22 #include <sys/kernel.h>
   23 #include <sys/malloc.h>
   24 #include <sys/proc.h>
   25 #include <sys/systm.h>
   26 
   27 #include <dev/sdmmc/sdmmc_ioreg.h>
   28 #include <dev/sdmmc/sdmmcchip.h>
   29 #include <dev/sdmmc/sdmmcreg.h>
   30 #include <dev/sdmmc/sdmmcvar.h>
   31 
   32 struct sdmmc_intr_handler {
   33         struct sdmmc_softc *ih_softc;
   34         char *ih_name;
   35         int (*ih_fun)(void *);
   36         void *ih_arg;
   37         TAILQ_ENTRY(sdmmc_intr_handler) entry;
   38 };
   39 
   40 int     sdmmc_submatch(struct device *, void *, void *);
   41 int     sdmmc_print(void *, const char *);
   42 int     sdmmc_io_rw_direct(struct sdmmc_softc *, struct sdmmc_function *,
   43             int, u_char *, int);
   44 int     sdmmc_io_rw_extended(struct sdmmc_softc *, struct sdmmc_function *,
   45             int, u_char *, int, int);
   46 int     sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
   47             int, u_char *);
   48 void    sdmmc_io_reset(struct sdmmc_softc *);
   49 int     sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
   50 
   51 #ifdef SDMMC_DEBUG
   52 #define DPRINTF(s)      printf s
   53 #else
   54 #define DPRINTF(s)      /**/
   55 #endif
   56 
   57 #ifdef SDMMC_DEBUG
   58 int     sdmmc_verbose = 1;
   59 #else
   60 int     sdmmc_verbose = 0;
   61 #endif
   62 
   63 /*
   64  * Initialize SD I/O card functions (before memory cards).  The host
   65  * system and controller must support card interrupts in order to use
   66  * I/O functions.
   67  */
   68 int
   69 sdmmc_io_enable(struct sdmmc_softc *sc)
   70 {
   71         u_int32_t host_ocr;
   72         u_int32_t card_ocr;
   73 
   74         /* Set host mode to SD "combo" card. */
   75         SET(sc->sc_flags, SMF_SD_MODE|SMF_IO_MODE|SMF_MEM_MODE);
   76 
   77         /* Reset I/O functions. */
   78         sdmmc_io_reset(sc);
   79 
   80         /*
   81          * Read the I/O OCR value, determine the number of I/O
   82          * functions and whether memory is also present (a "combo
   83          * card") by issuing CMD5.  SD memory-only and MMC cards
   84          * do not respond to CMD5.
   85          */
   86         if (sdmmc_io_send_op_cond(sc, 0, &card_ocr) != 0) {
   87                 /* No SDIO card; switch to SD memory-only mode. */
   88                 CLR(sc->sc_flags, SMF_IO_MODE);
   89                 return 0;
   90         }
   91 
   92         /* Parse the additional bits in the I/O OCR value. */
   93         if (!ISSET(card_ocr, SD_IO_OCR_MEM_PRESENT)) {
   94                 /* SDIO card without memory (not a "combo card"). */
   95                 DPRINTF(("%s: no memory present\n", SDMMCDEVNAME(sc)));
   96                 CLR(sc->sc_flags, SMF_MEM_MODE);
   97         }
   98         sc->sc_function_count = SD_IO_OCR_NUM_FUNCTIONS(card_ocr);
   99         if (sc->sc_function_count == 0) {
  100                 /* Useless SDIO card without any I/O functions. */
  101                 DPRINTF(("%s: no I/O functions\n", SDMMCDEVNAME(sc)));
  102                 CLR(sc->sc_flags, SMF_IO_MODE);
  103                 return 0;
  104         }
  105         card_ocr &= SD_IO_OCR_MASK;
  106 
  107         /* Set the lowest voltage supported by the card and host. */
  108         host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
  109         if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
  110                 printf("%s: can't supply voltage requested by card\n",
  111                     SDMMCDEVNAME(sc));
  112                 return 1;
  113         }
  114 
  115         /* Reset I/O functions (again). */
  116         sdmmc_io_reset(sc);
  117 
  118         /* Send the new OCR value until all cards are ready. */
  119         if (sdmmc_io_send_op_cond(sc, host_ocr, NULL) != 0) {
  120                 printf("%s: can't send I/O OCR\n", SDMMCDEVNAME(sc));
  121                 return 1;
  122         }
  123         return 0;
  124 }
  125 
  126 /*
  127  * Allocate sdmmc_function structures for SD card I/O function
  128  * (including function 0).
  129  */
  130 void
  131 sdmmc_io_scan(struct sdmmc_softc *sc)
  132 {
  133         struct sdmmc_function *sf0, *sf;
  134         int i;
  135 
  136         sf0 = sdmmc_function_alloc(sc);
  137         sf0->number = 0;
  138         if (sdmmc_set_relative_addr(sc, sf0) != 0) {
  139                 printf("%s: can't set I/O RCA\n", SDMMCDEVNAME(sc));
  140                 SET(sf0->flags, SFF_ERROR);
  141                 return;
  142         }
  143         sc->sc_fn0 = sf0;
  144         SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf0, sf_list);
  145 
  146         /* Verify that the RCA has been set by selecting the card. */
  147         if (sdmmc_select_card(sc, sf0) != 0) {
  148                 printf("%s: can't select I/O RCA %d\n", SDMMCDEVNAME(sc),
  149                     sf0->rca);
  150                 SET(sf0->flags, SFF_ERROR);
  151                 return;
  152         }
  153 
  154         for (i = 1; i <= sc->sc_function_count; i++) {
  155                 sf = sdmmc_function_alloc(sc);
  156                 sf->number = i;
  157                 sf->rca = sf0->rca;
  158 
  159                 SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
  160         }
  161 }
  162 
  163 /*
  164  * Initialize SDIO card functions.
  165  */
  166 int
  167 sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
  168 {
  169         if (sf->number == 0) {
  170                 sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH,
  171                     CCCR_BUS_WIDTH_1);
  172 
  173                 if (sdmmc_read_cis(sf, &sf->cis) != 0) {
  174                         printf("%s: can't read CIS\n", SDMMCDEVNAME(sc));
  175                         SET(sf->flags, SFF_ERROR);
  176                         return 1;
  177                 }
  178 
  179                 sdmmc_check_cis_quirks(sf);
  180 
  181                 if (sdmmc_verbose)
  182                         sdmmc_print_cis(sf);
  183         }
  184         return 0;
  185 }
  186 
  187 /*
  188  * Indicate whether the function is ready to operate.
  189  */
  190 int
  191 sdmmc_io_function_ready(struct sdmmc_function *sf)
  192 {
  193         struct sdmmc_softc *sc = sf->sc;
  194         struct sdmmc_function *sf0 = sc->sc_fn0;
  195         u_int8_t rv;
  196 
  197         if (sf->number == 0)
  198                 return 1;       /* FN0 is always ready */
  199 
  200         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_READY);
  201         return (rv & (1 << sf->number)) != 0;
  202 }
  203 
  204 /*
  205  * Enable the I/O function.  Return zero if the function was
  206  * enabled successfully.
  207  */
  208 int
  209 sdmmc_io_function_enable(struct sdmmc_function *sf)
  210 {
  211         struct sdmmc_softc *sc = sf->sc;
  212         struct sdmmc_function *sf0 = sc->sc_fn0;
  213         u_int8_t rv;
  214         int retry = 5;
  215 
  216         if (sf->number == 0)
  217                 return 0;       /* FN0 is always enabled */
  218 
  219         SDMMC_LOCK(sc);
  220         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
  221         rv |= (1<<sf->number);
  222         sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
  223         SDMMC_UNLOCK(sc);
  224 
  225         while (!sdmmc_io_function_ready(sf) && retry-- > 0)
  226                 tsleep(&lbolt, PPAUSE, "pause", 0);
  227         return (retry >= 0) ? 0 : ETIMEDOUT;
  228 }
  229 
  230 /*
  231  * Disable the I/O function.  Return zero if the function was
  232  * disabled successfully.
  233  */
  234 void
  235 sdmmc_io_function_disable(struct sdmmc_function *sf)
  236 {
  237         struct sdmmc_softc *sc = sf->sc;
  238         struct sdmmc_function *sf0 = sc->sc_fn0;
  239         u_int8_t rv;
  240 
  241         if (sf->number == 0)
  242                 return;         /* FN0 is always enabled */
  243 
  244         SDMMC_LOCK(sc);
  245         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
  246         rv &= ~(1<<sf->number);
  247         sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
  248         SDMMC_UNLOCK(sc);
  249 }
  250 
  251 void
  252 sdmmc_io_attach(struct sdmmc_softc *sc)
  253 {
  254         struct sdmmc_function *sf;
  255         struct sdmmc_attach_args saa;
  256 
  257         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
  258                 if (sf->number < 1)
  259                         continue;
  260 
  261                 bzero(&saa, sizeof saa);
  262                 saa.sf = sf;
  263 
  264                 sf->child = config_found_sm(&sc->sc_dev, &saa, sdmmc_print,
  265                     sdmmc_submatch);
  266         }
  267 }
  268 
  269 int
  270 sdmmc_submatch(struct device *parent, void *match, void *aux)
  271 {
  272         struct cfdata *cf = match;
  273 
  274         /* Skip the scsibus, it is configured directly. */
  275         if (strcmp(cf->cf_driver->cd_name, "scsibus") == 0)
  276                 return 0;
  277 
  278         return cf->cf_attach->ca_match(parent, cf, aux);
  279 }
  280 
  281 int
  282 sdmmc_print(void *aux, const char *pnp)
  283 {
  284         struct sdmmc_attach_args *sa = aux;
  285         struct sdmmc_function *sf = sa->sf;
  286         struct sdmmc_cis *cis = &sf->sc->sc_fn0->cis;
  287         int i;
  288 
  289         if (pnp) {
  290                 if (sf->number == 0)
  291                         return QUIET;
  292 
  293                 for (i = 0; i < 4 && cis->cis1_info[i]; i++)
  294                         printf("%s%s", i ? ", " : "\"", cis->cis1_info[i]);
  295                 if (i != 0)
  296                         printf("\"");
  297 
  298                 if (cis->manufacturer != SDMMC_VENDOR_INVALID &&
  299                     cis->product != SDMMC_PRODUCT_INVALID) {
  300                         printf("%s(", i ? " " : "");
  301                         if (cis->manufacturer != SDMMC_VENDOR_INVALID)
  302                                 printf("manufacturer 0x%x%s",
  303                                     cis->manufacturer,
  304                                     cis->product == SDMMC_PRODUCT_INVALID ?
  305                                     "" : ", ");
  306                         if (cis->product != SDMMC_PRODUCT_INVALID)
  307                                 printf("product 0x%x", cis->product);
  308                         printf(")");
  309                 }
  310                 printf("%sat %s", i ? " " : "", pnp);
  311         }
  312         printf(" function %d", sf->number);
  313 
  314         if (!pnp) {
  315                 for (i = 0; i < 3 && cis->cis1_info[i]; i++)
  316                         printf("%s%s", i ? ", " : " \"", cis->cis1_info[i]);
  317                 if (i != 0)
  318                         printf("\"");
  319         }
  320         return UNCONF;
  321 }
  322 
  323 void
  324 sdmmc_io_detach(struct sdmmc_softc *sc)
  325 {
  326         struct sdmmc_function *sf;
  327 
  328         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
  329                 if (sf->child != NULL) {
  330                         config_detach(sf->child, DETACH_FORCE);
  331                         sf->child = NULL;
  332                 }
  333         }
  334 
  335         KASSERT(TAILQ_EMPTY(&sc->sc_intrq));
  336 }
  337 
  338 int
  339 sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf,
  340     int reg, u_char *datap, int arg)
  341 {
  342         struct sdmmc_command cmd;
  343         int error;
  344 
  345         SDMMC_LOCK(sc);
  346 
  347         /* Make sure the card is selected. */
  348         if ((error = sdmmc_select_card(sc, sf)) != 0) {
  349                 SDMMC_UNLOCK(sc);
  350                 return error;
  351         }
  352 
  353         arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD52_FUNC_MASK) <<
  354             SD_ARG_CMD52_FUNC_SHIFT;
  355         arg |= (reg & SD_ARG_CMD52_REG_MASK) <<
  356             SD_ARG_CMD52_REG_SHIFT;
  357         arg |= (*datap & SD_ARG_CMD52_DATA_MASK) <<
  358             SD_ARG_CMD52_DATA_SHIFT;
  359 
  360         bzero(&cmd, sizeof cmd);
  361         cmd.c_opcode = SD_IO_RW_DIRECT;
  362         cmd.c_arg = arg;
  363         cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
  364 
  365         error = sdmmc_mmc_command(sc, &cmd);
  366         *datap = SD_R5_DATA(cmd.c_resp);
  367 
  368         SDMMC_UNLOCK(sc);
  369         return error;
  370 }
  371 
  372 /*
  373  * Useful values of `arg' to pass in are either SD_ARG_CMD53_READ or
  374  * SD_ARG_CMD53_WRITE.  SD_ARG_CMD53_INCREMENT may be ORed into `arg'
  375  * to access successive register locations instead of accessing the
  376  * same register many times.
  377  */
  378 int
  379 sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
  380     int reg, u_char *datap, int datalen, int arg)
  381 {
  382         struct sdmmc_command cmd;
  383         int error;
  384 
  385         SDMMC_LOCK(sc);
  386 
  387 #if 0
  388         /* Make sure the card is selected. */
  389         if ((error = sdmmc_select_card(sc, sf)) != 0) {
  390                 SDMMC_UNLOCK(sc);
  391                 return error;
  392         }
  393 #endif
  394 
  395         arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD53_FUNC_MASK) <<
  396             SD_ARG_CMD53_FUNC_SHIFT;
  397         arg |= (reg & SD_ARG_CMD53_REG_MASK) <<
  398             SD_ARG_CMD53_REG_SHIFT;
  399         arg |= (datalen & SD_ARG_CMD53_LENGTH_MASK) <<
  400             SD_ARG_CMD53_LENGTH_SHIFT;
  401 
  402         bzero(&cmd, sizeof cmd);
  403         cmd.c_opcode = SD_IO_RW_EXTENDED;
  404         cmd.c_arg = arg;
  405         cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
  406         cmd.c_data = datap;
  407         cmd.c_datalen = datalen;
  408         cmd.c_blklen = MIN(datalen, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
  409 
  410         if (!ISSET(arg, SD_ARG_CMD53_WRITE))
  411                 cmd.c_flags |= SCF_CMD_READ;
  412 
  413         error = sdmmc_mmc_command(sc, &cmd);
  414         SDMMC_UNLOCK(sc);
  415         return error;
  416 }
  417 
  418 u_int8_t
  419 sdmmc_io_read_1(struct sdmmc_function *sf, int reg)
  420 {
  421         u_int8_t data = 0;
  422         
  423         (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
  424             SD_ARG_CMD52_READ);
  425         return data;
  426 }
  427 
  428 void
  429 sdmmc_io_write_1(struct sdmmc_function *sf, int reg, u_int8_t data)
  430 {
  431         (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
  432             SD_ARG_CMD52_WRITE);
  433 }
  434 
  435 u_int16_t
  436 sdmmc_io_read_2(struct sdmmc_function *sf, int reg)
  437 {
  438         u_int16_t data = 0;
  439         
  440         (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2,
  441             SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
  442         return data;
  443 }
  444 
  445 void
  446 sdmmc_io_write_2(struct sdmmc_function *sf, int reg, u_int16_t data)
  447 {
  448         (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 2,
  449             SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
  450 }
  451 
  452 u_int32_t
  453 sdmmc_io_read_4(struct sdmmc_function *sf, int reg)
  454 {
  455         u_int32_t data = 0;
  456         
  457         (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4,
  458             SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
  459         return data;
  460 }
  461 
  462 void
  463 sdmmc_io_write_4(struct sdmmc_function *sf, int reg, u_int32_t data)
  464 {
  465         (void)sdmmc_io_rw_extended(sf->sc, sf, reg, (u_char *)&data, 4,
  466             SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
  467 }
  468 
  469 int
  470 sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
  471     int datalen)
  472 {
  473         int error;
  474 
  475         while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
  476                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
  477                     SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_READ);
  478                 if (error)
  479                         return error;
  480                 data += SD_ARG_CMD53_LENGTH_MAX;
  481                 datalen -= SD_ARG_CMD53_LENGTH_MAX;
  482         }
  483 
  484         return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
  485             SD_ARG_CMD53_READ);
  486 }
  487 
  488 int
  489 sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
  490     int datalen)
  491 {
  492         int error;
  493 
  494         while (datalen > SD_ARG_CMD53_LENGTH_MAX) {
  495                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
  496                     SD_ARG_CMD53_LENGTH_MAX, SD_ARG_CMD53_WRITE);
  497                 if (error)
  498                         return error;
  499                 data += SD_ARG_CMD53_LENGTH_MAX;
  500                 datalen -= SD_ARG_CMD53_LENGTH_MAX;
  501         }
  502 
  503         return sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
  504             SD_ARG_CMD53_WRITE);
  505 }
  506 
  507 int
  508 sdmmc_io_xchg(struct sdmmc_softc *sc, struct sdmmc_function *sf,
  509     int reg, u_char *datap)
  510 {
  511         return sdmmc_io_rw_direct(sc, sf, reg, datap,
  512             SD_ARG_CMD52_WRITE|SD_ARG_CMD52_EXCHANGE);
  513 }
  514 
  515 /*
  516  * Reset the I/O functions of the card.
  517  */
  518 void
  519 sdmmc_io_reset(struct sdmmc_softc *sc)
  520 {
  521 #if 0 /* XXX command fails */
  522         (void)sdmmc_io_write(sc, NULL, SD_IO_REG_CCCR_CTL, CCCR_CTL_RES);
  523         sdmmc_delay(100000);
  524 #endif
  525 }
  526 
  527 /*
  528  * Get or set the card's I/O OCR value (SDIO).
  529  */
  530 int
  531 sdmmc_io_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr, u_int32_t *ocrp)
  532 {
  533         struct sdmmc_command cmd;
  534         int error;
  535         int i;
  536 
  537         SDMMC_LOCK(sc);
  538 
  539         /*
  540          * If we change the OCR value, retry the command until the OCR
  541          * we receive in response has the "CARD BUSY" bit set, meaning
  542          * that all cards are ready for identification.
  543          */
  544         for (i = 0; i < 100; i++) {
  545                 bzero(&cmd, sizeof cmd);
  546                 cmd.c_opcode = SD_IO_SEND_OP_COND;
  547                 cmd.c_arg = ocr;
  548                 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R4;
  549 
  550                 error = sdmmc_mmc_command(sc, &cmd);
  551                 if (error != 0)
  552                         break;
  553                 if (ISSET(MMC_R4(cmd.c_resp), SD_IO_OCR_MEM_READY) ||
  554                     ocr == 0)
  555                         break;
  556                 error = ETIMEDOUT;
  557                 sdmmc_delay(10000);
  558         }
  559         if (error == 0 && ocrp != NULL)
  560                 *ocrp = MMC_R4(cmd.c_resp);
  561 
  562         SDMMC_UNLOCK(sc);
  563         return error;
  564 }
  565 
  566 /*
  567  * Card interrupt handling
  568  */
  569 
  570 void
  571 sdmmc_intr_enable(struct sdmmc_function *sf)
  572 {
  573         struct sdmmc_softc *sc = sf->sc;
  574         struct sdmmc_function *sf0 = sc->sc_fn0;
  575         u_int8_t imask;
  576 
  577         SDMMC_LOCK(sc);
  578         imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
  579         imask |= 1 << sf->number;
  580         sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
  581         SDMMC_UNLOCK(sc);
  582 }
  583 
  584 void
  585 sdmmc_intr_disable(struct sdmmc_function *sf)
  586 {
  587         struct sdmmc_softc *sc = sf->sc;
  588         struct sdmmc_function *sf0 = sc->sc_fn0;
  589         u_int8_t imask;
  590 
  591         SDMMC_LOCK(sc);
  592         imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
  593         imask &= ~(1 << sf->number);
  594         sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
  595         SDMMC_UNLOCK(sc);
  596 }
  597 
  598 /*
  599  * Establish a handler for the SDIO card interrupt.  Because the
  600  * interrupt may be shared with different SDIO functions, multiple
  601  * handlers can be established.
  602  */
  603 void *
  604 sdmmc_intr_establish(struct device *sdmmc, int (*fun)(void *),
  605     void *arg, const char *name)
  606 {
  607         struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
  608         struct sdmmc_intr_handler *ih;
  609         int s;
  610 
  611         if (sc->sct->card_intr_mask == NULL)
  612                 return NULL;
  613 
  614         ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK | M_CANFAIL);
  615         if (ih == NULL)
  616                 return NULL;
  617 
  618         bzero(ih, sizeof *ih);
  619         ih->ih_name = malloc(strlen(name), M_DEVBUF, M_WAITOK | M_CANFAIL);
  620         if (ih->ih_name == NULL) {
  621                 free(ih, M_DEVBUF);
  622                 return NULL;
  623         }
  624         strlcpy(ih->ih_name, name, strlen(name));
  625         ih->ih_softc = sc;
  626         ih->ih_fun = fun;
  627         ih->ih_arg = arg;
  628 
  629         s = splhigh();
  630         if (TAILQ_EMPTY(&sc->sc_intrq)) {
  631                 sdmmc_intr_enable(sc->sc_fn0);
  632                 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 1);
  633         }
  634         TAILQ_INSERT_TAIL(&sc->sc_intrq, ih, entry);
  635         splx(s);
  636         return ih;
  637 }
  638 
  639 /*
  640  * Disestablish the given handler.
  641  */
  642 void
  643 sdmmc_intr_disestablish(void *cookie)
  644 {
  645         struct sdmmc_intr_handler *ih = cookie;
  646         struct sdmmc_softc *sc = ih->ih_softc;
  647         int s;
  648 
  649         if (sc->sct->card_intr_mask == NULL)
  650                 return;
  651 
  652         s = splhigh();
  653         TAILQ_REMOVE(&sc->sc_intrq, ih, entry);
  654         if (TAILQ_EMPTY(&sc->sc_intrq)) {
  655                 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 0);
  656                 sdmmc_intr_disable(sc->sc_fn0);
  657         }
  658         splx(s);
  659 
  660         free(ih->ih_name, M_DEVBUF);
  661         free(ih, M_DEVBUF);
  662 }
  663 
  664 /*
  665  * Call established SDIO card interrupt handlers.  The host controller
  666  * must call this function from its own interrupt handler to handle an
  667  * SDIO interrupt from the card.
  668  */
  669 void
  670 sdmmc_card_intr(struct device *sdmmc)
  671 {
  672         struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
  673 
  674         if (sc->sct->card_intr_mask == NULL)
  675                 return;
  676 
  677         if (!sdmmc_task_pending(&sc->sc_intr_task))
  678                 sdmmc_add_task(sc, &sc->sc_intr_task);
  679 }
  680 
  681 void
  682 sdmmc_intr_task(void *arg)
  683 {
  684         struct sdmmc_softc *sc = arg;
  685         struct sdmmc_intr_handler *ih;
  686         int s;
  687 
  688         s = splhigh();
  689         TAILQ_FOREACH(ih, &sc->sc_intrq, entry) {
  690                 splx(s);
  691 
  692                 /* XXX examine return value and do evcount stuff*/
  693                 (void)ih->ih_fun(ih->ih_arg);
  694 
  695                 s = splhigh();
  696         }
  697         sdmmc_chip_card_intr_ack(sc->sct, sc->sch);
  698         splx(s);
  699 }

/* [<][>][^][v][top][bottom][index][help] */