1 /* $NetBSD: isapnp.c,v 1.9 1997/08/12 07:38:10 mikel Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Christos Zoulas. 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 Christos Zoulas. 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 /* 33 * ISA PnP bus autoconfiguration. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/device.h> 39 #include <sys/malloc.h> 40 41 #include <machine/bus.h> 42 43 #include <dev/isa/isavar.h> 44 45 #include <dev/isapnp/isapnpreg.h> 46 #include <dev/isapnp/isapnpvar.h> 47 48 static void isapnp_init __P((struct isapnp_softc *)); 49 static __inline u_char isapnp_shift_bit __P((struct isapnp_softc *)); 50 static int isapnp_findcard __P((struct isapnp_softc *)); 51 static void isapnp_free_region __P((bus_space_tag_t, struct isapnp_region *)); 52 static int isapnp_alloc_region __P((bus_space_tag_t, struct isapnp_region *)); 53 static int isapnp_alloc_pin __P((struct isapnp_pin *)); 54 static int isapnp_testconfig __P((bus_space_tag_t, bus_space_tag_t, 55 struct isapnp_attach_args *, int)); 56 static struct isapnp_attach_args *isapnp_bestconfig __P((struct isapnp_softc *, 57 struct isapnp_attach_args **)); 58 static void isapnp_print_region __P((const char *, struct isapnp_region *, 59 size_t)); 60 static void isapnp_configure __P((struct isapnp_softc *, 61 const struct isapnp_attach_args *)); 62 static void isapnp_print_pin __P((const char *, struct isapnp_pin *, size_t)); 63 static int isapnp_print __P((void *, const char *)); 64 #ifdef _KERNEL 65 static int isapnp_submatch __P((struct device *, void *, void *)); 66 #endif 67 static int isapnp_find __P((struct isapnp_softc *, int)); 68 #ifdef __BROKEN_INDIRECT_CONFIG 69 static int isapnp_match __P((struct device *, void *, void *)); 70 #else 71 static int isapnp_match __P((struct device *, struct cfdata *, void *)); 72 #endif 73 static void isapnp_attach __P((struct device *, struct device *, void *)); 74 75 struct cfattach isapnp_ca = { 76 sizeof(struct isapnp_softc), isapnp_match, isapnp_attach 77 }; 78 79 struct cfdriver isapnp_cd = { 80 NULL, "isapnp", DV_DULL 81 }; 82 83 84 /* isapnp_init(): 85 * Write the PNP initiation key to wake up the cards... 86 */ 87 static void 88 isapnp_init(sc) 89 struct isapnp_softc *sc; 90 { 91 int i; 92 u_char v = ISAPNP_LFSR_INIT; 93 94 /* First write 0's twice to enter the Wait for Key state */ 95 ISAPNP_WRITE_ADDR(sc, 0); 96 ISAPNP_WRITE_ADDR(sc, 0); 97 98 /* Send the 32 byte sequence to awake the logic */ 99 for (i = 0; i < ISAPNP_LFSR_LENGTH; i++) { 100 ISAPNP_WRITE_ADDR(sc, v); 101 v = ISAPNP_LFSR_NEXT(v); 102 } 103 } 104 105 106 /* isapnp_shift_bit(): 107 * Read a bit at a time from the config card. 108 */ 109 static __inline u_char 110 isapnp_shift_bit(sc) 111 struct isapnp_softc *sc; 112 { 113 u_char c1, c2; 114 115 DELAY(250); 116 c1 = ISAPNP_READ_DATA(sc); 117 DELAY(250); 118 c2 = ISAPNP_READ_DATA(sc); 119 120 if (c1 == 0x55 && c2 == 0xAA) 121 return 0x80; 122 else 123 return 0; 124 } 125 126 127 /* isapnp_findcard(): 128 * Attempt to read the vendor/serial/checksum for a card 129 * If a card is found [the checksum matches], assign the 130 * next card number to it and return 1 131 */ 132 static int 133 isapnp_findcard(sc) 134 struct isapnp_softc *sc; 135 { 136 u_char v = ISAPNP_LFSR_INIT, csum, w; 137 int i, b; 138 139 if (sc->sc_ncards == ISAPNP_MAX_CARDS) { 140 printf("%s: Too many pnp cards\n", sc->sc_dev.dv_xname); 141 return 0; 142 } 143 144 /* Set the read port */ 145 isapnp_write_reg(sc, ISAPNP_WAKE, 0); 146 isapnp_write_reg(sc, ISAPNP_SET_RD_PORT, sc->sc_read_port >> 2); 147 sc->sc_read_port |= 3; 148 DELAY(1000); 149 150 ISAPNP_WRITE_ADDR(sc, ISAPNP_SERIAL_ISOLATION); 151 DELAY(1000); 152 153 /* Read the 8 bytes of the Vendor ID and Serial Number */ 154 for(i = 0; i < 8; i++) { 155 /* Read each bit separately */ 156 for (w = 0, b = 0; b < 8; b++) { 157 u_char neg = isapnp_shift_bit(sc); 158 159 w >>= 1; 160 w |= neg; 161 v = ISAPNP_LFSR_NEXT(v) ^ neg; 162 } 163 sc->sc_id[sc->sc_ncards][i] = w; 164 } 165 166 /* Read the remaining checksum byte */ 167 for (csum = 0, b = 0; b < 8; b++) { 168 u_char neg = isapnp_shift_bit(sc); 169 170 csum >>= 1; 171 csum |= neg; 172 } 173 sc->sc_id[sc->sc_ncards][8] = csum; 174 175 if (csum == v) { 176 sc->sc_ncards++; 177 isapnp_write_reg(sc, ISAPNP_CARD_SELECT_NUM, sc->sc_ncards); 178 return 1; 179 } 180 return 0; 181 } 182 183 184 /* isapnp_free_region(): 185 * Free a region 186 */ 187 static void 188 isapnp_free_region(t, r) 189 bus_space_tag_t t; 190 struct isapnp_region *r; 191 { 192 #ifdef _KERNEL 193 bus_space_unmap(t, r->h, r->length); 194 #endif 195 } 196 197 198 /* isapnp_alloc_region(): 199 * Allocate a single region if possible 200 */ 201 static int 202 isapnp_alloc_region(t, r) 203 bus_space_tag_t t; 204 struct isapnp_region *r; 205 { 206 int error = 0; 207 208 for (r->base = r->minbase; r->base <= r->maxbase; 209 r->base += r->align) { 210 #ifdef _KERNEL 211 error = bus_space_map(t, r->base, r->length, 0, &r->h); 212 #endif 213 if (error == 0) 214 return 0; 215 } 216 return error; 217 } 218 219 220 /* isapnp_alloc_pin(): 221 * Allocate an irq/drq 222 * XXX: No resource conflict checks! 223 */ 224 static int 225 isapnp_alloc_pin(i) 226 struct isapnp_pin *i; 227 { 228 int b; 229 230 if (i->bits == 0) 231 i->num = 0; 232 else 233 for (b = 0; b < 16; b++) 234 if (i->bits & (1 << b)) { 235 i->num = b; 236 break; 237 } 238 return 0; 239 } 240 241 242 /* isapnp_testconfig(): 243 * Test/Allocate the regions used 244 */ 245 static int 246 isapnp_testconfig(iot, memt, ipa, alloc) 247 bus_space_tag_t iot, memt; 248 struct isapnp_attach_args *ipa; 249 int alloc; 250 { 251 int nio = 0, nmem = 0, nmem32 = 0, nirq = 0, ndrq = 0; 252 int error = 0; 253 254 #ifdef DEBUG_ISAPNP 255 isapnp_print_attach(ipa); 256 #endif 257 258 for (; nio < ipa->ipa_nio; nio++) { 259 error = isapnp_alloc_region(iot, &ipa->ipa_io[nio]); 260 if (error) 261 goto bad; 262 } 263 264 for (; nmem < ipa->ipa_nmem; nmem++) { 265 error = isapnp_alloc_region(memt, &ipa->ipa_mem[nmem]); 266 if (error) 267 goto bad; 268 } 269 270 for (; nmem32 < ipa->ipa_nmem32; nmem32++) { 271 error = isapnp_alloc_region(memt, &ipa->ipa_mem32[nmem32]); 272 if (error) 273 goto bad; 274 } 275 276 for (; nirq < ipa->ipa_nirq; nirq++) { 277 error = isapnp_alloc_pin(&ipa->ipa_irq[nirq]); 278 if (error) 279 goto bad; 280 } 281 282 for (; ndrq < ipa->ipa_ndrq; ndrq++) { 283 error = isapnp_alloc_pin(&ipa->ipa_drq[ndrq]); 284 if (error) 285 goto bad; 286 } 287 288 if (alloc) 289 return error; 290 291 bad: 292 #ifdef notyet 293 for (ndrq--; ndrq >= 0; ndrq--) 294 isapnp_free_pin(&ipa->ipa_drq[ndrq]); 295 296 for (nirq--; nirq >= 0; nirq--) 297 isapnp_free_pin(&ipa->ipa_irq[nirq]); 298 #endif 299 300 for (nmem32--; nmem32 >= 0; nmem32--) 301 isapnp_free_region(memt, &ipa->ipa_mem32[nmem32]); 302 303 for (nmem--; nmem >= 0; nmem--) 304 isapnp_free_region(memt, &ipa->ipa_mem[nmem]); 305 306 for (nio--; nio >= 0; nio--) 307 isapnp_free_region(iot, &ipa->ipa_io[nio]); 308 309 return error; 310 } 311 312 313 /* isapnp_config(): 314 * Test/Allocate the regions used 315 */ 316 int 317 isapnp_config(iot, memt, ipa) 318 bus_space_tag_t iot, memt; 319 struct isapnp_attach_args *ipa; 320 { 321 return isapnp_testconfig(iot, memt, ipa, 1); 322 } 323 324 325 /* isapnp_unconfig(): 326 * Free the regions used 327 */ 328 void 329 isapnp_unconfig(iot, memt, ipa) 330 bus_space_tag_t iot, memt; 331 struct isapnp_attach_args *ipa; 332 { 333 int i; 334 335 #ifdef notyet 336 for (i = 0; i < ipa->ipa_ndrq; i++) 337 isapnp_free_pin(&ipa->ipa_drq[i]); 338 339 for (i = 0; i < ipa->ipa_nirq; i++) 340 isapnp_free_pin(&ipa->ipa_irq[i]); 341 #endif 342 343 for (i = 0; i < ipa->ipa_nmem32; i++) 344 isapnp_free_region(memt, &ipa->ipa_mem32[i]); 345 346 for (i = 0; i < ipa->ipa_nmem; i++) 347 isapnp_free_region(memt, &ipa->ipa_mem[i]); 348 349 for (i = 0; i < ipa->ipa_nio; i++) 350 isapnp_free_region(iot, &ipa->ipa_io[i]); 351 } 352 353 354 /* isapnp_bestconfig(): 355 * Return the best configuration for each logical device, remove and 356 * free all other configurations. 357 */ 358 static struct isapnp_attach_args * 359 isapnp_bestconfig(sc, ipa) 360 struct isapnp_softc *sc; 361 struct isapnp_attach_args **ipa; 362 { 363 struct isapnp_attach_args *c, *best, *f = *ipa; 364 int error; 365 366 for (;;) { 367 if (f == NULL) 368 return NULL; 369 370 #define SAMEDEV(a, b) (strcmp((a)->ipa_devlogic, (b)->ipa_devlogic) == 0) 371 372 /* Find the best config */ 373 for (best = c = f; c != NULL; c = c->ipa_sibling) { 374 if (!SAMEDEV(c, f)) 375 continue; 376 if (c->ipa_pref < best->ipa_pref) 377 best = c; 378 } 379 380 /* Test the best config */ 381 error = isapnp_testconfig(sc->sc_iot, sc->sc_memt, best, 0); 382 383 /* Remove this config from the list */ 384 if (best == f) 385 f = f->ipa_sibling; 386 else { 387 for (c = f; c->ipa_sibling != best; c = c->ipa_sibling) 388 continue; 389 c->ipa_sibling = best->ipa_sibling; 390 } 391 392 if (error) { 393 best->ipa_pref = ISAPNP_DEP_CONFLICTING; 394 395 for (c = f; c != NULL; c = c->ipa_sibling) 396 if (c != best && SAMEDEV(c, best)) 397 break; 398 /* Last config for this logical device is conflicting */ 399 if (c == NULL) { 400 *ipa = f; 401 return best; 402 } 403 404 ISAPNP_FREE(best); 405 continue; 406 } 407 else { 408 /* Remove all other configs for this device */ 409 struct isapnp_attach_args *l = NULL, *n = NULL, *d; 410 411 for (c = f; c; ) { 412 if (c == best) 413 continue; 414 d = c->ipa_sibling; 415 if (SAMEDEV(c, best)) 416 ISAPNP_FREE(c); 417 else { 418 if (n) 419 n->ipa_sibling = c; 420 421 else 422 l = c; 423 n = c; 424 c->ipa_sibling = NULL; 425 } 426 c = d; 427 } 428 f = l; 429 } 430 *ipa = f; 431 return best; 432 } 433 } 434 435 436 /* isapnp_id_to_vendor(): 437 * Convert a pnp ``compressed ascii'' vendor id to a string 438 */ 439 char * 440 isapnp_id_to_vendor(v, id) 441 char *v; 442 const u_char *id; 443 { 444 static const char hex[] = "0123456789ABCDEF"; 445 char *p = v; 446 447 *p++ = 'A' + (id[0] >> 2) - 1; 448 *p++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1; 449 *p++ = 'A' + (id[1] & 0x1f) - 1; 450 *p++ = hex[id[2] >> 4]; 451 *p++ = hex[id[2] & 0x0f]; 452 *p++ = hex[id[3] >> 4]; 453 *p++ = hex[id[3] & 0x0f]; 454 *p = '\0'; 455 456 return v; 457 } 458 459 460 /* isapnp_print_region(): 461 * Print a region allocation 462 */ 463 static void 464 isapnp_print_region(str, r, n) 465 const char *str; 466 struct isapnp_region *r; 467 size_t n; 468 { 469 size_t i; 470 471 if (n == 0) 472 return; 473 474 printf(" %s ", str); 475 for (i = 0; i < n; i++, r++) { 476 printf("0x%x", r->base); 477 if (r->length) 478 printf("/%d", r->length); 479 if (i != n - 1) 480 printf(","); 481 } 482 } 483 484 485 /* isapnp_print_pin(): 486 * Print an irq/drq assignment 487 */ 488 static void 489 isapnp_print_pin(str, p, n) 490 const char *str; 491 struct isapnp_pin *p; 492 size_t n; 493 { 494 size_t i; 495 496 if (n == 0) 497 return; 498 499 printf(" %s ", str); 500 for (i = 0; i < n; i++, p++) { 501 printf("%d", p->num); 502 if (i != n - 1) 503 printf(","); 504 } 505 } 506 507 508 /* isapnp_print(): 509 * Print the configuration line for an ISA PnP card. 510 */ 511 static int 512 isapnp_print(aux, str) 513 void *aux; 514 const char *str; 515 { 516 struct isapnp_attach_args *ipa = aux; 517 518 if (str != NULL) 519 printf("%s: <%s, %s, %s, %s>", 520 str, ipa->ipa_devident, ipa->ipa_devlogic, 521 ipa->ipa_devcompat, ipa->ipa_devclass); 522 523 isapnp_print_region("port", ipa->ipa_io, ipa->ipa_nio); 524 isapnp_print_region("mem", ipa->ipa_mem, ipa->ipa_nmem); 525 isapnp_print_region("mem32", ipa->ipa_mem32, ipa->ipa_nmem32); 526 isapnp_print_pin("irq", ipa->ipa_irq, ipa->ipa_nirq); 527 isapnp_print_pin("drq", ipa->ipa_drq, ipa->ipa_ndrq); 528 529 return UNCONF; 530 } 531 532 533 #ifdef _KERNEL 534 /* isapnp_submatch(): 535 * Probe the logical device... 536 */ 537 static int 538 isapnp_submatch(parent, match, aux) 539 struct device *parent; 540 void *match, *aux; 541 { 542 struct cfdata *cf = match; 543 return ((*cf->cf_attach->ca_match)(parent, match, aux)); 544 } 545 #endif 546 547 548 /* isapnp_find(): 549 * Probe and add cards 550 */ 551 static int 552 isapnp_find(sc, all) 553 struct isapnp_softc *sc; 554 int all; 555 { 556 int p; 557 558 isapnp_init(sc); 559 560 isapnp_write_reg(sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV); 561 DELAY(2000); 562 563 isapnp_init(sc); 564 DELAY(2000); 565 566 for (p = ISAPNP_RDDATA_MIN; p <= ISAPNP_RDDATA_MAX; p += 4) { 567 sc->sc_read_port = p; 568 if (isapnp_map_readport(sc)) 569 continue; 570 DPRINTF(("%s: Trying port %x\n", sc->sc_dev.dv_xname, p)); 571 if (isapnp_findcard(sc)) 572 break; 573 isapnp_unmap_readport(sc); 574 } 575 576 if (p > ISAPNP_RDDATA_MAX) { 577 sc->sc_read_port = 0; 578 return 0; 579 } 580 581 if (all) 582 while (isapnp_findcard(sc)) 583 continue; 584 585 return 1; 586 } 587 588 589 /* isapnp_configure(): 590 * Configure a PnP card 591 * XXX: The memory configuration code is wrong. We need to check the 592 * range/length bit an do appropriate sets. 593 */ 594 static void 595 isapnp_configure(sc, ipa) 596 struct isapnp_softc *sc; 597 const struct isapnp_attach_args *ipa; 598 { 599 int i; 600 static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC; 601 static u_char isapnp_io_range[] = ISAPNP_IO_DESC; 602 static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC; 603 static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC; 604 static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC; 605 const struct isapnp_region *r; 606 const struct isapnp_pin *p; 607 struct isapnp_region rz; 608 struct isapnp_pin pz; 609 610 memset(&pz, 0, sizeof(pz)); 611 memset(&rz, 0, sizeof(rz)); 612 613 #define B0(a) ((a) & 0xff) 614 #define B1(a) (((a) >> 8) & 0xff) 615 #define B2(a) (((a) >> 16) & 0xff) 616 #define B3(a) (((a) >> 24) & 0xff) 617 618 for (i = 0; i < sizeof(isapnp_io_range); i++) { 619 if (i < ipa->ipa_nio) 620 r = &ipa->ipa_io[i]; 621 else 622 r = &rz; 623 624 isapnp_write_reg(sc, 625 isapnp_io_range[i] + ISAPNP_IO_BASE_15_8, B1(r->base)); 626 isapnp_write_reg(sc, 627 isapnp_io_range[i] + ISAPNP_IO_BASE_7_0, B0(r->base)); 628 } 629 630 for (i = 0; i < sizeof(isapnp_mem_range); i++) { 631 if (i < ipa->ipa_nmem) 632 r = &ipa->ipa_mem[i]; 633 else 634 r = &rz; 635 636 isapnp_write_reg(sc, 637 isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16, B2(r->base)); 638 isapnp_write_reg(sc, 639 isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8, B1(r->base)); 640 641 isapnp_write_reg(sc, 642 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16, 643 B2(r->length)); 644 isapnp_write_reg(sc, 645 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8, 646 B1(r->length)); 647 } 648 649 for (i = 0; i < sizeof(isapnp_irq_range); i++) { 650 u_char v; 651 652 if (i < ipa->ipa_nirq) 653 p = &ipa->ipa_irq[i]; 654 else 655 p = &pz; 656 657 isapnp_write_reg(sc, 658 isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER, p->num); 659 660 switch (p->flags) { 661 case ISAPNP_IRQTYPE_LEVEL_PLUS: 662 v = ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH; 663 break; 664 665 case ISAPNP_IRQTYPE_EDGE_PLUS: 666 v = ISAPNP_IRQ_HIGH; 667 break; 668 669 case ISAPNP_IRQTYPE_LEVEL_MINUS: 670 v = ISAPNP_IRQ_LEVEL; 671 break; 672 673 default: 674 case ISAPNP_IRQTYPE_EDGE_MINUS: 675 v = 0; 676 break; 677 } 678 isapnp_write_reg(sc, 679 isapnp_irq_range[i] + ISAPNP_IRQ_CONTROL, v); 680 } 681 682 for (i = 0; i < sizeof(isapnp_drq_range); i++) { 683 u_char v; 684 685 if (i < ipa->ipa_ndrq) 686 v = ipa->ipa_drq[i].num; 687 else 688 v = 4; 689 690 isapnp_write_reg(sc, isapnp_drq_range[i], v); 691 } 692 693 for (i = 0; i < sizeof(isapnp_mem32_range); i++) { 694 if (i < ipa->ipa_nmem32) 695 r = &ipa->ipa_mem32[i]; 696 else 697 r = &rz; 698 699 isapnp_write_reg(sc, 700 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24, 701 B3(r->base)); 702 isapnp_write_reg(sc, 703 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16, 704 B2(r->base)); 705 isapnp_write_reg(sc, 706 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8, 707 B1(r->base)); 708 isapnp_write_reg(sc, 709 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0, 710 B0(r->base)); 711 712 isapnp_write_reg(sc, 713 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24, 714 B3(r->length)); 715 isapnp_write_reg(sc, 716 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16, 717 B2(r->length)); 718 isapnp_write_reg(sc, 719 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8, 720 B1(r->length)); 721 isapnp_write_reg(sc, 722 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0, 723 B0(r->length)); 724 } 725 } 726 727 728 /* isapnp_match(): 729 * Probe routine 730 */ 731 static int 732 isapnp_match(parent, match, aux) 733 struct device *parent; 734 #ifdef __BROKEN_INDIRECT_CONFIG 735 void *match; 736 #else 737 struct cfdata *match; 738 #endif 739 void *aux; 740 { 741 int rv; 742 struct isapnp_softc sc; 743 struct isa_attach_args *ia = aux; 744 745 sc.sc_iot = ia->ia_iot; 746 sc.sc_ncards = 0; 747 (void) strcpy(sc.sc_dev.dv_xname, "(isapnp probe)"); 748 749 if (isapnp_map(&sc)) 750 return 0; 751 752 rv = isapnp_find(&sc, 0); 753 ia->ia_iobase = ISAPNP_ADDR; 754 ia->ia_iosize = 1; 755 756 isapnp_unmap(&sc); 757 if (rv) 758 isapnp_unmap_readport(&sc); 759 760 return (rv); 761 } 762 763 764 /* isapnp_attach 765 * Find and attach PnP cards. 766 */ 767 static void 768 isapnp_attach(parent, self, aux) 769 struct device *parent, *self; 770 void *aux; 771 { 772 struct isapnp_softc *sc = (struct isapnp_softc *) self; 773 struct isa_attach_args *ia = aux; 774 int c, d; 775 776 sc->sc_iot = ia->ia_iot; 777 sc->sc_memt = ia->ia_memt; 778 sc->sc_ncards = 0; 779 780 if (isapnp_map(sc)) 781 panic("%s: bus map failed\n", sc->sc_dev.dv_xname); 782 783 if (!isapnp_find(sc, 1)) 784 panic("%s: no cards found\n", sc->sc_dev.dv_xname); 785 786 printf(": read port 0x%x\n", sc->sc_read_port); 787 788 for (c = 0; c < sc->sc_ncards; c++) { 789 struct isapnp_attach_args *ipa, *lpa; 790 791 /* Good morning card c */ 792 isapnp_write_reg(sc, ISAPNP_WAKE, c + 1); 793 794 if ((ipa = isapnp_get_resource(sc, c)) == NULL) 795 continue; 796 797 DPRINTF(("Selecting attachments\n")); 798 for (d = 0; (lpa = isapnp_bestconfig(sc, &ipa)) != NULL; d++) { 799 isapnp_write_reg(sc, ISAPNP_LOGICAL_DEV_NUM, d); 800 isapnp_configure(sc, lpa); 801 #ifdef DEBUG_ISAPNP 802 { 803 struct isapnp_attach_args pa; 804 805 isapnp_get_config(sc, &pa); 806 isapnp_print_config(&pa); 807 } 808 #endif 809 810 #ifdef DEBUG 811 /* XXX do we even really need this? --thorpej */ 812 printf("%s: configuring <%s, %s, %s, %s>\n", 813 sc->sc_dev.dv_xname, 814 lpa->ipa_devident, lpa->ipa_devlogic, 815 lpa->ipa_devcompat, lpa->ipa_devclass); 816 #endif 817 818 if (lpa->ipa_pref == ISAPNP_DEP_CONFLICTING) { 819 printf("%s: <%s, %s, %s, %s> ignored; %s\n", 820 sc->sc_dev.dv_xname, 821 lpa->ipa_devident, lpa->ipa_devlogic, 822 lpa->ipa_devcompat, lpa->ipa_devclass, 823 "resource conflict"); 824 ISAPNP_FREE(lpa); 825 continue; 826 } 827 828 lpa->ipa_ic = ia->ia_ic; 829 lpa->ipa_iot = ia->ia_iot; 830 lpa->ipa_memt = ia->ia_memt; 831 lpa->ipa_dmat = ia->ia_dmat; 832 833 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1); 834 #ifdef _KERNEL 835 if (config_found_sm(self, lpa, isapnp_print, 836 isapnp_submatch) == NULL) 837 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 0); 838 #else 839 isapnp_print(lpa, NULL); 840 printf("\n"); 841 #endif 842 ISAPNP_FREE(lpa); 843 } 844 isapnp_write_reg(sc, ISAPNP_WAKE, 0); /* Good night cards */ 845 } 846 } 847