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