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

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

unix.superglobalmegacorp.com

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