static int vio_make_devnode(VIOsPAPRDevice *dev,

                            void *fdt)

{

    VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);

    int vdevice_off, node_off, ret;

    char *dt_name;



    vdevice_off = fdt_path_offset(fdt, "/vdevice");

    if (vdevice_off < 0) {

        return vdevice_off;

    }



    dt_name = vio_format_dev_name(dev);

    if (!dt_name) {

        return -ENOMEM;

    }



    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);

    free(dt_name);

    if (node_off < 0) {

        return node_off;

    }



    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);

    if (ret < 0) {

        return ret;

    }



    if (pc->dt_type) {

        ret = fdt_setprop_string(fdt, node_off, "device_type",

                                 pc->dt_type);

        if (ret < 0) {

            return ret;

        }

    }



    if (pc->dt_compatible) {

        ret = fdt_setprop_string(fdt, node_off, "compatible",

                                 pc->dt_compatible);

        if (ret < 0) {

            return ret;

        }

    }



    if (dev->qirq) {

        uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0};



        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,

                          sizeof(ints_prop));

        if (ret < 0) {

            return ret;

        }

    }



    if (dev->rtce_window_size) {

        uint32_t dma_prop[] = {cpu_to_be32(dev->reg),

                               0, 0,

                               0, cpu_to_be32(dev->rtce_window_size)};



        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);

        if (ret < 0) {

            return ret;

        }



        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);

        if (ret < 0) {

            return ret;

        }



        ret = fdt_setprop(fdt, node_off, "ibm,my-dma-window", dma_prop,

                          sizeof(dma_prop));

        if (ret < 0) {

            return ret;

        }

    }



    if (pc->devnode) {

        ret = (pc->devnode)(dev, fdt, node_off);

        if (ret < 0) {

            return ret;

        }

    }



    return node_off;

}
