xref: /netbsd/sys/arch/sparc64/sparc64/ofw_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $	*/
2 
3 /*
4  * Copyright (C) 1996 Wolfgang Solfrank.
5  * Copyright (C) 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <sys/param.h>
34 #include <sys/buf.h>
35 #include <sys/conf.h>
36 #include <sys/device.h>
37 #include <sys/disk.h>
38 #include <sys/disklabel.h>
39 #include <sys/fcntl.h>
40 #include <sys/ioctl.h>
41 #include <sys/malloc.h>
42 #include <sys/stat.h>
43 #include <sys/systm.h>
44 
45 #include <machine/openfirm.h>
46 
47 #if defined(FFS) && defined(CD9660)
48 #include <ufs/ffs/fs.h>
49 #endif
50 
51 /*
52  * Note that stdarg.h and the ANSI style va_start macro is used for both
53  * ANSI and traditional C compilers.
54  */
55 #include <machine/stdarg.h>
56 
57 #include <machine/sparc64.h>
58 
59 int vsprintf __P((char *, const char *, va_list));
60 
61 void dk_cleanup __P((void));
62 #if defined(FFS) && defined(CD9660)
63 static int dk_match_ffs __P((void));
64 #endif
65 
66 static u_int mmuh = -1, memh = -1;
67 
68 static u_int get_mmu_handle __P((void));
69 static u_int get_memory_handle __P((void));
70 
71 static u_int
72 get_mmu_handle()
73 {
74 	u_int chosen;
75 
76 	if ((chosen = OF_finddevice("/chosen")) == -1) {
77 		prom_printf("get_mmu_handle: cannot get /chosen\r\n");
78 		return -1;
79 	}
80 	if (OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) == -1) {
81 		prom_printf("get_mmu_handle: cannot get mmuh\r\n");
82 		return -1;
83 	}
84 	return mmuh;
85 }
86 
87 static u_int
88 get_memory_handle()
89 {
90 	u_int chosen;
91 
92 	if ((chosen = OF_finddevice("/chosen")) == -1) {
93 		prom_printf("get_mmu_handle: cannot get /chosen\r\n");
94 		return -1;
95 	}
96 	if (OF_getprop(chosen, "memory", &memh, sizeof(memh)) == -1) {
97 		prom_printf("get_memory_handle: cannot get memh\r\n");
98 		return -1;
99 	}
100 	return memh;
101 }
102 
103 
104 /*
105  * Point prom to our trap table.  This stops the prom from mapping us.
106  */
107 int
108 prom_set_trap_table(tba)
109 	vaddr_t tba;
110 {
111 	struct {
112 		cell_t name;
113 		cell_t nargs;
114 		cell_t nreturns;
115 		cell_t tba;
116 	} args;
117 
118 	args.name = ADR2CELL(&"SUNW,set-trap-table");
119 	args.nargs = 1;
120 	args.nreturns = 0;
121 	args.tba = ADR2CELL(tba);
122 	return openfirmware(&args);
123 }
124 
125 /*
126  * Have the prom convert from virtual to physical addresses.
127  *
128  * Only works while the prom is actively mapping us.
129  */
130 paddr_t
131 prom_vtop(vaddr)
132 	vaddr_t vaddr;
133 {
134 	struct {
135 		cell_t name;
136 		cell_t nargs;
137 		cell_t nreturns;
138 		cell_t method;
139 		cell_t ihandle;
140 		cell_t vaddr;
141 		cell_t status;
142 		cell_t retaddr;
143 		cell_t mode;
144 		cell_t phys_hi;
145 		cell_t phys_lo;
146 	} args;
147 
148 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
149 		prom_printf("prom_vtop: cannot get mmuh\r\n");
150 		return 0;
151 	}
152 	args.name = ADR2CELL(&"call-method");
153 	args.nargs = 3;
154 	args.nreturns = 5;
155 	args.method = ADR2CELL(&"translate");
156 	args.ihandle = HDL2CELL(mmuh);
157 	args.vaddr = ADR2CELL(vaddr);
158 	if(openfirmware(&args) == -1)
159 		return -1;
160 #if 0
161 	prom_printf("Called \"translate\", mmuh=%x, vaddr=%x, status=%x %x,\r\n retaddr=%x %x, mode=%x %x, phys_hi=%x %x, phys_lo=%x %x\r\n",
162 		    mmuh, vaddr, (int)(args.status>>32), (int)args.status, (int)(args.retaddr>>32), (int)args.retaddr,
163 		    (int)(args.mode>>32), (int)args.mode, (int)(args.phys_hi>>32), (int)args.phys_hi,
164 		    (int)(args.phys_lo>>32), (int)args.phys_lo);
165 #endif
166 	return (paddr_t)((((paddr_t)args.phys_hi)<<32)|(u_int32_t)args.phys_lo);
167 }
168 
169 /*
170  * Grab some address space from the prom
171  *
172  * Only works while the prom is actively mapping us.
173  */
174 vaddr_t
175 prom_claim_virt(vaddr, len)
176 	vaddr_t vaddr;
177 	int len;
178 {
179 	struct {
180 		cell_t name;
181 		cell_t nargs;
182 		cell_t nreturns;
183 		cell_t method;
184 		cell_t ihandle;
185 		cell_t align;
186 		cell_t len;
187 		cell_t vaddr;
188 		cell_t status;
189 		cell_t retaddr;
190 	} args;
191 
192 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
193 		prom_printf("prom_claim_virt: cannot get mmuh\r\n");
194 		return 0;
195 	}
196 	args.name = ADR2CELL(&"call-method");
197 	args.nargs = 5;
198 	args.nreturns = 2;
199 	args.method = ADR2CELL(&"claim");
200 	args.ihandle = HDL2CELL(mmuh);
201 	args.align = 0;
202 	args.len = len;
203 	args.vaddr = ADR2CELL(vaddr);
204 	if (openfirmware(&args) == -1)
205 		return -1;
206 	return (paddr_t)args.retaddr;
207 }
208 
209 /*
210  * Request some address space from the prom
211  *
212  * Only works while the prom is actively mapping us.
213  */
214 vaddr_t
215 prom_alloc_virt(len, align)
216 	int len;
217 	int align;
218 {
219 	static int retaddr;
220 	struct {
221 		cell_t name;
222 		cell_t nargs;
223 		cell_t nreturns;
224 		cell_t method;
225 		cell_t ihandle;
226 		cell_t align;
227 		cell_t len;
228 		cell_t status;
229 		cell_t retaddr;
230 	} args;
231 
232 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
233 		prom_printf("prom_alloc_virt: cannot get mmuh\r\n");
234 		return -1LL;
235 	}
236 	args.name = ADR2CELL(&"call-method");
237 	args.nargs = 4;
238 	args.nreturns = 2;
239 	args.method = ADR2CELL(&"claim");
240 	args.ihandle = HDL2CELL(mmuh);
241 	args.align = align;
242 	args.len = len;
243 	args.retaddr = ADR2CELL(&retaddr);
244 	if (openfirmware(&args) != 0)
245 		return -1;
246 	return retaddr; /* Kluge till we go 64-bit */
247 }
248 
249 /*
250  * Release some address space to the prom
251  *
252  * Only works while the prom is actively mapping us.
253  */
254 int
255 prom_free_virt(vaddr, len)
256 	vaddr_t vaddr;
257 	int len;
258 {
259 	struct {
260 		cell_t name;
261 		cell_t nargs;
262 		cell_t nreturns;
263 		cell_t method;
264 		cell_t ihandle;
265 		cell_t len;
266 		cell_t vaddr;
267 	} args;
268 
269 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
270 		prom_printf("prom_claim_virt: cannot get mmuh\r\n");
271 		return -1;
272 	}
273 	args.name = ADR2CELL(&"call-method");
274 	args.nargs = 4;
275 	args.nreturns = 0;
276 	args.method = ADR2CELL(&"release");
277 	args.ihandle = HDL2CELL(mmuh);
278 	args.vaddr = ADR2CELL(vaddr);
279 	args.len = len;
280 	return openfirmware(&args);
281 }
282 
283 
284 /*
285  * Unmap some address space
286  *
287  * Only works while the prom is actively mapping us.
288  */
289 int
290 prom_unmap_virt(vaddr, len)
291 	vaddr_t vaddr;
292 	int len;
293 {
294 	struct {
295 		cell_t name;
296 		cell_t nargs;
297 		cell_t nreturns;
298 		cell_t method;
299 		cell_t ihandle;
300 		cell_t len;
301 		cell_t vaddr;
302 	} args;
303 
304 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
305 		prom_printf("prom_claim_virt: cannot get mmuh\r\n");
306 		return -1;
307 	}
308 	args.name = ADR2CELL(&"call-method");
309 	args.nargs = 4;
310 	args.nreturns = 0;
311 	args.method = ADR2CELL(&"unmap");
312 	args.ihandle = HDL2CELL(mmuh);
313 	args.vaddr = ADR2CELL(vaddr);
314 	args.len = len;
315 	return openfirmware(&args);
316 }
317 
318 /*
319  * Have prom map in some memory
320  *
321  * Only works while the prom is actively mapping us.
322  */
323 int
324 prom_map_phys(paddr, size, vaddr, mode)
325 	paddr_t paddr;
326 	off_t size;
327 	vaddr_t vaddr;
328 	int mode;
329 {
330 	struct {
331 		cell_t name;
332 		cell_t nargs;
333 		cell_t nreturns;
334 		cell_t method;
335 		cell_t ihandle;
336 		cell_t mode;
337 		cell_t size;
338 		cell_t vaddr;
339 		cell_t phys_hi;
340 		cell_t phys_lo;
341 		cell_t status;
342 		cell_t retaddr;
343 	} args;
344 
345 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
346 		prom_printf("prom_map_phys: cannot get mmuh\r\n");
347 		return 0;
348 	}
349 	args.name = ADR2CELL(&"call-method");
350 	args.nargs = 7;
351 	args.nreturns = 1;
352 	args.method = ADR2CELL(&"map");
353 	args.ihandle = HDL2CELL(mmuh);
354 	args.mode = mode;
355 	args.size = size;
356 	args.vaddr = ADR2CELL(vaddr);
357 	args.phys_hi = HDL2CELL(paddr>>32);
358 	args.phys_lo = HDL2CELL(paddr);
359 
360 	if (openfirmware(&args) == -1)
361 		return -1;
362 	if (args.status)
363 		return -1;
364 	return args.retaddr;
365 }
366 
367 
368 /*
369  * Request some RAM from the prom
370  *
371  * Only works while the prom is actively mapping us.
372  */
373 paddr_t
374 prom_alloc_phys(len, align)
375 	int len;
376 	int align;
377 {
378 	struct {
379 		cell_t name;
380 		cell_t nargs;
381 		cell_t nreturns;
382 		cell_t method;
383 		cell_t ihandle;
384 		cell_t align;
385 		cell_t len;
386 		cell_t status;
387 		cell_t phys_hi;
388 		cell_t phys_lo;
389 	} args;
390 
391 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
392 		prom_printf("prom_alloc_phys: cannot get memh\r\n");
393 		return -1;
394 	}
395 	args.name = ADR2CELL(&"call-method");
396 	args.nargs = 4;
397 	args.nreturns = 3;
398 	args.method = ADR2CELL(&"claim");
399 	args.ihandle = HDL2CELL(memh);
400 	args.align = align;
401 	args.len = len;
402 	if (openfirmware(&args) != 0)
403 		return -1;
404 	return (paddr_t)((((paddr_t)args.phys_hi)<<32)|(u_int32_t)args.phys_lo);
405 }
406 
407 /*
408  * Request some specific RAM from the prom
409  *
410  * Only works while the prom is actively mapping us.
411  */
412 paddr_t
413 prom_claim_phys(phys, len)
414 	paddr_t phys;
415 	int len;
416 {
417 	struct {
418 		cell_t name;
419 		cell_t nargs;
420 		cell_t nreturns;
421 		cell_t method;
422 		cell_t ihandle;
423 		cell_t align;
424 		cell_t len;
425 		cell_t phys_hi;
426 		cell_t phys_lo;
427 		cell_t status;
428 		cell_t rphys_hi;
429 		cell_t rphys_lo;
430 	} args;
431 
432 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
433 		prom_printf("prom_alloc_phys: cannot get memh\r\n");
434 		return -1;
435 	}
436 	args.name = ADR2CELL(&"call-method");
437 	args.nargs = 6;
438 	args.nreturns = 3;
439 	args.method = ADR2CELL(&"claim");
440 	args.ihandle = HDL2CELL(memh);
441 	args.align = 0;
442 	args.len = len;
443 	args.phys_hi = HDL2CELL(phys>>32);
444 	args.phys_lo = HDL2CELL(phys);
445 	if (openfirmware(&args) != 0)
446 		return -1;
447 	return (paddr_t)((((paddr_t)args.rphys_hi)<<32)|(u_int32_t)args.rphys_lo);
448 }
449 
450 /*
451  * Free some RAM to prom
452  *
453  * Only works while the prom is actively mapping us.
454  */
455 int
456 prom_free_phys(phys, len)
457 	paddr_t phys;
458 	int len;
459 {
460 	struct {
461 		cell_t name;
462 		cell_t nargs;
463 		cell_t nreturns;
464 		cell_t method;
465 		cell_t ihandle;
466 		cell_t len;
467 		cell_t phys_hi;
468 		cell_t phys_lo;
469 	} args;
470 
471 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
472 		prom_printf("prom_free_phys: cannot get memh\r\n");
473 		return -1;
474 	}
475 	args.name = ADR2CELL(&"call-method");
476 	args.nargs = 5;
477 	args.nreturns = 0;
478 	args.method = ADR2CELL(&"release");
479 	args.ihandle = HDL2CELL(memh);
480 	args.len = len;
481 	args.phys_hi = HDL2CELL(phys>>32);
482 	args.phys_lo = HDL2CELL(phys);
483 	return openfirmware(&args);
484 }
485 
486 /*
487  * Get the msgbuf from the prom.  Only works once.
488  *
489  * Only works while the prom is actively mapping us.
490  */
491 paddr_t
492 prom_get_msgbuf(len, align)
493 	int len;
494 	int align;
495 {
496 	struct {
497 		cell_t name;
498 		cell_t nargs;
499 		cell_t nreturns;
500 		cell_t method;
501 		cell_t ihandle;
502 		cell_t align;
503 		cell_t len;
504 		cell_t id;
505 		cell_t status;
506 		cell_t phys_hi;
507 		cell_t phys_lo;
508 	} args;
509 	paddr_t addr;
510 	int rooth;
511 	int is_e250 = 1;
512 
513 	/* E250s tend to have buggy PROMs that break on test-method */
514 	if ((rooth = OF_finddevice("/")) != -1) {
515 		char name[80];
516 
517 		if ((OF_getprop(rooth, "name", &name, sizeof(name))) != -1) {
518 			if (strcmp(name, "SUNW,Ultra-250"))
519 				is_e250 = 0;
520 		} else prom_printf("prom_get_msgbuf: cannot get \"name\"\r\n");
521 	} else prom_printf("prom_get_msgbuf: cannot open root device \r\n");
522 
523 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
524 		prom_printf("prom_get_msgbuf: cannot get memh\r\n");
525 		return -1;
526 	}
527 	if (is_e250) {
528 		prom_printf("prom_get_msgbuf: Cannot recover msgbuf on E250\r\n");
529 	} else if (OF_test("test-method") == 0) {
530 		if (OF_test_method(memh, "SUNW,retain") != 0) {
531 			args.name = ADR2CELL(&"call-method");
532 			args.nargs = 5;
533 			args.nreturns = 3;
534 			args.method = ADR2CELL(&"SUNW,retain");
535 			args.id = ADR2CELL(&"msgbuf");
536 			args.ihandle = HDL2CELL(memh);
537 			args.len = len;
538 			args.align = align;
539 			args.status = -1;
540 			if (openfirmware(&args) == 0 && args.status == 0) {
541 				return (((paddr_t)args.phys_hi<<32)|
542 					(u_int32_t)args.phys_lo);
543 			} else prom_printf("prom_get_msgbuf: SUNW,retain failed\r\n");
544 		} else prom_printf("prom_get_msgbuf: test-method failed\r\n");
545 	} else prom_printf("prom_get_msgbuf: test failed\r\n");
546 	/* Allocate random memory -- page zero avail?*/
547 	addr = prom_claim_phys(0x000, len);
548 	prom_printf("prom_get_msgbuf: allocated new buf at %08x\r\n", (int)addr);
549 	if (addr == -1) {
550 		prom_printf("prom_get_msgbuf: cannot get allocate physmem\r\n");
551 		return -1;
552 	}
553 	prom_printf("prom_get_msgbuf: claiming new buf at %08x\r\n", (int)addr);
554 	{ int i; for (i=0; i<200000000; i++); }
555 	return addr; /* Kluge till we go 64-bit */
556 }
557 
558 /*
559  * Low-level prom I/O routines.
560  */
561 
562 static u_int stdin = NULL;
563 static u_int stdout = NULL;
564 
565 int
566 OF_stdin()
567 {
568 	u_int chosen;
569 
570 	if (stdin != NULL)
571 		return stdin;
572 
573 	chosen = OF_finddevice("/chosen");
574 	OF_getprop(chosen, "stdin", &stdin, sizeof(stdin));
575 	return stdin;
576 }
577 
578 int
579 OF_stdout()
580 {
581 	u_int chosen;
582 
583 	if (stdout != NULL)
584 		return stdout;
585 
586 	chosen = OF_finddevice("/chosen");
587 	OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
588 	return stdout;
589 }
590 
591 
592 /*
593  * print debug info to prom.
594  * This is not safe, but then what do you expect?
595  */
596 void
597 #ifdef __STDC__
598 prom_printf(const char *fmt, ...)
599 #else
600 prom_printf(fmt, va_alist)
601 	char *fmt;
602 	va_dcl
603 #endif
604 {
605 	int len;
606 	static char buf[256];
607 	va_list ap;
608 
609 	va_start(ap, fmt);
610 	len = vsprintf(buf, fmt, ap);
611 	va_end(ap);
612 
613 	OF_write(OF_stdout(), buf, len);
614 }
615 
616 #ifdef DEBUG
617 int ofmapintrdebug = 0;
618 #define	DPRINTF(x)	if (ofmapintrdebug) printf x
619 #else
620 #define DPRINTF(x)
621 #endif
622 
623 
624 /*
625  * Recursively hunt for a property.
626  */
627 int
628 OF_searchprop(int node, char *prop, void *buf, int buflen)
629 {
630 	int len;
631 
632 	for( ; node; node = OF_parent(node)) {
633 		len = OF_getprop(node, prop, buf, buflen);
634 		if (len >= 0)
635 			return (len);
636 	}
637 	/* Error -- not found */
638 	return (-1);
639 }
640 
641 
642 /*
643  * Compare a sequence of cells with a mask,
644  *  return 1 if they match and 0 if they don't.
645  */
646 static int compare_cells (int *cell1, int *cell2, int *mask, int ncells);
647 static int
648 compare_cells(int *cell1, int *cell2, int *mask, int ncells)
649 {
650 	int i;
651 
652 	for (i=0; i<ncells; i++) {
653 		DPRINTF(("src %x ^ dest %x -> %x & mask %x -> %x\n",
654 			cell1[i], cell2[i], (cell1[i] ^ cell2[i]),
655 			mask[i], ((cell1[i] ^ cell2[i]) & mask[i])));
656 		if (((cell1[i] ^ cell2[i]) & mask[i]) != 0)
657 			return (0);
658 	}
659 	return (1);
660 }
661 
662 /*
663  * Follow the OFW algorithm and return an interrupt specifier.
664  *
665  * Pass in the interrupt specifier you want mapped and the node
666  * you want it mapped from.  validlen is the number of cells in
667  * the interrupt specifier, and buflen is the number of cells in
668  * the buffer.
669  */
670 int
671 OF_mapintr(int node, int *interrupt, int validlen, int buflen)
672 {
673 	int i, len;
674 	int address_cells, size_cells, interrupt_cells, interrupt_map_len;
675 	int interrupt_map[100];
676 	int interrupt_map_mask[10];
677 	int reg[10];
678 
679 	/*
680 	 * If there is no interrupt map in the bus node, we
681 	 * need to convert the slot address to its parent
682 	 * bus format, and hunt up the parent bus to see if
683 	 * we need to remap.
684 	 *
685 	 * The specification for interrupt mapping is borken.
686 	 * You are supposed to query the interrupt parent in
687 	 * the interrupt-map specification to determine the
688 	 * number of address and interrupt cells, but we need
689 	 * to know how many address and interrupt cells to skip
690 	 * to find the phandle...
691 	 *
692 	 */
693 	if ((len = OF_getprop(node, "reg", &reg, sizeof(reg))) <= 0) {
694 		printf("OF_mapintr: no reg property?\n");
695 		return (-1);
696 	}
697 
698 	for (; node; node = OF_parent(node)) {
699 #ifdef DEBUG
700 		char name[40];
701 
702 		if (ofmapintrdebug) {
703 			OF_getprop(node, "name", &name, sizeof(name));
704 			printf("Node %s\n", name);
705 		}
706 #endif
707 
708 		if ((interrupt_map_len = OF_getprop(node,
709 			"interrupt-map", &interrupt_map,
710 			sizeof(interrupt_map))) <= 0) {
711 			/* Get reg for next level compare. */
712 			OF_getprop(node, "reg", &reg, sizeof(reg));
713 			continue;
714 		}
715 		/* Convert from bytes to cells. */
716 		interrupt_map_len = interrupt_map_len/sizeof(int);
717 		if ((len = (OF_searchprop(node, "#address-cells", &address_cells,
718 			sizeof(address_cells)))) <= 0) {
719 			/* How should I know. */
720 			address_cells = 2;
721 		}
722 		DPRINTF(("#address-cells = %d len %d", address_cells, len));
723 		if ((len = OF_searchprop(node, "#size-cells", &size_cells,
724 			sizeof(size_cells))) <= 0) {
725 			/* How should I know. */
726 			size_cells = 2;
727 		}
728 		DPRINTF(("#size-cells = %d len %d", size_cells, len));
729 		if ((len = OF_getprop(node, "#interrupt-cells", &interrupt_cells,
730 			sizeof(interrupt_cells))) <= 0) {
731 			/* How should I know. */
732 			interrupt_cells = 1;
733 		}
734 		DPRINTF(("#interrupt-cells = %d, len %d\n", interrupt_cells,
735 			len));
736 		if ((len = OF_getprop(node, "interrupt-map-mask", &interrupt_map_mask,
737 			sizeof(interrupt_map_mask))) <= 0) {
738 			/* Create a mask that masks nothing. */
739 			for (i = 0; i<(address_cells + interrupt_cells); i++)
740 				interrupt_map_mask[i] = -1;
741 		}
742 #ifdef DEBUG
743 		DPRINTF(("interrupt-map-mask len %d = ", len));
744 		for (i=0; i<(address_cells + interrupt_cells); i++)
745 			DPRINTF(("%x.", interrupt_map_mask[i]));
746 		DPRINTF(("reg = "));
747 		for (i=0; i<(address_cells); i++)
748 			DPRINTF(("%x.", reg[i]));
749 		DPRINTF(("interrupts = "));
750 		for (i=0; i<(interrupt_cells); i++)
751 			DPRINTF(("%x.", interrupt[i]));
752 
753 #endif
754 
755 		/* finally we can attempt the compare */
756 		i=0;
757 		while ( i < interrupt_map_len ) {
758 			int pintr_cells;
759 			int *imap = &interrupt_map[i];
760 			int *parent = &imap[address_cells + interrupt_cells];
761 
762 #ifdef DEBUG
763 			DPRINTF(("\ninterrupt-map addr "));
764 			for (len=0; len<address_cells; len++)
765 				DPRINTF(("%x.", imap[len]));
766 			DPRINTF((" intr "));
767 			for (; len<(address_cells+interrupt_cells); len++)
768 				DPRINTF(("%x.", imap[len]));
769 			DPRINTF(("\nnode %x vs parent %x\n",
770 				imap[len], *parent));
771 #endif
772 
773 			/* Find out how many cells we'll need to skip. */
774 			if ((len = OF_searchprop(*parent, "#interrupt-cells",
775 				&pintr_cells, sizeof(pintr_cells))) < 0) {
776 				pintr_cells = interrupt_cells;
777 			}
778 			DPRINTF(("pintr_cells = %d len %d\n", pintr_cells, len));
779 
780 			if (compare_cells(imap, reg,
781 				interrupt_map_mask, address_cells) &&
782 				compare_cells(&imap[address_cells],
783 					interrupt,
784 					&interrupt_map_mask[address_cells],
785 					interrupt_cells))
786 			{
787 				/* Bingo! */
788 				if (buflen < pintr_cells) {
789 					/* Error -- ran out of storage. */
790 					return (-1);
791 				}
792 				parent ++;
793 #ifdef DEBUG
794 				DPRINTF(("Match! using "));
795 				for (len=0; len<pintr_cells; len++)
796 					DPRINTF(("%x.", parent[len]));
797 #endif
798 				for (i=0; i<pintr_cells; i++)
799 					interrupt[i] = parent[i];
800 				validlen = pintr_cells;
801 				break;
802 			}
803 			/* Move on to the next interrupt_map entry. */
804 #ifdef DEBUG
805 			DPRINTF(("skip %d cells:",
806 				address_cells + interrupt_cells +
807 				pintr_cells + 1));
808 			for (len=0; len<(address_cells +
809 				interrupt_cells + pintr_cells + 1); len++)
810 				DPRINTF(("%x.", imap[len]));
811 #endif
812 			i += address_cells + interrupt_cells + pintr_cells + 1;
813 		}
814 
815 		/* Get reg for the next level search. */
816 		if ((len = OF_getprop(node, "reg", &reg, sizeof(reg))) <= 0) {
817 			DPRINTF(("OF_mapintr: no reg property?\n"));
818 			continue;
819 		}
820 		DPRINTF(("reg len %d\n", len));
821 
822 	}
823 	return (validlen);
824 }
825