OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ppc64/] [kernel/] [prom.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.