qemu/hw/core/fdt_generic_util.c
<<
>>
Prefs
   1/*
   2 * Utility functions for fdt generic framework
   3 *
   4 * Copyright (c) 2009 Edgar E. Iglesias.
   5 * Copyright (c) 2009 Michal Simek.
   6 * Copyright (c) 2011 PetaLogix Qld Pty Ltd.
   7 * Copyright (c) 2011 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>.
   8 *
   9 * Permission is hereby granted, free of charge, to any person obtaining a copy
  10 * of this software and associated documentation files (the "Software"), to deal
  11 * in the Software without restriction, including without limitation the rights
  12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13 * copies of the Software, and to permit persons to whom the Software is
  14 * furnished to do so, subject to the following conditions:
  15 *
  16 * The above copyright notice and this permission notice shall be included in
  17 * all copies or substantial portions of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25 * THE SOFTWARE.
  26 */
  27
  28#include "qemu/osdep.h"
  29#include "hw/fdt_generic_util.h"
  30#include "hw/fdt_generic_devices.h"
  31#include "net/net.h"
  32#include "exec/memory.h"
  33#include "exec/address-spaces.h"
  34#include "hw/sysbus.h"
  35#include "qapi/error.h"
  36#include "sysemu/sysemu.h"
  37#include "sysemu/blockdev.h"
  38#include "sysemu/char.h"
  39#include "qemu/log.h"
  40#include "qom/cpu.h"
  41
  42#ifndef FDT_GENERIC_UTIL_ERR_DEBUG
  43#define FDT_GENERIC_UTIL_ERR_DEBUG 3
  44#endif
  45#define DB_PRINT(lvl, ...) do { \
  46    if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
  47        qemu_log_mask(LOG_FDT, ": %s: ", __func__); \
  48        qemu_log_mask(LOG_FDT, ## __VA_ARGS__); \
  49    } \
  50} while (0);
  51
  52#define DB_PRINT_NP(lvl, ...) do { \
  53    if (FDT_GENERIC_UTIL_ERR_DEBUG > (lvl)) { \
  54       qemu_log_mask(LOG_FDT, "%s", node_path); \
  55       DB_PRINT((lvl), ## __VA_ARGS__); \
  56    } \
  57} while (0);
  58
  59#include "hw/remote-port-device.h"
  60#include "hw/remote-port.h"
  61
  62/* FIXME: wrap direct calls into libfdt */
  63
  64#include <libfdt.h>
  65#include <stdlib.h>
  66
  67int fdt_serial_ports;
  68
  69static int simple_bus_fdt_init(char *bus_node_path, FDTMachineInfo *fdti);
  70
  71typedef struct QEMUIRQSharedState {
  72    qemu_irq sink;
  73    int num;
  74    bool (*merge_fn)(bool *, int);
  75/* FIXME: remove artificial limit */
  76#define MAX_IRQ_SHARED_INPUTS 128
  77    bool inputs[MAX_IRQ_SHARED_INPUTS];
  78} QEMUIRQSharedState;
  79
  80static bool qemu_irq_shared_or_handler(bool *inputs, int n)
  81{
  82    int i;
  83
  84    assert(n < MAX_IRQ_SHARED_INPUTS);
  85
  86    for (i = 0; i < n; ++i) {
  87        if (inputs[i]) {
  88            return true;
  89        }
  90    }
  91    return false;
  92}
  93
  94static bool qemu_irq_shared_and_handler(bool *inputs, int n)
  95{
  96    int i;
  97
  98    assert(n < MAX_IRQ_SHARED_INPUTS);
  99
 100    for (i = 0; i < n; ++i) {
 101        if (!inputs[i]) {
 102            return false;
 103        }
 104    }
 105    return true;
 106}
 107
 108static void qemu_irq_shared_handler(void *opaque, int n, int level)
 109{
 110    QEMUIRQSharedState *s = opaque;
 111
 112    assert(n < MAX_IRQ_SHARED_INPUTS);
 113    s->inputs[n] = level;
 114    qemu_set_irq(s->sink, s->merge_fn(s->inputs, s->num));
 115}
 116
 117static void fdt_init_all_irqs(FDTMachineInfo *fdti)
 118{
 119    while (fdti->irqs) {
 120        FDTIRQConnection *first = fdti->irqs;
 121        qemu_irq sink = first->irq;
 122        bool (*merge_fn)(bool *, int) = first->merge_fn;
 123        int num_sources = 0;
 124        FDTIRQConnection *irq;
 125
 126        for (irq = first; irq; irq = irq->next) {
 127            if (irq->irq == sink) { /* Same sink */
 128                num_sources++;
 129            }
 130        }
 131        if (num_sources > 1) {
 132            QEMUIRQSharedState *s = g_malloc0(sizeof *s);
 133            s->sink = sink;
 134            s->merge_fn = merge_fn;
 135            qemu_irq *sources = qemu_allocate_irqs(qemu_irq_shared_handler, s,
 136                                                   num_sources);
 137            for (irq = first; irq; irq = irq->next) {
 138                if (irq->irq == sink) {
 139                    char *shared_irq_name = g_strdup_printf("shared-irq-%p",
 140                                                            *sources);
 141
 142                    if (irq->merge_fn != merge_fn) {
 143                        fprintf(stderr, "ERROR: inconsistent IRQ merge fns\n");
 144                        exit(1);
 145                    }
 146
 147                    object_property_add_child(OBJECT(irq->dev), shared_irq_name,
 148                                              OBJECT(*sources), &error_abort);
 149                    g_free(shared_irq_name);
 150                    irq->irq = *(sources++);
 151                    s->num++;
 152                }
 153            }
 154        }
 155        DB_PRINT(0, "%s: connected to %s irq line %d (%s)\n",
 156                 first->sink_info ? first->sink_info : "",
 157                 object_get_canonical_path(OBJECT(first->dev)),
 158                 first->i, first->name ? first->name : "");
 159
 160        qdev_connect_gpio_out_named(DEVICE(first->dev), first->name, first->i,
 161                                    first->irq);
 162        fdti->irqs = first->next;
 163        g_free(first);
 164    }
 165}
 166
 167FDTMachineInfo *fdt_generic_create_machine(void *fdt, qemu_irq *cpu_irq)
 168{
 169    char node_path[DT_PATH_LENGTH];
 170    QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL);
 171    FDTMachineInfo *fdti = fdt_init_new_fdti(fdt);
 172
 173    fdti->irq_base = cpu_irq;
 174
 175    fdt_serial_ports = 0;
 176
 177    /* parse the device tree */
 178    if (!qemu_devtree_get_root_node(fdt, node_path)) {
 179        memory_region_transaction_begin();
 180        fdt_init_set_opaque(fdti, node_path, NULL);
 181        simple_bus_fdt_init(node_path, fdti);
 182        while (qemu_co_enter_next(fdti->cq));
 183        fdt_init_all_irqs(fdti);
 184        memory_region_transaction_commit();
 185    } else {
 186        fprintf(stderr, "FDT: ERROR: cannot get root node from device tree %s\n"
 187            , node_path);
 188    }
 189
 190    DB_PRINT(0, "FDT: Device tree scan complete\n");
 191
 192    /* Set the number of CPUs */
 193    if (!qemu_opt_get_number(opts, "cpus", 0)) {
 194        smp_cpus = fdt_generic_num_cpus;
 195    }
 196
 197    DB_PRINT(0, "The value of smp_cpus is: %d\n", smp_cpus);
 198
 199    return fdti;
 200}
 201
 202struct FDTInitNodeArgs {
 203    char *node_path;
 204    char *parent_path;
 205    FDTMachineInfo *fdti;
 206};
 207
 208static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat);
 209
 210static void fdt_init_node(void *args)
 211{
 212    struct FDTInitNodeArgs *a = args;
 213    char *node_path = a->node_path;
 214    FDTMachineInfo *fdti = a->fdti;
 215    g_free(a);
 216
 217    simple_bus_fdt_init(node_path, fdti);
 218
 219    char *all_compats = NULL, *compat, *node_name, *next_compat;
 220    char *device_type = NULL;
 221    int compat_len;
 222
 223    DB_PRINT_NP(1, "enter\n");
 224
 225    /* try instance binding first */
 226    node_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
 227    DB_PRINT_NP(1, "node with name: %s\n", node_name ? node_name : "(none)");
 228    if (!node_name) {
 229        printf("FDT: ERROR: nameless node: %s\n", node_path);
 230    }
 231    if (!fdt_init_inst_bind(node_path, fdti, node_name)) {
 232        DB_PRINT_NP(0, "instance bind successful\n");
 233        goto exit;
 234    }
 235
 236    /* fallback to compatibility binding */
 237    all_compats = qemu_fdt_getprop(fdti->fdt, node_path, "compatible",
 238                                   &compat_len, false, NULL);
 239    if (!all_compats) {
 240        DB_PRINT_NP(0, "no compatibility found\n");
 241    }
 242
 243    for (compat = all_compats; compat && compat_len; compat = next_compat+1) {
 244        char *compat_prefixed = g_strdup_printf("compatible:%s", compat);
 245        if (!fdt_init_compat(node_path, fdti, compat_prefixed)) {
 246            goto exit;
 247        }
 248        g_free(compat_prefixed);
 249        if (!fdt_init_qdev(node_path, fdti, compat)) {
 250            goto exit;
 251        }
 252        next_compat = memchr(compat, '\0', DT_PATH_LENGTH);
 253        compat_len -= (next_compat + 1 - compat);
 254        if (compat_len > 0) {
 255            *next_compat = ' ';
 256        }
 257    }
 258
 259    device_type = qemu_fdt_getprop(fdti->fdt, node_path,
 260                                   "device_type", NULL, false, NULL);
 261    device_type = g_strdup_printf("device_type:%s", device_type);
 262    if (!fdt_init_compat(node_path, fdti, device_type)) {
 263        goto exit;
 264    }
 265
 266    /* Try to create the device using device_type property
 267     * Not every device tree node has compatible  property, so
 268     * try with device_type.
 269     */
 270    if (!fdt_init_qdev(node_path, fdti, device_type)) {
 271        goto exit;
 272    }
 273
 274    if (!all_compats) {
 275        goto exit;
 276    }
 277    DB_PRINT_NP(0, "FDT: Unsupported peripheral invalidated - "
 278                "compatibilities %s\n", all_compats);
 279    qemu_fdt_setprop_string(fdti->fdt, node_path, "compatible", "invalidated");
 280exit:
 281
 282    DB_PRINT_NP(1, "exit\n");
 283
 284    if (!fdt_init_has_opaque(fdti, node_path)) {
 285        fdt_init_set_opaque(fdti, node_path, NULL);
 286    }
 287    g_free(node_path);
 288    g_free(all_compats);
 289    g_free(device_type);
 290    return;
 291}
 292
 293static int simple_bus_fdt_init(char *node_path, FDTMachineInfo *fdti)
 294{
 295    int i;
 296    int num_children = qemu_devtree_get_num_children(fdti->fdt, node_path,
 297                                                        1);
 298    char **children = qemu_devtree_get_children(fdti->fdt, node_path, 1);
 299
 300    DB_PRINT_NP(num_children ? 0 : 1, "num child devices: %d\n", num_children);
 301
 302    for (i = 0; i < num_children; i++) {
 303        struct FDTInitNodeArgs *init_args = g_malloc0(sizeof(*init_args));
 304        init_args->node_path = children[i];
 305        init_args->fdti = fdti;
 306        qemu_coroutine_enter(qemu_coroutine_create(fdt_init_node, init_args));
 307    }
 308
 309    g_free(children);
 310    return 0;
 311}
 312
 313static qemu_irq fdt_get_gpio(FDTMachineInfo *fdti, char *node_path,
 314                             int* cur_cell, qemu_irq input,
 315                             const FDTGenericGPIOSet *gpio_set,
 316                             const char *debug_success, bool *end) {
 317    void *fdt = fdti->fdt;
 318    uint32_t parent_phandle, parent_cells = 0, cells[32];
 319    char parent_node_path[DT_PATH_LENGTH];
 320    DeviceState *parent;
 321    int i;
 322    Error *errp = NULL;
 323    const char *reason;
 324    bool free_reason = false;
 325    const char *propname = gpio_set->names->propname;
 326    const char *cells_propname = gpio_set->names->cells_propname;
 327
 328    cells[0] = 0;
 329
 330    parent_phandle = qemu_fdt_getprop_cell(fdt, node_path, propname,
 331                                           (*cur_cell)++, false, &errp);
 332    if (errp) {
 333        reason = g_strdup_printf("Cant get phandle from \"%s\" property\n",
 334                                 propname);
 335        *end = true;
 336        free_reason = true;
 337        goto fail_silent;
 338    }
 339    if (qemu_devtree_get_node_by_phandle(fdt, parent_node_path,
 340                                         parent_phandle)) {
 341        *end = true;
 342        reason = "cant get node from phandle\n";
 343        goto fail;
 344    }
 345    parent_cells = qemu_fdt_getprop_cell(fdt, parent_node_path,
 346                                         cells_propname, 0, false, &errp);
 347    if (errp) {
 348        *end = true;
 349        reason = g_strdup_printf("cant get the property \"%s\" from the " \
 350                                 "parent \"%s\"\n",
 351                                 cells_propname, parent_node_path);
 352        free_reason = true;
 353        goto fail;
 354    }
 355
 356    for (i = 0; i < parent_cells; ++i) {
 357        cells[i] = qemu_fdt_getprop_cell(fdt, node_path, propname,
 358                                         (*cur_cell)++, false, &errp);
 359        if (errp) {
 360            *end = true;
 361            reason = "cant get cell value";
 362            goto fail;
 363        }
 364    }
 365
 366    while (!fdt_init_has_opaque(fdti, parent_node_path)) {
 367        fdt_init_yield(fdti);
 368    }
 369    parent = DEVICE(fdt_init_get_opaque(fdti, parent_node_path));
 370
 371    if (!parent) {
 372        reason = "parent is not a device";
 373        goto fail_silent;
 374    }
 375
 376    while (!parent->realized) {
 377        fdt_init_yield(fdti);
 378    }
 379
 380    {
 381        const FDTGenericGPIOConnection *fgg_con = NULL;
 382        uint16_t range, idx;
 383        const char *gpio_name = NULL;
 384        qemu_irq ret;
 385
 386        if (object_dynamic_cast(OBJECT(parent), TYPE_FDT_GENERIC_GPIO)) {
 387            const FDTGenericGPIOSet *set;
 388            FDTGenericGPIOClass *parent_fggc =
 389                        FDT_GENERIC_GPIO_GET_CLASS(parent);
 390
 391            for (set = parent_fggc->controller_gpios; set && set->names;
 392                 set++) {
 393                if (!strcmp(gpio_set->names->cells_propname,
 394                            set->names->cells_propname)) {
 395                    fgg_con = set->gpios;
 396                    break;
 397                }
 398            }
 399        }
 400
 401        /* FIXME: cells[0] is not always the fdt indexing match system */
 402        idx = cells[0] & ~(1ul << 31);
 403        if (fgg_con) {
 404            range = fgg_con->range ? fgg_con->range : 1;
 405            while (!(idx >= fgg_con->fdt_index
 406                     && idx < (fgg_con->fdt_index + range))
 407                   && fgg_con->name) {
 408                fgg_con++;
 409            }
 410            if (!fgg_con) {
 411                goto fail;
 412            }
 413
 414            idx -= fgg_con->fdt_index;
 415            gpio_name = fgg_con->name;
 416        }
 417
 418        if (input) {
 419            FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
 420            bool (*merge_fn)(bool *, int) = qemu_irq_shared_or_handler;
 421
 422            /* FIXME: I am kind of stealing here. Use the msb of the first
 423             * cell to indicate the merge function. This needs to be discussed
 424             * with device-tree community on how this should be done properly.
 425             */
 426            if (cells[0] & (1 << 31)) {
 427                merge_fn = qemu_irq_shared_and_handler;
 428            }
 429
 430            DB_PRINT_NP(1, "%s GPIO output %s[%d] on %s\n", debug_success,
 431                        gpio_name ? gpio_name : "unnamed", idx,
 432                        parent_node_path);
 433            *irq = (FDTIRQConnection) {
 434                .dev = parent,
 435                .name = gpio_name,
 436                .merge_fn = merge_fn,
 437                .i = idx,
 438                .irq = input,
 439                .sink_info = NULL, /* FIMXE */
 440                .next = fdti->irqs
 441            };
 442            fdti->irqs = irq;
 443        }
 444        ret = qdev_get_gpio_in_named(parent, gpio_name, idx);
 445
 446        if (ret) {
 447            DB_PRINT_NP(1, "wiring GPIO input %s on %s ... \n",
 448                        fgg_con ? fgg_con->name : "unnamed", parent_node_path);
 449        }
 450        return ret;
 451    }
 452fail:
 453    fprintf(stderr, "%s Failed: %s\n", node_path, reason);
 454fail_silent:
 455    if (free_reason) {
 456        g_free((void *)reason);
 457    }
 458    return NULL;
 459}
 460
 461static void fdt_get_irq_info_from_intc(FDTMachineInfo *fdti, qemu_irq *ret,
 462                                       char *intc_node_path,
 463                                       uint32_t *cells, uint32_t num_cells,
 464                                       uint32_t max, Error **errp)
 465{
 466    FDTGenericIntcClass *intc_fdt_class;
 467    DeviceState *intc;
 468
 469    while (!fdt_init_has_opaque(fdti, intc_node_path)) {
 470        fdt_init_yield(fdti);
 471    }
 472    intc = DEVICE(fdt_init_get_opaque(fdti, intc_node_path));
 473
 474    if (!intc) {
 475        goto fail;
 476    }
 477
 478    while (!intc->realized) {
 479        fdt_init_yield(fdti);
 480    }
 481
 482    intc_fdt_class = FDT_GENERIC_INTC_GET_CLASS(intc);
 483    if (!intc_fdt_class) {
 484        goto fail;
 485    }
 486
 487    intc_fdt_class->get_irq(FDT_GENERIC_INTC(intc), ret, cells, num_cells,
 488                            max, errp);
 489
 490    return;
 491fail:
 492    error_setg(errp, "%s", __func__);
 493}
 494
 495static uint32_t imap_cache[4096];
 496static bool imap_cached = false;
 497
 498qemu_irq *fdt_get_irq_info(FDTMachineInfo *fdti, char *node_path, int irq_idx,
 499                          char *info, bool *map_mode) {
 500    void *fdt = fdti->fdt;
 501    uint32_t intc_phandle, intc_cells, cells[32];
 502    char intc_node_path[DT_PATH_LENGTH];
 503    qemu_irq *ret = NULL;
 504    int i;
 505    Error *errp = NULL;
 506
 507    intc_phandle = qemu_fdt_getprop_cell(fdt, node_path, "interrupt-parent",
 508                                         0, true, &errp);
 509    if (errp) {
 510        errp = NULL;
 511        intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
 512                                           "#interrupt-cells", 0, true, &errp);
 513        *map_mode = true;
 514    } else {
 515        if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
 516                                             intc_phandle)) {
 517            goto fail;
 518        }
 519
 520        /* Check if the device is using interrupt-maps */
 521        qemu_fdt_getprop_cell(fdt, node_path, "interrupt-map-mask", 0,
 522                              false, &errp);
 523        if (!errp) {
 524            errp = NULL;
 525            intc_cells = qemu_fdt_getprop_cell(fdt, node_path,
 526                                               "#interrupt-cells", 0,
 527                                               true, &errp);
 528            *map_mode = true;
 529        } else {
 530            errp = NULL;
 531            intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
 532                                               "#interrupt-cells", 0,
 533                                               true, &errp);
 534            *map_mode = false;
 535        }
 536    }
 537
 538    if (errp) {
 539        goto fail;
 540    }
 541
 542    DB_PRINT_NP(2, "%s intc_phandle: %d\n", node_path, intc_phandle);
 543
 544    for (i = 0; i < intc_cells; ++i) {
 545        cells[i] = qemu_fdt_getprop_cell(fdt, node_path, "interrupts",
 546                                         intc_cells * irq_idx + i, false, &errp);
 547        if (errp) {
 548            goto fail;
 549        }
 550    }
 551
 552    if (*map_mode) {
 553        int k;
 554        ret = g_new0(qemu_irq, 1);
 555        int num_matches = 0;
 556        int len;
 557        uint32_t imap_mask[intc_cells];
 558        uint32_t *imap_p;
 559        uint32_t *imap;
 560        bool use_parent = false;
 561
 562        for (k = 0; k < intc_cells; ++k) {
 563            imap_mask[k] = qemu_fdt_getprop_cell(fdt, node_path,
 564                                                 "interrupt-map-mask", k + 2,
 565                                                 true, &errp);
 566            if (errp) {
 567                goto fail;
 568            }
 569        }
 570
 571        /* Check if the device has an interrupt-map property */
 572        imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
 573                                  use_parent, &errp);
 574
 575        if (!imap || errp) {
 576            /* If the device doesn't have an interrupt-map, try again with
 577             * inheritance. This will return the parents interrupt-map
 578             */
 579            use_parent = true;
 580            errp = NULL;
 581
 582            imap_p = qemu_fdt_getprop(fdt, node_path, "interrupt-map",
 583                                      &len, use_parent, &errp);
 584            if (!imap_cached) {
 585                memcpy(imap_cache, imap_p, len);
 586                imap_cached = true;
 587            }
 588            imap = imap_cache;
 589
 590            if (errp) {
 591                goto fail;
 592            }
 593        }
 594
 595        len /= sizeof(uint32_t);
 596
 597        i = 0;
 598        assert(imap);
 599        while (i < len) {
 600            if (!use_parent) {
 601                /* Only re-sync the interrupt-map when the device has it's
 602                 * own map, to save time.
 603                 */
 604                imap = qemu_fdt_getprop(fdt, node_path, "interrupt-map", &len,
 605                                          use_parent, &errp);
 606
 607                if (errp) {
 608                    goto fail;
 609                }
 610
 611                len /= sizeof(uint32_t);
 612            }
 613
 614            bool match = true;
 615            uint32_t new_intc_cells, new_cells[32];
 616            i++; i++; /* FIXME: do address cells properly */
 617            for (k = 0; k < intc_cells; ++k) {
 618                uint32_t  map_val = be32_to_cpu(imap[i++]);
 619                if ((cells[k] ^ map_val) & imap_mask[k]) {
 620                    match = false;
 621                }
 622            }
 623            /* when caching, we hackishly store the number of cells for
 624             * the parent in the MSB. +1, so zero MSB means non cachd
 625             * and the full lookup is needed.
 626             */
 627            intc_phandle = be32_to_cpu(imap[i++]);
 628            if (intc_phandle & (0xffu << 24)) {
 629                new_intc_cells = (intc_phandle >> 24) - 1;
 630            } else {
 631                if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
 632                                                     intc_phandle)) {
 633                    goto fail;
 634                }
 635                new_intc_cells = qemu_fdt_getprop_cell(fdt, intc_node_path,
 636                                                       "#interrupt-cells", 0,
 637                                                       false, &errp);
 638                imap[i - 1] = cpu_to_be32(intc_phandle |
 639                                            (new_intc_cells + 1) << 24);
 640                if (errp) {
 641                    goto fail;
 642                }
 643            }
 644            for (k = 0; k < new_intc_cells; ++k) {
 645                new_cells[k] = be32_to_cpu(imap[i++]);
 646            }
 647            if (match) {
 648                num_matches++;
 649                ret = g_renew(qemu_irq, ret, num_matches + 1);
 650                if (intc_phandle & (0xffu << 24)) {
 651                    if (qemu_devtree_get_node_by_phandle(fdt, intc_node_path,
 652                                                         intc_phandle &
 653                                                         ((1 << 24) - 1))) {
 654                        goto fail;
 655                    }
 656                }
 657
 658                DB_PRINT_NP(2, "Getting IRQ information: %s -> 0x%x (%s)\n",
 659                            node_path, intc_phandle, intc_node_path);
 660
 661                memset(&ret[num_matches], 0, sizeof(*ret));
 662                fdt_get_irq_info_from_intc(fdti, &ret[num_matches-1], intc_node_path,
 663                                           new_cells, new_intc_cells, 1, &errp);
 664                if (info) {
 665                   sprintf(info, "%s", intc_node_path);
 666                   info += strlen(info) + 1;
 667                }
 668                if (errp) {
 669                    goto fail;
 670                }
 671            }
 672        }
 673        return ret;
 674    }
 675
 676    DB_PRINT_NP(2, "Getting IRQ information: %s -> %s\n",
 677                node_path, intc_node_path);
 678
 679    ret = g_new0(qemu_irq, fdt_generic_num_cpus + 2);
 680    fdt_get_irq_info_from_intc(fdti, ret, intc_node_path, cells, intc_cells,
 681                               fdt_generic_num_cpus, &errp);
 682
 683    if (errp) {
 684        goto fail;
 685    }
 686
 687    /* FIXME: Phase out this info bussiness */
 688    if (info) {
 689        sprintf(info, "%s", intc_node_path);
 690    }
 691
 692    return ret;
 693
 694fail:
 695    if (errp) {
 696        sprintf(info, "%s", error_get_pretty(errp));
 697    } else {
 698        sprintf(info, "(none)");
 699    }
 700    return NULL;
 701}
 702
 703qemu_irq *fdt_get_irq(FDTMachineInfo *fdti, char *node_path, int irq_idx,
 704                      bool *map_mode)
 705{
 706    return fdt_get_irq_info(fdti, node_path, irq_idx, NULL, map_mode);
 707}
 708
 709/* FIXME: figure out a real solution to this */
 710
 711#define DIGIT(a) ((a) >= '0' && (a) <= '9')
 712#define LOWER_CASE(a) ((a) >= 'a' && (a) <= 'z')
 713
 714static void trim_version(char *x)
 715{
 716    for (;;) {
 717        x = strchr(x, '-');
 718        if (!x) {
 719            return;
 720        }
 721        if (DIGIT(x[1])) {
 722            /* Try to trim Xilinx version suffix */
 723            char *p;
 724            if (strtol(x+1, &p, 0)) {
 725                p = p;  /* -Werror */
 726            }
 727            if ( *p == '.') {
 728                *x = 0;
 729                return;
 730            } else if ( *p == 0) {
 731                return;
 732            }
 733        } else if (x[1] == 'r' && x[3] == 'p') {
 734            /* Try to trim ARM version suffix */
 735            if (DIGIT(x[2]) && DIGIT(x[4])) {
 736                *x = 0;
 737                return;
 738            }
 739        }
 740        x++;
 741    }
 742}
 743
 744static void substitute_char(char *s, char a, char b)
 745{
 746    for (;;) {
 747        s = strchr(s, a);
 748        if (!s) {
 749            return;
 750        }
 751        *s = b;
 752        s++;
 753    }
 754}
 755
 756static inline const char *trim_vendor(const char *s)
 757{
 758    /* FIXME: be more intelligent */
 759    const char *ret = memchr(s, ',', strlen(s));
 760    return ret ? ret + 1 : s;
 761}
 762
 763static Object *fdt_create_from_compat(const char *compat, char **dev_type)
 764{
 765    Object *ret = NULL;
 766    char *c = g_strdup(compat);
 767
 768    /* Try to create the object */
 769    ret = object_new(c);
 770
 771    if (!ret) {
 772        /* Trim the version off the end and try again */
 773        trim_version(c);
 774        ret = object_new(c);
 775
 776        if (!ret) {
 777            /* Replace commas with full stops */
 778            substitute_char(c, ',', '.');
 779            ret = object_new(c);
 780        }
 781    }
 782
 783    if (!ret) {
 784        /* Restart with the orginal string and now replace commas with full stops
 785         * and try again. This means that versions are still included.
 786         */
 787        g_free(c);
 788        c = g_strdup(compat);
 789        substitute_char(c, ',', '.');
 790        ret = object_new(c);
 791    }
 792
 793    if (dev_type) {
 794        *dev_type = c;
 795    } else {
 796        g_free(c);
 797    }
 798
 799    if (!ret) {
 800        const char *no_vendor = trim_vendor(compat);
 801
 802        if (no_vendor != compat) {
 803            return fdt_create_from_compat(no_vendor, dev_type);
 804        }
 805    }
 806    return ret;
 807}
 808
 809/*FIXME: roll into device tree functionality */
 810
 811static inline uint64_t get_int_be(const void *p, int len)
 812{
 813    switch (len) {
 814    case 1:
 815        return *((uint8_t *)p);
 816    case 2:
 817        return be16_to_cpu(*((uint16_t *)p));
 818    case 4:
 819        return be32_to_cpu(*((uint32_t *)p));
 820    case 8:
 821        return be32_to_cpu(*((uint64_t *)p));
 822    default:
 823        fprintf(stderr, "unsupported integer length\n");
 824        abort();
 825    }
 826}
 827
 828/* FIXME: use structs instead of parallel arrays */
 829
 830static const char *fdt_generic_reg_size_prop_names[] = {
 831    "#address-cells",
 832    "#size-cells",
 833    "#bus-cells",
 834    "#priority-cells",
 835};
 836
 837static const int fdt_generic_reg_cells_defaults[] = {
 838    1,
 839    1,
 840    0,
 841    0,
 842};
 843
 844static int fdt_init_qdev(char *node_path, FDTMachineInfo *fdti, char *compat)
 845{
 846    Object *dev, *parent;
 847    char *dev_type = NULL;
 848    int is_intc;
 849    Error *errp = NULL;
 850    int i, j;
 851    QEMUDevtreeProp *prop, *props;
 852    char parent_node_path[DT_PATH_LENGTH];
 853    const FDTGenericGPIOSet *gpio_set = NULL;
 854    FDTGenericGPIOClass *fggc = NULL;
 855
 856    if (!compat) {
 857        return 1;
 858    }
 859    dev = fdt_create_from_compat(compat, &dev_type);
 860    if (!dev) {
 861        DB_PRINT_NP(1, "no match found for %s\n", compat);
 862        return 1;
 863    }
 864    DB_PRINT_NP(1, "matched compat %s\n", compat);
 865
 866    /* Do this super early so fdt_generic_num_cpus is correct ASAP */
 867    if (object_dynamic_cast(dev, TYPE_CPU)) {
 868        fdt_generic_num_cpus++;
 869        DB_PRINT_NP(0, "is a CPU - total so far %d\n", fdt_generic_num_cpus);
 870    }
 871
 872    if (qemu_devtree_getparent(fdti->fdt, parent_node_path, node_path)) {
 873        abort();
 874    }
 875    while (!fdt_init_has_opaque(fdti, parent_node_path)) {
 876        fdt_init_yield(fdti);
 877    }
 878    parent = fdt_init_get_opaque(fdti, parent_node_path);
 879    if (dev->parent) {
 880        DB_PRINT_NP(0, "Node already parented - skipping node\n");
 881    } else if (parent) {
 882        DB_PRINT_NP(1, "parenting node\n");
 883        object_property_add_child(OBJECT(parent),
 884                              qemu_devtree_get_node_name(fdti->fdt, node_path),
 885                              OBJECT(dev), NULL);
 886        if (object_dynamic_cast(dev, TYPE_DEVICE)) {
 887            Object *parent_bus = parent;
 888            unsigned int depth = 0;
 889
 890            DB_PRINT_NP(1, "bus parenting node\n");
 891            /* Look for an FDT ancestor that is a Bus.  */
 892            while (parent_bus && !object_dynamic_cast(parent_bus, TYPE_BUS)) {
 893                /*
 894                 * Assert against insanely deep hierarchies which are an
 895                 * indication of loops.
 896                 */
 897                assert(depth < 4096);
 898
 899                parent_bus = parent_bus->parent;
 900                depth++;
 901            }
 902
 903            if (!parent_bus
 904                && object_dynamic_cast(OBJECT(dev), TYPE_SYS_BUS_DEVICE)) {
 905                /*
 906                 * Didn't find any bus. Use the default sysbus one.
 907                 * This allows ad-hoc busses belonging to sysbus devices to be
 908                 * visible to -device bus=x.
 909                 */
 910                parent_bus = OBJECT(sysbus_get_default());
 911            }
 912
 913            if (parent_bus) {
 914                qdev_set_parent_bus(DEVICE(dev), BUS(parent_bus));
 915            }
 916        }
 917    } else {
 918        DB_PRINT_NP(1, "orphaning node\n");
 919        /* FIXME: Make this go away (centrally) */
 920        object_property_add_child(
 921                              object_get_root(),
 922                              qemu_devtree_get_node_name(fdti->fdt, node_path),
 923                              OBJECT(dev), NULL);
 924    }
 925    fdt_init_set_opaque(fdti, node_path, dev);
 926
 927    /* Set the default sync-quantum based on the global one. Node properties
 928     * in the dtb can later override this value.  */
 929    if (global_sync_quantum) {
 930        ObjectProperty *p;
 931
 932        p = object_property_find(OBJECT(dev), "sync-quantum", NULL);
 933        if (p) {
 934            object_property_set_int(OBJECT(dev), global_sync_quantum,
 935                                    "sync-quantum", &errp);
 936        }
 937    }
 938
 939    props = qemu_devtree_get_props(fdti->fdt, node_path);
 940    for (prop = props; prop->name; prop++) {
 941        const char *propname = trim_vendor(prop->name);
 942        int len = prop->len;
 943        void *val = prop->value;
 944
 945        ObjectProperty *p = object_property_find(OBJECT(dev), propname, NULL);
 946        if (p) {
 947            DB_PRINT_NP(1, "matched property: %s of type %s, len %d\n",
 948                                            propname, p->type, prop->len);
 949        }
 950        if (!p) {
 951            continue;
 952        }
 953
 954        if (!strcmp(propname, "type")) {
 955            continue;
 956        }
 957
 958        /* FIXME: handle generically using accessors and stuff */
 959        if (!strcmp(p->type, "uint8") || !strcmp(p->type, "uint16") ||
 960                !strcmp(p->type, "uint32") || !strcmp(p->type, "uint64")) {
 961            object_property_set_int(OBJECT(dev), get_int_be(val, len), propname,
 962                                    &error_abort);
 963            DB_PRINT_NP(0, "set property %s to %#llx\n", propname,
 964                        (unsigned long long)get_int_be(val, len));
 965        } else if (!strcmp(p->type, "boolean") || !strcmp(p->type, "bool")) {
 966            object_property_set_bool(OBJECT(dev), !!get_int_be(val, len),
 967                                     propname, &error_abort);
 968            DB_PRINT_NP(0, "set property %s to %s\n", propname,
 969                        get_int_be(val, len) ? "true" : "false");
 970        } else if (!strcmp(p->type, "string") || !strcmp(p->type, "str")) {
 971            object_property_set_str(OBJECT(dev), (const char *)val, propname,
 972                                    &error_abort);
 973            DB_PRINT_NP(0, "set property %s to %s\n", propname,
 974                        (const char *)val);
 975        } else if (!strncmp(p->type, "link", 4)) {
 976            char target_node_path[DT_PATH_LENGTH];
 977            char propname_target[1024];
 978            strcpy(propname_target, propname);
 979            strcat(propname_target, "-target");
 980
 981            Object *linked_dev, *proxy;
 982
 983            if (qemu_devtree_get_node_by_phandle(fdti->fdt, target_node_path,
 984                                                get_int_be(val, len))) {
 985                abort();
 986            }
 987            while (!fdt_init_has_opaque(fdti, target_node_path)) {
 988                fdt_init_yield(fdti);
 989            }
 990            linked_dev = fdt_init_get_opaque(fdti, target_node_path);
 991
 992            proxy = linked_dev ? object_property_get_link(linked_dev,
 993                                                          propname_target,
 994                                                          &errp) : NULL;
 995            if (!errp && proxy) {
 996                DB_PRINT_NP(0, "detected proxy object for %s connection\n",
 997                            propname);
 998                linked_dev = proxy;
 999            }
1000            errp = NULL;
1001            if (linked_dev) {
1002                object_property_set_link(OBJECT(dev), linked_dev, propname,
1003                                         &errp);
1004                if (errp) {
1005                    /* Unable to set the property, maybe it is a memory
1006                     * alias?
1007                     */
1008                    MemoryRegion *alias_mr;
1009                    int offset = len / 2;
1010                    alias_mr =
1011                        sysbus_mmio_get_region(SYS_BUS_DEVICE(linked_dev),
1012                                               get_int_be(val + offset,
1013                                                          len - offset));
1014
1015                    object_property_set_link(OBJECT(dev), OBJECT(alias_mr),
1016                                             propname, &error_abort);
1017
1018                    errp = NULL;
1019                }
1020                DB_PRINT_NP(0, "set link %s\n", propname);
1021            }
1022        } else {
1023            DB_PRINT_NP(0, "WARNING: property is of unknown type\n");
1024        }
1025    }
1026
1027    /* FIXME: not pretty, but is half a sane dts binding */
1028    if (object_dynamic_cast(dev, TYPE_REMOTE_PORT_DEVICE)) {
1029        int i;
1030
1031        for (i = 0;;++i) {
1032            char adaptor_node_path[DT_PATH_LENGTH];
1033            uint32_t adaptor_phandle, chan;
1034            DeviceState *adaptor;
1035            char *name;
1036
1037            adaptor_phandle = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1038                                                    "remote-ports",
1039                                                    2 * i, false, &errp);
1040            if (errp) {
1041                DB_PRINT_NP(1, "cant get phandle from \"remote-ports\" "
1042                            "property\n");
1043                break;
1044            }
1045            if (qemu_devtree_get_node_by_phandle(fdti->fdt, adaptor_node_path,
1046                                                 adaptor_phandle)) {
1047                DB_PRINT_NP(1, "cant get node from phandle\n");
1048                break;
1049            }
1050            adaptor = DEVICE(fdt_init_get_opaque(fdti, adaptor_node_path));
1051            name = g_strdup_printf("rp-adaptor%" PRId32, i);
1052            object_property_set_link(OBJECT(dev), OBJECT(adaptor), name, &errp);
1053            DB_PRINT_NP(0, "connecting RP to adaptor %s channel %d",
1054                        object_get_canonical_path(OBJECT(adaptor)), i);
1055            g_free(name);
1056            if (errp) {
1057                DB_PRINT_NP(1, "cant set adaptor link for device property\n");
1058                break;
1059            }
1060
1061            chan = qemu_fdt_getprop_cell(fdti->fdt, node_path, "remote-ports",
1062                                         2 * i + 1, false, &errp);
1063            if (errp) {
1064                DB_PRINT_NP(1, "cant get channel from \"remote-ports\" "
1065                            "property\n");
1066                break;
1067            }
1068
1069            name = g_strdup_printf("rp-chan%" PRId32, i);
1070            object_property_set_int(OBJECT(dev), chan, name, &errp);
1071            /* Not critical - device has right to not care about channel
1072             * numbers if its a pure slave (only responses).
1073             */
1074            if (errp) {
1075                DB_PRINT_NP(1, "cant set %s property %s\n", name, error_get_pretty(errp));
1076                errp = NULL;
1077            }
1078            g_free(name);
1079
1080            name = g_strdup_printf("remote-port-dev%d", chan);
1081            object_property_set_link(OBJECT(adaptor), OBJECT(dev), name,
1082                                     &errp);
1083            g_free(name);
1084            if (errp) {
1085                DB_PRINT_NP(1, "cant set device link for adaptor\n");
1086                break;
1087            }
1088        }
1089        errp = NULL;
1090    }
1091
1092    if (object_dynamic_cast(dev, TYPE_DEVICE)) {
1093        DeviceClass *dc = DEVICE_GET_CLASS(dev);
1094        /* connect nic if appropriate */
1095        static int nics;
1096        const char *short_name = qemu_devtree_get_node_name(fdti->fdt, node_path);
1097
1098        if (object_property_find(OBJECT(dev), "mac", NULL) &&
1099                    object_property_find(OBJECT(dev), "netdev", NULL)) {
1100            qdev_set_nic_properties(DEVICE(dev), &nd_table[nics]);
1101        }
1102        if (nd_table[nics].instantiated) {
1103            DB_PRINT_NP(0, "NIC instantiated: %s\n", dev_type);
1104            nics++;
1105        }
1106
1107        /* We don't want to connect remote port chardev's to the user facing
1108         * serial devices.
1109         */
1110        if (!object_dynamic_cast(dev, TYPE_REMOTE_PORT)) {
1111            /* Connect chardev if we can */
1112            if (fdt_serial_ports < MAX_SERIAL_PORTS && serial_hds[fdt_serial_ports]) {
1113                CharDriverState *value = (CharDriverState*) serial_hds[fdt_serial_ports];
1114
1115                object_property_set_str(dev, value->label, "chardev", &errp);
1116                if (!errp) {
1117                    /* It worked, the device is a charecter device */
1118                    fdt_serial_ports++;
1119                }
1120
1121                errp = NULL;
1122            }
1123        }
1124
1125        /* We also need to externally connect drives. Let's try to do that
1126         * here. Don't use drive_get_next() as it always increments the
1127         * next_block_unit variable.
1128         */
1129        object_property_find(OBJECT(dev), "drive", &errp);
1130        if (errp == NULL) {
1131            DriveInfo *dinfo = drive_get_next(IF_MTD);
1132            if (dinfo) {
1133                qdev_prop_set_drive(DEVICE(dev), "drive",
1134                                    blk_by_legacy_dinfo(dinfo), &error_abort);
1135            }
1136        }
1137        errp = NULL;
1138
1139        /* Regular TYPE_DEVICE houskeeping */
1140        DB_PRINT_NP(0, "Short naming node: %s\n", short_name);
1141        (DEVICE(dev))->id = g_strdup(short_name);
1142        qdev_init_nofail(DEVICE(dev));
1143        qemu_register_reset((void (*)(void *))dc->reset, dev);
1144    }
1145
1146    if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE) || 
1147        object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1148        FDTGenericRegPropInfo reg = {0};
1149        char parent_path[DT_PATH_LENGTH];
1150        int cell_idx = 0;
1151        bool extended = true;
1152
1153        qemu_fdt_getprop_cell(fdti->fdt, node_path, "reg-extended", 0, false,
1154                              &errp);
1155        if (errp) {
1156            error_free(errp);
1157            errp = NULL;
1158            extended = false;
1159            qemu_devtree_getparent(fdti->fdt, parent_path, node_path);
1160        }
1161
1162        for (reg.n = 0;; reg.n++) {
1163            char ph_parent[DT_PATH_LENGTH];
1164            const char *pnp = parent_path;
1165
1166            reg.parents = g_renew(Object *, reg.parents, reg.n + 1);
1167            reg.parents[reg.n] = parent;
1168
1169            if (extended) {
1170                int p_ph = qemu_fdt_getprop_cell(fdti->fdt, node_path,
1171                                                 "reg-extended", cell_idx++,
1172                                                 false, &errp);
1173                if (errp) {
1174                    error_free(errp);
1175                    errp = NULL;
1176                    goto exit_reg_parse;
1177                }
1178                if (qemu_devtree_get_node_by_phandle(fdti->fdt, ph_parent,
1179                                                     p_ph)) {
1180                    goto exit_reg_parse;
1181                }
1182                while (!fdt_init_has_opaque(fdti, ph_parent)) {
1183                    fdt_init_yield(fdti);
1184                }
1185                reg.parents[reg.n] = fdt_init_get_opaque(fdti, ph_parent);
1186                pnp = ph_parent;
1187            }
1188
1189            for (i = 0; i < FDT_GENERIC_REG_TUPLE_LENGTH; ++i) {
1190                const char *size_prop_name = fdt_generic_reg_size_prop_names[i];
1191                int nc = qemu_fdt_getprop_cell(fdti->fdt, pnp, size_prop_name,
1192                                               0, true, &errp);
1193
1194                if (errp) {
1195                    int size_default = fdt_generic_reg_cells_defaults[i];
1196
1197                    DB_PRINT_NP(0, "WARNING: no %s for %s container, assuming "
1198                                "default of %d\n", size_prop_name, pnp,
1199                                size_default);
1200                    nc = size_default;
1201                    error_free(errp);
1202                    errp = NULL;
1203                }
1204                
1205                reg.x[i] = g_renew(uint64_t, reg.x[i], reg.n + 1);
1206                reg.x[i][reg.n] = nc ?
1207                    qemu_fdt_getprop_sized_cell(fdti->fdt, node_path,
1208                                                extended ? "reg-extended"
1209                                                         : "reg",
1210                                                cell_idx, nc, &errp)
1211                    : 0;
1212                cell_idx += nc;
1213                if (errp) {
1214                    goto exit_reg_parse;
1215                }
1216            }
1217        }
1218exit_reg_parse:
1219
1220        if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_MMAP)) {
1221            FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_GET_CLASS(dev);
1222            if (fmc->parse_reg) {
1223                while (fmc->parse_reg(FDT_GENERIC_MMAP(dev), reg,
1224                                      &error_abort)) {
1225                    fdt_init_yield(fdti);
1226                }
1227            }
1228        }
1229    }
1230    
1231    if (object_dynamic_cast(dev, TYPE_SYS_BUS_DEVICE)) {
1232        {
1233            int len;
1234            fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1235                                    "interrupt-controller", &len);
1236            is_intc = len >= 0;
1237            DB_PRINT_NP(is_intc ? 0 : 1, "is interrupt controller: %c\n",
1238                        is_intc ? 'y' : 'n');
1239        }
1240        /* connect irq */
1241        j = 0;
1242        for (i = 0;; i++) {
1243            char irq_info[1024];
1244            char *irq_info_p = irq_info;
1245            bool map_mode;
1246            int len = -1;
1247            qemu_irq *irqs = fdt_get_irq_info(fdti, node_path, i, irq_info,
1248                                              &map_mode);
1249            /* INTCs inferr their top level, if no IRQ connection specified */
1250            fdt_get_property(fdti->fdt, fdt_path_offset(fdti->fdt, node_path),
1251                             "interrupts-extended", &len);
1252            if (!irqs && is_intc && i == 0 && len <= 0) {
1253                FDTGenericIntc *id = (FDTGenericIntc *)object_dynamic_cast(
1254                                        dev, TYPE_FDT_GENERIC_INTC);
1255                FDTGenericIntcClass *idc = FDT_GENERIC_INTC_GET_CLASS(id);
1256                if (id && idc->auto_parent) {
1257                    Error *err = NULL;
1258                    idc->auto_parent(id, &err);
1259                } else {
1260                    irqs = fdti->irq_base;
1261                }
1262            }
1263            if (!irqs) {
1264                break;
1265            }
1266            while (*irqs) {
1267                FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1268                *irq = (FDTIRQConnection) {
1269                    .dev = DEVICE(dev),
1270                    .name = SYSBUS_DEVICE_GPIO_IRQ,
1271                    .merge_fn = qemu_irq_shared_or_handler,
1272                    .i = j,
1273                    .irq = *irqs,
1274                    .sink_info = g_strdup(irq_info_p),
1275                    .next = fdti->irqs
1276                };
1277                if (!map_mode) {
1278                    j++;
1279                } else {
1280                    irq_info_p += strlen(irq_info_p) + 1;
1281                }
1282                fdti->irqs = irq;
1283                irqs++;
1284            }
1285            if (map_mode) {
1286                j++;
1287            }
1288        }
1289    }
1290
1291    if (object_dynamic_cast(dev, TYPE_FDT_GENERIC_GPIO)) {
1292        fggc = FDT_GENERIC_GPIO_GET_CLASS(dev);
1293        gpio_set = fggc->client_gpios;
1294    }
1295
1296    if (!gpio_set) {
1297        gpio_set = default_gpio_sets;
1298    }
1299
1300    for (; object_dynamic_cast(dev, TYPE_DEVICE) && gpio_set->names;
1301           gpio_set++) {
1302        bool end = false;
1303        int cur_cell = 0;
1304
1305        for (i = 0; !end; i++) {
1306            char *debug_success;
1307            const FDTGenericGPIOConnection *c = gpio_set->gpios;
1308            const char *gpio_name = NULL;
1309            uint16_t named_idx = 0;
1310            qemu_irq input, output;
1311            memset(&input, 0, sizeof(input));
1312
1313            if (c) {
1314                uint16_t range = c->range ? c->range : 1;
1315                while ((c->fdt_index > i || c->fdt_index + range <= i)
1316                       && c->name) {
1317                    c++;
1318                }
1319                named_idx = i - c->fdt_index;
1320                gpio_name = c->name;
1321            }
1322            if (!gpio_name) {
1323                const char *names_propname = gpio_set->names->names_propname;
1324                gpio_name = qemu_fdt_getprop_string(fdti->fdt, node_path,
1325                                                    names_propname, i, false,
1326                                                    NULL);
1327            }
1328            if (!gpio_name) {
1329                input = qdev_get_gpio_in(DEVICE(dev), i);
1330            } else {
1331                input = qdev_get_gpio_in_named(DEVICE(dev), gpio_name,
1332                                               named_idx);
1333            }
1334            debug_success = g_strdup_printf("Wiring GPIO input %s[%" PRId16 "] "
1335                                            "to", gpio_name, named_idx);
1336            output = fdt_get_gpio(fdti, node_path, &cur_cell, input, gpio_set,
1337                                  debug_success, &end);
1338            g_free(debug_success);
1339            if (output) {
1340                FDTIRQConnection *irq = g_new0(FDTIRQConnection, 1);
1341                *irq = (FDTIRQConnection) {
1342                    .dev = DEVICE(dev),
1343                    .name = gpio_name,
1344                    .merge_fn = qemu_irq_shared_or_handler,
1345                    .i = named_idx,
1346                    .irq = output,
1347                    .sink_info = NULL, /*FIXME */
1348                    .next = fdti->irqs
1349                };
1350                fdti->irqs = irq;
1351                DB_PRINT_NP(1, "... GPIO output %s[%" PRId16 "]\n", gpio_name,
1352                            named_idx);
1353            }
1354        }
1355    }
1356
1357    if (dev_type) {
1358        g_free(dev_type);
1359    }
1360
1361    return 0;
1362}
1363
1364static const TypeInfo fdt_generic_intc_info = {
1365    .name          = TYPE_FDT_GENERIC_INTC,
1366    .parent        = TYPE_INTERFACE,
1367    .class_size = sizeof(FDTGenericIntcClass),
1368};
1369
1370static const TypeInfo fdt_generic_mmap_info = {
1371    .name          = TYPE_FDT_GENERIC_MMAP,
1372    .parent        = TYPE_INTERFACE,
1373    .class_size = sizeof(FDTGenericMMapClass),
1374};
1375
1376static const TypeInfo fdt_generic_gpio_info = {
1377    .name          = TYPE_FDT_GENERIC_GPIO,
1378    .parent        = TYPE_INTERFACE,
1379    .class_size = sizeof(FDTGenericGPIOClass),
1380};
1381
1382static void fdt_generic_intc_register_types(void)
1383{
1384    type_register_static(&fdt_generic_intc_info);
1385    type_register_static(&fdt_generic_mmap_info);
1386    type_register_static(&fdt_generic_gpio_info);
1387}
1388
1389type_init(fdt_generic_intc_register_types)
1390