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