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