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