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(&region, 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(&region, &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