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