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