2 * Copyright (c) 2011, Bryan Venteicher <bryanv@daemoninthecloset.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sys/dev/virtio/virtio.c,v 1.1 2011/11/18 05:43:43 grehan Exp $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/malloc.h>
33 #include <sys/module.h>
36 #include <machine/inttypes.h>
38 #include <sys/serialize.h>
42 #include "virtqueue.h"
44 #include "virtio_bus_if.h"
46 static int virtio_modevent(module_t
, int, void *);
47 static const char *virtio_feature_name(uint64_t, struct virtio_feature_desc
*);
49 static struct virtio_ident
{
52 } virtio_ident_table
[] = {
53 { VIRTIO_ID_NETWORK
, "Network" },
54 { VIRTIO_ID_BLOCK
, "Block" },
55 { VIRTIO_ID_CONSOLE
, "Console" },
56 { VIRTIO_ID_ENTROPY
, "Entropy" },
57 { VIRTIO_ID_BALLOON
, "Balloon" },
58 { VIRTIO_ID_IOMEMORY
, "IOMemory" },
59 { VIRTIO_ID_SCSI
, "SCSI" },
60 { VIRTIO_ID_9P
, "9P Transport" },
65 /* Device independent features. */
66 static struct virtio_feature_desc virtio_common_feature_desc
[] = {
67 { VIRTIO_F_NOTIFY_ON_EMPTY
, "NotifyOnEmpty" },
68 { VIRTIO_F_ANY_LAYOUT
, "AnyLayout" },
69 { VIRTIO_RING_F_INDIRECT_DESC
, "RingIndirect" },
70 { VIRTIO_RING_F_EVENT_IDX
, "EventIdx" },
71 { VIRTIO_F_BAD_FEATURE
, "BadFeature" },
77 virtio_device_name(uint16_t devid
)
79 struct virtio_ident
*ident
;
81 for (ident
= virtio_ident_table
; ident
->name
!= NULL
; ident
++) {
82 if (ident
->devid
== devid
)
90 virtio_get_device_type(device_t dev
)
96 BUS_READ_IVAR(device_get_parent(dev
), dev
,
97 VIRTIO_IVAR_DEVTYPE
, &devtype
);
99 return ((int) devtype
);
103 virtio_set_feature_desc(device_t dev
,
104 struct virtio_feature_desc
*feature_desc
)
107 BUS_WRITE_IVAR(device_get_parent(dev
), dev
,
108 VIRTIO_IVAR_FEATURE_DESC
, (uintptr_t) feature_desc
);
112 virtio_describe(device_t dev
, const char *msg
,
113 uint64_t features
, struct virtio_feature_desc
*desc
)
121 if ((buf
= kmalloc(512, M_TEMP
, M_INTWAIT
)) == NULL
) {
122 device_printf(dev
, "%s features: 0x%"PRIx64
"\n", msg
,
127 sbuf_new(&sb
, buf
, 512, SBUF_FIXEDLEN
);
128 sbuf_printf(&sb
, "%s features: 0x%"PRIx64
, msg
, features
);
130 for (n
= 0, val
= 1ULL << 63; val
!= 0; val
>>= 1) {
132 * BAD_FEATURE is used to detect broken Linux clients
133 * and therefore is not applicable to FreeBSD.
135 if (((features
& val
) == 0) || val
== VIRTIO_F_BAD_FEATURE
)
143 name
= virtio_feature_name(val
, desc
);
145 sbuf_printf(&sb
, "%#jx", (uintmax_t) val
);
153 if (sbuf_finish(&sb
) == 0)
154 device_printf(dev
, "%s\n", sbuf_data(&sb
));
161 virtio_feature_name(uint64_t val
, struct virtio_feature_desc
*desc
)
164 struct virtio_feature_desc
*descs
[2] = { desc
,
165 virtio_common_feature_desc
};
167 for (i
= 0; i
< 2; i
++) {
168 if (descs
[i
] == NULL
)
171 for (j
= 0; descs
[i
][j
].vfd_val
!= 0; j
++) {
172 if (val
== descs
[i
][j
].vfd_val
)
173 return (descs
[i
][j
].vfd_str
);
181 * VirtIO bus method wrappers.
185 virtio_negotiate_features(device_t dev
, uint64_t child_features
)
187 return (VIRTIO_BUS_NEGOTIATE_FEATURES(device_get_parent(dev
),
192 virtio_alloc_virtqueues(device_t dev
, int flags
, int nvqs
,
193 struct vq_alloc_info
*info
)
195 return (VIRTIO_BUS_ALLOC_VIRTQUEUES(device_get_parent(dev
), flags
,
200 virtio_setup_intr(device_t dev
, uint irq
, lwkt_serialize_t slz
)
202 return (VIRTIO_BUS_SETUP_INTR(device_get_parent(dev
), irq
, slz
));
206 virtio_teardown_intr(device_t dev
, uint irq
)
208 return (VIRTIO_BUS_TEARDOWN_INTR(device_get_parent(dev
), irq
));
212 virtio_intr_count(device_t dev
)
214 return (VIRTIO_BUS_INTR_COUNT(device_get_parent(dev
)));
218 virtio_intr_alloc(device_t dev
, int *cnt
, int use_config
, int *cpus
)
220 return (VIRTIO_BUS_INTR_ALLOC(device_get_parent(dev
), cnt
, use_config
,
225 virtio_intr_release(device_t dev
)
227 return (VIRTIO_BUS_INTR_RELEASE(device_get_parent(dev
)));
231 virtio_bind_intr(device_t dev
, uint irq
, int what
,
232 driver_intr_t handler
, void *arg
)
234 return (VIRTIO_BUS_BIND_INTR(device_get_parent(dev
), irq
, what
,
239 virtio_unbind_intr(device_t dev
, int what
)
241 return (VIRTIO_BUS_UNBIND_INTR(device_get_parent(dev
), what
));
245 virtio_with_feature(device_t dev
, uint64_t feature
)
247 return (VIRTIO_BUS_WITH_FEATURE(device_get_parent(dev
), feature
));
251 virtio_stop(device_t dev
)
253 VIRTIO_BUS_STOP(device_get_parent(dev
));
257 virtio_reinit(device_t dev
, uint64_t features
)
259 return (VIRTIO_BUS_REINIT(device_get_parent(dev
), features
));
263 virtio_reinit_complete(device_t dev
)
265 VIRTIO_BUS_REINIT_COMPLETE(device_get_parent(dev
));
269 virtio_read_device_config(device_t dev
, bus_size_t offset
, void *dst
, int len
)
271 VIRTIO_BUS_READ_DEVICE_CONFIG(device_get_parent(dev
),
276 virtio_write_device_config(device_t dev
, bus_size_t offset
, void *dst
, int len
)
278 VIRTIO_BUS_WRITE_DEVICE_CONFIG(device_get_parent(dev
),
283 virtio_modevent(module_t mod
, int type
, void *unused
)
302 static moduledata_t virtio_mod
= {
308 DECLARE_MODULE(virtio
, virtio_mod
, SI_SUB_DRIVERS
, SI_ORDER_FIRST
);
309 MODULE_VERSION(virtio
, 1);