]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/virtio/mmio/virtio_mmio.c
Update elftoolchain to upstream rev 3130
[FreeBSD/FreeBSD.git] / sys / dev / virtio / mmio / virtio_mmio.c
1 /*-
2  * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
3  * Copyright (c) 2014 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by SRI International and the University of
7  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
8  * ("CTSRD"), as part of the DARPA CRASH research programme.
9  *
10  * Portions of this software were developed by Andrew Turner
11  * under sponsorship from the FreeBSD Foundation.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 /*
36  * VirtIO MMIO interface.
37  * This driver is heavily based on VirtIO PCI interface driver.
38  */
39
40 /*
41  * FDT example:
42  *              virtio_block@1000 {
43  *                      compatible = "virtio,mmio";
44  *                      reg = <0x1000 0x100>;
45  *                      interrupts = <63>;
46  *                      interrupt-parent = <&GIC>;
47  *              };
48  */
49
50 #include <sys/cdefs.h>
51 __FBSDID("$FreeBSD$");
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/bus.h>
56 #include <sys/kernel.h>
57 #include <sys/module.h>
58 #include <sys/malloc.h>
59 #include <sys/rman.h>
60
61 #include <machine/bus.h>
62 #include <machine/resource.h>
63
64 #include <dev/fdt/fdt_common.h>
65 #include <dev/ofw/openfirm.h>
66 #include <dev/ofw/ofw_bus.h>
67 #include <dev/ofw/ofw_bus_subr.h>
68
69 #include <dev/virtio/virtio.h>
70 #include <dev/virtio/virtqueue.h>
71 #include <dev/virtio/mmio/virtio_mmio.h>
72
73 #include "virtio_mmio_if.h"
74 #include "virtio_bus_if.h"
75 #include "virtio_if.h"
76
77 #define PAGE_SHIFT      12
78
79 struct vtmmio_virtqueue {
80         struct virtqueue        *vtv_vq;
81         int                      vtv_no_intr;
82 };
83
84 struct vtmmio_softc {
85         device_t                        dev;
86         device_t                        platform;
87         struct resource                 *res[2];
88
89         uint64_t                        vtmmio_features;
90         uint32_t                        vtmmio_flags;
91
92         /* This "bus" will only ever have one child. */
93         device_t                        vtmmio_child_dev;
94         struct virtio_feature_desc      *vtmmio_child_feat_desc;
95
96         int                             vtmmio_nvqs;
97         struct vtmmio_virtqueue         *vtmmio_vqs;
98         void                            *ih;
99 };
100
101 static int      vtmmio_probe(device_t);
102 static int      vtmmio_attach(device_t);
103 static int      vtmmio_detach(device_t);
104 static int      vtmmio_suspend(device_t);
105 static int      vtmmio_resume(device_t);
106 static int      vtmmio_shutdown(device_t);
107 static void     vtmmio_driver_added(device_t, driver_t *);
108 static void     vtmmio_child_detached(device_t, device_t);
109 static int      vtmmio_read_ivar(device_t, device_t, int, uintptr_t *);
110 static int      vtmmio_write_ivar(device_t, device_t, int, uintptr_t);
111 static uint64_t vtmmio_negotiate_features(device_t, uint64_t);
112 static int      vtmmio_with_feature(device_t, uint64_t);
113 static int      vtmmio_alloc_virtqueues(device_t, int, int,
114                     struct vq_alloc_info *);
115 static int      vtmmio_setup_intr(device_t, enum intr_type);
116 static void     vtmmio_stop(device_t);
117 static void     vtmmio_poll(device_t);
118 static int      vtmmio_reinit(device_t, uint64_t);
119 static void     vtmmio_reinit_complete(device_t);
120 static void     vtmmio_notify_virtqueue(device_t, uint16_t);
121 static uint8_t  vtmmio_get_status(device_t);
122 static void     vtmmio_set_status(device_t, uint8_t);
123 static void     vtmmio_read_dev_config(device_t, bus_size_t, void *, int);
124 static void     vtmmio_write_dev_config(device_t, bus_size_t, void *, int);
125 static void     vtmmio_describe_features(struct vtmmio_softc *, const char *,
126                     uint64_t);
127 static void     vtmmio_probe_and_attach_child(struct vtmmio_softc *);
128 static int      vtmmio_reinit_virtqueue(struct vtmmio_softc *, int);
129 static void     vtmmio_free_interrupts(struct vtmmio_softc *);
130 static void     vtmmio_free_virtqueues(struct vtmmio_softc *);
131 static void     vtmmio_release_child_resources(struct vtmmio_softc *);
132 static void     vtmmio_reset(struct vtmmio_softc *);
133 static void     vtmmio_select_virtqueue(struct vtmmio_softc *, int);
134 static void     vtmmio_vq_intr(void *);
135
136 /*
137  * I/O port read/write wrappers.
138  */
139 #define vtmmio_write_config_1(sc, o, v)                         \
140 do {                                                            \
141         bus_write_1((sc)->res[0], (o), (v));                    \
142         if (sc->platform != NULL)                               \
143                 VIRTIO_MMIO_NOTE(sc->platform, (o), (v));       \
144 } while (0)
145 #define vtmmio_write_config_2(sc, o, v)                         \
146 do {                                                            \
147         bus_write_2((sc)->res[0], (o), (v));                    \
148         if (sc->platform != NULL)                               \
149                 VIRTIO_MMIO_NOTE(sc->platform, (o), (v));       \
150 } while (0)
151 #define vtmmio_write_config_4(sc, o, v)                         \
152 do {                                                            \
153         bus_write_4((sc)->res[0], (o), (v));                    \
154         if (sc->platform != NULL)                               \
155                 VIRTIO_MMIO_NOTE(sc->platform, (o), (v));       \
156 } while (0)
157
158 #define vtmmio_read_config_1(sc, o) \
159         bus_read_1((sc)->res[0], (o))
160 #define vtmmio_read_config_2(sc, o) \
161         bus_read_2((sc)->res[0], (o))
162 #define vtmmio_read_config_4(sc, o) \
163         bus_read_4((sc)->res[0], (o))
164
165 static device_method_t vtmmio_methods[] = {
166         /* Device interface. */
167         DEVMETHOD(device_probe,                   vtmmio_probe),
168         DEVMETHOD(device_attach,                  vtmmio_attach),
169         DEVMETHOD(device_detach,                  vtmmio_detach),
170         DEVMETHOD(device_suspend,                 vtmmio_suspend),
171         DEVMETHOD(device_resume,                  vtmmio_resume),
172         DEVMETHOD(device_shutdown,                vtmmio_shutdown),
173
174         /* Bus interface. */
175         DEVMETHOD(bus_driver_added,               vtmmio_driver_added),
176         DEVMETHOD(bus_child_detached,             vtmmio_child_detached),
177         DEVMETHOD(bus_read_ivar,                  vtmmio_read_ivar),
178         DEVMETHOD(bus_write_ivar,                 vtmmio_write_ivar),
179
180         /* VirtIO bus interface. */
181         DEVMETHOD(virtio_bus_negotiate_features,  vtmmio_negotiate_features),
182         DEVMETHOD(virtio_bus_with_feature,        vtmmio_with_feature),
183         DEVMETHOD(virtio_bus_alloc_virtqueues,    vtmmio_alloc_virtqueues),
184         DEVMETHOD(virtio_bus_setup_intr,          vtmmio_setup_intr),
185         DEVMETHOD(virtio_bus_stop,                vtmmio_stop),
186         DEVMETHOD(virtio_bus_poll,                vtmmio_poll),
187         DEVMETHOD(virtio_bus_reinit,              vtmmio_reinit),
188         DEVMETHOD(virtio_bus_reinit_complete,     vtmmio_reinit_complete),
189         DEVMETHOD(virtio_bus_notify_vq,           vtmmio_notify_virtqueue),
190         DEVMETHOD(virtio_bus_read_device_config,  vtmmio_read_dev_config),
191         DEVMETHOD(virtio_bus_write_device_config, vtmmio_write_dev_config),
192
193         DEVMETHOD_END
194 };
195
196 static driver_t vtmmio_driver = {
197         "virtio_mmio",
198         vtmmio_methods,
199         sizeof(struct vtmmio_softc)
200 };
201
202 devclass_t vtmmio_devclass;
203
204 DRIVER_MODULE(virtio_mmio, simplebus, vtmmio_driver, vtmmio_devclass, 0, 0);
205 DRIVER_MODULE(virtio_mmio, ofwbus, vtmmio_driver, vtmmio_devclass, 0, 0);
206 MODULE_VERSION(virtio_mmio, 1);
207 MODULE_DEPEND(virtio_mmio, simplebus, 1, 1, 1);
208 MODULE_DEPEND(virtio_mmio, virtio, 1, 1, 1);
209
210 static int
211 vtmmio_setup_intr(device_t dev, enum intr_type type)
212 {
213         struct vtmmio_softc *sc;
214         int rid;
215         int err;
216
217         sc = device_get_softc(dev);
218
219         if (sc->platform != NULL) {
220                 err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev,
221                                         vtmmio_vq_intr, sc);
222                 if (err == 0) {
223                         /* Okay we have backend-specific interrupts */
224                         return (0);
225                 }
226         }
227
228         rid = 0;
229         sc->res[1] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
230                 RF_ACTIVE);
231         if (!sc->res[1]) {
232                 device_printf(dev, "Can't allocate interrupt\n");
233                 return (ENXIO);
234         }
235
236         if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
237                 NULL, vtmmio_vq_intr, sc, &sc->ih)) {
238                 device_printf(dev, "Can't setup the interrupt\n");
239                 return (ENXIO);
240         }
241
242         return (0);
243 }
244
245 static int
246 vtmmio_probe(device_t dev)
247 {
248
249         if (!ofw_bus_status_okay(dev))
250                 return (ENXIO);
251
252         if (!ofw_bus_is_compatible(dev, "virtio,mmio"))
253                 return (ENXIO);
254
255         device_set_desc(dev, "VirtIO MMIO adapter");
256         return (BUS_PROBE_DEFAULT);
257 }
258
259 static int
260 vtmmio_setup_platform(struct vtmmio_softc *sc)
261 {
262         phandle_t platform_node;
263         struct fdt_ic *ic;
264         phandle_t xref;
265         phandle_t node;
266
267         sc->platform = NULL;
268
269         if ((node = ofw_bus_get_node(sc->dev)) == -1)
270                 return (ENXIO);
271
272         if (OF_searchencprop(node, "platform", &xref,
273                 sizeof(xref)) == -1) {
274                 return (ENXIO);
275         }
276
277         platform_node = OF_node_from_xref(xref);
278
279         SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
280                 if (ic->iph == platform_node) {
281                         sc->platform = ic->dev;
282                         break;
283                 }
284         }
285
286         if (sc->platform == NULL) {
287                 /* No platform-specific device. Ignore it. */
288         }
289
290         return (0);
291 }
292
293 static int
294 vtmmio_attach(device_t dev)
295 {
296         struct vtmmio_softc *sc;
297         device_t child;
298         int rid;
299
300         sc = device_get_softc(dev);
301         sc->dev = dev;
302
303         vtmmio_setup_platform(sc);
304
305         rid = 0;
306         sc->res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
307                         RF_ACTIVE);
308         if (!sc->res[0]) {
309                 device_printf(dev, "Cannot allocate memory window.\n");
310                 return (ENXIO);
311         }
312
313         vtmmio_reset(sc);
314
315         /* Tell the host we've noticed this device. */
316         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
317
318         if ((child = device_add_child(dev, NULL, -1)) == NULL) {
319                 device_printf(dev, "Cannot create child device.\n");
320                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED);
321                 vtmmio_detach(dev);
322                 return (ENOMEM);
323         }
324
325         sc->vtmmio_child_dev = child;
326         vtmmio_probe_and_attach_child(sc);
327
328         return (0);
329 }
330
331 static int
332 vtmmio_detach(device_t dev)
333 {
334         struct vtmmio_softc *sc;
335         device_t child;
336         int error;
337
338         sc = device_get_softc(dev);
339
340         if ((child = sc->vtmmio_child_dev) != NULL) {
341                 error = device_delete_child(dev, child);
342                 if (error)
343                         return (error);
344                 sc->vtmmio_child_dev = NULL;
345         }
346
347         vtmmio_reset(sc);
348
349         if (sc->res[0] != NULL) {
350                 bus_release_resource(dev, SYS_RES_MEMORY, 0,
351                     sc->res[0]);
352                 sc->res[0] = NULL;
353         }
354
355         return (0);
356 }
357
358 static int
359 vtmmio_suspend(device_t dev)
360 {
361
362         return (bus_generic_suspend(dev));
363 }
364
365 static int
366 vtmmio_resume(device_t dev)
367 {
368
369         return (bus_generic_resume(dev));
370 }
371
372 static int
373 vtmmio_shutdown(device_t dev)
374 {
375
376         (void) bus_generic_shutdown(dev);
377
378         /* Forcibly stop the host device. */
379         vtmmio_stop(dev);
380
381         return (0);
382 }
383
384 static void
385 vtmmio_driver_added(device_t dev, driver_t *driver)
386 {
387         struct vtmmio_softc *sc;
388
389         sc = device_get_softc(dev);
390
391         vtmmio_probe_and_attach_child(sc);
392 }
393
394 static void
395 vtmmio_child_detached(device_t dev, device_t child)
396 {
397         struct vtmmio_softc *sc;
398
399         sc = device_get_softc(dev);
400
401         vtmmio_reset(sc);
402         vtmmio_release_child_resources(sc);
403 }
404
405 static int
406 vtmmio_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
407 {
408         struct vtmmio_softc *sc;
409
410         sc = device_get_softc(dev);
411
412         if (sc->vtmmio_child_dev != child)
413                 return (ENOENT);
414
415         switch (index) {
416         case VIRTIO_IVAR_DEVTYPE:
417         case VIRTIO_IVAR_SUBDEVICE:
418                 *result = vtmmio_read_config_4(sc, VIRTIO_MMIO_DEVICE_ID);
419                 break;
420         case VIRTIO_IVAR_VENDOR:
421                 *result = vtmmio_read_config_4(sc, VIRTIO_MMIO_VENDOR_ID);
422                 break;
423         default:
424                 return (ENOENT);
425         }
426
427         return (0);
428 }
429
430 static int
431 vtmmio_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
432 {
433         struct vtmmio_softc *sc;
434
435         sc = device_get_softc(dev);
436
437         if (sc->vtmmio_child_dev != child)
438                 return (ENOENT);
439
440         switch (index) {
441         case VIRTIO_IVAR_FEATURE_DESC:
442                 sc->vtmmio_child_feat_desc = (void *) value;
443                 break;
444         default:
445                 return (ENOENT);
446         }
447
448         return (0);
449 }
450
451 static uint64_t
452 vtmmio_negotiate_features(device_t dev, uint64_t child_features)
453 {
454         struct vtmmio_softc *sc;
455         uint64_t host_features, features;
456
457         sc = device_get_softc(dev);
458
459         host_features = vtmmio_read_config_4(sc, VIRTIO_MMIO_HOST_FEATURES);
460         vtmmio_describe_features(sc, "host", host_features);
461
462         /*
463          * Limit negotiated features to what the driver, virtqueue, and
464          * host all support.
465          */
466         features = host_features & child_features;
467         features = virtqueue_filter_features(features);
468         sc->vtmmio_features = features;
469
470         vtmmio_describe_features(sc, "negotiated", features);
471         vtmmio_write_config_4(sc, VIRTIO_MMIO_GUEST_FEATURES, features);
472
473         return (features);
474 }
475
476 static int
477 vtmmio_with_feature(device_t dev, uint64_t feature)
478 {
479         struct vtmmio_softc *sc;
480
481         sc = device_get_softc(dev);
482
483         return ((sc->vtmmio_features & feature) != 0);
484 }
485
486 static int
487 vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
488     struct vq_alloc_info *vq_info)
489 {
490         struct vtmmio_virtqueue *vqx;
491         struct vq_alloc_info *info;
492         struct vtmmio_softc *sc;
493         struct virtqueue *vq;
494         uint32_t size;
495         int idx, error;
496
497         sc = device_get_softc(dev);
498
499         if (sc->vtmmio_nvqs != 0)
500                 return (EALREADY);
501         if (nvqs <= 0)
502                 return (EINVAL);
503
504         sc->vtmmio_vqs = malloc(nvqs * sizeof(struct vtmmio_virtqueue),
505             M_DEVBUF, M_NOWAIT | M_ZERO);
506         if (sc->vtmmio_vqs == NULL)
507                 return (ENOMEM);
508
509         for (idx = 0; idx < nvqs; idx++) {
510                 vqx = &sc->vtmmio_vqs[idx];
511                 info = &vq_info[idx];
512
513                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
514
515                 vtmmio_select_virtqueue(sc, idx);
516                 size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
517
518                 error = virtqueue_alloc(dev, idx, size,
519                     VIRTIO_MMIO_VRING_ALIGN, 0xFFFFFFFFUL, info, &vq);
520                 if (error) {
521                         device_printf(dev,
522                             "cannot allocate virtqueue %d: %d\n",
523                             idx, error);
524                         break;
525                 }
526
527                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NUM, size);
528                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_ALIGN,
529                     VIRTIO_MMIO_VRING_ALIGN);
530 #if 0
531                 device_printf(dev, "virtqueue paddr 0x%08lx\n",
532                                 (uint64_t)virtqueue_paddr(vq));
533 #endif
534                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN,
535                         virtqueue_paddr(vq) >> PAGE_SHIFT);
536
537                 vqx->vtv_vq = *info->vqai_vq = vq;
538                 vqx->vtv_no_intr = info->vqai_intr == NULL;
539
540                 sc->vtmmio_nvqs++;
541         }
542
543         if (error)
544                 vtmmio_free_virtqueues(sc);
545
546         return (error);
547 }
548
549 static void
550 vtmmio_stop(device_t dev)
551 {
552
553         vtmmio_reset(device_get_softc(dev));
554 }
555
556 static void
557 vtmmio_poll(device_t dev)
558 {
559         struct vtmmio_softc *sc;
560
561         sc = device_get_softc(dev);
562
563         if (sc->platform != NULL)
564                 VIRTIO_MMIO_POLL(sc->platform);
565 }
566
567 static int
568 vtmmio_reinit(device_t dev, uint64_t features)
569 {
570         struct vtmmio_softc *sc;
571         int idx, error;
572
573         sc = device_get_softc(dev);
574
575         if (vtmmio_get_status(dev) != VIRTIO_CONFIG_STATUS_RESET)
576                 vtmmio_stop(dev);
577
578         /*
579          * Quickly drive the status through ACK and DRIVER. The device
580          * does not become usable again until vtmmio_reinit_complete().
581          */
582         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
583         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
584
585         vtmmio_negotiate_features(dev, features);
586
587         for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
588                 error = vtmmio_reinit_virtqueue(sc, idx);
589                 if (error)
590                         return (error);
591         }
592
593         return (0);
594 }
595
596 static void
597 vtmmio_reinit_complete(device_t dev)
598 {
599
600         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
601 }
602
603 static void
604 vtmmio_notify_virtqueue(device_t dev, uint16_t queue)
605 {
606         struct vtmmio_softc *sc;
607
608         sc = device_get_softc(dev);
609
610         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
611 }
612
613 static uint8_t
614 vtmmio_get_status(device_t dev)
615 {
616         struct vtmmio_softc *sc;
617
618         sc = device_get_softc(dev);
619
620         return (vtmmio_read_config_4(sc, VIRTIO_MMIO_STATUS));
621 }
622
623 static void
624 vtmmio_set_status(device_t dev, uint8_t status)
625 {
626         struct vtmmio_softc *sc;
627
628         sc = device_get_softc(dev);
629
630         if (status != VIRTIO_CONFIG_STATUS_RESET)
631                 status |= vtmmio_get_status(dev);
632
633         vtmmio_write_config_4(sc, VIRTIO_MMIO_STATUS, status);
634 }
635
636 static void
637 vtmmio_read_dev_config(device_t dev, bus_size_t offset,
638     void *dst, int length)
639 {
640         struct vtmmio_softc *sc;
641         bus_size_t off;
642         uint8_t *d;
643         int size;
644
645         sc = device_get_softc(dev);
646         off = VIRTIO_MMIO_CONFIG + offset;
647
648         for (d = dst; length > 0; d += size, off += size, length -= size) {
649 #ifdef ALLOW_WORD_ALIGNED_ACCESS
650                 if (length >= 4) {
651                         size = 4;
652                         *(uint32_t *)d = vtmmio_read_config_4(sc, off);
653                 } else if (length >= 2) {
654                         size = 2;
655                         *(uint16_t *)d = vtmmio_read_config_2(sc, off);
656                 } else
657 #endif
658                 {
659                         size = 1;
660                         *d = vtmmio_read_config_1(sc, off);
661                 }
662         }
663 }
664
665 static void
666 vtmmio_write_dev_config(device_t dev, bus_size_t offset,
667     void *src, int length)
668 {
669         struct vtmmio_softc *sc;
670         bus_size_t off;
671         uint8_t *s;
672         int size;
673
674         sc = device_get_softc(dev);
675         off = VIRTIO_MMIO_CONFIG + offset;
676
677         for (s = src; length > 0; s += size, off += size, length -= size) {
678 #ifdef ALLOW_WORD_ALIGNED_ACCESS
679                 if (length >= 4) {
680                         size = 4;
681                         vtmmio_write_config_4(sc, off, *(uint32_t *)s);
682                 } else if (length >= 2) {
683                         size = 2;
684                         vtmmio_write_config_2(sc, off, *(uint16_t *)s);
685                 } else
686 #endif
687                 {
688                         size = 1;
689                         vtmmio_write_config_1(sc, off, *s);
690                 }
691         }
692 }
693
694 static void
695 vtmmio_describe_features(struct vtmmio_softc *sc, const char *msg,
696     uint64_t features)
697 {
698         device_t dev, child;
699
700         dev = sc->dev;
701         child = sc->vtmmio_child_dev;
702
703         if (device_is_attached(child) && bootverbose == 0)
704                 return;
705
706         virtio_describe(dev, msg, features, sc->vtmmio_child_feat_desc);
707 }
708
709 static void
710 vtmmio_probe_and_attach_child(struct vtmmio_softc *sc)
711 {
712         device_t dev, child;
713
714         dev = sc->dev;
715         child = sc->vtmmio_child_dev;
716
717         if (child == NULL)
718                 return;
719
720         if (device_get_state(child) != DS_NOTPRESENT) {
721                 return;
722         }
723
724         if (device_probe(child) != 0) {
725                 return;
726         }
727
728         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
729         if (device_attach(child) != 0) {
730                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED);
731                 vtmmio_reset(sc);
732                 vtmmio_release_child_resources(sc);
733                 /* Reset status for future attempt. */
734                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
735         } else {
736                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
737                 VIRTIO_ATTACH_COMPLETED(child);
738         }
739 }
740
741 static int
742 vtmmio_reinit_virtqueue(struct vtmmio_softc *sc, int idx)
743 {
744         struct vtmmio_virtqueue *vqx;
745         struct virtqueue *vq;
746         int error;
747         uint16_t size;
748
749         vqx = &sc->vtmmio_vqs[idx];
750         vq = vqx->vtv_vq;
751
752         KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx));
753
754         vtmmio_select_virtqueue(sc, idx);
755         size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
756
757         error = virtqueue_reinit(vq, size);
758         if (error)
759                 return (error);
760
761         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN,
762             virtqueue_paddr(vq) >> PAGE_SHIFT);
763
764         return (0);
765 }
766
767 static void
768 vtmmio_free_interrupts(struct vtmmio_softc *sc)
769 {
770
771         if (sc->ih != NULL)
772                 bus_teardown_intr(sc->dev, sc->res[1], sc->ih);
773
774         if (sc->res[1] != NULL)
775                 bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->res[1]);
776 }
777
778 static void
779 vtmmio_free_virtqueues(struct vtmmio_softc *sc)
780 {
781         struct vtmmio_virtqueue *vqx;
782         int idx;
783
784         for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
785                 vqx = &sc->vtmmio_vqs[idx];
786
787                 vtmmio_select_virtqueue(sc, idx);
788                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN, 0);
789
790                 virtqueue_free(vqx->vtv_vq);
791                 vqx->vtv_vq = NULL;
792         }
793
794         free(sc->vtmmio_vqs, M_DEVBUF);
795         sc->vtmmio_vqs = NULL;
796         sc->vtmmio_nvqs = 0;
797 }
798
799 static void
800 vtmmio_release_child_resources(struct vtmmio_softc *sc)
801 {
802
803         vtmmio_free_interrupts(sc);
804         vtmmio_free_virtqueues(sc);
805 }
806
807 static void
808 vtmmio_reset(struct vtmmio_softc *sc)
809 {
810
811         /*
812          * Setting the status to RESET sets the host device to
813          * the original, uninitialized state.
814          */
815         vtmmio_set_status(sc->dev, VIRTIO_CONFIG_STATUS_RESET);
816 }
817
818 static void
819 vtmmio_select_virtqueue(struct vtmmio_softc *sc, int idx)
820 {
821
822         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
823 }
824
825 static void
826 vtmmio_vq_intr(void *arg)
827 {
828         struct vtmmio_virtqueue *vqx;
829         struct vtmmio_softc *sc;
830         struct virtqueue *vq;
831         uint32_t status;
832         int idx;
833
834         sc = arg;
835
836         status = vtmmio_read_config_4(sc, VIRTIO_MMIO_INTERRUPT_STATUS);
837         vtmmio_write_config_4(sc, VIRTIO_MMIO_INTERRUPT_ACK, status);
838
839         /* The config changed */
840         if (status & VIRTIO_MMIO_INT_CONFIG)
841                 if (sc->vtmmio_child_dev != NULL)
842                         VIRTIO_CONFIG_CHANGE(sc->vtmmio_child_dev);
843
844         /* Notify all virtqueues. */
845         if (status & VIRTIO_MMIO_INT_VRING) {
846                 for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
847                         vqx = &sc->vtmmio_vqs[idx];
848                         if (vqx->vtv_no_intr == 0) {
849                                 vq = vqx->vtv_vq;
850                                 virtqueue_intr(vq);
851                         }
852                 }
853         }
854 }