1 /* $OpenBSD: mpcpcibus.c,v 1.38 2009/03/29 22:58:31 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Per Fogelstrom 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 /* 30 * Generic PCI BUS Bridge driver. 31 * specialized hooks for different config methods. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 #include <sys/device.h> 39 #include <sys/proc.h> 40 #include <uvm/uvm_extern.h> 41 42 #include <machine/autoconf.h> 43 #include <machine/pcb.h> 44 #include <machine/bat.h> 45 #include <machine/powerpc.h> 46 47 #include <dev/pci/pcireg.h> 48 #include <dev/pci/pcivar.h> 49 #include <dev/pci/pcidevs.h> 50 51 #include <macppc/pci/pcibrvar.h> 52 #include <macppc/pci/mpc106reg.h> 53 54 #include <dev/ofw/openfirm.h> 55 56 int mpcpcibrmatch(struct device *, void *, void *); 57 void mpcpcibrattach(struct device *, struct device *, void *); 58 59 void mpc_attach_hook(struct device *, struct device *, 60 struct pcibus_attach_args *); 61 int mpc_bus_maxdevs(void *, int); 62 pcitag_t mpc_make_tag(void *, int, int, int); 63 void mpc_decompose_tag(void *, pcitag_t, int *, int *, int *); 64 pcireg_t mpc_conf_read(void *, pcitag_t, int); 65 void mpc_conf_write(void *, pcitag_t, int, pcireg_t); 66 67 int mpc_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *); 68 const char *mpc_intr_string(void *, pci_intr_handle_t); 69 int mpc_intr_line(void *, pci_intr_handle_t); 70 void *mpc_intr_establish(void *, pci_intr_handle_t, 71 int, int (*func)(void *), void *, char *); 72 void mpc_intr_disestablish(void *, void *); 73 int mpc_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *); 74 u_int32_t mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset); 75 int of_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *); 76 int find_node_intr (int parent, u_int32_t *addr, u_int32_t *intr); 77 u_int32_t pci_iack(void); 78 79 void fix_node_irq(int node, struct pcibus_attach_args *pba); 80 81 struct cfattach mpcpcibr_ca = { 82 sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach, 83 }; 84 85 struct cfdriver mpcpcibr_cd = { 86 NULL, "mpcpcibr", DV_DULL, 87 }; 88 89 static int mpcpcibrprint(void *, const char *pnp); 90 91 struct pcibr_config mpc_config; 92 93 /* 94 * config types 95 * bit meanings 96 * 0 - standard cf8/cfc type configurations, 97 * sometimes the base addresses for these are different 98 * 1 - Config Method #2 configuration - uni-north 99 * 100 * 2 - 64 bit config bus, data for accesses &4 is at daddr+4; 101 */ 102 struct config_type{ 103 char * compat; 104 u_int32_t addr; /* offset */ 105 u_int32_t data; /* offset */ 106 int config_type; 107 }; 108 struct config_type config_offsets[] = { 109 {"grackle", 0x00c00cf8, 0x00e00cfc, 0 }, 110 {"bandit", 0x00800000, 0x00c00000, 1 }, 111 {"uni-north", 0x00800000, 0x00c00000, 3 }, 112 {"u3-agp", 0x00800000, 0x00c00000, 3 }, 113 {"u3-ht", 0x00000cf8, 0x00000cfc, 3 }, 114 {"legacy", 0x00000cf8, 0x00000cfc, 0 }, 115 {"IBM,27-82660", 0x00000cf8, 0x00000cfc, 0 }, 116 {NULL, 0x00000000, 0x00000000, 0 }, 117 }; 118 119 struct powerpc_bus_dma_tag pci_bus_dma_tag = { 120 NULL, 121 _dmamap_create, 122 _dmamap_destroy, 123 _dmamap_load, 124 _dmamap_load_mbuf, 125 _dmamap_load_uio, 126 _dmamap_load_raw, 127 _dmamap_unload, 128 _dmamap_sync, 129 _dmamem_alloc, 130 _dmamem_free, 131 _dmamem_map, 132 _dmamem_unmap, 133 _dmamem_mmap 134 }; 135 136 int 137 mpcpcibrmatch(struct device *parent, void *match, void *aux) 138 { 139 struct confargs *ca = aux; 140 int found = 0; 141 142 if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0) 143 return (found); 144 145 found = 1; 146 147 return found; 148 } 149 150 int pci_map_a = 0; 151 152 struct ranges_32 { 153 u_int32_t flags; 154 u_int32_t pad1; 155 u_int32_t pad2; 156 u_int32_t base; 157 u_int32_t pad3; 158 u_int32_t size; 159 }; 160 void 161 mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store, 162 int rangesize); 163 void 164 mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store, 165 int rangesize); 166 void 167 mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store, 168 int rangesize) 169 { 170 int found; 171 unsigned int base = 0; 172 unsigned int size = 0; 173 struct ranges_32 *prange = (void *)range_store; 174 int rangelen; 175 int i; 176 177 rangelen = rangesize / sizeof (struct ranges_32); 178 179 /* mac configs */ 180 sc->sc_membus_space.bus_base = 0; 181 sc->sc_membus_space.bus_io = 0; 182 sc->sc_iobus_space.bus_base = 0; 183 sc->sc_iobus_space.bus_io = 1; 184 185 /* find io(config) base, flag == 0x01000000 */ 186 found = 0; 187 for (i = 0; i < rangelen ; i++) { 188 if (prange[i].flags == 0x01000000) { 189 /* find last? */ 190 found = i; 191 } 192 } 193 /* found the io space ranges */ 194 if (prange[found].flags == 0x01000000) { 195 sc->sc_iobus_space.bus_base = 196 prange[found].base; 197 sc->sc_iobus_space.bus_size = 198 prange[found].size; 199 } 200 201 /* the mem space ranges 202 * apple openfirmware always puts full 203 * addresses in config information, 204 * it is not necessary to have correct bus 205 * base address, but since 0 is reserved 206 * and all IO and device memory will be in 207 * upper 2G of address space, set to 208 * 0x80000000 209 * start with segment 1 not 0, 0 is config. 210 */ 211 for (i = 0; i < rangelen ; i++) { 212 if (prange[i].flags == 0x02000000) { 213 #ifdef DEBUG_PCI 214 printf("\nfound mem %x %x", 215 prange[i].base, 216 prange[i].size); 217 #endif 218 if (base != 0) { 219 if ((base + size) == prange[i].base) 220 size += prange[i].size; 221 else { 222 size = prange[i].size; 223 base = prange[i].base; 224 } 225 } else { 226 base = prange[i].base; 227 size = prange[i].size; 228 } 229 } 230 } 231 sc->sc_membus_space.bus_base = base; 232 sc->sc_membus_space.bus_size = size; 233 } 234 235 struct ranges_64 { 236 u_int32_t flags; 237 u_int32_t pad1; 238 u_int32_t pad2; 239 u_int32_t pad3; 240 u_int32_t base; 241 u_int32_t pad4; 242 u_int32_t size; 243 }; 244 void 245 mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store, 246 int rangesize) 247 { 248 int i, found; 249 unsigned int base = 0; 250 unsigned int size = 0; 251 int rangelen; 252 struct ranges_64 *prange = (void *)range_store; 253 254 rangelen = rangesize / sizeof (struct ranges_64); 255 256 /* mac configs */ 257 258 sc->sc_membus_space.bus_base = 0; 259 sc->sc_membus_space.bus_io = 0; 260 sc->sc_iobus_space.bus_base = 0; 261 sc->sc_iobus_space.bus_io = 1; 262 263 if (prange[0].flags == 0xabb10113) { /* appl U3; */ 264 prange[0].flags = 0x01000000; 265 prange[0].base = 0xf8070000; 266 prange[0].size = 0x00001000; 267 prange[1].flags = 0x02000000; 268 prange[1].base = 0xf2000000; 269 prange[1].size = 0x02800000; 270 rangelen = 2; 271 } 272 273 /* find io(config) base, flag == 0x01000000 */ 274 found = 0; 275 for (i = 0; i < rangelen ; i++) { 276 if (prange[i].flags == 0x01000000) { 277 /* find last? */ 278 found = i; 279 } 280 } 281 /* found the io space ranges */ 282 if (prange[found].flags == 0x01000000) { 283 sc->sc_iobus_space.bus_base = prange[found].base; 284 sc->sc_iobus_space.bus_size = prange[found].size; 285 } 286 287 /* the mem space ranges 288 * apple openfirmware always puts full 289 * addresses in config information, 290 * it is not necessary to have correct bus 291 * base address, but since 0 is reserved 292 * and all IO and device memory will be in 293 * upper 2G of address space, set to 294 * 0x80000000 295 * start with segment 1 not 0, 0 is config. 296 */ 297 for (i = 0; i < rangelen ; i++) { 298 if (prange[i].flags == 0x02000000) { 299 #ifdef DEBUG_PCI 300 printf("\nfound mem %x %x", 301 prange[i].base, 302 prange[i].size); 303 #endif 304 305 if (base != 0) { 306 if ((base + size) == prange[i].base) { 307 size += prange[i].size; 308 } else { 309 base = prange[i].base; 310 size = prange[i].size; 311 } 312 } else { 313 base = prange[i].base; 314 size = prange[i].size; 315 } 316 } 317 } 318 sc->sc_membus_space.bus_base = base; 319 sc->sc_membus_space.bus_size = size; 320 } 321 322 void 323 mpcpcibrattach(struct device *parent, struct device *self, void *aux) 324 { 325 struct pcibr_softc *sc = (struct pcibr_softc *)self; 326 struct confargs *ca = aux; 327 struct pcibr_config *lcp; 328 struct pcibus_attach_args pba; 329 int node; 330 int of_node = 0; 331 char compat[32]; 332 u_int32_t addr_offset; 333 u_int32_t data_offset; 334 int i; 335 int len; 336 int rangesize; 337 u_int32_t range_store[32]; 338 339 if (ca->ca_node == 0) { 340 printf("invalid node on mpcpcibr config\n"); 341 return; 342 } 343 len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat)); 344 compat[len] = '\0'; 345 if (len > 0) 346 printf(" %s", compat); 347 348 len=OF_getprop(ca->ca_node, "compatible", compat, 349 sizeof (compat)); 350 if (len <= 0 ) { 351 len=OF_getprop(ca->ca_node, "name", compat, 352 sizeof (compat)); 353 if (len <= 0) { 354 printf(" compatible and name not found\n"); 355 return; 356 } 357 compat[len] = 0; 358 if (strcmp (compat, "bandit") != 0) { 359 printf(" compatible not found and name %s found\n", 360 compat); 361 return; 362 } 363 } 364 compat[len] = 0; 365 if ((rangesize = OF_getprop(ca->ca_node, "ranges", 366 range_store, sizeof (range_store))) <= 0) { 367 if (strcmp(compat, "u3-ht") == 0) { 368 range_store[0] = 0xabb10113; /* appl U3; */ 369 } else 370 printf("range lookup failed, node %x\n", ca->ca_node); 371 } 372 /* translate byte(s) into item count*/ 373 374 lcp = sc->sc_pcibr = &sc->pcibr_config; 375 376 if (ppc_proc_is_64b) 377 mpcpcibus_find_ranges_64 (sc, range_store, rangesize); 378 else 379 mpcpcibus_find_ranges_32 (sc, range_store, rangesize); 380 381 addr_offset = 0; 382 for (i = 0; config_offsets[i].compat != NULL; i++) { 383 struct config_type *co = &config_offsets[i]; 384 if (strcmp(co->compat, compat) == 0) { 385 addr_offset = co->addr; 386 data_offset = co->data; 387 lcp->config_type = co->config_type; 388 break; 389 } 390 } 391 if (addr_offset == 0) { 392 printf("unable to find match for" 393 " compatible %s\n", compat); 394 return; 395 } 396 #ifdef DEBUG_FIXUP 397 printf(" mem base %x sz %x io base %x sz %x\n" 398 " config addr %x config data %x\n", 399 sc->sc_membus_space.bus_base, 400 sc->sc_membus_space.bus_size, 401 sc->sc_iobus_space.bus_base, 402 sc->sc_iobus_space.bus_size, 403 addr_offset, data_offset); 404 #endif 405 406 if ( bus_space_map(&(sc->sc_iobus_space), addr_offset, 407 NBPG, 0, &lcp->ioh_cf8) != 0 ) 408 panic("mpcpcibus: unable to map self"); 409 410 if ( bus_space_map(&(sc->sc_iobus_space), data_offset, 411 NBPG, 0, &lcp->ioh_cfc) != 0 ) 412 panic("mpcpcibus: unable to map self"); 413 414 of_node = ca->ca_node; 415 416 lcp->node = ca->ca_node; 417 lcp->lc_pc.pc_conf_v = lcp; 418 lcp->lc_pc.pc_attach_hook = mpc_attach_hook; 419 lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs; 420 lcp->lc_pc.pc_make_tag = mpc_make_tag; 421 lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag; 422 lcp->lc_pc.pc_conf_read = mpc_conf_read; 423 lcp->lc_pc.pc_conf_write = mpc_conf_write; 424 lcp->lc_pc.pc_ether_hw_addr = of_ether_hw_addr; 425 lcp->lc_iot = &sc->sc_iobus_space; 426 lcp->lc_memt = &sc->sc_membus_space; 427 428 lcp->lc_pc.pc_intr_v = lcp; 429 lcp->lc_pc.pc_intr_map = mpc_intr_map; 430 lcp->lc_pc.pc_intr_string = mpc_intr_string; 431 lcp->lc_pc.pc_intr_line = mpc_intr_line; 432 lcp->lc_pc.pc_intr_establish = mpc_intr_establish; 433 lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish; 434 435 printf(": %s, Revision 0x%x\n", compat, 436 mpc_cfg_read_1(lcp, MPC106_PCI_REVID)); 437 438 if ((strcmp(compat, "bandit")) != 0) 439 pci_addr_fixup(sc, &lcp->lc_pc, 32); 440 441 bzero(&pba, sizeof(pba)); 442 pba.pba_dmat = &pci_bus_dma_tag; 443 444 pba.pba_busname = "pci"; 445 pba.pba_iot = &sc->sc_iobus_space; 446 pba.pba_memt = &sc->sc_membus_space; 447 pba.pba_pc = &lcp->lc_pc; 448 pba.pba_domain = pci_ndomains++; 449 pba.pba_bus = 0; 450 451 /* we want to check pci irq settings */ 452 if (of_node != 0) { 453 int nn; 454 455 for (node = OF_child(of_node); node; node = nn) { 456 char name[32]; 457 int len; 458 len = OF_getprop(node, "name", name, 459 sizeof(name)); 460 name[len] = 0; 461 fix_node_irq(node, &pba); 462 463 /* iterate section */ 464 if ((nn = OF_child(node)) != 0) 465 continue; 466 467 while ((nn = OF_peer(node)) == 0) { 468 node = OF_parent(node); 469 if (node == of_node) { 470 nn = 0; /* done */ 471 break; 472 } 473 } 474 } 475 } 476 477 config_found(self, &pba, mpcpcibrprint); 478 479 } 480 481 #define OFW_PCI_PHYS_HI_BUSMASK 0x00ff0000 482 #define OFW_PCI_PHYS_HI_BUSSHIFT 16 483 #define OFW_PCI_PHYS_HI_DEVICEMASK 0x0000f800 484 #define OFW_PCI_PHYS_HI_DEVICESHIFT 11 485 #define OFW_PCI_PHYS_HI_FUNCTIONMASK 0x00000700 486 #define OFW_PCI_PHYS_HI_FUNCTIONSHIFT 8 487 488 #define pcibus(x) \ 489 (((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT) 490 #define pcidev(x) \ 491 (((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT) 492 #define pcifunc(x) \ 493 (((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT) 494 495 /* 496 * Find PCI IRQ from OF. 497 */ 498 int 499 find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr) 500 { 501 int iparent, len, mlen, alen, ilen; 502 int match, i, step; 503 u_int32_t map[144], *mp, *mp1; 504 u_int32_t imask[8], maskedaddr[8]; 505 u_int32_t address_cells, interrupt_cells, mask_cells; 506 507 len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); 508 mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask)); 509 alen = OF_getprop(parent, "#address-cells", 510 &address_cells, sizeof(address_cells)); 511 ilen = OF_getprop(parent, "#interrupt-cells", 512 &interrupt_cells, sizeof(interrupt_cells)); 513 514 if (len == -1 || mlen == -1 || alen == -1 || ilen == -1) 515 goto nomap; 516 517 mask_cells = address_cells + interrupt_cells; 518 if (mask_cells != (mlen / sizeof(u_int32_t))) 519 goto nomap; 520 for (i = 0; i < mask_cells; i++) 521 maskedaddr[i] = addr[i] & imask[i]; 522 523 /* interrupt-map is formatted as follows 524 * int * #address-cells, int * #interrupt-cells, int, int, int 525 * eg 526 * address-cells = 3 527 * interrupt-cells = 1 528 * 00001000 00000000 00000000 00000000 ff911258 00000034 00000001 529 * 00001800 00000000 00000000 00000000 ff911258 00000035 00000001 530 * 00002000 00000000 00000000 00000000 ff911258 00000036 00000001 531 * | address cells | | intr | |parent| | irq | |edge/level| 532 * | cells| | interrupt cells | 533 * | of parent | 534 * or at least something close to that. 535 */ 536 537 mp = map; 538 while (len > mlen) { 539 mp1 = mp + mask_cells; 540 541 iparent = *mp1; 542 alen = OF_getprop(iparent, "#address-cells", 543 &address_cells, sizeof(address_cells)); 544 if (alen == -1) 545 address_cells = 0; 546 ilen = OF_getprop(iparent, "#interrupt-cells", 547 &interrupt_cells, sizeof(interrupt_cells)); 548 if (ilen == -1) 549 goto nomap; 550 551 step = mask_cells + 1 + address_cells + interrupt_cells; 552 553 match = bcmp(maskedaddr, mp, mlen); 554 if (match == 0) { 555 if (OF_getprop(iparent, "interrupt-controller", 556 NULL, 0) == 0) { 557 *intr = mp1[1]; 558 return 1; 559 } 560 /* Recurse with new 'addr'. */ 561 return find_node_intr(iparent, &mp1[1], intr); 562 } 563 len -= step * sizeof(u_int32_t); 564 mp += step; 565 } 566 nomap: 567 return -1; 568 } 569 570 void 571 fix_node_irq(int node, struct pcibus_attach_args *pba) 572 { 573 struct { 574 u_int32_t phys_hi, phys_mid, phys_lo; 575 u_int32_t size_hi, size_lo; 576 } addr [8]; 577 u_int32_t map[144]; 578 int len; 579 pcitag_t tag; 580 u_int32_t irq; 581 u_int32_t intr; 582 int parent; 583 584 pci_chipset_tag_t pc = pba->pba_pc; 585 586 len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); 587 if (len == -1 || len < sizeof(addr[0])) 588 return; 589 590 /* if this node has a AAPL,interrupts property, firmware 591 * has initialized the register correctly. 592 */ 593 len = OF_getprop(node, "AAPL,interrupts", &intr, 4); 594 if (len != 4) { 595 596 parent = OF_parent(node); 597 598 irq = -1; 599 600 /* we want the first interrupt, set size_hi to 1 */ 601 addr[0].size_hi = 1; 602 if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1) { 603 len = OF_getprop(node, "interrupts", map, 604 sizeof(map)); 605 if (len != -1 && len != 4) { 606 irq = map[0]; 607 } else 608 return; 609 } 610 } else 611 irq = intr; 612 /* program the interrupt line register with the value 613 * found in openfirmware 614 */ 615 616 tag = pci_make_tag(pc, pcibus(addr[0].phys_hi), 617 pcidev(addr[0].phys_hi), pcifunc(addr[0].phys_hi)); 618 619 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); 620 intr &= ~PCI_INTERRUPT_LINE_MASK; 621 intr |= irq & PCI_INTERRUPT_LINE_MASK; 622 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr); 623 } 624 625 static int 626 mpcpcibrprint(void *aux, const char *pnp) 627 { 628 struct pcibus_attach_args *pba = aux; 629 630 if (pnp) 631 printf("%s at %s", pba->pba_busname, pnp); 632 printf(" bus %d", pba->pba_bus); 633 return(UNCONF); 634 } 635 636 void 637 mpc_attach_hook(struct device *parent, struct device *self, 638 struct pcibus_attach_args *pba) 639 { 640 } 641 642 int 643 of_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr) 644 { 645 u_int8_t laddr[6]; 646 struct pcibr_config *lcp = lcpc->pc_conf_v; 647 int of_node = lcp->node; 648 int node, nn; 649 for (node = OF_child(of_node); node; node = nn) { 650 char name[32]; 651 int len; 652 len = OF_getprop(node, "name", name, 653 sizeof(name)); 654 name[len] = 0; 655 656 len = OF_getprop(node, "local-mac-address", laddr, 657 sizeof laddr); 658 if (sizeof (laddr) == len) { 659 bcopy (laddr, oaddr, sizeof laddr); 660 return 1; 661 } 662 663 /* iterate section */ 664 if ((nn = OF_child(node)) != 0) { 665 continue; 666 } 667 while ((nn = OF_peer(node)) == 0) { 668 node = OF_parent(node); 669 if (node == of_node) { 670 nn = 0; /* done */ 671 break; 672 } 673 } 674 } 675 oaddr[0] = oaddr[1] = oaddr[2] = 0xff; 676 oaddr[3] = oaddr[4] = oaddr[5] = 0xff; 677 return 0; 678 } 679 680 int 681 mpc_ether_hw_addr(struct ppc_pci_chipset *p, u_int8_t *s) 682 { 683 printf("mpc_ether_hw_addr not supported\n"); 684 return(0); 685 } 686 687 int 688 mpc_bus_maxdevs(void *cpv, int busno) 689 { 690 return(32); 691 } 692 693 #define BUS_SHIFT 16 694 #define DEVICE_SHIFT 11 695 #define FNC_SHIFT 8 696 697 pcitag_t 698 mpc_make_tag(void *cpv, int bus, int dev, int fnc) 699 { 700 return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT); 701 } 702 703 void 704 mpc_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *fncp) 705 { 706 if (busp != NULL) 707 *busp = (tag >> BUS_SHIFT) & 0xff; 708 if (devp != NULL) 709 *devp = (tag >> DEVICE_SHIFT) & 0x1f; 710 if (fncp != NULL) 711 *fncp = (tag >> FNC_SHIFT) & 0x7; 712 } 713 714 u_int32_t 715 mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset) 716 { 717 struct pcibr_config *cp = cpv; 718 unsigned int bus, dev, fcn; 719 u_int32_t reg; 720 721 mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn); 722 723 if (cp->config_type & 1) { 724 /* Config Mechanism #2 */ 725 if (bus == 0) { 726 if (dev < 11) 727 return 0xffffffff; 728 /* 729 * Need to do config type 0 operation 730 * 1 << (11?+dev) | fcn << 8 | reg 731 * 11? is because pci spec states 732 * that 11-15 is reserved. 733 */ 734 reg = 1 << (dev) | fcn << 8 | offset; 735 736 } else { 737 if (dev > 15) 738 return 0xffffffff; 739 /* 740 * config type 1 741 */ 742 reg = tag | offset | 1; 743 } 744 } else { 745 /* config mechanism #2, type 0 746 * standard cf8/cfc config 747 */ 748 reg = 0x80000000 | tag | offset; 749 } 750 751 return reg; 752 } 753 754 /* #define DEBUG_CONFIG */ 755 pcireg_t 756 mpc_conf_read(void *cpv, pcitag_t tag, int offset) 757 { 758 struct pcibr_config *cp = cpv; 759 pcireg_t data; 760 u_int32_t reg; 761 int s; 762 int daddr = 0; 763 faultbuf env; 764 void *oldh; 765 766 if (offset & 3 || offset < 0 || offset >= 0x100) { 767 #ifdef DEBUG_CONFIG 768 printf ("pci_conf_read: bad reg %x\n", offset); 769 #endif /* DEBUG_CONFIG */ 770 return(~0); 771 } 772 773 reg = mpc_gen_config_reg(cpv, tag, offset); 774 /* if invalid tag, return -1 */ 775 if (reg == 0xffffffff) 776 return(~0); 777 778 if ((cp->config_type & 2) && (offset & 0x04)) 779 daddr += 4; 780 781 s = splhigh(); 782 783 oldh = curpcb->pcb_onfault; 784 if (setfault(&env)) { 785 /* we faulted during the read? */ 786 curpcb->pcb_onfault = oldh; 787 splx(s); 788 return 0xffffffff; 789 } 790 791 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg); 792 bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */ 793 data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr); 794 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */ 795 bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */ 796 797 curpcb->pcb_onfault = oldh; 798 799 splx(s); 800 #ifdef DEBUG_CONFIG 801 if (!((offset == 0) && (data == 0xffffffff))) { 802 unsigned int bus, dev, fcn; 803 mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn); 804 printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn, 805 offset); 806 printf(" daddr %x reg %x",daddr, reg); 807 printf(" data %x\n", data); 808 } 809 #endif 810 811 return(data); 812 } 813 814 void 815 mpc_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data) 816 { 817 struct pcibr_config *cp = cpv; 818 u_int32_t reg; 819 int s; 820 int daddr = 0; 821 822 reg = mpc_gen_config_reg(cpv, tag, offset); 823 824 /* if invalid tag, return ??? */ 825 if (reg == 0xffffffff) 826 return; 827 828 if ((cp->config_type & 2) && (offset & 0x04)) 829 daddr += 4; 830 831 #ifdef DEBUG_CONFIG 832 { 833 unsigned int bus, dev, fcn; 834 mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn); 835 printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus, 836 dev, fcn, offset); 837 printf(" daddr %x reg %x",daddr, reg); 838 printf(" data %x\n", data); 839 } 840 #endif 841 842 s = splhigh(); 843 844 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg); 845 bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */ 846 bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data); 847 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */ 848 bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */ 849 850 splx(s); 851 } 852 853 854 /*ARGSUSED*/ 855 int 856 mpc_intr_map(void *lcv, pcitag_t bustag, int buspin, int line, 857 pci_intr_handle_t *ihp) 858 { 859 int error = 0; 860 861 *ihp = -1; 862 if (buspin == 0) 863 error = 1; /* No IRQ used. */ 864 else if (buspin > 4) { 865 printf("mpc_intr_map: bad interrupt pin %d\n", buspin); 866 error = 1; 867 } 868 if (line == 0xff) 869 error = 1; 870 871 if (!error) 872 *ihp = line; 873 return error; 874 } 875 876 const char * 877 mpc_intr_string(void *lcv, pci_intr_handle_t ih) 878 { 879 static char str[16]; 880 881 snprintf(str, sizeof str, "irq %ld", ih); 882 return(str); 883 } 884 885 int 886 mpc_intr_line(void *lcv, pci_intr_handle_t ih) 887 { 888 return (ih); 889 } 890 891 void * 892 mpc_intr_establish(void *lcv, pci_intr_handle_t ih, int level, 893 int (*func)(void *), void *arg, char *name) 894 { 895 return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg, 896 name); 897 } 898 899 void 900 mpc_intr_disestablish(void *lcv, void *cookie) 901 { 902 /* XXX We should probably do something clever here.... later */ 903 } 904 905 u_int32_t 906 pci_iack() 907 { 908 /* do pci IACK cycle */ 909 /* this should be bus allocated. */ 910 volatile u_int8_t *iack = (u_int8_t *)0xbffffff0; 911 u_int8_t val; 912 913 val = *iack; 914 return val; 915 } 916 917 void 918 mpc_cfg_write_1(struct pcibr_config *cp, u_int32_t reg, u_int8_t val) 919 { 920 int s; 921 s = splhigh(); 922 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 923 bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val); 924 splx(s); 925 } 926 927 void 928 mpc_cfg_write_2(struct pcibr_config *cp, u_int32_t reg, u_int16_t val) 929 { 930 int s; 931 s = splhigh(); 932 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 933 bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val); 934 splx(s); 935 } 936 937 void 938 mpc_cfg_write_4(struct pcibr_config *cp, u_int32_t reg, u_int32_t val) 939 { 940 941 int s; 942 s = splhigh(); 943 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 944 bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val); 945 splx(s); 946 } 947 948 u_int8_t 949 mpc_cfg_read_1(struct pcibr_config *cp, u_int32_t reg) 950 { 951 u_int8_t _v_; 952 953 int s; 954 s = splhigh(); 955 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 956 _v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0); 957 splx(s); 958 return(_v_); 959 } 960 961 u_int16_t 962 mpc_cfg_read_2(struct pcibr_config *cp, u_int32_t reg) 963 { 964 u_int16_t _v_; 965 966 int s; 967 s = splhigh(); 968 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 969 _v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0); 970 splx(s); 971 return(_v_); 972 } 973 974 u_int32_t 975 mpc_cfg_read_4(struct pcibr_config *cp, u_int32_t reg) 976 { 977 u_int32_t _v_; 978 979 int s; 980 s = splhigh(); 981 bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg)); 982 _v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0); 983 splx(s); 984 return(_v_); 985 } 986