1 /* $OpenBSD: sdmmc_io.c,v 1.10 2007/09/17 01:33:33 krw 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 | M_ZERO); 615 if (ih == NULL) 616 return NULL; 617 618 ih->ih_name = malloc(strlen(name), M_DEVBUF, M_WAITOK | M_CANFAIL); 619 if (ih->ih_name == NULL) { 620 free(ih, M_DEVBUF); 621 return NULL; 622 } 623 strlcpy(ih->ih_name, name, strlen(name)); 624 ih->ih_softc = sc; 625 ih->ih_fun = fun; 626 ih->ih_arg = arg; 627 628 s = splhigh(); 629 if (TAILQ_EMPTY(&sc->sc_intrq)) { 630 sdmmc_intr_enable(sc->sc_fn0); 631 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 1); 632 } 633 TAILQ_INSERT_TAIL(&sc->sc_intrq, ih, entry); 634 splx(s); 635 return ih; 636 } 637 638 /* 639 * Disestablish the given handler. 640 */ 641 void 642 sdmmc_intr_disestablish(void *cookie) 643 { 644 struct sdmmc_intr_handler *ih = cookie; 645 struct sdmmc_softc *sc = ih->ih_softc; 646 int s; 647 648 if (sc->sct->card_intr_mask == NULL) 649 return; 650 651 s = splhigh(); 652 TAILQ_REMOVE(&sc->sc_intrq, ih, entry); 653 if (TAILQ_EMPTY(&sc->sc_intrq)) { 654 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 0); 655 sdmmc_intr_disable(sc->sc_fn0); 656 } 657 splx(s); 658 659 free(ih->ih_name, M_DEVBUF); 660 free(ih, M_DEVBUF); 661 } 662 663 /* 664 * Call established SDIO card interrupt handlers. The host controller 665 * must call this function from its own interrupt handler to handle an 666 * SDIO interrupt from the card. 667 */ 668 void 669 sdmmc_card_intr(struct device *sdmmc) 670 { 671 struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc; 672 673 if (sc->sct->card_intr_mask == NULL) 674 return; 675 676 if (!sdmmc_task_pending(&sc->sc_intr_task)) 677 sdmmc_add_task(sc, &sc->sc_intr_task); 678 } 679 680 void 681 sdmmc_intr_task(void *arg) 682 { 683 struct sdmmc_softc *sc = arg; 684 struct sdmmc_intr_handler *ih; 685 int s; 686 687 s = splhigh(); 688 TAILQ_FOREACH(ih, &sc->sc_intrq, entry) { 689 splx(s); 690 691 /* XXX examine return value and do evcount stuff*/ 692 (void)ih->ih_fun(ih->ih_arg); 693 694 s = splhigh(); 695 } 696 sdmmc_chip_card_intr_ack(sc->sct, sc->sch); 697 splx(s); 698 } 699