1 /* $NetBSD: ofwoea_machdep.c,v 1.64 2024/05/28 11:06:07 macallan Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tim Rightnour 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 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: ofwoea_machdep.c,v 1.64 2024/05/28 11:06:07 macallan Exp $"); 34 35 #include "ksyms.h" 36 #include "wsdisplay.h" 37 38 #ifdef _KERNEL_OPT 39 #include "opt_ddb.h" 40 #include "opt_kgdb.h" 41 #include "opt_modular.h" 42 #include "opt_multiprocessor.h" 43 #include "opt_oea.h" 44 #include "opt_ofwoea.h" 45 #include "opt_ppcarch.h" 46 #endif 47 48 #include <sys/param.h> 49 #include <sys/buf.h> 50 #include <sys/boot_flag.h> 51 #include <sys/extent.h> 52 #include <sys/kernel.h> 53 #include <sys/ksyms.h> 54 #include <uvm/uvm_extern.h> 55 56 #include <dev/ofw/openfirm.h> 57 #include <dev/wscons/wsconsio.h> 58 #include <dev/wscons/wsdisplayvar.h> 59 #include <dev/rasops/rasops.h> 60 #include <dev/wscons/wsdisplay_vconsvar.h> 61 #include <machine/pmap.h> 62 #include <machine/powerpc.h> 63 #include <machine/trap.h> 64 #include <machine/vmparam.h> 65 #include <machine/autoconf.h> 66 #include <sys/bus.h> 67 #include <powerpc/oea/bat.h> 68 #include <powerpc/oea/ofw_rasconsvar.h> 69 #include <powerpc/oea/cpufeat.h> 70 #include <powerpc/include/oea/spr.h> 71 #include <powerpc/ofw_cons.h> 72 #include <powerpc/ofw_machdep.h> 73 #include <powerpc/spr.h> 74 #include <powerpc/pic/picvar.h> 75 76 #ifdef DDB 77 #include <machine/db_machdep.h> 78 #include <ddb/db_extern.h> 79 #endif 80 81 #ifdef KGDB 82 #include <sys/kgdb.h> 83 #endif 84 85 #ifdef ofppc 86 extern struct model_data modeldata; 87 #endif 88 89 #ifdef OFWOEA_DEBUG 90 #define DPRINTF printf 91 #else 92 #define DPRINTF while (0) printf 93 #endif 94 95 typedef struct _rangemap { 96 u_int32_t addr; 97 u_int32_t size; 98 int type; 99 } rangemap_t; 100 101 struct OF_translation ofw_translations[OFW_MAX_TRANSLATIONS]; 102 103 /* 104 * Data structures holding OpenFirmware's translations when running 105 * in virtual-mode. 106 * 107 * When we call into OpenFirmware, we point the calling CPU's 108 * cpu_info::ci_battable at ofw_battable[]. For now, this table 109 * is empty, which will ensure that any DSI exceptions that occur 110 * during the firmware call will not erroneously load kernel BAT 111 * mappings that could clobber the firmware's translations. 112 */ 113 struct pmap ofw_pmap; 114 struct bat ofw_battable[BAT_VA2IDX(0xffffffff)+1]; 115 116 char bootpath[256] = ""; 117 char model_name[64]; 118 #if NKSYMS || defined(DDB) || defined(MODULAR) 119 void *startsym, *endsym; 120 #endif 121 122 #if PPC_OEA601 123 #define TIMEBASE_FREQ (1000000000) /* RTC register */ 124 #endif 125 126 #ifdef TIMEBASE_FREQ 127 u_int timebase_freq = TIMEBASE_FREQ; 128 #else 129 u_int timebase_freq = 0; 130 #endif 131 132 int ofw_quiesce; 133 134 extern int ofwmsr; 135 extern uint32_t ticks_per_sec; 136 extern uint32_t ns_per_tick; 137 extern uint32_t ticks_per_intr; 138 139 static void get_timebase_frequency(void); 140 static void init_decrementer(void); 141 142 static void restore_ofmap(void); 143 144 void 145 ofwoea_initppc(u_int startkernel, u_int endkernel, char *args) 146 { 147 register_t scratch; 148 149 #if NKSYMS || defined(DDB) || defined(MODULAR) 150 /* get info of kernel symbol table from bootloader */ 151 memcpy(&startsym, args + strlen(args) + 1, sizeof(startsym)); 152 memcpy(&endsym, args + strlen(args) + 1 + sizeof(startsym), 153 sizeof(endsym)); 154 if (startsym == NULL || endsym == NULL) 155 startsym = endsym = NULL; 156 #endif 157 158 /* Parse the args string */ 159 if (args) { 160 strcpy(bootpath, args); 161 args = bootpath; 162 while (*++args && *args != ' '); 163 if (*args) { 164 *args++ = 0; 165 while (*args) 166 BOOT_FLAG(*args++, boothowto); 167 } 168 } 169 170 /* if bootpath is still empty, get it from /chosen */ 171 if (bootpath[0] == 0) { 172 int chs = OF_finddevice("/chosen"); 173 int len; 174 175 len = OF_getprop(chs, "bootpath", bootpath, sizeof(bootpath) - 1); 176 if (len > -1) 177 bootpath[len] = 0; 178 } 179 180 /* Get the timebase frequency from the firmware. */ 181 get_timebase_frequency(); 182 183 /* Probe for the console device; it's initialized later. */ 184 ofwoea_cnprobe(); 185 186 if (ofw_quiesce) 187 OF_quiesce(); 188 189 oea_init(pic_ext_intr); 190 191 /* 192 * Now that we've installed our own exception vectors, 193 * ensure that exceptions that happen while running 194 * firmware code fall into ours. 195 */ 196 ofwmsr &= ~PSL_IP; 197 198 /* Initialize bus_space */ 199 ofwoea_bus_space_init(); 200 201 /* Initialize the console device. */ 202 ofwoea_consinit(); 203 204 uvm_md_init(); 205 206 pmap_bootstrap(startkernel, endkernel); 207 208 /* as far as I can tell, the pmap_setup_seg0 stuff is horribly broken */ 209 #if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 210 #if defined (PMAC_G5) 211 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/ 212 if (oeacpufeat & OEACPU_64_BRIDGE) { 213 vaddr_t va; 214 paddr_t pa; 215 vsize_t size; 216 int i; 217 218 pmap_setup_segment0_map(0, msgbuf_paddr, msgbuf_paddr, 219 round_page(MSGBUFSIZE), 0x0); 220 221 /* Map OFW code+data */ 222 223 for (i = 0; i < __arraycount(ofw_translations); i++) { 224 va = ofw_translations[i].virt; 225 size = ofw_translations[i].size; 226 pa = ofw_translations[i].phys; 227 /* XXX mode */ 228 229 if (size == 0) { 230 /* No more, all done! */ 231 break; 232 } 233 234 if (va < 0xff800000) 235 continue; 236 237 238 for (; va < (ofw_translations[i].virt + size); 239 va += PAGE_SIZE, pa += PAGE_SIZE) { 240 pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 241 VM_PROT_ALL | PMAP_WIRED); 242 } 243 } 244 245 #if NWSDISPLAY > 0 246 /* Map video frame buffer */ 247 248 struct rasops_info *ri = &rascons_console_screen.scr_ri; 249 250 if (ri->ri_bits != NULL) { 251 for (va = (vaddr_t) ri->ri_bits; 252 va < round_page((vaddr_t) ri->ri_bits + 253 ri->ri_height * ri->ri_stride); 254 va += PAGE_SIZE) { 255 pmap_enter(pmap_kernel(), va, va, 256 VM_PROT_READ | VM_PROT_WRITE, 257 PMAP_NOCACHE | PMAP_WIRED); 258 } 259 } 260 #endif 261 } 262 #elif defined (MAMBO) 263 /* Mapin 1st 256MB segment 1:1, also map in mem needed to access OFW*/ 264 if (oeacpufeat & OEACPU_64_BRIDGE) 265 pmap_setup_segment0_map(0, 0xf4000000, 0xf4000000, 0x1000, 0x0); 266 #endif /* PMAC_G5 */ 267 #endif /* PPC_OEA64 || PPC_OEA64_BRIDGE */ 268 269 /* Now enable translation (and machine checks/recoverable interrupts) */ 270 __asm __volatile ("sync; mfmsr %0; ori %0,%0,%1; mtmsr %0; isync" 271 : "=r"(scratch) 272 : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI)); 273 274 restore_ofmap(); 275 276 #if NWSDISPLAY > 0 277 rascons_finalize(); 278 #endif 279 280 #if NKSYMS || defined(DDB) || defined(MODULAR) 281 ksyms_addsyms_elf((int)((uintptr_t)endsym - (uintptr_t)startsym), startsym, endsym); 282 #endif 283 284 /* Kick off the clock. */ 285 init_decrementer(); 286 287 #ifdef DDB 288 if (boothowto & RB_KDB) 289 Debugger(); 290 #endif 291 } 292 293 static void 294 get_timebase_frequency(void) 295 { 296 int qhandle, phandle, node; 297 char type[32]; 298 299 if (timebase_freq != 0) { 300 ticks_per_sec = timebase_freq; 301 return; 302 } 303 304 node = OF_finddevice("/cpus/@0"); 305 if (node != -1 && 306 OF_getprop(node, "timebase-frequency", &ticks_per_sec, 307 sizeof ticks_per_sec) > 0) { 308 return; 309 } 310 311 node = OF_finddevice("/"); 312 for (qhandle = node; qhandle; qhandle = phandle) { 313 if (OF_getprop(qhandle, "device_type", type, sizeof type) > 0 314 && strcmp(type, "cpu") == 0 315 && OF_getprop(qhandle, "timebase-frequency", 316 &ticks_per_sec, sizeof ticks_per_sec) > 0) { 317 return; 318 } 319 if ((phandle = OF_child(qhandle))) 320 continue; 321 while (qhandle) { 322 if ((phandle = OF_peer(qhandle))) 323 break; 324 qhandle = OF_parent(qhandle); 325 } 326 } 327 panic("no cpu node"); 328 } 329 330 static void 331 init_decrementer(void) 332 { 333 int scratch, msr; 334 335 KASSERT(ticks_per_sec != 0); 336 337 __asm volatile ("mfmsr %0; andi. %1,%0,%2; mtmsr %1" 338 : "=r"(msr), "=r"(scratch) : "K"((u_short)~PSL_EE)); 339 ns_per_tick = 1000000000 / ticks_per_sec; 340 ticks_per_intr = ticks_per_sec / hz; 341 cpu_timebase = ticks_per_sec; 342 343 #ifdef PPC_OEA601 344 if ((mfpvr() >> 16) == MPC601) 345 curcpu()->ci_lasttb = rtc_nanosecs(); 346 else 347 #endif 348 curcpu()->ci_lasttb = mftbl(); 349 350 mtspr(SPR_DEC, ticks_per_intr); 351 mtmsr(msr); 352 } 353 354 void 355 restore_ofmap(void) 356 { 357 vaddr_t va, size; 358 paddr_t pa; 359 int i; 360 361 pmap_pinit(&ofw_pmap); 362 363 #ifndef _LP64 364 ofw_pmap.pm_sr[0] = KERNELN_SEGMENT(0)|SR_PRKEY; 365 ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT|SR_SUKEY|SR_PRKEY; 366 367 #ifdef KERNEL2_SR 368 ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT|SR_SUKEY|SR_PRKEY; 369 #endif 370 #endif 371 372 for (i = 0; i < __arraycount(ofw_translations); i++) { 373 va = ofw_translations[i].virt; 374 size = ofw_translations[i].size; 375 pa = ofw_translations[i].phys; 376 /* XXX mode */ 377 378 if (size == 0) { 379 /* No more, all done! */ 380 break; 381 } 382 383 if (va < 0xf0000000) /* XXX */ 384 continue; 385 386 /* 387 * XXX macallan@ 388 * My beige G3 throws a DSI trap if we try to map the last page 389 * of the 32bit address space. On old world macs the firmware 390 * ROM occupies 4MB at 0xffc00000, triggering it when we 391 * restore OF translations. This just works around a bug 392 * elsewhere in pmap and should go away once fixed there. 393 */ 394 if (pa == 0xffc00000 && size == 0x400000) 395 size = 0x3ff000; 396 397 while (size > 0) { 398 pmap_enter(&ofw_pmap, va, pa, VM_PROT_ALL, 399 VM_PROT_ALL|PMAP_WIRED); 400 pa += PAGE_SIZE; 401 va += PAGE_SIZE; 402 size -= PAGE_SIZE; 403 } 404 } 405 pmap_update(&ofw_pmap); 406 } 407 408 /* we define these partially, as we will fill the rest in later */ 409 struct powerpc_bus_space genppc_isa_io_space_tag = { 410 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 411 .pbs_base = 0x00000000, 412 }; 413 414 struct powerpc_bus_space genppc_isa_mem_space_tag = { 415 .pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 416 .pbs_base = 0x00000000, 417 }; 418 419 /* This gives us a maximum of 6 PCI busses, assuming both io/mem on each. 420 * Increase if necc. 421 */ 422 static char ex_storage[EXSTORAGE_MAX][EXTENT_FIXED_STORAGE_SIZE(EXTMAP_RANGES)] 423 __attribute__((aligned(8))); 424 425 426 static void 427 find_ranges(int base, rangemap_t *regions, int *cur, int type) 428 { 429 int node, i, len, reclen; 430 u_int32_t parent_acells, acells, scells, map[160]; 431 char tmp[32]; 432 433 node = base; 434 if (OF_getprop(node, "device_type", tmp, sizeof(tmp)) == -1) 435 goto rec; 436 if ((type == RANGE_TYPE_PCI || type == RANGE_TYPE_FIRSTPCI) && 437 strcmp("pci", tmp) != 0) 438 goto rec; 439 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) != 0) 440 goto rec; 441 if (type == RANGE_TYPE_MACIO && strcmp("memory-controller", tmp) == 0) { 442 len = OF_getprop(node, "reg", map, sizeof(map)); 443 acells = 1; 444 scells = 1; 445 } else { 446 len = OF_getprop(node, "ranges", map, sizeof(map)); 447 } 448 if (len == -1) 449 goto rec; 450 if (OF_getprop(OF_parent(node), "#address-cells", &parent_acells, 451 sizeof(parent_acells)) != sizeof(parent_acells)) 452 parent_acells = 1; 453 if (OF_getprop(node, "#address-cells", &acells, 454 sizeof(acells)) != sizeof(acells)) 455 acells = 3; 456 if (OF_getprop(node, "#size-cells", &scells, 457 sizeof(scells)) != sizeof(scells)) 458 scells = 2; 459 #ifdef ofppc 460 if (modeldata.ranges_offset == 0) 461 scells -= 1; 462 #endif 463 if (type == RANGE_TYPE_ISA) 464 reclen = 6; 465 else 466 reclen = parent_acells + acells + scells; 467 /* 468 * There exist ISA buses with empty ranges properties. This is 469 * known to occur on the Pegasos II machine, and likely others. 470 * According to them, that means that the isa bus is a fake bus, and 471 * the real maps are the PCI maps of the preceding bus. To deal 472 * with this, we will set cur to -1 and return. 473 */ 474 if (type == RANGE_TYPE_ISA && strcmp("isa", tmp) == 0 && len == 0) { 475 *cur = -1; 476 DPRINTF("Found empty range in isa bus\n"); 477 return; 478 } 479 480 DPRINTF("found a map reclen=%d cur=%d len=%d\n", reclen, *cur, len); 481 switch (type) { 482 case RANGE_TYPE_PCI: 483 case RANGE_TYPE_FIRSTPCI: 484 for (i=0; i < len/(4*reclen); i++) { 485 DPRINTF("FOUND PCI RANGE\n"); 486 regions[*cur].size = 487 map[i*reclen + parent_acells + acells + scells - 1]; 488 /* skip ranges of size==0 */ 489 if (regions[*cur].size == 0) 490 continue; 491 regions[*cur].type = (map[i*reclen] >> 24) & 0x3; 492 regions[*cur].addr = map[i*reclen + parent_acells + acells - 1]; 493 (*cur)++; 494 } 495 break; 496 case RANGE_TYPE_ISA: 497 for (i=0; i < len/(4*reclen); i++) { 498 if (map[i*reclen] == 1) 499 regions[*cur].type = RANGE_IO; 500 else 501 regions[*cur].type = RANGE_MEM; 502 DPRINTF("FOUND ISA RANGE TYPE=%d\n", 503 regions[*cur].type); 504 regions[*cur].size = 505 map[i*reclen + acells + scells]; 506 (*cur)++; 507 } 508 break; 509 case RANGE_TYPE_MACIO: 510 regions[*cur].type = RANGE_MEM; 511 if (len == 8) { 512 regions[*cur].size = map[1]; 513 regions[*cur].addr = map[0]; 514 } else { 515 regions[*cur].size = map[2]; 516 regions[*cur].addr = map[1]; 517 } 518 (*cur)++; 519 break; 520 } 521 DPRINTF("returning with CUR=%d\n", *cur); 522 return; 523 rec: 524 for (node = OF_child(base); node; node = OF_peer(node)) { 525 DPRINTF("RECURSE 1 STEP\n"); 526 find_ranges(node, regions, cur, type); 527 if (*cur == -1) 528 return; 529 } 530 } 531 532 static int 533 find_lowest_range(rangemap_t *ranges, int nrof, int type) 534 { 535 int i, low = 0; 536 u_int32_t addr = 0xffffffff; 537 538 for (i=0; i < nrof; i++) { 539 if (ranges[i].type == type && ranges[i].addr != 0 && 540 ranges[i].addr < addr) { 541 low = i; 542 addr = ranges[i].addr; 543 } 544 } 545 if (addr == 0xffffffff) 546 return -1; 547 return low; 548 } 549 550 /* 551 * Find a region of memory, and create a bus_space_tag for it. 552 * Notes: 553 * For ISA node is ignored. 554 * node is the starting node. if -1, we start at / and map everything. 555 */ 556 557 int 558 ofwoea_map_space(int rangetype, int iomem, int node, 559 struct powerpc_bus_space *tag, const char *name) 560 { 561 int i, cur, range, nrofholes, error; 562 static int exmap=0; 563 rangemap_t region, holes[32], list[32]; 564 565 memset(list, 0, sizeof(list)); 566 memset(®ion, 0, sizeof(region)); 567 cur = 0; 568 if (rangetype == RANGE_TYPE_ISA || node == -1) 569 node = OF_finddevice("/"); 570 if (rangetype == RANGE_TYPE_ISA) { 571 u_int32_t size = 0; 572 rangemap_t regions[32]; 573 574 DPRINTF("LOOKING FOR FIRSTPCI\n"); 575 find_ranges(node, list, &cur, RANGE_TYPE_FIRSTPCI); 576 range = 0; 577 DPRINTF("LOOKING FOR ISA\n"); 578 find_ranges(node, regions, &range, RANGE_TYPE_ISA); 579 if (range == 0 || cur == 0) 580 return -1; /* no isa stuff found */ 581 /* 582 * This may be confusing to some. The ISA ranges property 583 * is supposed to be a set of IO ranges for the ISA bus, but 584 * generally, it's just a set of pci devfunc lists that tell 585 * you to go look at the parent PCI device for the actual 586 * ranges. 587 */ 588 if (range == -1) { 589 /* we found a rangeless isa bus */ 590 if (iomem == RANGE_IO) 591 size = 0x10000; 592 else 593 size = 0x1000000; 594 } 595 DPRINTF("found isa stuff\n"); 596 for (i=0; i < range; i++) 597 if (regions[i].type == iomem) 598 size = regions[i].size; 599 if (iomem == RANGE_IO) { 600 /* the first io range is the one */ 601 for (i=0; i < cur; i++) 602 if (list[i].type == RANGE_IO && size) { 603 DPRINTF("found IO\n"); 604 tag->pbs_offset = list[i].addr; 605 tag->pbs_limit = size; 606 error = bus_space_init(tag, name, 607 ex_storage[exmap], 608 sizeof(ex_storage[exmap])); 609 exmap++; 610 return error; 611 } 612 } else { 613 for (i=0; i < cur; i++) 614 if (list[i].type == RANGE_MEM && 615 list[i].size == size) { 616 DPRINTF("found mem\n"); 617 tag->pbs_offset = list[i].addr; 618 tag->pbs_limit = size; 619 error = bus_space_init(tag, name, 620 ex_storage[exmap], 621 sizeof(ex_storage[exmap])); 622 exmap++; 623 return error; 624 } 625 } 626 return -1; /* NO ISA FOUND */ 627 } 628 find_ranges(node, list, &cur, rangetype); 629 630 DPRINTF("cur == %d\n", cur); 631 /* now list should contain a list of memory regions */ 632 for (i=0; i < cur; i++) 633 DPRINTF("addr=0x%x size=0x%x type=%d\n", list[i].addr, 634 list[i].size, list[i].type); 635 636 range = find_lowest_range(list, cur, iomem); 637 i = 0; 638 nrofholes = 0; 639 while (range != -1) { 640 DPRINTF("range==%d\n", range); 641 DPRINTF("i==%d\n", i); 642 if (i == 0) { 643 memcpy(®ion, &list[range], sizeof(rangemap_t)); 644 list[range].addr = 0; 645 i++; 646 range = find_lowest_range(list, cur, iomem); 647 continue; 648 } 649 if (region.addr + region.size < list[range].addr) { 650 /* allocate a hole */ 651 holes[nrofholes].type = iomem; 652 holes[nrofholes].addr = region.size + region.addr; 653 holes[nrofholes].size = list[range].addr - 654 holes[nrofholes].addr - 1; 655 nrofholes++; 656 } 657 region.size = list[range].size + list[range].addr - 658 region.addr; 659 list[range].addr = 0; 660 range = find_lowest_range(list, cur, iomem); 661 } 662 DPRINTF("RANGE iomem=%d FOUND\n", iomem); 663 DPRINTF("addr=0x%x size=0x%x type=%d\n", region.addr, 664 region.size, region.type); 665 DPRINTF("HOLES FOUND\n"); 666 for (i=0; i < nrofholes; i++) 667 DPRINTF("addr=0x%x size=0x%x type=%d\n", holes[i].addr, 668 holes[i].size, holes[i].type); 669 /* AT THIS POINT WE MAP IT */ 670 671 if ((rangetype == RANGE_TYPE_PCI) || (rangetype == RANGE_TYPE_MACIO)) { 672 if (exmap == EXSTORAGE_MAX) 673 panic("Not enough ex_storage space. " 674 "Increase EXSTORAGE_MAX"); 675 676 /* XXX doing this in here might be wrong */ 677 if (iomem == 1) { 678 /* we map an IO region */ 679 tag->pbs_offset = region.addr; 680 tag->pbs_base = 0; 681 tag->pbs_limit = region.size; 682 } else { 683 /* ... or a memory region */ 684 tag->pbs_offset = 0; 685 tag->pbs_base = region.addr; 686 tag->pbs_limit = region.size + region.addr; 687 } 688 689 error = bus_space_init(tag, name, ex_storage[exmap], 690 sizeof(ex_storage[exmap])); 691 exmap++; 692 if (error) 693 panic("ofwoea_bus_space_init: can't init tag %s", name); 694 for (i=0; i < nrofholes; i++) { 695 if (holes[i].type == RANGE_IO) { 696 error = extent_alloc_region(tag->pbs_extent, 697 holes[i].addr - tag->pbs_offset, 698 holes[i].size, EX_NOWAIT); 699 } else { 700 error = extent_alloc_region(tag->pbs_extent, 701 holes[i].addr, holes[i].size, EX_NOWAIT); 702 } 703 if (error) 704 panic("ofwoea_bus_space_init: can't block out" 705 " reserved space 0x%x-0x%x: error=%d", 706 holes[i].addr, holes[i].addr+holes[i].size, 707 error); 708 } 709 return error; 710 } 711 return -1; 712 } 713 714 void 715 ofwoea_bus_space_init(void) 716 { 717 int error; 718 719 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_IO, -1, 720 &genppc_isa_io_space_tag, "isa-ioport"); 721 if (error > 0) 722 panic("Could not map ISA IO"); 723 724 error = ofwoea_map_space(RANGE_TYPE_ISA, RANGE_MEM, -1, 725 &genppc_isa_mem_space_tag, "isa-iomem"); 726 if (error > 0) 727 panic("Could not map ISA MEM"); 728 } 729