~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/SLOF/clients/net-snk/oflib/of.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * Copyright (c) 2004, 2008 IBM Corporation
 
3
 * All rights reserved.
 
4
 * This program and the accompanying materials
 
5
 * are made available under the terms of the BSD License
 
6
 * which accompanies this distribution, and is available at
 
7
 * http://www.opensource.org/licenses/bsd-license.php
 
8
 *
 
9
 * Contributors:
 
10
 *     IBM Corporation - initial implementation
 
11
 *****************************************************************************/
 
12
 
 
13
#include <stdint.h>
 
14
#include <of.h>
 
15
#include <rtas.h>
 
16
#include <string.h>
 
17
#include <libbootmsg.h>
 
18
#include <kernel.h>
 
19
 
 
20
extern void call_client_interface(of_arg_t *);
 
21
 
 
22
static int claim_rc = 0;
 
23
static void* client_start;
 
24
static size_t client_size;
 
25
 
 
26
static inline int
 
27
of_0_1(const char *serv)
 
28
{
 
29
        of_arg_t arg = {
 
30
                p32cast serv,
 
31
                0, 1,
 
32
                { 0 }
 
33
        };
 
34
 
 
35
        call_client_interface(&arg);
 
36
 
 
37
        return arg.args[0];
 
38
}
 
39
 
 
40
static inline void
 
41
of_1_0(const char *serv, int arg0)
 
42
{
 
43
        of_arg_t arg = {
 
44
                p32cast serv,
 
45
                1, 0,
 
46
                {arg0, 0}
 
47
        };
 
48
 
 
49
        call_client_interface(&arg);
 
50
}
 
51
 
 
52
static inline unsigned int
 
53
of_1_1(const char *serv, int arg0)
 
54
{
 
55
        of_arg_t arg = {
 
56
                p32cast serv,
 
57
                1, 1,
 
58
                {arg0, 0}
 
59
        };
 
60
 
 
61
        call_client_interface(&arg);
 
62
        return arg.args[1];
 
63
}
 
64
 
 
65
static inline unsigned int
 
66
of_1_2(const char *serv, int arg0, int *ret0)
 
67
{
 
68
        of_arg_t arg = {
 
69
                p32cast serv,
 
70
                1, 2,
 
71
                {arg0, 0, 0}
 
72
        };
 
73
 
 
74
        call_client_interface(&arg);
 
75
        *ret0 = arg.args[2];
 
76
        return arg.args[1];
 
77
}
 
78
 
 
79
static inline void
 
80
of_2_0(const char *serv, int arg0, int arg1)
 
81
{
 
82
        of_arg_t arg = {
 
83
                p32cast serv,
 
84
                2, 0,
 
85
                {arg0, arg1, 0}
 
86
        };
 
87
 
 
88
        call_client_interface(&arg);
 
89
}
 
90
 
 
91
static inline unsigned int
 
92
of_2_1(const char *serv, int arg0, int arg1)
 
93
{
 
94
        of_arg_t arg = {
 
95
                p32cast serv,
 
96
                2, 1,
 
97
                {arg0, arg1, 0}
 
98
        };
 
99
 
 
100
        call_client_interface(&arg);
 
101
        return arg.args[2];
 
102
}
 
103
 
 
104
static inline unsigned int
 
105
of_2_2(const char *serv, int arg0, int arg1, int *ret0)
 
106
{
 
107
        of_arg_t arg = {
 
108
                p32cast serv,
 
109
                2, 2,
 
110
                {arg0, arg1, 0, 0}
 
111
        };
 
112
 
 
113
        call_client_interface(&arg);
 
114
        *ret0 = arg.args[3];
 
115
        return arg.args[2];
 
116
}
 
117
 
 
118
static inline unsigned int
 
119
of_2_3(const char *serv, int arg0, int arg1, int *ret0, int *ret1)
 
120
{
 
121
        of_arg_t arg = {
 
122
                p32cast serv,
 
123
                2, 3,
 
124
                {arg0, arg1, 0, 0, 0}
 
125
        };
 
126
 
 
127
        call_client_interface(&arg);
 
128
        *ret0 = arg.args[3];
 
129
        *ret1 = arg.args[4];
 
130
        return arg.args[2];
 
131
}
 
132
 
 
133
static inline void
 
134
of_3_0(const char *serv, int arg0, int arg1, int arg2)
 
135
{
 
136
        of_arg_t arg = {
 
137
                p32cast serv,
 
138
                3, 0,
 
139
                {arg0, arg1, arg2, 0}
 
140
        };
 
141
 
 
142
        call_client_interface(&arg);
 
143
        return;
 
144
}
 
145
 
 
146
static inline unsigned int
 
147
of_3_1(const char *serv, int arg0, int arg1, int arg2)
 
148
{
 
149
        of_arg_t arg = {
 
150
                p32cast serv,
 
151
                3, 1,
 
152
                {arg0, arg1, arg2, 0}
 
153
        };
 
154
 
 
155
        call_client_interface(&arg);
 
156
        return arg.args[3];
 
157
}
 
158
 
 
159
static inline unsigned int
 
160
of_3_2(const char *serv, int arg0, int arg1, int arg2, int *ret0)
 
161
{
 
162
        of_arg_t arg = {
 
163
                p32cast serv,
 
164
                3, 2,
 
165
                {arg0, arg1, arg2, 0, 0}
 
166
        };
 
167
 
 
168
        call_client_interface(&arg);
 
169
        *ret0 = arg.args[4];
 
170
        return arg.args[3];
 
171
}
 
172
 
 
173
static inline unsigned int
 
174
of_3_3(const char *serv, int arg0, int arg1, int arg2, int *ret0, int *ret1)
 
175
{
 
176
        of_arg_t arg = {
 
177
                p32cast serv,
 
178
                3, 3,
 
179
                {arg0, arg1, arg2, 0, 0, 0}
 
180
        };
 
181
 
 
182
        call_client_interface(&arg);
 
183
        *ret0 = arg.args[4];
 
184
        *ret1 = arg.args[5];
 
185
        return arg.args[3];
 
186
}
 
187
 
 
188
static inline unsigned int
 
189
of_4_1(const char *serv, int arg0, int arg1, int arg2, int arg3)
 
190
{
 
191
        of_arg_t arg = {
 
192
                p32cast serv,
 
193
                4, 1,
 
194
                {arg0, arg1, arg2, arg3, 0}
 
195
        };
 
196
 
 
197
        call_client_interface(&arg);
 
198
        return arg.args[4];
 
199
}
 
200
 
 
201
int
 
202
of_test(const char *name)
 
203
{
 
204
        return (int) of_1_1("test", p32cast name);
 
205
}
 
206
 
 
207
int
 
208
of_interpret_1(void *s, void *ret)
 
209
{
 
210
        return of_1_2("interpret", p32cast s, ret);
 
211
}
 
212
 
 
213
void
 
214
of_close(ihandle_t ihandle)
 
215
{
 
216
        of_1_0("close", ihandle);
 
217
}
 
218
 
 
219
int
 
220
of_write(ihandle_t ihandle, void *s, int len)
 
221
{
 
222
        return of_3_1("write", ihandle, p32cast s, len);
 
223
}
 
224
 
 
225
int
 
226
of_read(ihandle_t ihandle, void *s, int len)
 
227
{
 
228
        return of_3_1("read", ihandle, p32cast s, len);
 
229
}
 
230
 
 
231
int
 
232
of_seek(ihandle_t ihandle, int poshi, int poslo)
 
233
{
 
234
        return of_3_1("seek", ihandle, poshi, poslo);
 
235
}
 
236
 
 
237
int
 
238
of_getprop(phandle_t phandle, const char *name, void *buf, int len)
 
239
{
 
240
        return of_4_1("getprop", phandle, p32cast name, p32cast buf, len);
 
241
}
 
242
 
 
243
phandle_t
 
244
of_peer(phandle_t phandle)
 
245
{
 
246
        return (phandle_t) of_1_1("peer", phandle);
 
247
}
 
248
 
 
249
phandle_t
 
250
of_child(phandle_t phandle)
 
251
{
 
252
        return (phandle_t) of_1_1("child", phandle);
 
253
}
 
254
 
 
255
phandle_t
 
256
of_parent(phandle_t phandle)
 
257
{
 
258
        return (phandle_t) of_1_1("parent", phandle);
 
259
}
 
260
 
 
261
phandle_t
 
262
of_instance_to_package(ihandle_t ihandle)
 
263
{
 
264
        return (phandle_t) of_1_1("instance-to-package", ihandle);
 
265
}
 
266
 
 
267
 
 
268
phandle_t
 
269
of_finddevice(const char *name)
 
270
{
 
271
        return (phandle_t) of_1_1("finddevice", p32cast name);
 
272
}
 
273
 
 
274
ihandle_t
 
275
of_open(const char *name)
 
276
{
 
277
        return (ihandle_t) of_1_1("open", p32cast name);
 
278
}
 
279
 
 
280
void *
 
281
of_claim(void *start, unsigned int size, unsigned int align)
 
282
{
 
283
        return(void *)(long)(size_t)of_3_1("claim", p32cast start, size, align);
 
284
}
 
285
 
 
286
void
 
287
of_release(void *start, unsigned int size)
 
288
{
 
289
        (void) of_2_0("release", p32cast start, size);
 
290
}
 
291
 
 
292
void *
 
293
of_call_method_3(const char *name, ihandle_t ihandle, int arg0)
 
294
{
 
295
        int entry, rc;
 
296
        rc = of_3_2("call-method", p32cast name, ihandle, arg0, &entry);
 
297
        return rc != 0 ? 0 : (void *) (long) entry;
 
298
}
 
299
 
 
300
int
 
301
vpd_read(unsigned int offset, unsigned int length, char *data)
 
302
{
 
303
        int result;
 
304
        long tmp = (long) data;
 
305
        result = of_3_1("rtas-read-vpd", offset, length, (int) tmp);
 
306
        return result;
 
307
}
 
308
 
 
309
int
 
310
vpd_write(unsigned int offset, unsigned int length, char *data)
 
311
{
 
312
        int result;
 
313
        long tmp = (long) data;
 
314
        result = of_3_1("rtas-write-vpd", offset, length, (int) tmp);
 
315
        return result;
 
316
}
 
317
 
 
318
static void
 
319
ipmi_oem_led_set(int type, int instance, int state)
 
320
{
 
321
        return of_3_0("set-led", type, instance, state);
 
322
}
 
323
 
 
324
int
 
325
write_mm_log(char *data, unsigned int length, unsigned short type)
 
326
{
 
327
        long tmp = (long) data;
 
328
 
 
329
        ipmi_oem_led_set(2, 0, 1);
 
330
        return of_3_1("write-mm-log", (int) tmp, length, type);
 
331
}
 
332
 
 
333
int
 
334
of_yield(void)
 
335
{
 
336
        return of_0_1("yield");
 
337
}
 
338
 
 
339
void *
 
340
of_set_callback(void *addr)
 
341
{
 
342
        return (void *) (long) (size_t) of_1_1("set-callback", p32cast addr);
 
343
}
 
344
 
 
345
void
 
346
bootmsg_warning(short id, const char *str, short lvl)
 
347
{
 
348
        (void) of_3_0("bootmsg-warning", id, lvl, p32cast str);
 
349
}
 
350
 
 
351
void
 
352
bootmsg_error(short id, const char *str)
 
353
{
 
354
        (void) of_2_0("bootmsg-error", id, p32cast str);
 
355
}
 
356
 
 
357
/*
 
358
void
 
359
bootmsg_debugcp(short id, const char *str, short lvl)
 
360
{
 
361
        (void) of_3_0("bootmsg-debugcp", id, lvl, p32cast str);
 
362
}
 
363
 
 
364
void
 
365
bootmsg_cp(short id)
 
366
{
 
367
        (void) of_1_0("bootmsg-cp", id);
 
368
}
 
369
*/
 
370
 
 
371
#define CONFIG_SPACE 0
 
372
#define IO_SPACE 1
 
373
#define MEM_SPACE 2
 
374
 
 
375
#define ASSIGNED_ADDRESS_PROPERTY 0
 
376
#define REG_PROPERTY 1
 
377
 
 
378
#define DEBUG_TRANSLATE_ADDRESS 0
 
379
#if DEBUG_TRANSLATE_ADDRESS != 0
 
380
#define DEBUG_TR(str...) printf(str)
 
381
#else
 
382
#define DEBUG_TR(str...)
 
383
#endif
 
384
 
 
385
/**
 
386
 * pci_address_type tries to find the type for which a
 
387
 * mapping should be done. This is PCI specific and is done by
 
388
 * looking at the first 32bit of the phys-addr in
 
389
 * assigned-addresses
 
390
 *
 
391
 * @param node     the node of the device which requests
 
392
 *                 translatation
 
393
 * @param address  the address which needs to be translated
 
394
 * @param prop_type the type of the property to search in (either REG_PROPERTY or ASSIGNED_ADDRESS_PROPERTY)
 
395
 * @return         the corresponding type (config, i/o, mem)
 
396
 */
 
397
static int
 
398
pci_address_type(phandle_t node, uint64_t address, uint8_t prop_type)
 
399
{
 
400
        char *prop_name = "assigned-addresses";
 
401
        if (prop_type == REG_PROPERTY)
 
402
                prop_name = "reg";
 
403
        /* #address-cells */
 
404
        const unsigned int nac = 3;     //PCI
 
405
        /* #size-cells */
 
406
        const unsigned int nsc = 2;     //PCI
 
407
        /* up to 11 pairs of (phys-addr(3) size(2)) */
 
408
        unsigned char buf[11 * (nac + nsc) * sizeof(int)];
 
409
        unsigned int *assigned_ptr;
 
410
        int result = -1;
 
411
        int len;
 
412
        len = of_getprop(node, prop_name, buf, 11 * (nac + nsc) * sizeof(int));
 
413
        assigned_ptr = (unsigned int *) &buf[0];
 
414
        while (len > 0) {
 
415
                if ((prop_type == REG_PROPERTY)
 
416
                    && ((assigned_ptr[0] & 0xFF) != 0)) {
 
417
                        //BARs and Expansion ROM must be in assigned-addresses... so in reg
 
418
                        // we only look for those without config space offset set...
 
419
                        assigned_ptr += (nac + nsc);
 
420
                        len -= (nac + nsc) * sizeof(int);
 
421
                        continue;
 
422
                }
 
423
                DEBUG_TR("%s %x size %x\n", prop_name, assigned_ptr[2],
 
424
                         assigned_ptr[4]);
 
425
                if (address >= assigned_ptr[2]
 
426
                    && address <= assigned_ptr[2] + assigned_ptr[4]) {
 
427
                        DEBUG_TR("found a match\n");
 
428
                        result = (assigned_ptr[0] & 0x03000000) >> 24;
 
429
                        break;
 
430
                }
 
431
                assigned_ptr += (nac + nsc);
 
432
                len -= (nac + nsc) * sizeof(int);
 
433
        }
 
434
        /* this can only handle 32bit memory space and should be
 
435
         * removed as soon as translations for 64bit are available */
 
436
        return (result == 3) ? MEM_SPACE : result;
 
437
}
 
438
 
 
439
/**
 
440
 * this is a hack which returns the lower 64 bit of any number of cells
 
441
 * all the higher bits will silently discarded
 
442
 * right now this works pretty good as long 64 bit addresses is all we want
 
443
 *
 
444
 * @param addr  a pointer to the first address cell
 
445
 * @param nc    number of cells addr points to
 
446
 * @return      the lower 64 bit to which addr points
 
447
 */
 
448
static uint64_t
 
449
get_dt_address(uint32_t *addr, uint32_t nc)
 
450
{
 
451
        uint64_t result = 0;
 
452
        while (nc--)
 
453
                result = (result << 32) | *(addr++);
 
454
        return result;
 
455
}
 
456
 
 
457
/**
 
458
 * this functions tries to find a mapping for the given address
 
459
 * it assumes that if we have #address-cells == 3 that we are trying
 
460
 * to do a PCI translation
 
461
 *
 
462
 * @param  addr    a pointer to the address that should be translated
 
463
 *                 if a translation has been found the address will
 
464
 *                 be modified
 
465
 * @param  type    this is required for PCI devices to find the
 
466
 *                 correct translation
 
467
 * @param ranges   this is one "range" containing the translation
 
468
 *                 information (one range = nac + pnac + nsc)
 
469
 * @param nac      the OF property #address-cells
 
470
 * @param nsc      the OF property #size-cells
 
471
 * @param pnac     the OF property #address-cells from the parent node
 
472
 * @return         -1 if no translation was possible; else 0
 
473
 */
 
474
static int
 
475
map_one_range(uint64_t *addr, int type, uint32_t *ranges, uint32_t nac,
 
476
              uint32_t nsc, uint32_t pnac)
 
477
{
 
478
        long offset;
 
479
        /* cm - child mapping */
 
480
        /* pm - parent mapping */
 
481
        uint64_t cm, size, pm;
 
482
        /* only check for the type if nac == 3 (PCI) */
 
483
        DEBUG_TR("type %x, nac %x\n", ranges[0], nac);
 
484
        if (((ranges[0] & 0x03000000) >> 24) != type && nac == 3)
 
485
                return -1;
 
486
        /* okay, it is the same type let's see if we find a mapping */
 
487
        size = get_dt_address(ranges + nac + pnac, nsc);
 
488
        if (nac == 3)           /* skip type if PCI */
 
489
                cm = get_dt_address(ranges + 1, nac - 1);
 
490
        else
 
491
                cm = get_dt_address(ranges, nac);
 
492
 
 
493
        DEBUG_TR("\t\tchild_mapping %lx\n", cm);
 
494
        DEBUG_TR("\t\tsize %lx\n", size);
 
495
        DEBUG_TR("\t\t*address %lx\n", (uint64_t) * addr);
 
496
        if (cm + size <= (uint64_t) * addr || cm > (uint64_t) * addr)
 
497
                /* it is not inside the mapping range */
 
498
                return -1;
 
499
        /* get the offset */
 
500
        offset = *addr - cm;
 
501
        /* and add the offset on the parent mapping */
 
502
        if (pnac == 3)          /* skip type if PCI */
 
503
                pm = get_dt_address(ranges + nac + 1, pnac - 1);
 
504
        else
 
505
                pm = get_dt_address(ranges + nac, pnac);
 
506
        DEBUG_TR("\t\tparent_mapping %lx\n", pm);
 
507
        *addr = pm + offset;
 
508
        DEBUG_TR("\t\t*address %lx\n", *addr);
 
509
        return 0;
 
510
}
 
511
 
 
512
/**
 
513
 * translate_address_dev tries to translate the device specific address
 
514
 * to a host specific address by walking up in the device tree
 
515
 *
 
516
 * @param address  a pointer to a 64 bit value which will be
 
517
 *                 translated
 
518
 * @param current_node phandle of the device from which the
 
519
 *                     translation will be started
 
520
 */
 
521
void
 
522
translate_address_dev(uint64_t *addr, phandle_t current_node)
 
523
{
 
524
        unsigned char buf[1024];
 
525
        phandle_t parent;
 
526
        unsigned int pnac;
 
527
        unsigned int nac;
 
528
        unsigned int nsc;
 
529
        int addr_type;
 
530
        int len;
 
531
        unsigned int *ranges;
 
532
        unsigned int one_range;
 
533
        DEBUG_TR("translate address %lx, node: %lx\n", *addr, current_node);
 
534
        of_getprop(current_node, "name", buf, 400);
 
535
        DEBUG_TR("current node: %s\n", buf);
 
536
        addr_type =
 
537
            pci_address_type(current_node, *addr, ASSIGNED_ADDRESS_PROPERTY);
 
538
        if (addr_type == -1) {
 
539
                // check in "reg" property if not found in "assigned-addresses"
 
540
                addr_type = pci_address_type(current_node, *addr, REG_PROPERTY);
 
541
        }
 
542
        DEBUG_TR("address_type %x\n", addr_type);
 
543
        current_node = of_parent(current_node);
 
544
        while (1) {
 
545
                parent = of_parent(current_node);
 
546
                if (!parent) {
 
547
                        DEBUG_TR("reached root node...\n");
 
548
                        break;
 
549
                }
 
550
                of_getprop(current_node, "#address-cells", &nac, 4);
 
551
                of_getprop(current_node, "#size-cells", &nsc, 4);
 
552
                of_getprop(parent, "#address-cells", &pnac, 4);
 
553
                one_range = nac + pnac + nsc;
 
554
                len = of_getprop(current_node, "ranges", buf, 400);
 
555
                if (len < 0) {
 
556
                        DEBUG_TR("no 'ranges' property; not translatable\n");
 
557
                        return;
 
558
                }
 
559
                ranges = (unsigned int *) &buf[0];
 
560
                while (len > 0) {
 
561
                        if (!map_one_range
 
562
                            ((uint64_t *) addr, addr_type, ranges, nac, nsc,
 
563
                             pnac))
 
564
                                /* after a successful mapping we stop
 
565
                                 * going through the ranges */
 
566
                                break;
 
567
                        ranges += one_range;
 
568
                        len -= one_range * sizeof(int);
 
569
                }
 
570
                DEBUG_TR("address %lx\n", *addr);
 
571
                of_getprop(current_node, "name", buf, 400);
 
572
                DEBUG_TR("current node: %s\n", buf);
 
573
                DEBUG_TR("\t#address-cells: %x\n", nac);
 
574
                DEBUG_TR("\t#size-cells: %x\n", nsc);
 
575
                of_getprop(parent, "name", buf, 400);
 
576
                DEBUG_TR("parent node: %s\n", buf);
 
577
                DEBUG_TR("\t#address-cells: %x\n", pnac);
 
578
                current_node = parent;
 
579
        }
 
580
}
 
581
 
 
582
static phandle_t
 
583
get_boot_device(void)
 
584
{
 
585
        char buf[1024];
 
586
        phandle_t dev = of_finddevice("/chosen");
 
587
 
 
588
        if (dev == -1) {
 
589
                dev = of_finddevice("/aliases");
 
590
                if (dev == -1)
 
591
                        return dev;
 
592
                of_getprop(dev, "net", buf, 1024);
 
593
        } else
 
594
                of_getprop(dev, "bootpath", buf, 1024);
 
595
 
 
596
        return of_finddevice(buf);
 
597
}
 
598
 
 
599
/**
 
600
 * translate_address tries to translate the device specific address
 
601
 * of the boot device to a host specific address
 
602
 *
 
603
 * @param address  a pointer to a 64 bit value which will be
 
604
 *                 translated
 
605
 */
 
606
void
 
607
translate_address(unsigned long *addr)
 
608
{
 
609
        translate_address_dev((uint64_t*) addr, get_boot_device());
 
610
}
 
611
 
 
612
/**
 
613
 * get_puid walks up in the device tree until it finds a parent
 
614
 * node without a reg property. get_puid is assuming that if the
 
615
 * parent node has no reg property it has found the pci host bridge
 
616
 *
 
617
 * this is not the correct way to find PHBs but it seems to work
 
618
 * for all our systems
 
619
 *
 
620
 * @param node   the device for which to find the puid
 
621
 *
 
622
 * @return       the puid or 0
 
623
 */
 
624
uint64_t
 
625
get_puid(phandle_t node)
 
626
{
 
627
        uint64_t puid = 0;
 
628
        uint64_t tmp = 0;
 
629
        phandle_t curr_node, last_node;
 
630
 
 
631
        curr_node = last_node = of_parent(node);
 
632
 
 
633
        while (curr_node) {
 
634
                puid = tmp;
 
635
                if (of_getprop(curr_node, "reg", &tmp, 8) < 8) {
 
636
                        /* if the found PHB is not directly under
 
637
                         * root we need to translate the found address */
 
638
                        translate_address_dev(&puid, last_node);
 
639
                        return puid;
 
640
                }
 
641
                last_node = curr_node;
 
642
                curr_node = of_parent(curr_node);
 
643
        }
 
644
 
 
645
        return 0;
 
646
}
 
647
 
 
648
int of_get_mac(phandle_t device, char *mac)
 
649
{
 
650
        uint8_t localmac[8];
 
651
        int len;
 
652
 
 
653
        len = of_getprop(device, "local-mac-address", localmac, 8);
 
654
        if (len <= 0)
 
655
                return -1;
 
656
 
 
657
        if (len == 8) {
 
658
                /* Some bad FDT nodes like veth use a 8-byte wide
 
659
                 * property instead of 6-byte wide MACs... :-( */
 
660
                memcpy(mac, &localmac[2], 6);
 
661
        }
 
662
        else {
 
663
                memcpy(mac, localmac, 6);
 
664
        }
 
665
        return 0;
 
666
}
 
667
 
 
668
static void
 
669
get_timebase(unsigned int *timebase)
 
670
{
 
671
        phandle_t cpu;
 
672
        phandle_t cpus = of_finddevice("/cpus");
 
673
 
 
674
        if (cpus == -1)
 
675
                return;
 
676
 
 
677
        cpu = of_child(cpus);
 
678
 
 
679
        if (cpu == -1)
 
680
                return;
 
681
 
 
682
        of_getprop(cpu, "timebase-frequency", timebase, 4);
 
683
}
 
684
 
 
685
int of_glue_init(unsigned int * timebase,
 
686
                 size_t _client_start, size_t _client_size)
 
687
{
 
688
        phandle_t chosen = of_finddevice("/chosen");
 
689
        ihandle_t stdin_ih, stdout_ih;
 
690
 
 
691
        client_start = (void *) (long) _client_start;
 
692
        client_size = _client_size;
 
693
 
 
694
        if (chosen == -1)
 
695
                return -1;
 
696
 
 
697
        of_getprop(chosen, "stdin", &stdin_ih, sizeof(ihandle_t));
 
698
        of_getprop(chosen, "stdout", &stdout_ih, sizeof(ihandle_t));
 
699
        pre_open_ih(0, stdin_ih);
 
700
        pre_open_ih(1, stdout_ih);
 
701
        pre_open_ih(2, stdout_ih);
 
702
        get_timebase(timebase);
 
703
        rtas_init();
 
704
 
 
705
        claim_rc=(int)(long)of_claim(client_start, client_size, 0);
 
706
 
 
707
        return 0;
 
708
}
 
709
 
 
710
void of_glue_release(void)
 
711
{
 
712
        if (claim_rc >= 0) {
 
713
                of_release(client_start, client_size);
 
714
        }
 
715
}