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