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