]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/virtio/mmio/virtio_mmio.c
Update mandoc to cvs snaphot from 20150302
[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         vtmmio_write_config_4(sc, VIRTIO_MMIO_GUEST_PAGE_SIZE, 1 << PAGE_SHIFT);
510
511         for (idx = 0; idx < nvqs; idx++) {
512                 vqx = &sc->vtmmio_vqs[idx];
513                 info = &vq_info[idx];
514
515                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
516
517                 vtmmio_select_virtqueue(sc, idx);
518                 size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
519
520                 error = virtqueue_alloc(dev, idx, size,
521                     VIRTIO_MMIO_VRING_ALIGN, 0xFFFFFFFFUL, info, &vq);
522                 if (error) {
523                         device_printf(dev,
524                             "cannot allocate virtqueue %d: %d\n",
525                             idx, error);
526                         break;
527                 }
528
529                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NUM, size);
530                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_ALIGN,
531                     VIRTIO_MMIO_VRING_ALIGN);
532 #if 0
533                 device_printf(dev, "virtqueue paddr 0x%08lx\n",
534                                 (uint64_t)virtqueue_paddr(vq));
535 #endif
536                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN,
537                         virtqueue_paddr(vq) >> PAGE_SHIFT);
538
539                 vqx->vtv_vq = *info->vqai_vq = vq;
540                 vqx->vtv_no_intr = info->vqai_intr == NULL;
541
542                 sc->vtmmio_nvqs++;
543         }
544
545         if (error)
546                 vtmmio_free_virtqueues(sc);
547
548         return (error);
549 }
550
551 static void
552 vtmmio_stop(device_t dev)
553 {
554
555         vtmmio_reset(device_get_softc(dev));
556 }
557
558 static void
559 vtmmio_poll(device_t dev)
560 {
561         struct vtmmio_softc *sc;
562
563         sc = device_get_softc(dev);
564
565         if (sc->platform != NULL)
566                 VIRTIO_MMIO_POLL(sc->platform);
567 }
568
569 static int
570 vtmmio_reinit(device_t dev, uint64_t features)
571 {
572         struct vtmmio_softc *sc;
573         int idx, error;
574
575         sc = device_get_softc(dev);
576
577         if (vtmmio_get_status(dev) != VIRTIO_CONFIG_STATUS_RESET)
578                 vtmmio_stop(dev);
579
580         /*
581          * Quickly drive the status through ACK and DRIVER. The device
582          * does not become usable again until vtmmio_reinit_complete().
583          */
584         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
585         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
586
587         vtmmio_negotiate_features(dev, features);
588
589         for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
590                 error = vtmmio_reinit_virtqueue(sc, idx);
591                 if (error)
592                         return (error);
593         }
594
595         return (0);
596 }
597
598 static void
599 vtmmio_reinit_complete(device_t dev)
600 {
601
602         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
603 }
604
605 static void
606 vtmmio_notify_virtqueue(device_t dev, uint16_t queue)
607 {
608         struct vtmmio_softc *sc;
609
610         sc = device_get_softc(dev);
611
612         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
613 }
614
615 static uint8_t
616 vtmmio_get_status(device_t dev)
617 {
618         struct vtmmio_softc *sc;
619
620         sc = device_get_softc(dev);
621
622         return (vtmmio_read_config_4(sc, VIRTIO_MMIO_STATUS));
623 }
624
625 static void
626 vtmmio_set_status(device_t dev, uint8_t status)
627 {
628         struct vtmmio_softc *sc;
629
630         sc = device_get_softc(dev);
631
632         if (status != VIRTIO_CONFIG_STATUS_RESET)
633                 status |= vtmmio_get_status(dev);
634
635         vtmmio_write_config_4(sc, VIRTIO_MMIO_STATUS, status);
636 }
637
638 static void
639 vtmmio_read_dev_config(device_t dev, bus_size_t offset,
640     void *dst, int length)
641 {
642         struct vtmmio_softc *sc;
643         bus_size_t off;
644         uint8_t *d;
645         int size;
646
647         sc = device_get_softc(dev);
648         off = VIRTIO_MMIO_CONFIG + offset;
649
650         for (d = dst; length > 0; d += size, off += size, length -= size) {
651 #ifdef ALLOW_WORD_ALIGNED_ACCESS
652                 if (length >= 4) {
653                         size = 4;
654                         *(uint32_t *)d = vtmmio_read_config_4(sc, off);
655                 } else if (length >= 2) {
656                         size = 2;
657                         *(uint16_t *)d = vtmmio_read_config_2(sc, off);
658                 } else
659 #endif
660                 {
661                         size = 1;
662                         *d = vtmmio_read_config_1(sc, off);
663                 }
664         }
665 }
666
667 static void
668 vtmmio_write_dev_config(device_t dev, bus_size_t offset,
669     void *src, int length)
670 {
671         struct vtmmio_softc *sc;
672         bus_size_t off;
673         uint8_t *s;
674         int size;
675
676         sc = device_get_softc(dev);
677         off = VIRTIO_MMIO_CONFIG + offset;
678
679         for (s = src; length > 0; s += size, off += size, length -= size) {
680 #ifdef ALLOW_WORD_ALIGNED_ACCESS
681                 if (length >= 4) {
682                         size = 4;
683                         vtmmio_write_config_4(sc, off, *(uint32_t *)s);
684                 } else if (length >= 2) {
685                         size = 2;
686                         vtmmio_write_config_2(sc, off, *(uint16_t *)s);
687                 } else
688 #endif
689                 {
690                         size = 1;
691                         vtmmio_write_config_1(sc, off, *s);
692                 }
693         }
694 }
695
696 static void
697 vtmmio_describe_features(struct vtmmio_softc *sc, const char *msg,
698     uint64_t features)
699 {
700         device_t dev, child;
701
702         dev = sc->dev;
703         child = sc->vtmmio_child_dev;
704
705         if (device_is_attached(child) && bootverbose == 0)
706                 return;
707
708         virtio_describe(dev, msg, features, sc->vtmmio_child_feat_desc);
709 }
710
711 static void
712 vtmmio_probe_and_attach_child(struct vtmmio_softc *sc)
713 {
714         device_t dev, child;
715
716         dev = sc->dev;
717         child = sc->vtmmio_child_dev;
718
719         if (child == NULL)
720                 return;
721
722         if (device_get_state(child) != DS_NOTPRESENT) {
723                 return;
724         }
725
726         if (device_probe(child) != 0) {
727                 return;
728         }
729
730         vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
731         if (device_attach(child) != 0) {
732                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED);
733                 vtmmio_reset(sc);
734                 vtmmio_release_child_resources(sc);
735                 /* Reset status for future attempt. */
736                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
737         } else {
738                 vtmmio_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
739                 VIRTIO_ATTACH_COMPLETED(child);
740         }
741 }
742
743 static int
744 vtmmio_reinit_virtqueue(struct vtmmio_softc *sc, int idx)
745 {
746         struct vtmmio_virtqueue *vqx;
747         struct virtqueue *vq;
748         int error;
749         uint16_t size;
750
751         vqx = &sc->vtmmio_vqs[idx];
752         vq = vqx->vtv_vq;
753
754         KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx));
755
756         vtmmio_select_virtqueue(sc, idx);
757         size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
758
759         error = virtqueue_reinit(vq, size);
760         if (error)
761                 return (error);
762
763         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN,
764             virtqueue_paddr(vq) >> PAGE_SHIFT);
765
766         return (0);
767 }
768
769 static void
770 vtmmio_free_interrupts(struct vtmmio_softc *sc)
771 {
772
773         if (sc->ih != NULL)
774                 bus_teardown_intr(sc->dev, sc->res[1], sc->ih);
775
776         if (sc->res[1] != NULL)
777                 bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->res[1]);
778 }
779
780 static void
781 vtmmio_free_virtqueues(struct vtmmio_softc *sc)
782 {
783         struct vtmmio_virtqueue *vqx;
784         int idx;
785
786         for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
787                 vqx = &sc->vtmmio_vqs[idx];
788
789                 vtmmio_select_virtqueue(sc, idx);
790                 vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_PFN, 0);
791
792                 virtqueue_free(vqx->vtv_vq);
793                 vqx->vtv_vq = NULL;
794         }
795
796         free(sc->vtmmio_vqs, M_DEVBUF);
797         sc->vtmmio_vqs = NULL;
798         sc->vtmmio_nvqs = 0;
799 }
800
801 static void
802 vtmmio_release_child_resources(struct vtmmio_softc *sc)
803 {
804
805         vtmmio_free_interrupts(sc);
806         vtmmio_free_virtqueues(sc);
807 }
808
809 static void
810 vtmmio_reset(struct vtmmio_softc *sc)
811 {
812
813         /*
814          * Setting the status to RESET sets the host device to
815          * the original, uninitialized state.
816          */
817         vtmmio_set_status(sc->dev, VIRTIO_CONFIG_STATUS_RESET);
818 }
819
820 static void
821 vtmmio_select_virtqueue(struct vtmmio_softc *sc, int idx)
822 {
823
824         vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
825 }
826
827 static void
828 vtmmio_vq_intr(void *arg)
829 {
830         struct vtmmio_virtqueue *vqx;
831         struct vtmmio_softc *sc;
832         struct virtqueue *vq;
833         uint32_t status;
834         int idx;
835
836         sc = arg;
837
838         status = vtmmio_read_config_4(sc, VIRTIO_MMIO_INTERRUPT_STATUS);
839         vtmmio_write_config_4(sc, VIRTIO_MMIO_INTERRUPT_ACK, status);
840
841         /* The config changed */
842         if (status & VIRTIO_MMIO_INT_CONFIG)
843                 if (sc->vtmmio_child_dev != NULL)
844                         VIRTIO_CONFIG_CHANGE(sc->vtmmio_child_dev);
845
846         /* Notify all virtqueues. */
847         if (status & VIRTIO_MMIO_INT_VRING) {
848                 for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
849                         vqx = &sc->vtmmio_vqs[idx];
850                         if (vqx->vtv_no_intr == 0) {
851                                 vq = vqx->vtv_vq;
852                                 virtqueue_intr(vq);
853                         }
854                 }
855         }
856 }