xref: /freebsd/sys/dev/bhnd/siba/siba.c (revision f90f4b65)
1 /*-
2  * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38 #include <sys/systm.h>
39 
40 #include <machine/bus.h>
41 
42 #include <dev/bhnd/cores/chipc/chipcreg.h>
43 
44 #include "sibareg.h"
45 #include "sibavar.h"
46 
47 int
48 siba_probe(device_t dev)
49 {
50 	device_set_desc(dev, "SIBA BHND bus");
51 	return (BUS_PROBE_DEFAULT);
52 }
53 
54 int
55 siba_attach(device_t dev)
56 {
57 	struct siba_devinfo	*dinfo;
58 	struct siba_softc	*sc;
59 	device_t		*devs;
60 	int			 ndevs;
61 	int			 error;
62 
63 	sc = device_get_softc(dev);
64 	sc->dev = dev;
65 
66 	/* Fetch references to the siba SIBA_CFG* blocks for all
67 	 * registered devices */
68 	if ((error = device_get_children(dev, &devs, &ndevs)))
69 		return (error);
70 
71 	for (int i = 0; i < ndevs; i++) {
72 		struct siba_addrspace	*addrspace;
73 
74 		dinfo = device_get_ivars(devs[i]);
75 
76 		KASSERT(!device_is_suspended(devs[i]),
77 		    ("siba(4) stateful suspend handling requires that devices "
78 		        "not be suspended before siba_attach()"));
79 
80 		/* Fetch the core register address space */
81 		addrspace = siba_find_addrspace(dinfo, BHND_PORT_DEVICE, 0, 0);
82 		if (addrspace == NULL) {
83 			device_printf(dev,
84 			    "missing device registers for core %d\n", i);
85 			error = ENXIO;
86 			goto cleanup;
87 		}
88 
89 		/*
90 		 * Map the per-core configuration blocks
91 		 */
92 		KASSERT(dinfo->core_id.num_cfg_blocks <= SIBA_MAX_CFG,
93 		    ("config block count %u out of range",
94 		        dinfo->core_id.num_cfg_blocks));
95 
96 		for (u_int cfgidx = 0; cfgidx < dinfo->core_id.num_cfg_blocks;
97 		    cfgidx++)
98 		{
99 			rman_res_t	r_start, r_count, r_end;
100 
101 			/* Determine the config block's address range; configuration
102 			 * blocks are allocated starting at SIBA_CFG0_OFFSET,
103 			 * growing downwards. */
104 			r_start = addrspace->sa_base + SIBA_CFG0_OFFSET;
105 			r_start -= cfgidx * SIBA_CFG_SIZE;
106 
107 			r_count = SIBA_CFG_SIZE;
108 			r_end = r_start + r_count - 1;
109 
110 			/* Allocate the config resource */
111 			dinfo->cfg_rid[cfgidx] = 0;
112 			dinfo->cfg[cfgidx] = BHND_BUS_ALLOC_RESOURCE(dev, dev,
113 			    SYS_RES_MEMORY, &dinfo->cfg_rid[cfgidx], r_start,
114 			    r_end, r_count, RF_ACTIVE);
115 
116 			if (dinfo->cfg[cfgidx] == NULL) {
117 			     device_printf(dev, "failed allocating CFG_%u for "
118 			     "core %d\n", cfgidx, i);
119 			     error = ENXIO;
120 			     goto cleanup;
121 			}
122 		}
123 	}
124 
125 cleanup:
126 	free(devs, M_BHND);
127 	if (error)
128 		return (error);
129 
130 	/* Delegate remainder to standard bhnd method implementation */
131 	return (bhnd_generic_attach(dev));
132 }
133 
134 int
135 siba_detach(device_t dev)
136 {
137 	return (bhnd_generic_detach(dev));
138 }
139 
140 int
141 siba_resume(device_t dev)
142 {
143 	return (bhnd_generic_resume(dev));
144 }
145 
146 int
147 siba_suspend(device_t dev)
148 {
149 	return (bhnd_generic_suspend(dev));
150 }
151 
152 static int
153 siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
154 {
155 	const struct siba_devinfo *dinfo;
156 	const struct bhnd_core_info *cfg;
157 
158 	dinfo = device_get_ivars(child);
159 	cfg = &dinfo->core_id.core_info;
160 
161 	switch (index) {
162 	case BHND_IVAR_VENDOR:
163 		*result = cfg->vendor;
164 		return (0);
165 	case BHND_IVAR_DEVICE:
166 		*result = cfg->device;
167 		return (0);
168 	case BHND_IVAR_HWREV:
169 		*result = cfg->hwrev;
170 		return (0);
171 	case BHND_IVAR_DEVICE_CLASS:
172 		*result = bhnd_core_class(cfg);
173 		return (0);
174 	case BHND_IVAR_VENDOR_NAME:
175 		*result = (uintptr_t) bhnd_vendor_name(cfg->vendor);
176 		return (0);
177 	case BHND_IVAR_DEVICE_NAME:
178 		*result = (uintptr_t) bhnd_core_name(cfg);
179 		return (0);
180 	case BHND_IVAR_CORE_INDEX:
181 		*result = cfg->core_idx;
182 		return (0);
183 	case BHND_IVAR_CORE_UNIT:
184 		*result = cfg->unit;
185 		return (0);
186 	default:
187 		return (ENOENT);
188 	}
189 }
190 
191 static int
192 siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
193 {
194 	switch (index) {
195 	case BHND_IVAR_VENDOR:
196 	case BHND_IVAR_DEVICE:
197 	case BHND_IVAR_HWREV:
198 	case BHND_IVAR_DEVICE_CLASS:
199 	case BHND_IVAR_VENDOR_NAME:
200 	case BHND_IVAR_DEVICE_NAME:
201 	case BHND_IVAR_CORE_INDEX:
202 	case BHND_IVAR_CORE_UNIT:
203 		return (EINVAL);
204 	default:
205 		return (ENOENT);
206 	}
207 }
208 
209 static struct resource_list *
210 siba_get_resource_list(device_t dev, device_t child)
211 {
212 	struct siba_devinfo *dinfo = device_get_ivars(child);
213 	return (&dinfo->resources);
214 }
215 
216 static device_t
217 siba_find_hostb_device(device_t dev)
218 {
219 	struct siba_softc *sc = device_get_softc(dev);
220 
221 	/* This is set (or not) by the concrete siba driver subclass. */
222 	return (sc->hostb_dev);
223 }
224 
225 static int
226 siba_reset_core(device_t dev, device_t child, uint16_t flags)
227 {
228 	struct siba_devinfo *dinfo;
229 
230 	if (device_get_parent(child) != dev)
231 		BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags);
232 
233 	dinfo = device_get_ivars(child);
234 
235 	/* Can't reset the core without access to the CFG0 registers */
236 	if (dinfo->cfg[0] == NULL)
237 		return (ENODEV);
238 
239 	// TODO - perform reset
240 
241 	return (ENXIO);
242 }
243 
244 static int
245 siba_suspend_core(device_t dev, device_t child)
246 {
247 	struct siba_devinfo *dinfo;
248 
249 	if (device_get_parent(child) != dev)
250 		BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child);
251 
252 	dinfo = device_get_ivars(child);
253 
254 	/* Can't suspend the core without access to the CFG0 registers */
255 	if (dinfo->cfg[0] == NULL)
256 		return (ENODEV);
257 
258 	// TODO - perform suspend
259 
260 	return (ENXIO);
261 }
262 
263 static uint32_t
264 siba_read_config(device_t dev, device_t child, bus_size_t offset, u_int width)
265 {
266 	/* Unsuported */
267 	return (UINT32_MAX);
268 }
269 
270 static void
271 siba_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
272     u_int width)
273 {
274 	/* Unsuported */
275 	return;
276 }
277 
278 static u_int
279 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
280 {
281 	struct siba_devinfo *dinfo;
282 
283 	/* delegate non-bus-attached devices to our parent */
284 	if (device_get_parent(child) != dev)
285 		return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
286 		    type));
287 
288 	dinfo = device_get_ivars(child);
289 	return (siba_addrspace_port_count(dinfo));
290 }
291 
292 static u_int
293 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
294     u_int port)
295 {
296 	struct siba_devinfo	*dinfo;
297 
298 	/* delegate non-bus-attached devices to our parent */
299 	if (device_get_parent(child) != dev)
300 		return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
301 		    type, port));
302 
303 	dinfo = device_get_ivars(child);
304 	if (!siba_is_port_valid(dinfo, type, port))
305 		return (0);
306 
307 	return (siba_addrspace_region_count(dinfo, port));
308 }
309 
310 static int
311 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
312     u_int port_num, u_int region_num)
313 {
314 	struct siba_devinfo	*dinfo;
315 	struct siba_addrspace	*addrspace;
316 
317 	/* delegate non-bus-attached devices to our parent */
318 	if (device_get_parent(child) != dev)
319 		return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
320 		    port_type, port_num, region_num));
321 
322 	dinfo = device_get_ivars(child);
323 	addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
324 	if (addrspace == NULL)
325 		return (-1);
326 
327 	return (addrspace->sa_rid);
328 }
329 
330 static int
331 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
332     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
333 {
334 	struct siba_devinfo	*dinfo;
335 
336 	/* delegate non-bus-attached devices to our parent */
337 	if (device_get_parent(child) != dev)
338 		return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
339 		    type, rid, port_type, port_num, region_num));
340 
341 	dinfo = device_get_ivars(child);
342 
343 	/* Ports are always memory mapped */
344 	if (type != SYS_RES_MEMORY)
345 		return (EINVAL);
346 
347 	for (int i = 0; i < dinfo->core_id.num_addrspace; i++) {
348 		if (dinfo->addrspace[i].sa_rid != rid)
349 			continue;
350 
351 		*port_type = BHND_PORT_DEVICE;
352 		*port_num = siba_addrspace_port(i);
353 		*region_num = siba_addrspace_region(i);
354 		return (0);
355 	}
356 
357 	/* Not found */
358 	return (ENOENT);
359 }
360 
361 static int
362 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
363     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
364 {
365 	struct siba_devinfo	*dinfo;
366 	struct siba_addrspace	*addrspace;
367 
368 	/* delegate non-bus-attached devices to our parent */
369 	if (device_get_parent(child) != dev) {
370 		return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
371 		    port_type, port_num, region_num, addr, size));
372 	}
373 
374 	dinfo = device_get_ivars(child);
375 	addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
376 	if (addrspace == NULL)
377 		return (ENOENT);
378 
379 	*addr = addrspace->sa_base;
380 	*size = addrspace->sa_size - addrspace->sa_bus_reserved;
381 	return (0);
382 }
383 
384 
385 /**
386  * Register all address space mappings for @p di.
387  *
388  * @param dev The siba bus device.
389  * @param di The device info instance on which to register all address
390  * space entries.
391  * @param r A resource mapping the enumeration table block for @p di.
392  */
393 static int
394 siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
395     struct resource *r)
396 {
397 	struct siba_core_id	*cid;
398 	uint32_t		 addr;
399 	uint32_t		 size;
400 	int			 error;
401 
402 	cid = &di->core_id;
403 
404 
405 	/* Register the device address space entries */
406 	for (uint8_t i = 0; i < di->core_id.num_addrspace; i++) {
407 		uint32_t	adm;
408 		u_int		adm_offset;
409 		uint32_t	bus_reserved;
410 
411 		/* Determine the register offset */
412 		adm_offset = siba_admatch_offset(i);
413 		if (adm_offset == 0) {
414 		    device_printf(dev, "addrspace %hhu is unsupported", i);
415 		    return (ENODEV);
416 		}
417 
418 		/* Fetch the address match register value */
419 		adm = bus_read_4(r, adm_offset);
420 
421 		/* Parse the value */
422 		if ((error = siba_parse_admatch(adm, &addr, &size))) {
423 			device_printf(dev, "failed to decode address "
424 			    " match register value 0x%x\n", adm);
425 			return (error);
426 		}
427 
428 		/* If this is the device's core/enumeration addrespace,
429 		 * reserve the Sonics configuration register blocks for the
430 		 * use of our bus. */
431 		bus_reserved = 0;
432 		if (i == SIBA_CORE_ADDRSPACE)
433 			bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
434 
435 		/* Append the region info */
436 		error = siba_append_dinfo_region(di, i, addr, size,
437 		    bus_reserved);
438 		if (error)
439 			return (error);
440 	}
441 
442 	return (0);
443 }
444 
445 static struct bhnd_devinfo *
446 siba_alloc_bhnd_dinfo(device_t dev)
447 {
448 	struct siba_devinfo *dinfo = siba_alloc_dinfo(dev);
449 	return ((struct bhnd_devinfo *)dinfo);
450 }
451 
452 static void
453 siba_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo)
454 {
455 	siba_free_dinfo(dev, (struct siba_devinfo *)dinfo);
456 }
457 
458 /**
459  * Scan the core table and add all valid discovered cores to
460  * the bus.
461  *
462  * @param dev The siba bus device.
463  * @param chipid The chip identifier, if the device does not provide a
464  * ChipCommon core. Should o NULL otherwise.
465  */
466 int
467 siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
468 {
469 	struct bhnd_chipid	 ccid;
470 	struct bhnd_core_info	*cores;
471 	struct siba_devinfo	*dinfo;
472 	struct resource		*r;
473 	int			 rid;
474 	int			 error;
475 
476 	dinfo = NULL;
477 	cores = NULL;
478 	r = NULL;
479 
480 	/*
481 	 * Try to determine the number of device cores via the ChipCommon
482 	 * identification registers.
483 	 *
484 	 * A small number of very early devices do not include a ChipCommon
485 	 * core, in which case our caller must supply the chip identification
486 	 * information via a non-NULL chipid parameter.
487 	 */
488 	if (chipid == NULL) {
489 		uint32_t	idhigh, ccreg;
490 		uint16_t	vendor, device;
491 		uint8_t		ccrev;
492 
493 		/* Map the first core's register block. If the ChipCommon core
494 		 * exists, it will always be the first core. */
495 		rid = 0;
496 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
497 		    SIBA_CORE_ADDR(0), SIBA_CORE_SIZE,
498 		    SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1,
499 		    RF_ACTIVE);
500 
501 		/* Identify the core */
502 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
503 		vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
504 		device = SIBA_REG_GET(idhigh, IDH_DEVICE);
505 		ccrev = SIBA_IDH_CORE_REV(idhigh);
506 
507 		if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) {
508 			device_printf(dev,
509 			    "cannot identify device: no chipcommon core "
510 			    "found\n");
511 			error = ENXIO;
512 			goto cleanup;
513 		}
514 
515 		/* Identify the chipset */
516 		ccreg = bus_read_4(r, CHIPC_ID);
517 		ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR);
518 
519 		if (!CHIPC_NCORES_MIN_HWREV(ccrev)) {
520 			switch (ccid.chip_id) {
521 			case BHND_CHIPID_BCM4306:
522 				ccid.ncores = 6;
523 				break;
524 			case BHND_CHIPID_BCM4704:
525 				ccid.ncores = 9;
526 				break;
527 			case BHND_CHIPID_BCM5365:
528 				/*
529 				* BCM5365 does support ID_NUMCORE in at least
530 				* some of its revisions, but for unknown
531 				* reasons, Broadcom's drivers always exclude
532 				* the ChipCommon revision (0x5) used by BCM5365
533 				* from the set of revisions supporting
534 				* ID_NUMCORE, and instead supply a fixed value.
535 				*
536 				* Presumably, at least some of these devices
537 				* shipped with a broken ID_NUMCORE value.
538 				*/
539 				ccid.ncores = 7;
540 				break;
541 			default:
542 				device_printf(dev, "unable to determine core "
543 				    "count for unrecognized chipset 0x%hx\n",
544 				    ccid.chip_id);
545 				error = ENXIO;
546 				goto cleanup;
547 			}
548 		}
549 
550 		chipid = &ccid;
551 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
552 	}
553 
554 	/* Allocate our temporary core table and enumerate all cores */
555 	cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
556 	if (cores == NULL)
557 		return (ENOMEM);
558 
559 	/* Add all cores. */
560 	for (u_int i = 0; i < chipid->ncores; i++) {
561 		struct siba_core_id	 cid;
562 		device_t		 child;
563 		uint32_t		 idhigh, idlow;
564 		rman_res_t		 r_count, r_end, r_start;
565 
566 		/* Map the core's register block */
567 		rid = 0;
568 		r_start = SIBA_CORE_ADDR(i);
569 		r_count = SIBA_CORE_SIZE;
570 		r_end = r_start + SIBA_CORE_SIZE - 1;
571 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
572 		    r_end, r_count, RF_ACTIVE);
573 		if (r == NULL) {
574 			error = ENXIO;
575 			goto cleanup;
576 		}
577 
578 		/* Add the child device */
579 		child = BUS_ADD_CHILD(dev, 0, NULL, -1);
580 		if (child == NULL) {
581 			error = ENXIO;
582 			goto cleanup;
583 		}
584 
585 		/* Read the core info */
586 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
587 		idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
588 
589 		cid = siba_parse_core_id(idhigh, idlow, i, 0);
590 		cores[i] = cid.core_info;
591 
592 		/* Determine unit number */
593 		for (u_int j = 0; j < i; j++) {
594 			if (cores[j].vendor == cores[i].vendor &&
595 			    cores[j].device == cores[i].device)
596 				cores[i].unit++;
597 		}
598 
599 		/* Initialize per-device bus info */
600 		if ((dinfo = device_get_ivars(child)) == NULL) {
601 			error = ENXIO;
602 			goto cleanup;
603 		}
604 
605 		if ((error = siba_init_dinfo(dev, dinfo, &cid)))
606 			goto cleanup;
607 
608 		/* Register the core's address space(s). */
609 		if ((error = siba_register_addrspaces(dev, dinfo, r)))
610 			goto cleanup;
611 
612 		/* If pins are floating or the hardware is otherwise
613 		 * unpopulated, the device shouldn't be used. */
614 		if (bhnd_is_hw_disabled(child))
615 			device_disable(child);
616 
617 		/* Release our resource */
618 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
619 		r = NULL;
620 
621 		/* Issue bus callback for fully initialized child. */
622 		BHND_BUS_CHILD_ADDED(dev, child);
623 	}
624 
625 cleanup:
626 	if (cores != NULL)
627 		free(cores, M_BHND);
628 
629 	if (r != NULL)
630 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
631 
632 	return (error);
633 }
634 
635 static device_method_t siba_methods[] = {
636 	/* Device interface */
637 	DEVMETHOD(device_probe,			siba_probe),
638 	DEVMETHOD(device_attach,		siba_attach),
639 	DEVMETHOD(device_detach,		siba_detach),
640 	DEVMETHOD(device_resume,		siba_resume),
641 	DEVMETHOD(device_suspend,		siba_suspend),
642 
643 	/* Bus interface */
644 	DEVMETHOD(bus_read_ivar,		siba_read_ivar),
645 	DEVMETHOD(bus_write_ivar,		siba_write_ivar),
646 	DEVMETHOD(bus_get_resource_list,	siba_get_resource_list),
647 
648 	/* BHND interface */
649 	DEVMETHOD(bhnd_bus_find_hostb_device,	siba_find_hostb_device),
650 	DEVMETHOD(bhnd_bus_alloc_devinfo,	siba_alloc_bhnd_dinfo),
651 	DEVMETHOD(bhnd_bus_free_devinfo,	siba_free_bhnd_dinfo),
652 	DEVMETHOD(bhnd_bus_reset_core,		siba_reset_core),
653 	DEVMETHOD(bhnd_bus_suspend_core,	siba_suspend_core),
654 	DEVMETHOD(bhnd_bus_read_config,		siba_read_config),
655 	DEVMETHOD(bhnd_bus_write_config,	siba_write_config),
656 	DEVMETHOD(bhnd_bus_get_port_count,	siba_get_port_count),
657 	DEVMETHOD(bhnd_bus_get_region_count,	siba_get_region_count),
658 	DEVMETHOD(bhnd_bus_get_port_rid,	siba_get_port_rid),
659 	DEVMETHOD(bhnd_bus_decode_port_rid,	siba_decode_port_rid),
660 	DEVMETHOD(bhnd_bus_get_region_addr,	siba_get_region_addr),
661 
662 	DEVMETHOD_END
663 };
664 
665 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
666 
667 MODULE_VERSION(siba, 1);
668 MODULE_DEPEND(siba, bhnd, 1, 1, 1);
669