xref: /freebsd/sys/dev/bhnd/siba/siba.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
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 int
220 siba_reset_core(device_t dev, device_t child, uint16_t flags)
221 {
222 	struct siba_devinfo *dinfo;
223 
224 	if (device_get_parent(child) != dev)
225 		BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags);
226 
227 	dinfo = device_get_ivars(child);
228 
229 	/* Can't reset the core without access to the CFG0 registers */
230 	if (dinfo->cfg[0] == NULL)
231 		return (ENODEV);
232 
233 	// TODO - perform reset
234 
235 	return (ENXIO);
236 }
237 
238 static int
239 siba_suspend_core(device_t dev, device_t child)
240 {
241 	struct siba_devinfo *dinfo;
242 
243 	if (device_get_parent(child) != dev)
244 		BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child);
245 
246 	dinfo = device_get_ivars(child);
247 
248 	/* Can't suspend the core without access to the CFG0 registers */
249 	if (dinfo->cfg[0] == NULL)
250 		return (ENODEV);
251 
252 	// TODO - perform suspend
253 
254 	return (ENXIO);
255 }
256 
257 
258 static u_int
259 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
260 {
261 	struct siba_devinfo *dinfo;
262 
263 	/* delegate non-bus-attached devices to our parent */
264 	if (device_get_parent(child) != dev)
265 		return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
266 		    type));
267 
268 	dinfo = device_get_ivars(child);
269 
270 	/* We advertise exactly one port of any type */
271 	if (siba_dinfo_get_port(dinfo, type, 0) != NULL)
272 		return (1);
273 
274 	return (0);
275 }
276 
277 static u_int
278 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
279     u_int port_num)
280 {
281 	struct siba_devinfo	*dinfo;
282 	struct siba_port	*port;
283 
284 	/* delegate non-bus-attached devices to our parent */
285 	if (device_get_parent(child) != dev)
286 		return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
287 		    type, port_num));
288 
289 	dinfo = device_get_ivars(child);
290 	port = siba_dinfo_get_port(dinfo, type, port_num);
291 	if (port == NULL)
292 		return (0);
293 
294 	return (port->sp_num_addrs);
295 }
296 
297 static int
298 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
299     u_int port_num, u_int region_num)
300 {
301 	struct siba_devinfo	*dinfo;
302 	struct siba_port	*port;
303 	struct siba_addrspace	*addrspace;
304 
305 	/* delegate non-bus-attached devices to our parent */
306 	if (device_get_parent(child) != dev)
307 		return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
308 		    port_type, port_num, region_num));
309 
310 	dinfo = device_get_ivars(child);
311 	port = siba_dinfo_get_port(dinfo, port_type, port_num);
312 	if (port == NULL)
313 		return (-1);
314 
315 	STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
316 		if (addrspace->sa_region_num == region_num)
317 			return (addrspace->sa_rid);
318 	}
319 
320 	/* not found */
321 	return (-1);
322 }
323 
324 static int
325 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
326     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
327 {
328 	struct siba_devinfo	*dinfo;
329 	struct siba_port	*port;
330 	struct siba_addrspace	*addrspace;
331 
332 	/* delegate non-bus-attached devices to our parent */
333 	if (device_get_parent(child) != dev)
334 		return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
335 		    type, rid, port_type, port_num, region_num));
336 
337 	dinfo = device_get_ivars(child);
338 
339 	/* Ports are always memory mapped */
340 	if (type != SYS_RES_MEMORY)
341 		return (EINVAL);
342 
343 	/* Starting with the most likely device list, search all three port
344 	 * lists */
345 	bhnd_port_type types[] = {
346 	    BHND_PORT_DEVICE,
347 	    BHND_PORT_AGENT,
348 	    BHND_PORT_BRIDGE
349 	};
350 
351 	for (int i = 0; i < nitems(types); i++) {
352 		port = siba_dinfo_get_port(dinfo, types[i], 0);
353 		if (port == NULL)
354 			continue;
355 
356 		STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
357 			if (addrspace->sa_rid != rid)
358 				continue;
359 
360 			*port_type = port->sp_type;
361 			*port_num = port->sp_num;
362 			*region_num = addrspace->sa_region_num;
363 		}
364 	}
365 
366 	return (ENOENT);
367 }
368 
369 static int
370 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
371     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
372 {
373 	struct siba_devinfo	*dinfo;
374 	struct siba_port	*port;
375 	struct siba_addrspace	*addrspace;
376 
377 	/* delegate non-bus-attached devices to our parent */
378 	if (device_get_parent(child) != dev) {
379 		return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
380 		    port_type, port_num, region_num, addr, size));
381 	}
382 
383 	dinfo = device_get_ivars(child);
384 	port = siba_dinfo_get_port(dinfo, port_type, port_num);
385 	if (port == NULL)
386 		return (ENOENT);
387 
388 	STAILQ_FOREACH(addrspace, &port->sp_addrs, sa_link) {
389 		if (addrspace->sa_region_num != region_num)
390 			continue;
391 
392 		*addr = addrspace->sa_base;
393 		*size = addrspace->sa_size;
394 		return (0);
395 	}
396 
397 	return (ENOENT);
398 }
399 
400 
401 /**
402  * Register all address space mappings for @p di.
403  *
404  * @param dev The siba bus device.
405  * @param di The device info instance on which to register all address
406  * space entries.
407  * @param r A resource mapping the enumeration table block for @p di.
408  */
409 static int
410 siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
411     struct resource *r)
412 {
413 	struct siba_core_id	*cid;
414 	uint32_t		 addr;
415 	uint32_t		 size;
416 	u_int			 region_num;
417 	int			 error;
418 
419 	cid = &di->core_id;
420 
421 	/* Region numbers must be assigned in order, but our siba address
422 	 * space IDs may be sparsely allocated; thus, we track
423 	 * the region index seperately. */
424 	region_num = 0;
425 
426 	/* Register the device address space entries */
427 	for (uint8_t sid = 0; sid < di->core_id.num_addrspace; sid++) {
428 		uint32_t	adm;
429 		u_int		adm_offset;
430 		uint32_t	bus_reserved;
431 
432 		/* Determine the register offset */
433 		adm_offset = siba_admatch_offset(sid);
434 		if (adm_offset == 0) {
435 		    device_printf(dev, "addrspace %hhu is unsupported", sid);
436 		    return (ENODEV);
437 		}
438 
439 		/* Fetch the address match register value */
440 		adm = bus_read_4(r, adm_offset);
441 
442 		/* Skip disabled entries */
443 		if (adm & SIBA_AM_ADEN)
444 			continue;
445 
446 		/* Parse the value */
447 		if ((error = siba_parse_admatch(adm, &addr, &size))) {
448 			device_printf(dev, "failed to decode address "
449 			    " match register value 0x%x\n", adm);
450 			return (error);
451 		}
452 
453 		/* If this is the device's core/enumeration addrespace,
454 		 * reserve the Sonics configuration register blocks for the
455 		 * use of our bus. */
456 		bus_reserved = 0;
457 		if (sid == SIBA_ADDRSPACE_CORE)
458 			bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
459 
460 		/* Append the region info */
461 		error = siba_append_dinfo_region(di, BHND_PORT_DEVICE, 0,
462 		    region_num, sid, addr, size, bus_reserved);
463 		if (error)
464 			return (error);
465 
466 
467 		region_num++;
468 	}
469 
470 	return (0);
471 }
472 
473 /**
474  * Scan the core table and add all valid discovered cores to
475  * the bus.
476  *
477  * @param dev The siba bus device.
478  * @param chipid The chip identifier, if the device does not provide a
479  * ChipCommon core. Should o NULL otherwise.
480  */
481 int
482 siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
483 {
484 	struct bhnd_chipid	 ccid;
485 	struct bhnd_core_info	*cores;
486 	struct siba_devinfo	*dinfo;
487 	struct resource		*r;
488 	int			 rid;
489 	int			 error;
490 
491 	dinfo = NULL;
492 	cores = NULL;
493 	r = NULL;
494 
495 	/*
496 	 * Try to determine the number of device cores via the ChipCommon
497 	 * identification registers.
498 	 *
499 	 * A small number of very early devices do not include a ChipCommon
500 	 * core, in which case our caller must supply the chip identification
501 	 * information via a non-NULL chipid parameter.
502 	 */
503 	if (chipid == NULL) {
504 		uint32_t	idhigh, ccreg;
505 		uint16_t	vendor, device;
506 		uint8_t		ccrev;
507 
508 		/* Map the first core's register block. If the ChipCommon core
509 		 * exists, it will always be the first core. */
510 		rid = 0;
511 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
512 		    SIBA_CORE_ADDR(0), SIBA_CORE_SIZE,
513 		    SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1,
514 		    RF_ACTIVE);
515 
516 		/* Identify the core */
517 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
518 		vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
519 		device = SIBA_REG_GET(idhigh, IDH_DEVICE);
520 		ccrev = SIBA_IDH_CORE_REV(idhigh);
521 
522 		if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) {
523 			device_printf(dev,
524 			    "cannot identify device: no chipcommon core "
525 			    "found\n");
526 			error = ENXIO;
527 			goto cleanup;
528 		}
529 
530 		/* Identify the chipset */
531 		ccreg = bus_read_4(r, CHIPC_ID);
532 		ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR);
533 
534 		if (!CHIPC_NCORES_MIN_HWREV(ccrev)) {
535 			switch (device) {
536 			case BHND_CHIPID_BCM4306:
537 				ccid.ncores = 6;
538 				break;
539 			case BHND_CHIPID_BCM4704:
540 				ccid.ncores = 9;
541 				break;
542 			case BHND_CHIPID_BCM5365:
543 				/*
544 				* BCM5365 does support ID_NUMCORE in at least
545 				* some of its revisions, but for unknown
546 				* reasons, Broadcom's drivers always exclude
547 				* the ChipCommon revision (0x5) used by BCM5365
548 				* from the set of revisions supporting
549 				* ID_NUMCORE, and instead supply a fixed value.
550 				*
551 				* Presumably, at least some of these devices
552 				* shipped with a broken ID_NUMCORE value.
553 				*/
554 				ccid.ncores = 7;
555 				break;
556 			default:
557 				device_printf(dev, "unable to determine core "
558 				    "count for unrecognized chipset 0x%hx\n",
559 				    ccid.chip_id);
560 				error = ENXIO;
561 				goto cleanup;
562 			}
563 		}
564 
565 		chipid = &ccid;
566 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
567 	}
568 
569 	/* Allocate our temporary core table and enumerate all cores */
570 	cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
571 	if (cores == NULL)
572 		return (ENOMEM);
573 
574 	/* Add all cores. */
575 	for (u_int i = 0; i < chipid->ncores; i++) {
576 		struct siba_core_id	 cid;
577 		device_t		 child;
578 		uint32_t		 idhigh, idlow;
579 		rman_res_t		 r_count, r_end, r_start;
580 
581 		/* Map the core's register block */
582 		rid = 0;
583 		r_start = SIBA_CORE_ADDR(i);
584 		r_count = SIBA_CORE_SIZE;
585 		r_end = r_start + SIBA_CORE_SIZE - 1;
586 		r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
587 		    r_end, r_count, RF_ACTIVE);
588 		if (r == NULL) {
589 			error = ENXIO;
590 			goto cleanup;
591 		}
592 
593 		/* Read the core info */
594 		idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
595 		idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
596 
597 		cid = siba_parse_core_id(idhigh, idlow, i, 0);
598 		cores[i] = cid.core_info;
599 
600 		/* Determine unit number */
601 		for (u_int j = 0; j < i; j++) {
602 			if (cores[j].vendor == cores[i].vendor &&
603 			    cores[j].device == cores[i].device)
604 				cores[i].unit++;
605 		}
606 
607 		/* Allocate per-device bus info */
608 		dinfo = siba_alloc_dinfo(dev, &cid);
609 		if (dinfo == NULL) {
610 			error = ENXIO;
611 			goto cleanup;
612 		}
613 
614 		/* Register the core's address space(s). */
615 		if ((error = siba_register_addrspaces(dev, dinfo, r)))
616 			goto cleanup;
617 
618 		/* Add the child device */
619 		child = device_add_child(dev, NULL, -1);
620 		if (child == NULL) {
621 			error = ENXIO;
622 			goto cleanup;
623 		}
624 
625 		/* The child device now owns the dinfo pointer */
626 		device_set_ivars(child, dinfo);
627 		dinfo = NULL;
628 
629 		/* If pins are floating or the hardware is otherwise
630 		 * unpopulated, the device shouldn't be used. */
631 		if (bhnd_is_hw_disabled(child))
632 			device_disable(child);
633 
634 		/* Release our resource */
635 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
636 		r = NULL;
637 	}
638 
639 cleanup:
640 	if (cores != NULL)
641 		free(cores, M_BHND);
642 
643 	if (dinfo != NULL)
644 		siba_free_dinfo(dev, dinfo);
645 
646 	if (r != NULL)
647 		bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
648 
649 	return (error);
650 }
651 
652 static device_method_t siba_methods[] = {
653 	/* Device interface */
654 	DEVMETHOD(device_probe,			siba_probe),
655 	DEVMETHOD(device_attach,		siba_attach),
656 	DEVMETHOD(device_detach,		siba_detach),
657 
658 	/* Bus interface */
659 	DEVMETHOD(bus_child_deleted,		siba_child_deleted),
660 	DEVMETHOD(bus_read_ivar,		siba_read_ivar),
661 	DEVMETHOD(bus_write_ivar,		siba_write_ivar),
662 	DEVMETHOD(bus_get_resource_list,	siba_get_resource_list),
663 
664 	/* BHND interface */
665 	DEVMETHOD(bhnd_bus_reset_core,		siba_reset_core),
666 	DEVMETHOD(bhnd_bus_suspend_core,	siba_suspend_core),
667 	DEVMETHOD(bhnd_bus_get_port_count,	siba_get_port_count),
668 	DEVMETHOD(bhnd_bus_get_region_count,	siba_get_region_count),
669 	DEVMETHOD(bhnd_bus_get_port_rid,	siba_get_port_rid),
670 	DEVMETHOD(bhnd_bus_decode_port_rid,	siba_decode_port_rid),
671 	DEVMETHOD(bhnd_bus_get_region_addr,	siba_get_region_addr),
672 
673 	DEVMETHOD_END
674 };
675 
676 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
677 
678 MODULE_VERSION(siba, 1);
679 MODULE_DEPEND(siba, bhnd, 1, 1, 1);
680