Annotation of qemu/roms/SLOF/clients/net-snk/oflib/of.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.