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