1 /*
2 * Procedures for interfacing to the Open Firmware PROM on
3 * Power Macintosh computers.
4 *
5 * In particular, we are interested in the device tree
6 * and in using some of its services (exit, write to stdout).
7 *
8 * Paul Mackerras August 1996.
9 * Copyright (C) 1996 Paul Mackerras.
10 */
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/string.h>
14 #include <linux/init.h>
15 #include <linux/version.h>
16 #include <linux/threads.h>
17 #include <linux/spinlock.h>
18 #include <linux/pci.h>
19 #include <linux/slab.h>
20
21 #include <asm/sections.h>
22 #include <asm/prom.h>
23 #include <asm/page.h>
24 #include <asm/processor.h>
25 #include <asm/irq.h>
26 #include <asm/open_pic.h>
27 #include <asm/system.h>
28 #include <asm/btext.h>
29 #include <asm/pci-bridge.h>
30
31 struct pci_address {
32 unsigned a_hi;
33 unsigned a_mid;
34 unsigned a_lo;
35 };
36
37 struct pci_reg_property {
38 struct pci_address addr;
39 unsigned size_hi;
40 unsigned size_lo;
41 };
42
43 struct isa_reg_property {
44 unsigned space;
45 unsigned address;
46 unsigned size;
47 };
48
49 typedef unsigned long interpret_func(struct device_node *, unsigned long,
50 int, int);
51 static interpret_func interpret_pci_props;
52 static interpret_func interpret_dbdma_props;
53 static interpret_func interpret_isa_props;
54 static interpret_func interpret_macio_props;
55 static interpret_func interpret_root_props;
56
57 extern char *klimit;
58
59 /* Set for a newworld or CHRP machine */
60 int use_of_interrupt_tree;
61 struct device_node *dflt_interrupt_controller;
62 int num_interrupt_controllers;
63
64 int pmac_newworld;
65
66 extern unsigned int rtas_entry; /* physical pointer */
67
68 extern struct device_node *allnodes;
69
70 static unsigned long finish_node(struct device_node *, unsigned long,
71 interpret_func *, int, int);
72 static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
73
74 extern void enter_rtas(void *);
75 void phys_call_rtas(int, int, int, ...);
76
77 extern char cmd_line[512]; /* XXX */
78 extern boot_infos_t *boot_infos;
79 unsigned long dev_tree_size;
80
81 void __openfirmware
phys_call_rtas(int service,int nargs,int nret,...)82 phys_call_rtas(int service, int nargs, int nret, ...)
83 {
84 va_list list;
85 union {
86 unsigned long words[16];
87 double align;
88 } u;
89 void (*rtas)(void *, unsigned long);
90 int i;
91
92 u.words[0] = service;
93 u.words[1] = nargs;
94 u.words[2] = nret;
95 va_start(list, nret);
96 for (i = 0; i < nargs; ++i)
97 u.words[i+3] = va_arg(list, unsigned long);
98 va_end(list);
99
100 rtas = (void (*)(void *, unsigned long)) rtas_entry;
101 rtas(&u, rtas_data);
102 }
103
104 /*
105 * finish_device_tree is called once things are running normally
106 * (i.e. with text and data mapped to the address they were linked at).
107 * It traverses the device tree and fills in the name, type,
108 * {n_}addrs and {n_}intrs fields of each node.
109 */
110 void __init
finish_device_tree(void)111 finish_device_tree(void)
112 {
113 unsigned long mem = (unsigned long) klimit;
114 struct device_node *np;
115
116 /* All newworld pmac machines and CHRPs now use the interrupt tree */
117 for (np = allnodes; np != NULL; np = np->allnext) {
118 if (get_property(np, "interrupt-parent", 0)) {
119 use_of_interrupt_tree = 1;
120 break;
121 }
122 }
123 if (_machine == _MACH_Pmac && use_of_interrupt_tree)
124 pmac_newworld = 1;
125
126 #ifdef CONFIG_BOOTX_TEXT
127 if (boot_infos && pmac_newworld) {
128 prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
129 prom_print(" You should use an Open Firmware bootloader\n");
130 }
131 #endif /* CONFIG_BOOTX_TEXT */
132
133 if (use_of_interrupt_tree) {
134 /*
135 * We want to find out here how many interrupt-controller
136 * nodes there are, and if we are booted from BootX,
137 * we need a pointer to the first (and hopefully only)
138 * such node. But we can't use find_devices here since
139 * np->name has not been set yet. -- paulus
140 */
141 int n = 0;
142 char *name, *ic;
143 int iclen;
144
145 for (np = allnodes; np != NULL; np = np->allnext) {
146 ic = get_property(np, "interrupt-controller", &iclen);
147 name = get_property(np, "name", NULL);
148 /* checking iclen makes sure we don't get a false
149 match on /chosen.interrupt_controller */
150 if ((name != NULL
151 && strcmp(name, "interrupt-controller") == 0)
152 || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
153 if (n == 0)
154 dflt_interrupt_controller = np;
155 ++n;
156 }
157 }
158 num_interrupt_controllers = n;
159 }
160
161 mem = finish_node(allnodes, mem, NULL, 1, 1);
162 dev_tree_size = mem - (unsigned long) allnodes;
163 klimit = (char *) mem;
164 }
165
166 static unsigned long __init
finish_node(struct device_node * np,unsigned long mem_start,interpret_func * ifunc,int naddrc,int nsizec)167 finish_node(struct device_node *np, unsigned long mem_start,
168 interpret_func *ifunc, int naddrc, int nsizec)
169 {
170 struct device_node *child;
171 int *ip;
172
173 np->name = get_property(np, "name", 0);
174 np->type = get_property(np, "device_type", 0);
175
176 if (!np->name)
177 np->name = "<NULL>";
178 if (!np->type)
179 np->type = "<NULL>";
180
181 /* get the device addresses and interrupts */
182 if (ifunc != NULL)
183 mem_start = ifunc(np, mem_start, naddrc, nsizec);
184
185 if (use_of_interrupt_tree)
186 mem_start = finish_node_interrupts(np, mem_start);
187
188 /* Look for #address-cells and #size-cells properties. */
189 ip = (int *) get_property(np, "#address-cells", 0);
190 if (ip != NULL)
191 naddrc = *ip;
192 ip = (int *) get_property(np, "#size-cells", 0);
193 if (ip != NULL)
194 nsizec = *ip;
195
196 if (np->parent == NULL)
197 ifunc = interpret_root_props;
198 else if (np->type == 0)
199 ifunc = NULL;
200 else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
201 ifunc = interpret_pci_props;
202 else if (!strcmp(np->type, "dbdma"))
203 ifunc = interpret_dbdma_props;
204 else if (!strcmp(np->type, "mac-io")
205 || ifunc == interpret_macio_props)
206 ifunc = interpret_macio_props;
207 else if (!strcmp(np->type, "isa"))
208 ifunc = interpret_isa_props;
209 else if (!strcmp(np->name, "uni-n"))
210 ifunc = interpret_root_props;
211 else if (!((ifunc == interpret_dbdma_props
212 || ifunc == interpret_macio_props)
213 && (!strcmp(np->type, "escc")
214 || !strcmp(np->type, "media-bay"))))
215 ifunc = NULL;
216
217 /* if we were booted from BootX, convert the full name */
218 if (boot_infos
219 && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
220 if (np->full_name[19] == 0) {
221 strcpy(np->full_name, "/");
222 } else if (np->full_name[19] == ':') {
223 char *p = np->full_name + 19;
224 np->full_name = p;
225 for (; *p; ++p)
226 if (*p == ':')
227 *p = '/';
228 }
229 }
230
231 for (child = np->child; child != NULL; child = child->sibling)
232 mem_start = finish_node(child, mem_start, ifunc,
233 naddrc, nsizec);
234
235 return mem_start;
236 }
237
238 /*
239 * Find the interrupt parent of a node.
240 */
241 static struct device_node * __init
intr_parent(struct device_node * p)242 intr_parent(struct device_node *p)
243 {
244 phandle *parp;
245
246 parp = (phandle *) get_property(p, "interrupt-parent", NULL);
247 if (parp == NULL)
248 return p->parent;
249 p = find_phandle(*parp);
250 if (p != NULL)
251 return p;
252 /*
253 * On a powermac booted with BootX, we don't get to know the
254 * phandles for any nodes, so find_phandle will return NULL.
255 * Fortunately these machines only have one interrupt controller
256 * so there isn't in fact any ambiguity. -- paulus
257 */
258 if (num_interrupt_controllers == 1)
259 p = dflt_interrupt_controller;
260 return p;
261 }
262
263 /*
264 * Find out the size of each entry of the interrupts property
265 * for a node.
266 */
267 static int __init
prom_n_intr_cells(struct device_node * np)268 prom_n_intr_cells(struct device_node *np)
269 {
270 struct device_node *p;
271 unsigned int *icp;
272
273 for (p = np; (p = intr_parent(p)) != NULL; ) {
274 icp = (unsigned int *)
275 get_property(p, "#interrupt-cells", NULL);
276 if (icp != NULL)
277 return *icp;
278 if (get_property(p, "interrupt-controller", NULL) != NULL
279 || get_property(p, "interrupt-map", NULL) != NULL) {
280 printk("oops, node %s doesn't have #interrupt-cells\n",
281 p->full_name);
282 return 1;
283 }
284 }
285 printk("prom_n_intr_cells failed for %s\n", np->full_name);
286 return 1;
287 }
288
289 /*
290 * Map an interrupt from a device up to the platform interrupt
291 * descriptor.
292 */
293 static int __init
map_interrupt(unsigned int ** irq,struct device_node ** ictrler,struct device_node * np,unsigned int * ints,int nintrc)294 map_interrupt(unsigned int **irq, struct device_node **ictrler,
295 struct device_node *np, unsigned int *ints, int nintrc)
296 {
297 struct device_node *p, *ipar;
298 unsigned int *imap, *imask, *ip;
299 int i, imaplen, match;
300 int newintrc, newaddrc;
301 unsigned int *reg;
302 int naddrc;
303
304 reg = (unsigned int *) get_property(np, "reg", NULL);
305 naddrc = prom_n_addr_cells(np);
306 p = intr_parent(np);
307 while (p != NULL) {
308 if (get_property(p, "interrupt-controller", NULL) != NULL)
309 /* this node is an interrupt controller, stop here */
310 break;
311 imap = (unsigned int *)
312 get_property(p, "interrupt-map", &imaplen);
313 if (imap == NULL) {
314 p = intr_parent(p);
315 continue;
316 }
317 imask = (unsigned int *)
318 get_property(p, "interrupt-map-mask", NULL);
319 if (imask == NULL) {
320 printk("oops, %s has interrupt-map but no mask\n",
321 p->full_name);
322 return 0;
323 }
324 imaplen /= sizeof(unsigned int);
325 match = 0;
326 ipar = NULL;
327 while (imaplen > 0 && !match) {
328 /* check the child-interrupt field */
329 match = 1;
330 for (i = 0; i < naddrc && match; ++i)
331 match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
332 for (; i < naddrc + nintrc && match; ++i)
333 match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
334 imap += naddrc + nintrc;
335 imaplen -= naddrc + nintrc;
336 /* grab the interrupt parent */
337 ipar = find_phandle((phandle) *imap++);
338 --imaplen;
339 if (ipar == NULL && num_interrupt_controllers == 1)
340 /* cope with BootX not giving us phandles */
341 ipar = dflt_interrupt_controller;
342 if (ipar == NULL) {
343 printk("oops, no int parent %x in map of %s\n",
344 imap[-1], p->full_name);
345 return 0;
346 }
347 /* find the parent's # addr and intr cells */
348 ip = (unsigned int *)
349 get_property(ipar, "#interrupt-cells", NULL);
350 if (ip == NULL) {
351 printk("oops, no #interrupt-cells on %s\n",
352 ipar->full_name);
353 return 0;
354 }
355 newintrc = *ip;
356 ip = (unsigned int *)
357 get_property(ipar, "#address-cells", NULL);
358 newaddrc = (ip == NULL)? 0: *ip;
359 imap += newaddrc + newintrc;
360 imaplen -= newaddrc + newintrc;
361 }
362 if (imaplen < 0) {
363 printk("oops, error decoding int-map on %s, len=%d\n",
364 p->full_name, imaplen);
365 return 0;
366 }
367 if (!match) {
368 printk("oops, no match in %s int-map for %s\n",
369 p->full_name, np->full_name);
370 return 0;
371 }
372 p = ipar;
373 naddrc = newaddrc;
374 nintrc = newintrc;
375 ints = imap - nintrc;
376 reg = ints - naddrc;
377 }
378 if (p == NULL)
379 printk("hmmm, int tree for %s doesn't have ctrler\n",
380 np->full_name);
381 *irq = ints;
382 *ictrler = p;
383 return nintrc;
384 }
385
386 /*
387 * New version of finish_node_interrupts.
388 */
389 static unsigned long __init
finish_node_interrupts(struct device_node * np,unsigned long mem_start)390 finish_node_interrupts(struct device_node *np, unsigned long mem_start)
391 {
392 unsigned int *ints;
393 int intlen, intrcells;
394 int i, j, n, offset;
395 unsigned int *irq;
396 struct device_node *ic;
397
398 ints = (unsigned int *) get_property(np, "interrupts", &intlen);
399 if (ints == NULL)
400 return mem_start;
401 intrcells = prom_n_intr_cells(np);
402 intlen /= intrcells * sizeof(unsigned int);
403 np->n_intrs = intlen;
404 np->intrs = (struct interrupt_info *) mem_start;
405 mem_start += intlen * sizeof(struct interrupt_info);
406
407 for (i = 0; i < intlen; ++i) {
408 np->intrs[i].line = 0;
409 np->intrs[i].sense = 1;
410 n = map_interrupt(&irq, &ic, np, ints, intrcells);
411 if (n <= 0)
412 continue;
413 offset = 0;
414 /*
415 * On a CHRP we have an 8259 which is subordinate to
416 * the openpic in the interrupt tree, but we want the
417 * openpic's interrupt numbers offsetted, not the 8259's.
418 * So we apply the offset if the controller is at the
419 * root of the interrupt tree, i.e. has no interrupt-parent.
420 * This doesn't cope with the general case of multiple
421 * cascaded interrupt controllers, but then neither will
422 * irq.c at the moment either. -- paulus
423 */
424 if (num_interrupt_controllers > 1 && ic != NULL
425 && get_property(ic, "interrupt-parent", NULL) == NULL)
426 offset = 16;
427 np->intrs[i].line = irq[0] + offset;
428 if (n > 1)
429 np->intrs[i].sense = irq[1];
430 if (n > 2) {
431 printk("hmmm, got %d intr cells for %s:", n,
432 np->full_name);
433 for (j = 0; j < n; ++j)
434 printk(" %d", irq[j]);
435 printk("\n");
436 }
437 ints += intrcells;
438 }
439
440 return mem_start;
441 }
442
443 /*
444 * When BootX makes a copy of the device tree from the MacOS
445 * Name Registry, it is in the format we use but all of the pointers
446 * are offsets from the start of the tree.
447 * This procedure updates the pointers.
448 */
449 void __init
relocate_nodes(void)450 relocate_nodes(void)
451 {
452 unsigned long base;
453 struct device_node *np;
454 struct property *pp;
455
456 #define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)
457
458 base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
459 allnodes = (struct device_node *)(base + 4);
460 for (np = allnodes; np != 0; np = np->allnext) {
461 ADDBASE(np->full_name);
462 ADDBASE(np->properties);
463 ADDBASE(np->parent);
464 ADDBASE(np->child);
465 ADDBASE(np->sibling);
466 ADDBASE(np->allnext);
467 for (pp = np->properties; pp != 0; pp = pp->next) {
468 ADDBASE(pp->name);
469 ADDBASE(pp->value);
470 ADDBASE(pp->next);
471 }
472 }
473 }
474
475 int
prom_n_addr_cells(struct device_node * np)476 prom_n_addr_cells(struct device_node* np)
477 {
478 int* ip;
479 do {
480 if (np->parent)
481 np = np->parent;
482 ip = (int *) get_property(np, "#address-cells", 0);
483 if (ip != NULL)
484 return *ip;
485 } while (np->parent);
486 /* No #address-cells property for the root node, default to 1 */
487 return 1;
488 }
489
490 int
prom_n_size_cells(struct device_node * np)491 prom_n_size_cells(struct device_node* np)
492 {
493 int* ip;
494 do {
495 if (np->parent)
496 np = np->parent;
497 ip = (int *) get_property(np, "#size-cells", 0);
498 if (ip != NULL)
499 return *ip;
500 } while (np->parent);
501 /* No #size-cells property for the root node, default to 1 */
502 return 1;
503 }
504
505 static unsigned long __init
map_addr(struct device_node * np,unsigned long space,unsigned long addr)506 map_addr(struct device_node *np, unsigned long space, unsigned long addr)
507 {
508 int na;
509 unsigned int *ranges;
510 int rlen = 0;
511 unsigned int type;
512
513 type = (space >> 24) & 3;
514 if (type == 0)
515 return addr;
516
517 while ((np = np->parent) != NULL) {
518 if (strcmp(np->type, "pci") != 0)
519 continue;
520 /* PCI bridge: map the address through the ranges property */
521 na = prom_n_addr_cells(np);
522 ranges = (unsigned int *) get_property(np, "ranges", &rlen);
523 while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
524 if (((ranges[0] >> 24) & 3) == type
525 && ranges[2] <= addr
526 && addr - ranges[2] < ranges[na+4]) {
527 /* ok, this matches, translate it */
528 addr += ranges[na+2] - ranges[2];
529 break;
530 }
531 ranges += na + 5;
532 }
533 }
534 return addr;
535 }
536
537 static unsigned long __init
interpret_pci_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)538 interpret_pci_props(struct device_node *np, unsigned long mem_start,
539 int naddrc, int nsizec)
540 {
541 struct address_range *adr;
542 struct pci_reg_property *pci_addrs;
543 int i, l, *ip;
544
545 pci_addrs = (struct pci_reg_property *)
546 get_property(np, "assigned-addresses", &l);
547 if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
548 i = 0;
549 adr = (struct address_range *) mem_start;
550 while ((l -= sizeof(struct pci_reg_property)) >= 0) {
551 adr[i].space = pci_addrs[i].addr.a_hi;
552 adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
553 pci_addrs[i].addr.a_lo);
554 adr[i].size = pci_addrs[i].size_lo;
555 ++i;
556 }
557 np->addrs = adr;
558 np->n_addrs = i;
559 mem_start += i * sizeof(struct address_range);
560 }
561
562 if (use_of_interrupt_tree)
563 return mem_start;
564
565 ip = (int *) get_property(np, "AAPL,interrupts", &l);
566 if (ip == 0 && np->parent)
567 ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
568 if (ip == 0)
569 ip = (int *) get_property(np, "interrupts", &l);
570 if (ip != 0) {
571 np->intrs = (struct interrupt_info *) mem_start;
572 np->n_intrs = l / sizeof(int);
573 mem_start += np->n_intrs * sizeof(struct interrupt_info);
574 for (i = 0; i < np->n_intrs; ++i) {
575 np->intrs[i].line = *ip++;
576 np->intrs[i].sense = 1;
577 }
578 }
579
580 return mem_start;
581 }
582
583 static unsigned long __init
interpret_dbdma_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)584 interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
585 int naddrc, int nsizec)
586 {
587 struct reg_property *rp;
588 struct address_range *adr;
589 unsigned long base_address;
590 int i, l, *ip;
591 struct device_node *db;
592
593 base_address = 0;
594 for (db = np->parent; db != NULL; db = db->parent) {
595 if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
596 base_address = db->addrs[0].address;
597 break;
598 }
599 }
600
601 rp = (struct reg_property *) get_property(np, "reg", &l);
602 if (rp != 0 && l >= sizeof(struct reg_property)) {
603 i = 0;
604 adr = (struct address_range *) mem_start;
605 while ((l -= sizeof(struct reg_property)) >= 0) {
606 adr[i].space = 2;
607 adr[i].address = rp[i].address + base_address;
608 adr[i].size = rp[i].size;
609 ++i;
610 }
611 np->addrs = adr;
612 np->n_addrs = i;
613 mem_start += i * sizeof(struct address_range);
614 }
615
616 if (use_of_interrupt_tree)
617 return mem_start;
618
619 ip = (int *) get_property(np, "AAPL,interrupts", &l);
620 if (ip == 0)
621 ip = (int *) get_property(np, "interrupts", &l);
622 if (ip != 0) {
623 np->intrs = (struct interrupt_info *) mem_start;
624 np->n_intrs = l / sizeof(int);
625 mem_start += np->n_intrs * sizeof(struct interrupt_info);
626 for (i = 0; i < np->n_intrs; ++i) {
627 np->intrs[i].line = *ip++;
628 np->intrs[i].sense = 1;
629 }
630 }
631
632 return mem_start;
633 }
634
635 static unsigned long __init
interpret_macio_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)636 interpret_macio_props(struct device_node *np, unsigned long mem_start,
637 int naddrc, int nsizec)
638 {
639 struct reg_property *rp;
640 struct address_range *adr;
641 unsigned long base_address;
642 int i, l, *ip;
643 struct device_node *db;
644
645 base_address = 0;
646 for (db = np->parent; db != NULL; db = db->parent) {
647 if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
648 base_address = db->addrs[0].address;
649 break;
650 }
651 }
652
653 rp = (struct reg_property *) get_property(np, "reg", &l);
654 if (rp != 0 && l >= sizeof(struct reg_property)) {
655 i = 0;
656 adr = (struct address_range *) mem_start;
657 while ((l -= sizeof(struct reg_property)) >= 0) {
658 adr[i].space = 2;
659 adr[i].address = rp[i].address + base_address;
660 adr[i].size = rp[i].size;
661 ++i;
662 }
663 np->addrs = adr;
664 np->n_addrs = i;
665 mem_start += i * sizeof(struct address_range);
666 }
667
668 if (use_of_interrupt_tree)
669 return mem_start;
670
671 ip = (int *) get_property(np, "interrupts", &l);
672 if (ip == 0)
673 ip = (int *) get_property(np, "AAPL,interrupts", &l);
674 if (ip != 0) {
675 np->intrs = (struct interrupt_info *) mem_start;
676 np->n_intrs = l / sizeof(int);
677 for (i = 0; i < np->n_intrs; ++i) {
678 np->intrs[i].line = *ip++;
679 np->intrs[i].sense = 1;
680 }
681 mem_start += np->n_intrs * sizeof(struct interrupt_info);
682 }
683
684 return mem_start;
685 }
686
687 static unsigned long __init
interpret_isa_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)688 interpret_isa_props(struct device_node *np, unsigned long mem_start,
689 int naddrc, int nsizec)
690 {
691 struct isa_reg_property *rp;
692 struct address_range *adr;
693 int i, l, *ip;
694
695 rp = (struct isa_reg_property *) get_property(np, "reg", &l);
696 if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
697 i = 0;
698 adr = (struct address_range *) mem_start;
699 while ((l -= sizeof(struct reg_property)) >= 0) {
700 adr[i].space = rp[i].space;
701 adr[i].address = rp[i].address
702 + (adr[i].space? 0: _ISA_MEM_BASE);
703 adr[i].size = rp[i].size;
704 ++i;
705 }
706 np->addrs = adr;
707 np->n_addrs = i;
708 mem_start += i * sizeof(struct address_range);
709 }
710
711 if (use_of_interrupt_tree)
712 return mem_start;
713
714 ip = (int *) get_property(np, "interrupts", &l);
715 if (ip != 0) {
716 np->intrs = (struct interrupt_info *) mem_start;
717 np->n_intrs = l / (2 * sizeof(int));
718 mem_start += np->n_intrs * sizeof(struct interrupt_info);
719 for (i = 0; i < np->n_intrs; ++i) {
720 np->intrs[i].line = *ip++;
721 np->intrs[i].sense = *ip++;
722 }
723 }
724
725 return mem_start;
726 }
727
728 static unsigned long __init
interpret_root_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)729 interpret_root_props(struct device_node *np, unsigned long mem_start,
730 int naddrc, int nsizec)
731 {
732 struct address_range *adr;
733 int i, l, *ip;
734 unsigned int *rp;
735 int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
736
737 rp = (unsigned int *) get_property(np, "reg", &l);
738 if (rp != 0 && l >= rpsize) {
739 i = 0;
740 adr = (struct address_range *) mem_start;
741 while ((l -= rpsize) >= 0) {
742 adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
743 adr[i].address = rp[naddrc - 1];
744 adr[i].size = rp[naddrc + nsizec - 1];
745 ++i;
746 rp += naddrc + nsizec;
747 }
748 np->addrs = adr;
749 np->n_addrs = i;
750 mem_start += i * sizeof(struct address_range);
751 }
752
753 if (use_of_interrupt_tree)
754 return mem_start;
755
756 ip = (int *) get_property(np, "AAPL,interrupts", &l);
757 if (ip == 0)
758 ip = (int *) get_property(np, "interrupts", &l);
759 if (ip != 0) {
760 np->intrs = (struct interrupt_info *) mem_start;
761 np->n_intrs = l / sizeof(int);
762 mem_start += np->n_intrs * sizeof(struct interrupt_info);
763 for (i = 0; i < np->n_intrs; ++i) {
764 np->intrs[i].line = *ip++;
765 np->intrs[i].sense = 1;
766 }
767 }
768
769 return mem_start;
770 }
771
772 /*
773 * Work out the sense (active-low level / active-high edge)
774 * of each interrupt from the device tree.
775 */
776 void __init
prom_get_irq_senses(unsigned char * senses,int off,int max)777 prom_get_irq_senses(unsigned char *senses, int off, int max)
778 {
779 struct device_node *np;
780 int i, j;
781
782 /* default to level-triggered */
783 memset(senses, 1, max - off);
784 if (!use_of_interrupt_tree)
785 return;
786
787 for (np = allnodes; np != 0; np = np->allnext) {
788 for (j = 0; j < np->n_intrs; j++) {
789 i = np->intrs[j].line;
790 if (i >= off && i < max) {
791 if (np->intrs[j].sense == 1) {
792 senses[i-off] = (IRQ_SENSE_LEVEL |
793 IRQ_POLARITY_NEGATIVE);
794 } else {
795 senses[i-off] = (IRQ_SENSE_EDGE |
796 IRQ_POLARITY_POSITIVE);
797 }
798 }
799 }
800 }
801 }
802
803 /*
804 * Construct and return a list of the device_nodes with a given name.
805 */
806 struct device_node *
find_devices(const char * name)807 find_devices(const char *name)
808 {
809 struct device_node *head, **prevp, *np;
810
811 prevp = &head;
812 for (np = allnodes; np != 0; np = np->allnext) {
813 if (np->name != 0 && strcasecmp(np->name, name) == 0) {
814 *prevp = np;
815 prevp = &np->next;
816 }
817 }
818 *prevp = 0;
819 return head;
820 }
821
822 /*
823 * Construct and return a list of the device_nodes with a given type.
824 */
825 struct device_node *
find_type_devices(const char * type)826 find_type_devices(const char *type)
827 {
828 struct device_node *head, **prevp, *np;
829
830 prevp = &head;
831 for (np = allnodes; np != 0; np = np->allnext) {
832 if (np->type != 0 && strcasecmp(np->type, type) == 0) {
833 *prevp = np;
834 prevp = &np->next;
835 }
836 }
837 *prevp = 0;
838 return head;
839 }
840
841 /*
842 * Returns all nodes linked together
843 */
844 struct device_node * __openfirmware
find_all_nodes(void)845 find_all_nodes(void)
846 {
847 struct device_node *head, **prevp, *np;
848
849 prevp = &head;
850 for (np = allnodes; np != 0; np = np->allnext) {
851 *prevp = np;
852 prevp = &np->next;
853 }
854 *prevp = 0;
855 return head;
856 }
857
858 /* Checks if the given "compat" string matches one of the strings in
859 * the device's "compatible" property
860 */
861 int
device_is_compatible(struct device_node * device,const char * compat)862 device_is_compatible(struct device_node *device, const char *compat)
863 {
864 const char* cp;
865 int cplen, l;
866
867 cp = (char *) get_property(device, "compatible", &cplen);
868 if (cp == NULL)
869 return 0;
870 while (cplen > 0) {
871 if (strncasecmp(cp, compat, strlen(compat)) == 0)
872 return 1;
873 l = strlen(cp) + 1;
874 cp += l;
875 cplen -= l;
876 }
877
878 return 0;
879 }
880
881
882 /*
883 * Indicates whether the root node has a given value in its
884 * compatible property.
885 */
886 int
machine_is_compatible(const char * compat)887 machine_is_compatible(const char *compat)
888 {
889 struct device_node *root;
890
891 root = find_path_device("/");
892 if (root == 0)
893 return 0;
894 return device_is_compatible(root, compat);
895 }
896
897 /*
898 * Construct and return a list of the device_nodes with a given type
899 * and compatible property.
900 */
901 struct device_node *
find_compatible_devices(const char * type,const char * compat)902 find_compatible_devices(const char *type, const char *compat)
903 {
904 struct device_node *head, **prevp, *np;
905
906 prevp = &head;
907 for (np = allnodes; np != 0; np = np->allnext) {
908 if (type != NULL
909 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
910 continue;
911 if (device_is_compatible(np, compat)) {
912 *prevp = np;
913 prevp = &np->next;
914 }
915 }
916 *prevp = 0;
917 return head;
918 }
919
920 /*
921 * Find the device_node with a given full_name.
922 */
923 struct device_node *
find_path_device(const char * path)924 find_path_device(const char *path)
925 {
926 struct device_node *np;
927
928 for (np = allnodes; np != 0; np = np->allnext)
929 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
930 return np;
931 return NULL;
932 }
933
934 /*
935 * Find the device_node with a given phandle.
936 */
937 struct device_node * __init
find_phandle(phandle ph)938 find_phandle(phandle ph)
939 {
940 struct device_node *np;
941
942 for (np = allnodes; np != 0; np = np->allnext)
943 if (np->node == ph)
944 return np;
945 return NULL;
946 }
947
948 /*
949 * Find a property with a given name for a given node
950 * and return the value.
951 */
952 unsigned char *
get_property(struct device_node * np,const char * name,int * lenp)953 get_property(struct device_node *np, const char *name, int *lenp)
954 {
955 struct property *pp;
956
957 for (pp = np->properties; pp != 0; pp = pp->next)
958 if (pp->name != NULL && strcmp(pp->name, name) == 0) {
959 if (lenp != 0)
960 *lenp = pp->length;
961 return pp->value;
962 }
963 return 0;
964 }
965
966 /*
967 * Add a property to a node
968 */
969 void __openfirmware
prom_add_property(struct device_node * np,struct property * prop)970 prom_add_property(struct device_node* np, struct property* prop)
971 {
972 struct property **next = &np->properties;
973
974 prop->next = NULL;
975 while (*next)
976 next = &(*next)->next;
977 *next = prop;
978 }
979
980 /* I quickly hacked that one, check against spec ! */
981 static inline unsigned long __openfirmware
bus_space_to_resource_flags(unsigned int bus_space)982 bus_space_to_resource_flags(unsigned int bus_space)
983 {
984 u8 space = (bus_space >> 24) & 0xf;
985 if (space == 0)
986 space = 0x02;
987 if (space == 0x02)
988 return IORESOURCE_MEM;
989 else if (space == 0x01)
990 return IORESOURCE_IO;
991 else {
992 printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
993 bus_space);
994 return 0;
995 }
996 }
997
998 static struct resource* __openfirmware
find_parent_pci_resource(struct pci_dev * pdev,struct address_range * range)999 find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
1000 {
1001 unsigned long mask;
1002 int i;
1003
1004 /* Check this one */
1005 mask = bus_space_to_resource_flags(range->space);
1006 for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
1007 if ((pdev->resource[i].flags & mask) == mask &&
1008 pdev->resource[i].start <= range->address &&
1009 pdev->resource[i].end > range->address) {
1010 if ((range->address + range->size - 1) > pdev->resource[i].end) {
1011 /* Add better message */
1012 printk(KERN_WARNING "PCI/OF resource overlap !\n");
1013 return NULL;
1014 }
1015 break;
1016 }
1017 }
1018 if (i == DEVICE_COUNT_RESOURCE)
1019 return NULL;
1020 return &pdev->resource[i];
1021 }
1022
1023 /*
1024 * Request an OF device resource. Currently handles child of PCI devices,
1025 * or other nodes attached to the root node. Ultimately, put some
1026 * link to resources in the OF node.
1027 * WARNING: out_resource->name should be initialized before calling this
1028 * function.
1029 */
1030 struct resource* __openfirmware
request_OF_resource(struct device_node * node,int index,const char * name_postfix)1031 request_OF_resource(struct device_node* node, int index, const char* name_postfix)
1032 {
1033 struct pci_dev* pcidev;
1034 u8 pci_bus, pci_devfn;
1035 unsigned long iomask;
1036 struct device_node* nd;
1037 struct resource* parent;
1038 struct resource *res = NULL;
1039 int nlen, plen;
1040
1041 if (index >= node->n_addrs)
1042 goto fail;
1043
1044 /* Sanity check on bus space */
1045 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1046 if (iomask & IORESOURCE_MEM)
1047 parent = &iomem_resource;
1048 else if (iomask & IORESOURCE_IO)
1049 parent = &ioport_resource;
1050 else
1051 goto fail;
1052
1053 /* Find a PCI parent if any */
1054 nd = node;
1055 pcidev = NULL;
1056 while(nd) {
1057 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1058 pcidev = pci_find_slot(pci_bus, pci_devfn);
1059 if (pcidev) break;
1060 nd = nd->parent;
1061 }
1062 if (pcidev)
1063 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1064 if (!parent) {
1065 printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
1066 node->name);
1067 goto fail;
1068 }
1069
1070 res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
1071 if (!res)
1072 goto fail;
1073 nlen = strlen(node->name);
1074 plen = name_postfix ? strlen(name_postfix) : 0;
1075 res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
1076 if (res->name) {
1077 strcpy((char *)res->name, node->name);
1078 if (plen)
1079 strcpy((char *)res->name+nlen, name_postfix);
1080 }
1081 return res;
1082 fail:
1083 return NULL;
1084 }
1085
1086 int __openfirmware
release_OF_resource(struct device_node * node,int index)1087 release_OF_resource(struct device_node* node, int index)
1088 {
1089 struct pci_dev* pcidev;
1090 u8 pci_bus, pci_devfn;
1091 unsigned long iomask;
1092 struct device_node* nd;
1093 struct resource* parent;
1094 struct resource *res = NULL;
1095
1096 if (index >= node->n_addrs)
1097 return -EINVAL;
1098
1099 /* Sanity check on bus space */
1100 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1101 if (iomask & IORESOURCE_MEM)
1102 parent = &iomem_resource;
1103 else if (iomask & IORESOURCE_IO)
1104 parent = &ioport_resource;
1105 else
1106 return -EINVAL;
1107
1108 /* Find a PCI parent if any */
1109 nd = node;
1110 pcidev = NULL;
1111 while(nd) {
1112 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1113 pcidev = pci_find_slot(pci_bus, pci_devfn);
1114 if (pcidev) break;
1115 nd = nd->parent;
1116 }
1117 if (pcidev)
1118 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1119 if (!parent) {
1120 printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
1121 node->name);
1122 return -ENODEV;
1123 }
1124
1125 /* Find us in the parent */
1126 res = parent->child;
1127 while (res) {
1128 if (res->start == node->addrs[index].address &&
1129 res->end == (res->start + node->addrs[index].size - 1))
1130 break;
1131 res = res->sibling;
1132 }
1133 if (!res)
1134 return -ENODEV;
1135
1136 if (res->name) {
1137 kfree(res->name);
1138 res->name = NULL;
1139 }
1140 release_resource(res);
1141 kfree(res);
1142
1143 return 0;
1144 }
1145
1146 #if 0
1147 void __openfirmware
1148 print_properties(struct device_node *np)
1149 {
1150 struct property *pp;
1151 char *cp;
1152 int i, n;
1153
1154 for (pp = np->properties; pp != 0; pp = pp->next) {
1155 printk(KERN_INFO "%s", pp->name);
1156 for (i = strlen(pp->name); i < 16; ++i)
1157 printk(" ");
1158 cp = (char *) pp->value;
1159 for (i = pp->length; i > 0; --i, ++cp)
1160 if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
1161 || (i == 1 && *cp != 0))
1162 break;
1163 if (i == 0 && pp->length > 1) {
1164 /* looks like a string */
1165 printk(" %s\n", (char *) pp->value);
1166 } else {
1167 /* dump it in hex */
1168 n = pp->length;
1169 if (n > 64)
1170 n = 64;
1171 if (pp->length % 4 == 0) {
1172 unsigned int *p = (unsigned int *) pp->value;
1173
1174 n /= 4;
1175 for (i = 0; i < n; ++i) {
1176 if (i != 0 && (i % 4) == 0)
1177 printk("\n ");
1178 printk(" %08x", *p++);
1179 }
1180 } else {
1181 unsigned char *bp = pp->value;
1182
1183 for (i = 0; i < n; ++i) {
1184 if (i != 0 && (i % 16) == 0)
1185 printk("\n ");
1186 printk(" %02x", *bp++);
1187 }
1188 }
1189 printk("\n");
1190 if (pp->length > 64)
1191 printk(" ... (length = %d)\n",
1192 pp->length);
1193 }
1194 }
1195 }
1196 #endif
1197
1198 static spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
1199
1200 /* this can be called after setup -- Cort */
1201 int __openfirmware
call_rtas(const char * service,int nargs,int nret,unsigned long * outputs,...)1202 call_rtas(const char *service, int nargs, int nret,
1203 unsigned long *outputs, ...)
1204 {
1205 va_list list;
1206 int i;
1207 unsigned long s;
1208 struct device_node *rtas;
1209 int *tokp;
1210 union {
1211 unsigned long words[16];
1212 double align;
1213 } u;
1214
1215 rtas = find_devices("rtas");
1216 if (rtas == NULL)
1217 return -1;
1218 tokp = (int *) get_property(rtas, service, NULL);
1219 if (tokp == NULL) {
1220 printk(KERN_ERR "No RTAS service called %s\n", service);
1221 return -1;
1222 }
1223 u.words[0] = *tokp;
1224 u.words[1] = nargs;
1225 u.words[2] = nret;
1226 va_start(list, outputs);
1227 for (i = 0; i < nargs; ++i)
1228 u.words[i+3] = va_arg(list, unsigned long);
1229 va_end(list);
1230
1231 /*
1232 * RTAS doesn't use floating point.
1233 * Or at least, according to the CHRP spec we enter RTAS
1234 * with FP disabled, and it doesn't change the FP registers.
1235 * -- paulus.
1236 */
1237 spin_lock_irqsave(&rtas_lock, s);
1238 enter_rtas((void *)__pa(&u));
1239 spin_unlock_irqrestore(&rtas_lock, s);
1240
1241 if (nret > 1 && outputs != NULL)
1242 for (i = 0; i < nret-1; ++i)
1243 outputs[i] = u.words[i+nargs+4];
1244 return u.words[nargs+3];
1245 }
1246