1 /* $OpenBSD: pcmcia.c,v 1.39 2007/09/11 13:39:34 gilles Exp $ */ 2 /* $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $ */ 3 4 /* 5 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #include <sys/malloc.h> 38 39 #include <dev/pcmcia/pcmciareg.h> 40 #include <dev/pcmcia/pcmciachip.h> 41 #include <dev/pcmcia/pcmciavar.h> 42 43 #ifdef PCMCIADEBUG 44 #define DPRINTF(arg) printf arg 45 #else 46 #define DPRINTF(arg) 47 #endif 48 49 #ifdef PCMCIAVERBOSE 50 int pcmcia_verbose = 1; 51 #else 52 int pcmcia_verbose = 0; 53 #endif 54 55 int pcmcia_match(struct device *, void *, void *); 56 int pcmcia_submatch(struct device *, void *, void *); 57 void pcmcia_attach(struct device *, struct device *, void *); 58 int pcmcia_print(void *, const char *); 59 void pcmcia_card_detach_notify(struct device *, void *); 60 void pcmcia_power(int why, void *arg); 61 62 static inline void pcmcia_socket_enable(pcmcia_chipset_tag_t, 63 pcmcia_chipset_handle_t *); 64 static inline void pcmcia_socket_disable(pcmcia_chipset_tag_t, 65 pcmcia_chipset_handle_t *); 66 67 int pcmcia_card_intr(void *); 68 69 struct cfdriver pcmcia_cd = { 70 NULL, "pcmcia", DV_DULL 71 }; 72 73 struct cfattach pcmcia_ca = { 74 sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach 75 }; 76 77 int 78 pcmcia_ccr_read(pf, ccr) 79 struct pcmcia_function *pf; 80 int ccr; 81 { 82 83 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh, 84 pf->pf_ccr_offset + ccr)); 85 } 86 87 void 88 pcmcia_ccr_write(pf, ccr, val) 89 struct pcmcia_function *pf; 90 int ccr; 91 int val; 92 { 93 94 if ((pf->ccr_mask) & (1 << (ccr / 2))) { 95 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh, 96 pf->pf_ccr_offset + ccr, val); 97 } 98 } 99 100 int 101 pcmcia_match(parent, match, aux) 102 struct device *parent; 103 void *match, *aux; 104 { 105 struct cfdata *cf = match; 106 struct pcmciabus_attach_args *paa = aux; 107 108 if (strcmp(paa->paa_busname, cf->cf_driver->cd_name)) 109 return 0; 110 111 /* If the autoconfiguration got this far, there's a socket here. */ 112 return (1); 113 } 114 115 void 116 pcmcia_attach(parent, self, aux) 117 struct device *parent, *self; 118 void *aux; 119 { 120 struct pcmciabus_attach_args *paa = aux; 121 struct pcmcia_softc *sc = (struct pcmcia_softc *) self; 122 123 printf("\n"); 124 125 sc->pct = paa->pct; 126 sc->pch = paa->pch; 127 sc->iobase = paa->iobase; 128 sc->iosize = paa->iosize; 129 130 sc->ih = NULL; 131 powerhook_establish(pcmcia_power, sc); 132 } 133 134 void 135 pcmcia_power(why, arg) 136 int why; 137 void *arg; 138 { 139 struct pcmcia_softc *sc = (struct pcmcia_softc *) arg; 140 struct pcmcia_function *pf; 141 struct device *d; 142 int act = DVACT_ACTIVATE; 143 144 if (why != PWR_RESUME) 145 act = DVACT_DEACTIVATE; 146 147 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 148 pf = SIMPLEQ_NEXT(pf, pf_list)) { 149 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL) 150 continue; 151 d = pf->child; 152 if (d == NULL) 153 continue; 154 if (act == DVACT_ACTIVATE) 155 config_activate(pf->child); 156 else 157 config_deactivate(pf->child); 158 } 159 } 160 161 int 162 pcmcia_card_attach(dev) 163 struct device *dev; 164 { 165 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; 166 struct pcmcia_function *pf; 167 struct pcmcia_attach_args paa; 168 int attached; 169 170 /* 171 * this is here so that when socket_enable calls gettype, trt happens 172 */ 173 SIMPLEQ_FIRST(&sc->card.pf_head) = NULL; 174 175 pcmcia_chip_socket_enable(sc->pct, sc->pch); 176 177 pcmcia_read_cis(sc); 178 179 pcmcia_chip_socket_disable(sc->pct, sc->pch); 180 181 pcmcia_check_cis_quirks(sc); 182 183 /* 184 * Bail now if there was an error in the CIS. 185 */ 186 187 if (sc->card.error) 188 return (1); 189 190 #if 0 191 if (SIMPLEQ_EMPTY(&sc->card.pf_head)) 192 return (1); 193 #endif 194 195 if (pcmcia_verbose) 196 pcmcia_print_cis(sc); 197 198 /* 199 * If there was no function, this might be CIS-less card we still 200 * want to probe. Fixup a function element for it. 201 */ 202 if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) { 203 pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT | M_ZERO); 204 if (pf == NULL) 205 panic("pcmcia_card_attach"); 206 pf->number = 0; 207 pf->pf_flags = PFF_FAKE; 208 pf->last_config_index = -1; 209 SIMPLEQ_INIT(&pf->cfe_head); 210 SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list); 211 } 212 213 attached = 0; 214 215 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 216 pf = SIMPLEQ_NEXT(pf, pf_list)) { 217 pf->sc = sc; 218 pf->child = NULL; 219 pf->cfe = NULL; 220 pf->ih_fct = NULL; 221 pf->ih_arg = NULL; 222 } 223 224 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 225 pf = SIMPLEQ_NEXT(pf, pf_list)) { 226 paa.manufacturer = sc->card.manufacturer; 227 paa.product = sc->card.product; 228 paa.card = &sc->card; 229 paa.pf = pf; 230 231 pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print, 232 pcmcia_submatch); 233 if (pf->child) { 234 attached++; 235 236 if ((pf->pf_flags & PFF_FAKE) == 0) 237 DPRINTF(("%s: function %d CCR at %d offset %lx" 238 ": %x %x %x %x, %x %x %x %x, %x\n", 239 sc->dev.dv_xname, pf->number, 240 pf->pf_ccr_window, pf->pf_ccr_offset, 241 pcmcia_ccr_read(pf, 0x00), 242 pcmcia_ccr_read(pf, 0x02), 243 pcmcia_ccr_read(pf, 0x04), 244 pcmcia_ccr_read(pf, 0x06), 245 pcmcia_ccr_read(pf, 0x0A), 246 pcmcia_ccr_read(pf, 0x0C), 247 pcmcia_ccr_read(pf, 0x0E), 248 pcmcia_ccr_read(pf, 0x10), 249 pcmcia_ccr_read(pf, 0x12))); 250 } 251 } 252 return (attached ? 0 : 1); 253 } 254 255 void 256 pcmcia_card_detach(dev, flags) 257 struct device *dev; 258 int flags; /* DETACH_* flags */ 259 { 260 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; 261 struct pcmcia_function *pf; 262 int error; 263 264 /* 265 * We are running on either the PCMCIA socket's event thread 266 * or in user context detaching a device by user request. 267 */ 268 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 269 pf = SIMPLEQ_NEXT(pf, pf_list)) { 270 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL) 271 continue; 272 if (pf->child == NULL) 273 continue; 274 DPRINTF(("%s: detaching %s (function %d)\n", 275 sc->dev.dv_xname, pf->child->dv_xname, pf->number)); 276 if ((error = config_detach(pf->child, flags)) != 0) { 277 printf("%s: error %d detaching %s (function %d)\n", 278 sc->dev.dv_xname, error, pf->child->dv_xname, 279 pf->number); 280 } else 281 pf->child = NULL; 282 } 283 } 284 285 void 286 pcmcia_card_deactivate(dev) 287 struct device *dev; 288 { 289 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; 290 struct pcmcia_function *pf; 291 292 /* 293 * We're in the chip's card removal interrupt handler. 294 * Deactivate the child driver. The PCMCIA socket's 295 * event thread will run later to finish the detach. 296 */ 297 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 298 pf = SIMPLEQ_NEXT(pf, pf_list)) { 299 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL) 300 continue; 301 if (pf->child == NULL) 302 continue; 303 DPRINTF(("%s: deactivating %s (function %d)\n", 304 sc->dev.dv_xname, pf->child->dv_xname, pf->number)); 305 config_deactivate(pf->child); 306 } 307 } 308 309 int 310 pcmcia_submatch(parent, match, aux) 311 struct device *parent; 312 void *match, *aux; 313 { 314 struct cfdata *cf = match; 315 struct pcmcia_attach_args *paa = aux; 316 317 if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != 318 -1 /* PCMCIACF_FUNCTION_DEFAULT */ && 319 cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number) 320 return (0); 321 322 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 323 } 324 325 int 326 pcmcia_print(arg, pnp) 327 void *arg; 328 const char *pnp; 329 { 330 struct pcmcia_attach_args *pa = arg; 331 struct pcmcia_softc *sc = pa->pf->sc; 332 struct pcmcia_card *card = &sc->card; 333 int i; 334 335 if (pnp) { 336 for (i = 0; i < 4 && card->cis1_info[i]; i++) 337 printf("%s%s", i ? ", " : "\"", card->cis1_info[i]); 338 if (i != 0) 339 printf("\""); 340 341 if (card->manufacturer != PCMCIA_VENDOR_INVALID && 342 card->product != PCMCIA_PRODUCT_INVALID) { 343 if (i != 0) 344 printf(" "); 345 printf("("); 346 if (card->manufacturer != PCMCIA_VENDOR_INVALID) 347 printf("manufacturer 0x%x%s", 348 card->manufacturer, 349 card->product == PCMCIA_PRODUCT_INVALID ? 350 "" : ", "); 351 if (card->product != PCMCIA_PRODUCT_INVALID) 352 printf("product 0x%x", 353 card->product); 354 printf(")"); 355 } 356 if (i != 0) 357 printf(" "); 358 printf("at %s", pnp); 359 } 360 printf(" function %d", pa->pf->number); 361 362 if (!pnp) { 363 for (i = 0; i < 3 && card->cis1_info[i]; i++) 364 printf("%s%s", i ? ", " : " \"", card->cis1_info[i]); 365 if (i != 0) 366 printf("\""); 367 } 368 369 return (UNCONF); 370 } 371 372 int 373 pcmcia_card_gettype(dev) 374 struct device *dev; 375 { 376 struct pcmcia_softc *sc = (struct pcmcia_softc *)dev; 377 struct pcmcia_function *pf; 378 379 /* 380 * Set the iftype to memory if this card has no functions (not yet 381 * probed), or only one function, and that is not initialized yet or 382 * that is memory. 383 */ 384 pf = SIMPLEQ_FIRST(&sc->card.pf_head); 385 if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL && 386 ((pf->pf_flags & PFF_FAKE) || 387 pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY))) 388 return (PCMCIA_IFTYPE_MEMORY); 389 else 390 return (PCMCIA_IFTYPE_IO); 391 } 392 393 /* 394 * Initialize a PCMCIA function. May be called as long as the function is 395 * disabled. 396 */ 397 void 398 pcmcia_function_init(pf, cfe) 399 struct pcmcia_function *pf; 400 struct pcmcia_config_entry *cfe; 401 { 402 if (pf->pf_flags & PFF_ENABLED) 403 panic("pcmcia_function_init: function is enabled"); 404 405 /* Remember which configuration entry we are using. */ 406 pf->cfe = cfe; 407 } 408 409 static inline void pcmcia_socket_enable(pct, pch) 410 pcmcia_chipset_tag_t pct; 411 pcmcia_chipset_handle_t *pch; 412 { 413 pcmcia_chip_socket_enable(pct, pch); 414 } 415 416 static inline void pcmcia_socket_disable(pct, pch) 417 pcmcia_chipset_tag_t pct; 418 pcmcia_chipset_handle_t *pch; 419 { 420 pcmcia_chip_socket_disable(pct, pch); 421 } 422 423 /* Enable a PCMCIA function */ 424 int 425 pcmcia_function_enable(pf) 426 struct pcmcia_function *pf; 427 { 428 struct pcmcia_function *tmp; 429 int reg; 430 431 if (pf->cfe == NULL) 432 panic("pcmcia_function_enable: function not initialized"); 433 434 /* 435 * Increase the reference count on the socket, enabling power, if 436 * necessary. 437 */ 438 if (pf->sc->sc_enabled_count++ == 0) 439 pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch); 440 DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname, 441 pf->sc->sc_enabled_count)); 442 443 if (pf->pf_flags & PFF_ENABLED) { 444 /* 445 * Don't do anything if we're already enabled. 446 */ 447 DPRINTF(("%s: pcmcia_function_enable on enabled func\n")); 448 return (0); 449 } 450 451 /* If there was no CIS don't mess with CCR */ 452 if (pf->pf_flags & PFF_FAKE) 453 goto done; 454 455 /* 456 * It's possible for different functions' CCRs to be in the same 457 * underlying page. Check for that. 458 */ 459 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 460 if ((tmp->pf_flags & PFF_ENABLED) && 461 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) && 462 ((pf->ccr_base + PCMCIA_CCR_SIZE) <= 463 (tmp->ccr_base - tmp->pf_ccr_offset + 464 tmp->pf_ccr_realsize))) { 465 pf->pf_ccrt = tmp->pf_ccrt; 466 pf->pf_ccrh = tmp->pf_ccrh; 467 pf->pf_ccr_realsize = tmp->pf_ccr_realsize; 468 469 /* 470 * pf->pf_ccr_offset = (tmp->pf_ccr_offset - 471 * tmp->ccr_base) + pf->ccr_base; 472 */ 473 pf->pf_ccr_offset = 474 (tmp->pf_ccr_offset + pf->ccr_base) - 475 tmp->ccr_base; 476 pf->pf_ccr_window = tmp->pf_ccr_window; 477 break; 478 } 479 } 480 481 if (tmp == NULL) { 482 if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh)) 483 goto bad; 484 485 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base, 486 PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset, 487 &pf->pf_ccr_window)) { 488 pcmcia_mem_free(pf, &pf->pf_pcmh); 489 goto bad; 490 } 491 } 492 493 reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX); 494 reg |= PCMCIA_CCR_OPTION_LEVIREQ; 495 if (pcmcia_mfc(pf->sc)) { 496 reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE; 497 if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2))) 498 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE; 499 if (pf->ih_fct) 500 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE; 501 502 } 503 504 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 505 506 reg = 0; 507 508 if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0) 509 reg |= PCMCIA_CCR_STATUS_IOIS8; 510 if (pf->cfe->flags & PCMCIA_CFE_AUDIO) 511 reg |= PCMCIA_CCR_STATUS_AUDIO; 512 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg); 513 514 pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0); 515 516 if (pcmcia_mfc(pf->sc)) { 517 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, 518 (pf->pf_mfc_iobase >> 0) & 0xff); 519 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, 520 (pf->pf_mfc_iobase >> 8) & 0xff); 521 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2, 522 (pf->pf_mfc_iobase >> 16) & 0xff); 523 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3, 524 (pf->pf_mfc_iobase >> 24) & 0xff); 525 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, 526 pf->pf_mfc_iomax - pf->pf_mfc_iobase); 527 } 528 529 #ifdef PCMCIADEBUG 530 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 531 printf("%s: function %d CCR at %d offset %lx: " 532 "%x %x %x %x, %x %x %x %x, %x\n", 533 tmp->sc->dev.dv_xname, tmp->number, 534 tmp->pf_ccr_window, tmp->pf_ccr_offset, 535 pcmcia_ccr_read(tmp, 0x00), 536 pcmcia_ccr_read(tmp, 0x02), 537 pcmcia_ccr_read(tmp, 0x04), 538 pcmcia_ccr_read(tmp, 0x06), 539 540 pcmcia_ccr_read(tmp, 0x0A), 541 pcmcia_ccr_read(tmp, 0x0C), 542 pcmcia_ccr_read(tmp, 0x0E), 543 pcmcia_ccr_read(tmp, 0x10), 544 545 pcmcia_ccr_read(tmp, 0x12)); 546 } 547 #endif 548 549 done: 550 pf->pf_flags |= PFF_ENABLED; 551 delay(1000); 552 return (0); 553 554 bad: 555 /* 556 * Decrement the reference count, and power down the socket, if 557 * necessary. 558 */ 559 if (--pf->sc->sc_enabled_count == 0) 560 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch); 561 DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname, 562 pf->sc->sc_enabled_count)); 563 564 return (1); 565 } 566 567 /* Disable PCMCIA function. */ 568 void 569 pcmcia_function_disable(pf) 570 struct pcmcia_function *pf; 571 { 572 struct pcmcia_function *tmp; 573 574 if (pf->cfe == NULL) 575 panic("pcmcia_function_enable: function not initialized"); 576 577 if ((pf->pf_flags & PFF_ENABLED) == 0) { 578 /* 579 * Don't do anything if we're already disabled. 580 */ 581 return; 582 } 583 584 /* If there was no CIS don't mess with CCR */ 585 if (pf->pf_flags & PFF_FAKE) { 586 pf->pf_flags &= ~PFF_ENABLED; 587 goto done; 588 } 589 590 /* 591 * it's possible for different functions' CCRs to be in the same 592 * underlying page. Check for that. Note we mark us as disabled 593 * first to avoid matching ourself. 594 */ 595 pf->pf_flags &= ~PFF_ENABLED; 596 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) { 597 if ((tmp->pf_flags & PFF_ENABLED) && 598 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) && 599 ((pf->ccr_base + PCMCIA_CCR_SIZE) <= 600 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize))) 601 break; 602 } 603 604 /* Not used by anyone else; unmap the CCR. */ 605 if (tmp == NULL) { 606 pcmcia_mem_unmap(pf, pf->pf_ccr_window); 607 pcmcia_mem_free(pf, &pf->pf_pcmh); 608 } 609 610 done: 611 /* 612 * Decrement the reference count, and power down the socket, if 613 * necessary. 614 */ 615 if (--pf->sc->sc_enabled_count == 0) 616 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch); 617 DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname, 618 pf->sc->sc_enabled_count)); 619 } 620 621 int 622 pcmcia_io_map(pf, width, offset, size, pcihp, windowp) 623 struct pcmcia_function *pf; 624 int width; 625 bus_addr_t offset; 626 bus_size_t size; 627 struct pcmcia_io_handle *pcihp; 628 int *windowp; 629 { 630 int reg; 631 632 if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch, 633 width, offset, size, pcihp, windowp)) 634 return (1); 635 636 /* 637 * XXX In the multifunction multi-iospace-per-function case, this 638 * needs to cooperate with io_alloc to make sure that the spaces 639 * don't overlap, and that the ccr's are set correctly. 640 */ 641 642 if (pcmcia_mfc(pf->sc) && 643 (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) { 644 bus_addr_t iobase = pcihp->addr; 645 bus_addr_t iomax = pcihp->addr + pcihp->size - 1; 646 647 if (pf->pf_mfc_iomax == 0) { 648 pf->pf_mfc_iobase = iobase; 649 pf->pf_mfc_iomax = iomax; 650 } else { 651 if (iobase < pf->pf_mfc_iobase) 652 pf->pf_mfc_iobase = iobase; 653 if (iomax > pf->pf_mfc_iomax) 654 pf->pf_mfc_iomax = iomax; 655 } 656 657 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, 658 (pf->pf_mfc_iobase >> 0) & 0xff); 659 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, 660 (pf->pf_mfc_iobase >> 8) & 0xff); 661 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2, 662 (pf->pf_mfc_iobase >> 16) & 0xff); 663 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3, 664 (pf->pf_mfc_iobase >> 24) & 0xff); 665 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, 666 pf->pf_mfc_iomax - pf->pf_mfc_iobase); 667 668 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 669 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE; 670 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 671 } 672 return (0); 673 } 674 675 void * 676 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname) 677 struct pcmcia_function *pf; 678 int ipl; 679 int (*ih_fct)(void *); 680 void *ih_arg; 681 char *xname; 682 { 683 void *ret; 684 int s, ihcnt, hiipl, reg; 685 struct pcmcia_function *pf2; 686 687 /* Behave differently if this is a multifunction card. */ 688 if (pcmcia_mfc(pf->sc)) { 689 /* 690 * Mask all the ipl's which are already used by this card, 691 * and find the highest ipl number (lowest priority). 692 */ 693 ihcnt = 0; 694 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) { 695 if (pf2->ih_fct) { 696 DPRINTF(("%s: function %d has ih_fct %p\n", 697 pf->sc->dev.dv_xname, pf2->number, 698 pf2->ih_fct)); 699 700 if (ihcnt == 0) 701 hiipl = pf2->ih_ipl; 702 else if (pf2->ih_ipl > hiipl) 703 hiipl = pf2->ih_ipl; 704 705 ihcnt++; 706 } 707 } 708 709 /* 710 * Establish the real interrupt, changing the ipl if 711 * necessary. 712 */ 713 if (ihcnt == 0) { 714 #ifdef DIAGNOSTIC 715 if (pf->sc->ih != NULL) 716 panic("card has intr handler, " 717 "but no function does"); 718 #endif 719 s = spltty(); 720 721 /* Set up the handler for the new function. */ 722 pf->ih_fct = ih_fct; 723 pf->ih_arg = ih_arg; 724 pf->ih_ipl = ipl; 725 726 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 727 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc, 728 xname); 729 splx(s); 730 } else if (ipl > hiipl) { 731 #ifdef DIAGNOSTIC 732 if (pf->sc->ih == NULL) 733 panic("functions have ih, " 734 "but the card does not"); 735 #endif 736 737 s = spltty(); 738 739 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 740 pf->sc->ih); 741 742 /* set up the handler for the new function */ 743 pf->ih_fct = ih_fct; 744 pf->ih_arg = ih_arg; 745 pf->ih_ipl = ipl; 746 747 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 748 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc, 749 xname); 750 751 splx(s); 752 } else { 753 s = spltty(); 754 755 /* Set up the handler for the new function. */ 756 pf->ih_fct = ih_fct; 757 pf->ih_arg = ih_arg; 758 pf->ih_ipl = ipl; 759 760 splx(s); 761 } 762 763 ret = pf->sc->ih; 764 765 if (ret != NULL) { 766 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 767 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE; 768 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 769 770 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 771 reg |= PCMCIA_CCR_STATUS_INTRACK; 772 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg); 773 } 774 } else 775 ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch, 776 pf, ipl, ih_fct, ih_arg, xname); 777 778 return (ret); 779 } 780 781 void 782 pcmcia_intr_disestablish(pf, ih) 783 struct pcmcia_function *pf; 784 void *ih; 785 { 786 int s, reg, ihcnt, hiipl; 787 struct pcmcia_function *pf2; 788 789 /* Behave differently if this is a multifunction card. */ 790 if (pcmcia_mfc(pf->sc)) { 791 /* 792 * Mask all the ipl's which are already used by this card, 793 * and find the highest ipl number (lowest priority). Skip 794 * the current function. 795 */ 796 ihcnt = 0; 797 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) { 798 if (pf2 == pf) 799 continue; 800 801 if (pf2->ih_fct) { 802 if (ihcnt == 0) 803 hiipl = pf2->ih_ipl; 804 else if (pf2->ih_ipl > hiipl) 805 hiipl = pf2->ih_ipl; 806 ihcnt++; 807 } 808 } 809 810 /* 811 * If the ih being removed is lower priority than the lowest 812 * priority remaining interrupt, up the priority. 813 */ 814 815 /* 816 * ihcnt is the number of interrupt handlers *not* including 817 * the one about to be removed. 818 */ 819 if (ihcnt == 0) { 820 #ifdef DIAGNOSTIC 821 if (pf->sc->ih == NULL) 822 panic("disestablishing last function, but card has no ih"); 823 #endif 824 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 825 pf->sc->ih); 826 827 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 828 reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE; 829 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 830 831 pf->ih_fct = NULL; 832 pf->ih_arg = NULL; 833 834 pf->sc->ih = NULL; 835 } else if (pf->ih_ipl > hiipl) { 836 #ifdef DIAGNOSTIC 837 if (pf->sc->ih == NULL) 838 panic("changing ih ipl, but card has no ih"); 839 #endif 840 s = spltty(); 841 842 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 843 pf->sc->ih); 844 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 845 pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc, 846 NULL); 847 848 /* Null out the handler for this function. */ 849 pf->ih_fct = NULL; 850 pf->ih_arg = NULL; 851 852 splx(s); 853 } else { 854 s = spltty(); 855 856 pf->ih_fct = NULL; 857 pf->ih_arg = NULL; 858 859 splx(s); 860 } 861 } else 862 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih); 863 } 864 865 const char * 866 pcmcia_intr_string(pf, ih) 867 struct pcmcia_function *pf; 868 void *ih; 869 { 870 return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih); 871 } 872 873 int 874 pcmcia_card_intr(arg) 875 void *arg; 876 { 877 struct pcmcia_softc *sc = arg; 878 struct pcmcia_function *pf; 879 int reg, ret, ret2; 880 881 ret = 0; 882 883 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; 884 pf = SIMPLEQ_NEXT(pf, pf_list)) { 885 #ifdef PCMCIADEBUG 886 printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x", 887 sc->dev.dv_xname, pf->pf_flags, pf->number, 888 pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION), 889 pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS), 890 pcmcia_ccr_read(pf, PCMCIA_CCR_PIN)); 891 #endif 892 if (pf->ih_fct != NULL && 893 (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) { 894 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 895 if (reg & PCMCIA_CCR_STATUS_INTR) { 896 ret2 = (*pf->ih_fct)(pf->ih_arg); 897 if (ret2 != 0 && ret == 0) 898 ret = ret2; 899 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 900 #ifdef PCMCIADEBUG 901 printf("; csr %02x->%02x", 902 reg, reg & ~PCMCIA_CCR_STATUS_INTR); 903 #endif 904 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, 905 reg & ~PCMCIA_CCR_STATUS_INTR); 906 } 907 } 908 #ifdef PCMCIADEBUG 909 printf("\n"); 910 #endif 911 } 912 913 return (ret); 914 } 915