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