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