Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / of.c
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 /*****************************************************************************/