xref: /freebsd/sys/dev/xen/pcifront/pcifront.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2006, Cisco Systems, Inc.
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  *
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  * 3. Neither the name of Cisco Systems, Inc. nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/module.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/queue.h>
44 
45 #include <machine/vmparam.h>
46 #include <vm/vm.h>
47 #include <vm/pmap.h>
48 
49 #include <machine/bus.h>
50 #include <machine/resource.h>
51 #include <machine/frame.h>
52 
53 #include <sys/bus.h>
54 #include <sys/rman.h>
55 
56 #include <machine/intr_machdep.h>
57 
58 #include <machine/xen-os.h>
59 #include <machine/hypervisor.h>
60 #include <machine/hypervisor-ifs.h>
61 #include <machine/xen_intr.h>
62 #include <machine/evtchn.h>
63 #include <machine/xenbus.h>
64 #include <machine/gnttab.h>
65 #include <machine/xen-public/memory.h>
66 #include <machine/xen-public/io/pciif.h>
67 
68 #include <sys/pciio.h>
69 #include <dev/pci/pcivar.h>
70 #include "pcib_if.h"
71 
72 #ifdef XEN_PCIDEV_FE_DEBUG
73 #define DPRINTF(fmt, args...) \
74     printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
75 #else
76 #define DPRINTF(fmt, args...) ((void)0)
77 #endif
78 #define WPRINTF(fmt, args...) \
79     printf("pcifront (%s:%d): " fmt, __FUNCTION__, __LINE__, ##args)
80 
81 #define INVALID_GRANT_REF (0)
82 #define INVALID_EVTCHN    (-1)
83 #define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
84 
85 struct pcifront_device {
86 	STAILQ_ENTRY(pcifront_device) next;
87 
88 	struct xenbus_device *xdev;
89 
90 	int unit;
91 	int evtchn;
92 	int gnt_ref;
93 
94 	/* Lock this when doing any operations in sh_info */
95 	struct mtx sh_info_lock;
96 	struct xen_pci_sharedinfo *sh_info;
97 
98 	device_t ndev;
99 
100 	int ref_cnt;
101 };
102 
103 static STAILQ_HEAD(pcifront_dlist, pcifront_device) pdev_list = STAILQ_HEAD_INITIALIZER(pdev_list);
104 
105 struct xpcib_softc {
106 	int domain;
107 	int bus;
108 	struct pcifront_device *pdev;
109 };
110 
111 /* Allocate a PCI device structure */
112 static struct pcifront_device *
113 alloc_pdev(struct xenbus_device *xdev)
114 {
115 	struct pcifront_device *pdev = NULL;
116 	int err, unit;
117 
118 	err = sscanf(xdev->nodename, "device/pci/%d", &unit);
119 	if (err != 1) {
120 		if (err == 0)
121 			err = -EINVAL;
122 		xenbus_dev_fatal(pdev->xdev, err, "Error scanning pci device instance number");
123 		goto out;
124 	}
125 
126 	pdev = (struct pcifront_device *)malloc(sizeof(struct pcifront_device), M_DEVBUF, M_NOWAIT);
127 	if (pdev == NULL) {
128 		err = -ENOMEM;
129 		xenbus_dev_fatal(xdev, err, "Error allocating pcifront_device struct");
130 		goto out;
131 	}
132 	pdev->unit = unit;
133 	pdev->xdev = xdev;
134 	pdev->ref_cnt = 1;
135 
136 	pdev->sh_info = (struct xen_pci_sharedinfo *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
137 	if (pdev->sh_info == NULL) {
138 		free(pdev, M_DEVBUF);
139 		pdev = NULL;
140 		err = -ENOMEM;
141 		xenbus_dev_fatal(xdev, err, "Error allocating sh_info struct");
142 		goto out;
143 	}
144 	pdev->sh_info->flags = 0;
145 
146 	xdev->data = pdev;
147 
148 	mtx_init(&pdev->sh_info_lock, "info_lock", "pci shared dev info lock", MTX_DEF);
149 
150 	pdev->evtchn = INVALID_EVTCHN;
151 	pdev->gnt_ref = INVALID_GRANT_REF;
152 
153 	STAILQ_INSERT_TAIL(&pdev_list, pdev, next);
154 
155 	DPRINTF("Allocated pdev @ 0x%p (unit=%d)\n", pdev, unit);
156 
157  out:
158 	return pdev;
159 }
160 
161 /* Hold a reference to a pcifront device */
162 static void
163 get_pdev(struct pcifront_device *pdev)
164 {
165 	pdev->ref_cnt++;
166 }
167 
168 /* Release a reference to a pcifront device */
169 static void
170 put_pdev(struct pcifront_device *pdev)
171 {
172 	if (--pdev->ref_cnt > 0)
173 		return;
174 
175 	DPRINTF("freeing pdev @ 0x%p (ref_cnt=%d)\n", pdev, pdev->ref_cnt);
176 
177 	if (pdev->evtchn != INVALID_EVTCHN)
178 		xenbus_free_evtchn(pdev->xdev, pdev->evtchn);
179 
180 	if (pdev->gnt_ref != INVALID_GRANT_REF)
181 		gnttab_end_foreign_access(pdev->gnt_ref, 0, (void *)pdev->sh_info);
182 
183 	pdev->xdev->data = NULL;
184 
185 	free(pdev, M_DEVBUF);
186 }
187 
188 
189 /* Write to the xenbus info needed by backend */
190 static int
191 pcifront_publish_info(struct pcifront_device *pdev)
192 {
193 	int err = 0;
194 	struct xenbus_transaction *trans;
195 
196 	err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info));
197 	if (err < 0) {
198 		WPRINTF("error granting access to ring page\n");
199 		goto out;
200 	}
201 
202 	pdev->gnt_ref = err;
203 
204 	err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn);
205 	if (err)
206 		goto out;
207 
208  do_publish:
209 	trans = xenbus_transaction_start();
210 	if (IS_ERR(trans)) {
211 		xenbus_dev_fatal(pdev->xdev, err,
212 						 "Error writing configuration for backend "
213 						 "(start transaction)");
214 		goto out;
215 	}
216 
217 	err = xenbus_printf(trans, pdev->xdev->nodename,
218 						"pci-op-ref", "%u", pdev->gnt_ref);
219 	if (!err)
220 		err = xenbus_printf(trans, pdev->xdev->nodename,
221 							"event-channel", "%u", pdev->evtchn);
222 	if (!err)
223 		err = xenbus_printf(trans, pdev->xdev->nodename,
224 							"magic", XEN_PCI_MAGIC);
225 	if (!err)
226 		err = xenbus_switch_state(pdev->xdev, trans,
227 								  XenbusStateInitialised);
228 
229 	if (err) {
230 		xenbus_transaction_end(trans, 1);
231 		xenbus_dev_fatal(pdev->xdev, err,
232 						 "Error writing configuration for backend");
233 		goto out;
234 	} else {
235 		err = xenbus_transaction_end(trans, 0);
236 		if (err == -EAGAIN)
237 			goto do_publish;
238 		else if (err) {
239 			xenbus_dev_fatal(pdev->xdev, err,
240 							 "Error completing transaction for backend");
241 			goto out;
242 		}
243 	}
244 
245  out:
246 	return err;
247 }
248 
249 /* The backend is now connected so complete the connection process on our side */
250 static int
251 pcifront_connect(struct pcifront_device *pdev)
252 {
253 	device_t nexus;
254 	devclass_t nexus_devclass;
255 
256 	/* We will add our device as a child of the nexus0 device */
257 	if (!(nexus_devclass = devclass_find("nexus")) ||
258 		!(nexus = devclass_get_device(nexus_devclass, 0))) {
259 		WPRINTF("could not find nexus0!\n");
260 		return -1;
261 	}
262 
263 	/* Create a newbus device representing this frontend instance */
264 	pdev->ndev = BUS_ADD_CHILD(nexus, 0, "xpcife", pdev->unit);
265 	if (!pdev->ndev) {
266 		WPRINTF("could not create xpcife%d!\n", pdev->unit);
267 		return -EFAULT;
268 	}
269 	get_pdev(pdev);
270 	device_set_ivars(pdev->ndev, pdev);
271 
272 	/* Good to go connected now */
273 	xenbus_switch_state(pdev->xdev, NULL, XenbusStateConnected);
274 
275 	printf("pcifront: connected to %s\n", pdev->xdev->nodename);
276 
277 	mtx_lock(&Giant);
278 	device_probe_and_attach(pdev->ndev);
279 	mtx_unlock(&Giant);
280 
281 	return 0;
282 }
283 
284 /* The backend is closing so process a disconnect */
285 static int
286 pcifront_disconnect(struct pcifront_device *pdev)
287 {
288 	int err = 0;
289 	XenbusState prev_state;
290 
291 	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
292 
293 	if (prev_state < XenbusStateClosing) {
294 		err = xenbus_switch_state(pdev->xdev, NULL, XenbusStateClosing);
295 		if (!err && prev_state == XenbusStateConnected) {
296 			/* TODO - need to detach the newbus devices */
297 		}
298 	}
299 
300 	return err;
301 }
302 
303 /* Process a probe from the xenbus */
304 static int
305 pcifront_probe(struct xenbus_device *xdev,
306 			   const struct xenbus_device_id *id)
307 {
308 	int err = 0;
309 	struct pcifront_device *pdev;
310 
311 	DPRINTF("xenbus probing\n");
312 
313 	if ((pdev = alloc_pdev(xdev)) == NULL)
314 		goto out;
315 
316 	err = pcifront_publish_info(pdev);
317 
318  out:
319 	if (err)
320 		put_pdev(pdev);
321 	return err;
322 }
323 
324 /* Remove the xenbus PCI device */
325 static int
326 pcifront_remove(struct xenbus_device *xdev)
327 {
328 	DPRINTF("removing xenbus device node (%s)\n", xdev->nodename);
329 	if (xdev->data)
330 		put_pdev(xdev->data);
331 	return 0;
332 }
333 
334 /* Called by xenbus when our backend node changes state */
335 static void
336 pcifront_backend_changed(struct xenbus_device *xdev,
337 						 XenbusState be_state)
338 {
339 	struct pcifront_device *pdev = xdev->data;
340 
341 	switch (be_state) {
342 	case XenbusStateClosing:
343 		DPRINTF("backend closing (%s)\n", xdev->nodename);
344 		pcifront_disconnect(pdev);
345 		break;
346 
347 	case XenbusStateClosed:
348 		DPRINTF("backend closed (%s)\n", xdev->nodename);
349 		pcifront_disconnect(pdev);
350 		break;
351 
352 	case XenbusStateConnected:
353 		DPRINTF("backend connected (%s)\n", xdev->nodename);
354 		pcifront_connect(pdev);
355 		break;
356 
357 	default:
358 		break;
359 	}
360 }
361 
362 /* Process PCI operation */
363 static int
364 do_pci_op(struct pcifront_device *pdev, struct xen_pci_op *op)
365 {
366 	int err = 0;
367 	struct xen_pci_op *active_op = &pdev->sh_info->op;
368 	evtchn_port_t port = pdev->evtchn;
369 	time_t timeout;
370 
371 	mtx_lock(&pdev->sh_info_lock);
372 
373 	memcpy(active_op, op, sizeof(struct xen_pci_op));
374 
375 	/* Go */
376 	wmb();
377 	set_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
378 	notify_remote_via_evtchn(port);
379 
380 	timeout = time_uptime + 2;
381 
382 	clear_evtchn(port);
383 
384 	/* Spin while waiting for the answer */
385 	while (test_bit
386 	       (_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) {
387 		int err = HYPERVISOR_poll(&port, 1, 3 * hz);
388 		if (err)
389 			panic("Failed HYPERVISOR_poll: err=%d", err);
390 		clear_evtchn(port);
391 		if (time_uptime > timeout) {
392 			WPRINTF("pciback not responding!!!\n");
393 			clear_bit(_XEN_PCIF_active,
394 				  (unsigned long *)&pdev->sh_info->flags);
395 			err = XEN_PCI_ERR_dev_not_found;
396 			goto out;
397 		}
398 	}
399 
400 	memcpy(op, active_op, sizeof(struct xen_pci_op));
401 
402 	err = op->err;
403  out:
404 	mtx_unlock(&pdev->sh_info_lock);
405 	return err;
406 }
407 
408 /* ** XenBus Driver registration ** */
409 
410 static struct xenbus_device_id pcifront_ids[] = {
411 	{ "pci" },
412 	{ "" }
413 };
414 
415 static struct xenbus_driver pcifront = {
416 	.name = "pcifront",
417 	.ids = pcifront_ids,
418 	.probe = pcifront_probe,
419 	.remove = pcifront_remove,
420 	.otherend_changed = pcifront_backend_changed,
421 };
422 
423 /* Register the driver with xenbus during sys init */
424 static void
425 pcifront_init(void *unused)
426 {
427 	if ((xen_start_info->flags & SIF_INITDOMAIN))
428 		return;
429 
430 	DPRINTF("xenbus registering\n");
431 
432 	xenbus_register_frontend(&pcifront);
433 }
434 
435 SYSINIT(pciif, SI_SUB_PSEUDO, SI_ORDER_ANY, pcifront_init, NULL)
436 
437 
438 /* Newbus xpcife device driver probe */
439 static int
440 xpcife_probe(device_t dev)
441 {
442 #ifdef XEN_PCIDEV_FE_DEBUG
443 	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
444 	DPRINTF("xpcife probe (unit=%d)\n", pdev->unit);
445 #endif
446 	return (BUS_PROBE_NOWILDCARD);
447 }
448 
449 /* Newbus xpcife device driver attach */
450 static int
451 xpcife_attach(device_t dev)
452 {
453 	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(dev);
454 	int i, num_roots, len, err;
455 	char str[64];
456 	unsigned int domain, bus;
457 
458 	DPRINTF("xpcife attach (unit=%d)\n", pdev->unit);
459 
460 	err = xenbus_scanf(NULL, pdev->xdev->otherend,
461 					   "root_num", "%d", &num_roots);
462 	if (err != 1) {
463 		if (err == 0)
464 			err = -EINVAL;
465 		xenbus_dev_fatal(pdev->xdev, err,
466 						 "Error reading number of PCI roots");
467 		goto out;
468 	}
469 
470 	/* Add a pcib device for each root */
471 	for (i = 0; i < num_roots; i++) {
472 		device_t child;
473 
474 		len = snprintf(str, sizeof(str), "root-%d", i);
475 		if (unlikely(len >= (sizeof(str) - 1))) {
476 			err = -ENOMEM;
477 			goto out;
478 		}
479 
480 		err = xenbus_scanf(NULL, pdev->xdev->otherend, str,
481 						   "%x:%x", &domain, &bus);
482 		if (err != 2) {
483 			if (err >= 0)
484 				err = -EINVAL;
485 			xenbus_dev_fatal(pdev->xdev, err,
486 							 "Error reading PCI root %d", i);
487 			goto out;
488 		}
489 		err = 0;
490 		if (domain != pdev->xdev->otherend_id) {
491 			err = -EINVAL;
492 			xenbus_dev_fatal(pdev->xdev, err,
493 							 "Domain mismatch %d != %d", domain, pdev->xdev->otherend_id);
494 			goto out;
495 		}
496 
497 		child = device_add_child(dev, "pcib", bus);
498 		if (!child) {
499 			err = -ENOMEM;
500 			xenbus_dev_fatal(pdev->xdev, err,
501 							 "Unable to create pcib%d", bus);
502 			goto out;
503 		}
504 	}
505 
506  out:
507 	return bus_generic_attach(dev);
508 }
509 
510 static devclass_t xpcife_devclass;
511 
512 static device_method_t xpcife_methods[] = {
513 	/* Device interface */
514 	DEVMETHOD(device_probe, xpcife_probe),
515 	DEVMETHOD(device_attach, xpcife_attach),
516 	DEVMETHOD(device_detach,	bus_generic_detach),
517 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
518 	DEVMETHOD(device_suspend,	bus_generic_suspend),
519 	DEVMETHOD(device_resume,	bus_generic_resume),
520     /* Bus interface */
521     DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
522     DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
523     DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
524     DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
525     DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
526     DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
527 
528 	DEVMETHOD_END
529 };
530 
531 static driver_t xpcife_driver = {
532 	"xpcife",
533 	xpcife_methods,
534 	0,
535 };
536 
537 DRIVER_MODULE(xpcife, nexus, xpcife_driver, xpcife_devclass, 0, 0);
538 
539 
540 /* Newbus xen pcib device driver probe */
541 static int
542 xpcib_probe(device_t dev)
543 {
544 	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
545 	struct pcifront_device *pdev = (struct pcifront_device *)device_get_ivars(device_get_parent(dev));
546 
547 	DPRINTF("xpcib probe (bus=%d)\n", device_get_unit(dev));
548 
549 	sc->domain = pdev->xdev->otherend_id;
550 	sc->bus = device_get_unit(dev);
551 	sc->pdev = pdev;
552 
553 	return 0;
554 }
555 
556 /* Newbus xen pcib device driver attach */
557 static int
558 xpcib_attach(device_t dev)
559 {
560 	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
561 
562 	DPRINTF("xpcib attach (bus=%d)\n", sc->bus);
563 
564 	device_add_child(dev, "pci", -1);
565 	return bus_generic_attach(dev);
566 }
567 
568 static int
569 xpcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
570 {
571 	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
572 	switch (which) {
573 	case  PCIB_IVAR_BUS:
574 		*result = sc->bus;
575 		return 0;
576 	}
577 	return ENOENT;
578 }
579 
580 /* Return the number of slots supported */
581 static int
582 xpcib_maxslots(device_t dev)
583 {
584 	return 31;
585 }
586 
587 #define PCI_DEVFN(slot,func)	((((slot) & 0x1f) << 3) | ((func) & 0x07))
588 
589 /* Read configuration space register */
590 static u_int32_t
591 xpcib_read_config(device_t dev, int bus, int slot, int func,
592 				  int reg, int bytes)
593 {
594 	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
595 	struct xen_pci_op op = {
596 		.cmd    = XEN_PCI_OP_conf_read,
597 		.domain = sc->domain,
598 		.bus    = sc->bus,
599 		.devfn  = PCI_DEVFN(slot, func),
600 		.offset = reg,
601 		.size   = bytes,
602 	};
603 	int err;
604 
605 	err = do_pci_op(sc->pdev, &op);
606 
607 	DPRINTF("read config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
608 			bus, slot, func, reg, bytes, op.value, err);
609 
610 	if (err)
611 		op.value = ~0;
612 
613 	return op.value;
614 }
615 
616 /* Write configuration space register */
617 static void
618 xpcib_write_config(device_t dev, int bus, int slot, int func,
619 				   int reg, u_int32_t data, int bytes)
620 {
621 	struct xpcib_softc *sc = (struct xpcib_softc *)device_get_softc(dev);
622 	struct xen_pci_op op = {
623 		.cmd    = XEN_PCI_OP_conf_write,
624 		.domain = sc->domain,
625 		.bus    = sc->bus,
626 		.devfn  = PCI_DEVFN(slot, func),
627 		.offset = reg,
628 		.size   = bytes,
629 		.value  = data,
630 	};
631 	int err;
632 
633 	err = do_pci_op(sc->pdev, &op);
634 
635 	DPRINTF("write config (b=%d, s=%d, f=%d, reg=%d, len=%d, val=%x, err=%d)\n",
636 			bus, slot, func, reg, bytes, data, err);
637 }
638 
639 static int
640 xpcib_route_interrupt(device_t pcib, device_t dev, int pin)
641 {
642 	struct pci_devinfo *dinfo = device_get_ivars(dev);
643 	pcicfgregs *cfg = &dinfo->cfg;
644 
645 	DPRINTF("route intr (pin=%d, line=%d)\n", pin, cfg->intline);
646 
647 	return cfg->intline;
648 }
649 
650 static device_method_t xpcib_methods[] = {
651     /* Device interface */
652     DEVMETHOD(device_probe,		xpcib_probe),
653     DEVMETHOD(device_attach,		xpcib_attach),
654     DEVMETHOD(device_detach,		bus_generic_detach),
655     DEVMETHOD(device_shutdown,		bus_generic_shutdown),
656     DEVMETHOD(device_suspend,		bus_generic_suspend),
657     DEVMETHOD(device_resume,		bus_generic_resume),
658 
659     /* Bus interface */
660     DEVMETHOD(bus_read_ivar,		xpcib_read_ivar),
661     DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
662     DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
663     DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
664     DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
665     DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
666     DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
667 
668     /* pcib interface */
669     DEVMETHOD(pcib_maxslots,		xpcib_maxslots),
670     DEVMETHOD(pcib_read_config,		xpcib_read_config),
671     DEVMETHOD(pcib_write_config,	xpcib_write_config),
672     DEVMETHOD(pcib_route_interrupt,	xpcib_route_interrupt),
673 	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
674 
675     DEVMETHOD_END
676 };
677 
678 static devclass_t xpcib_devclass;
679 
680 DEFINE_CLASS_0(pcib, xpcib_driver, xpcib_methods, sizeof(struct xpcib_softc));
681 DRIVER_MODULE(pcib, xpcife, xpcib_driver, xpcib_devclass, 0, 0);
682 
683 /*
684  * Local variables:
685  * mode: C
686  * c-set-style: "BSD"
687  * c-basic-offset: 4
688  * tab-width: 4
689  * indent-tabs-mode: t
690  * End:
691  */
692