xref: /freebsd/sys/dev/virtio/pci/virtio_pci_legacy.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2011, Bryan Venteicher <bryanv@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /* Driver for the legacy VirtIO PCI interface. */
30 
31 #include <sys/cdefs.h>
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/lock.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/endian.h>
39 
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/bus.h>
43 #include <sys/rman.h>
44 
45 #include <dev/pci/pcivar.h>
46 #include <dev/pci/pcireg.h>
47 
48 #include <dev/virtio/virtio.h>
49 #include <dev/virtio/virtqueue.h>
50 #include <dev/virtio/pci/virtio_pci.h>
51 #include <dev/virtio/pci/virtio_pci_legacy_var.h>
52 
53 #include "virtio_bus_if.h"
54 #include "virtio_pci_if.h"
55 #include "virtio_if.h"
56 
57 struct vtpci_legacy_softc {
58 	device_t			 vtpci_dev;
59 	struct vtpci_common		 vtpci_common;
60 	int				 vtpci_res_type;
61 	struct resource			*vtpci_res;
62 	struct resource			*vtpci_msix_table_res;
63 	struct resource			*vtpci_msix_pba_res;
64 };
65 
66 static int	vtpci_legacy_probe(device_t);
67 static int	vtpci_legacy_attach(device_t);
68 static int	vtpci_legacy_detach(device_t);
69 static int	vtpci_legacy_suspend(device_t);
70 static int	vtpci_legacy_resume(device_t);
71 static int	vtpci_legacy_shutdown(device_t);
72 
73 static void	vtpci_legacy_driver_added(device_t, driver_t *);
74 static void	vtpci_legacy_child_detached(device_t, device_t);
75 static int	vtpci_legacy_read_ivar(device_t, device_t, int, uintptr_t *);
76 static int	vtpci_legacy_write_ivar(device_t, device_t, int, uintptr_t);
77 
78 static uint8_t	vtpci_legacy_read_isr(device_t);
79 static uint16_t	vtpci_legacy_get_vq_size(device_t, int);
80 static bus_size_t vtpci_legacy_get_vq_notify_off(device_t, int);
81 static void	vtpci_legacy_set_vq(device_t, struct virtqueue *);
82 static void	vtpci_legacy_disable_vq(device_t, int);
83 static int	vtpci_legacy_register_cfg_msix(device_t,
84 		    struct vtpci_interrupt *);
85 static int	vtpci_legacy_register_vq_msix(device_t, int idx,
86 		    struct vtpci_interrupt *);
87 
88 static uint64_t	vtpci_legacy_negotiate_features(device_t, uint64_t);
89 static int	vtpci_legacy_with_feature(device_t, uint64_t);
90 static int	vtpci_legacy_alloc_virtqueues(device_t, int, int,
91 		    struct vq_alloc_info *);
92 static int	vtpci_legacy_setup_interrupts(device_t, enum intr_type);
93 static void	vtpci_legacy_stop(device_t);
94 static int	vtpci_legacy_reinit(device_t, uint64_t);
95 static void	vtpci_legacy_reinit_complete(device_t);
96 static void	vtpci_legacy_notify_vq(device_t, uint16_t, bus_size_t);
97 static void	vtpci_legacy_read_dev_config(device_t, bus_size_t, void *, int);
98 static void	vtpci_legacy_write_dev_config(device_t, bus_size_t, const void *, int);
99 
100 static bool	vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc);
101 static void	vtpci_legacy_teardown_msix(struct vtpci_legacy_softc *sc);
102 static int	vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *);
103 static void	vtpci_legacy_free_resources(struct vtpci_legacy_softc *);
104 
105 static void	vtpci_legacy_probe_and_attach_child(struct vtpci_legacy_softc *);
106 
107 static uint8_t	vtpci_legacy_get_status(struct vtpci_legacy_softc *);
108 static void	vtpci_legacy_set_status(struct vtpci_legacy_softc *, uint8_t);
109 static void	vtpci_legacy_select_virtqueue(struct vtpci_legacy_softc *, int);
110 static void	vtpci_legacy_reset(struct vtpci_legacy_softc *);
111 
112 #define VIRTIO_PCI_LEGACY_CONFIG(_sc) \
113     VIRTIO_PCI_CONFIG_OFF(vtpci_is_msix_enabled(&(_sc)->vtpci_common))
114 
115 #define vtpci_legacy_read_config_1(sc, o) \
116     bus_read_1((sc)->vtpci_res, (o))
117 #define vtpci_legacy_write_config_1(sc, o, v) \
118     bus_write_1((sc)->vtpci_res, (o), (v))
119 /*
120  * VirtIO specifies that PCI Configuration area is guest endian. However,
121  * since PCI devices are inherently little-endian, on big-endian systems
122  * the bus layer transparently converts it to BE. For virtio-legacy, this
123  * conversion is undesired, so an extra byte swap is required to fix it.
124  */
125 #define vtpci_legacy_read_config_2(sc, o) \
126     le16toh(bus_read_2((sc)->vtpci_res, (o)))
127 #define vtpci_legacy_read_config_4(sc, o) \
128     le32toh(bus_read_4((sc)->vtpci_res, (o)))
129 #define vtpci_legacy_write_config_2(sc, o, v) \
130     bus_write_2((sc)->vtpci_res, (o), (htole16(v)))
131 #define vtpci_legacy_write_config_4(sc, o, v) \
132     bus_write_4((sc)->vtpci_res, (o), (htole32(v)))
133 /* PCI Header LE. On BE systems the bus layer takes care of byte swapping. */
134 #define vtpci_legacy_read_header_2(sc, o) \
135     bus_read_2((sc)->vtpci_res, (o))
136 #define vtpci_legacy_read_header_4(sc, o) \
137     bus_read_4((sc)->vtpci_res, (o))
138 #define vtpci_legacy_write_header_2(sc, o, v) \
139     bus_write_2((sc)->vtpci_res, (o), (v))
140 #define vtpci_legacy_write_header_4(sc, o, v) \
141     bus_write_4((sc)->vtpci_res, (o), (v))
142 
143 static device_method_t vtpci_legacy_methods[] = {
144 	/* Device interface. */
145 	DEVMETHOD(device_probe,			  vtpci_legacy_probe),
146 	DEVMETHOD(device_attach,		  vtpci_legacy_attach),
147 	DEVMETHOD(device_detach,		  vtpci_legacy_detach),
148 	DEVMETHOD(device_suspend,		  vtpci_legacy_suspend),
149 	DEVMETHOD(device_resume,		  vtpci_legacy_resume),
150 	DEVMETHOD(device_shutdown,		  vtpci_legacy_shutdown),
151 
152 	/* Bus interface. */
153 	DEVMETHOD(bus_driver_added,		  vtpci_legacy_driver_added),
154 	DEVMETHOD(bus_child_detached,		  vtpci_legacy_child_detached),
155 	DEVMETHOD(bus_child_pnpinfo,		  virtio_child_pnpinfo),
156 	DEVMETHOD(bus_read_ivar,		  vtpci_legacy_read_ivar),
157 	DEVMETHOD(bus_write_ivar,		  vtpci_legacy_write_ivar),
158 
159 	/* VirtIO PCI interface. */
160 	DEVMETHOD(virtio_pci_read_isr,		 vtpci_legacy_read_isr),
161 	DEVMETHOD(virtio_pci_get_vq_size,	 vtpci_legacy_get_vq_size),
162 	DEVMETHOD(virtio_pci_get_vq_notify_off,	 vtpci_legacy_get_vq_notify_off),
163 	DEVMETHOD(virtio_pci_set_vq,		 vtpci_legacy_set_vq),
164 	DEVMETHOD(virtio_pci_disable_vq,	 vtpci_legacy_disable_vq),
165 	DEVMETHOD(virtio_pci_register_cfg_msix,  vtpci_legacy_register_cfg_msix),
166 	DEVMETHOD(virtio_pci_register_vq_msix,	 vtpci_legacy_register_vq_msix),
167 
168 	/* VirtIO bus interface. */
169 	DEVMETHOD(virtio_bus_negotiate_features,  vtpci_legacy_negotiate_features),
170 	DEVMETHOD(virtio_bus_with_feature,	  vtpci_legacy_with_feature),
171 	DEVMETHOD(virtio_bus_alloc_virtqueues,	  vtpci_legacy_alloc_virtqueues),
172 	DEVMETHOD(virtio_bus_setup_intr,	  vtpci_legacy_setup_interrupts),
173 	DEVMETHOD(virtio_bus_stop,		  vtpci_legacy_stop),
174 	DEVMETHOD(virtio_bus_reinit,		  vtpci_legacy_reinit),
175 	DEVMETHOD(virtio_bus_reinit_complete,	  vtpci_legacy_reinit_complete),
176 	DEVMETHOD(virtio_bus_notify_vq,		  vtpci_legacy_notify_vq),
177 	DEVMETHOD(virtio_bus_read_device_config,  vtpci_legacy_read_dev_config),
178 	DEVMETHOD(virtio_bus_write_device_config, vtpci_legacy_write_dev_config),
179 
180 	DEVMETHOD_END
181 };
182 
183 static driver_t vtpci_legacy_driver = {
184 	.name = "virtio_pci",
185 	.methods = vtpci_legacy_methods,
186 	.size = sizeof(struct vtpci_legacy_softc)
187 };
188 
189 DRIVER_MODULE(virtio_pci_legacy, pci, vtpci_legacy_driver, 0, 0);
190 
191 static int
192 vtpci_legacy_probe(device_t dev)
193 {
194 	char desc[64];
195 	const char *name;
196 
197 	if (pci_get_vendor(dev) != VIRTIO_PCI_VENDORID)
198 		return (ENXIO);
199 
200 	if (pci_get_device(dev) < VIRTIO_PCI_DEVICEID_MIN ||
201 	    pci_get_device(dev) > VIRTIO_PCI_DEVICEID_LEGACY_MAX)
202 		return (ENXIO);
203 
204 	if (pci_get_revid(dev) != VIRTIO_PCI_ABI_VERSION)
205 		return (ENXIO);
206 
207 	name = virtio_device_name(pci_get_subdevice(dev));
208 	if (name == NULL)
209 		name = "Unknown";
210 
211 	snprintf(desc, sizeof(desc), "VirtIO PCI (legacy) %s adapter", name);
212 	device_set_desc_copy(dev, desc);
213 
214 	/* Prefer transitional modern VirtIO PCI. */
215 	return (BUS_PROBE_LOW_PRIORITY);
216 }
217 
218 static int
219 vtpci_legacy_attach(device_t dev)
220 {
221 	struct vtpci_legacy_softc *sc;
222 	int error;
223 
224 	sc = device_get_softc(dev);
225 	sc->vtpci_dev = dev;
226 	vtpci_init(&sc->vtpci_common, dev, false);
227 
228 	error = vtpci_legacy_alloc_resources(sc);
229 	if (error) {
230 		device_printf(dev, "cannot map I/O space nor memory space\n");
231 		return (error);
232 	}
233 
234 	if (vtpci_is_msix_available(&sc->vtpci_common) &&
235 	    !vtpci_legacy_setup_msix(sc)) {
236 		device_printf(dev, "cannot setup MSI-x resources\n");
237 		error = ENXIO;
238 		goto fail;
239 	}
240 
241 	vtpci_legacy_reset(sc);
242 
243 	/* Tell the host we've noticed this device. */
244 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
245 
246 	error = vtpci_add_child(&sc->vtpci_common);
247 	if (error)
248 		goto fail;
249 
250 	vtpci_legacy_probe_and_attach_child(sc);
251 
252 	return (0);
253 
254 fail:
255 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_FAILED);
256 	vtpci_legacy_detach(dev);
257 
258 	return (error);
259 }
260 
261 static int
262 vtpci_legacy_detach(device_t dev)
263 {
264 	struct vtpci_legacy_softc *sc;
265 	int error;
266 
267 	sc = device_get_softc(dev);
268 
269 	error = vtpci_delete_child(&sc->vtpci_common);
270 	if (error)
271 		return (error);
272 
273 	vtpci_legacy_reset(sc);
274 	vtpci_legacy_teardown_msix(sc);
275 	vtpci_legacy_free_resources(sc);
276 
277 	return (0);
278 }
279 
280 static int
281 vtpci_legacy_suspend(device_t dev)
282 {
283 	return (bus_generic_suspend(dev));
284 }
285 
286 static int
287 vtpci_legacy_resume(device_t dev)
288 {
289 	return (bus_generic_resume(dev));
290 }
291 
292 static int
293 vtpci_legacy_shutdown(device_t dev)
294 {
295 	(void) bus_generic_shutdown(dev);
296 	/* Forcibly stop the host device. */
297 	vtpci_legacy_stop(dev);
298 
299 	return (0);
300 }
301 
302 static void
303 vtpci_legacy_driver_added(device_t dev, driver_t *driver)
304 {
305 	vtpci_legacy_probe_and_attach_child(device_get_softc(dev));
306 }
307 
308 static void
309 vtpci_legacy_child_detached(device_t dev, device_t child)
310 {
311 	struct vtpci_legacy_softc *sc;
312 
313 	sc = device_get_softc(dev);
314 
315 	vtpci_legacy_reset(sc);
316 	vtpci_child_detached(&sc->vtpci_common);
317 
318 	/* After the reset, retell the host we've noticed this device. */
319 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
320 }
321 
322 static int
323 vtpci_legacy_read_ivar(device_t dev, device_t child, int index,
324     uintptr_t *result)
325 {
326 	struct vtpci_legacy_softc *sc;
327 	struct vtpci_common *cn;
328 
329 	sc = device_get_softc(dev);
330 	cn = &sc->vtpci_common;
331 
332 	if (vtpci_child_device(cn) != child)
333 		return (ENOENT);
334 
335 	switch (index) {
336 	case VIRTIO_IVAR_DEVTYPE:
337 		*result = pci_get_subdevice(dev);
338 		break;
339 	default:
340 		return (vtpci_read_ivar(cn, index, result));
341 	}
342 
343 	return (0);
344 }
345 
346 static int
347 vtpci_legacy_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
348 {
349 	struct vtpci_legacy_softc *sc;
350 	struct vtpci_common *cn;
351 
352 	sc = device_get_softc(dev);
353 	cn = &sc->vtpci_common;
354 
355 	if (vtpci_child_device(cn) != child)
356 		return (ENOENT);
357 
358 	switch (index) {
359 	default:
360 		return (vtpci_write_ivar(cn, index, value));
361 	}
362 
363 	return (0);
364 }
365 
366 static uint64_t
367 vtpci_legacy_negotiate_features(device_t dev, uint64_t child_features)
368 {
369 	struct vtpci_legacy_softc *sc;
370 	uint64_t host_features, features;
371 
372 	sc = device_get_softc(dev);
373 	host_features = vtpci_legacy_read_header_4(sc, VIRTIO_PCI_HOST_FEATURES);
374 
375 	features = vtpci_negotiate_features(&sc->vtpci_common,
376 	    child_features, host_features);
377 	vtpci_legacy_write_header_4(sc, VIRTIO_PCI_GUEST_FEATURES, features);
378 
379 	return (features);
380 }
381 
382 static int
383 vtpci_legacy_with_feature(device_t dev, uint64_t feature)
384 {
385 	struct vtpci_legacy_softc *sc;
386 
387 	sc = device_get_softc(dev);
388 
389 	return (vtpci_with_feature(&sc->vtpci_common, feature));
390 }
391 
392 static int
393 vtpci_legacy_alloc_virtqueues(device_t dev, int flags, int nvqs,
394     struct vq_alloc_info *vq_info)
395 {
396 	struct vtpci_legacy_softc *sc;
397 	struct vtpci_common *cn;
398 
399 	sc = device_get_softc(dev);
400 	cn = &sc->vtpci_common;
401 
402 	return (vtpci_alloc_virtqueues(cn, flags, nvqs, vq_info));
403 }
404 
405 static int
406 vtpci_legacy_setup_interrupts(device_t dev, enum intr_type type)
407 {
408 	struct vtpci_legacy_softc *sc;
409 
410 	sc = device_get_softc(dev);
411 
412 	return (vtpci_setup_interrupts(&sc->vtpci_common, type));
413 }
414 
415 static void
416 vtpci_legacy_stop(device_t dev)
417 {
418 	vtpci_legacy_reset(device_get_softc(dev));
419 }
420 
421 static int
422 vtpci_legacy_reinit(device_t dev, uint64_t features)
423 {
424 	struct vtpci_legacy_softc *sc;
425 	struct vtpci_common *cn;
426 	int error;
427 
428 	sc = device_get_softc(dev);
429 	cn = &sc->vtpci_common;
430 
431 	/*
432 	 * Redrive the device initialization. This is a bit of an abuse of
433 	 * the specification, but VirtualBox, QEMU/KVM, and BHyVe seem to
434 	 * play nice.
435 	 *
436 	 * We do not allow the host device to change from what was originally
437 	 * negotiated beyond what the guest driver changed. MSIX state should
438 	 * not change, number of virtqueues and their size remain the same, etc.
439 	 * This will need to be rethought when we want to support migration.
440 	 */
441 
442 	if (vtpci_legacy_get_status(sc) != VIRTIO_CONFIG_STATUS_RESET)
443 		vtpci_legacy_stop(dev);
444 
445 	/*
446 	 * Quickly drive the status through ACK and DRIVER. The device does
447 	 * not become usable again until DRIVER_OK in reinit complete.
448 	 */
449 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_ACK);
450 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER);
451 
452 	vtpci_legacy_negotiate_features(dev, features);
453 
454 	error = vtpci_reinit(cn);
455 	if (error)
456 		return (error);
457 
458 	return (0);
459 }
460 
461 static void
462 vtpci_legacy_reinit_complete(device_t dev)
463 {
464 	struct vtpci_legacy_softc *sc;
465 
466 	sc = device_get_softc(dev);
467 
468 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER_OK);
469 }
470 
471 static void
472 vtpci_legacy_notify_vq(device_t dev, uint16_t queue, bus_size_t offset)
473 {
474 	struct vtpci_legacy_softc *sc;
475 
476 	sc = device_get_softc(dev);
477 	MPASS(offset == VIRTIO_PCI_QUEUE_NOTIFY);
478 
479 	vtpci_legacy_write_header_2(sc, offset, queue);
480 }
481 
482 static uint8_t
483 vtpci_legacy_get_status(struct vtpci_legacy_softc *sc)
484 {
485 	return (vtpci_legacy_read_config_1(sc, VIRTIO_PCI_STATUS));
486 }
487 
488 static void
489 vtpci_legacy_set_status(struct vtpci_legacy_softc *sc, uint8_t status)
490 {
491 	if (status != VIRTIO_CONFIG_STATUS_RESET)
492 		status |= vtpci_legacy_get_status(sc);
493 
494 	vtpci_legacy_write_config_1(sc, VIRTIO_PCI_STATUS, status);
495 }
496 
497 static void
498 vtpci_legacy_read_dev_config(device_t dev, bus_size_t offset,
499     void *dst, int length)
500 {
501 	struct vtpci_legacy_softc *sc;
502 	bus_size_t off;
503 	uint8_t *d;
504 	int i;
505 
506 	sc = device_get_softc(dev);
507 	off = VIRTIO_PCI_LEGACY_CONFIG(sc) + offset;
508 
509 	d = dst;
510 	for (i = 0; i < length; i++) {
511 		d[i] = vtpci_legacy_read_config_1(sc, off + i);
512 	}
513 }
514 
515 static void
516 vtpci_legacy_write_dev_config(device_t dev, bus_size_t offset,
517     const void *src, int length)
518 {
519 	struct vtpci_legacy_softc *sc;
520 	bus_size_t off;
521 	const uint8_t *s;
522 	int i;
523 
524 	sc = device_get_softc(dev);
525 	off = VIRTIO_PCI_LEGACY_CONFIG(sc) + offset;
526 
527 	s = src;
528 	for (i = 0; i < length; i++) {
529 		vtpci_legacy_write_config_1(sc, off + i, s[i]);
530 	}
531 }
532 
533 static bool
534 vtpci_legacy_setup_msix(struct vtpci_legacy_softc *sc)
535 {
536 	device_t dev;
537 	int rid, table_rid;
538 
539 	dev = sc->vtpci_dev;
540 
541 	rid = table_rid = pci_msix_table_bar(dev);
542 	if (rid != PCIR_BAR(0)) {
543 		sc->vtpci_msix_table_res = bus_alloc_resource_any(
544 		    dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
545 		if (sc->vtpci_msix_table_res == NULL)
546 			return (false);
547 	}
548 
549 	rid = pci_msix_pba_bar(dev);
550 	if (rid != table_rid && rid != PCIR_BAR(0)) {
551 		sc->vtpci_msix_pba_res = bus_alloc_resource_any(
552 		    dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
553 		if (sc->vtpci_msix_pba_res == NULL)
554 			return (false);
555 	}
556 
557 	return (true);
558 }
559 
560 static void
561 vtpci_legacy_teardown_msix(struct vtpci_legacy_softc *sc)
562 {
563 	device_t dev;
564 
565 	dev = sc->vtpci_dev;
566 
567 	if (sc->vtpci_msix_pba_res != NULL) {
568 		bus_release_resource(dev, SYS_RES_MEMORY,
569 		    rman_get_rid(sc->vtpci_msix_pba_res),
570 		    sc->vtpci_msix_pba_res);
571 		sc->vtpci_msix_pba_res = NULL;
572 	}
573 	if (sc->vtpci_msix_table_res != NULL) {
574 		bus_release_resource(dev, SYS_RES_MEMORY,
575 		    rman_get_rid(sc->vtpci_msix_table_res),
576 		    sc->vtpci_msix_table_res);
577 		sc->vtpci_msix_table_res = NULL;
578 	}
579 }
580 
581 static int
582 vtpci_legacy_alloc_resources(struct vtpci_legacy_softc *sc)
583 {
584 	const int res_types[] = { SYS_RES_IOPORT, SYS_RES_MEMORY };
585 	device_t dev;
586 	int rid, i;
587 
588 	dev = sc->vtpci_dev;
589 
590 	/*
591 	 * Most hypervisors export the common configuration structure in IO
592 	 * space, but some use memory space; try both.
593 	 */
594 	for (i = 0; nitems(res_types); i++) {
595 		rid = PCIR_BAR(0);
596 		sc->vtpci_res_type = res_types[i];
597 		sc->vtpci_res = bus_alloc_resource_any(dev, res_types[i], &rid,
598 		    RF_ACTIVE);
599 		if (sc->vtpci_res != NULL)
600 			break;
601 	}
602 	if (sc->vtpci_res == NULL)
603 		return (ENXIO);
604 
605 	return (0);
606 }
607 
608 static void
609 vtpci_legacy_free_resources(struct vtpci_legacy_softc *sc)
610 {
611 	device_t dev;
612 
613 	dev = sc->vtpci_dev;
614 
615 	if (sc->vtpci_res != NULL) {
616 		bus_release_resource(dev, sc->vtpci_res_type, PCIR_BAR(0),
617 		    sc->vtpci_res);
618 		sc->vtpci_res = NULL;
619 	}
620 }
621 
622 static void
623 vtpci_legacy_probe_and_attach_child(struct vtpci_legacy_softc *sc)
624 {
625 	device_t dev, child;
626 
627 	dev = sc->vtpci_dev;
628 	child = vtpci_child_device(&sc->vtpci_common);
629 
630 	if (child == NULL || device_get_state(child) != DS_NOTPRESENT)
631 		return;
632 
633 	if (device_probe(child) != 0)
634 		return;
635 
636 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER);
637 
638 	if (device_attach(child) != 0) {
639 		vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_FAILED);
640 		/* Reset status for future attempt. */
641 		vtpci_legacy_child_detached(dev, child);
642 	} else {
643 		vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_DRIVER_OK);
644 		VIRTIO_ATTACH_COMPLETED(child);
645 	}
646 }
647 
648 static int
649 vtpci_legacy_register_msix(struct vtpci_legacy_softc *sc, int offset,
650     struct vtpci_interrupt *intr)
651 {
652 	uint16_t vector;
653 
654 	if (intr != NULL) {
655 		/* Map from guest rid to host vector. */
656 		vector = intr->vti_rid - 1;
657 	} else
658 		vector = VIRTIO_MSI_NO_VECTOR;
659 
660 	vtpci_legacy_write_header_2(sc, offset, vector);
661 	return (vtpci_legacy_read_header_2(sc, offset) == vector ? 0 : ENODEV);
662 }
663 
664 static int
665 vtpci_legacy_register_cfg_msix(device_t dev, struct vtpci_interrupt *intr)
666 {
667 	struct vtpci_legacy_softc *sc;
668 	int error;
669 
670 	sc = device_get_softc(dev);
671 
672 	error = vtpci_legacy_register_msix(sc, VIRTIO_MSI_CONFIG_VECTOR, intr);
673 	if (error) {
674 		device_printf(dev,
675 		    "unable to register config MSIX interrupt\n");
676 		return (error);
677 	}
678 
679 	return (0);
680 }
681 
682 static int
683 vtpci_legacy_register_vq_msix(device_t dev, int idx,
684     struct vtpci_interrupt *intr)
685 {
686 	struct vtpci_legacy_softc *sc;
687 	int error;
688 
689 	sc = device_get_softc(dev);
690 
691 	vtpci_legacy_select_virtqueue(sc, idx);
692 	error = vtpci_legacy_register_msix(sc, VIRTIO_MSI_QUEUE_VECTOR, intr);
693 	if (error) {
694 		device_printf(dev,
695 		    "unable to register virtqueue MSIX interrupt\n");
696 		return (error);
697 	}
698 
699 	return (0);
700 }
701 
702 static void
703 vtpci_legacy_reset(struct vtpci_legacy_softc *sc)
704 {
705 	/*
706 	 * Setting the status to RESET sets the host device to the
707 	 * original, uninitialized state.
708 	 */
709 	vtpci_legacy_set_status(sc, VIRTIO_CONFIG_STATUS_RESET);
710 	(void) vtpci_legacy_get_status(sc);
711 }
712 
713 static void
714 vtpci_legacy_select_virtqueue(struct vtpci_legacy_softc *sc, int idx)
715 {
716 	vtpci_legacy_write_header_2(sc, VIRTIO_PCI_QUEUE_SEL, idx);
717 }
718 
719 static uint8_t
720 vtpci_legacy_read_isr(device_t dev)
721 {
722 	struct vtpci_legacy_softc *sc;
723 
724 	sc = device_get_softc(dev);
725 
726 	return (vtpci_legacy_read_config_1(sc, VIRTIO_PCI_ISR));
727 }
728 
729 static uint16_t
730 vtpci_legacy_get_vq_size(device_t dev, int idx)
731 {
732 	struct vtpci_legacy_softc *sc;
733 
734 	sc = device_get_softc(dev);
735 
736 	vtpci_legacy_select_virtqueue(sc, idx);
737 	return (vtpci_legacy_read_header_2(sc, VIRTIO_PCI_QUEUE_NUM));
738 }
739 
740 static bus_size_t
741 vtpci_legacy_get_vq_notify_off(device_t dev, int idx)
742 {
743 	return (VIRTIO_PCI_QUEUE_NOTIFY);
744 }
745 
746 static void
747 vtpci_legacy_set_vq(device_t dev, struct virtqueue *vq)
748 {
749 	struct vtpci_legacy_softc *sc;
750 
751 	sc = device_get_softc(dev);
752 
753 	vtpci_legacy_select_virtqueue(sc, virtqueue_index(vq));
754 	vtpci_legacy_write_header_4(sc, VIRTIO_PCI_QUEUE_PFN,
755 	    virtqueue_paddr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT);
756 }
757 
758 static void
759 vtpci_legacy_disable_vq(device_t dev, int idx)
760 {
761 	struct vtpci_legacy_softc *sc;
762 
763 	sc = device_get_softc(dev);
764 
765 	vtpci_legacy_select_virtqueue(sc, idx);
766 	vtpci_legacy_write_header_4(sc, VIRTIO_PCI_QUEUE_PFN, 0);
767 }
768