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