2 * QEMU NVM Express Subsystem: nvme-subsys
4 * Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
6 * This code is licensed under the GNU GPL v2. Refer COPYING.
9 #include "qemu/units.h"
10 #include "qemu/osdep.h"
11 #include "qemu/uuid.h"
13 #include "qemu/cutils.h"
14 #include "qapi/error.h"
15 #include "hw/qdev-properties.h"
16 #include "hw/qdev-core.h"
17 #include "hw/block/block.h"
18 #include "block/aio.h"
19 #include "block/accounting.h"
20 #include "sysemu/sysemu.h"
21 #include "hw/pci/pci.h"
23 #include "nvme-subsys.h"
25 int nvme_subsys_register_ctrl(NvmeCtrl
*n
, Error
**errp
)
27 NvmeSubsystem
*subsys
= n
->subsys
;
30 for (cntlid
= 0; cntlid
< ARRAY_SIZE(subsys
->ctrls
); cntlid
++) {
31 if (!subsys
->ctrls
[cntlid
]) {
36 if (cntlid
== ARRAY_SIZE(subsys
->ctrls
)) {
37 error_setg(errp
, "no more free controller id");
41 subsys
->ctrls
[cntlid
] = n
;
46 int nvme_subsys_register_ns(NvmeNamespace
*ns
, Error
**errp
)
48 NvmeSubsystem
*subsys
= ns
->subsys
;
50 uint32_t nsid
= nvme_nsid(ns
);
53 assert(nsid
&& nsid
<= NVME_SUBSYS_MAX_NAMESPACES
);
55 if (subsys
->namespaces
[nsid
]) {
56 error_setg(errp
, "namespace %d already registerd to subsy %s",
57 nvme_nsid(ns
), subsys
->parent_obj
.id
);
61 subsys
->namespaces
[nsid
] = ns
;
63 for (i
= 0; i
< ARRAY_SIZE(subsys
->ctrls
); i
++) {
66 if (n
&& nvme_register_namespace(n
, ns
, errp
)) {
74 static void nvme_subsys_setup(NvmeSubsystem
*subsys
)
76 const char *nqn
= subsys
->params
.nqn
?
77 subsys
->params
.nqn
: subsys
->parent_obj
.id
;
79 snprintf((char *)subsys
->subnqn
, sizeof(subsys
->subnqn
),
80 "nqn.2019-08.org.qemu:%s", nqn
);
83 static void nvme_subsys_realize(DeviceState
*dev
, Error
**errp
)
85 NvmeSubsystem
*subsys
= NVME_SUBSYS(dev
);
87 nvme_subsys_setup(subsys
);
90 static Property nvme_subsystem_props
[] = {
91 DEFINE_PROP_STRING("nqn", NvmeSubsystem
, params
.nqn
),
92 DEFINE_PROP_END_OF_LIST(),
95 static void nvme_subsys_class_init(ObjectClass
*oc
, void *data
)
97 DeviceClass
*dc
= DEVICE_CLASS(oc
);
99 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
101 dc
->realize
= nvme_subsys_realize
;
102 dc
->desc
= "Virtual NVMe subsystem";
104 device_class_set_props(dc
, nvme_subsystem_props
);
107 static const TypeInfo nvme_subsys_info
= {
108 .name
= TYPE_NVME_SUBSYS
,
109 .parent
= TYPE_DEVICE
,
110 .class_init
= nvme_subsys_class_init
,
111 .instance_size
= sizeof(NvmeSubsystem
),
114 static void nvme_subsys_register_types(void)
116 type_register_static(&nvme_subsys_info
);
119 type_init(nvme_subsys_register_types
)