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

« back to all changes in this revision

Viewing changes to roms/openhackware/src/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
/* Open firmware emulation.
 
2
 *
 
3
 * This is really simplistic. The first goal is to implement all stuff
 
4
 * needed to boot Linux. Then, I'll try Darwin.
 
5
 * Note that this emulation run in the host environment.
 
6
 * There is no Forth interpreter, so standard bootloader cannot be launched.
 
7
 * In the future, it will be nice to get a complete OpenFirmware implementation
 
8
 * so that OSes can be launched exactly the way they are in the real world...
 
9
 *
 
10
 *  Copyright (c) 2003-2005 Jocelyn Mayer
 
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 V2
 
14
 *   as published by the Free Software Foundation
 
15
 *
 
16
 *   This program is distributed in the hope that it will be useful,
 
17
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *   GNU General Public License for more details.
 
20
 *
 
21
 *   You should have received a copy of the GNU General Public License
 
22
 *   along with this program; if not, write to the Free Software
 
23
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
24
 */
 
25
 
 
26
#include <stdlib.h>
 
27
#include <stdio.h>
 
28
#include "bios.h"
 
29
 
 
30
//#define DEBUG_OF 1
 
31
 
 
32
#if defined (DEBUG_OF)
 
33
#define OF_DPRINTF(fmt, args...) \
 
34
do { dprintf("%s: " fmt, __func__ , ##args); } while (0)
 
35
#else
 
36
#define OF_DPRINTF(fmt, args...) \
 
37
do { } while (0)
 
38
#endif
 
39
 
 
40
#define PROT_READ  1
 
41
#define PROT_WRITE 2
 
42
 
 
43
typedef struct OF_transl_t OF_transl_t;
 
44
struct OF_transl_t {
 
45
    uint32_t virt;
 
46
    uint32_t size;
 
47
    uint32_t phys;
 
48
    uint32_t mode;
 
49
};
 
50
 
 
51
typedef struct OF_env_t OF_env_t;
 
52
struct OF_env_t {
 
53
    uint32_t *stackp; /* Stack pointer          */
 
54
    uint32_t *stackb; /* Stack base             */
 
55
    uint32_t *funcp;  /* Function stack pointer */
 
56
    uint32_t *funcb;  /* Function stack base    */
 
57
};
 
58
 
 
59
typedef struct OF_bustyp_t OF_bustyp_t;
 
60
struct OF_bustyp_t {
 
61
    const char *name;
 
62
    int type;
 
63
};
 
64
 
 
65
typedef struct pci_address_t pci_address_t;
 
66
struct pci_address_t {
 
67
        uint32_t hi;
 
68
        uint32_t mid;
 
69
        uint32_t lo;
 
70
};
 
71
 
 
72
typedef struct pci_reg_prop_t pci_reg_prop_t;
 
73
struct pci_reg_prop_t {
 
74
        pci_address_t addr;
 
75
        uint32_t size_hi;
 
76
        uint32_t size_lo;
 
77
};
 
78
 
 
79
typedef struct pci_range_t pci_range_t;
 
80
struct pci_range_t {
 
81
        pci_address_t addr;
 
82
        uint32_t phys;
 
83
        uint32_t size_hi;
 
84
        uint32_t size_lo;
 
85
};
 
86
 
 
87
/*****************************************************************************/
 
88
__attribute__ (( section (".OpenFirmware") ))
 
89
static void OF_lds (uint8_t *dst, const void *address)
 
90
{
 
91
    const uint8_t *p;
 
92
    uint8_t *_d = dst;
 
93
 
 
94
    for (p = address; *p != '\0'; p++) {
 
95
        *_d++ = *p;
 
96
    }
 
97
    *_d = '\0';
 
98
    OF_DPRINTF("Loaded string %s\n", dst); 
 
99
}
 
100
 
 
101
__attribute__ (( section (".OpenFirmware") ))
 
102
static void OF_sts (void *address, const uint8_t *src)
 
103
{
 
104
    const uint8_t *_s;
 
105
    uint8_t *p = address;
 
106
 
 
107
    OF_DPRINTF("Store string %s\n", src);
 
108
    for (_s = src; *_s != '\0'; _s++) {
 
109
        *p++ = *_s;
 
110
    }
 
111
    *p = '\0';
 
112
}
 
113
 
 
114
#define OF_DUMP_STRING(env, buffer)    \
 
115
do {                                   \
 
116
    unsigned char tmp[OF_NAMELEN_MAX]; \
 
117
    OF_lds(tmp, buffer);               \
 
118
    OF_DPRINTF("[%s]\n", tmp);         \
 
119
} while (0)
 
120
 
 
121
/*****************************************************************************/
 
122
/* Forth like environmnent */
 
123
#define OF_CHECK_NBARGS(env, nb)                                              \
 
124
do {                                                                          \
 
125
    int nb_args;                                                              \
 
126
    nb_args = stackd_depth((env));                                            \
 
127
    if (nb_args != (nb)) {                                                    \
 
128
        printf("%s: Bad number of arguments (%d - %d)\n",                     \
 
129
               __func__, nb_args, (nb));                                      \
 
130
        bug();                                                                \
 
131
        popd_all((env), nb_args);                                             \
 
132
        pushd((env), -1);                                                     \
 
133
        return;                                                               \
 
134
    }                                                                         \
 
135
} while (0)
 
136
 
 
137
#define OF_STACK_SIZE 0x1000
 
138
#define OF_FSTACK_SIZE 0x100
 
139
__attribute__ (( section (".OpenFirmware_vars") ))
 
140
uint8_t OF_stack[OF_STACK_SIZE];
 
141
__attribute__ (( section (".OpenFirmware_vars") ))
 
142
uint8_t OF_fstack[OF_FSTACK_SIZE];
 
143
 
 
144
typedef void (*OF_cb_t)(OF_env_t *OF_env);
 
145
 
 
146
static inline void _push (uint32_t **stackp, uint32_t data)
 
147
{
 
148
    //    OF_DPRINTF("%p 0x%0x\n", *stackp, data);
 
149
    **stackp = data;
 
150
    (*stackp)--;
 
151
}
 
152
 
 
153
static inline uint32_t _pop (uint32_t **stackp)
 
154
{
 
155
    (*stackp)++;
 
156
    //    OF_DPRINTF("%p 0x%0x\n", *stackp, **stackp);
 
157
    return **stackp;
 
158
}
 
159
 
 
160
static inline void _pop_all (uint32_t **stackp, int nb)
 
161
{
 
162
    int i;
 
163
 
 
164
    for (i = 0; i < nb; i++)
 
165
        (*stackp)++;
 
166
}
 
167
 
 
168
static inline int _stack_depth (uint32_t *stackp, uint32_t *basep)
 
169
{
 
170
    return basep - stackp;
 
171
}
 
172
 
 
173
static inline void pushd (OF_env_t *OF_env, uint32_t data)
 
174
{
 
175
    _push(&OF_env->stackp, data);
 
176
}
 
177
 
 
178
static inline uint32_t popd (OF_env_t *OF_env)
 
179
{
 
180
    return _pop(&OF_env->stackp);
 
181
}
 
182
 
 
183
static inline void popd_all (OF_env_t *OF_env, int nb)
 
184
{
 
185
    _pop_all(&OF_env->stackp, nb);
 
186
}
 
187
 
 
188
static inline int stackd_depth (OF_env_t *OF_env)
 
189
{
 
190
    return _stack_depth(OF_env->stackp, OF_env->stackb);
 
191
}
 
192
 
 
193
static inline void pushf (OF_env_t *OF_env, OF_cb_t *func)
 
194
{
 
195
    _push(&OF_env->funcp, (uint32_t)func);
 
196
}
 
197
 
 
198
static inline OF_cb_t *popf (OF_env_t *OF_env)
 
199
{
 
200
    return (OF_cb_t *)_pop(&OF_env->funcp);
 
201
}
 
202
 
 
203
static inline void popf_all (OF_env_t *OF_env, int nb)
 
204
{
 
205
    _pop_all(&OF_env->funcp, nb);
 
206
}
 
207
 
 
208
static inline int stackf_depth (OF_env_t *OF_env)
 
209
{
 
210
    return _stack_depth(OF_env->funcp, OF_env->funcb);
 
211
}
 
212
 
 
213
static inline void OF_env_init (OF_env_t *OF_env)
 
214
{
 
215
    OF_env->stackb = (uint32_t *)(OF_stack + OF_STACK_SIZE - 4);
 
216
    OF_env->stackp = OF_env->stackb;
 
217
    OF_env->funcb = (uint32_t *)(OF_fstack + OF_FSTACK_SIZE - 4);
 
218
    OF_env->funcp = OF_env->funcb;
 
219
}
 
220
 
 
221
/* Forth run-time */
 
222
__attribute__ (( section (".OpenFirmware") ))
 
223
static void C_to_Forth (OF_env_t *env, void *p, OF_cb_t *cb)
 
224
{
 
225
    OF_cb_t *_cb;
 
226
    uint32_t *u, *rets;
 
227
    uint32_t i, n_args, n_rets, tmp;
 
228
 
 
229
    //    OF_DPRINTF("enter\n");
 
230
    /* Fill argument structure */
 
231
    u = p;
 
232
    n_args = *u++;
 
233
    n_rets = *u++;
 
234
    u += n_args;
 
235
    rets = u;
 
236
    //    OF_DPRINTF("n_args=%d n_rets=%d\n", n_args, n_rets);
 
237
    /* Load arguments */
 
238
    for (i = 0; i < n_args; i++)
 
239
        pushd(env, *(--u));
 
240
    pushf(env, cb);
 
241
    while (stackf_depth(env) != 0) {
 
242
        //        OF_DPRINTF("func stack: %p %p\n", env->funcb, env->funcp);
 
243
        _cb = popf(env);
 
244
        //        OF_DPRINTF("Next func: %p %d\n", cb, stackf_depth(env));
 
245
        (*_cb)(env);
 
246
    }
 
247
    //    OF_DPRINTF("Back to C: n_args=%d n_rets=%d\n", n_args, n_rets);
 
248
    /* Copy returned values */
 
249
    for (i = 0; stackd_depth(env) != 0; i++) {
 
250
        tmp = popd(env);
 
251
        //        OF_DPRINTF("Store 0x%0x (%d)\n", tmp, tmp);
 
252
        *rets++ = tmp;
 
253
    }
 
254
    for (; i < n_rets; i++)
 
255
        *rets++ = 0;
 
256
    OF_CHECK_NBARGS(env, 0);
 
257
    //    OF_DPRINTF("done\n");
 
258
}
 
259
 
 
260
/*****************************************************************************/
 
261
/* Memory pool (will be needed when it'll become native) */
 
262
#if 0
 
263
#define OF_INTBITS_LEN 128
 
264
#define OF_INTPOOL_LEN (OF_INTBITS_LEN * 8)
 
265
__attribute__ (( section (".OpenFirmware_vars") ))
 
266
static uint32_t OF_int_pool[OF_INTPOOL_LEN];
 
267
__attribute__ (( section (".OpenFirmware_vars") ))
 
268
static uint8_t  OF_int_bits[OF_INTBITS_LEN];
 
269
 
 
270
__attribute__ (( section (".OpenFirmware") ))
 
271
static uint32_t *OF_int_alloc (unused OF_env_t *env)
 
272
{
 
273
    uint8_t tmp;
 
274
    int i, j;
 
275
 
 
276
    for (i = 0; i < OF_INTBITS_LEN; i++) {
 
277
        tmp = OF_int_bits[i];
 
278
        if (tmp == 0xFF)
 
279
            continue;
 
280
        for (j = 0; j < 7; j++) {
 
281
            if ((tmp & 1) == 0) {
 
282
                OF_int_bits[i] |= 1 << j;
 
283
                return &OF_int_pool[(i << 3) | j];
 
284
            }
 
285
            tmp = tmp >> 1;
 
286
        }
 
287
    }
 
288
    printf("ALERT: unable to \"allocate\" new integer\n");
 
289
    
 
290
    return NULL;
 
291
}
 
292
 
 
293
__attribute__ (( section (".OpenFirmware") ))
 
294
static void OF_int_free (unused OF_env_t *env,
 
295
                         uint32_t *area)
 
296
{
 
297
    int i, j;
 
298
 
 
299
    i = area - OF_int_pool;
 
300
    j = i & 7;
 
301
    i = i >> 3;
 
302
    OF_int_bits[i] &= ~(1 << j);
 
303
}
 
304
 
 
305
__attribute__ (( section (".OpenFirmware") ))
 
306
static void OF_free (unused OF_env_t *env, void *area)
 
307
{
 
308
    uint32_t *check;
 
309
 
 
310
    /* Check if it's in our int pool */
 
311
    check = area;
 
312
    if (check >= OF_int_pool && check < (OF_int_pool + OF_INTPOOL_LEN)) {
 
313
        OF_int_free(env, check);
 
314
        return;
 
315
    }
 
316
#if 0
 
317
    free(area);
 
318
#endif
 
319
}
 
320
#endif
 
321
 
 
322
/*****************************************************************************/
 
323
/*                          Internal structures                              */
 
324
/* Property value types */
 
325
typedef struct OF_node_t OF_node_t;
 
326
typedef struct OF_prop_t OF_prop_t;
 
327
typedef struct OF_method_t OF_method_t;
 
328
typedef struct OF_inst_t OF_inst_t;
 
329
 
 
330
#define OF_ADDRESS_NONE ((uint32_t)(-1))
 
331
 
 
332
/* Tree node */
 
333
struct OF_node_t {
 
334
    /* Parent node */
 
335
    OF_node_t *parent;
 
336
    /* Link to next node at the same level */
 
337
    OF_node_t *next;
 
338
    /* Link to children, if any */
 
339
    OF_node_t *children, *child_last;
 
340
    /* refcount */
 
341
    int refcount;
 
342
    /* The following ones belong to the package */
 
343
    /* Package */
 
344
    uint16_t pack_id;
 
345
    /* links count */
 
346
    uint16_t link_count;
 
347
    uint16_t link_cur;
 
348
    OF_node_t *link_ref;
 
349
    /* Properties */
 
350
    OF_prop_t *properties, *prop_last, *prop_name, *prop_address;
 
351
    /* Methods */
 
352
    OF_method_t *methods, *method_last;
 
353
    /* private data */
 
354
    void *private_data;
 
355
    /* static data */
 
356
    void *static_data;
 
357
    /* instances */
 
358
    OF_inst_t *instances, *inst_last;
 
359
};
 
360
 
 
361
/* Node property */
 
362
struct OF_prop_t {
 
363
    /* Link to next property */
 
364
    OF_prop_t *next;
 
365
    /* The node it belongs to */
 
366
    OF_node_t *node;
 
367
    /* property name */
 
368
    const unsigned char *name;
 
369
    /* property value len */
 
370
    int vlen;
 
371
    /* property value buffer */
 
372
    char *value;
 
373
    /* Property change callback */
 
374
    void (*cb)(OF_env_t *OF_env, OF_prop_t *prop, const void *data, int len);
 
375
};
 
376
 
 
377
/* Node method */
 
378
enum {
 
379
    OF_METHOD_INTERNAL = 0,
 
380
    OF_METHOD_EXPORTED,
 
381
};
 
382
 
 
383
struct OF_method_t {
 
384
    /* Link to next method */
 
385
    OF_method_t *next;
 
386
    /* The package it belongs to */
 
387
    OF_node_t *node;
 
388
    /* method name */
 
389
    unsigned char *name;
 
390
    /* Method function pointer */
 
391
    OF_cb_t func;
 
392
};
 
393
 
 
394
/* Package instance */
 
395
struct OF_inst_t {
 
396
    /* Link to next instance of the same package */
 
397
    OF_inst_t *next;
 
398
    /* Link to the parent instance */
 
399
    OF_inst_t *parent;
 
400
    /* The package it belongs to */
 
401
    OF_node_t *node;
 
402
    /* Instance identifier */
 
403
    uint16_t inst_id;
 
404
    /* Instance data */
 
405
    void *data;
 
406
};
 
407
 
 
408
/* reg property */
 
409
typedef struct OF_regprop_t OF_regprop_t;
 
410
struct OF_regprop_t {
 
411
    uint32_t address;
 
412
    uint32_t size;
 
413
};
 
414
 
 
415
/* range property */
 
416
typedef struct OF_range_t OF_range_t;
 
417
struct OF_range_t {
 
418
    uint32_t virt;
 
419
    uint32_t size;
 
420
    uint32_t phys;
 
421
};
 
422
 
 
423
/* Open firmware tree */
 
424
#define OF_MAX_PACKAGE 256
 
425
/* nodes and packages */
 
426
__attribute__ (( section (".OpenFirmware_vars") ))
 
427
static OF_node_t *OF_node_root;
 
428
__attribute__ (( section (".OpenFirmware_vars") ))
 
429
static uint16_t OF_pack_last_id = 0;
 
430
__attribute__ (( section (".OpenFirmware_vars") ))
 
431
static uint16_t inst_last_id = 0;
 
432
/* To speed up lookup by id, we get a package table */
 
433
__attribute__ (( section (".OpenFirmware_vars") ))
 
434
static OF_node_t *OF_packages[OF_MAX_PACKAGE];
 
435
__attribute__ (( section (".OpenFirmware_vars") ))
 
436
static OF_node_t *OF_pack_active;
 
437
 
 
438
static OF_prop_t *OF_prop_string_new (OF_env_t *env, OF_node_t *node,
 
439
                                      const unsigned char *name,
 
440
                                      const unsigned char *string);
 
441
static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
 
442
                                   const unsigned char *name, uint32_t value);
 
443
static OF_prop_t *OF_property_get (OF_env_t *env, OF_node_t *node,
 
444
                                   const unsigned char *name);
 
445
static uint16_t OF_pack_handle (OF_env_t *env, OF_node_t *node);
 
446
 
 
447
__attribute__ (( section (".OpenFirmware_vars") ))
 
448
static uint8_t *RTAS_memory;
 
449
 
 
450
/*****************************************************************************/
 
451
/*                           Node management                                 */
 
452
/* Insert a new node */
 
453
__attribute__ (( section (".OpenFirmware") ))
 
454
static uint16_t OF_pack_new_id (unused OF_env_t *env, OF_node_t *node)
 
455
{
 
456
    uint16_t cur_id;
 
457
 
 
458
    for (cur_id = OF_pack_last_id + 1; cur_id != OF_pack_last_id; cur_id++) {
 
459
        if (cur_id == (uint16_t)(OF_MAX_PACKAGE))
 
460
            cur_id = 1;
 
461
        if (OF_packages[cur_id] == NULL) {
 
462
            OF_packages[cur_id] = node;
 
463
            OF_pack_last_id = cur_id;
 
464
            return cur_id;
 
465
        }
 
466
    }
 
467
 
 
468
    return (uint16_t)(-1);
 
469
}
 
470
 
 
471
static OF_node_t *OF_node_create (OF_env_t *env, OF_node_t *parent,
 
472
                                  const unsigned char *name, uint32_t address)
 
473
{
 
474
    OF_node_t *new;
 
475
 
 
476
    OF_DPRINTF("New node: %s\n", name);
 
477
    new = malloc(sizeof(OF_node_t));
 
478
    if (new == NULL) {
 
479
        ERROR("%s can't alloc new node '%s'\n", __func__, name);
 
480
        return NULL;
 
481
    }
 
482
    memset(new, 0, sizeof(OF_node_t));
 
483
    new->parent = parent;
 
484
    new->refcount = 1;
 
485
    new->link_count = 1;
 
486
    new->prop_name = OF_prop_string_new(env, new, "name", name);
 
487
    if (new->prop_name == NULL) {
 
488
        free(new);
 
489
        ERROR("%s can't alloc new node '%s' name\n", __func__, name);
 
490
        return NULL;
 
491
    }
 
492
    new->prop_address = OF_prop_int_new(env, new, "unit-address", address);
 
493
    if (new->prop_address == NULL) {
 
494
        free(new->prop_name->value);
 
495
        free(new->prop_name);
 
496
        free(new);
 
497
        ERROR("%s can't alloc new node '%s' address\n", __func__, name);
 
498
        return NULL;
 
499
    }
 
500
    /* Link it in parent tree */
 
501
    if (parent != NULL) {
 
502
        /* SHOULD LOCK */
 
503
        if (parent->children == NULL) {
 
504
            parent->children = new;
 
505
        } else {
 
506
            parent->child_last->next = new;
 
507
        }
 
508
        parent->child_last = new;
 
509
    } else {
 
510
        /* This is a bug and should never happen, but for root node */
 
511
        if (strcmp(name, "device-tree") != 0)
 
512
            ERROR("WARNING: parent of '%s' is NULL!\n", name);
 
513
    }
 
514
    //    OF_DPRINTF("New node: %s get id\n", name);
 
515
 
 
516
    return new;
 
517
}
 
518
 
 
519
__attribute__ (( section (".OpenFirmware") ))
 
520
static OF_node_t *OF_node_new (OF_env_t *env, OF_node_t *parent,
 
521
                               const unsigned char *name, uint32_t address)
 
522
{
 
523
    OF_node_t *new;
 
524
 
 
525
    new = OF_node_create(env, parent, name, address);
 
526
    if (new == NULL)
 
527
        return NULL;
 
528
    new->pack_id = OF_pack_new_id(env, new);
 
529
    //    OF_DPRINTF("New node: %s id=0x%0x\n", name, new->pack_id);
 
530
    OF_pack_active = new;
 
531
 
 
532
    return new;
 
533
}
 
534
 
 
535
static inline OF_node_t *OF_node_parent (unused OF_env_t *env, OF_node_t *node)
 
536
{
 
537
    return node->parent;
 
538
}
 
539
 
 
540
/* Look for a node, given its name */
 
541
__attribute__ (( section (".OpenFirmware") ))
 
542
static OF_node_t *OF_node_get_child (OF_env_t *env, OF_node_t *parent,
 
543
                                     const unsigned char *name,
 
544
                                     uint32_t address)
 
545
{
 
546
    unsigned char tname[OF_NAMELEN_MAX];
 
547
    OF_node_t *parse, *tmp;
 
548
    OF_prop_t *prop_name, *prop_address;
 
549
    uint32_t *addr_valp;
 
550
    int len, i;
 
551
 
 
552
    if (parent == OF_node_root) {
 
553
       OF_DPRINTF("Look for node [%s]\n", name);
 
554
    }
 
555
    len = strlen(name);
 
556
    memcpy(tname, name, len + 1);
 
557
    for (i = len; i > 0; i--) {
 
558
        if (tname[i - 1] == ',') {
 
559
            tname[i - 1] = '\0';
 
560
            len = i;
 
561
            break;
 
562
        }
 
563
    }
 
564
    for (parse = parent->children; parse != NULL; parse = parse->next) {
 
565
        prop_name = parse->prop_name;
 
566
        prop_address = parse->prop_address;
 
567
        if (prop_address == NULL)
 
568
            addr_valp = NULL;
 
569
        else
 
570
            addr_valp = (void *)prop_address->value;
 
571
#if 0
 
572
        OF_DPRINTF("node [%s] <=> [%s]\n", prop_name->value, tname);
 
573
#endif
 
574
        if (prop_name != NULL && strncmp(prop_name->value, tname, len) == 0 &&
 
575
            (prop_name->value[len] == '\0') &&
 
576
            (address == OF_ADDRESS_NONE || addr_valp == NULL ||
 
577
             address == *addr_valp)) {
 
578
            parse->refcount++;
 
579
            return parse;
 
580
        }
 
581
#if 1
 
582
        OF_DPRINTF("look in children [%s]\n", prop_name->value);
 
583
#endif
 
584
        tmp = OF_node_get_child(env, parse, tname, address);
 
585
        if (tmp != NULL)
 
586
            return tmp;
 
587
#if 0
 
588
        OF_DPRINTF("didn't find in children [%s]\n", prop_name->value);
 
589
#endif
 
590
    }
 
591
    if (parent == OF_node_root) {
 
592
        OF_DPRINTF("node [%s] not found\n", name);
 
593
    }
 
594
 
 
595
    return NULL;
 
596
}
 
597
 
 
598
__attribute__ (( section (".OpenFirmware") ))
 
599
static OF_node_t *OF_node_get (OF_env_t *env, const unsigned char *name)
 
600
{
 
601
    unsigned char tname[OF_NAMELEN_MAX];
 
602
    unsigned char *addrp;
 
603
    uint32_t address;
 
604
 
 
605
    if (strcmp(name, "device_tree") == 0)
 
606
        return OF_node_root;
 
607
 
 
608
    strcpy(tname, name);
 
609
    addrp = strchr(tname, '@');
 
610
    if (addrp == NULL) {
 
611
        address = OF_ADDRESS_NONE;
 
612
    } else {
 
613
        *addrp++ = '\0';
 
614
        address = strtol(addrp, NULL, 16);
 
615
    }
 
616
 
 
617
    /* SHOULD LOCK */
 
618
    return OF_node_get_child(env, OF_node_root, name, address);
 
619
}
 
620
 
 
621
/* Release a node */
 
622
__attribute__ (( section (".OpenFirmware") ))
 
623
static void OF_node_put (unused OF_env_t *env, OF_node_t *node)
 
624
{
 
625
    if (--node->refcount < 0)
 
626
        node->refcount = 0;
 
627
}
 
628
 
 
629
/*****************************************************************************/
 
630
/*                           Packages tree walk                              */
 
631
__attribute__ (( section (".OpenFirmware") ))
 
632
static uint16_t OF_pack_handle (unused OF_env_t *env, OF_node_t *node)
 
633
{
 
634
    if (node == NULL)
 
635
        return 0;
 
636
 
 
637
    return node->pack_id;
 
638
}
 
639
 
 
640
__attribute__ (( section (".OpenFirmware") ))
 
641
static OF_node_t *OF_pack_find_by_name (OF_env_t *env, OF_node_t *base,
 
642
                                        const unsigned char *name)
 
643
{
 
644
    unsigned char tmp[OF_NAMELEN_MAX], *addrp;
 
645
    const unsigned char *sl, *st;
 
646
    OF_node_t *parse;
 
647
    OF_prop_t *prop_name, *prop_address;
 
648
    uint32_t address, *addr_valp;
 
649
    int len;
 
650
 
 
651
    OF_DPRINTF("Path [%s] in '%s'\n", name, base->prop_name->value);
 
652
    st = name;
 
653
    if (*st == '/') {
 
654
        st++;
 
655
    }
 
656
    if (*st == '\0') {
 
657
        /* Should never happen */
 
658
        OF_DPRINTF("Done\n");
 
659
        return base;
 
660
    }
 
661
    sl = strchr(st, '/');
 
662
    if (sl == NULL) {
 
663
        len = strlen(st);
 
664
    } else {
 
665
        len = sl - st;
 
666
    }
 
667
    memcpy(tmp, st, len);
 
668
    tmp[len] = '\0';
 
669
    addrp = strchr(tmp, '@');
 
670
    if (addrp == NULL) {
 
671
        address = OF_ADDRESS_NONE;
 
672
    } else {
 
673
        len = addrp - tmp;
 
674
        *addrp++ = '\0';
 
675
        address = strtol(addrp, NULL, 16);
 
676
    }
 
677
    OF_DPRINTF("Look for [%s] '%s' %08x\n", tmp, sl, address);
 
678
    for (parse = base->children; parse != NULL; parse = parse->next) {
 
679
        prop_name = parse->prop_name;
 
680
        prop_address = parse->prop_address;
 
681
        if (prop_address == NULL)
 
682
            addr_valp = NULL;
 
683
        else
 
684
            addr_valp = (void *)prop_address->value;
 
685
#if 0
 
686
        OF_DPRINTF("Check [%s]\n", prop_name->value);
 
687
#endif
 
688
        if (prop_name == NULL) {
 
689
            printf("ERROR: missing address in node, parent: '%s'\n",
 
690
                   base->prop_name->value);
 
691
            bug();
 
692
        }
 
693
        if (strncmp(prop_name->value, tmp, len) == 0 &&
 
694
            prop_name->value[len] == '\0' &&
 
695
            (address == OF_ADDRESS_NONE || addr_valp == NULL ||
 
696
             address == *addr_valp)) {
 
697
            OF_pack_active = parse;
 
698
            if (sl == NULL) {
 
699
                OF_DPRINTF("Done\n");
 
700
                return parse;
 
701
            }
 
702
            OF_DPRINTF("Recurse: '%s'\n", sl + 1);
 
703
            return OF_pack_find_by_name(env, parse, sl + 1);
 
704
        }
 
705
    }
 
706
    OF_DPRINTF("Didn't found [%s]\n", tmp);
 
707
 
 
708
    return NULL;
 
709
}
 
710
 
 
711
__attribute__ (( section (".OpenFirmware") ))
 
712
static OF_node_t *OF_pack_find (unused OF_env_t *env, uint16_t phandle)
 
713
{
 
714
    if (phandle > OF_MAX_PACKAGE)
 
715
        return NULL;
 
716
    if (OF_packages[phandle] == NULL) {
 
717
        OF_DPRINTF("No package %0x\n", phandle);
 
718
    } else {
 
719
        OF_DPRINTF("return package: %0x %p [%s]\n", phandle,
 
720
                   OF_packages[phandle],
 
721
                   OF_packages[phandle]->prop_name->value);
 
722
    }
 
723
 
 
724
    return OF_packages[phandle];
 
725
}
 
726
 
 
727
__attribute__ (( section (".OpenFirmware") ))
 
728
static OF_node_t *OF_pack_next (OF_env_t *env, uint16_t phandle)
 
729
{
 
730
    OF_node_t *node;
 
731
 
 
732
    for (node = OF_pack_find(env, phandle); node != NULL; node = node->next) {
 
733
        if (OF_pack_handle(env, node) != phandle)
 
734
            break;
 
735
    }
 
736
#if 0
 
737
    OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
 
738
#endif
 
739
 
 
740
    return node;
 
741
}
 
742
 
 
743
__attribute__ (( section (".OpenFirmware") ))
 
744
static OF_node_t *OF_pack_child (OF_env_t *env, uint16_t phandle)
 
745
{
 
746
    OF_node_t *node;
 
747
 
 
748
    node = OF_pack_find(env, phandle);
 
749
    if (node == NULL) {
 
750
        ERROR("%s didn't find pack %04x\n", __func__, phandle);
 
751
        return NULL;
 
752
    }
 
753
    node = node->children;
 
754
#if 0
 
755
    OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
 
756
#endif
 
757
 
 
758
    return node;
 
759
}
 
760
 
 
761
__attribute__ (( section (".OpenFirmware") ))
 
762
static OF_node_t *OF_pack_parent (OF_env_t *env, uint16_t phandle)
 
763
{
 
764
    OF_node_t *node;
 
765
 
 
766
    node = OF_pack_find(env, phandle);
 
767
    if (node == NULL) {
 
768
        ERROR("%s didn't find pack %04x\n", __func__, phandle);
 
769
        return NULL;
 
770
    }
 
771
    node = OF_node_parent(env, node);
 
772
#if 0
 
773
    OF_DPRINTF("found node %p [%s]\n", node, node->prop_name->value);
 
774
#endif
 
775
 
 
776
    return node;
 
777
}
 
778
 
 
779
/*****************************************************************************/
 
780
/*                      Package properties management                        */
 
781
/* Insert a new property */
 
782
__attribute__ (( section (".OpenFirmware") ))
 
783
static OF_prop_t *OF_property_new (unused OF_env_t *env, OF_node_t *node,
 
784
                                   const unsigned char *name,
 
785
                                   const void *data, int len)
 
786
{
 
787
    OF_prop_t *prop;
 
788
 
 
789
#ifdef DEBUG_OF
 
790
    {
 
791
        OF_prop_t *_prop;
 
792
        _prop = OF_property_get(env, node, name);
 
793
        if (_prop != NULL) {
 
794
            printf("Property '%s' already present !\n", name);
 
795
            bug();
 
796
        }
 
797
    }
 
798
#endif
 
799
    /* Allocate a new property */
 
800
    prop = malloc(sizeof(OF_prop_t));
 
801
    if (prop == NULL) {
 
802
        ERROR("%s cannot allocate property '%s'\n", __func__, name);
 
803
        return NULL;
 
804
    }
 
805
    memset(prop, 0, sizeof(OF_prop_t));
 
806
    prop->name = strdup(name);
 
807
    if (prop->name == NULL) {
 
808
        free(prop);
 
809
        ERROR("%s cannot allocate property '%s' name\n", __func__, name);
 
810
        return NULL;
 
811
    }
 
812
    /* Fill it */
 
813
    if (data != NULL && len > 0) {
 
814
        prop->value = malloc(len);
 
815
        if (prop->value == NULL) {
 
816
            free(prop);
 
817
            ERROR("%s cannot allocate property '%s' value\n", __func__, name);
 
818
            return NULL;
 
819
        }
 
820
        prop->vlen = len;
 
821
        memcpy(prop->value, data, len);
 
822
    }
 
823
    OF_DPRINTF("New property [%s] '%s'\n\t%p %p %d %p\n", name, prop->name, prop->name, data, len, prop->value);
 
824
    /* Link it */
 
825
    /* SHOULD LOCK */
 
826
    if (node->properties == NULL)
 
827
        node->properties = prop;
 
828
    else
 
829
        node->prop_last->next = prop;
 
830
    node->prop_last = prop;
 
831
    
 
832
    return prop;
 
833
}
 
834
 
 
835
/* Find a property given its name */
 
836
__attribute__ (( section (".OpenFirmware") ))
 
837
static OF_prop_t *OF_property_get (unused OF_env_t *env, OF_node_t *node,
 
838
                                   const unsigned char *name)
 
839
{
 
840
    OF_prop_t *prop;
 
841
    
 
842
#if 0
 
843
    OF_DPRINTF("Look for property [%s] in 0x%0x '%s'\n", name,
 
844
               node->pack_id, node->prop_name->value);
 
845
#endif
 
846
    if (node == NULL)
 
847
        return NULL;
 
848
    /* *SHOULD LOCK* */
 
849
    for (prop = node->properties; prop != NULL; prop = prop->next) {
 
850
#if 0
 
851
        OF_DPRINTF("property [%s] <=> [%s]\n", prop->name, name);
 
852
#endif
 
853
        if (strcmp(prop->name, name) == 0) {
 
854
            return prop;
 
855
        }
 
856
    }
 
857
#if 0
 
858
    OF_DPRINTF("property [%s] not found in 0x%08x '%s'\n", name,
 
859
               node->pack_id, node->prop_name->value);
 
860
#endif
 
861
 
 
862
    return NULL;
 
863
}
 
864
 
 
865
/* Change a property */
 
866
__attribute__ (( section (".OpenFirmware") ))
 
867
static OF_prop_t *OF_property_set (OF_env_t *env, OF_node_t *node,
 
868
                                   const unsigned char *name,
 
869
                                   const void *data, int len)
 
870
{
 
871
    OF_prop_t *prop;
 
872
    void *tmp;
 
873
 
 
874
    if (node == NULL)
 
875
        return NULL;
 
876
    prop = OF_property_get(env, node, name);
 
877
    if (prop != NULL) {
 
878
        OF_DPRINTF("change property [%s]\n", name);
 
879
        tmp = malloc(len);
 
880
        if (tmp == NULL && len != 0) {
 
881
            ERROR("%s cannot set property '%s'\n", __func__, name);
 
882
            return NULL;
 
883
        }
 
884
        free(prop->value);
 
885
        prop->value = tmp;
 
886
        prop->vlen = len;
 
887
        memcpy(prop->value, data, len);
 
888
        if (prop->cb != NULL) {
 
889
            (*prop->cb)(env, prop, data, len);
 
890
        }
 
891
    } else {
 
892
        OF_DPRINTF("new property [%s]\n", name);
 
893
        prop = OF_property_new(env, node, name, data, len);
 
894
    }
 
895
 
 
896
    return prop;
 
897
}
 
898
 
 
899
__attribute__ (( section (".OpenFirmware") ))
 
900
static int OF_property_len (OF_env_t *env, OF_node_t *node,
 
901
                            const unsigned char *name)
 
902
{
 
903
    OF_prop_t *prop;
 
904
 
 
905
    prop = OF_property_get(env, node, name);
 
906
    if (prop == NULL)
 
907
        return -1;
 
908
    
 
909
    return prop->vlen;
 
910
}
 
911
 
 
912
__attribute__ (( section (".OpenFirmware") ))
 
913
static unsigned char *hex2buf (unsigned char *buf, uint32_t value, int fill)
 
914
{
 
915
    int pos, d;
 
916
    
 
917
    buf[8] = '\0';
 
918
    pos = 7;
 
919
    if (value == 0) {
 
920
        buf[pos--] = '0';
 
921
    } else {
 
922
        for (; value != 0; pos--) {
 
923
            d = value & 0xF;
 
924
            if (d > 9)
 
925
            d += 'a' - '0' - 10;
 
926
            buf[pos] = d + '0';
 
927
            value = value >> 4;
 
928
        }
 
929
    }
 
930
    if (fill != 0) {
 
931
        for (; pos != -1; pos--) {
 
932
            buf[pos] = '0';
 
933
        }
 
934
    }
 
935
 
 
936
    return &buf[pos];
 
937
}
 
938
 
 
939
__attribute__ (( section (".OpenFirmware") ))
 
940
static int OF_property_copy (OF_env_t *env, void *buffer, int maxlen,
 
941
                             OF_node_t *node, const unsigned char *name)
 
942
{
 
943
    unsigned char tmp[OF_PROPLEN_MAX];
 
944
    OF_prop_t *prop;
 
945
    int len;
 
946
 
 
947
    prop = OF_property_get(env, node, name);
 
948
    if (prop == NULL) {
 
949
        ERROR("%s cannot get property '%s' for %s\n", __func__, name,
 
950
              node->prop_name->value);
 
951
        return -1;
 
952
    }
 
953
    len = prop->vlen > maxlen ? maxlen : prop->vlen;
 
954
    if (prop->value != NULL) {
 
955
        tmp[0] = '0';
 
956
        tmp[1] = 'x';
 
957
        hex2buf(tmp + 2, *((uint32_t *)prop->value), 1);
 
958
    } else {
 
959
        *tmp = '\0';
 
960
    }
 
961
    OF_DPRINTF("copy property [%s] len=%d to %p len=%d\n",
 
962
               name, prop->vlen, buffer, maxlen);
 
963
    if (strcmp(name, "name") == 0) {
 
964
        OF_DPRINTF("=> '%s'\n", prop->value);
 
965
    }
 
966
    memcpy(buffer, prop->value, len);
 
967
    //    OF_DPRINTF("done\n");
 
968
 
 
969
    return len;
 
970
}
 
971
 
 
972
__attribute__ (( section (".OpenFirmware") ))
 
973
static OF_prop_t *OF_property_next (OF_env_t *env, OF_node_t *node,
 
974
                                    const unsigned char *name)
 
975
{
 
976
    OF_prop_t *prop, *next;
 
977
 
 
978
    if (name == NULL || *name == '\0') {
 
979
        next = node->properties;
 
980
    } else {
 
981
        prop = OF_property_get(env, node, name);
 
982
        if (prop == NULL) {
 
983
            OF_DPRINTF("Property [%s] not found\n", name);
 
984
            next = NULL;
 
985
        } else {
 
986
            next = prop->next;
 
987
            /* Skip address if not set */
 
988
            if (next == node->prop_address &&
 
989
                *((uint32_t *)next->value) == OF_ADDRESS_NONE)
 
990
                next = next->next;
 
991
        }
 
992
    }
 
993
#if 0
 
994
    OF_DPRINTF("Found property %p\n", next);
 
995
#endif
 
996
 
 
997
    return next;
 
998
}
 
999
 
 
1000
/* Simplified helpers */
 
1001
__attribute__ (( section (".OpenFirmware") ))
 
1002
static OF_prop_t *OF_prop_string_new (OF_env_t *env, OF_node_t *node,
 
1003
                                      const unsigned char *name,
 
1004
                                      const unsigned char *string)
 
1005
{
 
1006
#ifdef DEBUG_OF
 
1007
    {
 
1008
        OF_prop_t *prop;
 
1009
        prop = OF_property_get(env, node, name);
 
1010
        if (prop != NULL) {
 
1011
            printf("Property '%s' already present !\n", name);
 
1012
            bug();
 
1013
        }
 
1014
    }
 
1015
#endif
 
1016
    return OF_property_new(env, node, name,
 
1017
                           string, strlen(string) + 1);
 
1018
}
 
1019
 
 
1020
/* convert '\1' char to '\0' */
 
1021
static OF_prop_t *OF_prop_string_new1 (OF_env_t *env, OF_node_t *node,
 
1022
                                       const unsigned char *name,
 
1023
                                       const unsigned char *string)
 
1024
{
 
1025
    int len, i;
 
1026
    OF_prop_t *ret;
 
1027
    unsigned char *str;
 
1028
 
 
1029
    if (strchr(string, '\1') == NULL) {
 
1030
        return OF_prop_string_new(env, node, name, string);
 
1031
    } else {
 
1032
        len = strlen(string) + 1;
 
1033
        str = malloc(len);
 
1034
        if (!str)
 
1035
            return NULL;
 
1036
        memcpy(str, string, len);
 
1037
        for(i = 0; i < len; i++)
 
1038
            if (str[i] == '\1')
 
1039
                str[i] = '\0';
 
1040
        ret = OF_property_new(env, node, name,
 
1041
                              str, len);
 
1042
        free(str);
 
1043
        return ret;
 
1044
    }
 
1045
}
 
1046
 
 
1047
__attribute__ (( section (".OpenFirmware") ))
 
1048
static OF_prop_t *OF_prop_int_new (OF_env_t *env, OF_node_t *node,
 
1049
                                   const unsigned char *name, uint32_t value)
 
1050
{
 
1051
#ifdef DEBUG_OF
 
1052
    {
 
1053
        OF_prop_t *prop;
 
1054
        prop = OF_property_get(env, node, name);
 
1055
        if (prop != NULL) {
 
1056
            printf("Property '%s' already present !\n", name);
 
1057
            bug();
 
1058
        }
 
1059
    }
 
1060
#endif
 
1061
    return OF_property_new(env, node, name, &value, sizeof(uint32_t));
 
1062
}
 
1063
 
 
1064
__attribute__ (( section (".OpenFirmware") ))
 
1065
static OF_prop_t *OF_prop_string_set (OF_env_t *env, OF_node_t *node,
 
1066
                                      const unsigned char *name,
 
1067
                                      const unsigned char *string)
 
1068
{
 
1069
    const unsigned char *tmp;
 
1070
 
 
1071
    tmp = strdup(string);
 
1072
    if (tmp == NULL) {
 
1073
        ERROR("%s cannot duplicate property '%s'\n", __func__, name);
 
1074
        return NULL;
 
1075
    }
 
1076
 
 
1077
    return OF_property_set(env, node, name, tmp, strlen(string) + 1);
 
1078
}
 
1079
 
 
1080
__attribute__ (( section (".OpenFirmware") ))
 
1081
static OF_prop_t *OF_prop_int_set (OF_env_t *env, OF_node_t *node,
 
1082
                                   const unsigned char *name, uint32_t value)
 
1083
{
 
1084
    return OF_property_set(env, node, name, &value, sizeof(uint32_t));
 
1085
}
 
1086
 
 
1087
__attribute__ (( section (".OpenFirmware") ))
 
1088
unused
 
1089
static OF_prop_t *OF_set_compatibility (OF_env_t *env, OF_node_t *node,
 
1090
                                        const unsigned char *compat)
 
1091
{
 
1092
    return OF_prop_string_new(env, node, "compatible", compat);
 
1093
}
 
1094
 
 
1095
__attribute__ (( section (".OpenFirmware") ))
 
1096
static inline void OF_property_set_cb (unused OF_env_t *OF_env,
 
1097
                                       OF_prop_t *prop,
 
1098
                                       void (*cb)(OF_env_t *OF_env,
 
1099
                                                  OF_prop_t *prop,
 
1100
                                                  const void *data, int len))
 
1101
{
 
1102
    prop->cb = cb;
 
1103
}
 
1104
 
 
1105
/*****************************************************************************/
 
1106
/*                       Packages methods management                         */
 
1107
__attribute__ (( section (".OpenFirmware") ))
 
1108
static OF_method_t *OF_method_new (unused OF_env_t *env, OF_node_t *node,
 
1109
                                   const unsigned char *name, OF_cb_t cb)
 
1110
{
 
1111
    OF_method_t *new;
 
1112
 
 
1113
    new = malloc(sizeof(OF_method_t));
 
1114
    if (new == NULL) {
 
1115
        ERROR("%s cannot allocate method '%s'\n", __func__, name);
 
1116
        return NULL;
 
1117
    }
 
1118
    memset(new, 0, sizeof(OF_method_t));
 
1119
    new->node = node;
 
1120
    new->name = strdup(name);
 
1121
    if (new->name == NULL) {
 
1122
        free(new);
 
1123
        ERROR("%s cannot allocate method '%s' name\n", __func__, name);
 
1124
        return NULL;
 
1125
    }
 
1126
    OF_DPRINTF("new method name %p %s\n", new, new->name);
 
1127
    new->func = cb;
 
1128
    /* Link it */
 
1129
    /* *SHOULD LOCK* */
 
1130
    if (node->method_last == NULL)
 
1131
        node->methods = new;
 
1132
    else
 
1133
        node->method_last->next = new;
 
1134
    node->method_last = new;
 
1135
 
 
1136
    return new;
 
1137
}
 
1138
 
 
1139
__attribute__ (( section (".OpenFirmware") ))
 
1140
static OF_method_t *OF_method_get (unused OF_env_t *env, OF_node_t *node,
 
1141
                                   const unsigned char *name)
 
1142
{
 
1143
    OF_method_t *parse;
 
1144
 
 
1145
    if (node == NULL) {
 
1146
        OF_DPRINTF("No method in NULL package !\n");
 
1147
        return NULL;
 
1148
    }
 
1149
#if 0
 
1150
    OF_DPRINTF("Look for method %s in package %0x\n",
 
1151
               name, node->pack_id);
 
1152
#endif
 
1153
    for (parse = node->methods; parse != NULL; parse = parse->next) {
 
1154
#if 0
 
1155
        OF_DPRINTF("check %p %p\n", parse, parse->name);
 
1156
        OF_DPRINTF("name=%s\n", parse->name);
 
1157
#endif
 
1158
        if (strcmp(parse->name, name) == 0)
 
1159
            return parse;
 
1160
    }
 
1161
 
 
1162
    return NULL;
 
1163
}
 
1164
 
 
1165
/*****************************************************************************/
 
1166
/*                     Packages instances management                         */
 
1167
__attribute__ (( section (".OpenFirmware") ))
 
1168
static uint16_t OF_inst_new_id (unused OF_env_t *env, OF_node_t *node)
 
1169
{
 
1170
    OF_inst_t *tmp_inst;
 
1171
    uint16_t cur_id;
 
1172
 
 
1173
#if 0
 
1174
    OF_DPRINTF("[%s] %d\n", node->prop_name->value,
 
1175
               inst_last_id);
 
1176
#endif
 
1177
    for (cur_id = inst_last_id + 1;
 
1178
         cur_id != inst_last_id; cur_id++) {
 
1179
        if (cur_id == (uint16_t)(OF_MAX_PACKAGE))
 
1180
            cur_id = 0;
 
1181
        for (tmp_inst = node->instances; tmp_inst != NULL;
 
1182
             tmp_inst = tmp_inst->next) {
 
1183
            if (tmp_inst->inst_id == cur_id)
 
1184
                continue;
 
1185
        }
 
1186
        inst_last_id = cur_id;
 
1187
#if 1
 
1188
        OF_DPRINTF("0x%0x\n", cur_id);
 
1189
#endif
 
1190
        return cur_id;
 
1191
    }
 
1192
    OF_DPRINTF("no ID found\n");
 
1193
 
 
1194
    return (uint16_t)(-1);
 
1195
}
 
1196
 
 
1197
/* Create a new package's instance */
 
1198
__attribute__ (( section (".OpenFirmware") ))
 
1199
static OF_inst_t *OF_instance_new (OF_env_t *env, OF_node_t *node)
 
1200
{
 
1201
    OF_inst_t *new, *parent;
 
1202
    uint16_t new_id;
 
1203
 
 
1204
    /* TODO: recurse to root... */
 
1205
    new = malloc(sizeof(OF_inst_t));
 
1206
    if (new == NULL) {
 
1207
        ERROR("%s cannot allocate instance of '%s'\n", __func__,
 
1208
              node->prop_name->value);
 
1209
        return NULL;
 
1210
    }
 
1211
    memset(new, 0, sizeof(OF_inst_t));
 
1212
    if (OF_node_parent(env, node) != NULL) {
 
1213
        parent = OF_instance_new(env, OF_node_parent(env, node));
 
1214
        if (parent == NULL) {
 
1215
            free(new);
 
1216
            ERROR("%s cannot allocate instance of '%s' parent\n", __func__,
 
1217
                  node->prop_name->value);
 
1218
            return NULL;
 
1219
        }
 
1220
        new->parent = parent;
 
1221
    } else {
 
1222
        new->parent = NULL;
 
1223
    }
 
1224
    new_id = OF_inst_new_id(env, node);
 
1225
    if (new_id == (uint16_t)(-1)) {
 
1226
        free(new);
 
1227
        return NULL;
 
1228
    }
 
1229
    new->inst_id = new_id;
 
1230
    new->node = node;
 
1231
    /* Link it */
 
1232
    /* SHOULD LOCK */
 
1233
    if (node->inst_last == NULL)
 
1234
        node->instances = new;
 
1235
    else
 
1236
        node->inst_last->next = new;
 
1237
    node->inst_last = new;
 
1238
 
 
1239
    return new;
 
1240
}
 
1241
 
 
1242
__attribute__ (( section (".OpenFirmware") ))
 
1243
static uint32_t OF_instance_get_id (unused OF_env_t *env, OF_inst_t *instance)
 
1244
{
 
1245
    OF_DPRINTF("p: %0x i: %0x\n", instance->node->pack_id, instance->inst_id);
 
1246
    return (instance->node->pack_id << 16) | instance->inst_id;
 
1247
}
 
1248
 
 
1249
__attribute__ (( section (".OpenFirmware") ))
 
1250
static OF_inst_t *OF_inst_find (OF_env_t *env, uint32_t ihandle)
 
1251
{
 
1252
    OF_node_t *node;
 
1253
    OF_inst_t *parse;
 
1254
    uint16_t phandle = ihandle >> 16;
 
1255
 
 
1256
    ihandle &= 0xFFFF;
 
1257
    OF_DPRINTF("p: %0x i: %0x\n", phandle, ihandle);
 
1258
    if (ihandle > OF_MAX_PACKAGE)
 
1259
        return NULL;
 
1260
    node = OF_pack_find(env, phandle);
 
1261
    if (node == NULL)
 
1262
        return NULL;
 
1263
    for (parse = node->instances; parse != NULL; parse = parse->next) {
 
1264
        if (parse->inst_id == ihandle)
 
1265
            return parse;
 
1266
    }
 
1267
 
 
1268
    return NULL;
 
1269
}
 
1270
 
 
1271
#if 0
 
1272
__attribute__ (( section (".OpenFirmware") ))
 
1273
static OF_inst_t *OF_inst_get_child (OF_env_t *env, OF_node_t *parent,
 
1274
                                     const uint32_t handle)
 
1275
{
 
1276
    OF_node_t *parse, *tmp;
 
1277
 
 
1278
    for (parse = parent->children; parse != NULL; parse = parse->next) {
 
1279
        if (parse->pack_id == (handle >> 16)) {
 
1280
            return NULL;
 
1281
        }
 
1282
        tmp = OF_inst_get_child(env, parse, handle);
 
1283
        if (tmp != NULL)
 
1284
            return tmp;
 
1285
    }
 
1286
 
 
1287
    return NULL;
 
1288
}
 
1289
 
 
1290
__attribute__ (( section (".OpenFirmware") ))
 
1291
static OF_inst_t *OF_inst_get (OF_env_t *env, const unsigned char *name)
 
1292
{
 
1293
    return _OF_node_get(env, &OF_node_root);
 
1294
    
 
1295
}
 
1296
#endif
 
1297
 
 
1298
#if 0
 
1299
__attribute__ (( section (".OpenFirmware") ))
 
1300
int get_node_name (OF_env_t *env, unsigned char *name,
 
1301
                   int len, OF_node_t *node)
 
1302
{
 
1303
    int tmp, total;
 
1304
    int i;
 
1305
 
 
1306
    /* Set up manufacturer name */
 
1307
    total = 0;
 
1308
    tmp = 0;
 
1309
#if 0
 
1310
    if (OF_node_parent(env, node) == NULL ||
 
1311
        node->manufct != OF_node_parent(env, node)->manufct) {
 
1312
        tmp = strlen(node->manufct);
 
1313
        if ((tmp + 2) > len)
 
1314
            return -1;
 
1315
        memcpy(name, node->manufct, tmp);
 
1316
        name += tmp;
 
1317
    } else if (len < 2) {
 
1318
        return -1;
 
1319
    }
 
1320
    *name++ = ',';
 
1321
    len -= tmp + 1;
 
1322
    total += tmp + 1;
 
1323
#endif
 
1324
    /* Set up device model */
 
1325
    tmp = strlen(node->name);
 
1326
    if ((tmp + 2) > len)
 
1327
        return -1;
 
1328
    memcpy(name, node->model, tmp);
 
1329
    name += tmp;
 
1330
    *name++ = '@';
 
1331
    len -= tmp + 1;
 
1332
    total += tmp + 1;
 
1333
    /* Set up unit address */
 
1334
    tmp = strlen(node->address);
 
1335
    if ((tmp + 2) > len)
 
1336
        return -1;
 
1337
    memcpy(name, node->address, tmp);
 
1338
    name += tmp;
 
1339
    *name++ = ':';
 
1340
    len -= tmp + 1;
 
1341
    total += tmp + 1;
 
1342
    for (i = 0; node->arguments[i] != NULL; i++) {
 
1343
        if (i != 0)
 
1344
            *name++ = ',';
 
1345
        tmp = strlen(node->arguments[i]);
 
1346
        if ((tmp + 2) > len)
 
1347
            return -1;
 
1348
        memcpy(name, node->arguments[i], tmp);
 
1349
        name += tmp;
 
1350
        len -= tmp + 1;
 
1351
        total += tmp + 1;
 
1352
    }
 
1353
    *name = '\0';
 
1354
 
 
1355
    return total;
 
1356
}
 
1357
#endif
 
1358
 
 
1359
__attribute__ (( section (".OpenFirmware") ))
 
1360
static int OF_pack_get_path (OF_env_t *env, unsigned char *name,
 
1361
                             int len, OF_node_t *node)
 
1362
{
 
1363
    OF_prop_t *prop_name, *prop_address;
 
1364
    uint32_t address;
 
1365
    int tmp, nlen;
 
1366
 
 
1367
    /* Recurse until we reach the root node */
 
1368
    OF_DPRINTF("look for [%s]\n", node->prop_name->value);
 
1369
    if (OF_node_parent(env, node) == NULL) {
 
1370
        name[0] = '/';
 
1371
        tmp = 0;
 
1372
        nlen = 1;
 
1373
    } else {
 
1374
        tmp = OF_pack_get_path(env, name, len, OF_node_parent(env, node));
 
1375
        /* Add node name */
 
1376
        prop_name = node->prop_name;
 
1377
        prop_address = node->prop_address;
 
1378
#if 1
 
1379
        OF_DPRINTF("Found [%s]\n", prop_name->value);
 
1380
#endif
 
1381
        if ((len - tmp) < 2) {
 
1382
            OF_DPRINTF("Buffer too short (%d 2)\n", len - tmp);
 
1383
            return 0;
 
1384
        }
 
1385
        if (prop_name == NULL) {
 
1386
            printf("No name in node !\n");
 
1387
            bug();
 
1388
        }
 
1389
        nlen = strlen(prop_name->value);
 
1390
#if 1
 
1391
        OF_DPRINTF("got '%s' for '%s' parent (%d %d)\n",
 
1392
                   name, prop_name->value, tmp, nlen);
 
1393
#endif
 
1394
        if (name[tmp - 1] != '/') {
 
1395
            name[tmp] = '/';
 
1396
            tmp++;
 
1397
        }
 
1398
        address = *((uint32_t *)prop_address->value);
 
1399
        if (address != OF_ADDRESS_NONE) {
 
1400
            if ((len - tmp - nlen) < 10) {
 
1401
                OF_DPRINTF("Buffer too short (%d %d)\n", len - tmp, nlen + 10);
 
1402
                return 0;
 
1403
            }
 
1404
        } else {
 
1405
            if ((len - tmp - nlen) < 1) {
 
1406
                OF_DPRINTF("Buffer too short (%d %d)\n", len - tmp, nlen + 1);
 
1407
                return 0;
 
1408
            }
 
1409
        }
 
1410
        memcpy(name + tmp, prop_name->value, nlen);
 
1411
        if (address != OF_ADDRESS_NONE) {
 
1412
            OF_DPRINTF("Add address 0x%08x\n", address);
 
1413
            sprintf(name + tmp + nlen, "@%x", address);
 
1414
            nlen += strlen(name + tmp + nlen);
 
1415
        } else {
 
1416
            OF_DPRINTF("No address....\n");
 
1417
        }
 
1418
    }
 
1419
    name[tmp + nlen] = '\0';
 
1420
    OF_DPRINTF("stored [%d]\n", tmp + nlen);
 
1421
    OF_DUMP_STRING(env, name);
 
1422
#if 1
 
1423
    OF_DPRINTF("name '%s' => '%s' %d\n",
 
1424
               node->properties->value, name, tmp + nlen);
 
1425
#endif
 
1426
 
 
1427
    return tmp + nlen;
 
1428
}
 
1429
 
 
1430
__attribute__ (( section (".OpenFirmware") ))
 
1431
static int OF_inst_get_path (OF_env_t *env, unsigned char *name,
 
1432
                             int len, OF_inst_t *inst)
 
1433
{
 
1434
    return OF_pack_get_path(env, name, len, inst->node);
 
1435
}
 
1436
 
 
1437
/*****************************************************************************/
 
1438
/*                       Open firmware C interface                           */
 
1439
static void OF_serial_write (OF_env_t *OF_env);
 
1440
static void OF_serial_read (OF_env_t *OF_env);
 
1441
static void OF_mmu_translate (OF_env_t *OF_env);
 
1442
static void OF_mmu_map (OF_env_t *OF_env);
 
1443
static void RTAS_instantiate (OF_env_t *RTAS_env);
 
1444
 
 
1445
static OF_env_t *OF_env_main;
 
1446
 
 
1447
/* Init standard OF structures */
 
1448
__attribute__ (( section (".OpenFirmware") ))
 
1449
int OF_init (void)
 
1450
{
 
1451
#if 0
 
1452
        "PowerMac3,1\0MacRISC\0Power Macintosh\0";
 
1453
        "PowerMac1,2\0MacRISC\0Power Macintosh\0";
 
1454
        "AAPL,PowerMac G3\0PowerMac G3\0MacRISC\0Power Macintosh\0";
 
1455
        "AAPL,PowerMac3,0\0MacRISC\0Power Macintosh\0";
 
1456
        "AAPL,Gossamer\0MacRISC\0Power Macintosh\0";
 
1457
#endif
 
1458
    OF_env_t *OF_env;
 
1459
    OF_node_t *als, *opt, *chs, *pks;
 
1460
    OF_inst_t *inst;
 
1461
    OF_range_t range;
 
1462
 
 
1463
    OF_DPRINTF("start\n");
 
1464
    OF_env_main = malloc(sizeof(OF_env_t));
 
1465
    if (OF_env_main == NULL) {
 
1466
        ERROR("%s cannot allocate main OF env\n", __func__);
 
1467
        return -1;
 
1468
    }
 
1469
    //    memset(OF_env_main, 0, sizeof(OF_env_t));
 
1470
    OF_env = OF_env_main;
 
1471
    //    OF_env_init(OF_env);
 
1472
 
 
1473
    OF_DPRINTF("start\n");
 
1474
    /* Set up standard IEEE 1275 nodes */
 
1475
    /* "/device-tree" */
 
1476
    OF_node_root = OF_node_new(OF_env, NULL, "device-tree", OF_ADDRESS_NONE);
 
1477
    if (OF_node_root == NULL) {
 
1478
        ERROR("Cannot create 'device-tree'\n");
 
1479
        return -1;
 
1480
    }
 
1481
    OF_prop_string_new(OF_env, OF_node_root, "device_type", "bootrom");
 
1482
    if (arch == ARCH_HEATHROW) {
 
1483
        const unsigned char compat_str[] =
 
1484
            "PowerMac1,1\0MacRISC\0Power Macintosh";
 
1485
        OF_property_new(OF_env, OF_node_root, "compatible",
 
1486
                        compat_str, sizeof(compat_str));
 
1487
    OF_prop_string_new(OF_env, OF_node_root,
 
1488
                           "model", "Power Macintosh");
 
1489
    } else {
 
1490
        const unsigned char compat_str[] =
 
1491
            "PowerMac3,1\0MacRISC\0Power Macintosh";
 
1492
    OF_property_new(OF_env, OF_node_root, "compatible",
 
1493
                    compat_str, sizeof(compat_str));
 
1494
        OF_prop_string_new(OF_env, OF_node_root,
 
1495
                           "model", "PowerMac3,1");
 
1496
    }
 
1497
#if 0
 
1498
    OF_prop_string_new(OF_env, OF_node_root, "copyright", copyright);
 
1499
#else
 
1500
    OF_prop_string_new(OF_env, OF_node_root, "copyright",
 
1501
            "Copyright 1983-1999 Apple Computer, Inc. All Rights Reserved");
 
1502
#endif
 
1503
    OF_prop_string_new(OF_env, OF_node_root, "system-id", "42");
 
1504
    OF_prop_int_new(OF_env, OF_node_root, "#address-cells", 1);
 
1505
    OF_prop_int_new(OF_env, OF_node_root, "#size-cells", 1);
 
1506
    OF_prop_int_new(OF_env, OF_node_root, "clock-frequency", 0x05F03E4D);
 
1507
    /* "/aliases" node */
 
1508
    als = OF_node_new(OF_env, OF_node_root, "aliases", OF_ADDRESS_NONE);
 
1509
    if (als == NULL) {
 
1510
        ERROR("Cannot create 'aliases'\n");
 
1511
        return -1;
 
1512
    }
 
1513
    /* "/chosen" node */
 
1514
    chs = OF_node_new(OF_env, OF_node_root, "chosen", OF_ADDRESS_NONE);
 
1515
    if (chs == NULL) {
 
1516
        ERROR("Cannot create 'choosen'\n");
 
1517
        return -1;
 
1518
    }
 
1519
    /* "/packages" node */
 
1520
    pks = OF_node_new(OF_env, OF_node_root, "packages", OF_ADDRESS_NONE);
 
1521
    if (pks == NULL) {
 
1522
        ERROR("Cannot create 'packages'\n");
 
1523
        return -1;
 
1524
    }
 
1525
    /* "/cpus" node */
 
1526
    {
 
1527
        OF_node_t *cpus;
 
1528
        cpus = OF_node_new(OF_env, OF_node_root, "cpus", OF_ADDRESS_NONE);
 
1529
        if (cpus == NULL) {
 
1530
            ERROR("Cannot create 'cpus'\n");
 
1531
            return -1;
 
1532
        }
 
1533
        OF_prop_int_new(OF_env, cpus, "#address-cells", 1);
 
1534
        OF_prop_int_new(OF_env, cpus, "#size-cells", 0);
 
1535
        OF_node_put(OF_env, cpus);
 
1536
    }
 
1537
    /* "/memory@0" node */
 
1538
    {
 
1539
        OF_node_t *mem;
 
1540
        mem = OF_node_new(OF_env, OF_node_root, "memory", 0);
 
1541
        if (mem == NULL) {
 
1542
            ERROR("Cannot create 'memory'\n");
 
1543
            return -1;
 
1544
        }
 
1545
        OF_prop_string_new(OF_env, mem, "device_type", "memory");
 
1546
        OF_prop_int_new(OF_env, chs, "memory", OF_pack_handle(OF_env, mem));
 
1547
        OF_node_put(OF_env, mem);
 
1548
    }
 
1549
    /* "/openprom" node */
 
1550
    {
 
1551
        OF_node_t *opp;
 
1552
        opp = OF_node_new(OF_env, OF_node_root, "openprom", OF_ADDRESS_NONE);
 
1553
        if (opp == NULL) {
 
1554
            ERROR("Cannot create 'openprom'\n");
 
1555
            return -1;
 
1556
        }
 
1557
        OF_prop_string_new(OF_env, opp, "device_type", "BootROM");
 
1558
        OF_prop_string_new(OF_env, opp, "model", "OpenFirmware 3");
 
1559
        OF_prop_int_new(OF_env, opp, "boot-syntax", 0x0001);
 
1560
        OF_property_new(OF_env, opp, "relative-addressing", NULL, 0);
 
1561
        OF_property_new(OF_env, opp, "supports-bootinfo", NULL, 0);
 
1562
        OF_prop_string_new(OF_env, opp, "built-on", stringify(BUILD_DATE));
 
1563
        OF_prop_string_new(OF_env, als, "rom", "/openprom");
 
1564
        OF_node_put(OF_env, opp);
 
1565
    }
 
1566
    /* "/options" node */
 
1567
    opt = OF_node_new(OF_env, OF_node_root, "options", OF_ADDRESS_NONE);
 
1568
    if (opt == NULL) {
 
1569
        ERROR("Cannot create 'options'\n");
 
1570
        return -1;
 
1571
    }
 
1572
    OF_prop_string_new(OF_env, opt, "little-endian?", "false");
 
1573
    OF_prop_string_new(OF_env, opt, "real-mode?", "false");
 
1574
    // Will play with this...
 
1575
    OF_prop_string_new(OF_env, opt, "security-mode", "none");
 
1576
    /* "/rom@ff800000" node */
 
1577
    {
 
1578
        OF_regprop_t regs;
 
1579
        OF_node_t *rom, *brom;
 
1580
 
 
1581
        rom = OF_node_new(OF_env, OF_node_root, "rom", 0xff800000);
 
1582
        if (rom == NULL) {
 
1583
            ERROR("Cannot create 'rom'\n");
 
1584
            return -1;
 
1585
        }
 
1586
        regs.address = 0xFF800000;
 
1587
        regs.size = 0x00000000;
 
1588
        OF_property_new(OF_env, rom, "reg", &regs, sizeof(OF_regprop_t));
 
1589
        range.virt = 0xFF800000;
 
1590
        range.phys = 0xFF800000;
 
1591
        range.size = 0x00800000;
 
1592
        OF_property_new(OF_env, rom, "ranges", &range, sizeof(OF_range_t));
 
1593
        OF_prop_int_new(OF_env, rom, "#address-cells", 1);
 
1594
 
 
1595
        /* "/rom/boot-rom@fff00000" node */
 
1596
        brom = OF_node_new(OF_env, rom, "boot-rom", 0xfff00000);
 
1597
        if (brom == NULL) {
 
1598
            ERROR("Cannot create 'boot-rom'\n");
 
1599
            return -1;
 
1600
        }
 
1601
        regs.address = 0xFFF00000;
 
1602
        regs.size = 0x00100000;
 
1603
        OF_property_new(OF_env, brom, "reg", &regs, sizeof(OF_regprop_t));
 
1604
        OF_prop_string_new(OF_env, brom, "write-characteristic", "flash");
 
1605
        OF_prop_string_new(OF_env, brom, "BootROM-build-date",
 
1606
                           stringify(BUILD_DATE) " at " stringify(BUILD_TIME));
 
1607
        OF_prop_string_new(OF_env, brom, "BootROM-version", BIOS_VERSION);
 
1608
        OF_prop_string_new(OF_env, brom, "copyright", copyright);
 
1609
        OF_prop_string_new(OF_env, brom, "model", BIOS_str);
 
1610
        OF_prop_int_new(OF_env, brom, "result", 0);
 
1611
#if 1
 
1612
        {
 
1613
            /* Hack taken 'as-is' from PearPC */
 
1614
            unsigned char info[] = {
 
1615
                0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
 
1616
                0x00, 0x01, 0x12, 0xf2, 0x19, 0x99, 0x08, 0x19,
 
1617
                0x94, 0x4e, 0x73, 0x27, 0xff, 0xf0, 0x80, 0x00,
 
1618
                0x00, 0x07, 0x80, 0x01, 0x00, 0x01, 0x12, 0xf2,
 
1619
                0x19, 0x99, 0x08, 0x19, 0xd7, 0xf3, 0xfc, 0x17,
 
1620
                0xff, 0xf8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02,
 
1621
                0x00, 0x01, 0x12, 0xf2, 0x19, 0x99, 0x08, 0x19,
 
1622
                0xbb, 0x10, 0xfc, 0x17,
 
1623
            };
 
1624
            OF_property_new(OF_env, brom, "info", info, sizeof(info));
 
1625
        }
 
1626
#endif
 
1627
        OF_node_put(OF_env, brom);
 
1628
        OF_node_put(OF_env, rom);
 
1629
    }
 
1630
#if 0
 
1631
    /* From here, hardcoded hacks to get a Mac-like machine */
 
1632
    /* XXX: Core99 does not seem to like this NVRAM tree */
 
1633
    /* "/nvram@fff04000" node */
 
1634
    {
 
1635
        OF_regprop_t regs;
 
1636
        OF_node_t *nvr;
 
1637
 
 
1638
        nvr = OF_node_new(OF_env, OF_node_root, "nvram", 0xfff04000);
 
1639
        if (nvr == NULL) {
 
1640
            ERROR("Cannot create 'nvram'\n");
 
1641
            return -1;
 
1642
        }
 
1643
        OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
 
1644
        /* XXX: use real NVRAM size instead */
 
1645
        OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
 
1646
        OF_prop_string_new(OF_env, nvr, "compatible", "nvram,flash");
 
1647
        regs.address = 0xFFF04000;
 
1648
        regs.size = 0x00004000; /* Strange, isn't it ? */
 
1649
        OF_property_new(OF_env, nvr, "reg", &regs, sizeof(regs));
 
1650
        OF_prop_int_new(OF_env, chs, "nvram", OF_pack_handle(OF_env, nvr));
 
1651
        OF_node_put(OF_env, nvr);
 
1652
    }
 
1653
#endif
 
1654
    /* "/pseudo-hid" : hid emulation as Apple does */
 
1655
    {
 
1656
        OF_node_t *hid;
 
1657
 
 
1658
        hid = OF_node_new(OF_env, OF_node_root,
 
1659
                          "pseudo-hid", OF_ADDRESS_NONE);
 
1660
        if (hid == NULL) {
 
1661
            ERROR("Cannot create 'pseudo-hid'\n");
 
1662
            return -1;
 
1663
        }
 
1664
        
 
1665
        /* "keyboard" node */
 
1666
        {
 
1667
            OF_node_t *kbd;
 
1668
            kbd = OF_node_new(OF_env, hid, "keyboard", OF_ADDRESS_NONE);
 
1669
            if (kbd == NULL) {
 
1670
                ERROR("Cannot create 'keyboard'\n");
 
1671
                return -1;
 
1672
            }
 
1673
            OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
 
1674
            OF_node_put(OF_env, kbd);
 
1675
        }
 
1676
        /* "mouse" node */
 
1677
        {
 
1678
            OF_node_t *mouse;
 
1679
            mouse = OF_node_new(OF_env, hid, "mouse", OF_ADDRESS_NONE);
 
1680
            if (mouse == NULL) {
 
1681
                ERROR("Cannot create 'mouse'\n");
 
1682
                return -1;
 
1683
            }
 
1684
            OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
 
1685
            OF_node_put(OF_env, mouse);
 
1686
        }
 
1687
        /* "eject-key" node */
 
1688
        {
 
1689
            OF_node_t *ejk;
 
1690
            ejk = OF_node_new(OF_env, hid, "eject-key", OF_ADDRESS_NONE);
 
1691
            if (ejk == NULL) {
 
1692
                ERROR("Cannot create 'eject-key'\n");
 
1693
                return -1;
 
1694
            }
 
1695
            OF_prop_string_new(OF_env, ejk, "device_type", "eject-key");
 
1696
            OF_node_put(OF_env, ejk);
 
1697
        }
 
1698
        OF_node_put(OF_env, hid);
 
1699
    }
 
1700
    if (arch == ARCH_MAC99) {
 
1701
        OF_node_t *unin;
 
1702
        OF_regprop_t regs;
 
1703
 
 
1704
        unin = OF_node_new(OF_env, OF_node_root,
 
1705
                           "uni-n", 0xf8000000);
 
1706
        if (unin == NULL) {
 
1707
            ERROR("Cannot create 'uni-n'\n");
 
1708
            return -1;
 
1709
        }
 
1710
        OF_prop_string_new(OF_env, unin, "device-type", "memory-controller");
 
1711
        OF_prop_string_new(OF_env, unin, "model", "AAPL,UniNorth");
 
1712
        OF_prop_string_new(OF_env, unin, "compatible", "uni-north");
 
1713
        regs.address = 0xf8000000;
 
1714
        regs.size = 0x01000000;
 
1715
        OF_property_new(OF_env, unin, "reg", &regs, sizeof(regs));
 
1716
        OF_prop_int_new(OF_env, unin, "#address-cells", 1);
 
1717
        OF_prop_int_new(OF_env, unin, "#size-cells", 1);
 
1718
        OF_prop_int_new(OF_env, unin, "device-rev", 3);
 
1719
        OF_node_put(OF_env, unin);
 
1720
    }
 
1721
    
 
1722
#if 1 /* This is mandatory for claim to work
 
1723
       * but I don't know where it should really be (in cpu ?)
 
1724
       */
 
1725
    {
 
1726
        OF_node_t *mmu;
 
1727
 
 
1728
        /* "/mmu" node */
 
1729
        mmu = OF_node_new(OF_env, OF_node_root, "mmu", OF_ADDRESS_NONE);
 
1730
        if (mmu == NULL) {
 
1731
            ERROR("Cannot create 'mmu'\n");
 
1732
            return -1;
 
1733
        }
 
1734
        inst = OF_instance_new(OF_env, mmu);
 
1735
        if (inst == NULL) {
 
1736
            OF_node_put(OF_env, mmu);
 
1737
            ERROR("Cannot create 'mmu' instance\n");
 
1738
            return -1;
 
1739
        }
 
1740
        OF_prop_int_new(OF_env, chs, "mmu",
 
1741
                        OF_instance_get_id(OF_env, inst));
 
1742
        OF_method_new(OF_env, mmu, "translate", &OF_mmu_translate);
 
1743
        OF_method_new(OF_env, mmu, "map", &OF_mmu_map);
 
1744
        OF_node_put(OF_env, mmu);
 
1745
    }
 
1746
#endif
 
1747
 
 
1748
    /* "/options/boot-args" node */
 
1749
    {
 
1750
        //        const unsigned char *args = "-v rootdev cdrom";
 
1751
        //const unsigned char *args = "-v io=0xffffffff";
 
1752
        const unsigned char *args = "-v";
 
1753
        /* Ask MacOS X to print debug messages */
 
1754
        //        OF_prop_string_new(OF_env, chs, "machargs", args);
 
1755
        //        OF_prop_string_new(OF_env, opt, "boot-command", args);
 
1756
        OF_prop_string_new(OF_env, opt, "boot-args", args);
 
1757
    }
 
1758
    
 
1759
    /* Release nodes */
 
1760
    OF_node_put(OF_env, opt);
 
1761
    OF_node_put(OF_env, pks);
 
1762
    OF_node_put(OF_env, chs);
 
1763
    OF_node_put(OF_env, als);
 
1764
    OF_node_put(OF_env, OF_node_root);
 
1765
    OF_DPRINTF("done\n");
 
1766
    
 
1767
    return 0;
 
1768
}
 
1769
 
 
1770
/* Motherboard */
 
1771
#if 0 // For now, static values are used
 
1772
__attribute__ (( section (".OpenFirmware") ))
 
1773
int OF_register_mb (const unsigned char *model, const unsigned char **compats)
 
1774
{
 
1775
    OF_env_t *OF_env;
 
1776
    OF_node_t *root;
 
1777
    int i;
 
1778
    
 
1779
    OF_env = OF_env_main;
 
1780
    OF_DPRINTF("start\n");
 
1781
    root = OF_node_get(OF_env, "device_tree");
 
1782
    if (root == NULL) {
 
1783
        ERROR("Cannot get 'device-tree'\n");
 
1784
        return -1;
 
1785
    }
 
1786
    OF_DPRINTF("add model\n");
 
1787
    OF_prop_string_new(OF_env, OF_node_root, "model", model);
 
1788
    for (i = 0; i < 1 && compats[i] != NULL; i++) {
 
1789
        OF_DPRINTF("add compats %s\n", compats[i]);
 
1790
        OF_set_compatibility(OF_env, OF_node_root, compats[i]);
 
1791
    }
 
1792
    /* we don't implement neither "l2-cache" nor "cache" nodes */
 
1793
    OF_node_put(OF_env, root);
 
1794
    OF_DPRINTF("done\n");
 
1795
 
 
1796
    return 0;
 
1797
}
 
1798
#endif
 
1799
 
 
1800
/* CPU */
 
1801
__attribute__ (( section (".OpenFirmware") ))
 
1802
int OF_register_cpu (const unsigned char *name, int num, uint32_t pvr,
 
1803
                     uint32_t min_freq, uint32_t max_freq, uint32_t bus_freq,
 
1804
                     uint32_t tb_freq, uint32_t reset_io)
 
1805
{
 
1806
    unsigned char tmp[OF_NAMELEN_MAX];
 
1807
    OF_env_t *OF_env;
 
1808
    OF_node_t *cpus, *cpu, *l2c, *chs, *als;
 
1809
 
 
1810
    OF_env = OF_env_main;
 
1811
    OF_DPRINTF("start\n");
 
1812
    cpus = OF_node_get(OF_env, "cpus");
 
1813
    if (cpus == NULL) {
 
1814
        ERROR("Cannot get 'cpus'\n");
 
1815
        return -1;
 
1816
    }
 
1817
    cpu = OF_node_new(OF_env, cpus, name, OF_ADDRESS_NONE);
 
1818
    if (cpu == NULL) {
 
1819
        OF_node_put(OF_env, cpus);
 
1820
        ERROR("Cannot create cpu '%s'\n", name);
 
1821
        return -1;
 
1822
    }
 
1823
    OF_prop_string_new(OF_env, cpu, "device_type", "cpu");
 
1824
    OF_prop_int_new(OF_env, cpu, "#address-cells", 0x00000001);
 
1825
    OF_prop_int_new(OF_env, cpu, "#size-cells", 0x00000000);
 
1826
    OF_prop_int_new(OF_env, cpu, "reg", num);
 
1827
    OF_prop_int_new(OF_env, cpu, "cpu-version", pvr);
 
1828
    OF_prop_int_new(OF_env, cpu, "clock-frequency", max_freq);
 
1829
    OF_prop_int_new(OF_env, cpu, "timebase-frequency", tb_freq);
 
1830
    OF_prop_int_new(OF_env, cpu, "bus-frequency", bus_freq);
 
1831
    OF_prop_int_new(OF_env, cpu, "min-clock-frequency", min_freq);
 
1832
    OF_prop_int_new(OF_env, cpu, "max-clock-frequency", max_freq);
 
1833
    OF_prop_int_new(OF_env, cpu, "tlb-size", 0x80);
 
1834
    OF_prop_int_new(OF_env, cpu, "tlb-sets", 0x40);
 
1835
    OF_prop_int_new(OF_env, cpu, "i-tlb-size", 0x40);
 
1836
    OF_prop_int_new(OF_env, cpu, "i-tlb-sets", 0x20);
 
1837
    OF_prop_int_new(OF_env, cpu, "i-cache-size", 0x8000);
 
1838
    OF_prop_int_new(OF_env, cpu, "i-cache-sets", 0x80);
 
1839
    OF_prop_int_new(OF_env, cpu, "i-cache-bloc-size", 0x20);
 
1840
    OF_prop_int_new(OF_env, cpu, "i-cache-line-size", 0x20);
 
1841
    OF_prop_int_new(OF_env, cpu, "d-tlb-size", 0x40);
 
1842
    OF_prop_int_new(OF_env, cpu, "d-tlb-sets", 0x20);
 
1843
    OF_prop_int_new(OF_env, cpu, "d-cache-size", 0x8000);
 
1844
    OF_prop_int_new(OF_env, cpu, "d-cache-sets", 0x80);
 
1845
    OF_prop_int_new(OF_env, cpu, "d-cache-bloc-size", 0x20);
 
1846
    OF_prop_int_new(OF_env, cpu, "d-cache-line-size", 0x20);
 
1847
    OF_prop_int_new(OF_env, cpu, "reservation-granule-size", 0x20);
 
1848
    OF_prop_int_new(OF_env, cpus, "soft-reset", reset_io);
 
1849
    OF_prop_string_new(OF_env, cpus, "graphics", "");
 
1850
    OF_prop_string_new(OF_env, cpus, "performance-monitor", "");
 
1851
    OF_prop_string_new(OF_env, cpus, "data-streams", "");
 
1852
    OF_prop_string_new(OF_env, cpu, "state", "running");
 
1853
    /* We don't implement:
 
1854
     * "dynamic-powerstep" & "reduced-clock-frequency"
 
1855
     * "l2cr-value"
 
1856
     */
 
1857
    /* Add L2 cache */
 
1858
    l2c = OF_node_new(OF_env, cpu, "l2cache", OF_ADDRESS_NONE);
 
1859
    if (l2c == NULL) {
 
1860
        ERROR("Cannot create 'l2cache'\n");
 
1861
        return -1;
 
1862
    }
 
1863
    OF_prop_string_new(OF_env, l2c, "device_type", "cache");
 
1864
    OF_prop_int_new(OF_env, l2c, "i-cache-size", 0x100000);
 
1865
    OF_prop_int_new(OF_env, l2c, "i-cache-sets", 0x2000);
 
1866
    OF_prop_int_new(OF_env, l2c, "i-cache-line-size", 0x40);
 
1867
    OF_prop_int_new(OF_env, l2c, "d-cache-size", 0x100000);
 
1868
    OF_prop_int_new(OF_env, l2c, "d-cache-sets", 0x2000);
 
1869
    OF_prop_int_new(OF_env, l2c, "d-cache-line-size", 0x40);
 
1870
    /* Register it in the cpu node */
 
1871
    OF_prop_int_new(OF_env, cpu, "l2-cache", OF_pack_handle(OF_env, l2c));
 
1872
    OF_node_put(OF_env, l2c);
 
1873
    /* Set it in "/chosen" and "/aliases" */
 
1874
    if (num == 0) {
 
1875
        OF_pack_get_path(OF_env, tmp, 512, cpu);
 
1876
        chs = OF_node_get(OF_env, "chosen");
 
1877
        if (chs == NULL) {
 
1878
            OF_node_put(OF_env, cpus);
 
1879
            ERROR("Cannot get 'chosen'\n");
 
1880
            return -1;
 
1881
        }
 
1882
        OF_prop_int_new(OF_env, chs, "cpu", OF_pack_handle(OF_env, cpu));
 
1883
        OF_node_put(OF_env, chs);
 
1884
        als = OF_node_get(OF_env, "aliases");
 
1885
        if (als == NULL) {
 
1886
            OF_node_put(OF_env, cpus);
 
1887
            ERROR("Cannot get 'aliases'\n");
 
1888
            return -1;
 
1889
        }
 
1890
        OF_prop_string_new(OF_env, als, "cpu", tmp);
 
1891
        OF_node_put(OF_env, als);
 
1892
    }
 
1893
    OF_node_put(OF_env, cpu);
 
1894
    OF_node_put(OF_env, cpus);
 
1895
    OF_DPRINTF("done\n");
 
1896
 
 
1897
    return 0;
 
1898
}
 
1899
 
 
1900
__attribute__ (( section (".OpenFirmware") ))
 
1901
int OF_register_translations (int nb, OF_transl_t *translations)
 
1902
{
 
1903
    OF_env_t *OF_env;
 
1904
    OF_node_t *cpus, *cpu;
 
1905
    OF_transl_t *new;
 
1906
    int i;
 
1907
 
 
1908
    OF_env = OF_env_main;
 
1909
    OF_DPRINTF("start\n");
 
1910
    cpus = OF_node_get(OF_env, "cpus");
 
1911
    if (cpus == NULL) {
 
1912
        OF_node_put(OF_env, cpus);
 
1913
        ERROR("Cannot get 'cpus'\n");
 
1914
        return -1;
 
1915
    }
 
1916
    cpu = cpus->children;
 
1917
    new = malloc(nb * sizeof(OF_transl_t));
 
1918
    if (new == NULL) {
 
1919
        ERROR("Cannot create new translation\n");
 
1920
        return -1;
 
1921
    }
 
1922
    for (i = 0; i < nb; i++) {
 
1923
        new->virt = translations[i].virt;
 
1924
        new->size = translations[i].size;
 
1925
        new->phys = translations[i].phys;
 
1926
        new->mode = translations[i].mode;
 
1927
        OF_DPRINTF("%d\n", i);
 
1928
    }
 
1929
    OF_property_new(OF_env, cpu, "translations",
 
1930
                    new, nb * sizeof(OF_transl_t));
 
1931
    OF_node_put(OF_env, cpus);
 
1932
    OF_DPRINTF("done\n");
 
1933
    
 
1934
    return 0;
 
1935
}
 
1936
 
 
1937
/* Memory ranges */
 
1938
typedef struct OF_mem_t OF_mem_t;
 
1939
struct OF_mem_t {
 
1940
    uint32_t start;
 
1941
    uint32_t size;
 
1942
};
 
1943
 
 
1944
#define OF_MAX_MEMRANGES 16
 
1945
/* First entry is the whole known memory space */
 
1946
static OF_mem_t OF_mem_ranges[OF_MAX_MEMRANGES + 1];
 
1947
 
 
1948
__attribute__ (( section (".OpenFirmware") ))
 
1949
int OF_register_memory (uint32_t memsize, unused uint32_t bios_size)
 
1950
{
 
1951
    OF_env_t *OF_env;
 
1952
    OF_node_t *mem;
 
1953
    OF_regprop_t regs[4];
 
1954
    int i;
 
1955
 
 
1956
    OF_env = OF_env_main;
 
1957
    OF_DPRINTF("find node\n");
 
1958
    mem = OF_node_get(OF_env, "memory");
 
1959
    if (mem == NULL) {
 
1960
        ERROR("Cannot get 'memory'\n");
 
1961
        return -1;
 
1962
    }
 
1963
    OF_DPRINTF("Memory package: %04x\n", OF_pack_handle(OF_env, mem));
 
1964
    regs[0].address = 0x00000000;
 
1965
    regs[0].size = memsize;
 
1966
    regs[1].address = 0x00000000;
 
1967
    regs[1].size = 0x00000000;
 
1968
    regs[2].address = 0x00000000;
 
1969
    regs[2].size = 0x00000000;
 
1970
    regs[3].address = 0x00000000;
 
1971
    regs[3].size = 0x00000000;
 
1972
    OF_property_new(OF_env, mem, "reg", regs, 4 * sizeof(OF_regprop_t));
 
1973
#if 0
 
1974
#if 1
 
1975
    regs[0].address = 0x00000000;
 
1976
    regs[0].size = 0x05800000;
 
1977
    regs[1].address = 0x06000000;
 
1978
    regs[1].size = memsize - 0x06000000;
 
1979
    regs[2].address = 0x00000000;
 
1980
    regs[2].size = 0x00000000;
 
1981
    OF_property_new(OF_env, mem, "available",
 
1982
                    regs, 3 * sizeof(OF_regprop_t));
 
1983
#else
 
1984
    regs[0].address = 0x06000000;
 
1985
    regs[0].size = memsize - 0x06000000;
 
1986
    regs[1].address = 0x00000000;
 
1987
    regs[1].size = 0x00000000;
 
1988
    OF_property_new(OF_env, mem, "available",
 
1989
                    regs, 2 * sizeof(OF_regprop_t));
 
1990
#endif
 
1991
#endif
 
1992
    OF_node_put(OF_env, mem);
 
1993
#if 0
 
1994
    {
 
1995
        OF_node_t *mmu;
 
1996
        mmu = OF_node_get(OF_env, "mmu");
 
1997
        if (mmu == NULL) {
 
1998
            ERROR("Cannot get 'mmu'\n");
 
1999
            return -1;
 
2000
        }
 
2001
        regs[0].address = 0x00000000;
 
2002
        regs[0].size = memsize;
 
2003
        OF_property_new(OF_env, mmu, "reg", regs, sizeof(OF_regprop_t));
 
2004
        regs[0].address = 0x00000000;
 
2005
        regs[0].size = 0x05800000;
 
2006
        regs[1].address = 0x06000000;
 
2007
        regs[1].size = memsize - 0x06000000;
 
2008
        regs[2].address = 0x00000000;
 
2009
        regs[2].size = 0x00000000;
 
2010
        OF_property_new(OF_env, mmu, "available",
 
2011
                        regs, 3 * sizeof(OF_regprop_t));
 
2012
        OF_node_put(OF_env, mmu);
 
2013
    }
 
2014
#endif
 
2015
    /* Also update the claim areas */
 
2016
    OF_mem_ranges[0].start = 0x00000000;
 
2017
    OF_mem_ranges[0].size = memsize;
 
2018
    OF_mem_ranges[1].start = 0x58000000;
 
2019
    OF_mem_ranges[1].size = 0x08000000;
 
2020
    for (i = 2; i < OF_MAX_MEMRANGES + 1; i++) {
 
2021
        OF_mem_ranges[i].start = -1;
 
2022
        OF_mem_ranges[i].size = -1;
 
2023
    }
 
2024
    OF_DPRINTF("done\n");
 
2025
 
 
2026
    return 0;
 
2027
}
 
2028
 
 
2029
/* Linux kernel command line */
 
2030
__attribute__ (( section (".OpenFirmware") ))
 
2031
int OF_register_bootargs (const unsigned char *bootargs)
 
2032
{
 
2033
    OF_env_t *OF_env;
 
2034
    OF_node_t *chs;
 
2035
 
 
2036
    OF_env = OF_env_main;
 
2037
    if (bootargs == NULL)
 
2038
        bootargs = "";
 
2039
    chs = OF_node_get(OF_env, "chosen");
 
2040
    if (chs == NULL) {
 
2041
        ERROR("Cannot get 'chosen'\n");
 
2042
        return -1;
 
2043
    }
 
2044
    OF_prop_string_set(OF_env, chs, "bootargs", bootargs);
 
2045
    //        OF_prop_string_set(OF_env, OF_node_root, "bootargs", "");
 
2046
    OF_node_put(OF_env, chs);
 
2047
 
 
2048
    return 0;
 
2049
}
 
2050
 
 
2051
__attribute__ (( section (".OpenFirmware") ))
 
2052
static void *OF_pci_device_new (OF_env_t *OF_env, OF_node_t *parent,
 
2053
                                pci_dev_t *dev, uint32_t address,
 
2054
                                uint16_t rev, uint32_t ccode,
 
2055
                                uint16_t min_grant, uint16_t max_latency)
 
2056
{
 
2057
    OF_node_t *node;
 
2058
 
 
2059
    dprintf("register '%s' '%s' '%s' '%s' 0x%08x in '%s' 0x%08x\n",
 
2060
           dev->name, dev->type, dev->compat, dev->model, address,
 
2061
           parent->prop_name->value, *(uint32_t *)parent->prop_address->value);
 
2062
    node = OF_node_new(OF_env, parent, dev->name, address);
 
2063
    if (node == NULL)
 
2064
        return NULL;
 
2065
    OF_prop_int_new(OF_env, node, "vendor-id", dev->vendor);
 
2066
    OF_prop_int_new(OF_env, node, "device-id", dev->product);
 
2067
    OF_prop_int_new(OF_env, node, "revision-id", rev);
 
2068
    OF_prop_int_new(OF_env, node, "class-code", ccode);
 
2069
    OF_prop_int_new(OF_env, node, "min-grant", min_grant);
 
2070
    OF_prop_int_new(OF_env, node, "max-latency", max_latency);
 
2071
    if (dev->type != NULL)
 
2072
        OF_prop_string_new1(OF_env, node, "device_type", dev->type);
 
2073
    if (dev->compat != NULL)
 
2074
        OF_prop_string_new1(OF_env, node, "compatible", dev->compat);
 
2075
    if (dev->model != NULL)
 
2076
        OF_prop_string_new1(OF_env, node, "model", dev->model);
 
2077
    if (dev->acells != 0)
 
2078
        OF_prop_int_new(OF_env, node, "#address-cells", dev->acells);
 
2079
    if (dev->scells != 0)
 
2080
        OF_prop_int_new(OF_env, node, "#size-cells", dev->scells);
 
2081
    if (dev->icells != 0)
 
2082
        OF_prop_int_new(OF_env, node, "#interrupt-cells", dev->icells);
 
2083
    dprintf("Done %p %p\n", parent, node);
 
2084
    
 
2085
    return node;
 
2086
}
 
2087
 
 
2088
__attribute__ (( section (".OpenFirmware") ))
 
2089
void *OF_register_pci_host (pci_dev_t *dev, uint16_t rev, uint32_t ccode,
 
2090
                            uint32_t cfg_base, uint32_t cfg_len,
 
2091
                            uint32_t mem_base, uint32_t mem_len,
 
2092
                            uint32_t io_base, uint32_t io_len,
 
2093
                            uint32_t rbase, uint32_t rlen,
 
2094
                            uint16_t min_grant, uint16_t max_latency)
 
2095
{
 
2096
    OF_env_t *OF_env;
 
2097
    pci_range_t ranges[3];
 
2098
    OF_regprop_t regs[1];
 
2099
    OF_node_t *pci_host, *als;
 
2100
    int nranges;
 
2101
    unsigned char buffer[OF_NAMELEN_MAX];
 
2102
 
 
2103
    OF_env = OF_env_main;
 
2104
    dprintf("register PCI host '%s' '%s' '%s' '%s'\n",
 
2105
            dev->name, dev->type, dev->compat, dev->model);
 
2106
    pci_host = OF_pci_device_new(OF_env, OF_node_root, dev, cfg_base,
 
2107
                                 rev, ccode, min_grant, max_latency);
 
2108
    if (pci_host == NULL) {
 
2109
        ERROR("Cannot create pci host\n");
 
2110
        return NULL;
 
2111
    }
 
2112
    
 
2113
    als = OF_node_get(OF_env, "aliases");
 
2114
    if (als == NULL) {
 
2115
        ERROR("Cannot get 'aliases'\n");
 
2116
        return NULL;
 
2117
    }
 
2118
    sprintf(buffer, "/%s", dev->name);
 
2119
    OF_prop_string_set(OF_env, als, "pci", buffer);
 
2120
    OF_node_put(OF_env, als);
 
2121
    
 
2122
 
 
2123
    regs[0].address = cfg_base;
 
2124
    regs[0].size = cfg_len;
 
2125
    OF_property_new(OF_env, pci_host, "reg", regs, sizeof(OF_regprop_t));
 
2126
    nranges = 0;
 
2127
    if (rbase != 0x00000000) {
 
2128
        ranges[nranges].addr.hi  = 0x02000000;
 
2129
        ranges[nranges].addr.mid = 0x00000000;
 
2130
        ranges[nranges].addr.lo  = rbase;
 
2131
        ranges[nranges].phys     = rbase;
 
2132
        ranges[nranges].size_hi  = 0x00000000;
 
2133
        ranges[nranges].size_lo  = rlen;
 
2134
        nranges++;
 
2135
    }
 
2136
    if (io_base != 0x00000000) {
 
2137
        ranges[nranges].addr.hi  = 0x01000000;
 
2138
        ranges[nranges].addr.mid = 0x00000000;
 
2139
        ranges[nranges].addr.lo  = 0x00000000;
 
2140
        ranges[nranges].phys     = io_base;
 
2141
        ranges[nranges].size_hi  = 0x00000000;
 
2142
        ranges[nranges].size_lo  = io_len;
 
2143
        nranges++;
 
2144
    }
 
2145
    if (mem_base != 0x00000000) {
 
2146
        ranges[nranges].addr.hi  = 0x02000000;
 
2147
        ranges[nranges].addr.mid = 0x00000000;
 
2148
        ranges[nranges].addr.lo  = mem_base;
 
2149
        ranges[nranges].phys     = mem_base;
 
2150
        ranges[nranges].size_hi  = 0x00000000;
 
2151
        ranges[nranges].size_lo  = mem_len;
 
2152
        nranges++;
 
2153
    }
 
2154
    OF_property_new(OF_env, pci_host, "ranges", ranges,
 
2155
                    nranges * sizeof(pci_range_t));
 
2156
 
 
2157
    return pci_host;
 
2158
}
 
2159
 
 
2160
__attribute__ (( section (".OpenFirmware") ))
 
2161
void *OF_register_pci_bridge (void *parent, pci_dev_t *dev,
 
2162
                              uint32_t cfg_base, uint32_t cfg_len,
 
2163
                              uint8_t devfn, uint8_t rev, uint32_t ccode,
 
2164
                              uint16_t min_grant, uint16_t max_latency)
 
2165
{
 
2166
    OF_env_t *OF_env;
 
2167
    OF_regprop_t regs[1];
 
2168
    OF_node_t *pci_bridge;
 
2169
 
 
2170
    OF_env = OF_env_main;
 
2171
    OF_DPRINTF("register '%s' %08x '%s' '%s' '%s'\n",
 
2172
               dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
 
2173
    dprintf("register PCI bridge '%s' %08x '%s' '%s' '%s'\n",
 
2174
            dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
 
2175
    pci_bridge = OF_pci_device_new(OF_env, parent, dev, devfn >> 3,
 
2176
                                   rev, ccode, min_grant, max_latency);
 
2177
    if (pci_bridge == NULL) {
 
2178
        ERROR("Cannot create pci bridge\n");
 
2179
        return NULL;
 
2180
    }
 
2181
    regs[0].address = cfg_base;
 
2182
    regs[0].size = cfg_len;
 
2183
    OF_property_new(OF_env, pci_bridge, "reg", regs, sizeof(OF_regprop_t));
 
2184
 
 
2185
    return pci_bridge;
 
2186
}
 
2187
 
 
2188
__attribute__ (( section (".OpenFirmware") ))
 
2189
void *OF_register_pci_device (void *parent, pci_dev_t *dev,
 
2190
                              uint8_t devfn, uint8_t rev, uint32_t ccode,
 
2191
                              uint16_t min_grant, uint16_t max_latency)
 
2192
{
 
2193
    OF_env_t *OF_env;
 
2194
    OF_node_t *pci_dev;
 
2195
 
 
2196
    OF_env = OF_env_main;
 
2197
    OF_DPRINTF("register '%s' %08x '%s' '%s' '%s'\n",
 
2198
               dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
 
2199
    dprintf("register pci device '%s' %08x '%s' '%s' '%s'\n",
 
2200
               dev->name, devfn >> 3, dev->type, dev->compat, dev->model);
 
2201
    pci_dev = OF_pci_device_new(OF_env, parent, dev, devfn >> 3,
 
2202
                                rev, ccode, min_grant, max_latency);
 
2203
 
 
2204
    return pci_dev;
 
2205
}
 
2206
 
 
2207
/* XXX: suppress that, used for interrupt map init */
 
2208
OF_node_t *pci_host_node;
 
2209
uint32_t pci_host_interrupt_map[7 * 32];
 
2210
int pci_host_interrupt_map_len = 0;
 
2211
 
 
2212
void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses)
 
2213
{
 
2214
    OF_env_t *OF_env;
 
2215
    OF_regprop_t regs[1];
 
2216
    
 
2217
    OF_env = OF_env_main;
 
2218
    regs[0].address = first_bus;
 
2219
    regs[0].size = nb_busses;
 
2220
    OF_property_new(OF_env, dev, "bus-range", regs, sizeof(OF_regprop_t));
 
2221
    pci_host_node = dev;
 
2222
}
 
2223
 
 
2224
void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
 
2225
                             uint32_t *regions, uint32_t *sizes,
 
2226
                             int irq_line)
 
2227
{
 
2228
    OF_env_t *OF_env;
 
2229
    pci_reg_prop_t pregs[6], rregs[6];
 
2230
    uint32_t mask;
 
2231
    int i, j, k;
 
2232
 
 
2233
    OF_env = OF_env_main;
 
2234
    /* XXX: only useful for VGA card in fact */
 
2235
    if (regions[0] != 0x00000000)
 
2236
        OF_prop_int_set(OF_env, dev, "address", regions[0] & ~0x0000000F);
 
2237
    for (i = 0, j = 0, k = 0; i < 6; i++) {
 
2238
        if (regions[i] != 0x00000000 && sizes[i] != 0x00000000) {
 
2239
            /* Generate "reg" property
 
2240
             */
 
2241
            if (regions[i] & 1) {
 
2242
                /* IO space */
 
2243
                rregs[j].addr.hi = 0x01000000;
 
2244
                mask = 0x00000001;
 
2245
            } else if (regions[i] & 4) {
 
2246
                /* 64 bits address space */
 
2247
                rregs[j].addr.hi = 0x83000000;
 
2248
                mask = 0x0000000F;
 
2249
#if 0
 
2250
            } else if ((regions[i] & 0xF) == 0x00) { /* ? */
 
2251
                /* Configuration space */
 
2252
                rregs[j].addr.hi = 0x00000000;
 
2253
                mask = 0x0000000F;
 
2254
#endif
 
2255
            } else {
 
2256
                /* 32 bits address space */
 
2257
                rregs[j].addr.hi = 0x82000000;
 
2258
                mask = 0x0000000F;
 
2259
            }
 
2260
            /* Set bus number */
 
2261
            rregs[j].addr.hi |= bus << 16;
 
2262
            /* Set device/function */
 
2263
            rregs[j].addr.hi |= devfn << 8;
 
2264
            /* Set register */
 
2265
#if 1
 
2266
            rregs[j].addr.hi |= 0x10 + (i * sizeof(uint32_t)); /* ? */
 
2267
#endif
 
2268
            /* Set address */
 
2269
            rregs[j].addr.mid = 0x00000000;
 
2270
            rregs[j].addr.lo = regions[i] & ~mask;
 
2271
            /* Set size */
 
2272
            rregs[j].size_hi = 0x00000000;
 
2273
            rregs[j].size_lo = sizes[i];
 
2274
#if 0
 
2275
            if ((rregs[j].addr.hi & 0x03000000) != 0x00000000)
 
2276
#endif
 
2277
            {
 
2278
                /* No assigned address for configuration space */
 
2279
                pregs[k].addr.hi = rregs[j].addr.hi; /* ? */
 
2280
                pregs[k].addr.mid = rregs[j].addr.mid;
 
2281
                pregs[k].addr.lo = rregs[j].addr.lo; /* ? */
 
2282
                pregs[k].size_hi = rregs[j].size_hi;
 
2283
                pregs[k].size_lo = rregs[j].size_lo;
 
2284
                k++;
 
2285
            }
 
2286
            j++;
 
2287
        }
 
2288
    }
 
2289
    if (j > 0) {
 
2290
        OF_property_new(OF_env, dev, "reg",
 
2291
                        rregs, j * sizeof(pci_reg_prop_t));
 
2292
    } else {
 
2293
        OF_property_new(OF_env, dev, "reg", NULL, 0);
 
2294
    }
 
2295
    if (k > 0) {
 
2296
        OF_property_new(OF_env, dev, "assigned-addresses",
 
2297
                        pregs, k * sizeof(pci_reg_prop_t));
 
2298
    } else {
 
2299
        OF_property_new(OF_env, dev, "assigned-addresses", NULL, 0);
 
2300
    }
 
2301
    if (irq_line >= 0) {
 
2302
        int i;
 
2303
        OF_prop_int_new(OF_env, dev, "interrupts", 1);
 
2304
        i = pci_host_interrupt_map_len;
 
2305
        pci_host_interrupt_map[i++] = (devfn << 8) & 0xf800;
 
2306
        pci_host_interrupt_map[i++] = 0;
 
2307
        pci_host_interrupt_map[i++] = 0;
 
2308
        pci_host_interrupt_map[i++] = 0;
 
2309
        pci_host_interrupt_map[i++] = 0; /* pic handle will be patched later */
 
2310
        pci_host_interrupt_map[i++] = irq_line;
 
2311
        if (arch != ARCH_HEATHROW) {
 
2312
            pci_host_interrupt_map[i++] = 1;
 
2313
        }
 
2314
        pci_host_interrupt_map_len = i;
 
2315
    }
 
2316
#if 1
 
2317
    {
 
2318
        OF_prop_t *prop_name = ((OF_node_t *)dev)->prop_name;
 
2319
 
 
2320
        if (j > 0) {
 
2321
            dprintf("PCI device '%s' %d %d %d reg properties:\n",
 
2322
                    prop_name->value, bus, devfn >> 3, devfn & 7);
 
2323
            for (i = 0; i < j; i++) {
 
2324
                dprintf("  addr: %08x %08x %08x size: %08x %08x\n",
 
2325
                        rregs[i].addr.hi, rregs[i].addr.mid, rregs[i].addr.lo,
 
2326
                        rregs[i].size_hi, rregs[i].size_lo);
 
2327
            }
 
2328
        } else {
 
2329
            dprintf("PCI device '%s' %d %d %d has no reg properties:\n",
 
2330
                    prop_name->value, bus, devfn >> 3, devfn & 7);
 
2331
        }
 
2332
        if (k > 0) {
 
2333
            dprintf("PCI device '%s' %d %d %d "
 
2334
                    "assigned addresses properties:\n",
 
2335
                    prop_name->value, bus, devfn >> 3, devfn & 7);
 
2336
            for (i = 0; i < j; i++) {
 
2337
                dprintf("  addr: %08x %08x %08x size: %08x %08x\n",
 
2338
                        pregs[i].addr.hi, pregs[i].addr.mid, pregs[i].addr.lo,
 
2339
                        pregs[i].size_hi, pregs[i].size_lo);
 
2340
            }
 
2341
        } else {
 
2342
            dprintf("PCI device '%s' %d %d %d has no "
 
2343
                    "assigned addresses properties:\n",
 
2344
                    prop_name->value, bus, devfn >> 3, devfn & 7);
 
2345
        }
 
2346
    }
 
2347
#endif
 
2348
}
 
2349
 
 
2350
__attribute__ (( section (".OpenFirmware") ))
 
2351
int OF_register_bus (const unsigned char *name, uint32_t address,
 
2352
                     const unsigned char *type)
 
2353
{
 
2354
    unsigned char buffer[OF_NAMELEN_MAX];
 
2355
    OF_env_t *OF_env;
 
2356
    OF_node_t *bus, *als;
 
2357
    
 
2358
    OF_env = OF_env_main;
 
2359
    als = OF_node_get(OF_env, "aliases");
 
2360
    if (als == NULL) {
 
2361
        ERROR("Cannot get 'aliases'\n");
 
2362
        return -1;
 
2363
    }
 
2364
    bus = OF_node_new(OF_env, OF_node_root, name, address);
 
2365
    if (bus == NULL) {
 
2366
        OF_node_put(OF_env, als);
 
2367
        ERROR("Cannot create bus '%s'\n", name);
 
2368
        return -1;
 
2369
    }
 
2370
    OF_prop_string_set(OF_env, bus, "type", type);
 
2371
    sprintf(buffer, "/%s", name);
 
2372
    OF_prop_string_set(OF_env, als, name, buffer);
 
2373
    /* For ISA, should add DMA ranges */
 
2374
    OF_node_put(OF_env, bus);
 
2375
    OF_node_put(OF_env, als);
 
2376
 
 
2377
    return 0;
 
2378
}
 
2379
 
 
2380
// We will need to register stdin & stdout via the serial port
 
2381
__attribute__ (( section (".OpenFirmware") ))
 
2382
int OF_register_serial (const unsigned char *bus, const unsigned char *name,
 
2383
                        uint32_t io_base, unused int irq)
 
2384
{
 
2385
    unsigned char tmp[OF_NAMELEN_MAX];
 
2386
    OF_env_t *OF_env;
 
2387
    OF_node_t *busn, *srl, *als;
 
2388
 
 
2389
    OF_env = OF_env_main;
 
2390
    als = OF_node_get(OF_env, "aliases");
 
2391
    if (als == NULL) {
 
2392
        ERROR("Cannot get 'aliases'\n");
 
2393
        return -1;
 
2394
    }
 
2395
    busn = OF_node_get(OF_env, bus);
 
2396
    srl = OF_node_new(OF_env, busn, name, io_base);
 
2397
    if (srl == NULL) {
 
2398
        OF_node_put(OF_env, als);
 
2399
        ERROR("Cannot create serial '%s'\n", name);
 
2400
        return -1;
 
2401
    }
 
2402
    OF_prop_string_set(OF_env, srl, "device_type", "serial");
 
2403
    OF_prop_string_set(OF_env, srl, "compatible", "pnpPNP,501");
 
2404
    switch (io_base) {
 
2405
    case 0x3F8:
 
2406
        OF_pack_get_path(OF_env, tmp, 512, srl);
 
2407
        OF_prop_string_new(OF_env, als, "com1", tmp);
 
2408
        break;
 
2409
    case 0x2F8:
 
2410
        OF_pack_get_path(OF_env, tmp, 512, srl);
 
2411
        OF_prop_string_new(OF_env, als, "com2", tmp);
 
2412
        break;
 
2413
    default:
 
2414
        break;
 
2415
    }
 
2416
    /* register read/write methods and create an instance of the package */
 
2417
    OF_method_new(OF_env, srl, "write", &OF_serial_write);
 
2418
    OF_method_new(OF_env, srl, "read", &OF_serial_read);
 
2419
    OF_node_put(OF_env, srl);
 
2420
    OF_node_put(OF_env, busn);
 
2421
    OF_node_put(OF_env, als);
 
2422
 
 
2423
    return 0;
 
2424
}
 
2425
 
 
2426
/* We will also need /isa/rtc */
 
2427
 
 
2428
__attribute__ (( section (".OpenFirmware") ))
 
2429
int OF_register_stdio (const unsigned char *dev_in,
 
2430
                       const unsigned char *dev_out)
 
2431
{
 
2432
    OF_env_t *OF_env;
 
2433
    OF_node_t *chs, *ndev_in, *ndev_out, *kbd;
 
2434
    OF_inst_t *in_inst, *out_inst;
 
2435
    
 
2436
    OF_env = OF_env_main;
 
2437
    chs = OF_node_get(OF_env, "chosen");
 
2438
    if (chs == NULL) {
 
2439
        ERROR("Cannot get 'chosen'\n");
 
2440
        return -1;
 
2441
    }
 
2442
    ndev_in = OF_node_get(OF_env, dev_in);
 
2443
    ndev_out = OF_node_get(OF_env, dev_out);
 
2444
    in_inst = OF_instance_new(OF_env, ndev_in);
 
2445
    if (in_inst == NULL) {
 
2446
        OF_node_put(OF_env, ndev_out);
 
2447
        OF_node_put(OF_env, ndev_in);
 
2448
        OF_node_put(OF_env, chs);
 
2449
        ERROR("Cannot create in_inst\n");
 
2450
        return -1;
 
2451
    }
 
2452
    out_inst = OF_instance_new(OF_env, ndev_out);
 
2453
    if (out_inst == NULL) {
 
2454
        OF_node_put(OF_env, ndev_out);
 
2455
        OF_node_put(OF_env, ndev_in);
 
2456
        OF_node_put(OF_env, chs);
 
2457
        ERROR("Cannot create out_inst\n");
 
2458
        return -1;
 
2459
    }
 
2460
    OF_prop_int_set(OF_env, chs, "stdin",
 
2461
                    OF_instance_get_id(OF_env, in_inst));
 
2462
    OF_prop_int_set(OF_env, chs, "stdout",
 
2463
                    OF_instance_get_id(OF_env, out_inst));
 
2464
    kbd = OF_node_new(OF_env, ndev_in, "keyboard", OF_ADDRESS_NONE);
 
2465
    if (kbd == NULL) {
 
2466
        OF_node_put(OF_env, ndev_out);
 
2467
        OF_node_put(OF_env, ndev_in);
 
2468
        OF_node_put(OF_env, chs);
 
2469
        ERROR("Cannot create 'keyboard' for stdio\n");
 
2470
        return -1;
 
2471
    }
 
2472
    OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
 
2473
    OF_node_put(OF_env, kbd);
 
2474
    OF_DPRINTF("stdin h: 0x%0x out : 0x%0x\n",
 
2475
               OF_instance_get_id(OF_env, in_inst),
 
2476
               OF_instance_get_id(OF_env, out_inst));
 
2477
    OF_node_put(OF_env, ndev_out);
 
2478
    OF_node_put(OF_env, ndev_in);
 
2479
    OF_node_put(OF_env, chs);
 
2480
 
 
2481
    return 0;
 
2482
}
 
2483
 
 
2484
static void keylargo_ata(OF_node_t *mio, uint32_t base_address,
 
2485
                         uint32_t base, int irq1, int irq2, 
 
2486
                         uint16_t pic_phandle)
 
2487
{
 
2488
    OF_env_t *OF_env = OF_env_main;
 
2489
    OF_node_t *ata;
 
2490
    OF_regprop_t regs[2];
 
2491
 
 
2492
    ata = OF_node_new(OF_env, mio, "ata-4", base);
 
2493
    if (ata == NULL) {
 
2494
        ERROR("Cannot create 'ata-4'\n");
 
2495
        return;
 
2496
    }
 
2497
    OF_prop_string_new(OF_env, ata, "device_type", "ata");
 
2498
#if 1
 
2499
    OF_prop_string_new(OF_env, ata, "compatible", "key2largo-ata");
 
2500
    OF_prop_string_new(OF_env, ata, "model", "ata-4");
 
2501
    OF_prop_string_new(OF_env, ata, "cable-type", "80-conductor");
 
2502
#else
 
2503
    OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
 
2504
    OF_prop_string_new(OF_env, ata, "model", "ata-4");
 
2505
#endif
 
2506
    OF_prop_int_new(OF_env, ata, "#address-cells", 1);
 
2507
    OF_prop_int_new(OF_env, ata, "#size-cells", 0);
 
2508
    regs[0].address = base;
 
2509
    regs[0].size = 0x00001000;
 
2510
#if 0 // HACK: Don't set up DMA registers
 
2511
    regs[1].address = 0x00008A00;
 
2512
    regs[1].size = 0x00001000;
 
2513
    OF_property_new(OF_env, ata, "reg",
 
2514
                    regs, 2 * sizeof(OF_regprop_t));
 
2515
#else
 
2516
    OF_property_new(OF_env, ata, "reg",
 
2517
                    regs, sizeof(OF_regprop_t));
 
2518
#endif
 
2519
    OF_prop_int_new(OF_env, ata, "interrupt-parent", pic_phandle);
 
2520
    regs[0].address = irq1;
 
2521
    regs[0].size = 0x00000001;
 
2522
    regs[1].address = irq2;
 
2523
    regs[1].size = 0x00000000;
 
2524
    OF_property_new(OF_env, ata, "interrupts",
 
2525
                    regs, 2 * sizeof(OF_regprop_t));
 
2526
    if (base == 0x1f000)
 
2527
        ide_pci_pmac_register(base_address + base, 0x00000000, ata);
 
2528
    else
 
2529
        ide_pci_pmac_register(0x00000000, base_address + base, ata);
 
2530
}
 
2531
 
 
2532
void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
 
2533
                            void *private_data)
 
2534
{
 
2535
    unsigned char tmp[OF_NAMELEN_MAX];
 
2536
    OF_env_t *OF_env;
 
2537
    pci_reg_prop_t pregs[2];
 
2538
    OF_node_t *mio, *chs, *als;
 
2539
    uint16_t pic_phandle;
 
2540
    int rec_len;
 
2541
    OF_prop_t *mio_reg;
 
2542
 
 
2543
    OF_DPRINTF("mac-io: %p\n", dev);
 
2544
    OF_env = OF_env_main;
 
2545
    chs = OF_node_get(OF_env, "chosen");
 
2546
    if (chs == NULL) {
 
2547
        ERROR("Cannot get 'chosen'\n");
 
2548
        return;
 
2549
    }
 
2550
    als = OF_node_get(OF_env, "aliases");
 
2551
    if (als == NULL) {
 
2552
        OF_node_put(OF_env, als);
 
2553
        ERROR("Cannot get 'aliases'\n");
 
2554
        return;
 
2555
    }
 
2556
    /* Mac-IO is mandatory for OSX to boot */
 
2557
    mio = dev;
 
2558
    mio->private_data = private_data;
 
2559
    pregs[0].addr.hi = 0x00000000;
 
2560
    pregs[0].addr.mid = 0x00000000;
 
2561
    pregs[0].addr.lo = 0x00000000;
 
2562
    pregs[0].size_hi = base_address;
 
2563
    pregs[0].size_lo = size;
 
2564
    mio_reg = OF_property_get(OF_env, mio, "reg");
 
2565
    if (mio_reg && mio_reg->vlen >= 5 * 4) {
 
2566
        pregs[0].addr.mid = ((pci_reg_prop_t *)mio_reg->value)->addr.hi;
 
2567
    }
 
2568
    OF_property_new(OF_env, mio, "ranges",
 
2569
                    &pregs, sizeof(pci_reg_prop_t));
 
2570
#if 0
 
2571
    pregs[0].addr.hi = 0x82013810;
 
2572
    pregs[0].addr.mid = 0x00000000;
 
2573
    pregs[0].addr.lo = 0x80800000;
 
2574
    pregs[0].size_hi = 0x00000000;
 
2575
    pregs[0].size_lo = 0x00080000;
 
2576
    OF_property_new(OF_env, mio, "assigned-addresses",
 
2577
                    &pregs, sizeof(pci_reg_prop_t));
 
2578
#endif
 
2579
 
 
2580
    if (arch == ARCH_HEATHROW) {
 
2581
        /* Heathrow PIC */
 
2582
        OF_regprop_t regs;
 
2583
        OF_node_t *mpic;
 
2584
        const char compat_str[] = "heathrow\0mac-risc";
 
2585
 
 
2586
        mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x10);
 
2587
        if (mpic == NULL) {
 
2588
            ERROR("Cannot create 'mpic'\n");
 
2589
            goto out;
 
2590
        }
 
2591
        OF_prop_string_new(OF_env, mpic, "device_type", "interrupt-controller");
 
2592
        OF_property_new(OF_env, mpic, "compatible", compat_str, sizeof(compat_str));
 
2593
        OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 1);
 
2594
        regs.address = 0x10;
 
2595
        regs.size = 0x20;
 
2596
        OF_property_new(OF_env, mpic, "reg",
 
2597
                        &regs, sizeof(regs));
 
2598
        OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
 
2599
        pic_phandle = OF_pack_handle(OF_env, mpic);
 
2600
        OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
 
2601
        OF_node_put(OF_env, mpic);
 
2602
        rec_len = 6;
 
2603
    } else {
 
2604
    /* OpenPIC */
 
2605
        OF_regprop_t regs[4];
 
2606
        OF_node_t *mpic;
 
2607
        mpic = OF_node_new(OF_env, mio, "interrupt-controller", 0x40000);
 
2608
        if (mpic == NULL) {
 
2609
            ERROR("Cannot create 'mpic'\n");
 
2610
            goto out;
 
2611
        }
 
2612
        OF_prop_string_new(OF_env, mpic, "device_type", "open-pic");
 
2613
        OF_prop_string_new(OF_env, mpic, "compatible", "chrp,open-pic");
 
2614
        OF_property_new(OF_env, mpic, "interrupt-controller", NULL, 0);
 
2615
        OF_property_new(OF_env, mpic, "built-in", NULL, 0);
 
2616
        OF_prop_int_new(OF_env, mpic, "clock-frequency", 0x003F7A00);
 
2617
        OF_prop_int_new(OF_env, mpic, "#address-cells", 0);
 
2618
        OF_prop_int_new(OF_env, mpic, "#interrupt-cells", 2);
 
2619
        memset(regs, 0, 4 * sizeof(OF_regprop_t));
 
2620
        regs[0].address = 0x00040000;
 
2621
        regs[0].size = 0x00040000;
 
2622
        OF_property_new(OF_env, mpic, "reg",
 
2623
                        &regs, 1 * sizeof(OF_regprop_t));
 
2624
        pic_phandle = OF_pack_handle(OF_env, mpic);
 
2625
        OF_prop_int_new(OF_env, chs, "interrupt-controller", pic_phandle);
 
2626
        OF_node_put(OF_env, mpic);
 
2627
        rec_len = 7;
 
2628
    }
 
2629
 
 
2630
    /* patch pci host table */
 
2631
    /* XXX: do it after the PCI init */
 
2632
    {
 
2633
        int i;
 
2634
        uint32_t tab[4];
 
2635
 
 
2636
        for(i = 0; i < pci_host_interrupt_map_len; i += rec_len)
 
2637
            pci_host_interrupt_map[i + 4] = pic_phandle;
 
2638
#if 0
 
2639
        dprintf("interrupt-map:\n");
 
2640
        for(i = 0; i < pci_host_interrupt_map_len; i++) {
 
2641
            dprintf(" %08x", pci_host_interrupt_map[i]);
 
2642
            if ((i % rec_len) == (rec_len - 1))
 
2643
                dprintf("\n");
 
2644
        }
 
2645
        dprintf("\n");
 
2646
#endif
 
2647
        OF_property_new(OF_env, pci_host_node, "interrupt-map", 
 
2648
                        pci_host_interrupt_map, 
 
2649
                        pci_host_interrupt_map_len * sizeof(uint32_t));
 
2650
        tab[0] = 0xf800;
 
2651
        tab[1] = 0;
 
2652
        tab[2] = 0;
 
2653
        tab[3] = 0;
 
2654
        OF_property_new(OF_env, pci_host_node, "interrupt-map-mask", 
 
2655
                        tab, 4 * sizeof(uint32_t));
 
2656
    }
 
2657
#if 0
 
2658
    /* escc is useful to get MacOS X debug messages */
 
2659
    {
 
2660
        OF_regprop_t regs[8];
 
2661
        uint32_t irqs[6];
 
2662
        OF_node_t *scc, *chann;
 
2663
        scc = OF_node_new(OF_env, mio, "escc", 0x13000);
 
2664
        if (scc == NULL) {
 
2665
            ERROR("Cannot create 'escc'\n");
 
2666
            goto out;
 
2667
        }
 
2668
        OF_prop_string_new(OF_env, scc, "device_type", "escc");
 
2669
        OF_prop_string_new(OF_env, scc, "compatible", "chrp,es0");
 
2670
        OF_property_new(OF_env, scc, "built-in", NULL, 0);
 
2671
        OF_prop_int_new(OF_env, scc, "#address-cells", 1);
 
2672
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2673
        regs[0].address = 0x00013000;
 
2674
        regs[0].size = 0x00001000;
 
2675
        regs[1].address = 0x00008400;
 
2676
        regs[1].size = 0x00000100;
 
2677
        regs[2].address = 0x00008500;
 
2678
        regs[2].size = 0x00000100;
 
2679
        regs[3].address = 0x00008600;
 
2680
        regs[3].size = 0x00000100;
 
2681
        regs[4].address = 0x00008700;
 
2682
        regs[4].size = 0x00000100;
 
2683
        OF_property_new(OF_env, scc, "reg",
 
2684
                        regs, 5 * sizeof(OF_regprop_t));
 
2685
        OF_property_new(OF_env, scc, "ranges", NULL, 0);
 
2686
        /* Set up two channels */
 
2687
        chann = OF_node_new(OF_env, scc, "ch-a", 0x13020);
 
2688
        if (chann == NULL) {
 
2689
            ERROR("Cannot create 'ch-a'\n");
 
2690
            goto out;
 
2691
        }
 
2692
        OF_prop_string_new(OF_env, chann, "device_type", "serial");
 
2693
        OF_prop_string_new(OF_env, chann, "compatible", "chrp,es2");
 
2694
        OF_property_new(OF_env, chann, "built-in", NULL, 0);
 
2695
        OF_prop_int_new(OF_env, chann, "slot-names", 0);
 
2696
        OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
 
2697
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2698
        regs[0].address = 0x00013020;
 
2699
        regs[0].size = 0x00000001;
 
2700
        regs[1].address = 0x00013030;
 
2701
        regs[1].size = 0x00000001;
 
2702
        regs[2].address = 0x00013050;
 
2703
        regs[2].size = 0x00000001;
 
2704
        regs[3].address = 0x00008400;
 
2705
        regs[3].size = 0x00000100;
 
2706
        regs[4].address = 0x00008500;
 
2707
        regs[4].size = 0x00000100;
 
2708
        OF_property_new(OF_env, chann, "reg",
 
2709
                        regs, 5 * sizeof(OF_regprop_t));
 
2710
        /* XXX: tofix: those are regprops */
 
2711
        irqs[0] = 0x16;
 
2712
        irqs[1] = 0x01;
 
2713
        irqs[2] = 0x05;
 
2714
        irqs[3] = 0x00;
 
2715
        irqs[4] = 0x06;
 
2716
        irqs[5] = 0x00;
 
2717
        OF_property_new(OF_env, chann, "interrupts",
 
2718
                        irqs, 6 * sizeof(uint32_t));
 
2719
        OF_node_put(OF_env, chann);
 
2720
        chann = OF_node_new(OF_env, scc, "ch-b", 0x13000);
 
2721
        if (chann == NULL) {
 
2722
            ERROR("Cannot create 'ch-b'\n");
 
2723
            goto out;
 
2724
        }
 
2725
        OF_prop_string_new(OF_env, chann, "device_type", "serial");
 
2726
        OF_prop_string_new(OF_env, chann, "compatible", "chrp,es3");
 
2727
        OF_property_new(OF_env, chann, "built-in", NULL, 0);
 
2728
        OF_prop_int_new(OF_env, chann, "slot-names", 0);
 
2729
        OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
 
2730
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2731
        regs[0].address = 0x00013000;
 
2732
        regs[0].size = 0x00000001;
 
2733
        regs[1].address = 0x00013010;
 
2734
        regs[1].size = 0x00000001;
 
2735
        regs[2].address = 0x00013040;
 
2736
        regs[2].size = 0x00000001;
 
2737
        regs[3].address = 0x00008600;
 
2738
        regs[3].size = 0x00000100;
 
2739
        regs[4].address = 0x00008700;
 
2740
        regs[4].size = 0x00000100;
 
2741
        OF_property_new(OF_env, chann, "reg",
 
2742
                        regs, 5 * sizeof(OF_regprop_t));
 
2743
        /* XXX: tofix: those are regprops */
 
2744
        irqs[0] = 0x17;
 
2745
        irqs[1] = 0x01;
 
2746
        irqs[2] = 0x07;
 
2747
        irqs[3] = 0x00;
 
2748
        irqs[4] = 0x08;
 
2749
        irqs[5] = 0x00;
 
2750
        OF_property_new(OF_env, chann, "interrupts",
 
2751
                        irqs, 6 * sizeof(uint32_t));
 
2752
        OF_node_put(OF_env, chann);
 
2753
        OF_node_put(OF_env, scc);
 
2754
        /* MacOS likes escc-legacy */
 
2755
        scc = OF_node_new(OF_env, mio, "escc-legacy", 0x12000);
 
2756
        if (scc == NULL) {
 
2757
            ERROR("Cannot create 'escc-legacy'\n");
 
2758
            goto out;
 
2759
        }
 
2760
        OF_prop_string_new(OF_env, scc, "device_type", "escc-legacy");
 
2761
        OF_prop_string_new(OF_env, scc, "compatible", "chrp,es1");
 
2762
        OF_property_new(OF_env, scc, "built-in", NULL, 0);
 
2763
        OF_prop_int_new(OF_env, scc, "#address-cells", 1);
 
2764
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2765
        regs[0].address = 0x00012000;
 
2766
        regs[0].size = 0x00001000;
 
2767
        regs[1].address = 0x00008400;
 
2768
        regs[1].size = 0x00000100;
 
2769
        regs[2].address = 0x00008500;
 
2770
        regs[2].size = 0x00000100;
 
2771
        regs[3].address = 0x00008600;
 
2772
        regs[3].size = 0x00000100;
 
2773
        regs[4].address = 0x00008700;
 
2774
        regs[4].size = 0x00000100;
 
2775
        OF_property_new(OF_env, scc, "reg",
 
2776
                        regs, 8 * sizeof(OF_regprop_t));
 
2777
        OF_property_new(OF_env, scc, "ranges", NULL, 0);
 
2778
        /* Set up two channels */
 
2779
        chann = OF_node_new(OF_env, scc, "ch-a", 0x12004);
 
2780
        if (chann == NULL) {
 
2781
            ERROR("Cannot create 'ch-a'\n");
 
2782
            goto out;
 
2783
        }
 
2784
        OF_prop_string_new(OF_env, chann, "device_type", "serial");
 
2785
        OF_prop_string_new(OF_env, chann, "compatible", "chrp,es4");
 
2786
        OF_property_new(OF_env, chann, "built-in", NULL, 0);
 
2787
        OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
 
2788
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2789
        regs[0].address = 0x00012004;
 
2790
        regs[0].size = 0x00000001;
 
2791
        regs[1].address = 0x00012006;
 
2792
        regs[1].size = 0x00000001;
 
2793
        regs[2].address = 0x0001200A;
 
2794
        regs[2].size = 0x00000001;
 
2795
        regs[3].address = 0x00008400;
 
2796
        regs[3].size = 0x00000100;
 
2797
        regs[4].address = 0x00008500;
 
2798
        regs[4].size = 0x00000100;
 
2799
        OF_property_new(OF_env, chann, "reg",
 
2800
                        regs, 8 * sizeof(OF_regprop_t));
 
2801
        /* XXX: tofix: those are regprops */
 
2802
        irqs[0] = 0x16;
 
2803
        irqs[1] = 0x01;
 
2804
        irqs[2] = 0x05;
 
2805
        irqs[3] = 0x00;
 
2806
        irqs[4] = 0x06;
 
2807
        irqs[5] = 0x00;
 
2808
        OF_property_new(OF_env, chann, "interrupts",
 
2809
                        irqs, 6 * sizeof(uint32_t));
 
2810
        OF_node_put(OF_env, chann);
 
2811
        chann = OF_node_new(OF_env, scc, "ch-b", 0x12000);
 
2812
        if (chann == NULL) {
 
2813
            ERROR("Cannot create 'ch-b'\n");
 
2814
            goto out;
 
2815
        }
 
2816
        OF_prop_string_new(OF_env, chann, "device_type", "serial");
 
2817
        OF_prop_string_new(OF_env, chann, "compatible", "chrp,es5");
 
2818
        OF_property_new(OF_env, chann, "built-in", NULL, 0);
 
2819
        OF_prop_int_new(OF_env, chann, "interrupt-parent", pic_phandle);
 
2820
        memset(regs, 0, 8 * sizeof(OF_regprop_t));
 
2821
        regs[0].address = 0x00012000;
 
2822
        regs[0].size = 0x00000001;
 
2823
        regs[1].address = 0x00012002;
 
2824
        regs[1].size = 0x00000001;
 
2825
        regs[2].address = 0x00012008;
 
2826
        regs[2].size = 0x00000001;
 
2827
        regs[3].address = 0x00008600;
 
2828
        regs[3].size = 0x00000100;
 
2829
        regs[4].address = 0x00008700;
 
2830
        regs[4].size = 0x00000100;
 
2831
        OF_property_new(OF_env, chann, "reg",
 
2832
                        regs, 8 * sizeof(OF_regprop_t));
 
2833
        /* XXX: tofix: those are regprops */
 
2834
        irqs[0] = 0x17;
 
2835
        irqs[1] = 0x01;
 
2836
        irqs[2] = 0x07;
 
2837
        irqs[3] = 0x00;
 
2838
        irqs[4] = 0x08;
 
2839
        irqs[5] = 0x00;
 
2840
        OF_property_new(OF_env, chann, "interrupts",
 
2841
                        irqs, 6 * sizeof(uint32_t));
 
2842
        OF_node_put(OF_env, chann);
 
2843
        OF_node_put(OF_env, scc);
 
2844
    }
 
2845
#endif
 
2846
    /* Keylargo IDE controller: need some work (DMA problem ?) */
 
2847
    if (arch == ARCH_MAC99) {
 
2848
        keylargo_ata(mio, base_address, 0x1f000, 0x13, 0xb, pic_phandle);
 
2849
        keylargo_ata(mio, base_address, 0x20000, 0x14, 0xb, pic_phandle);
 
2850
    }
 
2851
#if 0
 
2852
    /* Timer */
 
2853
    {
 
2854
        OF_node_t *tmr;
 
2855
        OF_regprop_t regs[1];
 
2856
        tmr = OF_node_new(OF_env, mio, "timer", 0x15000);
 
2857
        if (tmr == NULL) {
 
2858
            ERROR("Cannot create 'timer'\n");
 
2859
            goto out;
 
2860
        }
 
2861
        OF_prop_string_new(OF_env, tmr, "device_type", "timer");
 
2862
        OF_prop_string_new(OF_env, tmr, "compatible", "keylargo-timer");
 
2863
        OF_prop_int_new(OF_env, tmr, "clock-frequency", 0x01194000);
 
2864
        regs[0].address = 0x00015000;
 
2865
        regs[0].size = 0x00001000;
 
2866
        OF_property_new(OF_env, tmr, "reg", regs, sizeof(OF_regprop_t));
 
2867
        OF_prop_int_new(OF_env, tmr, "interrupt-parent", pic_phandle);
 
2868
        regs[0].address = 0x00000020;
 
2869
        regs[0].size = 0x00000001;
 
2870
        OF_property_new(OF_env, tmr, "interrupts",
 
2871
                        regs, sizeof(OF_regprop_t));
 
2872
        OF_node_put(OF_env, tmr);
 
2873
    }
 
2874
#endif
 
2875
    /* VIA-PMU */
 
2876
    {
 
2877
        /* Controls adb, RTC and power-mgt (forget it !) */
 
2878
        OF_node_t *via, *adb;
 
2879
        OF_regprop_t regs[1];
 
2880
#if 0 // THIS IS A HACK AND IS COMPLETELY ABSURD !
 
2881
      // (but needed has Qemu doesn't emulate via-pmu).
 
2882
        via = OF_node_new(OF_env, mio, "via-pmu", 0x16000);
 
2883
        if (via == NULL) {
 
2884
            ERROR("Cannot create 'via-pmu'\n");
 
2885
            goto out;
 
2886
        }
 
2887
        OF_prop_string_new(OF_env, via, "device_type", "via-pmu");
 
2888
        OF_prop_string_new(OF_env, via, "compatible", "pmu");
 
2889
#else
 
2890
        via = OF_node_new(OF_env, mio, "via-cuda", 0x16000);
 
2891
        if (via == NULL) {
 
2892
            ERROR("Cannot create 'via-cuda'\n");
 
2893
            goto out;
 
2894
        }
 
2895
        OF_prop_string_new(OF_env, via, "device_type", "via-cuda");
 
2896
        OF_prop_string_new(OF_env, via, "compatible", "cuda");
 
2897
#endif
 
2898
        regs[0].address = 0x00016000;
 
2899
        regs[0].size = 0x00002000;
 
2900
        OF_property_new(OF_env, via, "reg", regs, sizeof(OF_regprop_t));
 
2901
        OF_prop_int_new(OF_env, via, "interrupt-parent", pic_phandle);
 
2902
        if (arch == ARCH_HEATHROW) {
 
2903
            OF_prop_int_new(OF_env, via, "interrupts", 0x12);
 
2904
        } else {
 
2905
        regs[0].address = 0x00000019;
 
2906
        regs[0].size = 0x00000001;
 
2907
        OF_property_new(OF_env, via, "interrupts",
 
2908
                        regs, sizeof(OF_regprop_t));
 
2909
        }
 
2910
        /* force usage of OF bus speeds */
 
2911
        OF_prop_int_new(OF_env, via, "BusSpeedCorrect", 1);
 
2912
#if 0
 
2913
        OF_prop_int_new(OF_env, via, "pmu-version", 0x00D0740C);
 
2914
#endif
 
2915
        {
 
2916
            OF_node_t *kbd, *mouse;
 
2917
        /* ADB pseudo-device */
 
2918
        adb = OF_node_new(OF_env, via, "adb", OF_ADDRESS_NONE);
 
2919
        if (adb == NULL) {
 
2920
            ERROR("Cannot create 'adb'\n");
 
2921
            goto out;
 
2922
        }
 
2923
        OF_prop_string_new(OF_env, adb, "device_type", "adb");
 
2924
#if 0
 
2925
        OF_prop_string_new(OF_env, adb, "compatible", "pmu-99");
 
2926
#else
 
2927
        OF_prop_string_new(OF_env, adb, "compatible", "adb");
 
2928
#endif
 
2929
        OF_prop_int_new(OF_env, adb, "#address-cells", 1);
 
2930
        OF_prop_int_new(OF_env, adb, "#size-cells", 0);
 
2931
        OF_pack_get_path(OF_env, tmp, 512, adb);
 
2932
        OF_prop_string_new(OF_env, als, "adb", tmp);
 
2933
 
 
2934
            kbd = OF_node_new(OF_env, adb, "keyboard", 2);
 
2935
            if (kbd == NULL) {
 
2936
                ERROR("Cannot create 'kbd'\n");
 
2937
                goto out;
 
2938
            }
 
2939
            OF_prop_string_new(OF_env, kbd, "device_type", "keyboard");
 
2940
            OF_prop_int_new(OF_env, kbd, "reg", 2);
 
2941
 
 
2942
            mouse = OF_node_new(OF_env, adb, "mouse", 3);
 
2943
            if (mouse == NULL) {
 
2944
                ERROR("Cannot create 'mouse'\n");
 
2945
                goto out;
 
2946
            }
 
2947
            OF_prop_string_new(OF_env, mouse, "device_type", "mouse");
 
2948
            OF_prop_int_new(OF_env, mouse, "reg", 3);
 
2949
            OF_prop_int_new(OF_env, mouse, "#buttons", 3);
 
2950
        }
 
2951
        {
 
2952
            OF_node_t *rtc;
 
2953
        
 
2954
        rtc = OF_node_new(OF_env, via, "rtc", OF_ADDRESS_NONE);
 
2955
        if (rtc == NULL) {
 
2956
            ERROR("Cannot create 'rtc'\n");
 
2957
            goto out;
 
2958
        }
 
2959
        OF_prop_string_new(OF_env, rtc, "device_type", "rtc");
 
2960
#if 0
 
2961
        OF_prop_string_new(OF_env, rtc, "compatible", "rtc,via-pmu");
 
2962
#else
 
2963
        OF_prop_string_new(OF_env, rtc, "compatible", "rtc");
 
2964
#endif
 
2965
        OF_node_put(OF_env, rtc);
 
2966
    }
 
2967
        //        OF_node_put(OF_env, via);
 
2968
    }
 
2969
    {
 
2970
        OF_node_t *pmgt;
 
2971
        pmgt = OF_node_new(OF_env, mio, "power-mgt", OF_ADDRESS_NONE);
 
2972
        OF_prop_string_new(OF_env, pmgt, "device_type", "power-mgt");
 
2973
        OF_prop_string_new(OF_env, pmgt, "compatible", "cuda");
 
2974
        OF_prop_string_new(OF_env, pmgt, "mgt-kind", "min-consumption-pwm-led");
 
2975
        OF_node_put(OF_env, pmgt);
 
2976
    }
 
2977
 
 
2978
    if (arch == ARCH_HEATHROW) {
 
2979
        /* NVRAM */
 
2980
        OF_node_t *nvr;
 
2981
        OF_regprop_t regs;
 
2982
        nvr = OF_node_new(OF_env, mio, "nvram", 0x60000);
 
2983
        OF_prop_string_new(OF_env, nvr, "device_type", "nvram");
 
2984
        regs.address = 0x60000;
 
2985
        regs.size = 0x00020000;
 
2986
        OF_property_new(OF_env, nvr, "reg", &regs, sizeof(regs));
 
2987
        OF_prop_int_new(OF_env, nvr, "#bytes", 0x2000);
 
2988
        OF_node_put(OF_env, nvr);
 
2989
    }
 
2990
 
 
2991
 out:
 
2992
    //    OF_node_put(OF_env, mio);
 
2993
    OF_node_put(OF_env, chs);
 
2994
    OF_node_put(OF_env, als);
 
2995
}
 
2996
 
 
2997
void OF_finalize_pci_ide (void *dev, 
 
2998
                          uint32_t io_base0, uint32_t io_base1,
 
2999
                          uint32_t io_base2, uint32_t io_base3)
 
3000
{
 
3001
    OF_env_t *OF_env = OF_env_main;
 
3002
    OF_node_t *pci_ata = dev;
 
3003
    OF_node_t *ata, *atas[2];
 
3004
    int i;
 
3005
 
 
3006
    OF_prop_int_new(OF_env, pci_ata, "#address-cells", 1);
 
3007
    OF_prop_int_new(OF_env, pci_ata, "#size-cells", 0);
 
3008
 
 
3009
    /* XXX: Darwin handles only one device */
 
3010
    for(i = 0; i < 1; i++) {
 
3011
        ata = OF_node_new(OF_env, pci_ata, "ata-4", i);
 
3012
        if (ata == NULL) {
 
3013
            ERROR("Cannot create 'ata-4'\n");
 
3014
            return;
 
3015
        }
 
3016
        OF_prop_string_new(OF_env, ata, "device_type", "ata");
 
3017
        OF_prop_string_new(OF_env, ata, "compatible", "cmd646-ata");
 
3018
        OF_prop_string_new(OF_env, ata, "model", "ata-4");
 
3019
        OF_prop_int_new(OF_env, ata, "#address-cells", 1);
 
3020
        OF_prop_int_new(OF_env, ata, "#size-cells", 0);
 
3021
        OF_prop_int_new(OF_env, ata, "reg", i);
 
3022
        atas[i] = ata;
 
3023
    }
 
3024
    ide_pci_pc_register(io_base0, io_base1, io_base2, io_base3,
 
3025
                        atas[0], atas[1]);
 
3026
}
 
3027
 
 
3028
/*****************************************************************************/
 
3029
/* Fake package */
 
3030
static void OF_method_fake (OF_env_t *OF_env)
 
3031
{
 
3032
    uint32_t ihandle;
 
3033
 
 
3034
    ihandle = popd(OF_env);
 
3035
    OF_DPRINTF("ih: %0x %d\n", ihandle, stackd_depth(OF_env));
 
3036
    pushd(OF_env, ihandle);
 
3037
}
 
3038
 
 
3039
static void OF_mmu_translate (OF_env_t *OF_env)
 
3040
{
 
3041
    const unsigned char *args;
 
3042
    uint32_t address, more;
 
3043
    uint32_t ihandle;
 
3044
 
 
3045
    OF_CHECK_NBARGS(OF_env, 4);
 
3046
    /* As we get a 1:1 mapping, do nothing */
 
3047
    ihandle = popd(OF_env);
 
3048
    args = (void *)popd(OF_env);
 
3049
    address = popd(OF_env);
 
3050
    more = popd(OF_env);
 
3051
    OF_DPRINTF("Translate address %0x %0x %0x\n", ihandle, address, more);
 
3052
    //    BAT_setup(3, more, address, 0x10000000, 1, 1, 2);
 
3053
    pushd(OF_env, address);
 
3054
    pushd(OF_env, 0x00000000);
 
3055
    pushd(OF_env, 0x00000000);
 
3056
    pushd(OF_env, 0);
 
3057
}
 
3058
 
 
3059
static void OF_mmu_map (OF_env_t *OF_env)
 
3060
{
 
3061
    const unsigned char *args;
 
3062
    uint32_t address, virt, size;
 
3063
    uint32_t ihandle;
 
3064
 
 
3065
    OF_CHECK_NBARGS(OF_env, 6);
 
3066
    /* As we get a 1:1 mapping, do nothing */
 
3067
    ihandle = popd(OF_env);
 
3068
    args = (void *)popd(OF_env);
 
3069
    popd(OF_env);
 
3070
    size = popd(OF_env);
 
3071
    virt = popd(OF_env);
 
3072
    address = popd(OF_env);
 
3073
    OF_DPRINTF("Map %0x %0x %0x %0x\n", ihandle, address,
 
3074
               virt, size);
 
3075
    pushd(OF_env, 0);
 
3076
}
 
3077
 
 
3078
/* Serial device package */
 
3079
static void OF_serial_write (OF_env_t *OF_env)
 
3080
{
 
3081
    const unsigned char *args;
 
3082
    OF_inst_t *inst;
 
3083
    OF_node_t *node;
 
3084
    uint32_t ihandle;
 
3085
    unsigned char *str;
 
3086
    int len;
 
3087
 
 
3088
    OF_CHECK_NBARGS(OF_env, 4);
 
3089
    ihandle = popd(OF_env);
 
3090
    args = (void *)popd(OF_env);
 
3091
    str = (void *)popd(OF_env);
 
3092
    len = popd(OF_env);
 
3093
    inst = OF_inst_find(OF_env, ihandle);
 
3094
    if (inst == NULL) {
 
3095
        pushd(OF_env, -1);
 
3096
        ERROR("Cannot get serial instance\n");
 
3097
        return;
 
3098
    }
 
3099
    node = inst->node;
 
3100
    //    OF_DPRINTF("args: %p str: %p\n", args, str);
 
3101
    /* XXX: should use directly the serial port
 
3102
     *      and have another console package.
 
3103
     */
 
3104
    console_write(str, len);
 
3105
    pushd(OF_env, 0);
 
3106
}
 
3107
 
 
3108
static void OF_serial_read (OF_env_t *OF_env)
 
3109
{
 
3110
    const unsigned char *args;
 
3111
    char *dest;
 
3112
    uint32_t len;
 
3113
    uint32_t ihandle;
 
3114
    uint16_t phandle;
 
3115
    int ret, count;
 
3116
 
 
3117
    OF_CHECK_NBARGS(OF_env, 4);
 
3118
    ihandle = popd(OF_env);
 
3119
    args = (void *)popd(OF_env);
 
3120
    phandle = (ihandle >> 16) & 0xFFFF;
 
3121
    dest = (void *)popd(OF_env);
 
3122
    len = popd(OF_env);
 
3123
    ret = -1; /* Don't know why gcc thinks it might be uninitialized... */
 
3124
    for (count = 0; count < 1000; count++) {
 
3125
        ret = console_read(dest, len);
 
3126
        /* Stop if we read something or got an error */
 
3127
        if (ret != 0)
 
3128
            break;
 
3129
        /* Random sleep. Seems allright for serial port */
 
3130
        usleep(10000);
 
3131
    }
 
3132
    if (ret <= 0) {
 
3133
        pushd(OF_env, 0);
 
3134
    } else {
 
3135
        OF_DPRINTF("send '%s'\n", dest);
 
3136
        pushd(OF_env, ret);
 
3137
    }
 
3138
}
 
3139
 
 
3140
typedef struct blockdev_inst_t {
 
3141
    int type;
 
3142
    union {
 
3143
        bloc_device_t *bd;
 
3144
        part_t *part;
 
3145
        inode_t *file;
 
3146
    } u;
 
3147
} blockdev_inst_t;
 
3148
 
 
3149
static int OF_split_args (unsigned char *args, unsigned char **argv,
 
3150
                          int max_args)
 
3151
{
 
3152
    unsigned char *pos, *end;
 
3153
    int i;
 
3154
 
 
3155
    pos = args;
 
3156
    end = pos;
 
3157
    for (i = 0; i < max_args && *pos != '\0' && end != NULL; i++) {
 
3158
        end = strchr(pos, ',');
 
3159
        if (end != NULL)
 
3160
            *end = '\0';
 
3161
        argv[i] = pos;
 
3162
        pos = end + 1;
 
3163
    }
 
3164
 
 
3165
    return i;
 
3166
}
 
3167
 
 
3168
static void OF_convert_path (unsigned char **path)
 
3169
{
 
3170
    unsigned char *pos;
 
3171
 
 
3172
    OF_DPRINTF("%s: '%s'\n", __func__, *path);
 
3173
    for (pos = *path; *pos != '\0'; pos++) {
 
3174
        if (*pos == '\\')
 
3175
            *pos = '/';
 
3176
    }
 
3177
    OF_DPRINTF("%s: '%s'\n", __func__, *path);
 
3178
    pos = *path;
 
3179
#if 1
 
3180
    if (pos[0] == '/' && pos[1] == '/') {
 
3181
        pos += 2;
 
3182
        *path = pos;
 
3183
    }
 
3184
#else
 
3185
    for (; *pos == '/'; pos++)
 
3186
        continue;
 
3187
    *path = pos;
 
3188
#endif
 
3189
    OF_DPRINTF("%s: '%s'\n", __func__, *path);
 
3190
}
 
3191
 
 
3192
/* Block devices package */
 
3193
static void OF_blockdev_open (OF_env_t *OF_env)
 
3194
{
 
3195
    unsigned char tmp[OF_NAMELEN_MAX];
 
3196
    unsigned char *args, *argv[4];
 
3197
    OF_inst_t *dsk_inst;
 
3198
    OF_node_t *dsk;
 
3199
    bloc_device_t *bd;
 
3200
    blockdev_inst_t *bdinst;
 
3201
    uint32_t ihandle;
 
3202
    uint16_t phandle;
 
3203
    int nargs, partnum;
 
3204
 
 
3205
    OF_CHECK_NBARGS(OF_env, 2);
 
3206
    ihandle = popd(OF_env);
 
3207
    args = (void *)popd(OF_env);
 
3208
    phandle = (ihandle >> 16) & 0xFFFF;
 
3209
    dsk_inst = OF_inst_find(OF_env, ihandle);
 
3210
    if (dsk_inst == NULL) {
 
3211
        ERROR("Disk not found (ih: %0x)\n", ihandle);
 
3212
        pushd(OF_env, -1);
 
3213
        return;
 
3214
    }
 
3215
    dsk = dsk_inst->node;
 
3216
    bd = dsk->private_data;
 
3217
    bdinst = malloc(sizeof(blockdev_inst_t));
 
3218
    if (bdinst == NULL) {
 
3219
        ihandle = -1;
 
3220
        ERROR("Cannot alloc blockdev instance\n");
 
3221
        goto out;
 
3222
    }
 
3223
    memset(bdinst, 0, sizeof(blockdev_inst_t));
 
3224
    OF_DPRINTF("called with args '%s'\n", args);
 
3225
    nargs = OF_split_args(args, argv, 4);
 
3226
    partnum = -1;
 
3227
    if (nargs > 0) {
 
3228
        partnum = strtol(argv[0], NULL, 10);
 
3229
        if (partnum > 0) {
 
3230
            OF_DPRINTF("Open partition... %d %d\n", partnum, nargs);
 
3231
            bdinst->type = 1;
 
3232
            bdinst->u.part = part_get(bd, partnum);
 
3233
            if (bdinst->u.part == NULL) {
 
3234
                OF_DPRINTF("Partition %d not found\n", partnum);
 
3235
                free(bdinst);
 
3236
                pushd(OF_env, -1);
 
3237
                return;
 
3238
            }
 
3239
            if (nargs > 1) {
 
3240
                /* TODO: open file */
 
3241
                bdinst->type = 2;
 
3242
                OF_DPRINTF("Open file... %d %d '%s'\n",
 
3243
                           partnum, nargs, argv[1]);
 
3244
                OF_convert_path(&argv[1]);
 
3245
                if (*argv[1] != '/') {
 
3246
                    sprintf(tmp, "%s/%s",
 
3247
                            fs_get_boot_dirname(part_fs(bdinst->u.part)),
 
3248
                            argv[1]);
 
3249
                    bdinst->u.file = fs_open(part_fs(bdinst->u.part), tmp);
 
3250
                } else {
 
3251
                    bdinst->u.file = fs_open(part_fs(bdinst->u.part), argv[1]);
 
3252
                }
 
3253
                if (bdinst->u.file == NULL) {
 
3254
#if 0
 
3255
                    bug();
 
3256
#endif
 
3257
                    pushd(OF_env, 0x00000000);
 
3258
                    ERROR("File not found '%s'\n", argv[1]);
 
3259
                    return;
 
3260
                }
 
3261
            }
 
3262
        }
 
3263
    }
 
3264
    if (nargs == 0 || partnum == 0) {
 
3265
        OF_DPRINTF("Open disk... %d %d\n", nargs, partnum);
 
3266
        bdinst->type = 0;
 
3267
        bdinst->u.bd = bd;
 
3268
    }
 
3269
    /* TODO: find partition &/| file */
 
3270
    dsk_inst->data = bdinst;
 
3271
    OF_node_put(OF_env, dsk);
 
3272
 out:
 
3273
    pushd(OF_env, ihandle);
 
3274
}
 
3275
 
 
3276
static void OF_blockdev_seek (OF_env_t *OF_env)
 
3277
{
 
3278
    const unsigned char *args;
 
3279
    OF_inst_t *dsk_inst;
 
3280
    blockdev_inst_t *bdinst;
 
3281
    uint32_t posh, posl, bloc, pos, blocsize, tmp;
 
3282
    uint32_t ihandle;
 
3283
    uint16_t phandle;
 
3284
    int sh;
 
3285
 
 
3286
    OF_CHECK_NBARGS(OF_env, 4);
 
3287
    ihandle = popd(OF_env);
 
3288
    args = (void *)popd(OF_env);
 
3289
    phandle = (ihandle >> 16) & 0xFFFF;
 
3290
    posh = popd(OF_env);
 
3291
    posl = popd(OF_env);
 
3292
    dsk_inst = OF_inst_find(OF_env, ihandle);
 
3293
    if (dsk_inst == NULL) {
 
3294
        ERROR("Disk not found (ih: %0x)\n", ihandle);
 
3295
        pushd(OF_env, -1);
 
3296
        return;
 
3297
    }
 
3298
    bdinst = dsk_inst->data;
 
3299
    switch (bdinst->type) {
 
3300
    case 0:
 
3301
        blocsize = bd_seclen(bdinst->u.bd);
 
3302
        for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
 
3303
            sh++;
 
3304
        bloc = ((posh  << (32 - sh)) | (posl / blocsize));
 
3305
        pos = posl % blocsize;
 
3306
        OF_DPRINTF("disk: bsize %08x %08x %08x => %08x %08x\n", blocsize,
 
3307
               posh, posl, bloc, pos);
 
3308
        pushd(OF_env, bd_seek(bdinst->u.bd, bloc, pos));
 
3309
        break;
 
3310
    case 1:
 
3311
        blocsize = part_blocsize(bdinst->u.part);
 
3312
        for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
 
3313
            sh++;
 
3314
        bloc = ((posh  << (32 - sh)) | (posl / blocsize));
 
3315
        pos = posl % blocsize;
 
3316
        OF_DPRINTF("part: bsize %08x %08x %08x => %08x %08x\n", blocsize,
 
3317
               posh, posl, bloc, pos);
 
3318
        pushd(OF_env, part_seek(bdinst->u.part, bloc, pos));
 
3319
        break;
 
3320
    case 2:
 
3321
        blocsize = part_blocsize(fs_inode_get_part(bdinst->u.file));
 
3322
        for (tmp = blocsize, sh = 0; tmp != 1; tmp = tmp / 2)
 
3323
            sh++;
 
3324
        bloc = ((posh  << (32 - sh)) | (posl / blocsize));
 
3325
        pos = posl % blocsize;
 
3326
        OF_DPRINTF("file: bsize %08x %08x %08x => %08x %08x\n", blocsize,
 
3327
                   posh, posl, bloc, pos);
 
3328
        pushd(OF_env, fs_seek(bdinst->u.file, bloc, pos));
 
3329
        break;
 
3330
    }
 
3331
}
 
3332
 
 
3333
static void OF_blockdev_read (OF_env_t *OF_env)
 
3334
{
 
3335
    const unsigned char *args;
 
3336
    OF_inst_t *dsk_inst;
 
3337
    blockdev_inst_t *bdinst;
 
3338
    void *dest;
 
3339
    uint32_t len;
 
3340
    uint32_t ihandle;
 
3341
    uint16_t phandle;
 
3342
 
 
3343
    OF_CHECK_NBARGS(OF_env, 4);
 
3344
    ihandle = popd(OF_env);
 
3345
    args = (void *)popd(OF_env);
 
3346
    phandle = (ihandle >> 16) & 0xFFFF;
 
3347
    dest = (void *)popd(OF_env);
 
3348
    len = popd(OF_env);
 
3349
    dsk_inst = OF_inst_find(OF_env, ihandle);
 
3350
    if (dsk_inst == NULL) {
 
3351
        ERROR("Disk not found (ih: %0x)\n", ihandle);
 
3352
        pushd(OF_env, -1);
 
3353
        return;
 
3354
    }
 
3355
    bdinst = dsk_inst->data;
 
3356
    set_check(0);
 
3357
    OF_DPRINTF("dest: %p len: %d %d\n", dest, len, bdinst->type);
 
3358
    switch (bdinst->type) {
 
3359
    case 0:
 
3360
        OF_DPRINTF("read disk\n");
 
3361
        pushd(OF_env, bd_read(bdinst->u.bd, dest, len));
 
3362
        break;
 
3363
    case 1:
 
3364
        OF_DPRINTF("read partition\n");
 
3365
        pushd(OF_env, part_read(bdinst->u.part, dest, len));
 
3366
        break;
 
3367
    case 2:
 
3368
        OF_DPRINTF("read file\n");
 
3369
        pushd(OF_env, fs_read(bdinst->u.file, dest, len));
 
3370
        break;
 
3371
    }
 
3372
    OF_DPRINTF("%08x %08x %08x %08x\n",
 
3373
               ((uint32_t *)dest)[0], ((uint32_t *)dest)[1],
 
3374
               ((uint32_t *)dest)[2], ((uint32_t *)dest)[3]);
 
3375
    OF_DPRINTF("%08x %08x %08x %08x\n",
 
3376
               ((uint32_t *)dest)[4], ((uint32_t *)dest)[5],
 
3377
               ((uint32_t *)dest)[6], ((uint32_t *)dest)[7]);
 
3378
        
 
3379
    set_check(1);
 
3380
}
 
3381
 
 
3382
static void OF_blockdev_get_blocsize (OF_env_t *OF_env)
 
3383
{
 
3384
    const unsigned char *args;
 
3385
    OF_inst_t *dsk_inst;
 
3386
    blockdev_inst_t *bdinst;
 
3387
    uint32_t ihandle;
 
3388
    uint16_t phandle;
 
3389
    uint32_t blocsize;
 
3390
 
 
3391
    OF_CHECK_NBARGS(OF_env, 2);
 
3392
    ihandle = popd(OF_env);
 
3393
    args = (void *)popd(OF_env);
 
3394
    phandle = (ihandle >> 16) & 0xFFFF;
 
3395
    dsk_inst = OF_inst_find(OF_env, ihandle);
 
3396
    if (dsk_inst == NULL) {
 
3397
        ERROR("Disk not found (ih: %0x)\n", ihandle);
 
3398
        pushd(OF_env, -1);
 
3399
        return;
 
3400
    }
 
3401
    bdinst = dsk_inst->data;
 
3402
#if 0
 
3403
    switch (bdinst->type) {
 
3404
    case 0:
 
3405
        blocsize = bd_seclen(bdinst->u.bd);
 
3406
        break;
 
3407
    case 1:
 
3408
        blocsize = part_blocsize(bdinst->u.part);
 
3409
        break;
 
3410
    case 2:
 
3411
        blocsize = 512;
 
3412
        break;
 
3413
    }
 
3414
#else
 
3415
    blocsize = 512;
 
3416
#endif
 
3417
    pushd(OF_env, blocsize);
 
3418
    pushd(OF_env, 0);
 
3419
}
 
3420
 
 
3421
static void OF_blockdev_dma_alloc (OF_env_t *OF_env)
 
3422
{
 
3423
    const unsigned char *args;
 
3424
    void *address;
 
3425
    uint32_t ihandle;
 
3426
    uint32_t size;
 
3427
 
 
3428
    OF_CHECK_NBARGS(OF_env, 3);
 
3429
    ihandle = popd(OF_env);
 
3430
    args = (void *)popd(OF_env);
 
3431
    size = popd(OF_env);
 
3432
    OF_DPRINTF("size: %08x\n", size);
 
3433
    mem_align(size);
 
3434
    address = malloc(size);
 
3435
    if (address != NULL)
 
3436
        memset(address, 0, size);
 
3437
    pushd(OF_env, (uint32_t)address);
 
3438
    pushd(OF_env, 0);
 
3439
}
 
3440
 
 
3441
static void OF_blockdev_dma_free (OF_env_t *OF_env)
 
3442
{
 
3443
    const unsigned char *args;
 
3444
    void *address;
 
3445
    uint32_t ihandle;
 
3446
    uint32_t size;
 
3447
 
 
3448
    OF_CHECK_NBARGS(OF_env, 4);
 
3449
    ihandle = popd(OF_env);
 
3450
    args = (void *)popd(OF_env);
 
3451
    size = popd(OF_env);
 
3452
    address = (void *)popd(OF_env);
 
3453
    OF_DPRINTF("address: %p size: %08x\n", address, size);
 
3454
    free(address);
 
3455
    pushd(OF_env, 0);
 
3456
}
 
3457
 
 
3458
void *OF_blockdev_register (void *parent, void *private,
 
3459
                            const unsigned char *type,
 
3460
                            const unsigned char *name, int devnum,
 
3461
                            const char *alias)
 
3462
{
 
3463
    unsigned char tmp[OF_NAMELEN_MAX], path[OF_NAMELEN_MAX], *pos;
 
3464
    OF_env_t *OF_env;
 
3465
    OF_node_t *dsk, *als;
 
3466
    int i;
 
3467
    
 
3468
    OF_env = OF_env_main;
 
3469
    dsk = OF_node_new(OF_env, parent, name, devnum);
 
3470
    if (dsk == NULL) {
 
3471
        ERROR("Cannot create blockdev '%s'\n", name);
 
3472
        return NULL;
 
3473
    }
 
3474
    OF_prop_string_new(OF_env, dsk, "device_type", "block");
 
3475
    OF_prop_string_new(OF_env, dsk, "category", type);
 
3476
    OF_prop_int_new(OF_env, dsk, "device_id", devnum);
 
3477
    OF_prop_int_new(OF_env, dsk, "reg", devnum);
 
3478
    OF_method_new(OF_env, dsk, "open", &OF_blockdev_open);
 
3479
    OF_method_new(OF_env, dsk, "seek", &OF_blockdev_seek);
 
3480
    OF_method_new(OF_env, dsk, "read", &OF_blockdev_read);
 
3481
    OF_method_new(OF_env, dsk, "block-size",
 
3482
                  &OF_blockdev_get_blocsize);
 
3483
    OF_method_new(OF_env, dsk, "dma-alloc", &OF_blockdev_dma_alloc);
 
3484
    OF_method_new(OF_env, dsk, "dma-free", &OF_blockdev_dma_free);
 
3485
    if (strcmp(type, "cdrom") == 0)
 
3486
        OF_method_new(OF_env, dsk, "eject", &OF_method_fake);
 
3487
    OF_method_new(OF_env, dsk, "close", &OF_method_fake);
 
3488
    dsk->private_data = private;
 
3489
    /* Set up aliases */
 
3490
    OF_pack_get_path(OF_env, path, OF_NAMELEN_MAX, dsk);
 
3491
    if (alias != NULL) {
 
3492
        als = OF_node_get(OF_env, "aliases");
 
3493
        if (als == NULL) {
 
3494
            ERROR("Cannot get 'aliases'\n");
 
3495
            return NULL;
 
3496
        }
 
3497
        strcpy(tmp, alias);
 
3498
        if (OF_property_copy(OF_env, NULL, 0, als, tmp) >= 0) {
 
3499
            pos = tmp + strlen(alias);
 
3500
            for (i = 0; ; i++) {
 
3501
                sprintf(pos, "%d", i);
 
3502
                if (OF_property_copy(OF_env, NULL, 0, als, tmp) < 0)
 
3503
                    break;
 
3504
            }
 
3505
        }
 
3506
        OF_DPRINTF("Set alias to %s\n", tmp);
 
3507
        OF_prop_string_new(OF_env, dsk, "alias", tmp);
 
3508
        OF_prop_string_new(OF_env, als, tmp, path);
 
3509
        OF_node_put(OF_env, als);
 
3510
    }
 
3511
    
 
3512
    return dsk;
 
3513
}
 
3514
 
 
3515
void OF_blockdev_set_boot_device (void *disk, int partnum,
 
3516
                                  const unsigned char *file)
 
3517
{
 
3518
    unsigned char tmp[OF_NAMELEN_MAX], *pos;
 
3519
    OF_env_t *OF_env;
 
3520
    OF_node_t *dsk = disk, *opts, *chs;
 
3521
    
 
3522
    OF_env = OF_env_main;
 
3523
    
 
3524
    if (OF_property_copy(OF_env, tmp, OF_NAMELEN_MAX, dsk, "alias") < 0)
 
3525
        OF_pack_get_path(OF_env, tmp, OF_NAMELEN_MAX, dsk);
 
3526
    sprintf(tmp + strlen(tmp), ":%d", partnum);
 
3527
    /* OpenDarwin 6.02 seems to need this one */
 
3528
    opts = OF_node_get(OF_env, "options");
 
3529
    if (opts == NULL) {
 
3530
        ERROR("Cannot get 'options'\n");
 
3531
        return;
 
3532
    }
 
3533
    OF_prop_string_set(OF_env, OF_node_root, "boot-device", tmp);
 
3534
    OF_prop_string_set(OF_env, opts, "boot-device", tmp);
 
3535
    OF_DPRINTF("Set boot device to: '%s'\n", tmp);
 
3536
    OF_node_put(OF_env, opts);
 
3537
    /* Set the real boot path */
 
3538
    pos = tmp + strlen(tmp);
 
3539
    sprintf(pos, ",%s", file);
 
3540
    /* Convert all '/' into '\' in the boot file name */
 
3541
    for (; *pos != '\0'; pos++) {
 
3542
        if (*pos == '/')
 
3543
            *pos = '\\';
 
3544
    }
 
3545
    chs = OF_node_get(OF_env, "chosen");
 
3546
    if (chs == NULL) {
 
3547
        ERROR("Cannot get 'chosen'\n");
 
3548
        return;
 
3549
    }
 
3550
    OF_prop_string_set(OF_env, chs, "bootpath", tmp);
 
3551
    OF_DPRINTF("Set boot path to: '%s'\n", tmp);
 
3552
    OF_node_put(OF_env, chs);
 
3553
}
 
3554
 
 
3555
/* Display package */
 
3556
static void OF_vga_draw_rectangle (OF_env_t *OF_env)
 
3557
{
 
3558
    const void *buf;
 
3559
    const unsigned char *args;
 
3560
    uint32_t posx, posy, width, height;
 
3561
    uint32_t ihandle;
 
3562
 
 
3563
    OF_CHECK_NBARGS(OF_env, 7);
 
3564
    ihandle = popd(OF_env);
 
3565
    args = (void *)popd(OF_env);
 
3566
    height = popd(OF_env);
 
3567
    width = popd(OF_env);
 
3568
    posy = popd(OF_env);
 
3569
    posx = popd(OF_env);
 
3570
    buf = (const void *)popd(OF_env);
 
3571
    OF_DPRINTF("x=%d y=%d h=%d ", posx, posy, width);
 
3572
    OF_DPRINTF("w=%d buf=%p\n", height, buf);
 
3573
    set_check(0);
 
3574
    vga_draw_buf(buf, width * vga_fb_bpp, posx, posy, width, height);
 
3575
    set_check(1);
 
3576
    pushd(OF_env, 0);
 
3577
}
 
3578
 
 
3579
static void OF_vga_fill_rectangle (OF_env_t *OF_env)
 
3580
{
 
3581
    const unsigned char *args;
 
3582
    uint32_t color, posx, posy, width, height;
 
3583
    uint32_t ihandle;
 
3584
 
 
3585
    OF_CHECK_NBARGS(OF_env, 7);
 
3586
    ihandle = popd(OF_env);
 
3587
    args = (void *)popd(OF_env);
 
3588
    height = popd(OF_env);
 
3589
    width = popd(OF_env);
 
3590
    posy = popd(OF_env);
 
3591
    posx = popd(OF_env);
 
3592
    color = popd(OF_env);
 
3593
    OF_DPRINTF("x=%d y=%d\n", posx, posy);
 
3594
    OF_DPRINTF("h=%d w=%d c=%0x\n", width, height, color);
 
3595
    vga_fill_rect(posx, posy, width, height, color);
 
3596
    pushd(OF_env, 0);
 
3597
}
 
3598
 
 
3599
static void OF_vga_set_width (OF_env_t *OF_env, OF_prop_t *prop,
 
3600
                              const void *data, int len)
 
3601
{
 
3602
    uint32_t width, height, depth;
 
3603
 
 
3604
    if (len == sizeof(uint32_t)) {
 
3605
        width = *(uint32_t *)data;
 
3606
        OF_property_copy(OF_env, &height, 4, prop->node, "height");
 
3607
        OF_property_copy(OF_env, &depth, 4, prop->node, "depth");
 
3608
        vga_set_mode(width, height, depth);
 
3609
    }
 
3610
}
 
3611
 
 
3612
static void OF_vga_set_height (OF_env_t *OF_env, OF_prop_t *prop,
 
3613
                               const void *data, int len)
 
3614
{
 
3615
    uint32_t width, height, depth;
 
3616
 
 
3617
    if (len == sizeof(uint32_t)) {
 
3618
        OF_property_copy(OF_env, &width, 4, prop->node, "width");
 
3619
        height = *(uint32_t *)data;
 
3620
        OF_property_copy(OF_env, &depth, 4, prop->node, "depth");
 
3621
        vga_set_mode(width, height, depth);
 
3622
    }
 
3623
}
 
3624
 
 
3625
static void OF_vga_set_depth (OF_env_t *OF_env, OF_prop_t *prop,
 
3626
                              const void *data, int len)
 
3627
{
 
3628
    uint32_t width, height, depth;
 
3629
 
 
3630
    if (len == sizeof(uint32_t)) {
 
3631
        OF_property_copy(OF_env, &width, 4, prop->node, "width");
 
3632
        OF_property_copy(OF_env, &height, 4, prop->node, "height");
 
3633
        depth = *(uint32_t *)data;
 
3634
        vga_set_mode(width, height, depth);
 
3635
    }
 
3636
}
 
3637
 
 
3638
void OF_vga_register (const unsigned char *name, unused uint32_t address,
 
3639
                      int width, int height, int depth,
 
3640
                      unsigned long vga_bios_addr, unsigned long vga_bios_size)
 
3641
{
 
3642
    OF_env_t *OF_env;
 
3643
    unsigned char tmp[OF_NAMELEN_MAX];
 
3644
    OF_node_t *disp, *chs, *als;
 
3645
    OF_prop_t *prop;
 
3646
    
 
3647
    OF_DPRINTF("Set frame buffer %08x %dx%dx%d\n",
 
3648
               address, width, height, depth);
 
3649
    OF_env = OF_env_main;
 
3650
    disp = OF_node_get(OF_env, name);
 
3651
    if (disp == NULL) {
 
3652
        ERROR("Cannot get display '%s'\n", name);
 
3653
        return;
 
3654
    }
 
3655
    prop = OF_prop_int_new(OF_env, disp, "width", width);
 
3656
    if (prop == NULL) {
 
3657
        OF_node_put(OF_env, disp);
 
3658
        ERROR("Cannot create display width property\n");
 
3659
        return;
 
3660
    }
 
3661
    OF_property_set_cb(OF_env, prop, &OF_vga_set_width);
 
3662
    prop = OF_prop_int_new(OF_env, disp, "height", height);
 
3663
    if (prop == NULL) {
 
3664
        OF_node_put(OF_env, disp);
 
3665
        ERROR("Cannot create display height property\n");
 
3666
        return;
 
3667
    }
 
3668
    OF_property_set_cb(OF_env, prop, &OF_vga_set_height);
 
3669
    switch (depth) {
 
3670
    case 8:
 
3671
        break;
 
3672
    case 15:
 
3673
        depth = 16;
 
3674
        break;
 
3675
    case 32:
 
3676
        break;
 
3677
    default:
 
3678
        /* OF spec this is mandatory, but we have no support for it */
 
3679
        printf("%d bits VGA isn't implemented\n", depth);
 
3680
        bug();
 
3681
        /* Never come here */
 
3682
        break;
 
3683
    }
 
3684
    prop = OF_prop_int_new(OF_env, disp, "depth", depth);
 
3685
    if (prop == NULL) {
 
3686
        ERROR("Cannot create display depth\n");
 
3687
        goto out;
 
3688
    }
 
3689
    OF_property_set_cb(OF_env, prop, &OF_vga_set_depth);
 
3690
    OF_prop_int_new(OF_env, disp, "linebytes", vga_fb_linesize);
 
3691
    OF_method_new(OF_env, disp, "draw-rectangle", &OF_vga_draw_rectangle);
 
3692
    OF_method_new(OF_env, disp, "fill-rectangle", &OF_vga_fill_rectangle);
 
3693
    OF_method_new(OF_env, disp, "color!", &OF_method_fake);
 
3694
    chs = OF_node_get(OF_env, "chosen");
 
3695
    if (chs == NULL) {
 
3696
        ERROR("Cannot get 'chosen'\n");
 
3697
        goto out;
 
3698
    }
 
3699
    OF_prop_int_new(OF_env, chs, "display", OF_pack_handle(OF_env, disp));
 
3700
    OF_node_put(OF_env, chs);
 
3701
    OF_pack_get_path(OF_env, tmp, 512, disp);
 
3702
    printf("Set display '%s' path to '%s'\n", name, tmp);
 
3703
    als = OF_node_get(OF_env, "aliases");
 
3704
    if (als == NULL) {
 
3705
        ERROR("Cannot get 'aliases'\n");
 
3706
        goto out;
 
3707
    }
 
3708
    OF_prop_string_new(OF_env, als, "screen", tmp);
 
3709
    OF_prop_string_new(OF_env, als, "display", tmp);
 
3710
    OF_node_put(OF_env, als);
 
3711
    /* XXX: may also need read-rectangle */
 
3712
 
 
3713
    if (vga_bios_size >= 8) {
 
3714
        const uint8_t *p;
 
3715
        int size;
 
3716
        /* check the QEMU VGA BIOS header */
 
3717
        p = (const uint8_t *)vga_bios_addr;
 
3718
        if (p[0] == 'N' && p[1] == 'D' && p[2] == 'R' && p[3] == 'V') {
 
3719
            size = *(uint32_t *)(p + 4);
 
3720
            OF_property_new(OF_env, disp, "driver,AAPL,MacOS,PowerPC", 
 
3721
                            p + 8, size);
 
3722
        }
 
3723
    }
 
3724
 out:
 
3725
    OF_node_put(OF_env, disp);
 
3726
}
 
3727
 
 
3728
/* Pseudo packages to make BootX happy */
 
3729
/* sl_words package */
 
3730
static void slw_set_output_level (OF_env_t *OF_env)
 
3731
{
 
3732
    OF_node_t *slw;
 
3733
    const unsigned char *args;
 
3734
    int level;
 
3735
 
 
3736
    OF_CHECK_NBARGS(OF_env, 3);
 
3737
    popd(OF_env);
 
3738
    args = (void *)popd(OF_env);
 
3739
    level = popd(OF_env);
 
3740
    slw = OF_node_get(OF_env, "sl_words");
 
3741
    if (slw == NULL) {
 
3742
        pushd(OF_env, -1);
 
3743
    } else {
 
3744
        OF_DPRINTF("Set output level to: %d\n", level);
 
3745
        OF_prop_int_set(OF_env, slw, "outputLevel", level);
 
3746
        OF_node_put(OF_env, slw);
 
3747
        pushd(OF_env, 0);
 
3748
    }
 
3749
}
 
3750
 
 
3751
#ifdef DEBUG_BIOS
 
3752
#define EMIT_BUFFER_LEN 256
 
3753
static unsigned char emit_buffer[EMIT_BUFFER_LEN];
 
3754
static int emit_pos = 0;
 
3755
#endif
 
3756
 
 
3757
static void slw_emit (OF_env_t *OF_env)
 
3758
{
 
3759
    const unsigned char *args;
 
3760
    int c;
 
3761
 
 
3762
    OF_CHECK_NBARGS(OF_env, 3);
 
3763
    popd(OF_env);
 
3764
    args = (void *)popd(OF_env);
 
3765
    c = popd(OF_env);
 
3766
    //    OF_DPRINTF("Emit char %d\n", c);
 
3767
#ifdef DEBUG_BIOS
 
3768
    if (emit_pos < EMIT_BUFFER_LEN - 1) {
 
3769
        emit_buffer[emit_pos++] = c;
 
3770
        //        outb(0xFF00, c);
 
3771
        outb(0x0F00, c);
 
3772
    } else {
 
3773
        emit_buffer[emit_pos] = '\0';
 
3774
    }
 
3775
#else
 
3776
    outb(0x0F00, c);
 
3777
#endif
 
3778
    pushd(OF_env, 0);
 
3779
}
 
3780
 
 
3781
static void slw_cr (OF_env_t *OF_env)
 
3782
{
 
3783
    const unsigned char *args;
 
3784
 
 
3785
    OF_CHECK_NBARGS(OF_env, 2);
 
3786
    popd(OF_env);
 
3787
    args = (void *)popd(OF_env);
 
3788
    //    OF_DPRINTF("Emit CR char\n");
 
3789
    //    outb(0xFF01, '\n');
 
3790
    outb(0x0F01, '\n');
 
3791
#ifdef DEBUG_BIOS
 
3792
    emit_buffer[emit_pos] = '\0';
 
3793
    if (strcmp(emit_buffer, "Call Kernel!") == 0) {
 
3794
        /* Set qemu in debug mode:
 
3795
         * log in_asm,op,int,ioport,cpu
 
3796
         */
 
3797
        uint16_t loglevel = 0x02 | 0x10 | 0x80;
 
3798
        //        outw(0xFF02, loglevel);
 
3799
        outb(0x0F02, loglevel);
 
3800
    }
 
3801
    emit_pos = 0;
 
3802
#endif
 
3803
    pushd(OF_env, 0);
 
3804
}
 
3805
 
 
3806
static void slw_init_keymap (OF_env_t *OF_env)
 
3807
{
 
3808
    const unsigned char *args;
 
3809
    OF_node_t *node;
 
3810
    OF_prop_t *prop;
 
3811
    uint32_t phandle, ihandle;
 
3812
 
 
3813
    OF_CHECK_NBARGS(OF_env, 3);
 
3814
    ihandle = popd(OF_env);
 
3815
    args = (void *)popd(OF_env);
 
3816
    phandle = ihandle >> 16;
 
3817
    ihandle &= 0xFFFF;
 
3818
    OF_DPRINTF("\n");
 
3819
    node = OF_pack_find(OF_env, phandle);
 
3820
    if (node == NULL) {
 
3821
        ERROR("Cant' init slw keymap\n");
 
3822
        pushd(OF_env, -1);
 
3823
    } else {
 
3824
        prop = OF_property_get(OF_env, node, "keyMap");
 
3825
        if (prop == NULL) {
 
3826
            pushd(OF_env, -1);
 
3827
        } else {
 
3828
            pushd(OF_env, (uint32_t)prop->value);
 
3829
            pushd(OF_env, 0);
 
3830
        }
 
3831
    }
 
3832
}
 
3833
 
 
3834
static void slw_update_keymap (OF_env_t *OF_env)
 
3835
{
 
3836
    const unsigned char *args;
 
3837
 
 
3838
    OF_CHECK_NBARGS(OF_env, 2);
 
3839
    popd(OF_env);
 
3840
    args = (void *)popd(OF_env);
 
3841
    OF_DPRINTF("\n");
 
3842
    pushd(OF_env, 0);
 
3843
}
 
3844
 
 
3845
static void slw_spin (OF_env_t *OF_env)
 
3846
{
 
3847
    const unsigned char *args;
 
3848
    /* XXX: cur_spin should be in sl_words package */
 
3849
    static int cur_spin = 0;
 
3850
    int c;
 
3851
 
 
3852
    OF_CHECK_NBARGS(OF_env, 2);
 
3853
    popd(OF_env);
 
3854
    args = (void *)popd(OF_env);
 
3855
    if (cur_spin > 15) {
 
3856
        c = RGB(0x30, 0x30, 0x50);
 
3857
    } else {
 
3858
        c = RGB(0x11, 0x11, 0x11);
 
3859
    }
 
3860
    c = vga_get_color(c);
 
3861
    vga_fill_rect((cur_spin % 15) * 5 + 280, 420, 4, 3, c);
 
3862
    cur_spin = (cur_spin + 1) & 31;
 
3863
    OF_DPRINTF("\n");
 
3864
    pushd(OF_env, -1);
 
3865
}
 
3866
 
 
3867
static void slw_spin_init (OF_env_t *OF_env)
 
3868
{
 
3869
    const unsigned char *args;
 
3870
 
 
3871
    OF_CHECK_NBARGS(OF_env, 8);
 
3872
    popd(OF_env);
 
3873
    args = (void *)popd(OF_env);
 
3874
    popd(OF_env);
 
3875
    popd(OF_env);
 
3876
    popd(OF_env);
 
3877
    popd(OF_env);
 
3878
    popd(OF_env);
 
3879
    popd(OF_env);
 
3880
    pushd(OF_env, -1);
 
3881
}
 
3882
 
 
3883
static void slw_pwd (OF_env_t *OF_env)
 
3884
{
 
3885
    const unsigned char *args;
 
3886
 
 
3887
    OF_CHECK_NBARGS(OF_env, 3);
 
3888
    popd(OF_env);
 
3889
    args = (void *)popd(OF_env);
 
3890
    OF_DPRINTF("\n");
 
3891
    pushd(OF_env, -1);
 
3892
}
 
3893
 
 
3894
static void slw_sum (OF_env_t *OF_env)
 
3895
{
 
3896
    const unsigned char *args;
 
3897
 
 
3898
    OF_CHECK_NBARGS(OF_env, 3);
 
3899
    popd(OF_env);
 
3900
    args = (void *)popd(OF_env);
 
3901
    OF_DPRINTF("\n");
 
3902
    pushd(OF_env, -1);
 
3903
}
 
3904
 
 
3905
/*****************************************************************************/
 
3906
/*                       Client program interface                            */
 
3907
/* Client interface services */
 
3908
static void OF_test (OF_env_t *OF_env);
 
3909
 
 
3910
/* Device tree services */
 
3911
/* Get next package */
 
3912
__attribute__ (( section (".OpenFirmware") ))
 
3913
static void OF_peer (OF_env_t *OF_env)
 
3914
{
 
3915
    OF_node_t *node;
 
3916
    uint32_t phandle;
 
3917
 
 
3918
    OF_CHECK_NBARGS(OF_env, 1);
 
3919
    phandle = popd(OF_env);
 
3920
    OF_DPRINTF("phandle 0x%0x\n", phandle);
 
3921
    if (phandle == 0)
 
3922
        node = OF_node_root;
 
3923
    else
 
3924
        node = OF_pack_next(OF_env, phandle);
 
3925
    if (node == NULL)
 
3926
        pushd(OF_env, 0);
 
3927
    else
 
3928
        pushd(OF_env, OF_pack_handle(OF_env, node));
 
3929
}
 
3930
 
 
3931
/* Get first child package */
 
3932
__attribute__ (( section (".OpenFirmware") ))
 
3933
static void OF_child (OF_env_t *OF_env)
 
3934
{
 
3935
    OF_node_t *node;
 
3936
    uint32_t phandle;
 
3937
 
 
3938
    OF_CHECK_NBARGS(OF_env, 1);
 
3939
    phandle = popd(OF_env);
 
3940
    OF_DPRINTF("phandle 0x%0x\n", phandle);
 
3941
    node = OF_pack_child(OF_env, phandle);
 
3942
    if (node == NULL)
 
3943
        pushd(OF_env, 0);
 
3944
    else
 
3945
        pushd(OF_env, OF_pack_handle(OF_env, node));
 
3946
}
 
3947
 
 
3948
/* Get parent package */
 
3949
__attribute__ (( section (".OpenFirmware") ))
 
3950
static void OF_parent (OF_env_t *OF_env)
 
3951
{
 
3952
    OF_node_t *node;
 
3953
    uint32_t phandle;
 
3954
 
 
3955
    OF_CHECK_NBARGS(OF_env, 1);
 
3956
    phandle = popd(OF_env);
 
3957
    OF_DPRINTF("phandle 0x%0x\n", phandle);
 
3958
    node = OF_pack_parent(OF_env, phandle);
 
3959
    if (node == NULL)
 
3960
        pushd(OF_env, 0);
 
3961
    else
 
3962
        pushd(OF_env, OF_pack_handle(OF_env, node));
 
3963
}
 
3964
 
 
3965
/* Get package related to an instance */
 
3966
__attribute__ (( section (".OpenFirmware") ))
 
3967
static void OF_instance_to_package (OF_env_t *OF_env)
 
3968
{
 
3969
    uint32_t ihandle;
 
3970
 
 
3971
    OF_CHECK_NBARGS(OF_env, 1);
 
3972
    ihandle = popd(OF_env);
 
3973
    OF_DPRINTF("ihandle 0x%0x\n", ihandle);
 
3974
    pushd(OF_env, (ihandle >> 16) & 0xFFFF);
 
3975
}
 
3976
 
 
3977
/* Get property len */
 
3978
__attribute__ (( section (".OpenFirmware") ))
 
3979
static void OF_getproplen (OF_env_t *OF_env)
 
3980
{
 
3981
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
3982
    OF_node_t *node;
 
3983
    uint32_t phandle;
 
3984
 
 
3985
    OF_CHECK_NBARGS(OF_env, 2);
 
3986
    phandle = popd(OF_env);
 
3987
    namep = (unsigned char *)popd(OF_env);
 
3988
    OF_lds(name, namep);
 
3989
    OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
 
3990
    node = OF_pack_find(OF_env, phandle);
 
3991
    if (node == NULL)
 
3992
        pushd(OF_env, -1);
 
3993
    else
 
3994
        pushd(OF_env, OF_property_len(OF_env, node, name));
 
3995
}
 
3996
 
 
3997
/* Get property */
 
3998
__attribute__ (( section (".OpenFirmware") ))
 
3999
static void OF_getprop (OF_env_t *OF_env)
 
4000
{
 
4001
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4002
    OF_node_t *node;
 
4003
    void *buffer;
 
4004
    uint32_t phandle;
 
4005
    int len, nb_args;
 
4006
 
 
4007
    //    OF_CHECK_NBARGS(OF_env, 4);
 
4008
    nb_args = stackd_depth(OF_env);
 
4009
    phandle = popd(OF_env);
 
4010
    namep = (unsigned char *)popd(OF_env);
 
4011
    OF_lds(name, namep);
 
4012
    buffer = (void *)popd(OF_env);
 
4013
    if (nb_args == 3) {
 
4014
        /* This hack is needed to boot MacOS X panther (10.3) */
 
4015
        len = 1024;
 
4016
    } else {
 
4017
        len = popd(OF_env);
 
4018
    }
 
4019
    OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
 
4020
    OF_DPRINTF("buffer %p len %d\n", buffer, len);
 
4021
    node = OF_pack_find(OF_env, phandle);
 
4022
    if (node == NULL) {
 
4023
        len = -1;
 
4024
    } else {
 
4025
        len = OF_property_copy(OF_env, buffer, len, node, name);
 
4026
        if (len != -1) {
 
4027
            OF_DPRINTF("Copied %d bytes\n", len);
 
4028
        }
 
4029
    }
 
4030
    pushd(OF_env, len);
 
4031
}
 
4032
 
 
4033
/* Check existence of next property */
 
4034
__attribute__ (( section (".OpenFirmware") ))
 
4035
static void OF_nextprop (OF_env_t *OF_env)
 
4036
{
 
4037
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4038
    OF_node_t *node;
 
4039
    OF_prop_t *next;
 
4040
    unsigned char *next_name;
 
4041
    uint32_t phandle;
 
4042
 
 
4043
    OF_CHECK_NBARGS(OF_env, 3);
 
4044
    phandle = popd(OF_env);
 
4045
    namep = (unsigned char *)popd(OF_env);
 
4046
    OF_lds(name, namep);
 
4047
    OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
 
4048
    next_name = (unsigned char *)popd(OF_env);
 
4049
    node = OF_pack_find(OF_env, phandle);
 
4050
    if (node == NULL) {
 
4051
        pushd(OF_env, -1);
 
4052
    } else {
 
4053
        next = OF_property_next(OF_env, node, name);
 
4054
        if (next == NULL || next->name == NULL) {
 
4055
            OF_DPRINTF("No next property found [%s]\n", name);
 
4056
            pushd(OF_env, 0);
 
4057
        } else {
 
4058
            OF_DPRINTF("Return property name [%s]\n", next->name);
 
4059
            OF_sts(next_name, (void *)(next->name));
 
4060
            OF_DUMP_STRING(OF_env, next_name);
 
4061
            pushd(OF_env, strlen(next->name) + 1);
 
4062
        }
 
4063
    }
 
4064
}
 
4065
 
 
4066
/* Set a property */
 
4067
__attribute__ (( section (".OpenFirmware") ))
 
4068
static void OF_setprop (OF_env_t *OF_env)
 
4069
{
 
4070
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4071
    unsigned char *value, *buffer;
 
4072
    OF_node_t *node;
 
4073
    OF_prop_t *prop;
 
4074
    uint32_t phandle;
 
4075
    int len;
 
4076
    int i;
 
4077
 
 
4078
    OF_CHECK_NBARGS(OF_env, 4);
 
4079
    phandle = popd(OF_env);
 
4080
    namep = (unsigned char *)popd(OF_env);
 
4081
    OF_lds(name, namep);
 
4082
    OF_DPRINTF("phandle 0x%0x prop [%s]\n", phandle, name);
 
4083
    buffer = (unsigned char *)popd(OF_env);
 
4084
    len = popd(OF_env);
 
4085
    node = OF_pack_find(OF_env, phandle);
 
4086
    if (node == NULL) {
 
4087
        pushd(OF_env, -1);
 
4088
        ERROR("Cannot get pack %04x\n", phandle);
 
4089
        return;
 
4090
    }
 
4091
    value = malloc(len);
 
4092
    if (value == NULL && len != 0) {
 
4093
        pushd(OF_env, -1);
 
4094
        ERROR("%s: Cannot alloc property '%s' (%d)\n", __func__, name, len);
 
4095
        return;
 
4096
    }
 
4097
    for (i = 0; i < len; i++)
 
4098
        value[i] = buffer[i];
 
4099
    prop = OF_property_set(OF_env, node, name, value, len);
 
4100
    if (prop == NULL)
 
4101
        len = -1;
 
4102
   pushd(OF_env, len);
 
4103
}
 
4104
 
 
4105
/* "canon" */
 
4106
 
 
4107
/* Find a device given its path */
 
4108
__attribute__ (( section (".OpenFirmware") ))
 
4109
static OF_node_t *OF_get_alias (OF_env_t *OF_env, const unsigned char *name)
 
4110
{
 
4111
    unsigned char tmp[OF_NAMELEN_MAX], *pos, *st;
 
4112
    const unsigned char *alias, *npos;
 
4113
    OF_node_t *als, *node;
 
4114
    OF_prop_t *prop;
 
4115
 
 
4116
    node = NULL;
 
4117
    strcpy(tmp, name);
 
4118
    for (st = tmp; *st == '/'; st++)
 
4119
        continue;
 
4120
    pos = strchr(st, '/');
 
4121
    if (pos == NULL) {
 
4122
        pos = strchr(st, ':');
 
4123
    }
 
4124
    if (pos != NULL) {
 
4125
        *pos = '\0';
 
4126
        npos = name + (pos - tmp);
 
4127
    } else {
 
4128
        npos = "";
 
4129
    }
 
4130
    OF_DPRINTF("Look for alias for '%s' => '%s' '%s'\n", name, tmp, npos);
 
4131
    als = OF_pack_find_by_name(OF_env, OF_node_root, "/aliases");
 
4132
    if (als == NULL) {
 
4133
        ERROR("Cannot get 'aliases'\n");
 
4134
        return NULL;
 
4135
    }
 
4136
    prop = OF_property_get(OF_env, als, tmp);
 
4137
    if (prop == NULL) {
 
4138
        OF_DPRINTF("No %s alias !\n", tmp);
 
4139
        goto out;
 
4140
    }
 
4141
    alias = prop->value;
 
4142
    OF_DPRINTF("Found alias '%s' '%s'\n", alias, npos);
 
4143
    sprintf(tmp, "%s%s", alias, npos);
 
4144
    node = OF_pack_find_by_name(OF_env, OF_node_root, tmp);
 
4145
    if (node == NULL) {
 
4146
        printf("%s alias is a broken link !\n", name);
 
4147
        goto out;
 
4148
    }
 
4149
    OF_node_put(OF_env, node);
 
4150
 out:
 
4151
    OF_node_put(OF_env, als);
 
4152
 
 
4153
    return node;
 
4154
}
 
4155
 
 
4156
__attribute__ (( section (".OpenFirmware") ))
 
4157
static void OF_finddevice (OF_env_t *OF_env)
 
4158
{
 
4159
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4160
    OF_node_t *node;
 
4161
    int ret;
 
4162
 
 
4163
    OF_CHECK_NBARGS(OF_env, 1);
 
4164
    namep = (unsigned char *)popd(OF_env);
 
4165
    OF_lds(name, namep);
 
4166
    OF_DPRINTF("name %p [%s]\n", namep, name);
 
4167
    /* Search first in "/aliases" */
 
4168
    node = OF_get_alias(OF_env, name);
 
4169
    if (node == NULL) {
 
4170
        node = OF_pack_find_by_name(OF_env, OF_node_root, name);
 
4171
    }
 
4172
    if (node == NULL)
 
4173
        ret = -1;
 
4174
    else
 
4175
        ret = OF_pack_handle(OF_env, node);
 
4176
    OF_DPRINTF("ret 0x%0x\n", ret);
 
4177
    pushd(OF_env, ret);
 
4178
}
 
4179
 
 
4180
/* "instance-to-path */
 
4181
__attribute__ (( section (".OpenFirmware") ))
 
4182
static void OF_instance_to_path (OF_env_t *OF_env)
 
4183
{
 
4184
    void *buffer;
 
4185
    OF_inst_t *inst;
 
4186
    uint32_t ihandle;
 
4187
    int len;
 
4188
 
 
4189
    OF_CHECK_NBARGS(OF_env, 3);
 
4190
    OF_DPRINTF("\n");
 
4191
    ihandle = popd(OF_env);
 
4192
    buffer = (void *)popd(OF_env);
 
4193
    len = popd(OF_env);
 
4194
    OF_DPRINTF("ihandle: 0x%0x len=%d\n", ihandle, len);
 
4195
    inst = OF_inst_find(OF_env, ihandle);
 
4196
    if (inst == NULL)
 
4197
        len = -1;
 
4198
    else
 
4199
        len = OF_inst_get_path(OF_env, buffer, len, inst) + 1;
 
4200
    OF_DUMP_STRING(OF_env, buffer);
 
4201
    pushd(OF_env, len);
 
4202
}
 
4203
 
 
4204
/* "package-to-path" */
 
4205
__attribute__ (( section (".OpenFirmware") ))
 
4206
static void OF_package_to_path (OF_env_t *OF_env)
 
4207
{
 
4208
    void *buffer;
 
4209
    OF_node_t *node;
 
4210
    uint32_t phandle;
 
4211
    int len;
 
4212
 
 
4213
    OF_CHECK_NBARGS(OF_env, 3);
 
4214
    OF_DPRINTF("\n");
 
4215
    phandle = popd(OF_env);
 
4216
    buffer = (void *)popd(OF_env);
 
4217
    len = popd(OF_env);
 
4218
    node = OF_pack_find(OF_env, phandle);
 
4219
    if (node == NULL)
 
4220
        len = -1;
 
4221
    else
 
4222
        len = OF_pack_get_path(OF_env, buffer, len, node) + 1;
 
4223
    OF_DUMP_STRING(OF_env, buffer);
 
4224
    pushd(OF_env, len);
 
4225
}
 
4226
 
 
4227
/* Call a package's method */
 
4228
__attribute__ (( section (".OpenFirmware") ))
 
4229
static void _OF_callmethod (OF_env_t *OF_env, const unsigned char *name,
 
4230
                            uint32_t ihandle, const unsigned char *argp)
 
4231
{
 
4232
    OF_node_t *node;
 
4233
    OF_inst_t *inst;
 
4234
    OF_method_t *method;
 
4235
    OF_cb_t cb;
 
4236
 
 
4237
    inst = OF_inst_find(OF_env, ihandle);
 
4238
    OF_DPRINTF("Attempt to call method [%s] of package instance 0x%0x\n",
 
4239
               name, ihandle);
 
4240
    if (inst == NULL) {
 
4241
        OF_DPRINTF("No instance %0x\n", ihandle);
 
4242
        pushd(OF_env, -1);
 
4243
        return;
 
4244
    }
 
4245
    node = inst->node;
 
4246
    method = OF_method_get(OF_env, node, name);
 
4247
    if (method != NULL) {
 
4248
        cb = method->func;
 
4249
    } else {
 
4250
        if (strcmp(name, "open") == 0) {
 
4251
            cb = &OF_method_fake;
 
4252
        } else {
 
4253
            printf("Method '%s' not found in '%s'\n",
 
4254
                   name, node->prop_name->value);
 
4255
            pushd(OF_env, -1);
 
4256
            bug();
 
4257
            return;
 
4258
        }
 
4259
    }
 
4260
#if 0
 
4261
    OF_DPRINTF("Push instance method %p (%p)...\n", &method->func,
 
4262
               &slw_emit);
 
4263
#endif
 
4264
    pushf(OF_env, &cb);
 
4265
    if (argp != NULL)
 
4266
        pushd(OF_env, (uint32_t)argp);
 
4267
    else
 
4268
        pushd(OF_env, 0x00000000);
 
4269
    pushd(OF_env, ihandle);
 
4270
}
 
4271
 
 
4272
__attribute__ (( section (".OpenFirmware") ))
 
4273
static unsigned char *OF_get_args (unused OF_env_t *env, unsigned char *name)
 
4274
{
 
4275
    unsigned char *sd;
 
4276
 
 
4277
    sd = strchr(name, ':');
 
4278
    if (sd == NULL)
 
4279
        return NULL;
 
4280
    *sd = '\0';
 
4281
 
 
4282
    return sd + 1;
 
4283
}
 
4284
 
 
4285
__attribute__ (( section (".OpenFirmware") ))
 
4286
static void OF_callmethod (OF_env_t *OF_env)
 
4287
{
 
4288
    const unsigned char *args;
 
4289
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4290
    uint32_t ihandle;
 
4291
 
 
4292
    OF_DPRINTF("\n\n\n#### CALL METHOD ####\n\n");
 
4293
    namep = (unsigned char *)popd(OF_env);
 
4294
    OF_lds(name, namep);
 
4295
    args = OF_get_args(OF_env, name);
 
4296
    ihandle = popd(OF_env);
 
4297
    _OF_callmethod(OF_env, name, ihandle, args);
 
4298
}
 
4299
 
 
4300
/* Device IO services */
 
4301
/* Create a new instance of a device's package */
 
4302
__attribute__ (( section (".OpenFirmware") ))
 
4303
static void OF_open (OF_env_t *OF_env)
 
4304
{
 
4305
    const unsigned char *args;
 
4306
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4307
    OF_node_t *node;
 
4308
    OF_inst_t *inst;
 
4309
    uint32_t ihandle;
 
4310
 
 
4311
    OF_CHECK_NBARGS(OF_env, 1);
 
4312
    namep = (unsigned char *)popd(OF_env);
 
4313
    OF_lds(name, namep);
 
4314
    OF_DPRINTF("package [%s]\n", name);
 
4315
    args = OF_get_args(OF_env, name);
 
4316
    node = OF_get_alias(OF_env, name);
 
4317
    if (node == NULL) {
 
4318
        node = OF_pack_find_by_name(OF_env, OF_node_root, name);
 
4319
    }
 
4320
    if (node == NULL) {
 
4321
        OF_DPRINTF("package not found !\n");
 
4322
        pushd(OF_env, -1);
 
4323
        return;
 
4324
    }
 
4325
    inst = OF_instance_new(OF_env, node);
 
4326
    if (inst == NULL) {
 
4327
        pushd(OF_env, -1);
 
4328
        ERROR("Cannot create package instance\n");
 
4329
        return;
 
4330
    }
 
4331
    ihandle = OF_instance_get_id(OF_env, inst);
 
4332
    /* If an "open" method exists in the package, call it */
 
4333
    OF_DPRINTF("package [%s] => %0x\n", name, ihandle);
 
4334
    OF_node_put(OF_env, node);
 
4335
    _OF_callmethod(OF_env, "open", ihandle, args);
 
4336
}
 
4337
 
 
4338
/* De-instanciate a package */
 
4339
__attribute__ (( section (".OpenFirmware") ))
 
4340
static void OF_close (OF_env_t *OF_env)
 
4341
{
 
4342
    uint32_t ihandle;
 
4343
 
 
4344
    OF_CHECK_NBARGS(OF_env, 1);
 
4345
    ihandle = popd(OF_env);
 
4346
    /* If an "close" method exists in the package, call it */
 
4347
    _OF_callmethod(OF_env, "close", ihandle, NULL);
 
4348
    /* XXX: Should free the instance */
 
4349
}
 
4350
 
 
4351
/* "read" */
 
4352
__attribute__ (( section (".OpenFirmware") ))
 
4353
static void OF_read (OF_env_t *OF_env)
 
4354
{
 
4355
    uint32_t ihandle;
 
4356
 
 
4357
    OF_CHECK_NBARGS(OF_env, 3);
 
4358
    ihandle = popd(OF_env);
 
4359
    OF_DPRINTF("ih: %0x\n", ihandle);
 
4360
    /* If a "read" method exists in the package, call it */
 
4361
    _OF_callmethod(OF_env, "read", ihandle, NULL);
 
4362
}
 
4363
 
 
4364
/* Try call the "read" method of a device's package */
 
4365
/* "write" */
 
4366
__attribute__ (( section (".OpenFirmware") ))
 
4367
static void OF_write (OF_env_t *OF_env)
 
4368
{
 
4369
    uint32_t ihandle;
 
4370
 
 
4371
    OF_CHECK_NBARGS(OF_env, 3);
 
4372
    ihandle = popd(OF_env);
 
4373
    //    OF_DPRINTF("ih: %0x\n", ihandle);
 
4374
    /* If a "write" method exists in the package, call it */
 
4375
    _OF_callmethod(OF_env, "write", ihandle, NULL);
 
4376
}
 
4377
 
 
4378
/* "seek" */
 
4379
__attribute__ (( section (".OpenFirmware") ))
 
4380
static void OF_seek (OF_env_t *OF_env)
 
4381
{
 
4382
    uint32_t ihandle;
 
4383
 
 
4384
    OF_CHECK_NBARGS(OF_env, 3);
 
4385
    ihandle = popd(OF_env);
 
4386
    OF_DPRINTF("ih: %0x\n", ihandle);
 
4387
    /* If a "seek" method exists in the package, call it */
 
4388
    _OF_callmethod(OF_env, "seek", ihandle, NULL);
 
4389
}
 
4390
 
 
4391
/* Memory services */
 
4392
/* Claim some memory space */
 
4393
__attribute__ (( section (".OpenFirmware") ))
 
4394
uint32_t OF_claim_virt (uint32_t virt, uint32_t size, int *range)
 
4395
{
 
4396
    int i, keep = -1;
 
4397
 
 
4398
    OF_DPRINTF("Claim %d bytes at 0x%0x\n", size, virt);
 
4399
    /* First check that the requested memory stands in the physical memory */
 
4400
    if (OF_mem_ranges[0].start > virt ||
 
4401
        (OF_mem_ranges[0].start + OF_mem_ranges[0].size) < (virt + size)) {
 
4402
        ERROR("not in memory: start 0x%0x virt 0x%0x end 0x%0x 0x%0x\n",
 
4403
              OF_mem_ranges[0].start, virt,
 
4404
              OF_mem_ranges[0].start + OF_mem_ranges[0].size,
 
4405
              virt + size);
 
4406
        return (uint32_t)(-1);
 
4407
    }
 
4408
    /* Now check that it doesn't overlap with already claimed areas */
 
4409
    for (i = 1; i < OF_MAX_MEMRANGES + 1; i++) {
 
4410
        if (OF_mem_ranges[i].start == (uint32_t)(-1) ||
 
4411
            OF_mem_ranges[i].size == (uint32_t)(-1)) {
 
4412
            if (keep == -1)
 
4413
                keep = i;
 
4414
            continue;
 
4415
        }
 
4416
        if (OF_mem_ranges[i].start == virt &&
 
4417
            (OF_mem_ranges[i].start + OF_mem_ranges[i].size) == (virt + size)) {
 
4418
            return virt;
 
4419
        }
 
4420
        if (!((OF_mem_ranges[i].start >= (virt + size) ||
 
4421
               (OF_mem_ranges[i].start + OF_mem_ranges[i].size) <= virt))) {
 
4422
            ERROR("overlap: start 0x%0x virt 0x%0x end 0x%0x 0x%0x\n",
 
4423
                  OF_mem_ranges[i].start, virt,
 
4424
                  OF_mem_ranges[i].start + OF_mem_ranges[i].size,
 
4425
                  virt + size);
 
4426
            /* Aie... */
 
4427
            return (uint32_t)(-1);
 
4428
        }
 
4429
    }
 
4430
    OF_DPRINTF("return range: %d\n", keep);
 
4431
    if (keep == -1) {
 
4432
        /* no more rooms */
 
4433
        ERROR("No more rooms\n");
 
4434
        return (uint32_t)(-1);
 
4435
    } else {
 
4436
        ERROR("Give range: start 0x%0x 0x%0x\n", virt, size);
 
4437
    }
 
4438
    if (range != NULL)
 
4439
        *range = keep;
 
4440
 
 
4441
    return virt;
 
4442
}
 
4443
 
 
4444
/* We always try to get the upper address we can */
 
4445
__attribute__ (( section (".OpenFirmware") ))
 
4446
static uint32_t OF_claim_size (uint32_t size, int align, int *range)
 
4447
{
 
4448
    uint32_t addr, max = (uint32_t)(-1);
 
4449
    int i;
 
4450
    
 
4451
    OF_DPRINTF("Try map %d bytes at 0x00000000\n", size);
 
4452
    if (OF_claim_virt(0, size, range) != (uint32_t)(-1))
 
4453
        max = 0;
 
4454
    for (i = 1; i < OF_MAX_MEMRANGES + 1; i++) {
 
4455
        if (OF_mem_ranges[i].start == (uint32_t)(-1) ||
 
4456
            OF_mem_ranges[i].size == (uint32_t)(-1))
 
4457
            continue;
 
4458
        addr = (OF_mem_ranges[i].start + OF_mem_ranges[i].size + align - 1) &
 
4459
            ~(align - 1);
 
4460
        OF_DPRINTF("Try map %d bytes at 0x%0x\n", size, addr);
 
4461
        if ((addr + 1) > (max + 1)) {
 
4462
            if (OF_claim_virt(addr, size, range) != (uint32_t)(-1))
 
4463
                max = addr;
 
4464
        }
 
4465
    }
 
4466
 
 
4467
    return max;
 
4468
}
 
4469
 
 
4470
__attribute__ (( section (".OpenFirmware") ))
 
4471
static void OF_claim (OF_env_t *OF_env)
 
4472
{
 
4473
    uint32_t virt, size, addr;
 
4474
    int align;
 
4475
    int i, range;
 
4476
 
 
4477
    OF_CHECK_NBARGS(OF_env, 3);
 
4478
    virt = popd(OF_env);
 
4479
    size = popd(OF_env);
 
4480
    align = popd(OF_env);
 
4481
    DPRINTF("virt 0x%0x size 0x%0x align %d\n", virt, size, align);
 
4482
    if (align == 0) {
 
4483
        addr = OF_claim_virt(virt, size, &range);
 
4484
    } else {
 
4485
        for (i = 1; i < align; i = i << 1)
 
4486
            continue;
 
4487
        align = i;
 
4488
        size = (size + align - 1) & ~(align - 1);
 
4489
        addr = OF_claim_size(size, align, &range);
 
4490
    }
 
4491
    if (addr == (uint32_t)-1) {
 
4492
        ERROR("No range match !\n");
 
4493
        pushd(OF_env, -1);
 
4494
    }
 
4495
    if (range != -1) {
 
4496
        OF_mem_ranges[range].start = addr;
 
4497
        OF_mem_ranges[range].size = size;
 
4498
    }
 
4499
    OF_DPRINTF("Give address 0x%0x\n", addr);
 
4500
    pushd(OF_env, addr);
 
4501
}
 
4502
 
 
4503
/* release some previously claimed memory */
 
4504
__attribute__ (( section (".OpenFirmware") ))
 
4505
static void OF_release (OF_env_t *OF_env)
 
4506
{
 
4507
    uint32_t virt, size;
 
4508
    int i;
 
4509
 
 
4510
    OF_CHECK_NBARGS(OF_env, 2);
 
4511
    virt = popd(OF_env);
 
4512
    size = popd(OF_env);
 
4513
    OF_DPRINTF("virt 0x%0x size 0x%0x\n", virt, size);
 
4514
    for (i = 0; i < OF_MAX_MEMRANGES; i++) {
 
4515
        if (OF_mem_ranges[i].start == virt && OF_mem_ranges[i].size == size) {
 
4516
            OF_mem_ranges[i].start = (uint32_t)(-1);
 
4517
            OF_mem_ranges[i].size = (uint32_t)(-1);
 
4518
            break;
 
4519
        }
 
4520
    }
 
4521
}
 
4522
 
 
4523
/* Control transfer services */
 
4524
/* "boot" */
 
4525
 
 
4526
/* Enter Open-Firmware interpreter */
 
4527
__attribute__ (( section (".OpenFirmware") ))
 
4528
static void OF_enter (OF_env_t *OF_env)
 
4529
{
 
4530
    int n_args;
 
4531
 
 
4532
    n_args = stackd_depth(OF_env);
 
4533
    /* means that the bootloader has ended.
 
4534
     * So qemu will...
 
4535
     */
 
4536
    OF_DPRINTF("%d \n", n_args);
 
4537
    //    printf("Bootloader has quitted...\n");
 
4538
    //    abort();
 
4539
}
 
4540
 
 
4541
/* Exit client program */
 
4542
__attribute__ (( section (".OpenFirmware") ))
 
4543
static void OF_exit (OF_env_t *OF_env)
 
4544
{
 
4545
    int n_args;
 
4546
 
 
4547
    n_args = stackd_depth(OF_env);
 
4548
    /* means that the bootloader has ended.
 
4549
     * So qemu will...
 
4550
     */
 
4551
    OF_DPRINTF("%d \n", n_args);
 
4552
    //    printf("Bootloader has quitted...\n");
 
4553
    //    abort();
 
4554
}
 
4555
 
 
4556
/* "chain" */
 
4557
 
 
4558
/* User interface services */
 
4559
/* "interpret" */
 
4560
 
 
4561
__attribute__ (( section (".OpenFirmware") ))
 
4562
static void OF_interpret (OF_env_t *OF_env)
 
4563
{
 
4564
    const unsigned char *FString;
 
4565
    void *buf;
 
4566
    OF_inst_t *inst;
 
4567
    OF_node_t *pks, *slw, *chs, *disp;
 
4568
    uint32_t ihandle, crc;
 
4569
 
 
4570
    OF_DPRINTF("\n");
 
4571
    //    OF_CHECK_NBARGS(OF_env, 1);
 
4572
    FString = (const void *)popd(OF_env);
 
4573
    crc = crc32(0, FString, strlen(FString));
 
4574
    OF_DPRINTF("\n\nOF INTERPRETER CALL:\n [%s]\n crc=%0x\n", FString, crc);
 
4575
    /* Do some hacks to make BootX happy */
 
4576
    switch (crc) {
 
4577
    case 0x225b6748: /* MacOS X 10.2 and OpenDarwin 1.41 */
 
4578
    case 0xb1cd4d25: /* OpenDarwin 6.02 */
 
4579
        /* Create "sl_words" package */
 
4580
        popd(OF_env);
 
4581
        /* Find "/packages" */
 
4582
        pks = OF_pack_find_by_name(OF_env, OF_node_root, "/packages");
 
4583
        if (pks == NULL) {
 
4584
            OF_node_put(OF_env, pks);
 
4585
            pushd(OF_env, -1);
 
4586
            ERROR("Cannot get '/packages'\n");
 
4587
            break;
 
4588
        }
 
4589
        slw = OF_node_new(OF_env, pks, "sl_words", OF_ADDRESS_NONE);
 
4590
        if (slw == NULL) {
 
4591
            OF_node_put(OF_env, pks);
 
4592
            pushd(OF_env, -1);
 
4593
            ERROR("Cannot create 'sl_words'\n");
 
4594
            break;
 
4595
        }
 
4596
        /* Create methods */
 
4597
        OF_method_new(OF_env, slw, "slw_set_output_level",
 
4598
                      &slw_set_output_level);
 
4599
        OF_method_new(OF_env, slw, "slw_emit", &slw_emit);
 
4600
        OF_method_new(OF_env, slw, "slw_cr", &slw_cr);
 
4601
        OF_method_new(OF_env, slw, "slw_init_keymap", &slw_init_keymap);
 
4602
        OF_method_new(OF_env, slw, "slw_update_keymap", &slw_update_keymap);
 
4603
        OF_method_new(OF_env, slw, "slw_spin", &slw_spin);
 
4604
        OF_method_new(OF_env, slw, "slw_spin_init", &slw_spin_init);
 
4605
        OF_method_new(OF_env, slw, "slw_pwd", &slw_pwd);
 
4606
        OF_method_new(OF_env, slw, "slw_sum", &slw_sum);
 
4607
        /* Init properties */
 
4608
        OF_prop_int_new(OF_env, slw, "outputLevel", 0);
 
4609
        OF_prop_int_new(OF_env, slw, "keyboardIH", 0);
 
4610
        {
 
4611
#if 0
 
4612
            OF_node_t *kbd;
 
4613
            kbd = OF_pack_find_by_name(OF_env, OF_node_root, "/keyboard");
 
4614
            if (kbd == NULL) {
 
4615
                OF_node_put(OF_env, pks);
 
4616
                pushd(OF_env, -1);
 
4617
                ERROR("Cannot get '/keyboard'\n");
 
4618
                break;
 
4619
            }
 
4620
            buf = malloc(0x20);
 
4621
            if (buf == NULL) {
 
4622
                OF_node_put(OF_env, pks);
 
4623
                pushd(OF_env, -1);
 
4624
                ERROR("Cannot allocate keyboard buff\n");
 
4625
                break;
 
4626
            }
 
4627
#else
 
4628
            buf = malloc(0x20);
 
4629
            if (buf == NULL) {
 
4630
                OF_node_put(OF_env, pks);
 
4631
                pushd(OF_env, -1);
 
4632
                ERROR("Cannot allocate keyboard buff\n");
 
4633
                break;
 
4634
            }
 
4635
            memset(buf, 0, 0x20);
 
4636
            OF_property_new(OF_env, slw, "keyMap", buf, 0x20);
 
4637
#endif
 
4638
        }
 
4639
        OF_prop_int_new(OF_env, slw, "screenIH", 0);
 
4640
        OF_prop_int_new(OF_env, slw, "cursorAddr", 0);
 
4641
        OF_prop_int_new(OF_env, slw, "cursorX", 0);
 
4642
        OF_prop_int_new(OF_env, slw, "cursorY", 0);
 
4643
        OF_prop_int_new(OF_env, slw, "cursorW", 0);
 
4644
        OF_prop_int_new(OF_env, slw, "cursorH", 0);
 
4645
        OF_prop_int_new(OF_env, slw, "cursorFrames", 0);
 
4646
        OF_prop_int_new(OF_env, slw, "cursorPixelSize", 0);
 
4647
        OF_prop_int_new(OF_env, slw, "cursorStage", 0);
 
4648
        OF_prop_int_new(OF_env, slw, "cursorTime", 0);
 
4649
        OF_prop_int_new(OF_env, slw, "cursorDelay", 0);
 
4650
        /* Instanciate sl_words */
 
4651
        inst = OF_instance_new(OF_env, slw);
 
4652
        if (inst == NULL) {
 
4653
            OF_node_put(OF_env, pks);
 
4654
            pushd(OF_env, -1);
 
4655
            ERROR("Cannot create sl_words instance\n");
 
4656
            break;
 
4657
        }
 
4658
        ihandle = OF_instance_get_id(OF_env, inst);
 
4659
        /* Release packages */
 
4660
        OF_node_put(OF_env, slw);
 
4661
        OF_node_put(OF_env, pks);
 
4662
        OF_DPRINTF("sl_words instance: %0x\n", ihandle);
 
4663
        /* Set return value */
 
4664
        if (crc == 0xb1cd4d25) /* Hack for OpenDarwin 6.02 */
 
4665
            pushd(OF_env, ihandle);
 
4666
        pushd(OF_env, ihandle);
 
4667
        pushd(OF_env, 0);
 
4668
        break;
 
4669
    case 0x233441d3: /* MacOS X 10.2 and OpenDarwin 1.41 */
 
4670
        /* Create "memory-map" pseudo device */
 
4671
        {
 
4672
            OF_node_t *map;
 
4673
            uint32_t phandle;
 
4674
 
 
4675
        /* Find "/packages" */
 
4676
        chs = OF_pack_find_by_name(OF_env, OF_node_root, "/chosen");
 
4677
        if (chs == NULL) {
 
4678
            pushd(OF_env, -1);
 
4679
            ERROR("Cannot get '/chosen'\n");
 
4680
            break;
 
4681
        }
 
4682
            map = OF_node_new(OF_env, chs, "memory-map", OF_ADDRESS_NONE);
 
4683
            if (map == NULL) {
 
4684
                pushd(OF_env, -1);
 
4685
                ERROR("Cannot create 'memory-map'\n");
 
4686
                break;
 
4687
            }
 
4688
            phandle = OF_pack_handle(OF_env, map);
 
4689
            OF_node_put(OF_env, map);
 
4690
            OF_node_put(OF_env, chs);
 
4691
            pushd(OF_env, phandle);
 
4692
        pushd(OF_env, 0);
 
4693
        }
 
4694
        break;
 
4695
    case 0x32a2d18e: /* MacOS X 10.2 and OpenDarwin 6.02 */
 
4696
        /* Return screen ihandle */
 
4697
        disp = OF_get_alias(OF_env, "screen");
 
4698
        if (disp == NULL) {
 
4699
            pushd(OF_env, 0);
 
4700
            pushd(OF_env, -1);
 
4701
            ERROR("Cannot get 'screen' alias\n");
 
4702
            break;
 
4703
        }
 
4704
        inst = OF_instance_new(OF_env, disp);
 
4705
        if (inst == NULL) {
 
4706
            OF_node_put(OF_env, disp);
 
4707
            pushd(OF_env, 0);
 
4708
            pushd(OF_env, -1);
 
4709
            ERROR("Cannot create 'screen' instance\n");
 
4710
            break;
 
4711
        }
 
4712
        ihandle = OF_instance_get_id(OF_env, inst);
 
4713
        OF_node_put(OF_env, disp);
 
4714
        OF_DPRINTF("Return screen ihandle: %0x\n", ihandle);
 
4715
        pushd(OF_env, ihandle);
 
4716
        pushd(OF_env, 0);
 
4717
        break;
 
4718
    case 0xF3A9841F: /* MacOS X 10.2 */
 
4719
    case 0x76fbdf18: /* OpenDarwin 6.02 */
 
4720
        /* Set current display as active package */
 
4721
        disp = OF_get_alias (OF_env, "screen");
 
4722
        if (disp == NULL) {
 
4723
            pushd(OF_env, 0);
 
4724
            pushd(OF_env, -1);
 
4725
        }
 
4726
        OF_node_put(OF_env, disp);
 
4727
        break;
 
4728
    case 0x1c3bc93f: /* MacOS X 10.3 */
 
4729
        /* get-package-property if 0 0 then */
 
4730
        OF_getprop(OF_env);
 
4731
        {
 
4732
            uint32_t len;
 
4733
            len = popd(OF_env);
 
4734
            if (len == (uint32_t)-1)
 
4735
                len = 0;
 
4736
            pushd(OF_env, len);
 
4737
        }
 
4738
        break;
 
4739
    case 0x218d5ccb: /* yaboot */
 
4740
    case 0x27b32255:
 
4741
    case 0x05d332ef:
 
4742
    case 0xc7b5d3b5:
 
4743
        /* skip it */
 
4744
        break;
 
4745
    case 0xf541a878:
 
4746
    case 0x6a9b2be6:
 
4747
        /* Yaboot: set background color to black */
 
4748
        break;
 
4749
    case 0x846077fb:
 
4750
    case 0x299c2c5d: /* gentoo */
 
4751
        /* Yaboot: set foreground color to grey */
 
4752
        break;
 
4753
    case 0x4ad41f2d:
 
4754
        /* Yaboot: wait 10 ms: sure ! */
 
4755
        break;
 
4756
 
 
4757
    default:
 
4758
        /* ERROR */
 
4759
        printf("Script: len=%d\n%s\n", (int)strlen(FString), FString);
 
4760
        printf("Call %0x NOT IMPLEMENTED !\n", crc);
 
4761
        bug();
 
4762
        break;
 
4763
    }
 
4764
    OF_DPRINTF("\n\nOF INTERPRETER CALL DONE\n\n");
 
4765
}
 
4766
 
 
4767
/* "set-callback" */
 
4768
/* "set-symbol-lookup" */
 
4769
 
 
4770
/* Time services */
 
4771
/* "milliseconds" */
 
4772
__attribute__ (( section (".OpenFirmware") ))
 
4773
static void OF_milliseconds (OF_env_t *OF_env)
 
4774
{
 
4775
#if 0
 
4776
    struct timeval tv;
 
4777
 
 
4778
    OF_DPRINTF("\n");
 
4779
    OF_CHECK_NBARGS(OF_env, 0);
 
4780
    gettimeofday(&tv, NULL);
 
4781
    pushd(OF_env, (tv.tv_sec * 1000) + (tv.tv_usec / 1000));
 
4782
#else
 
4783
    static uint32_t ms = 0;
 
4784
 
 
4785
    OF_CHECK_NBARGS(OF_env, 0);
 
4786
    pushd(OF_env, ms);
 
4787
    usleep(10000); /* XXX: TOFIX: Random sleep */
 
4788
    ms += 10;
 
4789
#endif
 
4790
}
 
4791
 
 
4792
/* Undocumented in IEEE 1275 */
 
4793
__attribute__ (( section (".OpenFirmware") ))
 
4794
static void OF_quiesce (OF_env_t *OF_env)
 
4795
{
 
4796
    OF_CHECK_NBARGS(OF_env, 0);
 
4797
    /* Should free all OF resources */
 
4798
    bd_reset_all();
 
4799
#if defined (DEBUG_BIOS)
 
4800
    {
 
4801
        uint16_t loglevel = 0x02 | 0x10 | 0x80;
 
4802
        //        outw(0xFF02, loglevel);
 
4803
        outb(0x0F02, loglevel);
 
4804
    }
 
4805
#endif
 
4806
}
 
4807
 
 
4808
typedef struct OF_service_t OF_service_t;
 
4809
struct OF_service_t {
 
4810
    const unsigned char *name;
 
4811
    OF_cb_t cb;
 
4812
};
 
4813
 
 
4814
static OF_service_t services[] = {
 
4815
    { "test",                &OF_test,                },
 
4816
    { "peer",                &OF_peer,                },
 
4817
    { "child",               &OF_child,               },
 
4818
    { "parent",              &OF_parent,              },
 
4819
    { "instance-to-package", &OF_instance_to_package, },
 
4820
    { "getproplen",          &OF_getproplen,          },
 
4821
    { "getprop",             &OF_getprop,             },
 
4822
    { "nextprop",            &OF_nextprop,            },
 
4823
    { "setprop",             &OF_setprop,             },
 
4824
    { "finddevice",          &OF_finddevice,          },
 
4825
    { "instance-to-path",    &OF_instance_to_path,    },
 
4826
    { "package-to-path",     &OF_package_to_path,     },
 
4827
    { "call-method",         &OF_callmethod,          },
 
4828
    { "open",                &OF_open,                },
 
4829
    { "open-package",        &OF_open,                },
 
4830
    { "close",               &OF_close,               },
 
4831
    { "read",                &OF_read,                },
 
4832
    { "write",               &OF_write,               },
 
4833
    { "seek",                &OF_seek,                },
 
4834
    { "claim",               &OF_claim,               },
 
4835
    { "release",             &OF_release,             },
 
4836
    { "enter",               &OF_enter,               },
 
4837
    { "exit",                &OF_exit,                },
 
4838
    { "interpret",           &OF_interpret,           },
 
4839
    { "milliseconds",        &OF_milliseconds,        },
 
4840
    { "quiesce",             &OF_quiesce,             },
 
4841
};
 
4842
 
 
4843
/* Probe if a named service exists */
 
4844
__attribute__ (( section (".OpenFirmware") ))
 
4845
static void OF_test (OF_env_t *OF_env)
 
4846
{
 
4847
    unsigned char name[OF_NAMELEN_MAX], *namep;
 
4848
    uint32_t i;
 
4849
    int ret = -1;
 
4850
 
 
4851
    OF_CHECK_NBARGS(OF_env, 1);
 
4852
    namep = (unsigned char *)popd(OF_env);
 
4853
    OF_lds(name, namep);
 
4854
    OF_DPRINTF("service [%s]\n", name);
 
4855
    for (i = 0; i < (sizeof(services) / sizeof(OF_service_t)); i++) {
 
4856
        if (strcmp(services[i].name, name) == 0) {
 
4857
            ret = 0;
 
4858
            break;
 
4859
        }
 
4860
    }
 
4861
    pushd(OF_env, ret);
 
4862
}
 
4863
 
 
4864
/* Main entry point for PPC clients */
 
4865
__attribute__ (( section (".OpenFirmware") ))
 
4866
int OF_client_entry (void *p)
 
4867
{
 
4868
    unsigned char buffer[OF_NAMELEN_MAX];
 
4869
    OF_env_t OF_env;
 
4870
    OF_cb_t cb;
 
4871
    unsigned char *namep;
 
4872
    uint32_t i;
 
4873
 
 
4874
    /* set our environment */
 
4875
    MMU_off();
 
4876
    OF_DPRINTF("Called with arg: %p\n", p);
 
4877
    /* Load function name string */
 
4878
    namep = (unsigned char *)(*(uint32_t *)p);
 
4879
    OF_lds(buffer, namep);
 
4880
    /* Find callback */
 
4881
    cb = NULL;
 
4882
    OF_DPRINTF("Look for service [%s]\n", buffer);
 
4883
    for (i = 0; i < (sizeof(services) / sizeof(OF_service_t)); i++) {
 
4884
        if (strcmp(services[i].name, buffer) == 0) {
 
4885
            cb = services[i].cb;
 
4886
            break;
 
4887
        }
 
4888
    }
 
4889
    if (cb == NULL) {
 
4890
        OF_DPRINTF("service [%s] not implemented\n", buffer);
 
4891
        //        bug();
 
4892
        return -1;
 
4893
    }
 
4894
#if 0
 
4895
    OF_DPRINTF("Service [%s] found\n", buffer);
 
4896
#endif
 
4897
    /* Set up stack *NON REENTRANT* */
 
4898
    OF_env_init(&OF_env);
 
4899
    /* Launch Forth glue */
 
4900
    C_to_Forth(&OF_env, (uint32_t *)p + 1, &cb);
 
4901
    OF_DPRINTF("done\n");
 
4902
    MMU_on();
 
4903
 
 
4904
    return 0;
 
4905
}
 
4906
 
 
4907
/*****************************************************************************/
 
4908
/* Run-time abstraction services */
 
4909
/* RTAS RAM is organised this way:
 
4910
 * RTAS_memory is given by the OS when instanciating RTAS.
 
4911
 * it's an 32 kB area divided in 2 zones:
 
4912
 * Up is a stack, used to call RTAS services
 
4913
 * Down is the variables area.
 
4914
 */
 
4915
 
 
4916
__attribute__ (( section (".RTAS_vars") ))
 
4917
static OF_cb_t *RTAS_callbacks[32];
 
4918
#if 0
 
4919
__attribute__ (( section (".RTAS_vars") ))
 
4920
static uint8_t *RTAS_base;
 
4921
#endif
 
4922
 
 
4923
/* RTAS is called in real mode (ie no MMU), privileged with all exceptions
 
4924
 * disabled. It has to preserve all registers except R3 to R12.
 
4925
 * The OS should ensure it's not re-entered.
 
4926
 */
 
4927
__attribute__ (( section (".RTAS") ))
 
4928
int RTAS_entry (void *p)
 
4929
{
 
4930
    OF_env_t RTAS_env;
 
4931
    uint32_t token;
 
4932
 
 
4933
    OF_DPRINTF("Called with arg: %p\n", p);
 
4934
    /* set our environment */
 
4935
    token = *(uint32_t *)p;
 
4936
    /* Set up stack */
 
4937
    RTAS_env.stackb = (uint32_t *)(RTAS_memory + 0x8000 - 4);
 
4938
    RTAS_env.stackp = RTAS_env.stackb;
 
4939
    RTAS_env.funcb = (uint32_t *)(RTAS_memory + 0x8000 - OF_STACK_SIZE - 4);
 
4940
    RTAS_env.funcp = RTAS_env.funcb;
 
4941
    /* Call Forth glue */
 
4942
    C_to_Forth(&RTAS_env, (uint32_t *)p + 1, RTAS_callbacks[token & 0x3F]);
 
4943
    OF_DPRINTF("done\n");
 
4944
 
 
4945
    return 0;
 
4946
}
 
4947
 
 
4948
__attribute__ (( section (".RTAS") ))
 
4949
static void RTAS_restart_rtas (OF_env_t *RTAS_env)
 
4950
{
 
4951
    OF_DPRINTF("\n");
 
4952
    OF_CHECK_NBARGS(RTAS_env, 0);
 
4953
    /* No implementation: return error */
 
4954
    pushd(RTAS_env, -1);
 
4955
}
 
4956
 
 
4957
__attribute__ (( section (".RTAS") ))
 
4958
static void RTAS_nvram_fetch (OF_env_t *RTAS_env)
 
4959
{
 
4960
    uint8_t *buffer;
 
4961
    int offset, length;
 
4962
    int i;
 
4963
 
 
4964
    OF_DPRINTF("\n");
 
4965
    OF_CHECK_NBARGS(RTAS_env, 3);
 
4966
    offset = popd(RTAS_env);
 
4967
    buffer = (uint8_t *)popd(RTAS_env);
 
4968
    length = popd(RTAS_env);
 
4969
    for (i = 0; i < length; i++) {
 
4970
        if ((i + offset) >= NVRAM_get_size(nvram)) {
 
4971
            pushd(RTAS_env, -3);
 
4972
            return;
 
4973
        }
 
4974
        *buffer++ = NVRAM_read(nvram, i + offset);
 
4975
    }
 
4976
    pushd(RTAS_env, length);
 
4977
}
 
4978
 
 
4979
__attribute__ (( section (".RTAS") ))
 
4980
static void RTAS_nvram_store (OF_env_t *RTAS_env)
 
4981
{
 
4982
    uint8_t *buffer;
 
4983
    int offset, length;
 
4984
    int i;
 
4985
 
 
4986
    OF_DPRINTF("\n");
 
4987
    OF_CHECK_NBARGS(RTAS_env, 3);
 
4988
    offset = popd(RTAS_env);
 
4989
    buffer = (uint8_t *)popd(RTAS_env);
 
4990
    length = popd(RTAS_env);
 
4991
    for (i = 0; i < length; i++) {
 
4992
        if ((i + offset) >= NVRAM_get_size(nvram)) {
 
4993
            pushd(RTAS_env, -3);
 
4994
            return;
 
4995
        }
 
4996
        NVRAM_write(nvram, i + offset, *buffer++);
 
4997
    }
 
4998
    pushd(RTAS_env, length);
 
4999
}
 
5000
 
 
5001
__attribute__ (( section (".RTAS") ))
 
5002
static void RTAS_get_time_of_day (OF_env_t *RTAS_env)
 
5003
{
 
5004
#if 0
 
5005
    struct tm tm;
 
5006
    time_t t;
 
5007
 
 
5008
    OF_DPRINTF("\n");
 
5009
    OF_CHECK_NBARGS(RTAS_env, 0);
 
5010
    t = get_time();
 
5011
    localtime_r(&t, &tm);
 
5012
    pushd(RTAS_env, 0); /* nanoseconds */
 
5013
    pushd(RTAS_env, tm.tm_sec);
 
5014
    pushd(RTAS_env, tm.tm_min);
 
5015
    pushd(RTAS_env, tm.tm_hour);
 
5016
    pushd(RTAS_env, tm.tm_mday);
 
5017
    pushd(RTAS_env, tm.tm_mon);
 
5018
    pushd(RTAS_env, tm.tm_year);
 
5019
    pushd(RTAS_env, 0); /* status */
 
5020
#else
 
5021
    pushd(RTAS_env, 0);
 
5022
    pushd(RTAS_env, 0);
 
5023
    pushd(RTAS_env, 0);
 
5024
    pushd(RTAS_env, 0);
 
5025
    pushd(RTAS_env, 0);
 
5026
    pushd(RTAS_env, 0);
 
5027
    pushd(RTAS_env, 0);
 
5028
    pushd(RTAS_env, 0);
 
5029
#endif
 
5030
}
 
5031
 
 
5032
__attribute__ (( section (".RTAS") ))
 
5033
static void RTAS_set_time_of_day (OF_env_t *RTAS_env)
 
5034
{
 
5035
#if 0
 
5036
    struct tm tm;
 
5037
    time_t t;
 
5038
 
 
5039
    OF_DPRINTF("\n");
 
5040
    OF_CHECK_NBARGS(RTAS_env, 7);
 
5041
    tm.tm_year = popd(RTAS_env);
 
5042
    tm.tm_mon = popd(RTAS_env);
 
5043
    tm.tm_mday = popd(RTAS_env);
 
5044
    tm.tm_hour = popd(RTAS_env);
 
5045
    tm.tm_min = popd(RTAS_env);
 
5046
    tm.tm_sec = popd(RTAS_env);
 
5047
    popd(RTAS_env); /* nanoseconds */
 
5048
    t = mktime(&tm);
 
5049
    set_time_offset(t);
 
5050
#endif
 
5051
    pushd(RTAS_env, 0); /* status */
 
5052
}
 
5053
 
 
5054
__attribute__ (( section (".RTAS") ))
 
5055
static void RTAS_set_time_for_power_on (OF_env_t *RTAS_env)
 
5056
{
 
5057
    OF_DPRINTF("\n");
 
5058
    OF_CHECK_NBARGS(RTAS_env, 7);
 
5059
    /* Do nothing */
 
5060
    pushd(RTAS_env, 0); /* status */
 
5061
}
 
5062
 
 
5063
__attribute__ (( section (".RTAS") ))
 
5064
static void RTAS_event_scan (OF_env_t *RTAS_env)
 
5065
{
 
5066
    OF_DPRINTF("\n");
 
5067
    OF_CHECK_NBARGS(RTAS_env, 4);
 
5068
    /* Pretend there are no new events */
 
5069
    pushd(RTAS_env, 1);
 
5070
}
 
5071
 
 
5072
__attribute__ (( section (".RTAS") ))
 
5073
static void RTAS_check_exception (OF_env_t *RTAS_env)
 
5074
{
 
5075
    OF_DPRINTF("\n");
 
5076
    OF_CHECK_NBARGS(RTAS_env, 6);
 
5077
    /* Pretend we found no exceptions */
 
5078
    pushd(RTAS_env, 1);
 
5079
}
 
5080
 
 
5081
__attribute__ (( section (".RTAS") ))
 
5082
static void RTAS_read_pci_config (OF_env_t *RTAS_env)
 
5083
{
 
5084
    OF_DPRINTF("\n");
 
5085
    OF_CHECK_NBARGS(RTAS_env, 2);
 
5086
    /* Hardware error */
 
5087
    pushd(RTAS_env, -1);
 
5088
}
 
5089
 
 
5090
__attribute__ (( section (".RTAS") ))
 
5091
static void RTAS_write_pci_config (OF_env_t *RTAS_env)
 
5092
{
 
5093
    OF_DPRINTF("\n");
 
5094
    OF_CHECK_NBARGS(RTAS_env, 3);
 
5095
    /* Hardware error */
 
5096
    pushd(RTAS_env, -1);
 
5097
}
 
5098
 
 
5099
__attribute__ (( section (".RTAS") ))
 
5100
static void RTAS_display_character (OF_env_t *RTAS_env)
 
5101
{
 
5102
    int c;
 
5103
 
 
5104
    OF_DPRINTF("\n");
 
5105
    OF_CHECK_NBARGS(RTAS_env, 1);
 
5106
    c = popd(RTAS_env);
 
5107
#if 0
 
5108
    printf("%c", c);
 
5109
#else
 
5110
    outb(0x0F00, c);
 
5111
#endif
 
5112
    pushd(RTAS_env, 0);
 
5113
}
 
5114
 
 
5115
__attribute__ (( section (".RTAS") ))
 
5116
static void RTAS_set_indicator (OF_env_t *RTAS_env)
 
5117
{
 
5118
    const unsigned char *name;
 
5119
    int indic, state;
 
5120
 
 
5121
    OF_DPRINTF("\n");
 
5122
    OF_CHECK_NBARGS(RTAS_env, 3);
 
5123
    indic = popd(RTAS_env);
 
5124
    state = popd(RTAS_env);
 
5125
    switch (indic) {
 
5126
    case 1:
 
5127
        name = "tone frequency";
 
5128
        break;
 
5129
    case 2:
 
5130
        name = "tone volume";
 
5131
        break;
 
5132
    case 3:
 
5133
        name = "system power state";
 
5134
        break;
 
5135
    case 4:
 
5136
        name = "warning light";
 
5137
        break;
 
5138
    case 5:
 
5139
        name = "disk activity light";
 
5140
        break;
 
5141
    case 6:
 
5142
        name = "hexadecimal display unit";
 
5143
        break;
 
5144
    case 7:
 
5145
        name = "batery warning time";
 
5146
        break;
 
5147
    case 8:
 
5148
        name = "condition cycle request";
 
5149
        break;
 
5150
    case 9000 ... 9999:
 
5151
        name = "vendor specific";
 
5152
        break;
 
5153
    default:
 
5154
        pushd(RTAS_env, -3);
 
5155
        return;
 
5156
    }        
 
5157
    OF_DPRINTF("Set indicator %d [%s] to %d\n", indic, name, state);
 
5158
    pushd(RTAS_env, 0);
 
5159
}
 
5160
 
 
5161
__attribute__ (( section (".RTAS") ))
 
5162
static void RTAS_get_sensor_state (OF_env_t *RTAS_env)
 
5163
{
 
5164
    const unsigned char *name;
 
5165
    int type, index;
 
5166
    int state;
 
5167
 
 
5168
    OF_DPRINTF("\n");
 
5169
    OF_CHECK_NBARGS(RTAS_env, 2);
 
5170
    type = popd(RTAS_env);
 
5171
    index = popd(RTAS_env);
 
5172
    switch (index) {
 
5173
    case 1:
 
5174
        name = "key switch";
 
5175
        state = 1; /* Normal */
 
5176
        break;
 
5177
    case 2:
 
5178
        name = "enclosure switch";
 
5179
        state = 0; /* Closed */
 
5180
        break;
 
5181
    case 3:
 
5182
        name = "thermal sensor";
 
5183
        state = 40; /* in degrees Celsius (not too hot !) */
 
5184
        break;
 
5185
    case 4:
 
5186
        name = "lid status";
 
5187
        state = 1; /* Open */
 
5188
        break;
 
5189
    case 5:
 
5190
        name = "power source";
 
5191
        state = 0; /* AC */
 
5192
        break;
 
5193
    case 6:
 
5194
        name = "battery voltage";
 
5195
        state = 6; /* Let's have a moderated answer :-) */
 
5196
        break;
 
5197
    case 7:
 
5198
        name = "battery capacity remaining";
 
5199
        state = 3; /* High */
 
5200
        break;
 
5201
    case 8:
 
5202
        name = "battery capacity percentage";
 
5203
        state = 1000; /* 100 % */
 
5204
        break;
 
5205
    case 9:
 
5206
        name = "EPOW sensor";
 
5207
        state = 5; /* ? */
 
5208
        break;
 
5209
    case 10:
 
5210
        name = "battery condition cycle state";
 
5211
        state = 0; /* none */
 
5212
        break;
 
5213
    case 11:
 
5214
        name = "battery charge state";
 
5215
        state = 2; /* No current flow */
 
5216
        break;
 
5217
    case 9000 ... 9999:
 
5218
        name = "vendor specific";
 
5219
        state = 0;
 
5220
        break;
 
5221
    default:
 
5222
        pushd(RTAS_env, -3);
 
5223
        return;
 
5224
    }        
 
5225
    OF_DPRINTF("Pretend sensor %d [%s] is in state %d\n", index, name, state);
 
5226
    pushd(RTAS_env, state);
 
5227
    pushd(RTAS_env, 0);
 
5228
}
 
5229
 
 
5230
#if 0 // No power management */
 
5231
__attribute__ (( section (".RTAS") ))
 
5232
static void RTAS_set_power_level (OF_env_t *RTAS_env)
 
5233
{
 
5234
    OF_DPRINTF("\n");
 
5235
}
 
5236
 
 
5237
__attribute__ (( section (".RTAS") ))
 
5238
static void RTAS_get_power_level (OF_env_t *RTAS_env)
 
5239
{
 
5240
    OF_DPRINTF("\n");
 
5241
}
 
5242
 
 
5243
__attribute__ (( section (".RTAS") ))
 
5244
static void RTAS_assume_power_management (OF_env_t *RTAS_env)
 
5245
{
 
5246
    OF_DPRINTF("\n");
 
5247
}
 
5248
 
 
5249
__attribute__ (( section (".RTAS") ))
 
5250
static void RTAS_relinquish_power_management (OF_env_t *RTAS_env)
 
5251
{
 
5252
    OF_DPRINTF("\n");
 
5253
}
 
5254
#endif
 
5255
 
 
5256
__attribute__ (( section (".RTAS") ))
 
5257
static void RTAS_power_off (OF_env_t *RTAS_env)
 
5258
{
 
5259
    printf("RTAS was asked to switch off\n");
 
5260
    OF_CHECK_NBARGS(RTAS_env, 2);
 
5261
    //    abort();
 
5262
}
 
5263
 
 
5264
__attribute__ (( section (".RTAS") ))
 
5265
static void RTAS_suspend (OF_env_t *RTAS_env)
 
5266
{
 
5267
    OF_DPRINTF("\n");
 
5268
    OF_CHECK_NBARGS(RTAS_env, 3);
 
5269
    /* Pretend we don't succeed */
 
5270
    pushd(RTAS_env, -1);
 
5271
}
 
5272
 
 
5273
__attribute__ (( section (".RTAS") ))
 
5274
static void RTAS_hibernate (OF_env_t *RTAS_env)
 
5275
{
 
5276
    OF_DPRINTF("\n");
 
5277
    OF_CHECK_NBARGS(RTAS_env, 3);
 
5278
    /* Pretend we don't succeed */
 
5279
    pushd(RTAS_env, -1);
 
5280
}
 
5281
 
 
5282
__attribute__ (( section (".RTAS") ))
 
5283
static void RTAS_system_reboot (OF_env_t *RTAS_env)
 
5284
{
 
5285
    printf("RTAS was asked to reboot\n");
 
5286
    OF_CHECK_NBARGS(RTAS_env, 0);
 
5287
    //    abort();
 
5288
}
 
5289
 
 
5290
#if 0 // No power management nor SMP */
 
5291
__attribute__ (( section (".RTAS") ))
 
5292
static void RTAS_cache_control (OF_env_t *RTAS_env)
 
5293
{
 
5294
    OF_DPRINTF("\n");
 
5295
}
 
5296
 
 
5297
__attribute__ (( section (".RTAS") ))
 
5298
static void RTAS_freeze_time_base (OF_env_t *RTAS_env)
 
5299
{
 
5300
    OF_DPRINTF("\n");
 
5301
}
 
5302
 
 
5303
__attribute__ (( section (".RTAS") ))
 
5304
static void RTAS_thaw_time_base (OF_env_t *RTAS_env)
 
5305
{
 
5306
    OF_DPRINTF("\n");
 
5307
}
 
5308
 
 
5309
__attribute__ (( section (".RTAS") ))
 
5310
static void RTAS_stop_self (OF_env_t *RTAS_env)
 
5311
{
 
5312
    OF_DPRINTF("\n");
 
5313
}
 
5314
 
 
5315
__attribute__ (( section (".RTAS") ))
 
5316
static void RTAS_start_cpu (OF_env_t *RTAS_env)
 
5317
{
 
5318
    OF_DPRINTF("\n");
 
5319
}
 
5320
#endif
 
5321
 
 
5322
__attribute__ (( section (".RTAS") ))
 
5323
static void RTAS_instantiate (OF_env_t *RTAS_env)
 
5324
{
 
5325
    const unsigned char *args;
 
5326
    uint32_t ihandle;
 
5327
    uint32_t base_address;
 
5328
 
 
5329
    OF_DPRINTF("\n");
 
5330
    OF_CHECK_NBARGS(RTAS_env, 3);
 
5331
    ihandle = popd(RTAS_env);
 
5332
    args = (void *)popd(RTAS_env);
 
5333
    base_address = popd(RTAS_env);
 
5334
    memmove((void *)base_address, (void *)(&_RTAS_start),
 
5335
            (char *)(&_RTAS_data_end) - (char *)(&_RTAS_start));
 
5336
    OF_DPRINTF("base_address=0x%0x\n", base_address);
 
5337
    pushd(RTAS_env, base_address);
 
5338
    pushd(RTAS_env, 0);
 
5339
}
 
5340
 
 
5341
__attribute__ (( section (".RTAS") ))
 
5342
static void RTAS_new_cb (OF_env_t *env, OF_node_t *rtas,
 
5343
                         const unsigned char *name,
 
5344
                         OF_cb_t cb, uint32_t *token_next)
 
5345
{
 
5346
    OF_prop_int_new(env, rtas, name, 0xabcd0000 | *token_next);
 
5347
    RTAS_callbacks[*token_next] = &cb;
 
5348
    (*token_next)++;
 
5349
}
 
5350
 
 
5351
__attribute__ (( section (".RTAS") ))
 
5352
void RTAS_init (void)
 
5353
{
 
5354
    OF_env_t *RTAS_env;
 
5355
    OF_node_t *rtas, *chs;
 
5356
    OF_prop_t *stdout;
 
5357
    uint32_t token_next = 0, size;
 
5358
 
 
5359
    RTAS_env = OF_env_main;
 
5360
    rtas = OF_node_new(RTAS_env, OF_node_root, "rtas", OF_ADDRESS_NONE);
 
5361
    if (rtas == NULL) {
 
5362
        ERROR("RTAS not found\n");
 
5363
        return;
 
5364
    }
 
5365
    size = ((char *)(&_RTAS_data_end) - (char *)(&_RTAS_start) + 0x0000FFFF) &
 
5366
        ~0x0000FFFF;
 
5367
    OF_DPRINTF("RTAS size: %d bytes (%d)\n", size,
 
5368
               (char *)(&_RTAS_data_end) - (char *)(&_RTAS_start));
 
5369
    OF_prop_int_new(RTAS_env, rtas, "rtas-size", size);
 
5370
    OF_prop_int_new(RTAS_env, rtas, "rtas-version", 1);
 
5371
    OF_prop_int_new(RTAS_env, rtas, "rtas-event-scan-rate", 0);
 
5372
    OF_prop_int_new(RTAS_env, rtas, "rtas-error-log-max", 0);
 
5373
    chs = OF_node_get(RTAS_env, "chosen");
 
5374
    if (chs == NULL) {
 
5375
        ERROR("choosen not found\n");
 
5376
        return;
 
5377
    }
 
5378
    stdout = OF_property_get(RTAS_env, chs, "stdout");
 
5379
    if (stdout == NULL) {
 
5380
        OF_node_put(RTAS_env, chs);
 
5381
        ERROR("stdout not found\n");
 
5382
        return;
 
5383
    }
 
5384
    OF_prop_int_new(RTAS_env, rtas, "rtas-display-device",
 
5385
                    *(uint32_t *)stdout->value);
 
5386
    /* RTAS tokens */
 
5387
    RTAS_new_cb(RTAS_env, rtas, "restart_rtas",
 
5388
                &RTAS_restart_rtas, &token_next);
 
5389
    RTAS_new_cb(RTAS_env, rtas, "nvram_fetch",
 
5390
                &RTAS_nvram_fetch, &token_next);
 
5391
    RTAS_new_cb(RTAS_env, rtas, "nvram_store",
 
5392
                &RTAS_nvram_store, &token_next);
 
5393
    RTAS_new_cb(RTAS_env, rtas, "get-time-of_day",
 
5394
                &RTAS_get_time_of_day, &token_next);
 
5395
    RTAS_new_cb(RTAS_env, rtas, "set-time-of-day",
 
5396
                &RTAS_set_time_of_day, &token_next);
 
5397
    RTAS_new_cb(RTAS_env, rtas, "set-time-for-power-on",
 
5398
                &RTAS_set_time_for_power_on, &token_next);
 
5399
    RTAS_new_cb(RTAS_env, rtas, "event-scan", &RTAS_event_scan, &token_next);
 
5400
    RTAS_new_cb(RTAS_env, rtas, "check-exception",
 
5401
                &RTAS_check_exception, &token_next);
 
5402
    RTAS_new_cb(RTAS_env, rtas, "read-pci-config",
 
5403
                &RTAS_read_pci_config, &token_next);
 
5404
    RTAS_new_cb(RTAS_env, rtas, "write-pci-config",
 
5405
                &RTAS_write_pci_config, &token_next);
 
5406
    RTAS_new_cb(RTAS_env, rtas, "display-character",
 
5407
                &RTAS_display_character, &token_next);
 
5408
    RTAS_new_cb(RTAS_env, rtas, "set-indicator",
 
5409
                &RTAS_set_indicator, &token_next);
 
5410
    RTAS_new_cb(RTAS_env, rtas, "get-sensor-state",
 
5411
                &RTAS_get_sensor_state, &token_next);
 
5412
#if 0 // No power management */
 
5413
    RTAS_new_cb(RTAS_env, rtas, "set-power-level",
 
5414
                &RTAS_set_power_level, &token_next);
 
5415
    RTAS_new_cb(RTAS_env, rtas, "get-power-level",
 
5416
                &RTAS_get_power_level, &token_next);
 
5417
    RTAS_new_cb(RTAS_env, rtas, "assume-power-management",
 
5418
                &RTAS_assume_power_management, &token_next);
 
5419
    RTAS_new_cb(RTAS_env, rtas, "relinquish-power-management",
 
5420
                &RTAS_relinquish_power_management, &token_next);
 
5421
#endif
 
5422
    RTAS_new_cb(RTAS_env, rtas, "power-off", &RTAS_power_off, &token_next);
 
5423
    RTAS_new_cb(RTAS_env, rtas, "suspend", &RTAS_suspend, &token_next);
 
5424
    RTAS_new_cb(RTAS_env, rtas, "hibernate", &RTAS_hibernate, &token_next);
 
5425
    RTAS_new_cb(RTAS_env, rtas, "system-reboot",
 
5426
                &RTAS_system_reboot, &token_next);
 
5427
#if 0 // No power management nor SMP */
 
5428
    RTAS_new_cb(RTAS_env, rtas, "cache-control",
 
5429
                &RTAS_cache_control, &token_next);
 
5430
    RTAS_new_cb(RTAS_env, rtas, "freeze_time_base",
 
5431
                &RTAS_freeze_time_base, &token_next);
 
5432
    RTAS_new_cb(RTAS_env, rtas, "thaw_time_base",
 
5433
                &RTAS_thaw_time_base, &token_next);
 
5434
    RTAS_new_cb(RTAS_env, rtas, "stop-self", &RTAS_stop_self, &token_next);
 
5435
    RTAS_new_cb(RTAS_env, rtas, "start-cpu", &RTAS_start_cpu, &token_next);
 
5436
#endif
 
5437
    /* missing
 
5438
     * "update-flash"
 
5439
     * "update-flash-and-reboot"
 
5440
     * "query-cpu-stopped-state" for SMP
 
5441
     */
 
5442
    OF_method_new(RTAS_env, rtas, "instantiate-rtas", &RTAS_instantiate);
 
5443
    OF_node_put(RTAS_env, rtas);
 
5444
    OF_node_new(RTAS_env, OF_node_root, "nomore", OF_ADDRESS_NONE);
 
5445
    DPRINTF("RTAS done\n");
 
5446
}
 
5447
 
 
5448
/*****************************************************************************/
 
5449
/*                          That's all for now...                            */
 
5450
/*****************************************************************************/