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