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