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