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