1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#if 0
19#define DEBUG_YABOOT
20#endif
21
22#if 0
23#define DEBUG_PROM
24#endif
25
26#include <stdarg.h>
27#include <linux/config.h>
28#include <linux/kernel.h>
29#include <linux/string.h>
30#include <linux/init.h>
31#include <linux/version.h>
32#include <linux/threads.h>
33#include <linux/spinlock.h>
34#include <linux/blk.h>
35
36#ifdef DEBUG_YABOOT
37#define call_yaboot(FUNC,...) \
38 do { \
39 if (FUNC) { \
40 struct prom_t *_prom = PTRRELOC(&prom); \
41 unsigned long prom_entry = _prom->entry;\
42 _prom->entry = (unsigned long)(FUNC); \
43 enter_prom(__VA_ARGS__); \
44 _prom->entry = prom_entry; \
45 } \
46 } while (0)
47#else
48#define call_yaboot(FUNC,...) do { ; } while (0)
49#endif
50
51#include <asm/init.h>
52#include <linux/types.h>
53#include <linux/pci.h>
54#include <asm/prom.h>
55#include <asm/rtas.h>
56#include <asm/lmb.h>
57#include <asm/abs_addr.h>
58#include <asm/page.h>
59#include <asm/processor.h>
60#include <asm/irq.h>
61#include <asm/io.h>
62#include <asm/smp.h>
63#include <asm/system.h>
64#include <asm/mmu.h>
65#include <asm/pgtable.h>
66#include <asm/bitops.h>
67#include <asm/naca.h>
68#include <asm/pci.h>
69#include "open_pic.h"
70#include <asm/bootinfo.h>
71#include <asm/ppcdebug.h>
72
73#ifdef CONFIG_FB
74#include <asm/linux_logo.h>
75#endif
76
77extern char _end[];
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101#define PROM_BUG() do { \
102 prom_print(RELOC("kernel BUG at ")); \
103 prom_print(RELOC(__FILE__)); \
104 prom_print(RELOC(":")); \
105 prom_print_hex(__LINE__); \
106 prom_print(RELOC("!\n")); \
107 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
108} while (0)
109
110
111
112struct pci_reg_property {
113 struct pci_address addr;
114 u32 size_hi;
115 u32 size_lo;
116};
117
118
119struct isa_reg_property {
120 u32 space;
121 u32 address;
122 u32 size;
123};
124
125struct pci_intr_map {
126 struct pci_address addr;
127 u32 dunno;
128 phandle int_ctrler;
129 u32 intr;
130};
131
132
133typedef unsigned long interpret_func(struct device_node *, unsigned long,
134 int, int);
135#if 0
136static interpret_func interpret_pci_props;
137#endif
138static unsigned long interpret_pci_props(struct device_node *, unsigned long,
139 int, int);
140
141static interpret_func interpret_isa_props;
142static interpret_func interpret_root_props;
143
144#ifndef FB_MAX
145#define FB_MAX 8
146#endif
147
148
149struct prom_t prom = {
150 0,
151 0,
152 0,
153 0,
154 0,
155 {0,0,0,{0},NULL},
156 0,
157 32,
158 0
159#ifdef DEBUG_YABOOT
160 ,NULL
161#endif
162};
163
164
165char *prom_display_paths[FB_MAX] __initdata = { 0, };
166unsigned int prom_num_displays = 0;
167char *of_stdout_device = 0;
168
169extern struct rtas_t rtas;
170extern unsigned long klimit;
171extern unsigned long embedded_sysmap_end;
172extern struct lmb lmb;
173#ifdef CONFIG_MSCHUNKS
174extern struct msChunks msChunks;
175#endif
176
177#define MAX_PHB 16 * 3
178struct _of_tce_table of_tce_table[MAX_PHB + 1] = {{0, 0, 0}};
179
180char *bootpath = 0;
181char *bootdevice = 0;
182
183struct device_node *allnodes = 0;
184
185#define UNDEFINED_IRQ 0xffff
186unsigned short real_irq_to_virt_map[NR_HW_IRQS];
187unsigned short virt_irq_to_real_map[NR_IRQS];
188int last_virt_irq = 2;
189
190static unsigned long call_prom(const char *service, int nargs, int nret, ...);
191static void prom_exit(void);
192static unsigned long copy_device_tree(unsigned long);
193static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
194 unsigned long, struct device_node ***);
195static unsigned long finish_node(struct device_node *, unsigned long,
196 interpret_func *, int, int);
197static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
198static unsigned long check_display(unsigned long);
199static int prom_next_node(phandle *);
200static struct bi_record * prom_bi_rec_verify(struct bi_record *);
201static unsigned long prom_bi_rec_reserve(unsigned long);
202static struct device_node *find_phandle(phandle);
203
204#ifdef CONFIG_MSCHUNKS
205static unsigned long prom_initialize_mschunks(unsigned long);
206#ifdef DEBUG_PROM
207void prom_dump_mschunks_mapping(void);
208#endif
209#endif
210#ifdef DEBUG_PROM
211void prom_dump_lmb(void);
212#endif
213
214extern unsigned long reloc_offset(void);
215
216extern void enter_prom(void *dummy,...);
217
218void cacheable_memzero(void *, unsigned int);
219
220#ifndef CONFIG_CMDLINE
221#define CONFIG_CMDLINE ""
222#endif
223char cmd_line[512] = CONFIG_CMDLINE;
224unsigned long dev_tree_size;
225
226#ifdef CONFIG_HMT
227struct {
228 unsigned int pir;
229 unsigned int threadid;
230} hmt_thread_data[NR_CPUS] = {0};
231#endif
232
233char testString[] = "LINUX\n";
234
235
236
237
238
239
240
241static unsigned long __init
242call_prom(const char *service, int nargs, int nret, ...)
243{
244 int i;
245 unsigned long offset = reloc_offset();
246 struct prom_t *_prom = PTRRELOC(&prom);
247 va_list list;
248
249 _prom->args.service = (u32)LONG_LSW(service);
250 _prom->args.nargs = nargs;
251 _prom->args.nret = nret;
252 _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
253
254 va_start(list, nret);
255 for (i=0; i < nargs ;i++)
256 _prom->args.args[i] = (prom_arg_t)LONG_LSW(va_arg(list, unsigned long));
257 va_end(list);
258
259 for (i=0; i < nret ;i++)
260 _prom->args.rets[i] = 0;
261
262 enter_prom(&_prom->args);
263
264 return (unsigned long)((nret > 0) ? _prom->args.rets[0] : 0);
265}
266
267
268static void __init
269prom_exit()
270{
271 unsigned long offset = reloc_offset();
272
273 call_prom(RELOC("exit"), 0, 0);
274
275 for (;;)
276 ;
277}
278
279void __init
280prom_enter(void)
281{
282 unsigned long offset = reloc_offset();
283
284 call_prom(RELOC("enter"), 0, 0);
285}
286
287
288void __init
289prom_print(const char *msg)
290{
291 const char *p, *q;
292 unsigned long offset = reloc_offset();
293 struct prom_t *_prom = PTRRELOC(&prom);
294
295 if (_prom->stdout == 0)
296 return;
297
298 for (p = msg; *p != 0; p = q) {
299 for (q = p; *q != 0 && *q != '\n'; ++q)
300 ;
301 if (q > p)
302 call_prom(RELOC("write"), 3, 1, _prom->stdout,
303 p, q - p);
304 if (*q != 0) {
305 ++q;
306 call_prom(RELOC("write"), 3, 1, _prom->stdout,
307 RELOC("\r\n"), 2);
308 }
309 }
310}
311
312void
313prom_print_hex(unsigned long val)
314{
315 int i, nibbles = sizeof(val)*2;
316 char buf[sizeof(val)*2+1];
317
318 for (i = nibbles-1; i >= 0; i--) {
319 buf[i] = (val & 0xf) + '0';
320 if (buf[i] > '9')
321 buf[i] += ('a'-'0'-10);
322 val >>= 4;
323 }
324 buf[nibbles] = '\0';
325 prom_print(buf);
326}
327
328void
329prom_print_nl(void)
330{
331 unsigned long offset = reloc_offset();
332 prom_print(RELOC("\n"));
333}
334
335
336static unsigned long
337prom_initialize_naca(unsigned long mem)
338{
339 phandle node;
340 char type[64];
341 unsigned long num_cpus = 0;
342 unsigned long offset = reloc_offset();
343 struct prom_t *_prom = PTRRELOC(&prom);
344 struct naca_struct *_naca = RELOC(naca);
345 struct systemcfg *_systemcfg = RELOC(systemcfg);
346
347
348#ifdef DEBUG_PROM
349 prom_print(RELOC("prom_initialize_naca: start...\n"));
350#endif
351
352 _naca->pftSize = 0;
353
354 for (node = 0; prom_next_node(&node); ) {
355 type[0] = 0;
356 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
357 type, sizeof(type));
358
359 if (!strcmp(type, RELOC("cpu"))) {
360 num_cpus += 1;
361
362
363
364
365 if ( num_cpus == 1 ) {
366 u32 size, lsize, sets;
367
368 call_prom(RELOC("getprop"), 4, 1, node,
369 RELOC("d-cache-size"),
370 &size, sizeof(size));
371
372 call_prom(RELOC("getprop"), 4, 1, node,
373 RELOC("d-cache-line-size"),
374 &lsize, sizeof(lsize));
375
376 _systemcfg->dCacheL1Size = size;
377 _systemcfg->dCacheL1LineSize = lsize;
378 _naca->dCacheL1LogLineSize = __ilog2(lsize);
379 _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
380
381 call_prom(RELOC("getprop"), 4, 1, node,
382 RELOC("i-cache-size"),
383 &size, sizeof(size));
384
385 call_prom(RELOC("getprop"), 4, 1, node,
386 RELOC("i-cache-line-size"),
387 &lsize, sizeof(lsize));
388
389 _systemcfg->iCacheL1Size = size;
390 _systemcfg->iCacheL1LineSize = lsize;
391 _naca->iCacheL1LogLineSize = __ilog2(lsize);
392 _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
393
394 if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
395 u32 pft_size[2];
396 call_prom(RELOC("getprop"), 4, 1, node,
397 RELOC("ibm,pft-size"),
398 &pft_size, sizeof(pft_size));
399
400 _naca->pftSize = pft_size[1];
401 }
402 }
403 } else if (!strcmp(type, RELOC("serial"))) {
404 phandle isa, pci;
405 struct isa_reg_property reg;
406 union pci_range ranges;
407
408 type[0] = 0;
409 call_prom(RELOC("getprop"), 4, 1, node,
410 RELOC("ibm,aix-loc"), type, sizeof(type));
411
412 if (strcmp(type, RELOC("S1")))
413 continue;
414
415 call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
416 ®, sizeof(reg));
417
418 isa = call_prom(RELOC("parent"), 1, 1, node);
419 if (!isa)
420 PROM_BUG();
421 pci = call_prom(RELOC("parent"), 1, 1, isa);
422 if (!pci)
423 PROM_BUG();
424
425 call_prom(RELOC("getprop"), 4, 1, pci, RELOC("ranges"),
426 &ranges, sizeof(ranges));
427
428 if ( _prom->encode_phys_size == 32 )
429 _naca->serialPortAddr = ranges.pci32.phys+reg.address;
430 else {
431 _naca->serialPortAddr =
432 ((((unsigned long)ranges.pci64.phys_hi) << 32) |
433 (ranges.pci64.phys_lo)) + reg.address;
434 }
435 }
436 }
437
438 _naca->interrupt_controller = IC_INVALID;
439 for (node = 0; prom_next_node(&node); ) {
440 type[0] = 0;
441 call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
442 type, sizeof(type));
443 if (strcmp(type, RELOC("interrupt-controller"))) {
444 continue;
445 }
446 call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
447 type, sizeof(type));
448 if (strstr(type, RELOC("open-pic"))) {
449 _naca->interrupt_controller = IC_OPEN_PIC;
450 } else if (strstr(type, RELOC("ppc-xicp"))) {
451 _naca->interrupt_controller = IC_PPC_XIC;
452 } else {
453 prom_print(RELOC("prom: failed to recognize interrupt-controller\n"));
454 }
455 break;
456 }
457
458 if (_naca->interrupt_controller == IC_INVALID) {
459 prom_print(RELOC("prom: failed to find interrupt-controller\n"));
460 PROM_BUG();
461 }
462
463
464 if ( (_systemcfg->processorCount = num_cpus) < 1 )
465 PROM_BUG();
466
467 _systemcfg->physicalMemorySize = lmb_phys_mem_size();
468
469 if (_systemcfg->platform == PLATFORM_PSERIES) {
470 unsigned long rnd_mem_size, pteg_count;
471
472
473 rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
474 if (rnd_mem_size < _systemcfg->physicalMemorySize)
475 rnd_mem_size <<= 1;
476
477
478 pteg_count = (rnd_mem_size >> (12 + 1));
479
480 _naca->pftSize = __ilog2(pteg_count << 7);
481 }
482
483 if (_naca->pftSize == 0) {
484 prom_print(RELOC("prom: failed to compute pftSize!\n"));
485 PROM_BUG();
486 }
487
488
489
490
491
492
493 _naca->slb_size = 64;
494
495
496 strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
497 _systemcfg->version.major = SYSTEMCFG_MAJOR;
498 _systemcfg->version.minor = SYSTEMCFG_MINOR;
499 _systemcfg->processor = _get_PVR();
500
501#ifdef DEBUG_PROM
502 prom_print(RELOC("systemcfg->processorCount = 0x"));
503 prom_print_hex(_systemcfg->processorCount);
504 prom_print_nl();
505
506 prom_print(RELOC("systemcfg->physicalMemorySize = 0x"));
507 prom_print_hex(_systemcfg->physicalMemorySize);
508 prom_print_nl();
509
510 prom_print(RELOC("naca->pftSize = 0x"));
511 prom_print_hex(_naca->pftSize);
512 prom_print_nl();
513
514 prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x"));
515 prom_print_hex(_systemcfg->dCacheL1LineSize);
516 prom_print_nl();
517
518 prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x"));
519 prom_print_hex(_systemcfg->iCacheL1LineSize);
520 prom_print_nl();
521
522 prom_print(RELOC("naca->serialPortAddr = 0x"));
523 prom_print_hex(_naca->serialPortAddr);
524 prom_print_nl();
525
526 prom_print(RELOC("naca->interrupt_controller = 0x"));
527 prom_print_hex(_naca->interrupt_controller);
528 prom_print_nl();
529
530 prom_print(RELOC("systemcfg->platform = 0x"));
531 prom_print_hex(_systemcfg->platform);
532 prom_print_nl();
533
534 prom_print(RELOC("prom_initialize_naca: end...\n"));
535#endif
536
537 return mem;
538}
539
540
541static unsigned long __init
542prom_initialize_lmb(unsigned long mem)
543{
544 phandle node;
545 char type[64];
546 unsigned long i, offset = reloc_offset();
547 struct prom_t *_prom = PTRRELOC(&prom);
548 union lmb_reg_property reg;
549 unsigned long lmb_base, lmb_size;
550 unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
551
552#ifdef CONFIG_MSCHUNKS
553 unsigned long max_addr = 0;
554#if 1
555
556 unsigned long io_base = 3UL<<30;
557 unsigned long io_size = 1UL<<30;
558 unsigned long have_630 = 1;
559
560#else
561 unsigned long io_base = <real io base here>;
562 unsigned long io_size = <real io size here>;
563#endif
564#endif
565
566 lmb_init();
567
568 for (node = 0; prom_next_node(&node); ) {
569 type[0] = 0;
570 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
571 type, sizeof(type));
572
573 if (strcmp(type, RELOC("memory")))
574 continue;
575
576 num_regs = call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
577 ®, sizeof(reg)) / bytes_per_reg;
578
579 for (i=0; i < num_regs ;i++) {
580 if (_prom->encode_phys_size == 32) {
581 lmb_base = reg.addr32[i].address;
582 lmb_size = reg.addr32[i].size;
583 } else {
584 lmb_base = reg.addr64[i].address;
585 lmb_size = reg.addr64[i].size;
586 }
587
588#ifdef CONFIG_MSCHUNKS
589 if ( lmb_addrs_overlap(lmb_base,lmb_size,
590 io_base,io_size) ) {
591
592
593
594 have_630 = 0;
595 }
596#endif
597 if ( lmb_add(lmb_base, lmb_size) < 0 )
598 prom_print(RELOC("Too many LMB's, discarding this one...\n"));
599#ifdef CONFIG_MSCHUNKS
600 else if ( max_addr < (lmb_base+lmb_size-1) )
601 max_addr = lmb_base+lmb_size-1;
602#endif
603 }
604
605 }
606
607#ifdef CONFIG_MSCHUNKS
608 if ( have_630 && lmb_addrs_overlap(0,max_addr,io_base,io_size) )
609 lmb_add_io(io_base, io_size);
610#endif
611
612 lmb_analyze();
613#ifdef DEBUG_PROM
614 prom_dump_lmb();
615#endif
616
617#ifdef CONFIG_MSCHUNKS
618 mem = prom_initialize_mschunks(mem);
619#ifdef DEBUG_PROM
620 prom_dump_mschunks_mapping();
621#endif
622#endif
623
624 return mem;
625}
626
627
628static void __init
629prom_instantiate_rtas(void)
630{
631 unsigned long offset = reloc_offset();
632 struct prom_t *_prom = PTRRELOC(&prom);
633 struct rtas_t *_rtas = PTRRELOC(&rtas);
634 struct naca_struct *_naca = RELOC(naca);
635 struct systemcfg *_systemcfg = RELOC(systemcfg);
636 ihandle prom_rtas;
637 u32 getprop_rval;
638
639#ifdef DEBUG_PROM
640 prom_print(RELOC("prom_instantiate_rtas: start...\n"));
641#endif
642 prom_rtas = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
643 if (prom_rtas != (ihandle) -1) {
644 char hypertas_funcs[1024];
645 int rc;
646
647 if ((rc = call_prom(RELOC("getprop"),
648 4, 1, prom_rtas,
649 RELOC("ibm,hypertas-functions"),
650 hypertas_funcs,
651 sizeof(hypertas_funcs))) > 0) {
652 _systemcfg->platform = PLATFORM_PSERIES_LPAR;
653 }
654
655 call_prom(RELOC("getprop"),
656 4, 1, prom_rtas,
657 RELOC("rtas-size"),
658 &getprop_rval,
659 sizeof(getprop_rval));
660 _rtas->size = getprop_rval;
661 prom_print(RELOC("instantiating rtas"));
662 if (_rtas->size != 0) {
663 unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
664
665
666
667
668
669 if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
670 struct lmb *_lmb = PTRRELOC(&lmb);
671 rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
672 }
673 _rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);
674
675 prom_print(RELOC(" at 0x"));
676 prom_print_hex(_rtas->base);
677
678 prom_rtas = (ihandle)call_prom(RELOC("open"),
679 1, 1, RELOC("/rtas"));
680 prom_print(RELOC("..."));
681
682 if ((long)call_prom(RELOC("call-method"), 3, 2,
683 RELOC("instantiate-rtas"),
684 prom_rtas,
685 _rtas->base) >= 0) {
686 _rtas->entry = (long)_prom->args.rets[1];
687 }
688 }
689
690 if (_rtas->entry <= 0) {
691 prom_print(RELOC(" failed\n"));
692 } else {
693 prom_print(RELOC(" done\n"));
694 }
695
696#ifdef DEBUG_PROM
697 prom_print(RELOC("rtas->base = 0x"));
698 prom_print_hex(_rtas->base);
699 prom_print_nl();
700 prom_print(RELOC("rtas->entry = 0x"));
701 prom_print_hex(_rtas->entry);
702 prom_print_nl();
703 prom_print(RELOC("rtas->size = 0x"));
704 prom_print_hex(_rtas->size);
705 prom_print_nl();
706#endif
707 }
708#ifdef DEBUG_PROM
709 prom_print(RELOC("prom_instantiate_rtas: end...\n"));
710#endif
711}
712
713unsigned long prom_strtoul(const char *cp)
714{
715 unsigned long result = 0,value;
716
717 while (*cp) {
718 value = *cp-'0';
719 result = result*10 + value;
720 cp++;
721 }
722
723 return result;
724}
725
726
727#ifdef CONFIG_MSCHUNKS
728static unsigned long
729prom_initialize_mschunks(unsigned long mem)
730{
731 unsigned long offset = reloc_offset();
732 struct lmb *_lmb = PTRRELOC(&lmb);
733 struct msChunks *_msChunks = PTRRELOC(&msChunks);
734 unsigned long i, pchunk = 0;
735 unsigned long addr_range = _lmb->memory.size + _lmb->memory.iosize;
736 unsigned long chunk_size = _lmb->memory.lcd_size;
737
738
739 mem = msChunks_alloc(mem, addr_range / chunk_size, chunk_size);
740
741
742 for (i=0; i < _lmb->memory.cnt ;i++) {
743 unsigned long base = _lmb->memory.region[i].base;
744 unsigned long size = _lmb->memory.region[i].size;
745 unsigned long achunk = addr_to_chunk(base);
746 unsigned long end_achunk = addr_to_chunk(base+size);
747
748 if(_lmb->memory.region[i].type != LMB_MEMORY_AREA)
749 continue;
750
751 _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
752 for (; achunk < end_achunk ;) {
753 PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
754 }
755 }
756
757#ifdef CONFIG_MSCHUNKS
758
759 for (i=0; i < _lmb->memory.cnt ;i++) {
760 unsigned long base = _lmb->memory.region[i].base;
761 unsigned long size = _lmb->memory.region[i].size;
762 unsigned long achunk = addr_to_chunk(base);
763 unsigned long end_achunk = addr_to_chunk(base+size);
764
765 if(_lmb->memory.region[i].type != LMB_IO_AREA)
766 continue;
767
768 _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
769 for (; achunk < end_achunk ;) {
770 PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
771 }
772 }
773#endif
774
775 return mem;
776}
777
778#ifdef DEBUG_PROM
779void
780prom_dump_mschunks_mapping(void)
781{
782 unsigned long offset = reloc_offset();
783 struct msChunks *_msChunks = PTRRELOC(&msChunks);
784 unsigned long chunk;
785
786 prom_print(RELOC("\nprom_dump_mschunks_mapping:\n"));
787 prom_print(RELOC(" msChunks.num_chunks = 0x"));
788 prom_print_hex(_msChunks->num_chunks);
789 prom_print_nl();
790 prom_print(RELOC(" msChunks.chunk_size = 0x"));
791 prom_print_hex(_msChunks->chunk_size);
792 prom_print_nl();
793 prom_print(RELOC(" msChunks.chunk_shift = 0x"));
794 prom_print_hex(_msChunks->chunk_shift);
795 prom_print_nl();
796 prom_print(RELOC(" msChunks.chunk_mask = 0x"));
797 prom_print_hex(_msChunks->chunk_mask);
798 prom_print_nl();
799 prom_print(RELOC(" msChunks.abs = 0x"));
800 prom_print_hex(_msChunks->abs);
801 prom_print_nl();
802
803 prom_print(RELOC(" msChunks mapping:\n"));
804 for(chunk=0; chunk < _msChunks->num_chunks ;chunk++) {
805 prom_print(RELOC(" phys 0x"));
806 prom_print_hex(chunk);
807 prom_print(RELOC(" -> abs 0x"));
808 prom_print_hex(PTRRELOC(_msChunks->abs)[chunk]);
809 prom_print_nl();
810 }
811
812}
813#endif
814#endif
815
816#ifdef DEBUG_PROM
817void
818prom_dump_lmb(void)
819{
820 unsigned long i;
821 unsigned long offset = reloc_offset();
822 struct lmb *_lmb = PTRRELOC(&lmb);
823
824 prom_print(RELOC("\nprom_dump_lmb:\n"));
825 prom_print(RELOC(" memory.cnt = 0x"));
826 prom_print_hex(_lmb->memory.cnt);
827 prom_print_nl();
828 prom_print(RELOC(" memory.size = 0x"));
829 prom_print_hex(_lmb->memory.size);
830 prom_print_nl();
831 prom_print(RELOC(" memory.lcd_size = 0x"));
832 prom_print_hex(_lmb->memory.lcd_size);
833 prom_print_nl();
834 for (i=0; i < _lmb->memory.cnt ;i++) {
835 prom_print(RELOC(" memory.region[0x"));
836 prom_print_hex(i);
837 prom_print(RELOC("].base = 0x"));
838 prom_print_hex(_lmb->memory.region[i].base);
839 prom_print_nl();
840 prom_print(RELOC(" .physbase = 0x"));
841 prom_print_hex(_lmb->memory.region[i].physbase);
842 prom_print_nl();
843 prom_print(RELOC(" .size = 0x"));
844 prom_print_hex(_lmb->memory.region[i].size);
845 prom_print_nl();
846 prom_print(RELOC(" .type = 0x"));
847 prom_print_hex(_lmb->memory.region[i].type);
848 prom_print_nl();
849 }
850
851 prom_print_nl();
852 prom_print(RELOC(" reserved.cnt = 0x"));
853 prom_print_hex(_lmb->reserved.cnt);
854 prom_print_nl();
855 prom_print(RELOC(" reserved.size = 0x"));
856 prom_print_hex(_lmb->reserved.size);
857 prom_print_nl();
858 prom_print(RELOC(" reserved.lcd_size = 0x"));
859 prom_print_hex(_lmb->reserved.lcd_size);
860 prom_print_nl();
861 for (i=0; i < _lmb->reserved.cnt ;i++) {
862 prom_print(RELOC(" reserved.region[0x"));
863 prom_print_hex(i);
864 prom_print(RELOC("].base = 0x"));
865 prom_print_hex(_lmb->reserved.region[i].base);
866 prom_print_nl();
867 prom_print(RELOC(" .physbase = 0x"));
868 prom_print_hex(_lmb->reserved.region[i].physbase);
869 prom_print_nl();
870 prom_print(RELOC(" .size = 0x"));
871 prom_print_hex(_lmb->reserved.region[i].size);
872 prom_print_nl();
873 prom_print(RELOC(" .type = 0x"));
874 prom_print_hex(_lmb->reserved.region[i].type);
875 prom_print_nl();
876 }
877}
878#endif
879
880
881void
882prom_initialize_tce_table(void)
883{
884 phandle node;
885 ihandle phb_node;
886 unsigned long offset = reloc_offset();
887 char compatible[64], path[64], type[64], model[64];
888 unsigned long i, table = 0;
889 unsigned long base, vbase, align;
890 unsigned int minalign, minsize;
891 struct _of_tce_table *prom_tce_table = RELOC(of_tce_table);
892 unsigned long tce_entry, *tce_entryp;
893
894#ifdef DEBUG_PROM
895 prom_print(RELOC("starting prom_initialize_tce_table\n"));
896#endif
897
898
899 for (node = 0; prom_next_node(&node); ) {
900 compatible[0] = 0;
901 type[0] = 0;
902 model[0] = 0;
903 call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
904 compatible, sizeof(compatible));
905 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
906 type, sizeof(type));
907 call_prom(RELOC("getprop"), 4, 1, node, RELOC("model"),
908 model, sizeof(model));
909
910
911 if (compatible[0] != 0) {
912 if((strstr(compatible, RELOC("python")) == NULL) &&
913 (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
914 (strstr(compatible, RELOC("Winnipeg")) == NULL))
915 continue;
916 } else if (model[0] != 0) {
917 if ((strstr(model, RELOC("ython")) == NULL) &&
918 (strstr(model, RELOC("peedwagon")) == NULL) &&
919 (strstr(model, RELOC("innipeg")) == NULL))
920 continue;
921 }
922
923 if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {
924 continue;
925 }
926
927 if (call_prom(RELOC("getprop"), 4, 1, node,
928 RELOC("tce-table-minalign"), &minalign,
929 sizeof(minalign)) < 0) {
930 minalign = 0;
931 }
932
933 if (call_prom(RELOC("getprop"), 4, 1, node,
934 RELOC("tce-table-minsize"), &minsize,
935 sizeof(minsize)) < 0) {
936 minsize = 4UL << 20;
937 }
938
939
940
941
942
943
944 minsize = 4UL << 20;
945
946
947 align = (minalign < minsize) ? minsize : minalign;
948
949
950 base = lmb_alloc(minsize, align);
951
952 if ( !base ) {
953 prom_print(RELOC("ERROR, cannot find space for TCE table.\n"));
954 prom_exit();
955 }
956
957 vbase = absolute_to_virt(base);
958
959
960 prom_tce_table[table].node = node;
961 prom_tce_table[table].base = vbase;
962 prom_tce_table[table].size = minsize;
963
964#ifdef DEBUG_PROM
965 prom_print(RELOC("TCE table: 0x"));
966 prom_print_hex(table);
967 prom_print_nl();
968
969 prom_print(RELOC("\tnode = 0x"));
970 prom_print_hex(node);
971 prom_print_nl();
972
973 prom_print(RELOC("\tbase = 0x"));
974 prom_print_hex(vbase);
975 prom_print_nl();
976
977 prom_print(RELOC("\tsize = 0x"));
978 prom_print_hex(minsize);
979 prom_print_nl();
980#endif
981
982
983
984
985 tce_entryp = (unsigned long *)base;
986 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
987 tce_entry = (i << PAGE_SHIFT);
988 tce_entry |= 0x3;
989 *tce_entryp = tce_entry;
990 }
991
992
993 if (call_prom(RELOC("package-to-path"), 3, 1, node,
994 path, 255) <= 0) {
995 prom_print(RELOC("package-to-path failed\n"));
996 } else {
997 prom_print(RELOC("opened "));
998 prom_print(path);
999 prom_print_nl();
1000 }
1001
1002 phb_node = (ihandle)call_prom(RELOC("open"), 1, 1, path);
1003 if ( (long)phb_node <= 0) {
1004 prom_print(RELOC("open failed\n"));
1005 } else {
1006 prom_print(RELOC("open success\n"));
1007 }
1008 call_prom(RELOC("call-method"), 6, 0,
1009 RELOC("set-64-bit-addressing"),
1010 phb_node,
1011 -1,
1012 minsize,
1013 base & 0xffffffff,
1014 (base >> 32) & 0xffffffff);
1015 call_prom(RELOC("close"), 1, 0, phb_node);
1016
1017 table++;
1018 }
1019
1020
1021 prom_tce_table[table].node = 0;
1022#ifdef DEBUG_PROM
1023 prom_print(RELOC("ending prom_initialize_tce_table\n"));
1024#endif
1025}
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048static void
1049prom_hold_cpus(unsigned long mem)
1050{
1051 unsigned long i;
1052 unsigned int reg;
1053 phandle node;
1054 unsigned long offset = reloc_offset();
1055 char type[64], *path;
1056 int cpuid = 0;
1057 extern void __secondary_hold(void);
1058 extern unsigned long __secondary_hold_spinloop;
1059 extern unsigned long __secondary_hold_acknowledge;
1060 unsigned long *spinloop = __v2a(&__secondary_hold_spinloop);
1061 unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
1062 unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));
1063 struct naca_struct *_naca = RELOC(naca);
1064 struct systemcfg *_systemcfg = RELOC(systemcfg);
1065 struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
1066 struct prom_t *_prom = PTRRELOC(&prom);
1067
1068
1069 _systemcfg->processorCount = 1;
1070
1071#ifdef DEBUG_PROM
1072 prom_print(RELOC("prom_hold_cpus: start...\n"));
1073 prom_print(RELOC(" 1) spinloop = 0x"));
1074 prom_print_hex(spinloop);
1075 prom_print_nl();
1076 prom_print(RELOC(" 1) *spinloop = 0x"));
1077 prom_print_hex(*spinloop);
1078 prom_print_nl();
1079 prom_print(RELOC(" 1) acknowledge = 0x"));
1080 prom_print_hex(acknowledge);
1081 prom_print_nl();
1082 prom_print(RELOC(" 1) *acknowledge = 0x"));
1083 prom_print_hex(*acknowledge);
1084 prom_print_nl();
1085 prom_print(RELOC(" 1) secondary_hold = 0x"));
1086 prom_print_hex(secondary_hold);
1087 prom_print_nl();
1088#endif
1089
1090
1091
1092
1093
1094
1095 *spinloop = 0;
1096
1097#ifdef CONFIG_HMT
1098 for (i=0; i < NR_CPUS; i++) {
1099 RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
1100 }
1101#endif
1102
1103 for (node = 0; prom_next_node(&node); ) {
1104 type[0] = 0;
1105 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
1106 type, sizeof(type));
1107 if (strcmp(type, RELOC("cpu")) != 0)
1108 continue;
1109
1110
1111 call_prom(RELOC("getprop"), 4, 1, node, RELOC("status"),
1112 type, sizeof(type));
1113 if (strcmp(type, RELOC("okay")) != 0)
1114 continue;
1115
1116 reg = -1;
1117 call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
1118 ®, sizeof(reg));
1119
1120
1121 if ( reg == _prom->cpu )
1122 continue;
1123
1124 path = (char *) mem;
1125 memset(path, 0, 256);
1126 if ((long) call_prom(RELOC("package-to-path"), 3, 1,
1127 node, path, 255) < 0)
1128 continue;
1129
1130 cpuid++;
1131
1132#ifdef DEBUG_PROM
1133 prom_print_nl();
1134 prom_print(RELOC("cpuid = 0x"));
1135 prom_print_hex(cpuid);
1136 prom_print_nl();
1137 prom_print(RELOC("cpu hw idx = 0x"));
1138 prom_print_hex(reg);
1139 prom_print_nl();
1140#endif
1141 _xPaca[cpuid].xHwProcNum = reg;
1142
1143 prom_print(RELOC("starting cpu "));
1144 prom_print(path);
1145
1146
1147
1148
1149
1150 *acknowledge = (unsigned long)-1;
1151
1152#ifdef DEBUG_PROM
1153 prom_print(RELOC(" 3) spinloop = 0x"));
1154 prom_print_hex(spinloop);
1155 prom_print_nl();
1156 prom_print(RELOC(" 3) *spinloop = 0x"));
1157 prom_print_hex(*spinloop);
1158 prom_print_nl();
1159 prom_print(RELOC(" 3) acknowledge = 0x"));
1160 prom_print_hex(acknowledge);
1161 prom_print_nl();
1162 prom_print(RELOC(" 3) *acknowledge = 0x"));
1163 prom_print_hex(*acknowledge);
1164 prom_print_nl();
1165 prom_print(RELOC(" 3) secondary_hold = 0x"));
1166 prom_print_hex(secondary_hold);
1167 prom_print_nl();
1168 prom_print(RELOC(" 3) cpuid = 0x"));
1169 prom_print_hex(cpuid);
1170 prom_print_nl();
1171#endif
1172 call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid);
1173 prom_print(RELOC("..."));
1174 for ( i = 0 ; (i < 100000000) &&
1175 (*acknowledge == ((unsigned long)-1)); i++ ) ;
1176#ifdef DEBUG_PROM
1177 {
1178 unsigned long *p = 0x0;
1179 prom_print(RELOC(" 4) 0x0 = 0x"));
1180 prom_print_hex(*p);
1181 prom_print_nl();
1182 }
1183#endif
1184 if (*acknowledge == cpuid) {
1185 prom_print(RELOC("ok\n"));
1186
1187 _systemcfg->processorCount++;
1188 } else {
1189 prom_print(RELOC("failed: "));
1190 prom_print_hex(*acknowledge);
1191 prom_print_nl();
1192 }
1193 }
1194#ifdef CONFIG_HMT
1195
1196 if (__is_processor(PV_PULSAR) ||
1197 __is_processor(PV_ICESTAR) ||
1198 __is_processor(PV_SSTAR)) {
1199 prom_print(RELOC(" starting secondary threads\n"));
1200
1201 for (i=0; i < _systemcfg->processorCount ;i++) {
1202 unsigned long threadid = _systemcfg->processorCount*2-1-i;
1203
1204 if (i == 0) {
1205 unsigned long pir = _get_PIR();
1206 if (__is_processor(PV_PULSAR)) {
1207 RELOC(hmt_thread_data)[i].pir =
1208 pir & 0x1f;
1209 } else {
1210 RELOC(hmt_thread_data)[i].pir =
1211 pir & 0x3ff;
1212 }
1213 }
1214
1215 RELOC(hmt_thread_data)[i].threadid = threadid;
1216#ifdef DEBUG_PROM
1217 prom_print(RELOC(" cpuid 0x"));
1218 prom_print_hex(i);
1219 prom_print(RELOC(" maps to threadid 0x"));
1220 prom_print_hex(threadid);
1221 prom_print_nl();
1222 prom_print(RELOC(" pir 0x"));
1223 prom_print_hex(RELOC(hmt_thread_data)[i].pir);
1224 prom_print_nl();
1225#endif
1226 _xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1;
1227 }
1228 _systemcfg->processorCount *= 2;
1229 } else {
1230 prom_print(RELOC("Processor is not HMT capable\n"));
1231 }
1232#endif
1233
1234#ifdef DEBUG_PROM
1235 prom_print(RELOC("prom_hold_cpus: end...\n"));
1236#endif
1237}
1238
1239#ifdef CONFIG_PPCDBG
1240extern char *trace_names[];
1241
1242void parse_ppcdbg_optionlist(const char *cmd,
1243 const char *cmdend)
1244{
1245 unsigned long offset = reloc_offset();
1246 char **_trace_names = PTRRELOC(&trace_names[0]);
1247 const char *all = RELOC("all");
1248 struct naca_struct *_naca = RELOC(naca);
1249 const char *p, *pend;
1250 int onoff, i, cmdidx;
1251 unsigned long mask;
1252 char cmdbuf[30];
1253
1254 for (p = cmd, pend = strchr(p, ',');
1255 p < cmdend;
1256 pend = strchr(p, ',')) {
1257 if (pend == NULL || pend > cmdend)
1258 pend = cmdend;
1259 onoff = 1;
1260 if (*p == '+' || *p == '-') {
1261
1262 onoff = (*p == '+');
1263 p++;
1264 }
1265
1266 if (pend - p < sizeof(cmdbuf)) {
1267 strncpy(cmdbuf, p, pend - p);
1268 cmdbuf[pend - p] = '\0';
1269 for (cmdidx = -1, i = 0; i < PPCDBG_NUM_FLAGS; i++) {
1270 if (_trace_names[i] &&
1271 (strcmp(PTRRELOC(_trace_names[i]), cmdbuf) == 0)) {
1272 cmdidx = i;
1273 break;
1274 }
1275 }
1276 mask = 0;
1277 if (cmdidx >= 0) {
1278 mask = (1 << cmdidx);
1279 } else if (strcmp(cmdbuf, all) == 0) {
1280 mask = PPCDBG_ALL;
1281 } else {
1282 prom_print(RELOC("ppcdbg: unknown debug: "));
1283 prom_print(cmdbuf);
1284 prom_print_nl();
1285 }
1286 if (mask) {
1287 if (onoff)
1288 _naca->debug_switch |= mask;
1289 else
1290 _naca->debug_switch &= ~mask;
1291 }
1292 }
1293 p = pend+1;
1294 }
1295}
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312void parse_ppcdbg_cmd_line(const char *line)
1313{
1314 unsigned long offset = reloc_offset();
1315 const char *ppcdbgopt = RELOC("ppcdbg=");
1316 struct naca_struct *_naca = RELOC(naca);
1317 const char *cmd, *end;
1318
1319 _naca->debug_switch = PPC_DEBUG_DEFAULT;
1320 cmd = line;
1321 while (cmd && (cmd = strstr(cmd, ppcdbgopt)) != NULL) {
1322 cmd += 7;
1323 for (end = cmd;
1324 *end != '\0' && *end != '\t' && *end != ' ';
1325 end++)
1326 ;
1327 parse_ppcdbg_optionlist(cmd, end);
1328 }
1329}
1330#endif
1331
1332
1333
1334
1335
1336static void __init
1337prom_parse_cmd_line(char *line)
1338{
1339#ifdef CONFIG_PPCDBG
1340 parse_ppcdbg_cmd_line(line);
1341#endif
1342}
1343
1344
1345
1346
1347
1348
1349unsigned long __init
1350prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
1351 unsigned long r6, unsigned long r7, yaboot_debug_t *yaboot)
1352{
1353 int chrp = 0;
1354 unsigned long mem;
1355 ihandle prom_mmu, prom_op, prom_root, prom_cpu;
1356 phandle cpu_pkg;
1357 unsigned long offset = reloc_offset();
1358 long l, sz;
1359 char *p, *d;
1360 unsigned long phys;
1361 u32 getprop_rval;
1362 struct naca_struct *_naca = RELOC(naca);
1363 struct systemcfg *_systemcfg = RELOC(systemcfg);
1364 struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
1365 struct prom_t *_prom = PTRRELOC(&prom);
1366 char *_cmd_line = PTRRELOC(&cmd_line[0]);
1367
1368
1369 _systemcfg->platform = PLATFORM_PSERIES;
1370
1371 if (RELOC(embedded_sysmap_end))
1372 RELOC(klimit) = __va(PAGE_ALIGN(RELOC(embedded_sysmap_end)));
1373
1374
1375 _prom->entry = pp;
1376 _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
1377 if ( _prom->bi_recs != NULL ) {
1378 RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]);
1379 }
1380
1381#ifdef DEBUG_YABOOT
1382 call_yaboot(yaboot->dummy,offset>>32,offset&0xffffffff);
1383 call_yaboot(yaboot->printf, RELOC("offset = 0x%08x%08x\n"), LONG_MSW(offset), LONG_LSW(offset));
1384#endif
1385
1386
1387 phys = KERNELBASE - offset;
1388
1389#ifdef DEBUG_YABOOT
1390 call_yaboot(yaboot->printf, RELOC("phys = 0x%08x%08x\n"), LONG_MSW(phys), LONG_LSW(phys));
1391#endif
1392
1393
1394#ifdef DEBUG_YABOOT
1395 _prom->yaboot = yaboot;
1396 call_yaboot(yaboot->printf, RELOC("pp = 0x%08x%08x\n"), LONG_MSW(pp), LONG_LSW(pp));
1397 call_yaboot(yaboot->printf, RELOC("prom = 0x%08x%08x\n"), LONG_MSW(_prom->entry), LONG_LSW(_prom->entry));
1398#endif
1399
1400
1401 _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1,
1402 RELOC("/chosen"));
1403
1404#ifdef DEBUG_YABOOT
1405 call_yaboot(yaboot->printf, RELOC("prom->chosen = 0x%08x%08x\n"), LONG_MSW(_prom->chosen), LONG_LSW(_prom->chosen));
1406#endif
1407
1408 if ((long)_prom->chosen <= 0)
1409 prom_exit();
1410
1411 if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1412 RELOC("stdout"), &getprop_rval,
1413 sizeof(getprop_rval)) <= 0)
1414 prom_exit();
1415
1416 _prom->stdout = (ihandle)(unsigned long)getprop_rval;
1417
1418#ifdef DEBUG_YABOOT
1419 if (_prom->stdout == 0) {
1420 call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout));
1421 }
1422
1423 call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout));
1424#endif
1425
1426#ifdef DEBUG_YABOOT
1427 call_yaboot(yaboot->printf, RELOC("Location: 0x11\n"));
1428#endif
1429
1430 mem = RELOC(klimit) - offset;
1431#ifdef DEBUG_YABOOT
1432 call_yaboot(yaboot->printf, RELOC("Location: 0x11b\n"));
1433#endif
1434
1435
1436 p = (char *) mem;
1437 memset(p, 0, 256);
1438 call_prom(RELOC("instance-to-path"), 3, 1, _prom->stdout, p, 255);
1439 RELOC(of_stdout_device) = PTRUNRELOC(p);
1440 mem += strlen(p) + 1;
1441
1442 getprop_rval = 1;
1443 prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
1444 if (prom_root != (ihandle)-1) {
1445 call_prom(RELOC("getprop"), 4, 1,
1446 prom_root, RELOC("#size-cells"),
1447 &getprop_rval, sizeof(getprop_rval));
1448 }
1449 _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64;
1450
1451
1452 sz = (long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1453 RELOC("bootargs"), _cmd_line,
1454 sizeof(cmd_line)-1);
1455 if (sz > 0)
1456 _cmd_line[sz] = '\0';
1457 if (sz <=1 )
1458 strcpy(_cmd_line,RELOC(CONFIG_CMDLINE));
1459
1460 prom_parse_cmd_line(_cmd_line);
1461
1462#ifdef DEBUG_PROM
1463 prom_print(RELOC("DRENG: Detect OF version...\n"));
1464#endif
1465
1466 prom_op = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom"));
1467 if (prom_op != (ihandle)-1) {
1468 char model[64];
1469 sz = (long)call_prom(RELOC("getprop"), 4, 1, prom_op,
1470 RELOC("model"), model, 64);
1471 if (sz > 0) {
1472 char *c;
1473
1474 if ( strncmp(model,RELOC("IBM"),3) ) {
1475 for (c = model; *c; c++)
1476 if (*c >= '0' && *c <= '9') {
1477 _prom->version = *c - '0';
1478 break;
1479 }
1480 }
1481 else
1482 chrp = 1;
1483 }
1484 }
1485 if (_prom->version >= 3)
1486 prom_print(RELOC("OF Version 3 detected.\n"));
1487
1488
1489
1490 if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1491 RELOC("cpu"), &getprop_rval,
1492 sizeof(getprop_rval)) <= 0)
1493 prom_exit();
1494
1495 prom_cpu = (ihandle)(unsigned long)getprop_rval;
1496 cpu_pkg = call_prom(RELOC("instance-to-package"), 1, 1, prom_cpu);
1497 call_prom(RELOC("getprop"), 4, 1,
1498 cpu_pkg, RELOC("reg"),
1499 &getprop_rval, sizeof(getprop_rval));
1500 _prom->cpu = (int)(unsigned long)getprop_rval;
1501 _xPaca[0].xHwProcNum = _prom->cpu;
1502
1503#ifdef DEBUG_PROM
1504 prom_print(RELOC("Booting CPU hw index = 0x"));
1505 prom_print_hex(_prom->cpu);
1506 prom_print_nl();
1507#endif
1508
1509
1510 p = (char *) mem;
1511 l = (long) call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1512 RELOC("bootpath"), p, 1<<20);
1513 if (l > 0) {
1514 p[l] = 0;
1515 RELOC(bootpath) = PTRUNRELOC(p);
1516 mem += l + 1;
1517 d = (char *) mem;
1518 *d = 0;
1519 call_prom(RELOC("canon"), 3, 1, p, d, 1<<20);
1520 RELOC(bootdevice) = PTRUNRELOC(d);
1521 mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
1522 }
1523
1524 mem = prom_initialize_lmb(mem);
1525
1526 mem = prom_bi_rec_reserve(mem);
1527
1528 mem = check_display(mem);
1529
1530 prom_instantiate_rtas();
1531
1532
1533 mem = prom_initialize_naca(mem);
1534
1535
1536
1537
1538
1539 if (_systemcfg->processorCount > 1)
1540 prom_hold_cpus(mem);
1541
1542#ifdef DEBUG_PROM
1543 prom_print(RELOC("copying OF device tree...\n"));
1544#endif
1545 mem = copy_device_tree(mem);
1546
1547 RELOC(klimit) = mem + offset;
1548
1549 lmb_reserve(0, __pa(RELOC(klimit)));
1550
1551 if (_systemcfg->platform == PLATFORM_PSERIES)
1552 prom_initialize_tce_table();
1553
1554 if ((long) call_prom(RELOC("getprop"), 4, 1,
1555 _prom->chosen,
1556 RELOC("mmu"),
1557 &getprop_rval,
1558 sizeof(getprop_rval)) <= 0) {
1559 prom_print(RELOC(" no MMU found\n"));
1560 prom_exit();
1561 }
1562
1563
1564 prom_mmu = (ihandle)(unsigned long)getprop_rval;
1565
1566 if ((long)call_prom(RELOC("call-method"), 4, 4,
1567 RELOC("translate"),
1568 prom_mmu,
1569 (void *)(KERNELBASE - offset),
1570 (void *)1) != 0) {
1571 prom_print(RELOC(" (translate failed) "));
1572 } else {
1573 prom_print(RELOC(" (translate ok) "));
1574 phys = (unsigned long)_prom->args.rets[3];
1575 }
1576
1577
1578 if (_prom->version >= 3) {
1579 prom_print(RELOC("Calling quiesce ...\n"));
1580 call_prom(RELOC("quiesce"), 0, 0);
1581 phys = KERNELBASE - offset;
1582 }
1583
1584 prom_print(RELOC("returning from prom_init\n"));
1585 return phys;
1586}
1587
1588
1589static int
1590prom_set_color(ihandle ih, int i, int r, int g, int b)
1591{
1592 unsigned long offset = reloc_offset();
1593
1594 return (int)(long)call_prom(RELOC("call-method"), 6, 1,
1595 RELOC("color!"),
1596 ih,
1597 (void *)(long) i,
1598 (void *)(long) b,
1599 (void *)(long) g,
1600 (void *)(long) r );
1601}
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611static unsigned long __init
1612check_display(unsigned long mem)
1613{
1614 phandle node;
1615 ihandle ih;
1616 int i;
1617 unsigned long offset = reloc_offset();
1618 struct prom_t *_prom = PTRRELOC(&prom);
1619 char type[64], *path;
1620 static unsigned char default_colors[] = {
1621 0x00, 0x00, 0x00,
1622 0x00, 0x00, 0xaa,
1623 0x00, 0xaa, 0x00,
1624 0x00, 0xaa, 0xaa,
1625 0xaa, 0x00, 0x00,
1626 0xaa, 0x00, 0xaa,
1627 0xaa, 0xaa, 0x00,
1628 0xaa, 0xaa, 0xaa,
1629 0x55, 0x55, 0x55,
1630 0x55, 0x55, 0xff,
1631 0x55, 0xff, 0x55,
1632 0x55, 0xff, 0xff,
1633 0xff, 0x55, 0x55,
1634 0xff, 0x55, 0xff,
1635 0xff, 0xff, 0x55,
1636 0xff, 0xff, 0xff
1637 };
1638
1639 _prom->disp_node = 0;
1640
1641 for (node = 0; prom_next_node(&node); ) {
1642 type[0] = 0;
1643 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
1644 type, sizeof(type));
1645 if (strcmp(type, RELOC("display")) != 0)
1646 continue;
1647
1648 path = (char *) mem;
1649 memset(path, 0, 256);
1650 if ((long) call_prom(RELOC("package-to-path"), 3, 1,
1651 node, path, 255) < 0)
1652 continue;
1653 prom_print(RELOC("opening display "));
1654 prom_print(path);
1655 ih = (ihandle)call_prom(RELOC("open"), 1, 1, path);
1656 if (ih == (ihandle)0 || ih == (ihandle)-1) {
1657 prom_print(RELOC("... failed\n"));
1658 continue;
1659 }
1660 prom_print(RELOC("... ok\n"));
1661
1662 if (_prom->disp_node == 0)
1663 _prom->disp_node = (ihandle)(unsigned long)node;
1664
1665
1666
1667 for (i = 0; i < 32; i++)
1668 if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
1669 RELOC(default_colors)[i*3+1],
1670 RELOC(default_colors)[i*3+2]) != 0)
1671 break;
1672
1673#ifdef CONFIG_FB
1674 for (i = 0; i < LINUX_LOGO_COLORS; i++)
1675 if (prom_set_color(ih, i + 32,
1676 RELOC(linux_logo_red)[i],
1677 RELOC(linux_logo_green)[i],
1678 RELOC(linux_logo_blue)[i]) != 0)
1679 break;
1680#endif
1681
1682
1683
1684
1685
1686 mem += strlen(path) + 1;
1687 i = RELOC(prom_num_displays)++;
1688 if (RELOC(of_stdout_device) != 0 && i > 0
1689 && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
1690 for (; i > 0; --i)
1691 RELOC(prom_display_paths[i]) = RELOC(prom_display_paths[i-1]);
1692 }
1693 RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
1694 if (RELOC(prom_num_displays) >= FB_MAX)
1695 break;
1696 }
1697 return DOUBLEWORD_ALIGN(mem);
1698}
1699
1700void
1701virt_irq_init(void)
1702{
1703 int i;
1704 for (i = 0; i < NR_IRQS; i++)
1705 virt_irq_to_real_map[i] = UNDEFINED_IRQ;
1706 for (i = 0; i < NR_HW_IRQS; i++)
1707 real_irq_to_virt_map[i] = UNDEFINED_IRQ;
1708}
1709
1710
1711
1712
1713unsigned long
1714virt_irq_create_mapping(unsigned long real_irq)
1715{
1716 unsigned long virq;
1717 if (naca->interrupt_controller == IC_OPEN_PIC)
1718 return real_irq;
1719 virq = real_irq_to_virt(real_irq);
1720 if (virq == UNDEFINED_IRQ) {
1721
1722 if (real_irq < NR_IRQS && virt_irq_to_real(real_irq) == UNDEFINED_IRQ) {
1723
1724 virq = real_irq;
1725 } else {
1726 while (last_virt_irq < NR_IRQS &&
1727 virt_irq_to_real(++last_virt_irq) != UNDEFINED_IRQ)
1728 ;
1729 if (last_virt_irq >= NR_IRQS)
1730 panic("Too many IRQs are required on this system. NR_IRQS=%d\n", NR_IRQS);
1731 virq = last_virt_irq;
1732 }
1733 virt_irq_to_real_map[virq] = real_irq;
1734 real_irq_to_virt_map[real_irq] = virq;
1735 }
1736 return virq;
1737}
1738
1739
1740static int __init
1741prom_next_node(phandle *nodep)
1742{
1743 phandle node;
1744 unsigned long offset = reloc_offset();
1745
1746 if ((node = *nodep) != 0
1747 && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)
1748 return 1;
1749 if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
1750 return 1;
1751 for (;;) {
1752 if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)
1753 return 0;
1754 if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
1755 return 1;
1756 }
1757}
1758
1759
1760
1761
1762static unsigned long __init
1763copy_device_tree(unsigned long mem_start)
1764{
1765 phandle root;
1766 unsigned long new_start;
1767 struct device_node **allnextp;
1768 unsigned long offset = reloc_offset();
1769 unsigned long mem_end = mem_start + (8<<20);
1770
1771 root = call_prom(RELOC("peer"), 1, 1, (phandle)0);
1772 if (root == (phandle)0) {
1773 prom_print(RELOC("couldn't get device tree root\n"));
1774 prom_exit();
1775 }
1776 allnextp = &RELOC(allnodes);
1777 mem_start = DOUBLEWORD_ALIGN(mem_start);
1778 new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
1779 *allnextp = 0;
1780 return new_start;
1781}
1782
1783__init
1784static unsigned long
1785inspect_node(phandle node, struct device_node *dad,
1786 unsigned long mem_start, unsigned long mem_end,
1787 struct device_node ***allnextpp)
1788{
1789 int l;
1790 phandle child;
1791 struct device_node *np;
1792 struct property *pp, **prev_propp;
1793 char *prev_name, *namep;
1794 unsigned char *valp;
1795 unsigned long offset = reloc_offset();
1796
1797 np = (struct device_node *) mem_start;
1798 mem_start += sizeof(struct device_node);
1799 memset(np, 0, sizeof(*np));
1800 np->node = node;
1801 **allnextpp = PTRUNRELOC(np);
1802 *allnextpp = &np->allnext;
1803 if (dad != 0) {
1804 np->parent = PTRUNRELOC(dad);
1805
1806 if (dad->next == 0)
1807 dad->child = PTRUNRELOC(np);
1808 else
1809 dad->next->sibling = PTRUNRELOC(np);
1810 dad->next = np;
1811 }
1812
1813
1814 prev_propp = &np->properties;
1815 prev_name = RELOC("");
1816 for (;;) {
1817 pp = (struct property *) mem_start;
1818 namep = (char *) (pp + 1);
1819 pp->name = PTRUNRELOC(namep);
1820 if ((long) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,
1821 namep) <= 0)
1822 break;
1823 mem_start = DOUBLEWORD_ALIGN((unsigned long)namep + strlen(namep) + 1);
1824 prev_name = namep;
1825 valp = (unsigned char *) mem_start;
1826 pp->value = PTRUNRELOC(valp);
1827 pp->length = (int)(long)
1828 call_prom(RELOC("getprop"), 4, 1, node, namep,
1829 valp, mem_end - mem_start);
1830 if (pp->length < 0)
1831 continue;
1832 mem_start = DOUBLEWORD_ALIGN(mem_start + pp->length);
1833 *prev_propp = PTRUNRELOC(pp);
1834 prev_propp = &pp->next;
1835 }
1836 *prev_propp = 0;
1837
1838
1839 l = (long) call_prom(RELOC("package-to-path"), 3, 1, node,
1840 (char *) mem_start, mem_end - mem_start);
1841 if (l >= 0) {
1842 np->full_name = PTRUNRELOC((char *) mem_start);
1843 *(char *)(mem_start + l) = 0;
1844 mem_start = DOUBLEWORD_ALIGN(mem_start + l + 1);
1845 }
1846
1847
1848 child = call_prom(RELOC("child"), 1, 1, node);
1849 while (child != (phandle)0) {
1850 mem_start = inspect_node(child, np, mem_start, mem_end,
1851 allnextpp);
1852 child = call_prom(RELOC("peer"), 1, 1, child);
1853 }
1854
1855 return mem_start;
1856}
1857
1858
1859
1860
1861
1862
1863
1864void __init
1865finish_device_tree(void)
1866{
1867 unsigned long mem = klimit;
1868
1869 virt_irq_init();
1870
1871 mem = finish_node(allnodes, mem, NULL, 0, 0);
1872 dev_tree_size = mem - (unsigned long) allnodes;
1873
1874 mem = _ALIGN(mem, PAGE_SIZE);
1875 lmb_reserve(__pa(klimit), mem-klimit);
1876
1877 klimit = mem;
1878
1879 rtas.dev = find_devices("rtas");
1880}
1881
1882static unsigned long __init
1883finish_node(struct device_node *np, unsigned long mem_start,
1884 interpret_func *ifunc, int naddrc, int nsizec)
1885{
1886 struct device_node *child;
1887 int *ip;
1888
1889 np->name = get_property(np, "name", 0);
1890 np->type = get_property(np, "device_type", 0);
1891
1892
1893 if (ifunc != NULL) {
1894 mem_start = ifunc(np, mem_start, naddrc, nsizec);
1895 }
1896 mem_start = finish_node_interrupts(np, mem_start);
1897
1898
1899 ip = (int *) get_property(np, "#address-cells", 0);
1900 if (ip != NULL)
1901 naddrc = *ip;
1902 ip = (int *) get_property(np, "#size-cells", 0);
1903 if (ip != NULL)
1904 nsizec = *ip;
1905
1906
1907
1908
1909 ifunc = NULL;
1910 if (!strcmp(np->name, "display"))
1911 np->name = get_property(np, "compatible", 0);
1912
1913 if (!strcmp(np->name, "device-tree") || np->parent == NULL)
1914 ifunc = interpret_root_props;
1915 else if (np->type == 0)
1916 ifunc = NULL;
1917 else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
1918 ifunc = interpret_pci_props;
1919 else if (!strcmp(np->type, "isa"))
1920 ifunc = interpret_isa_props;
1921
1922 for (child = np->child; child != NULL; child = child->sibling)
1923 mem_start = finish_node(child, mem_start, ifunc,
1924 naddrc, nsizec);
1925
1926 return mem_start;
1927}
1928
1929
1930
1931
1932
1933
1934__init
1935static unsigned long
1936finish_node_interrupts(struct device_node *np, unsigned long mem_start)
1937{
1938
1939 unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;
1940 phandle *parent, map_parent;
1941 struct device_node *node, *parent_node;
1942 int l, isize, ipsize, asize, map_size, regpsize;
1943
1944
1945
1946 interrupts = (unsigned int *)get_property(np, "interrupts", &l);
1947 if (interrupts == NULL)
1948 return mem_start;
1949 ipsize = l>>2;
1950
1951 reg = (unsigned int *)get_property(np, "reg", &l);
1952 regpsize = l>>2;
1953
1954
1955 isize = 1;
1956 node = np;
1957
1958 do {
1959
1960
1961 isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);
1962 if (isizep)
1963 isize = *isizep;
1964
1965
1966
1967
1968 if (get_property(node, "interrupt-controller", &l)) {
1969 int i,j;
1970
1971 np->intrs = (struct interrupt_info *) mem_start;
1972 np->n_intrs = ipsize / isize;
1973 mem_start += np->n_intrs * sizeof(struct interrupt_info);
1974 for (i = 0; i < np->n_intrs; ++i) {
1975 np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(*interrupts++));
1976 np->intrs[i].sense = 1;
1977 if (isize > 1)
1978 np->intrs[i].sense = *interrupts++;
1979 for (j=2; j<isize; j++)
1980 interrupts++;
1981 }
1982 return mem_start;
1983 }
1984
1985
1986
1987
1988
1989 if (np != node)
1990 map = (unsigned int *)get_property(node, "interrupt-map", &l);
1991 else
1992 map = NULL;
1993 if (map && l) {
1994 int i, found, temp_isize, temp_asize;
1995 map_size = l>>2;
1996 map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
1997 asizep = (unsigned int *)get_property(node, "#address-cells", &l);
1998 if (asizep && l == sizeof(unsigned int))
1999 asize = *asizep;
2000 else
2001 asize = 0;
2002 found = 0;
2003 while (map_size>0 && !found) {
2004 found = 1;
2005 for (i=0; i<asize; i++) {
2006 unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;
2007 if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))
2008 found = 0;
2009 map++;
2010 map_size--;
2011 }
2012 for (i=0; i<isize; i++) {
2013 unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;
2014 if ((mask & *map) != (mask & interrupts[i]))
2015 found = 0;
2016 map++;
2017 map_size--;
2018 }
2019 map_parent = *((phandle *)map);
2020 map+=1; map_size-=1;
2021 parent_node = find_phandle(map_parent);
2022 temp_isize = isize;
2023 temp_asize = 0;
2024 if (parent_node) {
2025 isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
2026 if (isizep)
2027 temp_isize = *isizep;
2028 asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l);
2029 if (asizep && l == sizeof(unsigned int))
2030 temp_asize = *asizep;
2031 }
2032 if (!found) {
2033 map += temp_isize + temp_asize;
2034 map_size -= temp_isize + temp_asize;
2035 }
2036 }
2037 if (found) {
2038
2039
2040
2041 node = parent_node;
2042 reg = map;
2043 regpsize = temp_asize;
2044 interrupts = map + temp_asize;
2045 ipsize = temp_isize;
2046 continue;
2047 }
2048 }
2049
2050
2051 parent = (phandle *)get_property(node, "interrupt-parent", &l);
2052 if (parent && (l == sizeof(phandle)) &&
2053 (parent_node = find_phandle(*parent))) {
2054 node = parent_node;
2055 continue;
2056 }
2057
2058 node = node->parent;
2059 } while (node);
2060
2061 return mem_start;
2062}
2063
2064int
2065prom_n_addr_cells(struct device_node* np)
2066{
2067 int* ip;
2068 do {
2069 if (np->parent)
2070 np = np->parent;
2071 ip = (int *) get_property(np, "#address-cells", 0);
2072 if (ip != NULL)
2073 return *ip;
2074 } while (np->parent);
2075
2076 return 1;
2077}
2078
2079int
2080prom_n_size_cells(struct device_node* np)
2081{
2082 int* ip;
2083 do {
2084 if (np->parent)
2085 np = np->parent;
2086 ip = (int *) get_property(np, "#size-cells", 0);
2087 if (ip != NULL)
2088 return *ip;
2089 } while (np->parent);
2090
2091 return 1;
2092}
2093
2094static unsigned long __init
2095interpret_pci_props(struct device_node *np, unsigned long mem_start,
2096 int naddrc, int nsizec)
2097{
2098 struct address_range *adr;
2099 struct pci_reg_property *pci_addrs;
2100 int i, l;
2101
2102 pci_addrs = (struct pci_reg_property *)
2103 get_property(np, "assigned-addresses", &l);
2104 if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
2105 i = 0;
2106 adr = (struct address_range *) mem_start;
2107 while ((l -= sizeof(struct pci_reg_property)) >= 0) {
2108 adr[i].space = pci_addrs[i].addr.a_hi;
2109 adr[i].address = pci_addrs[i].addr.a_lo;
2110 adr[i].size = pci_addrs[i].size_lo;
2111 ++i;
2112 }
2113 np->addrs = adr;
2114 np->n_addrs = i;
2115 mem_start += i * sizeof(struct address_range);
2116 }
2117 return mem_start;
2118}
2119
2120static unsigned long __init
2121interpret_isa_props(struct device_node *np, unsigned long mem_start,
2122 int naddrc, int nsizec)
2123{
2124 struct isa_reg_property *rp;
2125 struct address_range *adr;
2126 int i, l;
2127
2128 rp = (struct isa_reg_property *) get_property(np, "reg", &l);
2129 if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
2130 i = 0;
2131 adr = (struct address_range *) mem_start;
2132 while ((l -= sizeof(struct reg_property)) >= 0) {
2133 adr[i].space = rp[i].space;
2134 adr[i].address = rp[i].address
2135 + (adr[i].space? 0: _ISA_MEM_BASE);
2136 adr[i].size = rp[i].size;
2137 ++i;
2138 }
2139 np->addrs = adr;
2140 np->n_addrs = i;
2141 mem_start += i * sizeof(struct address_range);
2142 }
2143
2144 return mem_start;
2145}
2146
2147static unsigned long __init
2148interpret_root_props(struct device_node *np, unsigned long mem_start,
2149 int naddrc, int nsizec)
2150{
2151 struct address_range *adr;
2152 int i, l;
2153 unsigned int *rp;
2154 int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
2155
2156 rp = (unsigned int *) get_property(np, "reg", &l);
2157 if (rp != 0 && l >= rpsize) {
2158 i = 0;
2159 adr = (struct address_range *) mem_start;
2160 while ((l -= rpsize) >= 0) {
2161 adr[i].space = 0;
2162 adr[i].address = rp[naddrc - 1];
2163 adr[i].size = rp[naddrc + nsizec - 1];
2164 ++i;
2165 rp += naddrc + nsizec;
2166 }
2167 np->addrs = adr;
2168 np->n_addrs = i;
2169 mem_start += i * sizeof(struct address_range);
2170 }
2171
2172 return mem_start;
2173}
2174
2175
2176
2177
2178
2179void __init
2180prom_get_irq_senses(unsigned char *senses, int off, int max)
2181{
2182 struct device_node *np;
2183 int i, j;
2184
2185
2186 memset(senses, 1, max - off);
2187
2188 for (np = allnodes; np != 0; np = np->allnext) {
2189 for (j = 0; j < np->n_intrs; j++) {
2190 i = np->intrs[j].line;
2191 if (i >= off && i < max)
2192 senses[i-off] = np->intrs[j].sense;
2193 }
2194 }
2195}
2196
2197
2198
2199
2200struct device_node *
2201find_devices(const char *name)
2202{
2203 struct device_node *head, **prevp, *np;
2204
2205 prevp = &head;
2206 for (np = allnodes; np != 0; np = np->allnext) {
2207 if (np->name != 0 && strcasecmp(np->name, name) == 0) {
2208 *prevp = np;
2209 prevp = &np->next;
2210 }
2211 }
2212 *prevp = 0;
2213 return head;
2214}
2215
2216
2217
2218
2219struct device_node *
2220find_type_devices(const char *type)
2221{
2222 struct device_node *head, **prevp, *np;
2223
2224 prevp = &head;
2225 for (np = allnodes; np != 0; np = np->allnext) {
2226 if (np->type != 0 && strcasecmp(np->type, type) == 0) {
2227 *prevp = np;
2228 prevp = &np->next;
2229 }
2230 }
2231 *prevp = 0;
2232 return head;
2233}
2234
2235
2236
2237
2238struct device_node * __openfirmware
2239find_all_nodes(void)
2240{
2241 struct device_node *head, **prevp, *np;
2242
2243 prevp = &head;
2244 for (np = allnodes; np != 0; np = np->allnext) {
2245 *prevp = np;
2246 prevp = &np->next;
2247 }
2248 *prevp = 0;
2249 return head;
2250}
2251
2252
2253
2254
2255int
2256device_is_compatible(struct device_node *device, const char *compat)
2257{
2258 const char* cp;
2259 int cplen, l;
2260
2261 cp = (char *) get_property(device, "compatible", &cplen);
2262 if (cp == NULL)
2263 return 0;
2264 while (cplen > 0) {
2265 if (strncasecmp(cp, compat, strlen(compat)) == 0)
2266 return 1;
2267 l = strlen(cp) + 1;
2268 cp += l;
2269 cplen -= l;
2270 }
2271
2272 return 0;
2273}
2274
2275
2276
2277
2278
2279
2280int
2281machine_is_compatible(const char *compat)
2282{
2283 struct device_node *root;
2284
2285 root = find_path_device("/");
2286 if (root == 0)
2287 return 0;
2288 return device_is_compatible(root, compat);
2289}
2290
2291
2292
2293
2294
2295struct device_node *
2296find_compatible_devices(const char *type, const char *compat)
2297{
2298 struct device_node *head, **prevp, *np;
2299
2300 prevp = &head;
2301 for (np = allnodes; np != 0; np = np->allnext) {
2302 if (type != NULL
2303 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
2304 continue;
2305 if (device_is_compatible(np, compat)) {
2306 *prevp = np;
2307 prevp = &np->next;
2308 }
2309 }
2310 *prevp = 0;
2311 return head;
2312}
2313
2314
2315
2316
2317struct device_node *
2318find_path_device(const char *path)
2319{
2320 struct device_node *np;
2321
2322 for (np = allnodes; np != 0; np = np->allnext)
2323 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
2324 return np;
2325 return NULL;
2326}
2327
2328
2329
2330
2331static struct device_node * __init
2332find_phandle(phandle ph)
2333{
2334 struct device_node *np;
2335
2336 for (np = allnodes; np != 0; np = np->allnext)
2337 if (np->node == ph)
2338 return np;
2339 return NULL;
2340}
2341
2342
2343
2344
2345
2346unsigned char *
2347get_property(struct device_node *np, const char *name, int *lenp)
2348{
2349 struct property *pp;
2350
2351 for (pp = np->properties; pp != 0; pp = pp->next)
2352 if (strcmp(pp->name, name) == 0) {
2353 if (lenp != 0)
2354 *lenp = pp->length;
2355 return pp->value;
2356 }
2357 return 0;
2358}
2359
2360
2361
2362
2363void __openfirmware
2364prom_add_property(struct device_node* np, struct property* prop)
2365{
2366 struct property **next = &np->properties;
2367
2368 prop->next = NULL;
2369 while (*next)
2370 next = &(*next)->next;
2371 *next = prop;
2372}
2373
2374#if 0
2375void __openfirmware
2376print_properties(struct device_node *np)
2377{
2378 struct property *pp;
2379 char *cp;
2380 int i, n;
2381
2382 for (pp = np->properties; pp != 0; pp = pp->next) {
2383 printk(KERN_INFO "%s", pp->name);
2384 for (i = strlen(pp->name); i < 16; ++i)
2385 printk(" ");
2386 cp = (char *) pp->value;
2387 for (i = pp->length; i > 0; --i, ++cp)
2388 if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
2389 || (i == 1 && *cp != 0))
2390 break;
2391 if (i == 0 && pp->length > 1) {
2392
2393 printk(" %s\n", (char *) pp->value);
2394 } else {
2395
2396 n = pp->length;
2397 if (n > 64)
2398 n = 64;
2399 if (pp->length % 4 == 0) {
2400 unsigned int *p = (unsigned int *) pp->value;
2401
2402 n /= 4;
2403 for (i = 0; i < n; ++i) {
2404 if (i != 0 && (i % 4) == 0)
2405 printk("\n ");
2406 printk(" %08x", *p++);
2407 }
2408 } else {
2409 unsigned char *bp = pp->value;
2410
2411 for (i = 0; i < n; ++i) {
2412 if (i != 0 && (i % 16) == 0)
2413 printk("\n ");
2414 printk(" %02x", *bp++);
2415 }
2416 }
2417 printk("\n");
2418 if (pp->length > 64)
2419 printk(" ... (length = %d)\n",
2420 pp->length);
2421 }
2422 }
2423}
2424#endif
2425
2426
2427void __init
2428abort()
2429{
2430#ifdef CONFIG_XMON
2431 xmon(NULL);
2432#endif
2433 for (;;)
2434 prom_exit();
2435}
2436
2437
2438
2439static struct bi_record *
2440prom_bi_rec_verify(struct bi_record *bi_recs)
2441{
2442 struct bi_record *first, *last;
2443
2444 if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
2445 return NULL;
2446
2447 last = (struct bi_record *)bi_recs->data[0];
2448 if ( last == NULL || last->tag != BI_LAST )
2449 return NULL;
2450
2451 first = (struct bi_record *)last->data[0];
2452 if ( first == NULL || first != bi_recs )
2453 return NULL;
2454
2455 return bi_recs;
2456}
2457
2458static unsigned long
2459prom_bi_rec_reserve(unsigned long mem)
2460{
2461 unsigned long offset = reloc_offset();
2462 struct prom_t *_prom = PTRRELOC(&prom);
2463 struct bi_record *rec;
2464
2465 if ( _prom->bi_recs != NULL) {
2466
2467 for ( rec=_prom->bi_recs;
2468 rec->tag != BI_LAST;
2469 rec=bi_rec_next(rec) ) {
2470 switch (rec->tag) {
2471#ifdef CONFIG_BLK_DEV_INITRD
2472 case BI_INITRD:
2473 lmb_reserve(rec->data[0], rec->data[1]);
2474 break;
2475#endif
2476 }
2477 }
2478
2479
2480
2481
2482 _prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
2483 }
2484
2485 return mem;
2486}
2487
2488