static int nvme_init(PCIDevice *pci_dev)

{

    NvmeCtrl *n = NVME(pci_dev);

    NvmeIdCtrl *id = &n->id_ctrl;



    int i;

    int64_t bs_size;

    uint8_t *pci_conf;



    if (!(n->conf.bs)) {

        return -1;

    }



    bs_size = bdrv_getlength(n->conf.bs);

    if (bs_size < 0) {

        return -1;

    }



    blkconf_serial(&n->conf, &n->serial);

    if (!n->serial) {

        return -1;

    }



    pci_conf = pci_dev->config;

    pci_conf[PCI_INTERRUPT_PIN] = 1;

    pci_config_set_prog_interface(pci_dev->config, 0x2);

    pci_config_set_class(pci_dev->config, PCI_CLASS_STORAGE_EXPRESS);

    pcie_endpoint_cap_init(&n->parent_obj, 0x80);



    n->num_namespaces = 1;

    n->num_queues = 64;

    n->reg_size = 1 << qemu_fls(0x1004 + 2 * (n->num_queues + 1) * 4);

    n->ns_size = bs_size / (uint64_t)n->num_namespaces;



    n->namespaces = g_new0(NvmeNamespace, n->num_namespaces);

    n->sq = g_new0(NvmeSQueue *, n->num_queues);

    n->cq = g_new0(NvmeCQueue *, n->num_queues);



    memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n,

                          "nvme", n->reg_size);

    pci_register_bar(&n->parent_obj, 0,

        PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64,

        &n->iomem);

    msix_init_exclusive_bar(&n->parent_obj, n->num_queues, 4);



    id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));

    id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));

    strpadcpy((char *)id->mn, sizeof(id->mn), "QEMU NVMe Ctrl", ' ');

    strpadcpy((char *)id->fr, sizeof(id->fr), "1.0", ' ');

    strpadcpy((char *)id->sn, sizeof(id->sn), n->serial, ' ');

    id->rab = 6;

    id->ieee[0] = 0x00;

    id->ieee[1] = 0x02;

    id->ieee[2] = 0xb3;

    id->oacs = cpu_to_le16(0);

    id->frmw = 7 << 1;

    id->lpa = 1 << 0;

    id->sqes = (0x6 << 4) | 0x6;

    id->cqes = (0x4 << 4) | 0x4;

    id->nn = cpu_to_le32(n->num_namespaces);

    id->psd[0].mp = cpu_to_le16(0x9c4);

    id->psd[0].enlat = cpu_to_le32(0x10);

    id->psd[0].exlat = cpu_to_le32(0x4);



    n->bar.cap = 0;

    NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);

    NVME_CAP_SET_CQR(n->bar.cap, 1);

    NVME_CAP_SET_AMS(n->bar.cap, 1);

    NVME_CAP_SET_TO(n->bar.cap, 0xf);

    NVME_CAP_SET_CSS(n->bar.cap, 1);



    n->bar.vs = 0x00010001;

    n->bar.intmc = n->bar.intms = 0;



    for (i = 0; i < n->num_namespaces; i++) {

        NvmeNamespace *ns = &n->namespaces[i];

        NvmeIdNs *id_ns = &ns->id_ns;

        id_ns->nsfeat = 0;

        id_ns->nlbaf = 0;

        id_ns->flbas = 0;

        id_ns->mc = 0;

        id_ns->dpc = 0;

        id_ns->dps = 0;

        id_ns->lbaf[0].ds = BDRV_SECTOR_BITS;

        id_ns->ncap  = id_ns->nuse = id_ns->nsze =

            cpu_to_le64(n->ns_size >>

                id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas)].ds);

    }

    return 0;

}
