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
ofwoea_initppc(u_int startkernel,u_int endkernel,char * args)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
get_timebase_frequency(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
init_decrementer(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
restore_ofmap(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
find_ranges(int base,rangemap_t * regions,int * cur,int type)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
find_lowest_range(rangemap_t * ranges,int nrof,int type)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
ofwoea_map_space(int rangetype,int iomem,int node,struct powerpc_bus_space * tag,const char * name)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
ofwoea_bus_space_init(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