xref: /freebsd/sys/dev/bhnd/siba/siba.c (revision cdf63a700c77204252e3c2e38d7106965559f3c6)
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 	device_t		*devs;
59 	int			 ndevs;
60 	int			 error;
61 
62 	// TODO: We need to set the initiator timeout for the
63 	// core that will be issuing requests to non-memory locations.
64 	//
65 	// In the case of a bridged device, this is the hostb core.
66 	// On a non-bridged device, this will be the CPU.
67 
68 	/* Fetch references to the siba SIBA_CFG* blocks for all
69 	 * registered devices */
70 	if ((error = device_get_children(dev, &devs, &ndevs)))
71 		return (error);
72 
73 	for (int i = 0; i < ndevs; i++) {
74 		struct siba_addrspace	*addrspace;
75 		struct siba_port	*port;
76 
77 		dinfo = device_get_ivars(devs[i]);
78 
79 		KASSERT(!device_is_suspended(devs[i]),
80 		    ("siba(4) stateful suspend handling requires that devices "
81 		        "not be suspended before siba_attach()"));
82 
83 		/* Fetch the core register address space */
84 		port = siba_dinfo_get_port(dinfo, BHND_PORT_DEVICE, 0);
85 		if (port == NULL) {
86 			error = ENXIO;
87 			goto cleanup;
88 		}
89 
90 		addrspace = siba_find_port_addrspace(port, SIBA_ADDRSPACE_CORE);
91 		if (addrspace == NULL) {
92 			error = ENXIO;
93 			goto cleanup;
94 		}
95 
96 		/*
97 		 * Map the per-core configuration blocks
98 		 */
99 		KASSERT(dinfo->core_id.num_cfg_blocks <= SIBA_CFG_NUM_MAX,
100 		    ("config block count %u out of range",
101 		        dinfo->core_id.num_cfg_blocks));
102 
103 		for (u_int cfgidx = 0; cfgidx < dinfo->core_id.num_cfg_blocks;
104 		    cfgidx++)
105 		{
106 			rman_res_t	r_start, r_count, r_end;
107 
108 			/* Determine the config block's address range; configuration
109 			 * blocks are allocated starting at SIBA_CFG0_OFFSET,
110 			 * growing downwards. */
111 			r_start = addrspace->sa_base + SIBA_CFG0_OFFSET;
112 			r_start -= cfgidx * SIBA_CFG_SIZE;
113 
114 			r_count = SIBA_CFG_SIZE;
115 			r_end = r_start + r_count - 1;
116 
117 			/* Allocate the config resource */
118 			dinfo->cfg_rid[cfgidx] = 0;
119 			dinfo->cfg[cfgidx] = bhnd_alloc_resource(dev,
120 			    SYS_RES_MEMORY, &dinfo->cfg_rid[cfgidx], r_start,
121 			    r_end, r_count, RF_ACTIVE);
122 
123 			if (dinfo->cfg[cfgidx] == NULL) {
124 			     device_printf(dev, "failed allocating CFG_%u for "
125 			     "core %d\n", cfgidx, i);
126 			     error = ENXIO;
127 			     goto cleanup;
128 			}
129 		}
130 	}
131 
132 cleanup:
133 	free(devs, M_BHND);
134 	if (error)
135 		return (error);
136 
137 	/* Delegate remainder to standard bhnd method implementation */
138 	return (bhnd_generic_attach(dev));
139 }
140 
141 int
142 siba_detach(device_t dev)
143 {
144 	return (bhnd_generic_detach(dev));
145 }
146 
147 static int
148 siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
149 {
150 	const struct siba_devinfo *dinfo;
151 	const struct bhnd_core_info *cfg;
152 
153 	dinfo = device_get_ivars(child);
154 	cfg = &dinfo->core_id.core_info;
155 
156 	switch (index) {
157 	case BHND_IVAR_VENDOR:
158 		*result = cfg->vendor;
159 		return (0);
160 	case BHND_IVAR_DEVICE:
161 		*result = cfg->device;
162 		return (0);
163 	case BHND_IVAR_HWREV:
164 		*result = cfg->hwrev;
165 		return (0);
166 	case BHND_IVAR_DEVICE_CLASS:
167 		*result = bhnd_core_class(cfg);
168 		return (0);
169 	case BHND_IVAR_VENDOR_NAME:
170 		*result = (uintptr_t) bhnd_vendor_name(cfg->vendor);
171 		return (0);
172 	case BHND_IVAR_DEVICE_NAME:
173 		*result = (uintptr_t) bhnd_core_name(cfg);
174 		return (0);
175 	case BHND_IVAR_CORE_INDEX:
176 		*result = cfg->core_idx;
177 		return (0);
178 	case BHND_IVAR_CORE_UNIT:
179 		*result = cfg->unit;
180 		return (0);
181 	default:
182 		return (ENOENT);
183 	}
184 }
185 
186 static int
187 siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
188 {
189 	switch (index) {
190 	case BHND_IVAR_VENDOR:
191 	case BHND_IVAR_DEVICE:
192 	case BHND_IVAR_HWREV:
193 	case BHND_IVAR_DEVICE_CLASS:
194 	case BHND_IVAR_VENDOR_NAME:
195 	case BHND_IVAR_DEVICE_NAME:
196 	case BHND_IVAR_CORE_INDEX:
197 	case BHND_IVAR_CORE_UNIT:
198 		return (EINVAL);
199 	default:
200 		return (ENOENT);
201 	}
202 }
203 
204 static void
205 siba_child_deleted(device_t dev, device_t child)
206 {
207 	struct siba_devinfo *dinfo = device_get_ivars(child);
208 	if (dinfo != NULL)
209 		siba_free_dinfo(dev, dinfo);
210 }
211 
212 static struct resource_list *
213 siba_get_resource_list(device_t dev, device_t child)
214 {
215 	struct siba_devinfo *dinfo = device_get_ivars(child);
216 	return (&dinfo->resources);
217 }
218 
219 static device_t
220 siba_find_hostb_device(device_t dev)
221 {
222 	struct siba_softc *sc = device_get_softc(dev);
223 
224 	/* This is set (or not) by the concrete siba driver subclass. */
225 	return (sc->hostb_dev);
226 }
227 
228 static int
229 siba_reset_core(device_t dev, device_t child, uint16_t flags)
230 {
231 	struct siba_devinfo *dinfo;
232 
233 	if (device_get_parent(child) != dev)
234 		BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags);
235 
236 	dinfo = device_get_ivars(child);
237 
238 	/* Can't reset the core without access to the CFG0 registers */
239 	if (dinfo->cfg[0] == NULL)
240 		return (ENODEV);
241 
242 	// TODO - perform reset
243 
244 	return (ENXIO);
245 }
246 
247 static int
248 siba_suspend_core(device_t dev, device_t child)
249 {
250 	struct siba_devinfo *dinfo;
251 
252 	if (device_get_parent(child) != dev)
253 		BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child);
254 
255 	dinfo = device_get_ivars(child);
256 
257 	/* Can't suspend the core without access to the CFG0 registers */
258 	if (dinfo->cfg[0] == NULL)
259 		return (ENODEV);
260 
261 	// TODO - perform suspend
262 
263 	return (ENXIO);
264 }
265 
266 
267 static u_int
268 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
269 {
270 	struct siba_devinfo *dinfo;
271 
272 	/* delegate non-bus-attached devices to our parent */
273 	if (device_get_parent(child) != dev)
274 		return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
275 		    type));
276 
277 	dinfo = device_get_ivars(child);
278 
279 	/* We advertise exactly one port of any type */
280 	if (siba_dinfo_get_port(dinfo, type, 0) != NULL)
281 		return (1);
282 
283 	return (0);
284 }
285 
286 static u_int
287 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
288     u_int port_num)
289 {
290 	struct siba_devinfo	*dinfo;
291 	struct siba_port	*port;
292 
293 	/* delegate non-bus-attached devices to our parent */
294 	if (device_get_parent(child) != dev)
295 		return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
296 		    type, port_num));
297 
298 	dinfo = device_get_ivars(child);
299 	port = siba_dinfo_get_port(dinfo, type, port_num);
300 	if (port == NULL)
301 		return (0);
302 
303 	return (port->sp_num_addrs);
304 }
305 
306 static int
307 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
308     u_int port_num, u_int region_num)
309 {
310 	struct siba_devinfo	*dinfo;
311 	struct siba_port	*port;
312 	struct siba_addrspace	*addrspace;
313 
314 	/* delegate non-bus-attached devices to our parent */
315 	if (device_get_parent(child) != dev)
316 		return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
317 		    port_type, port_num, region_num));
318 
319 	dinfo = device_get_ivars(child);
320 	port = siba_dinfo_get_port(dinfo, port_type, port_num);
321 	if (port == NULL)
322 		return (-1);
323 
324 	STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
325 		if (addrspace->sa_region_num == region_num)
326 			return (addrspace->sa_rid);
327 	}
328 
329 	/* not found */
330 	return (-1);
331 }
332 
333 static int
334 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
335     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
336 {
337 	struct siba_devinfo	*dinfo;
338 	struct siba_port	*port;
339 	struct siba_addrspace	*addrspace;
340 
341 	/* delegate non-bus-attached devices to our parent */
342 	if (device_get_parent(child) != dev)
343 		return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
344 		    type, rid, port_type, port_num, region_num));
345 
346 	dinfo = device_get_ivars(child);
347 
348 	/* Ports are always memory mapped */
349 	if (type != SYS_RES_MEMORY)
350 		return (EINVAL);
351 
352 	/* Starting with the most likely device list, search all three port
353 	 * lists */
354 	bhnd_port_type types[] = {
355 	    BHND_PORT_DEVICE,
356 	    BHND_PORT_AGENT,
357 	    BHND_PORT_BRIDGE
358 	};
359 
360 	for (int i = 0; i < nitems(types); i++) {
361 		port = siba_dinfo_get_port(dinfo, types[i], 0);
362 		if (port == NULL)
363 			continue;
364 
365 		STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
366 			if (addrspace->sa_rid != rid)
367 				continue;
368 
369 			*port_type = port->sp_type;
370 			*port_num = port->sp_num;
371 			*region_num = addrspace->sa_region_num;
372 		}
373 	}
374 
375 	return (ENOENT);
376 }
377 
378 static int
379 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
380     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
381 {
382 	struct siba_devinfo	*dinfo;
383 	struct siba_port	*port;
384 	struct siba_addrspace	*addrspace;
385 
386 	/* delegate non-bus-attached devices to our parent */
387 	if (device_get_parent(child) != dev) {
388 		return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
389 		    port_type, port_num, region_num, addr, size));
390 	}
391 
392 	dinfo = device_get_ivars(child);
393 	port = siba_dinfo_get_port(dinfo, port_type, port_num);
394 	if (port == NULL)
395 		return (ENOENT);
396 
397 	STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
398 		if (addrspace->sa_region_num != region_num)
399 			continue;
400 
401 		*addr = addrspace->sa_base;
402 		*size = addrspace->sa_size;
403 		return (0);
404 	}
405 
406 	return (ENOENT);
407 }
408 
409 
410 /**
411  * Register all address space mappings for @p di.
412  *
413  * @param dev The siba bus device.
414  * @param di The device info instance on which to register all address
415  * space entries.
416  * @param r A resource mapping the enumeration table block for @p di.
417  */
418 static int
419 siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
420     struct resource *r)
421 {
422 	struct siba_core_id	*cid;
423 	uint32_t		 addr;
424 	uint32_t		 size;
425 	u_int			 region_num;
426 	int			 error;
427 
428 	cid = &di->core_id;
429 
430 	/* Region numbers must be assigned in order, but our siba address
431 	 * space IDs may be sparsely allocated; thus, we track
432 	 * the region index separately. */
433 	region_num = 0;
434 
435 	/* Register the device address space entries */
436 	for (uint8_t sid = 0; sid < di->core_id.num_addrspace; sid++) {
437 		uint32_t	adm;
438 		u_int		adm_offset;
439 		uint32_t	bus_reserved;
440 
441 		/* Determine the register offset */
442 		adm_offset = siba_admatch_offset(sid);
443 		if (adm_offset == 0) {
444 		    device_printf(dev, "addrspace %hhu is unsupported", sid);
445 		    return (ENODEV);
446 		}
447 
448 		/* Fetch the address match register value */
449 		adm = bus_read_4(r, adm_offset);
450 
451 		/* Skip disabled entries */
452 		if (adm & SIBA_AM_ADEN)
453 			continue;
454 
455 		/* Parse the value */
456 		if ((error = siba_parse_admatch(adm, &addr, &size))) {
457 			device_printf(dev, "failed to decode address "
458 			    " match register value 0x%x\n", adm);
459 			return (error);
460 		}
461 
462 		/* If this is the device's core/enumeration addrespace,
463 		 * reserve the Sonics configuration register blocks for the
464 		 * use of our bus. */
465 		bus_reserved = 0;
466 		if (sid == SIBA_ADDRSPACE_CORE)
467 			bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
468 
469 		/* Append the region info */
470 		error = siba_append_dinfo_region(di, BHND_PORT_DEVICE, 0,
471 		    region_num, sid, addr, size, bus_reserved);
472 		if (error)
473 			return (error);
474 
475 
476 		region_num++;
477 	}
478 
479 	return (0);
480 }
481 
482 /**
483  * Scan the core table and add all valid discovered cores to
484  * the bus.
485  *
486  * @param dev The siba bus device.
487  * @param chipid The chip identifier, if the device does not provide a
488  * ChipCommon core. Should o NULL otherwise.
489  */
490 int
491 siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
492 {
493 	struct bhnd_chipid	 ccid;
494 	struct bhnd_core_info	*cores;
495 	struct siba_devinfo	*dinfo;
496 	struct resource		*r;
497 	int			 rid;
498 	int			 error;
499 
500 	dinfo = NULL;
501 	cores = NULL;
502 	r = NULL;
503 
504 	/*
505 	 * Try to determine the number of device cores via the ChipCommon
506 	 * identification registers.
507 	 *
508 	 * A small number of very early devices do not include a ChipCommon
509 	 * core, in which case our caller must supply the chip identification
510 	 * information via a non-NULL chipid parameter.
511 	 */
512 	if (chipid == NULL) {
513 		uint32_t	idhigh, ccreg;
514 		uint16_t	vendor, device;
515 		uint8_t		ccrev;
516 
517 		/* Map the first core's register block. If the ChipCommon core
518 		 * exists, it will always be the first core. */
519 		rid = 0;
520 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
521 		    SIBA_CORE_ADDR(0), SIBA_CORE_SIZE,
522 		    SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1,
523 		    RF_ACTIVE);
524 
525 		/* Identify the core */
526 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
527 		vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
528 		device = SIBA_REG_GET(idhigh, IDH_DEVICE);
529 		ccrev = SIBA_IDH_CORE_REV(idhigh);
530 
531 		if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) {
532 			device_printf(dev,
533 			    "cannot identify device: no chipcommon core "
534 			    "found\n");
535 			error = ENXIO;
536 			goto cleanup;
537 		}
538 
539 		/* Identify the chipset */
540 		ccreg = bus_read_4(r, CHIPC_ID);
541 		ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR);
542 
543 		if (!CHIPC_NCORES_MIN_HWREV(ccrev)) {
544 			switch (device) {
545 			case BHND_CHIPID_BCM4306:
546 				ccid.ncores = 6;
547 				break;
548 			case BHND_CHIPID_BCM4704:
549 				ccid.ncores = 9;
550 				break;
551 			case BHND_CHIPID_BCM5365:
552 				/*
553 				* BCM5365 does support ID_NUMCORE in at least
554 				* some of its revisions, but for unknown
555 				* reasons, Broadcom's drivers always exclude
556 				* the ChipCommon revision (0x5) used by BCM5365
557 				* from the set of revisions supporting
558 				* ID_NUMCORE, and instead supply a fixed value.
559 				*
560 				* Presumably, at least some of these devices
561 				* shipped with a broken ID_NUMCORE value.
562 				*/
563 				ccid.ncores = 7;
564 				break;
565 			default:
566 				device_printf(dev, "unable to determine core "
567 				    "count for unrecognized chipset 0x%hx\n",
568 				    ccid.chip_id);
569 				error = ENXIO;
570 				goto cleanup;
571 			}
572 		}
573 
574 		chipid = &ccid;
575 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
576 	}
577 
578 	/* Allocate our temporary core table and enumerate all cores */
579 	cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
580 	if (cores == NULL)
581 		return (ENOMEM);
582 
583 	/* Add all cores. */
584 	for (u_int i = 0; i < chipid->ncores; i++) {
585 		struct siba_core_id	 cid;
586 		device_t		 child;
587 		uint32_t		 idhigh, idlow;
588 		rman_res_t		 r_count, r_end, r_start;
589 
590 		/* Map the core's register block */
591 		rid = 0;
592 		r_start = SIBA_CORE_ADDR(i);
593 		r_count = SIBA_CORE_SIZE;
594 		r_end = r_start + SIBA_CORE_SIZE - 1;
595 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
596 		    r_end, r_count, RF_ACTIVE);
597 		if (r == NULL) {
598 			error = ENXIO;
599 			goto cleanup;
600 		}
601 
602 		/* Read the core info */
603 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
604 		idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
605 
606 		cid = siba_parse_core_id(idhigh, idlow, i, 0);
607 		cores[i] = cid.core_info;
608 
609 		/* Determine unit number */
610 		for (u_int j = 0; j < i; j++) {
611 			if (cores[j].vendor == cores[i].vendor &&
612 			    cores[j].device == cores[i].device)
613 				cores[i].unit++;
614 		}
615 
616 		/* Allocate per-device bus info */
617 		dinfo = siba_alloc_dinfo(dev, &cid);
618 		if (dinfo == NULL) {
619 			error = ENXIO;
620 			goto cleanup;
621 		}
622 
623 		/* Register the core's address space(s). */
624 		if ((error = siba_register_addrspaces(dev, dinfo, r)))
625 			goto cleanup;
626 
627 		/* Add the child device */
628 		child = device_add_child(dev, NULL, -1);
629 		if (child == NULL) {
630 			error = ENXIO;
631 			goto cleanup;
632 		}
633 
634 		/* The child device now owns the dinfo pointer */
635 		device_set_ivars(child, dinfo);
636 		dinfo = NULL;
637 
638 		/* If pins are floating or the hardware is otherwise
639 		 * unpopulated, the device shouldn't be used. */
640 		if (bhnd_is_hw_disabled(child))
641 			device_disable(child);
642 
643 		/* Release our resource */
644 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
645 		r = NULL;
646 	}
647 
648 cleanup:
649 	if (cores != NULL)
650 		free(cores, M_BHND);
651 
652 	if (dinfo != NULL)
653 		siba_free_dinfo(dev, dinfo);
654 
655 	if (r != NULL)
656 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
657 
658 	return (error);
659 }
660 
661 static device_method_t siba_methods[] = {
662 	/* Device interface */
663 	DEVMETHOD(device_probe,			siba_probe),
664 	DEVMETHOD(device_attach,		siba_attach),
665 	DEVMETHOD(device_detach,		siba_detach),
666 
667 	/* Bus interface */
668 	DEVMETHOD(bus_child_deleted,		siba_child_deleted),
669 	DEVMETHOD(bus_read_ivar,		siba_read_ivar),
670 	DEVMETHOD(bus_write_ivar,		siba_write_ivar),
671 	DEVMETHOD(bus_get_resource_list,	siba_get_resource_list),
672 
673 	/* BHND interface */
674 	DEVMETHOD(bhnd_bus_find_hostb_device,	siba_find_hostb_device),
675 	DEVMETHOD(bhnd_bus_reset_core,		siba_reset_core),
676 	DEVMETHOD(bhnd_bus_suspend_core,	siba_suspend_core),
677 	DEVMETHOD(bhnd_bus_get_port_count,	siba_get_port_count),
678 	DEVMETHOD(bhnd_bus_get_region_count,	siba_get_region_count),
679 	DEVMETHOD(bhnd_bus_get_port_rid,	siba_get_port_rid),
680 	DEVMETHOD(bhnd_bus_decode_port_rid,	siba_decode_port_rid),
681 	DEVMETHOD(bhnd_bus_get_region_addr,	siba_get_region_addr),
682 
683 	DEVMETHOD_END
684 };
685 
686 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
687 
688 MODULE_VERSION(siba, 1);
689 MODULE_DEPEND(siba, bhnd, 1, 1, 1);
690