|
|
1.1 root 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:
1.1.1.3 ! root 13: #include <stdint.h>
1.1 root 14: #include <of.h>
15: #include <rtas.h>
16: #include <string.h>
17: #include <netdriver_int.h>
18: #include <fileio.h>
1.1.1.3 ! root 19: #include <libbootmsg.h>
1.1 root 20:
21: extern void call_client_interface(of_arg_t *);
22:
23: static int ofmod_init(void);
24: static int ofmod_term(void);
25: static int ofmod_open(snk_fileio_t*, const char* name, int flags);
26: static int ofmod_read(char *buffer, int len);
27: static int ofmod_write(char *buffer, int len);
28: static int ofmod_ioctl(int request, void *data);
29:
1.1.1.3 ! root 30: int glue_init(snk_kernel_t *, unsigned int *, size_t, size_t);
! 31: void glue_release(void);
! 32:
1.1 root 33: snk_module_t of_module = {
34: .version = 1,
35: .type = MOD_TYPE_OTHER,
36: .running = 1,
37: .link_addr = (char*) 1,
38: .init = ofmod_init,
39: .term = ofmod_term,
40: .open = ofmod_open,
41: .write = ofmod_write,
42: .read = ofmod_read,
43: .ioctl = ofmod_ioctl
44: };
45:
46: static ihandle_t fd_ihandle_array[FILEIO_MAX];
47: static int claim_rc = 0;
48: static void* client_start;
49: static size_t client_size;
50:
1.1.1.3 ! root 51: static inline int
1.1 root 52: of_0_1(const char *serv)
53: {
54: of_arg_t arg = {
55: p32cast serv,
56: 0, 1,
57: { 0 }
58: };
59:
60: call_client_interface(&arg);
61:
62: return arg.args[0];
63: }
64:
1.1.1.3 ! root 65: static inline void
1.1 root 66: of_1_0(const char *serv, int arg0)
67: {
68: of_arg_t arg = {
69: p32cast serv,
70: 1, 0,
71: {arg0, 0}
72: };
73:
74: call_client_interface(&arg);
75: }
76:
1.1.1.3 ! root 77: static inline unsigned int
1.1 root 78: of_1_1(const char *serv, int arg0)
79: {
80: of_arg_t arg = {
81: p32cast serv,
82: 1, 1,
83: {arg0, 0}
84: };
85:
86: call_client_interface(&arg);
87: return arg.args[1];
88: }
89:
1.1.1.3 ! root 90: static inline unsigned int
1.1 root 91: of_1_2(const char *serv, int arg0, int *ret0)
92: {
93: of_arg_t arg = {
94: p32cast serv,
95: 1, 2,
96: {arg0, 0, 0}
97: };
98:
99: call_client_interface(&arg);
100: *ret0 = arg.args[2];
101: return arg.args[1];
102: }
103:
1.1.1.3 ! root 104: static inline void
1.1 root 105: of_2_0(const char *serv, int arg0, int arg1)
106: {
107: of_arg_t arg = {
108: p32cast serv,
109: 2, 0,
110: {arg0, arg1, 0}
111: };
112:
113: call_client_interface(&arg);
114: }
115:
1.1.1.3 ! root 116: static inline unsigned int
1.1 root 117: of_2_1(const char *serv, int arg0, int arg1)
118: {
119: of_arg_t arg = {
120: p32cast serv,
121: 2, 1,
122: {arg0, arg1, 0}
123: };
124:
125: call_client_interface(&arg);
126: return arg.args[2];
127: }
128:
1.1.1.3 ! root 129: static inline unsigned int
1.1 root 130: of_2_2(const char *serv, int arg0, int arg1, int *ret0)
131: {
132: of_arg_t arg = {
133: p32cast serv,
134: 2, 2,
135: {arg0, arg1, 0, 0}
136: };
137:
138: call_client_interface(&arg);
139: *ret0 = arg.args[3];
140: return arg.args[2];
141: }
142:
1.1.1.3 ! root 143: static inline unsigned int
1.1 root 144: of_2_3(const char *serv, int arg0, int arg1, int *ret0, int *ret1)
145: {
146: of_arg_t arg = {
147: p32cast serv,
148: 2, 3,
149: {arg0, arg1, 0, 0, 0}
150: };
151:
152: call_client_interface(&arg);
153: *ret0 = arg.args[3];
154: *ret1 = arg.args[4];
155: return arg.args[2];
156: }
157:
1.1.1.3 ! root 158: static inline void
1.1 root 159: of_3_0(const char *serv, int arg0, int arg1, int arg2)
160: {
161: of_arg_t arg = {
162: p32cast serv,
163: 3, 0,
164: {arg0, arg1, arg2, 0}
165: };
166:
167: call_client_interface(&arg);
168: return;
169: }
170:
1.1.1.3 ! root 171: static inline unsigned int
1.1 root 172: of_3_1(const char *serv, int arg0, int arg1, int arg2)
173: {
174: of_arg_t arg = {
175: p32cast serv,
176: 3, 1,
177: {arg0, arg1, arg2, 0}
178: };
179:
180: call_client_interface(&arg);
181: return arg.args[3];
182: }
183:
1.1.1.3 ! root 184: static inline unsigned int
1.1 root 185: of_3_2(const char *serv, int arg0, int arg1, int arg2, int *ret0)
186: {
187: of_arg_t arg = {
188: p32cast serv,
189: 3, 2,
190: {arg0, arg1, arg2, 0, 0}
191: };
192:
193: call_client_interface(&arg);
194: *ret0 = arg.args[4];
195: return arg.args[3];
196: }
197:
1.1.1.3 ! root 198: static inline unsigned int
1.1 root 199: of_3_3(const char *serv, int arg0, int arg1, int arg2, int *ret0, int *ret1)
200: {
201: of_arg_t arg = {
202: p32cast serv,
203: 3, 3,
204: {arg0, arg1, arg2, 0, 0, 0}
205: };
206:
207: call_client_interface(&arg);
208: *ret0 = arg.args[4];
209: *ret1 = arg.args[5];
210: return arg.args[3];
211: }
212:
1.1.1.3 ! root 213: static inline unsigned int
1.1 root 214: of_4_1(const char *serv, int arg0, int arg1, int arg2, int arg3)
215: {
216: of_arg_t arg = {
217: p32cast serv,
218: 4, 1,
219: {arg0, arg1, arg2, arg3, 0}
220: };
221:
222: call_client_interface(&arg);
223: return arg.args[4];
224: }
225:
226: int
1.1.1.3 ! root 227: of_test(const char *name)
! 228: {
! 229: return (int) of_1_1("test", p32cast name);
! 230: }
! 231:
! 232: int
1.1 root 233: of_interpret_1(void *s, void *ret)
234: {
235: return of_1_2("interpret", p32cast s, ret);
236: }
237:
238: void
239: of_close(ihandle_t ihandle)
240: {
241: of_1_0("close", ihandle);
242: }
243:
244: int
245: of_write(ihandle_t ihandle, void *s, int len)
246: {
247: return of_3_1("write", ihandle, p32cast s, len);
248: }
249:
250: int
251: of_read(ihandle_t ihandle, void *s, int len)
252: {
253: return of_3_1("read", ihandle, p32cast s, len);
254: }
255:
256: int
257: of_seek(ihandle_t ihandle, int poshi, int poslo)
258: {
259: return of_3_1("seek", ihandle, poshi, poslo);
260: }
261:
262: int
263: of_getprop(phandle_t phandle, const char *name, void *buf, int len)
264: {
265: return of_4_1("getprop", phandle, p32cast name, p32cast buf, len);
266: }
267:
268: phandle_t
269: of_peer(phandle_t phandle)
270: {
271: return (phandle_t) of_1_1("peer", phandle);
272: }
273:
274: phandle_t
275: of_child(phandle_t phandle)
276: {
277: return (phandle_t) of_1_1("child", phandle);
278: }
279:
280: phandle_t
281: of_parent(phandle_t phandle)
282: {
283: return (phandle_t) of_1_1("parent", phandle);
284: }
285:
286: phandle_t
287: of_finddevice(const char *name)
288: {
289: return (phandle_t) of_1_1("finddevice", p32cast name);
290: }
291:
292: ihandle_t
293: of_open(const char *name)
294: {
295: return (ihandle_t) of_1_1("open", p32cast name);
296: }
297:
298: void *
299: of_claim(void *start, unsigned int size, unsigned int align)
300: {
301: return(void *)(long)(size_t)of_3_1("claim", p32cast start, size, align);
302: }
303:
304: void
305: of_release(void *start, unsigned int size)
306: {
307: (void) of_2_0("release", p32cast start, size);
308: }
309:
310: unsigned int
311: romfs_lookup(const char *name, void **addr)
312: {
313: unsigned int high, low;
314: unsigned int i = of_2_3("ibm,romfs-lookup", p32cast name, strlen(name),
315: (int *) &high, (int *) &low);
316: *addr = (void*)(((unsigned long) high << 32) | (unsigned long) low);
317: return i;
318: }
319:
320: void *
321: of_call_method_3(const char *name, ihandle_t ihandle, int arg0)
322: {
323: int entry, rc;
324: rc = of_3_2("call-method", p32cast name, ihandle, arg0, &entry);
325: return rc != 0 ? 0 : (void *) (long) entry;
326: }
327:
328: int
329: vpd_read(unsigned int offset, unsigned int length, char *data)
330: {
331: int result;
332: long tmp = (long) data;
333: result = of_3_1("rtas-read-vpd", offset, length, (int) tmp);
334: return result;
335: }
336:
337: int
338: vpd_write(unsigned int offset, unsigned int length, char *data)
339: {
340: int result;
341: long tmp = (long) data;
342: result = of_3_1("rtas-write-vpd", offset, length, (int) tmp);
343: return result;
344: }
345:
346: static void
347: ipmi_oem_led_set(int type, int instance, int state)
348: {
349: return of_3_0("set-led", type, instance, state);
350: }
351:
352: int
353: write_mm_log(char *data, unsigned int length, unsigned short type)
354: {
355: long tmp = (long) data;
356:
357: ipmi_oem_led_set(2, 0, 1);
358: return of_3_1("write-mm-log", (int) tmp, length, type);
359: }
360:
361: int
362: of_yield(void)
363: {
364: return of_0_1("yield");
365: }
366:
367: void *
368: of_set_callback(void *addr)
369: {
370: return (void *) (long) (size_t) of_1_1("set-callback", p32cast addr);
371: }
372:
373: void
374: bootmsg_warning(short id, const char *str, short lvl)
375: {
376: (void) of_3_0("bootmsg-warning", id, lvl, p32cast str);
377: }
378:
379: void
380: bootmsg_error(short id, const char *str)
381: {
382: (void) of_2_0("bootmsg-error", id, p32cast str);
383: }
384:
1.1.1.3 ! root 385: /*
1.1 root 386: void
387: bootmsg_debugcp(short id, const char *str, short lvl)
388: {
389: (void) of_3_0("bootmsg-debugcp", id, lvl, p32cast str);
390: }
391:
392: void
393: bootmsg_cp(short id)
394: {
395: (void) of_1_0("bootmsg-cp", id);
396: }
1.1.1.3 ! root 397: */
1.1 root 398:
399: static long
400: of_fileio_read(snk_fileio_t *fileio, char *buf, long len)
401: {
402: if(!fileio)
403: return -1;
404: return of_read( * (ihandle_t*) fileio->data, buf, len );
405: }
406:
407: static long
408: of_fileio_write(snk_fileio_t *fileio, char *buf, long len)
409: {
410: if(!fileio)
411: return -1;
412: return of_write( * (ihandle_t*) fileio->data, buf, len );
413: }
414:
415: static int
416: of_fileio_close(snk_fileio_t *fileio)
417: {
418: if(!fileio)
419: return -1;
420:
421: fileio->type = FILEIO_TYPE_EMPTY;
422: of_close( * (ihandle_t*) fileio->data );
423: return 0;
424: }
425:
1.1.1.3 ! root 426: static long
! 427: dma_map_in(void *address, long size, int cachable)
! 428: {
! 429: unsigned int ret;
! 430:
! 431: /* Is dma-map-in available? */
! 432: if (of_test("dma-map-in") != 0) {
! 433: /* No dma-map-in available ==> Assume we can use 1:1 addresses */
! 434: return (long)address;
! 435: }
! 436:
! 437: ret = of_3_1("dma-map-in", p32cast address, (int)size, cachable);
! 438:
! 439: return ret;
! 440: }
! 441:
! 442: static void
! 443: dma_map_out(void *address, long devaddr, long size)
! 444: {
! 445: /* Is dma-map-out available? */
! 446: if (of_test("dma-map-out") != 0) {
! 447: /* No dma-map-out available */
! 448: return;
! 449: }
! 450:
! 451: of_3_0("dma-map-out", p32cast address, (int)devaddr, (int)size);
! 452: }
! 453:
1.1 root 454:
455: #define CONFIG_SPACE 0
456: #define IO_SPACE 1
457: #define MEM_SPACE 2
458:
459: #define ASSIGNED_ADDRESS_PROPERTY 0
460: #define REG_PROPERTY 1
461:
462: #define DEBUG_TRANSLATE_ADDRESS 0
463: #if DEBUG_TRANSLATE_ADDRESS != 0
464: #define DEBUG_TR(str...) printk(str)
465: #else
466: #define DEBUG_TR(str...)
467: #endif
468:
469: /**
470: * pci_address_type tries to find the type for which a
471: * mapping should be done. This is PCI specific and is done by
472: * looking at the first 32bit of the phys-addr in
473: * assigned-addresses
474: *
475: * @param node the node of the device which requests
476: * translatation
477: * @param address the address which needs to be translated
478: * @param prop_type the type of the property to search in (either REG_PROPERTY or ASSIGNED_ADDRESS_PROPERTY)
479: * @return the corresponding type (config, i/o, mem)
480: */
481: static int
482: pci_address_type(phandle_t node, uint64_t address, uint8_t prop_type)
483: {
484: char *prop_name = "assigned-addresses";
485: if (prop_type == REG_PROPERTY)
486: prop_name = "reg";
487: /* #address-cells */
488: const unsigned int nac = 3; //PCI
489: /* #size-cells */
490: const unsigned int nsc = 2; //PCI
491: /* up to 11 pairs of (phys-addr(3) size(2)) */
492: unsigned char buf[11 * (nac + nsc) * sizeof(int)];
493: unsigned int *assigned_ptr;
494: int result = -1;
495: int len;
496: len = of_getprop(node, prop_name, buf, 11 * (nac + nsc) * sizeof(int));
497: assigned_ptr = (unsigned int *) &buf[0];
498: while (len > 0) {
499: if ((prop_type == REG_PROPERTY)
500: && ((assigned_ptr[0] & 0xFF) != 0)) {
501: //BARs and Expansion ROM must be in assigned-addresses... so in reg
502: // we only look for those without config space offset set...
503: assigned_ptr += (nac + nsc);
504: len -= (nac + nsc) * sizeof(int);
505: continue;
506: }
507: DEBUG_TR("%s %x size %x\n", prop_name, assigned_ptr[2],
508: assigned_ptr[4]);
509: if (address >= assigned_ptr[2]
510: && address <= assigned_ptr[2] + assigned_ptr[4]) {
511: DEBUG_TR("found a match\n");
512: result = (assigned_ptr[0] & 0x03000000) >> 24;
513: break;
514: }
515: assigned_ptr += (nac + nsc);
516: len -= (nac + nsc) * sizeof(int);
517: }
518: /* this can only handle 32bit memory space and should be
519: * removed as soon as translations for 64bit are available */
520: return (result == 3) ? MEM_SPACE : result;
521: }
522:
523: /**
524: * this is a hack which returns the lower 64 bit of any number of cells
525: * all the higher bits will silently discarded
526: * right now this works pretty good as long 64 bit addresses is all we want
527: *
528: * @param addr a pointer to the first address cell
529: * @param nc number of cells addr points to
530: * @return the lower 64 bit to which addr points
531: */
532: static uint64_t
533: get_dt_address(uint32_t *addr, uint32_t nc)
534: {
535: uint64_t result = 0;
536: while (nc--)
537: result = (result << 32) | *(addr++);
538: return result;
539: }
540:
541: /**
542: * this functions tries to find a mapping for the given address
543: * it assumes that if we have #address-cells == 3 that we are trying
544: * to do a PCI translation
545: *
546: * @param addr a pointer to the address that should be translated
547: * if a translation has been found the address will
548: * be modified
549: * @param type this is required for PCI devices to find the
550: * correct translation
551: * @param ranges this is one "range" containing the translation
552: * information (one range = nac + pnac + nsc)
553: * @param nac the OF property #address-cells
554: * @param nsc the OF property #size-cells
555: * @param pnac the OF property #address-cells from the parent node
556: * @return -1 if no translation was possible; else 0
557: */
558: static int
559: map_one_range(uint64_t *addr, int type, uint32_t *ranges, uint32_t nac,
560: uint32_t nsc, uint32_t pnac)
561: {
562: long offset;
563: /* cm - child mapping */
564: /* pm - parent mapping */
565: uint64_t cm, size, pm;
566: /* only check for the type if nac == 3 (PCI) */
567: DEBUG_TR("type %x, nac %x\n", ranges[0], nac);
568: if (((ranges[0] & 0x03000000) >> 24) != type && nac == 3)
569: return -1;
570: /* okay, it is the same type let's see if we find a mapping */
571: size = get_dt_address(ranges + nac + pnac, nsc);
572: if (nac == 3) /* skip type if PCI */
573: cm = get_dt_address(ranges + 1, nac - 1);
574: else
575: cm = get_dt_address(ranges, nac);
576:
577: DEBUG_TR("\t\tchild_mapping %lx\n", cm);
578: DEBUG_TR("\t\tsize %lx\n", size);
579: DEBUG_TR("\t\t*address %lx\n", (uint64_t) * addr);
580: if (cm + size <= (uint64_t) * addr || cm > (uint64_t) * addr)
581: /* it is not inside the mapping range */
582: return -1;
583: /* get the offset */
584: offset = *addr - cm;
585: /* and add the offset on the parent mapping */
586: if (pnac == 3) /* skip type if PCI */
587: pm = get_dt_address(ranges + nac + 1, pnac - 1);
588: else
589: pm = get_dt_address(ranges + nac, pnac);
590: DEBUG_TR("\t\tparent_mapping %lx\n", pm);
591: *addr = pm + offset;
592: DEBUG_TR("\t\t*address %lx\n", *addr);
593: return 0;
594: }
595:
596: /**
597: * translate_address_dev tries to translate the device specific address
598: * to a host specific address by walking up in the device tree
599: *
600: * @param address a pointer to a 64 bit value which will be
601: * translated
602: * @param current_node phandle of the device from which the
603: * translation will be started
604: */
605: void
606: translate_address_dev(uint64_t *addr, phandle_t current_node)
607: {
608: unsigned char buf[1024];
609: phandle_t parent;
610: unsigned int pnac;
611: unsigned int nac;
612: unsigned int nsc;
613: int addr_type;
614: int len;
615: unsigned int *ranges;
616: unsigned int one_range;
617: DEBUG_TR("translate address %lx, node: %lx\n", *addr, current_node);
618: of_getprop(current_node, "name", buf, 400);
619: DEBUG_TR("current node: %s\n", buf);
620: addr_type =
621: pci_address_type(current_node, *addr, ASSIGNED_ADDRESS_PROPERTY);
622: if (addr_type == -1) {
623: // check in "reg" property if not found in "assigned-addresses"
624: addr_type = pci_address_type(current_node, *addr, REG_PROPERTY);
625: }
626: DEBUG_TR("address_type %x\n", addr_type);
627: current_node = of_parent(current_node);
628: while (1) {
629: parent = of_parent(current_node);
630: if (!parent) {
631: DEBUG_TR("reached root node...\n");
632: break;
633: }
634: of_getprop(current_node, "#address-cells", &nac, 4);
635: of_getprop(current_node, "#size-cells", &nsc, 4);
636: of_getprop(parent, "#address-cells", &pnac, 4);
637: one_range = nac + pnac + nsc;
638: len = of_getprop(current_node, "ranges", buf, 400);
639: if (len < 0) {
640: DEBUG_TR("no 'ranges' property; not translatable\n");
641: return;
642: }
643: ranges = (unsigned int *) &buf[0];
644: while (len > 0) {
645: if (!map_one_range
646: ((uint64_t *) addr, addr_type, ranges, nac, nsc,
647: pnac))
648: /* after a successful mapping we stop
649: * going through the ranges */
650: break;
651: ranges += one_range;
652: len -= one_range * sizeof(int);
653: }
654: DEBUG_TR("address %lx\n", *addr);
655: of_getprop(current_node, "name", buf, 400);
656: DEBUG_TR("current node: %s\n", buf);
657: DEBUG_TR("\t#address-cells: %x\n", nac);
658: DEBUG_TR("\t#size-cells: %x\n", nsc);
659: of_getprop(parent, "name", buf, 400);
660: DEBUG_TR("parent node: %s\n", buf);
661: DEBUG_TR("\t#address-cells: %x\n", pnac);
662: current_node = parent;
663: }
664: }
665:
666: static phandle_t
667: get_boot_device(void)
668: {
669: char buf[1024];
670: phandle_t dev = of_finddevice("/chosen");
671:
672: if (dev == -1) {
673: dev = of_finddevice("/aliases");
674: if (dev == -1)
675: return dev;
676: of_getprop(dev, "net", buf, 1024);
677: } else
678: of_getprop(dev, "bootpath", buf, 1024);
679:
680: return of_finddevice(buf);
681: }
682:
683: /**
684: * translate_address tries to translate the device specific address
685: * of the boot device to a host specific address
686: *
687: * @param address a pointer to a 64 bit value which will be
688: * translated
689: */
690: void
691: translate_address(unsigned long *addr)
692: {
693: translate_address_dev((uint64_t*) addr, get_boot_device());
694: }
695:
696: /**
697: * get_puid walks up in the device tree until it finds a parent
698: * node without a reg property. get_puid is assuming that if the
699: * parent node has no reg property it has found the pci host bridge
700: *
701: * this is not the correct way to find PHBs but it seems to work
702: * for all our systems
703: *
704: * @param node the device for which to find the puid
705: *
706: * @return the puid or 0
707: */
708: uint64_t
709: get_puid(phandle_t node)
710: {
711: uint64_t puid = 0;
712: uint64_t tmp = 0;
1.1.1.2 root 713: phandle_t curr_node, last_node;
714:
715: curr_node = last_node = of_parent(node);
716:
717: while (curr_node) {
1.1 root 718: puid = tmp;
719: if (of_getprop(curr_node, "reg", &tmp, 8) < 8) {
720: /* if the found PHB is not directly under
721: * root we need to translate the found address */
1.1.1.2 root 722: translate_address_dev(&puid, last_node);
1.1 root 723: return puid;
724: }
1.1.1.2 root 725: last_node = curr_node;
1.1 root 726: curr_node = of_parent(curr_node);
727: }
1.1.1.2 root 728:
1.1 root 729: return 0;
730: }
731:
732: static int set_vio_config(vio_config_t * vio_config, phandle_t net)
733: {
1.1.1.3 ! root 734: vio_config->config_type = CONFIG_TYPE_VIO;
! 735: vio_config->reg_len = of_getprop(net, "reg", vio_config->reg,
! 736: sizeof(vio_config->reg));
1.1 root 737: of_getprop(net, "compatible", &vio_config->compat, 64);
738:
739: return 0;
740: }
741:
742: /* Fill in the pci config structure from the device tree */
743: static int set_pci_config(pci_config_t * pci_config, phandle_t net)
744: {
745: unsigned char buf[400];
746: int len, bar_nr;
747: unsigned int *assigned_ptr;
748:
1.1.1.3 ! root 749: pci_config->config_type = CONFIG_TYPE_PCI;
! 750:
1.1 root 751: of_getprop(net, "vendor-id", &pci_config->vendor_id, 4);
752: of_getprop(net, "device-id", &pci_config->device_id, 4);
753: of_getprop(net, "revision-id", &pci_config->revision_id, 4);
754: of_getprop(net, "class-code", &pci_config->class_code, 4);
755: of_getprop(net, "interrupts", &pci_config->interrupt_line, 4);
756:
757: len = of_getprop(net, "assigned-addresses", buf, 400);
758: if (len <= 0)
759: return -1;
760:
761: assigned_ptr = (unsigned int *) &buf[0];
762: pci_config->bus = (assigned_ptr[0] & 0x00ff0000) >> 16;
763: pci_config->devfn = (assigned_ptr[0] & 0x0000ff00) >> 8;
764:
765: while (len > 0) {
766: /* Fixme 64 bit bars */
767: bar_nr = ((assigned_ptr[0] & 0xff) - 0x10) / 4;
768: pci_config->bars[bar_nr].type =
769: (assigned_ptr[0] & 0x0f000000) >> 24;
770: pci_config->bars[bar_nr].addr = assigned_ptr[2];
771: pci_config->bars[bar_nr].size = assigned_ptr[4];
772: assigned_ptr += 5;
773: len -= 5 * sizeof(int);
774: }
775:
776: pci_config->puid = get_puid(net);
777:
778: return 0;
779: }
780:
781: static int set_config(snk_kernel_t * snk_kernel_interface)
782: {
783: phandle_t parent, net = get_boot_device();
784: char compat[64];
785:
786: if (net == -1)
787: return -1;
788:
789: parent = of_parent(net);
790: of_getprop(parent, "compatible", compat, 64);
1.1.1.3 ! root 791:
! 792: if (strcmp(compat, "IBM,vdevice") == 0
! 793: || strncmp(compat, "ibm,virtio", 10) == 0)
1.1 root 794: return set_vio_config(&snk_kernel_interface->vio_conf, net);
1.1.1.3 ! root 795:
1.1 root 796: return set_pci_config(&snk_kernel_interface->pci_conf, net);
797: }
798:
799: void
800: get_mac(char *mac)
801: {
1.1.1.2 root 802: uint8_t localmac[8];
803: int len;
804:
1.1 root 805: phandle_t net = get_boot_device();
806: if (net == -1)
807: return;
808:
1.1.1.2 root 809: len = of_getprop(net, "local-mac-address", localmac, 8);
1.1.1.3 ! root 810: if (len <= 0)
! 811: return;
1.1.1.2 root 812:
813: if (len == 8) {
814: /* Some bad FDT nodes like veth use a 8-byte wide
815: * property instead of 6-byte wide MACs... :-( */
816: memcpy(mac, &localmac[2], 6);
817: }
818: else {
819: memcpy(mac, localmac, 6);
820: }
1.1 root 821: }
822:
823: static void
824: get_timebase(unsigned int *timebase)
825: {
826: phandle_t cpu;
827: phandle_t cpus = of_finddevice("/cpus");
828:
829: if (cpus == -1)
830: return;
831:
832: cpu = of_child(cpus);
833:
834: if (cpu == -1)
835: return;
836:
837: of_getprop(cpu, "timebase-frequency", timebase, 4);
838: }
839:
1.1.1.3 ! root 840:
1.1 root 841: int
842: glue_init(snk_kernel_t * snk_kernel_interface, unsigned int * timebase,
843: size_t _client_start, size_t _client_size)
844: {
845: phandle_t chosen = of_finddevice("/chosen");
846:
847: client_start = (void *) (long) _client_start;
848: client_size = _client_size;
849:
850: if (chosen == -1)
851: return -1;
852:
853: fd_array[0].type = FILEIO_TYPE_USED;
854: fd_array[0].read = of_fileio_read;
855: fd_array[0].write = of_fileio_write;
856: fd_array[0].ioctl = 0;
857: fd_array[0].close = of_fileio_close;
858: fd_array[0].data = &fd_ihandle_array[0];
859: of_getprop(chosen, "stdin", fd_array[0].data, sizeof(ihandle_t));
860:
861: fd_array[1].type = FILEIO_TYPE_USED;
862: fd_array[1].read = of_fileio_read;
863: fd_array[1].write = of_fileio_write;
864: fd_array[1].ioctl = 0;
865: fd_array[1].close = of_fileio_close;
866: fd_array[1].data = &fd_ihandle_array[1];
867: of_getprop(chosen, "stdout", fd_array[1].data, sizeof(ihandle_t));
868:
869: if (of_write(fd_ihandle_array[1], " ", 1) < 0)
870: return -2;
871:
872: /* Setup Kernel Struct */
873: if (set_config(snk_kernel_interface) == -1) {
874: snk_kernel_interface->print(" No net device found \n");
875: }
876:
877: get_timebase(timebase);
878: rtas_init();
879:
880: snk_kernel_interface->k_romfs_lookup = romfs_lookup;
881: snk_kernel_interface->translate_addr = translate_address;
882: snk_kernel_interface->pci_config_read = rtas_pci_config_read;
883: snk_kernel_interface->pci_config_write = rtas_pci_config_write;
1.1.1.3 ! root 884: snk_kernel_interface->dma_map_in = dma_map_in;
! 885: snk_kernel_interface->dma_map_out = dma_map_out;
! 886:
1.1 root 887: claim_rc=(int)(long)of_claim(client_start, client_size, 0);
888:
889: return 0;
890: }
891:
892: void
893: glue_release(void)
894: {
895: if (claim_rc >= 0) {
896: of_release(client_start, client_size);
897: }
898: }
899:
900: static int
901: ofmod_init(void)
902: {
903: of_module.running = 1;
904: return 0;
905: }
906:
907: static int
908: ofmod_term(void)
909: {
910: of_module.running = 0;
911: return 0;
912: }
913:
914: static int
915: ofmod_open(snk_fileio_t *fileio, const char* name, int flags)
916: {
917: if ((fd_ihandle_array[fileio->idx] = of_open (name)) == 0)
918: {
919: /* this module can not open this file */
920: return -1;
921: }
922:
923: fileio->type = FILEIO_TYPE_USED;
924: fileio->read = of_fileio_read;
925: fileio->write = of_fileio_write;
926: fileio->close = of_fileio_close;
927: fileio->data = &fd_ihandle_array[fileio->idx];
928: return 0;
929: }
930:
931: static int
932: ofmod_read(char *buffer, int len)
933: {
934: return len;
935: }
936:
937: static int
938: ofmod_write(char *buffer, int len)
939: {
940: return len;
941: }
942:
943: static int
944: ofmod_ioctl(int request, void *data)
945: {
946: return 0;
947: }
948:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.