1 /* $NetBSD: pcmcia.c,v 1.36 2003/10/22 07:46:48 briggs 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.36 2003/10/22 07:46:48 briggs 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 aprint_normal("%s at %s, ", devinfo, pnp); 295 } 296 aprint_normal(" 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 but decrement if we're already disabled. 571 */ 572 goto out; 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 out: 597 /* 598 * Decrement the reference count, and power down the socket, if 599 * necessary. 600 */ 601 if (--pf->sc->sc_enabled_count == 0) 602 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch); 603 DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname, 604 pf->sc->sc_enabled_count)); 605 } 606 607 int 608 pcmcia_io_map(pf, width, offset, size, pcihp, windowp) 609 struct pcmcia_function *pf; 610 int width; 611 bus_addr_t offset; 612 bus_size_t size; 613 struct pcmcia_io_handle *pcihp; 614 int *windowp; 615 { 616 int reg; 617 618 if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch, 619 width, offset, size, pcihp, windowp)) 620 return (1); 621 622 /* 623 * XXX in the multifunction multi-iospace-per-function case, this 624 * needs to cooperate with io_alloc to make sure that the spaces 625 * don't overlap, and that the ccr's are set correctly 626 */ 627 628 if (pcmcia_mfc(pf->sc)) { 629 long tmp, iosize; 630 631 if (pf->pf_mfc_iomax == 0) { 632 pf->pf_mfc_iobase = pcihp->addr + offset; 633 pf->pf_mfc_iomax = pf->pf_mfc_iobase + size; 634 } else { 635 /* this makes the assumption that nothing overlaps */ 636 if (pf->pf_mfc_iobase > pcihp->addr + offset) 637 pf->pf_mfc_iobase = pcihp->addr + offset; 638 if (pf->pf_mfc_iomax < pcihp->addr + offset + size) 639 pf->pf_mfc_iomax = pcihp->addr + offset + size; 640 } 641 642 tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase; 643 /* round up to nearest (2^n)-1 */ 644 for (iosize = 1; iosize >= tmp; iosize <<= 1) 645 ; 646 iosize--; 647 648 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, 649 pf->pf_mfc_iobase & 0xff); 650 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, 651 (pf->pf_mfc_iobase >> 8) & 0xff); 652 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2, 0); 653 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3, 0); 654 655 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, iosize); 656 657 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 658 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE; 659 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 660 } 661 return (0); 662 } 663 664 void 665 pcmcia_io_unmap(pf, window) 666 struct pcmcia_function *pf; 667 int window; 668 { 669 670 pcmcia_chip_io_unmap(pf->sc->pct, pf->sc->pch, window); 671 672 /* XXX Anything for multi-function cards? */ 673 } 674 675 void * 676 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg) 677 struct pcmcia_function *pf; 678 int ipl; 679 int (*ih_fct) __P((void *)); 680 void *ih_arg; 681 { 682 void *ret; 683 684 /* behave differently if this is a multifunction card */ 685 686 if (pcmcia_mfc(pf->sc)) { 687 int s, ihcnt, hiipl, reg; 688 struct pcmcia_function *pf2; 689 690 /* 691 * mask all the ipl's which are already used by this card, 692 * and find the highest ipl number (lowest priority) 693 */ 694 695 ihcnt = 0; 696 s = 0; /* this is only here to keep the compiler 697 happy */ 698 hiipl = 0; /* this is only here to keep the compiler 699 happy */ 700 701 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) { 702 if (pf2->ih_fct) { 703 DPRINTF(("%s: function %d has ih_fct %p\n", 704 pf->sc->dev.dv_xname, pf2->number, 705 pf2->ih_fct)); 706 707 if (ihcnt == 0) { 708 hiipl = pf2->ih_ipl; 709 } else { 710 if (pf2->ih_ipl > hiipl) 711 hiipl = pf2->ih_ipl; 712 } 713 714 ihcnt++; 715 } 716 } 717 718 /* 719 * establish the real interrupt, changing the ipl if 720 * necessary 721 */ 722 723 if (ihcnt == 0) { 724 #ifdef DIAGNOSTIC 725 if (pf->sc->ih != NULL) 726 panic("card has intr handler, but no function does"); 727 #endif 728 s = splhigh(); 729 730 /* set up the handler for the new function */ 731 732 pf->ih_fct = ih_fct; 733 pf->ih_arg = ih_arg; 734 pf->ih_ipl = ipl; 735 736 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 737 pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc); 738 splx(s); 739 } else if (ipl > hiipl) { 740 #ifdef DIAGNOSTIC 741 if (pf->sc->ih == NULL) 742 panic("functions have ih, but the card does not"); 743 #endif 744 745 /* XXX need #ifdef for splserial on x86 */ 746 s = splhigh(); 747 748 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 749 pf->sc->ih); 750 751 /* set up the handler for the new function */ 752 pf->ih_fct = ih_fct; 753 pf->ih_arg = ih_arg; 754 pf->ih_ipl = ipl; 755 756 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 757 pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc); 758 759 splx(s); 760 } else { 761 s = splhigh(); 762 763 /* set up the handler for the new function */ 764 765 pf->ih_fct = ih_fct; 766 pf->ih_arg = ih_arg; 767 pf->ih_ipl = ipl; 768 769 splx(s); 770 } 771 772 ret = pf->sc->ih; 773 774 if (ret != NULL) { 775 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 776 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE; 777 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 778 779 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 780 reg |= PCMCIA_CCR_STATUS_INTRACK; 781 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg); 782 } 783 } else { 784 ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch, 785 pf, ipl, ih_fct, ih_arg); 786 } 787 788 return (ret); 789 } 790 791 void 792 pcmcia_intr_disestablish(pf, ih) 793 struct pcmcia_function *pf; 794 void *ih; 795 { 796 /* behave differently if this is a multifunction card */ 797 798 if (pcmcia_mfc(pf->sc)) { 799 int s, ihcnt, hiipl; 800 struct pcmcia_function *pf2; 801 802 /* 803 * mask all the ipl's which are already used by this card, 804 * and find the highest ipl number (lowest priority). Skip 805 * the current function. 806 */ 807 808 ihcnt = 0; 809 s = 0; /* avoid compiler warning */ 810 hiipl = 0; /* avoid compiler warning */ 811 812 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) { 813 if (pf2 == pf) 814 continue; 815 816 if (pf2->ih_fct) { 817 if (ihcnt == 0) { 818 hiipl = pf2->ih_ipl; 819 } else { 820 if (pf2->ih_ipl > hiipl) 821 hiipl = pf2->ih_ipl; 822 } 823 ihcnt++; 824 } 825 } 826 827 /* 828 * If the ih being removed is lower priority than the lowest 829 * priority remaining interrupt, up the priority. 830 */ 831 832 /* 833 * ihcnt is the number of interrupt handlers *not* including 834 * the one about to be removed. 835 */ 836 837 if (ihcnt == 0) { 838 int reg; 839 840 #ifdef DIAGNOSTIC 841 if (pf->sc->ih == NULL) 842 panic("disestablishing last function, but card has no ih"); 843 #endif 844 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 845 pf->sc->ih); 846 847 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 848 reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE; 849 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 850 851 pf->ih_fct = NULL; 852 pf->ih_arg = NULL; 853 854 pf->sc->ih = NULL; 855 } else if (pf->ih_ipl > hiipl) { 856 #ifdef DIAGNOSTIC 857 if (pf->sc->ih == NULL) 858 panic("changing ih ipl, but card has no ih"); 859 #endif 860 /* XXX need #ifdef for splserial on x86 */ 861 s = splhigh(); 862 863 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, 864 pf->sc->ih); 865 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, 866 pf->sc->pch, pf, hiipl, PCMCIA_CARD_INTR, pf->sc); 867 868 /* null out the handler for this function */ 869 870 pf->ih_fct = NULL; 871 pf->ih_arg = NULL; 872 873 splx(s); 874 } else { 875 s = splhigh(); 876 877 pf->ih_fct = NULL; 878 pf->ih_arg = NULL; 879 880 splx(s); 881 } 882 } else { 883 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih); 884 } 885 } 886 887 int 888 pcmcia_card_intr(arg) 889 void *arg; 890 { 891 struct pcmcia_softc *sc = arg; 892 struct pcmcia_function *pf; 893 int reg, ret, ret2; 894 895 ret = 0; 896 897 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) { 898 if (pf->ih_fct != NULL && 899 (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) { 900 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 901 if (reg & PCMCIA_CCR_STATUS_INTR) { 902 ret2 = (*pf->ih_fct)(pf->ih_arg); 903 if (ret2 != 0 && ret == 0) 904 ret = ret2; 905 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 906 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, 907 reg & ~PCMCIA_CCR_STATUS_INTR); 908 } 909 } 910 } 911 912 return (ret); 913 } 914 915 #ifdef PCMCIADEBUG 916 int 917 pcmcia_card_intrdebug(arg) 918 void *arg; 919 { 920 struct pcmcia_softc *sc = arg; 921 struct pcmcia_function *pf; 922 int reg, ret, ret2; 923 924 ret = 0; 925 926 SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) { 927 printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x", 928 sc->dev.dv_xname, pf->pf_flags, pf->number, 929 pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION), 930 pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS), 931 pcmcia_ccr_read(pf, PCMCIA_CCR_PIN)); 932 if (pf->ih_fct != NULL && 933 (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) { 934 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 935 if (reg & PCMCIA_CCR_STATUS_INTR) { 936 ret2 = (*pf->ih_fct)(pf->ih_arg); 937 if (ret2 != 0 && ret == 0) 938 ret = ret2; 939 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS); 940 printf("; csr %02x->%02x", 941 reg, reg & ~PCMCIA_CCR_STATUS_INTR); 942 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, 943 reg & ~PCMCIA_CCR_STATUS_INTR); 944 } 945 } 946 printf("\n"); 947 } 948 949 return (ret); 950 } 951 #endif 952