1/* $NetBSD: isapnp.c,v 1.58 2008/04/28 20:23:53 martin Exp $ */ 2 3/*- 4 * Copyright (c) 1996, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * ISA PnP bus autoconfiguration. 34 */ 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: isapnp.c,v 1.58 2008/04/28 20:23:53 martin Exp $"); 38 39#include "isadma.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/device.h> 44#include <sys/malloc.h> 45 46#include <sys/bus.h> 47 48#include <dev/isa/isavar.h> 49 50#include <dev/isapnp/isapnpreg.h> 51#include <dev/isapnp/isapnpvar.h> 52#include <dev/isapnp/isapnpdevs.h> 53 54#include "wss_isapnp.h" /* XXX part of disgusting CS chip hack */ 55 56#ifndef ISAPNP_ALLOC_INTR_MASK 57#define ISAPNP_ALLOC_INTR_MASK (~0) 58#endif 59 60static void isapnp_init(struct isapnp_softc *); 61static inline u_char isapnp_shift_bit(struct isapnp_softc *); 62static int isapnp_findcard(struct isapnp_softc *); 63static void isapnp_free_region(bus_space_tag_t, struct isapnp_region *); 64static int isapnp_alloc_region(bus_space_tag_t, struct isapnp_region *); 65static int isapnp_alloc_irq(isa_chipset_tag_t, struct isapnp_pin *); 66static int isapnp_alloc_drq(isa_chipset_tag_t, struct isapnp_pin *); 67static int isapnp_testconfig(bus_space_tag_t, bus_space_tag_t, 68 struct isapnp_attach_args *, int); 69static struct isapnp_attach_args *isapnp_bestconfig(struct isapnp_softc *, 70 struct isapnp_attach_args **); 71static void isapnp_print_region(const char *, struct isapnp_region *, size_t); 72static void isapnp_configure(struct isapnp_softc *, 73 const struct isapnp_attach_args *); 74static void isapnp_print_pin(const char *, struct isapnp_pin *, size_t); 75static int isapnp_print(void *, const char *); 76#ifdef _KERNEL 77static int isapnp_submatch(device_t, cfdata_t, const int *, void *); 78#endif 79static int isapnp_find(struct isapnp_softc *, int); 80static int isapnp_match(device_t, cfdata_t, void *); 81static void isapnp_attach(device_t, device_t, void *); 82static void isapnp_callback(device_t); 83 84CFATTACH_DECL_NEW(isapnp, sizeof(struct isapnp_softc), 85 isapnp_match, isapnp_attach, NULL, NULL); 86 87/* 88 * This keeps track if which ISA's we have been probed on. 89 */ 90struct isapnp_probe_cookie { 91 LIST_ENTRY(isapnp_probe_cookie) ipc_link; 92 device_t ipc_parent; 93}; 94LIST_HEAD(, isapnp_probe_cookie) isapnp_probes = 95 LIST_HEAD_INITIALIZER(isapnp_probes); 96 97/* isapnp_init(): 98 * Write the PNP initiation key to wake up the cards... 99 */ 100static void 101isapnp_init(struct isapnp_softc *sc) 102{ 103 int i; 104 u_char v = ISAPNP_LFSR_INIT; 105 106 /* First write 0's twice to enter the Wait for Key state */ 107 ISAPNP_WRITE_ADDR(sc, 0); 108 ISAPNP_WRITE_ADDR(sc, 0); 109 110 /* Send the 32 byte sequence to awake the logic */ 111 for (i = 0; i < ISAPNP_LFSR_LENGTH; i++) { 112 ISAPNP_WRITE_ADDR(sc, v); 113 v = ISAPNP_LFSR_NEXT(v); 114 } 115} 116 117 118/* isapnp_shift_bit(): 119 * Read a bit at a time from the config card. 120 */ 121static inline u_char 122isapnp_shift_bit(struct isapnp_softc *sc) 123{ 124 u_char c1, c2; 125 126 DELAY(250); 127 c1 = ISAPNP_READ_DATA(sc); 128 DELAY(250); 129 c2 = ISAPNP_READ_DATA(sc); 130 131 if (c1 == 0x55 && c2 == 0xAA) 132 return 0x80; 133 else 134 return 0; 135} 136 137 138/* isapnp_findcard(): 139 * Attempt to read the vendor/serial/checksum for a card 140 * If a card is found [the checksum matches], assign the 141 * next card number to it and return 1 142 */ 143static int 144isapnp_findcard(struct isapnp_softc *sc) 145{ 146 u_char v = ISAPNP_LFSR_INIT, csum, w; 147 int i, b; 148 149 if (sc->sc_ncards == ISAPNP_MAX_CARDS) { 150 aprint_error_dev(sc->sc_dev, "Too many pnp cards\n"); 151 return 0; 152 } 153 154 /* Set the read port */ 155 isapnp_write_reg(sc, ISAPNP_WAKE, 0); 156 isapnp_write_reg(sc, ISAPNP_SET_RD_PORT, sc->sc_read_port >> 2); 157 sc->sc_read_port |= 3; 158 DELAY(1000); 159 160 ISAPNP_WRITE_ADDR(sc, ISAPNP_SERIAL_ISOLATION); 161 DELAY(1000); 162 163 /* Read the 8 bytes of the Vendor ID and Serial Number */ 164 for(i = 0; i < 8; i++) { 165 /* Read each bit separately */ 166 for (w = 0, b = 0; b < 8; b++) { 167 u_char neg = isapnp_shift_bit(sc); 168 169 w >>= 1; 170 w |= neg; 171 v = ISAPNP_LFSR_NEXT(v) ^ neg; 172 } 173 sc->sc_id[sc->sc_ncards][i] = w; 174 } 175 176 /* Read the remaining checksum byte */ 177 for (csum = 0, b = 0; b < 8; b++) { 178 u_char neg = isapnp_shift_bit(sc); 179 180 csum >>= 1; 181 csum |= neg; 182 } 183 sc->sc_id[sc->sc_ncards][8] = csum; 184 185 if (csum == v) { 186 sc->sc_ncards++; 187 isapnp_write_reg(sc, ISAPNP_CARD_SELECT_NUM, sc->sc_ncards); 188 return 1; 189 } 190 return 0; 191} 192 193 194/* isapnp_free_region(): 195 * Free a region 196 */ 197static void 198isapnp_free_region(bus_space_tag_t t, struct isapnp_region *r) 199{ 200 if (r->length == 0) 201 return; 202 203#ifdef _KERNEL 204 bus_space_unmap(t, r->h, r->length); 205#endif 206} 207 208 209/* isapnp_alloc_region(): 210 * Allocate a single region if possible 211 */ 212static int 213isapnp_alloc_region(bus_space_tag_t t, struct isapnp_region *r) 214{ 215 int error = 0; 216 217 if (r->length == 0) { 218 r->base = 0; 219 return 0; 220 } 221 222 for (r->base = r->minbase; r->base <= r->maxbase; 223 r->base += r->align) { 224#ifdef _KERNEL 225 error = bus_space_map(t, r->base, r->length, 0, &r->h); 226#endif 227 if (error == 0) 228 return 0; 229 if (r->align == 0) 230 break; 231 } 232 return error; 233} 234 235 236/* isapnp_alloc_irq(): 237 * Allocate an irq 238 */ 239static int 240isapnp_alloc_irq(isa_chipset_tag_t ic, struct isapnp_pin *i) 241{ 242 int irq; 243#define LEVEL_IRQ (ISAPNP_IRQTYPE_LEVEL_PLUS|ISAPNP_IRQTYPE_LEVEL_MINUS) 244 i->type = (i->flags & LEVEL_IRQ) ? IST_LEVEL : IST_EDGE; 245 246 if (i->bits == 0) { 247 i->num = 0; 248 return 0; 249 } 250 251 if (isa_intr_alloc(ic, ISAPNP_ALLOC_INTR_MASK & i->bits, 252 i->type, &irq) == 0) { 253 i->num = irq; 254 return 0; 255 } 256 257 return EINVAL; 258} 259 260/* isapnp_alloc_drq(): 261 * Allocate a drq 262 */ 263static int 264isapnp_alloc_drq(isa_chipset_tag_t ic, struct isapnp_pin *i) 265{ 266#if NISADMA > 0 267 int b; 268 269 if (i->bits == 0) { 270 i->num = 0; 271 return 0; 272 } 273 274 for (b = 0; b < 8; b++) 275 if ((i->bits & (1 << b)) && isa_drq_isfree(ic, b)) { 276 i->num = b; 277 return 0; 278 } 279#endif /* NISADMA > 0 */ 280 281 return EINVAL; 282} 283 284/* isapnp_testconfig(): 285 * Test/Allocate the regions used 286 */ 287static int 288isapnp_testconfig(bus_space_tag_t iot, bus_space_tag_t memt, 289 struct isapnp_attach_args *ipa, int alloc) 290{ 291 int nio = 0, nmem = 0, nmem32 = 0, nirq = 0, ndrq = 0; 292 int error = 0; 293 294#ifdef DEBUG_ISAPNP 295 isapnp_print_attach(ipa); 296#endif 297 298 for (; nio < ipa->ipa_nio; nio++) { 299 error = isapnp_alloc_region(iot, &ipa->ipa_io[nio]); 300 if (error) 301 goto bad; 302 } 303 304 for (; nmem < ipa->ipa_nmem; nmem++) { 305 error = isapnp_alloc_region(memt, &ipa->ipa_mem[nmem]); 306 if (error) 307 goto bad; 308 } 309 310 for (; nmem32 < ipa->ipa_nmem32; nmem32++) { 311 error = isapnp_alloc_region(memt, &ipa->ipa_mem32[nmem32]); 312 if (error) 313 goto bad; 314 } 315 316 for (; nirq < ipa->ipa_nirq; nirq++) { 317 error = isapnp_alloc_irq(ipa->ipa_ic, &ipa->ipa_irq[nirq]); 318 if (error) 319 goto bad; 320 } 321 322 for (; ndrq < ipa->ipa_ndrq; ndrq++) { 323 error = isapnp_alloc_drq(ipa->ipa_ic, &ipa->ipa_drq[ndrq]); 324 if (error) 325 goto bad; 326 } 327 328 if (alloc) 329 return error; 330 331bad: 332#ifdef notyet 333 for (ndrq--; ndrq >= 0; ndrq--) 334 isapnp_free_pin(&ipa->ipa_drq[ndrq]); 335 336 for (nirq--; nirq >= 0; nirq--) 337 isapnp_free_pin(&ipa->ipa_irq[nirq]); 338#endif 339 340 for (nmem32--; nmem32 >= 0; nmem32--) 341 isapnp_free_region(memt, &ipa->ipa_mem32[nmem32]); 342 343 for (nmem--; nmem >= 0; nmem--) 344 isapnp_free_region(memt, &ipa->ipa_mem[nmem]); 345 346 for (nio--; nio >= 0; nio--) 347 isapnp_free_region(iot, &ipa->ipa_io[nio]); 348 349 return error; 350} 351 352 353/* isapnp_config(): 354 * Test/Allocate the regions used 355 */ 356int 357isapnp_config(bus_space_tag_t iot, bus_space_tag_t memt, 358 struct isapnp_attach_args *ipa) 359{ 360 return isapnp_testconfig(iot, memt, ipa, 1); 361} 362 363 364/* isapnp_unconfig(): 365 * Free the regions used 366 */ 367void 368isapnp_unconfig(bus_space_tag_t iot, bus_space_tag_t memt, 369 struct isapnp_attach_args *ipa) 370{ 371 int i; 372 373#ifdef notyet 374 for (i = 0; i < ipa->ipa_ndrq; i++) 375 isapnp_free_pin(&ipa->ipa_drq[i]); 376 377 for (i = 0; i < ipa->ipa_nirq; i++) 378 isapnp_free_pin(&ipa->ipa_irq[i]); 379#endif 380 381 for (i = 0; i < ipa->ipa_nmem32; i++) 382 isapnp_free_region(memt, &ipa->ipa_mem32[i]); 383 384 for (i = 0; i < ipa->ipa_nmem; i++) 385 isapnp_free_region(memt, &ipa->ipa_mem[i]); 386 387 for (i = 0; i < ipa->ipa_nio; i++) 388 isapnp_free_region(iot, &ipa->ipa_io[i]); 389} 390 391 392/* isapnp_bestconfig(): 393 * Return the best configuration for each logical device, remove and 394 * free all other configurations. 395 */ 396static struct isapnp_attach_args * 397isapnp_bestconfig(struct isapnp_softc *sc, struct isapnp_attach_args **ipa) 398{ 399 struct isapnp_attach_args *c, *best, *f = *ipa; 400 int error; 401 402 for (;;) { 403 if (f == NULL) 404 return NULL; 405 406#define SAMEDEV(a, b) (strcmp((a)->ipa_devlogic, (b)->ipa_devlogic) == 0) 407 408 /* Find the best config */ 409 for (best = c = f; c != NULL; c = c->ipa_sibling) { 410 if (!SAMEDEV(c, f)) 411 continue; 412 if (c->ipa_pref < best->ipa_pref) 413 best = c; 414 } 415 416 /* 417 * Make sure the ISA chipset is initialized! We need 418 * it to test the best config! 419 */ 420 best->ipa_ic = sc->sc_ic; 421 422 /* Test the best config */ 423 error = isapnp_testconfig(sc->sc_iot, sc->sc_memt, best, 0); 424 425 /* Remove this config from the list */ 426 if (best == f) 427 f = f->ipa_sibling; 428 else { 429 for (c = f; c->ipa_sibling != best; c = c->ipa_sibling) 430 continue; 431 c->ipa_sibling = best->ipa_sibling; 432 } 433 434 if (error) { 435 best->ipa_pref = ISAPNP_DEP_CONFLICTING; 436 437 for (c = f; c != NULL; c = c->ipa_sibling) 438 if (c != best && SAMEDEV(c, best)) 439 break; 440 /* Last config for this logical device is conflicting */ 441 if (c == NULL) { 442 *ipa = f; 443 return best; 444 } 445 446 ISAPNP_FREE(best); 447 continue; 448 } 449 else { 450 /* Remove all other configs for this device */ 451 struct isapnp_attach_args *l = NULL, *n = NULL, *d; 452 453 for (c = f; c; ) { 454 if (c == best) 455 continue; 456 d = c->ipa_sibling; 457 if (SAMEDEV(c, best)) 458 ISAPNP_FREE(c); 459 else { 460 if (n) 461 n->ipa_sibling = c; 462 463 else 464 l = c; 465 n = c; 466 c->ipa_sibling = NULL; 467 } 468 c = d; 469 } 470 f = l; 471 } 472 *ipa = f; 473 return best; 474 } 475} 476 477 478/* isapnp_id_to_vendor(): 479 * Convert a pnp ``compressed ascii'' vendor id to a string 480 */ 481char * 482isapnp_id_to_vendor(char *v, const u_char *id) 483{ 484 char *p = v; 485 486 *p++ = 'A' + (id[0] >> 2) - 1; 487 *p++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1; 488 *p++ = 'A' + (id[1] & 0x1f) - 1; 489 *p++ = HEXDIGITS[id[2] >> 4]; 490 *p++ = HEXDIGITS[id[2] & 0x0f]; 491 *p++ = HEXDIGITS[id[3] >> 4]; 492 *p++ = HEXDIGITS[id[3] & 0x0f]; 493 *p = '\0'; 494 495 return v; 496} 497 498 499/* isapnp_print_region(): 500 * Print a region allocation 501 */ 502static void 503isapnp_print_region(const char *str, struct isapnp_region *r, size_t n) 504{ 505 size_t i; 506 507 if (n == 0) 508 return; 509 510 aprint_normal(" %s ", str); 511 for (i = 0; i < n; i++, r++) { 512 aprint_normal("0x%x", r->base); 513 if (r->length) 514 aprint_normal("/%d", r->length); 515 if (i != n - 1) 516 aprint_normal(","); 517 } 518} 519 520 521/* isapnp_print_pin(): 522 * Print an irq/drq assignment 523 */ 524static void 525isapnp_print_pin(const char *str, struct isapnp_pin *p, size_t n) 526{ 527 size_t i; 528 529 if (n == 0) 530 return; 531 532 printf(" %s ", str); 533 for (i = 0; i < n; i++, p++) { 534 printf("%d", p->num); 535 if (i != n - 1) 536 printf(","); 537 } 538} 539 540 541/* isapnp_print(): 542 * Print the configuration line for an ISA PnP card. 543 */ 544static int 545isapnp_print(void *aux, const char *str) 546{ 547 struct isapnp_attach_args *ipa = aux; 548 549 if (str != NULL) 550 aprint_normal("%s: <%s, %s, %s, %s>", 551 str, ipa->ipa_devident, ipa->ipa_devlogic, 552 ipa->ipa_devcompat, ipa->ipa_devclass); 553 554 isapnp_print_region("port", ipa->ipa_io, ipa->ipa_nio); 555 isapnp_print_region("mem", ipa->ipa_mem, ipa->ipa_nmem); 556 isapnp_print_region("mem32", ipa->ipa_mem32, ipa->ipa_nmem32); 557 isapnp_print_pin("irq", ipa->ipa_irq, ipa->ipa_nirq); 558 isapnp_print_pin("drq", ipa->ipa_drq, ipa->ipa_ndrq); 559 560 return UNCONF; 561} 562 563 564#ifdef _KERNEL 565/* isapnp_submatch(): 566 * Probe the logical device... 567 */ 568static int 569isapnp_submatch(device_t parent, cfdata_t match, const int *ldesc, void *aux) 570{ 571 572 return (config_match(parent, match, aux)); 573} 574 575 576/* isapnp_devmatch(): 577 * Match a probed device with the information from the driver 578 */ 579int 580isapnp_devmatch(const struct isapnp_attach_args *ipa, 581 const struct isapnp_devinfo *dinfo, int *variant) 582{ 583 const struct isapnp_matchinfo *match; 584 int n; 585 586 for (match = dinfo->devlogic, n = dinfo->nlogic; n--; match++) 587 if (strcmp(match->name, ipa->ipa_devlogic) == 0) { 588 *variant = match->variant; 589 return (1); 590 } 591 592 for (match = dinfo->devcompat, n = dinfo->ncompat; n--; match++) 593 if (strcmp(match->name, ipa->ipa_devcompat) == 0) { 594 *variant = match->variant; 595 return (1); 596 } 597 598 return (0); 599} 600 601 602/* isapnp_isa_attach_hook(): 603 * This routine is called from the isa attach code and 604 * is a kludge; we are resetting all the cards here in order 605 * to undo any card configuration that the bios did for us, in order 606 * to avoid having the PnP devices match an isa probe. The correct 607 * way of doing this is to read the PnP BIOS and find the card settings 608 * from there. Unfortunately it is not as easy as it sounds. 609 */ 610void 611isapnp_isa_attach_hook(struct isa_softc *isa_sc) 612{ 613 struct isapnp_softc sc; 614 615 sc.sc_iot = isa_sc->sc_iot; 616 sc.sc_ncards = 0; 617 618 if (isapnp_map(&sc)) 619 return; 620 621#if NWSS_ISAPNP > 0 622 /* 623 * XXX XXX 624 * This a totally disgusting hack, but I can't figure out another way. 625 * It seems that many CS audio chips have a bug (as far as I can 626 * understand). The reset below does not really reset the chip, it 627 * remains in a catatonic state and will not respond when probed. 628 * The chip can be used both as a WSS and as a SB device, and a 629 * single read at the WSS address (0x534) takes it out of this 630 * non-responsive state. 631 * The read has to happen at this point in time (or earlier) so 632 * it cannot be moved to the wss_isapnp.c driver. 633 * (BTW, We're not alone in having problems with these chips: 634 * Windoze 98 couldn't detect the sound chip on a Dell when I tried.) 635 * 636 * Lennart Augustsson <augustss@NetBSD.org> 637 * 638 * (Implementation from John Kohl <jtk@kolvir.arlington.ma.us>) 639 */ 640 { 641 bus_space_handle_t ioh; 642 int rv; 643 if ((rv = bus_space_map(sc.sc_iot, 0x534, 1, 0, &ioh)) == 0) { 644 DPRINTF(("wss probe kludge\n")); 645 (void)bus_space_read_1(sc.sc_iot, ioh, 0); 646 bus_space_unmap(sc.sc_iot, ioh, 1); 647 } else { 648 DPRINTF(("wss probe kludge failed to map: %d\n", rv)); 649 } 650 } 651#endif 652 653 isapnp_init(&sc); 654 655 isapnp_write_reg(&sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV); 656 DELAY(2000); 657 658 isapnp_unmap(&sc); 659} 660#endif 661 662 663/* isapnp_find(): 664 * Probe and add cards 665 */ 666static int 667isapnp_find(struct isapnp_softc *sc, int all) 668{ 669 int p; 670 671 isapnp_init(sc); 672 673 isapnp_write_reg(sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV); 674 DELAY(2000); 675 676 isapnp_init(sc); 677 DELAY(2000); 678 679 for (p = ISAPNP_RDDATA_MIN; p <= ISAPNP_RDDATA_MAX; p += 4) { 680 sc->sc_read_port = p; 681 if (isapnp_map_readport(sc)) 682 continue; 683 DPRINTF(("%s: Trying port %x\r", device_xname(sc->sc_dev), p)); 684 if (isapnp_findcard(sc)) 685 break; 686 isapnp_unmap_readport(sc); 687 } 688 689 if (p > ISAPNP_RDDATA_MAX) { 690 sc->sc_read_port = 0; 691 return 0; 692 } 693 694 if (all) 695 while (isapnp_findcard(sc)) 696 continue; 697 698 return 1; 699} 700 701 702/* isapnp_configure(): 703 * Configure a PnP card 704 * XXX: The memory configuration code is wrong. We need to check the 705 * range/length bit an do appropriate sets. 706 */ 707static void 708isapnp_configure(struct isapnp_softc *sc, const struct isapnp_attach_args *ipa) 709{ 710 int i; 711 static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC; 712 static u_char isapnp_io_range[] = ISAPNP_IO_DESC; 713 static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC; 714 static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC; 715 static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC; 716 const struct isapnp_region *r; 717 const struct isapnp_pin *p; 718 struct isapnp_region rz; 719 struct isapnp_pin pz; 720 721 memset(&pz, 0, sizeof(pz)); 722 memset(&rz, 0, sizeof(rz)); 723 724#define B0(a) ((a) & 0xff) 725#define B1(a) (((a) >> 8) & 0xff) 726#define B2(a) (((a) >> 16) & 0xff) 727#define B3(a) (((a) >> 24) & 0xff) 728 729 for (i = 0; i < sizeof(isapnp_io_range); i++) { 730 if (i < ipa->ipa_nio) 731 r = &ipa->ipa_io[i]; 732 else 733 r = &rz; 734 735 isapnp_write_reg(sc, 736 isapnp_io_range[i] + ISAPNP_IO_BASE_15_8, B1(r->base)); 737 isapnp_write_reg(sc, 738 isapnp_io_range[i] + ISAPNP_IO_BASE_7_0, B0(r->base)); 739 } 740 741 for (i = 0; i < sizeof(isapnp_mem_range); i++) { 742 if (i < ipa->ipa_nmem) 743 r = &ipa->ipa_mem[i]; 744 else 745 r = &rz; 746 747 isapnp_write_reg(sc, 748 isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16, B2(r->base)); 749 isapnp_write_reg(sc, 750 isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8, B1(r->base)); 751 752 isapnp_write_reg(sc, 753 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16, 754 B2(r->length)); 755 isapnp_write_reg(sc, 756 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8, 757 B1(r->length)); 758 } 759 760 for (i = 0; i < sizeof(isapnp_irq_range); i++) { 761 u_char v; 762 763 if (i < ipa->ipa_nirq) 764 p = &ipa->ipa_irq[i]; 765 else 766 p = &pz; 767 768 isapnp_write_reg(sc, 769 isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER, p->num); 770 771 switch (p->flags) { 772 case ISAPNP_IRQTYPE_LEVEL_PLUS: 773 v = ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH; 774 break; 775 776 case ISAPNP_IRQTYPE_EDGE_PLUS: 777 v = ISAPNP_IRQ_HIGH; 778 break; 779 780 case ISAPNP_IRQTYPE_LEVEL_MINUS: 781 v = ISAPNP_IRQ_LEVEL; 782 break; 783 784 default: 785 case ISAPNP_IRQTYPE_EDGE_MINUS: 786 v = 0; 787 break; 788 } 789 isapnp_write_reg(sc, 790 isapnp_irq_range[i] + ISAPNP_IRQ_CONTROL, v); 791 } 792 793 for (i = 0; i < sizeof(isapnp_drq_range); i++) { 794 u_char v; 795 796 if (i < ipa->ipa_ndrq) 797 v = ipa->ipa_drq[i].num; 798 else 799 v = 4; 800 801 isapnp_write_reg(sc, isapnp_drq_range[i], v); 802 } 803 804 for (i = 0; i < sizeof(isapnp_mem32_range); i++) { 805 if (i < ipa->ipa_nmem32) 806 r = &ipa->ipa_mem32[i]; 807 else 808 r = &rz; 809 810 isapnp_write_reg(sc, 811 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24, 812 B3(r->base)); 813 isapnp_write_reg(sc, 814 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16, 815 B2(r->base)); 816 isapnp_write_reg(sc, 817 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8, 818 B1(r->base)); 819 isapnp_write_reg(sc, 820 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0, 821 B0(r->base)); 822 823 isapnp_write_reg(sc, 824 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24, 825 B3(r->length)); 826 isapnp_write_reg(sc, 827 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16, 828 B2(r->length)); 829 isapnp_write_reg(sc, 830 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8, 831 B1(r->length)); 832 isapnp_write_reg(sc, 833 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0, 834 B0(r->length)); 835 } 836} 837 838 839/* isapnp_match(): 840 * Probe routine 841 */ 842static int 843isapnp_match(device_t parent, cfdata_t match, void *aux) 844{ 845 struct isapnp_softc sc; 846 struct isa_attach_args *ia = aux; 847 struct isapnp_probe_cookie *ipc; 848 849 /* 850 * If the system has no ISA expansion slots, skip the probe 851 * because it's very slow. 852 */ 853 if (isa_get_slotcount() == 0) 854 return (0); 855 856 /* 857 * Ensure we only probe ISA PnP once; we don't actually consume 858 * bus resources, so we have to prevent being cloned forever. 859 */ 860 for (ipc = LIST_FIRST(&isapnp_probes); ipc != NULL; 861 ipc = LIST_NEXT(ipc, ipc_link)) 862 if (ipc->ipc_parent == parent) 863 return (0); 864 865 ipc = malloc(sizeof(*ipc), M_DEVBUF, M_NOWAIT); 866 if (ipc == NULL) 867 panic("isapnp_match: can't allocate probe cookie"); 868 869 ipc->ipc_parent = parent; 870 LIST_INSERT_HEAD(&isapnp_probes, ipc, ipc_link); 871 872 sc.sc_iot = ia->ia_iot; 873 874 if (isapnp_map(&sc)) 875 return 0; 876 877 isapnp_unmap(&sc); 878 879 /* 880 * We always match. We must let all legacy ISA devices map 881 * their address spaces before we look for a read port. 882 */ 883 ia->ia_io[0].ir_addr = ISAPNP_ADDR; 884 ia->ia_io[0].ir_size = 1; 885 886 ia->ia_niomem = 0; 887 ia->ia_nirq = 0; 888 ia->ia_ndrq = 0; 889 890 return (1); 891} 892 893 894/* isapnp_attach 895 * Attach the PnP `bus'. 896 */ 897static void 898isapnp_attach(device_t parent, device_t self, void *aux) 899{ 900 struct isapnp_softc *sc = device_private(self); 901 struct isa_attach_args *ia = aux; 902 903 sc->sc_dev = self; 904 sc->sc_iot = ia->ia_iot; 905 sc->sc_memt = ia->ia_memt; 906 sc->sc_ic = ia->ia_ic; 907 sc->sc_dmat = ia->ia_dmat; 908 sc->sc_ncards = 0; 909 910 aprint_naive("\n"); 911 aprint_normal("\n"); 912 913 if (isapnp_map(sc)) { 914 aprint_error_dev(self, "unable to map PnP register\n"); 915 return; 916 } 917 918#ifdef _KERNEL 919 /* 920 * Defer configuration until the rest of the ISA devices have 921 * attached themselves. 922 */ 923 config_defer(self, isapnp_callback); 924#else 925 isapnp_callback(self); 926#endif 927 928 if (!pmf_device_register(self, NULL, NULL)) 929 aprint_error_dev(self, "couldn't establish power handler\n"); 930} 931 932/* isapnp_callback 933 * Find and attach PnP cards. 934 */ 935void 936isapnp_callback(device_t self) 937{ 938 struct isapnp_softc *sc = device_private(self); 939 struct isapnp_attach_args *ipa, *lpa; 940 int c, d; 941 942 /* 943 * Look for cards. If none are found, we say so and just return. 944 */ 945 if (isapnp_find(sc, 1) == 0) { 946 aprint_verbose_dev(sc->sc_dev, 947 "no ISA Plug 'n Play devices found\n"); 948 return; 949 } 950 951 aprint_verbose_dev(sc->sc_dev, "read port 0x%x\n", sc->sc_read_port); 952 953 /* 954 * Now configure all of the cards. 955 */ 956 for (c = 0; c < sc->sc_ncards; c++) { 957 /* Good morning card c */ 958 isapnp_write_reg(sc, ISAPNP_WAKE, c + 1); 959 960 if ((ipa = isapnp_get_resource(sc, c)) == NULL) 961 continue; 962 963 DPRINTF(("Selecting attachments\n")); 964 for (d = 0; 965 (lpa = isapnp_bestconfig(sc, &ipa)) != NULL; d++) { 966 isapnp_write_reg(sc, ISAPNP_LOGICAL_DEV_NUM, d); 967 isapnp_configure(sc, lpa); 968#ifdef DEBUG_ISAPNP 969 { 970 struct isapnp_attach_args pa; 971 972 isapnp_get_config(sc, &pa); 973 isapnp_print_config(&pa); 974 } 975#endif 976 977 DPRINTF(("%s: configuring <%s, %s, %s, %s>\n", 978 device_xname(sc->sc_dev), 979 lpa->ipa_devident, lpa->ipa_devlogic, 980 lpa->ipa_devcompat, lpa->ipa_devclass)); 981 if (lpa->ipa_pref == ISAPNP_DEP_CONFLICTING) { 982 aprint_verbose_dev(sc->sc_dev, 983 "<%s, %s, %s, %s> ignored; %s\n", 984 lpa->ipa_devident, lpa->ipa_devlogic, 985 lpa->ipa_devcompat, lpa->ipa_devclass, 986 "resource conflict"); 987 ISAPNP_FREE(lpa); 988 continue; 989 } 990 991 lpa->ipa_ic = sc->sc_ic; 992 lpa->ipa_iot = sc->sc_iot; 993 lpa->ipa_memt = sc->sc_memt; 994 lpa->ipa_dmat = sc->sc_dmat; 995 996 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1); 997#ifdef _KERNEL 998 if (config_found_sm_loc(self, "isapnp", NULL, lpa, 999 isapnp_print, isapnp_submatch) == NULL) 1000 isapnp_write_reg(sc, ISAPNP_ACTIVATE, 0); 1001#else 1002 isapnp_print(lpa, NULL); 1003 aprint_verbose("\n"); 1004#endif 1005 ISAPNP_FREE(lpa); 1006 } 1007 isapnp_write_reg(sc, ISAPNP_WAKE, 0); /* Good night cards */ 1008 } 1009} 1010