xref: /freebsd/sys/dev/vmd/vmd.c (revision a2464ee12761660f50d0b6f59f233949ebcacc87)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021 Alexander Motin <mav@FreeBSD.org>
5  * Copyright 2019 Cisco Systems, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following 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 AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/kernel.h>
38 #include <sys/limits.h>
39 #include <sys/module.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 
44 #include <machine/bus.h>
45 #include <machine/resource.h>
46 #include <machine/intr_machdep.h>
47 #include <sys/rman.h>
48 #include <sys/lock.h>
49 #include <sys/mutex.h>
50 
51 #include <sys/pciio.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/pcireg.h>
54 #include <dev/pci/pci_private.h>
55 #include <dev/pci/pcib_private.h>
56 
57 #include <dev/vmd/vmd.h>
58 
59 #include "pcib_if.h"
60 
61 struct vmd_type {
62 	u_int16_t	vmd_vid;
63 	u_int16_t	vmd_did;
64 	char		*vmd_name;
65 	int		flags;
66 #define BUS_RESTRICT	1
67 #define VECTOR_OFFSET	2
68 };
69 
70 #define VMD_CAP		0x40
71 #define VMD_BUS_RESTRICT	0x1
72 
73 #define VMD_CONFIG	0x44
74 #define VMD_BUS_START(x)	((x >> 8) & 0x3)
75 
76 #define VMD_LOCK	0x70
77 
78 SYSCTL_NODE(_hw, OID_AUTO, vmd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
79     "Intel Volume Management Device tuning parameters");
80 
81 /*
82  * All MSIs within a group share address, so VMD can't distinguish them.
83  * It makes no sense to use more than one per device, only if required by
84  * some specific device drivers.
85  */
86 static int vmd_max_msi = 1;
87 SYSCTL_INT(_hw_vmd, OID_AUTO, max_msi, CTLFLAG_RWTUN, &vmd_max_msi, 0,
88     "Maximum number of MSI vectors per device");
89 
90 /*
91  * MSI-X can use different addresses, but we have limited number of MSI-X
92  * we can route to, so use conservative default to try to avoid sharing.
93  */
94 static int vmd_max_msix = 3;
95 SYSCTL_INT(_hw_vmd, OID_AUTO, max_msix, CTLFLAG_RWTUN, &vmd_max_msix, 0,
96     "Maximum number of MSI-X vectors per device");
97 
98 static struct vmd_type vmd_devs[] = {
99         { 0x8086, 0x201d, "Intel Volume Management Device", 0 },
100         { 0x8086, 0x28c0, "Intel Volume Management Device", BUS_RESTRICT },
101         { 0x8086, 0x467f, "Intel Volume Management Device", BUS_RESTRICT | VECTOR_OFFSET },
102         { 0x8086, 0x4c3d, "Intel Volume Management Device", BUS_RESTRICT | VECTOR_OFFSET },
103         { 0x8086, 0x9a0b, "Intel Volume Management Device", BUS_RESTRICT | VECTOR_OFFSET },
104         { 0x8086, 0xa77f, "Intel Volume Management Device", BUS_RESTRICT | VECTOR_OFFSET },
105         { 0, 0, NULL, 0 }
106 };
107 
108 static int
109 vmd_probe(device_t dev)
110 {
111 	struct vmd_type *t;
112 	uint16_t vid, did;
113 
114 	vid = pci_get_vendor(dev);
115 	did = pci_get_device(dev);
116 	for (t = vmd_devs; t->vmd_name != NULL; t++) {
117 		if (vid == t->vmd_vid && did == t->vmd_did) {
118 			device_set_desc(dev, t->vmd_name);
119 			return (BUS_PROBE_DEFAULT);
120 		}
121 	}
122 	return (ENXIO);
123 }
124 
125 static void
126 vmd_free(struct vmd_softc *sc)
127 {
128 	struct vmd_irq *vi;
129 	struct vmd_irq_user *u;
130 	int i;
131 
132 	if (sc->psc.bus.rman.rm_end != 0)
133 		rman_fini(&sc->psc.bus.rman);
134 	if (sc->psc.mem.rman.rm_end != 0)
135 		rman_fini(&sc->psc.mem.rman);
136 	while ((u = LIST_FIRST(&sc->vmd_users)) != NULL) {
137 		LIST_REMOVE(u, viu_link);
138 		free(u, M_DEVBUF);
139 	}
140 	if (sc->vmd_irq != NULL) {
141 		for (i = 0; i < sc->vmd_msix_count; i++) {
142 			vi = &sc->vmd_irq[i];
143 			if (vi->vi_res == NULL)
144 				continue;
145 			bus_teardown_intr(sc->psc.dev, vi->vi_res,
146 			    vi->vi_handle);
147 			bus_release_resource(sc->psc.dev, SYS_RES_IRQ,
148 			    vi->vi_rid, vi->vi_res);
149 		}
150 	}
151 	free(sc->vmd_irq, M_DEVBUF);
152 	sc->vmd_irq = NULL;
153 	pci_release_msi(sc->psc.dev);
154 	for (i = 0; i < VMD_MAX_BAR; i++) {
155 		if (sc->vmd_regs_res[i] != NULL)
156 			bus_release_resource(sc->psc.dev, SYS_RES_MEMORY,
157 			    sc->vmd_regs_rid[i], sc->vmd_regs_res[i]);
158 	}
159 }
160 
161 /* Hidden PCI Roots are hidden in BAR(0). */
162 
163 static uint32_t
164 vmd_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width)
165 {
166 	struct vmd_softc *sc;
167 	bus_addr_t offset;
168 
169 	sc = device_get_softc(dev);
170 	if (b < sc->vmd_bus_start || b > sc->vmd_bus_end)
171 		return (0xffffffff);
172 
173 	offset = ((b - sc->vmd_bus_start) << 20) + (s << 15) + (f << 12) + reg;
174 
175 	switch (width) {
176 	case 4:
177 		return (bus_space_read_4(sc->vmd_btag, sc->vmd_bhandle,
178 		    offset));
179 	case 2:
180 		return (bus_space_read_2(sc->vmd_btag, sc->vmd_bhandle,
181 		    offset));
182 	case 1:
183 		return (bus_space_read_1(sc->vmd_btag, sc->vmd_bhandle,
184 		    offset));
185 	default:
186 		__assert_unreachable();
187 		return (0xffffffff);
188 	}
189 }
190 
191 static void
192 vmd_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg,
193     uint32_t val, int width)
194 {
195 	struct vmd_softc *sc;
196 	bus_addr_t offset;
197 
198 	sc = device_get_softc(dev);
199 	if (b < sc->vmd_bus_start || b > sc->vmd_bus_end)
200 		return;
201 
202 	offset = ((b - sc->vmd_bus_start) << 20) + (s << 15) + (f << 12) + reg;
203 
204 	switch (width) {
205 	case 4:
206 		return (bus_space_write_4(sc->vmd_btag, sc->vmd_bhandle,
207 		    offset, val));
208 	case 2:
209 		return (bus_space_write_2(sc->vmd_btag, sc->vmd_bhandle,
210 		    offset, val));
211 	case 1:
212 		return (bus_space_write_1(sc->vmd_btag, sc->vmd_bhandle,
213 		    offset, val));
214 	default:
215 		__assert_unreachable();
216 	}
217 }
218 
219 static int
220 vmd_intr(void *arg)
221 {
222 	/*
223 	 * We have nothing to do here, but we have to register some interrupt
224 	 * handler to make PCI code setup and enable the MSI-X vector.
225 	 */
226 	return (FILTER_STRAY);
227 }
228 
229 static int
230 vmd_attach(device_t dev)
231 {
232 	struct vmd_softc *sc;
233 	struct pcib_secbus *bus;
234 	struct pcib_window *w;
235 	struct vmd_type *t;
236 	struct vmd_irq *vi;
237 	uint16_t vid, did;
238 	uint32_t bar;
239 	int i, j, error;
240 	char buf[64];
241 
242 	sc = device_get_softc(dev);
243 	bzero(sc, sizeof(*sc));
244 	sc->psc.dev = dev;
245 	sc->psc.domain = PCI_DOMAINMAX - device_get_unit(dev);
246 
247 	pci_enable_busmaster(dev);
248 
249 	for (i = 0, j = 0; i < VMD_MAX_BAR; i++, j++) {
250 		sc->vmd_regs_rid[i] = PCIR_BAR(j);
251 		bar = pci_read_config(dev, PCIR_BAR(0), 4);
252 		if (PCI_BAR_MEM(bar) && (bar & PCIM_BAR_MEM_TYPE) ==
253 		    PCIM_BAR_MEM_64)
254 			j++;
255 		if ((sc->vmd_regs_res[i] = bus_alloc_resource_any(dev,
256 		    SYS_RES_MEMORY, &sc->vmd_regs_rid[i], RF_ACTIVE)) == NULL) {
257 			device_printf(dev, "Cannot allocate resources\n");
258 			goto fail;
259 		}
260 	}
261 
262 	sc->vmd_btag = rman_get_bustag(sc->vmd_regs_res[0]);
263 	sc->vmd_bhandle = rman_get_bushandle(sc->vmd_regs_res[0]);
264 
265 	vid = pci_get_vendor(dev);
266 	did = pci_get_device(dev);
267 	for (t = vmd_devs; t->vmd_name != NULL; t++) {
268 		if (vid == t->vmd_vid && did == t->vmd_did)
269 			break;
270 	}
271 
272 	sc->vmd_bus_start = 0;
273 	if ((t->flags & BUS_RESTRICT) &&
274 	    (pci_read_config(dev, VMD_CAP, 2) & VMD_BUS_RESTRICT)) {
275 		switch (VMD_BUS_START(pci_read_config(dev, VMD_CONFIG, 2))) {
276 		case 0:
277 			sc->vmd_bus_start = 0;
278 			break;
279 		case 1:
280 			sc->vmd_bus_start = 128;
281 			break;
282 		case 2:
283 			sc->vmd_bus_start = 224;
284 			break;
285 		default:
286 			device_printf(dev, "Unknown bus offset\n");
287 			goto fail;
288 		}
289 	}
290 	sc->vmd_bus_end = MIN(PCI_BUSMAX, sc->vmd_bus_start +
291 	    (rman_get_size(sc->vmd_regs_res[0]) >> 20) - 1);
292 
293 	bus = &sc->psc.bus;
294 	bus->sec = sc->vmd_bus_start;
295 	bus->sub = sc->vmd_bus_end;
296 	bus->dev = dev;
297 	bus->rman.rm_start = 0;
298 	bus->rman.rm_end = PCI_BUSMAX;
299 	bus->rman.rm_type = RMAN_ARRAY;
300 	snprintf(buf, sizeof(buf), "%s bus numbers", device_get_nameunit(dev));
301 	bus->rman.rm_descr = strdup(buf, M_DEVBUF);
302 	error = rman_init(&bus->rman);
303 	if (error) {
304 		device_printf(dev, "Failed to initialize bus rman\n");
305 		bus->rman.rm_end = 0;
306 		goto fail;
307 	}
308 	error = rman_manage_region(&bus->rman, sc->vmd_bus_start,
309 	    sc->vmd_bus_end);
310 	if (error) {
311 		device_printf(dev, "Failed to add resource to bus rman\n");
312 		goto fail;
313 	}
314 
315 	w = &sc->psc.mem;
316 	w->rman.rm_type = RMAN_ARRAY;
317 	snprintf(buf, sizeof(buf), "%s memory window", device_get_nameunit(dev));
318 	w->rman.rm_descr = strdup(buf, M_DEVBUF);
319 	error = rman_init(&w->rman);
320 	if (error) {
321 		device_printf(dev, "Failed to initialize memory rman\n");
322 		w->rman.rm_end = 0;
323 		goto fail;
324 	}
325 	error = rman_manage_region(&w->rman,
326 	    rman_get_start(sc->vmd_regs_res[1]),
327 	    rman_get_end(sc->vmd_regs_res[1]));
328 	if (error) {
329 		device_printf(dev, "Failed to add resource to memory rman\n");
330 		goto fail;
331 	}
332 	error = rman_manage_region(&w->rman,
333 	    rman_get_start(sc->vmd_regs_res[2]) + 0x2000,
334 	    rman_get_end(sc->vmd_regs_res[2]));
335 	if (error) {
336 		device_printf(dev, "Failed to add resource to memory rman\n");
337 		goto fail;
338 	}
339 
340 	LIST_INIT(&sc->vmd_users);
341 	sc->vmd_fist_vector = (t->flags & VECTOR_OFFSET) ? 1 : 0;
342 	sc->vmd_msix_count = pci_msix_count(dev);
343 	if (pci_alloc_msix(dev, &sc->vmd_msix_count) == 0) {
344 		sc->vmd_irq = malloc(sizeof(struct vmd_irq) *
345 		    sc->vmd_msix_count, M_DEVBUF, M_WAITOK | M_ZERO);
346 		for (i = 0; i < sc->vmd_msix_count; i++) {
347 			vi = &sc->vmd_irq[i];
348 			vi->vi_rid = i + 1;
349 			vi->vi_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
350 			    &vi->vi_rid, RF_ACTIVE | RF_SHAREABLE);
351 			if (vi->vi_res == NULL) {
352 				device_printf(dev, "Failed to allocate irq\n");
353 				goto fail;
354 			}
355 			vi->vi_irq = rman_get_start(vi->vi_res);
356 			if (bus_setup_intr(dev, vi->vi_res, INTR_TYPE_MISC |
357 			    INTR_MPSAFE, vmd_intr, NULL, vi, &vi->vi_handle)) {
358 				device_printf(dev, "Can't set up interrupt\n");
359 				bus_release_resource(dev, SYS_RES_IRQ,
360 				    vi->vi_rid, vi->vi_res);
361 				vi->vi_res = NULL;
362 				goto fail;
363 			}
364 		}
365 	}
366 
367 	sc->vmd_dma_tag = bus_get_dma_tag(dev);
368 
369 	sc->psc.child = device_add_child(dev, "pci", -1);
370 	return (bus_generic_attach(dev));
371 
372 fail:
373 	vmd_free(sc);
374 	return (ENXIO);
375 }
376 
377 static int
378 vmd_detach(device_t dev)
379 {
380 	struct vmd_softc *sc = device_get_softc(dev);
381 	int error;
382 
383 	error = bus_generic_detach(dev);
384 	if (error)
385 		return (error);
386 	error = device_delete_children(dev);
387 	if (error)
388 		return (error);
389 	vmd_free(sc);
390 	return (0);
391 }
392 
393 static bus_dma_tag_t
394 vmd_get_dma_tag(device_t dev, device_t child)
395 {
396 	struct vmd_softc *sc = device_get_softc(dev);
397 
398 	return (sc->vmd_dma_tag);
399 }
400 
401 static struct resource *
402 vmd_alloc_resource(device_t dev, device_t child, int type, int *rid,
403     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
404 {
405 	struct vmd_softc *sc = device_get_softc(dev);
406 	struct resource *res;
407 
408 	switch (type) {
409 	case SYS_RES_IRQ:
410 		/* VMD harwdare does not support legacy interrupts. */
411 		if (*rid == 0)
412 			return (NULL);
413 		return (bus_generic_alloc_resource(dev, child, type, rid,
414 		    start, end, count, flags | RF_SHAREABLE));
415 	case SYS_RES_MEMORY:
416 		res = rman_reserve_resource(&sc->psc.mem.rman, start, end,
417 		    count, flags, child);
418 		if (res == NULL)
419 			return (NULL);
420 		if (bootverbose)
421 			device_printf(dev,
422 			    "allocated memory range (%#jx-%#jx) for rid %d of %s\n",
423 			    rman_get_start(res), rman_get_end(res), *rid,
424 			    pcib_child_name(child));
425 		break;
426 	case PCI_RES_BUS:
427 		res = rman_reserve_resource(&sc->psc.bus.rman, start, end,
428 		    count, flags, child);
429 		if (res == NULL)
430 			return (NULL);
431 		if (bootverbose)
432 			device_printf(dev,
433 			    "allocated bus range (%ju-%ju) for rid %d of %s\n",
434 			    rman_get_start(res), rman_get_end(res), *rid,
435 			    pcib_child_name(child));
436 		break;
437 	default:
438 		/* VMD harwdare does not support I/O ports. */
439 		return (NULL);
440 	}
441 	rman_set_rid(res, *rid);
442 	return (res);
443 }
444 
445 static int
446 vmd_adjust_resource(device_t dev, device_t child, int type,
447     struct resource *r, rman_res_t start, rman_res_t end)
448 {
449 
450 	if (type == SYS_RES_IRQ) {
451 		return (bus_generic_adjust_resource(dev, child, type, r,
452 		    start, end));
453 	}
454 	return (rman_adjust_resource(r, start, end));
455 }
456 
457 static int
458 vmd_release_resource(device_t dev, device_t child, int type, int rid,
459     struct resource *r)
460 {
461 
462 	if (type == SYS_RES_IRQ) {
463 		return (bus_generic_release_resource(dev, child, type, rid,
464 		    r));
465 	}
466 	return (rman_release_resource(r));
467 }
468 
469 static int
470 vmd_route_interrupt(device_t dev, device_t child, int pin)
471 {
472 
473 	/* VMD harwdare does not support legacy interrupts. */
474 	return (PCI_INVALID_IRQ);
475 }
476 
477 static int
478 vmd_alloc_msi(device_t dev, device_t child, int count, int maxcount,
479     int *irqs)
480 {
481 	struct vmd_softc *sc = device_get_softc(dev);
482 	struct vmd_irq_user *u;
483 	int i, ibest = 0, best = INT_MAX;
484 
485 	if (count > vmd_max_msi)
486 		return (ENOSPC);
487 	LIST_FOREACH(u, &sc->vmd_users, viu_link) {
488 		if (u->viu_child == child)
489 			return (EBUSY);
490 	}
491 
492 	for (i = sc->vmd_fist_vector; i < sc->vmd_msix_count; i++) {
493 		if (best > sc->vmd_irq[i].vi_nusers) {
494 			best = sc->vmd_irq[i].vi_nusers;
495 			ibest = i;
496 		}
497 	}
498 
499 	u = malloc(sizeof(*u), M_DEVBUF, M_WAITOK | M_ZERO);
500 	u->viu_child = child;
501 	u->viu_vector = ibest;
502 	LIST_INSERT_HEAD(&sc->vmd_users, u, viu_link);
503 	sc->vmd_irq[ibest].vi_nusers += count;
504 
505 	for (i = 0; i < count; i++)
506 		irqs[i] = sc->vmd_irq[ibest].vi_irq;
507 	return (0);
508 }
509 
510 static int
511 vmd_release_msi(device_t dev, device_t child, int count, int *irqs)
512 {
513 	struct vmd_softc *sc = device_get_softc(dev);
514 	struct vmd_irq_user *u;
515 
516 	LIST_FOREACH(u, &sc->vmd_users, viu_link) {
517 		if (u->viu_child == child) {
518 			sc->vmd_irq[u->viu_vector].vi_nusers -= count;
519 			LIST_REMOVE(u, viu_link);
520 			free(u, M_DEVBUF);
521 			return (0);
522 		}
523 	}
524 	return (EINVAL);
525 }
526 
527 static int
528 vmd_alloc_msix(device_t dev, device_t child, int *irq)
529 {
530 	struct vmd_softc *sc = device_get_softc(dev);
531 	struct vmd_irq_user *u;
532 	int i, ibest = 0, best = INT_MAX;
533 
534 	i = 0;
535 	LIST_FOREACH(u, &sc->vmd_users, viu_link) {
536 		if (u->viu_child == child)
537 			i++;
538 	}
539 	if (i >= vmd_max_msix)
540 		return (ENOSPC);
541 
542 	for (i = sc->vmd_fist_vector; i < sc->vmd_msix_count; i++) {
543 		if (best > sc->vmd_irq[i].vi_nusers) {
544 			best = sc->vmd_irq[i].vi_nusers;
545 			ibest = i;
546 		}
547 	}
548 
549 	u = malloc(sizeof(*u), M_DEVBUF, M_WAITOK | M_ZERO);
550 	u->viu_child = child;
551 	u->viu_vector = ibest;
552 	LIST_INSERT_HEAD(&sc->vmd_users, u, viu_link);
553 	sc->vmd_irq[ibest].vi_nusers++;
554 
555 	*irq = sc->vmd_irq[ibest].vi_irq;
556 	return (0);
557 }
558 
559 static int
560 vmd_release_msix(device_t dev, device_t child, int irq)
561 {
562 	struct vmd_softc *sc = device_get_softc(dev);
563 	struct vmd_irq_user *u;
564 
565 	LIST_FOREACH(u, &sc->vmd_users, viu_link) {
566 		if (u->viu_child == child &&
567 		    sc->vmd_irq[u->viu_vector].vi_irq == irq) {
568 			sc->vmd_irq[u->viu_vector].vi_nusers--;
569 			LIST_REMOVE(u, viu_link);
570 			free(u, M_DEVBUF);
571 			return (0);
572 		}
573 	}
574 	return (EINVAL);
575 }
576 
577 static int
578 vmd_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, uint32_t *data)
579 {
580 	struct vmd_softc *sc = device_get_softc(dev);
581 	int i;
582 
583 	for (i = sc->vmd_fist_vector; i < sc->vmd_msix_count; i++) {
584 		if (sc->vmd_irq[i].vi_irq == irq)
585 			break;
586 	}
587 	if (i >= sc->vmd_msix_count)
588 		return (EINVAL);
589 	*addr = MSI_INTEL_ADDR_BASE | (i << 12);
590 	*data = 0;
591 	return (0);
592 }
593 
594 static device_method_t vmd_pci_methods[] = {
595 	/* Device interface */
596 	DEVMETHOD(device_probe,			vmd_probe),
597 	DEVMETHOD(device_attach,		vmd_attach),
598 	DEVMETHOD(device_detach,		vmd_detach),
599 	DEVMETHOD(device_suspend,		bus_generic_suspend),
600 	DEVMETHOD(device_resume,		bus_generic_resume),
601 	DEVMETHOD(device_shutdown,		bus_generic_shutdown),
602 
603 	/* Bus interface */
604 	DEVMETHOD(bus_get_dma_tag,		vmd_get_dma_tag),
605 	DEVMETHOD(bus_read_ivar,		pcib_read_ivar),
606 	DEVMETHOD(bus_write_ivar,		pcib_write_ivar),
607 	DEVMETHOD(bus_alloc_resource,		vmd_alloc_resource),
608 	DEVMETHOD(bus_adjust_resource,		vmd_adjust_resource),
609 	DEVMETHOD(bus_release_resource,		vmd_release_resource),
610 	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
611 	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
612 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
613 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
614 
615 	/* pcib interface */
616 	DEVMETHOD(pcib_maxslots,		pcib_maxslots),
617 	DEVMETHOD(pcib_read_config,		vmd_read_config),
618 	DEVMETHOD(pcib_write_config,		vmd_write_config),
619 	DEVMETHOD(pcib_route_interrupt,		vmd_route_interrupt),
620 	DEVMETHOD(pcib_alloc_msi,		vmd_alloc_msi),
621 	DEVMETHOD(pcib_release_msi,		vmd_release_msi),
622 	DEVMETHOD(pcib_alloc_msix,		vmd_alloc_msix),
623 	DEVMETHOD(pcib_release_msix,		vmd_release_msix),
624 	DEVMETHOD(pcib_map_msi,			vmd_map_msi),
625 	DEVMETHOD(pcib_request_feature,		pcib_request_feature_allow),
626 
627 	DEVMETHOD_END
628 };
629 
630 DEFINE_CLASS_0(pcib, vmd_pci_driver, vmd_pci_methods, sizeof(struct vmd_softc));
631 DRIVER_MODULE(vmd, pci, vmd_pci_driver, NULL, NULL);
632 MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, vmd,
633     vmd_devs, nitems(vmd_devs) - 1);
634