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