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

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>
1.1.1.2 ! root       19: #include <stdint.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: 
                     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;
1.1.1.2 ! root      675:        phandle_t curr_node, last_node;
        !           676: 
        !           677:        curr_node = last_node = of_parent(node);
        !           678: 
        !           679:        while (curr_node) {
1.1       root      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 */
1.1.1.2 ! root      684:                        translate_address_dev(&puid, last_node);
1.1       root      685:                        return puid;
                    686:                }
1.1.1.2 ! root      687:                last_node = curr_node;
1.1       root      688:                curr_node = of_parent(curr_node);
                    689:        }
1.1.1.2 ! root      690: 
1.1       root      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: {
1.1.1.2 ! root      757:        uint8_t localmac[8];
        !           758:        int len;
        !           759: 
1.1       root      760:        phandle_t net = get_boot_device();
                    761: 
                    762:        if (net == -1)
                    763:                return;
                    764: 
1.1.1.2 ! root      765:        len = of_getprop(net, "local-mac-address", localmac, 8);
        !           766: 
        !           767:        if (len == 8) {
        !           768:                /* Some bad FDT nodes like veth use a 8-byte wide
        !           769:                 * property instead of 6-byte wide MACs... :-( */
        !           770:                memcpy(mac, &localmac[2], 6);
        !           771:        }
        !           772:        else {
        !           773:                memcpy(mac, localmac, 6);
        !           774:        }
1.1       root      775: }
                    776: 
                    777: static void
                    778: get_timebase(unsigned int *timebase)
                    779: {
                    780:        phandle_t cpu;
                    781:        phandle_t cpus = of_finddevice("/cpus");
                    782: 
                    783:        if (cpus == -1)
                    784:                return;
                    785: 
                    786:        cpu = of_child(cpus);
                    787: 
                    788:        if (cpu == -1)
                    789:                return;
                    790: 
                    791:        of_getprop(cpu, "timebase-frequency", timebase, 4);
                    792: }
                    793: 
                    794: int
                    795: glue_init(snk_kernel_t * snk_kernel_interface, unsigned int * timebase,
                    796:           size_t _client_start, size_t _client_size)
                    797: {
                    798:        phandle_t chosen = of_finddevice("/chosen");
                    799: 
                    800:        client_start = (void *) (long) _client_start;
                    801:        client_size = _client_size;
                    802: 
                    803:        if (chosen == -1)
                    804:                return -1;
                    805: 
                    806:        fd_array[0].type  = FILEIO_TYPE_USED;
                    807:        fd_array[0].read  = of_fileio_read;
                    808:        fd_array[0].write = of_fileio_write;
                    809:        fd_array[0].ioctl = 0;
                    810:        fd_array[0].close = of_fileio_close;
                    811:        fd_array[0].data  = &fd_ihandle_array[0];
                    812:        of_getprop(chosen, "stdin", fd_array[0].data, sizeof(ihandle_t));
                    813: 
                    814:        fd_array[1].type  = FILEIO_TYPE_USED;
                    815:        fd_array[1].read  = of_fileio_read;
                    816:        fd_array[1].write = of_fileio_write;
                    817:        fd_array[1].ioctl = 0;
                    818:        fd_array[1].close = of_fileio_close;
                    819:        fd_array[1].data  = &fd_ihandle_array[1];
                    820:        of_getprop(chosen, "stdout", fd_array[1].data, sizeof(ihandle_t));
                    821: 
                    822:        if (of_write(fd_ihandle_array[1], " ", 1) < 0)
                    823:                return -2;
                    824: 
                    825:        /* Setup Kernel Struct */
                    826:        if (set_config(snk_kernel_interface) == -1) {
                    827:                snk_kernel_interface->print(" No net device found \n");
                    828:        }
                    829: 
                    830:        get_timebase(timebase);
                    831:        rtas_init();
                    832: 
                    833:        snk_kernel_interface->k_romfs_lookup = romfs_lookup;
                    834:        snk_kernel_interface->translate_addr = translate_address;
                    835:        snk_kernel_interface->pci_config_read = rtas_pci_config_read;
                    836:        snk_kernel_interface->pci_config_write = rtas_pci_config_write;
                    837:        claim_rc=(int)(long)of_claim(client_start, client_size, 0);
                    838: 
                    839:        return 0;
                    840: }
                    841: 
                    842: void
                    843: glue_release(void)
                    844: {
                    845:        if (claim_rc >= 0) {
                    846:                of_release(client_start, client_size);
                    847:        }
                    848: }
                    849: 
                    850: static int
                    851: ofmod_init(void)
                    852: {
                    853:        of_module.running = 1;
                    854:        return 0;
                    855: }
                    856: 
                    857: static int
                    858: ofmod_term(void)
                    859: {
                    860:        of_module.running = 0;
                    861:        return 0;
                    862: }
                    863: 
                    864: static int
                    865: ofmod_open(snk_fileio_t *fileio, const char* name, int flags)
                    866: {
                    867:        if ((fd_ihandle_array[fileio->idx] = of_open (name)) == 0)
                    868:        {
                    869:                /* this module can not open this file */
                    870:                return -1;
                    871:        }
                    872: 
                    873:        fileio->type  = FILEIO_TYPE_USED;
                    874:        fileio->read  = of_fileio_read;
                    875:        fileio->write = of_fileio_write;
                    876:        fileio->close = of_fileio_close;
                    877:        fileio->data  = &fd_ihandle_array[fileio->idx];
                    878:        return 0;
                    879: }
                    880: 
                    881: static int
                    882: ofmod_read(char *buffer, int len)
                    883: {
                    884:        return len;
                    885: }
                    886: 
                    887: static int
                    888: ofmod_write(char *buffer, int len)
                    889: {
                    890:        return len;
                    891: }
                    892: 
                    893: static int
                    894: ofmod_ioctl(int request, void *data)
                    895: {
                    896:        return 0;
                    897: }
                    898: 

unix.superglobalmegacorp.com

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