xref: /freebsd/sys/dev/bhnd/siba/siba.c (revision 09a53ad8f1318c5daae6cfb19d97f4f6459f0013)
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 static bhnd_erom_class_t *
48 siba_get_erom_class(driver_t *driver)
49 {
50 	return (&siba_erom_parser);
51 }
52 
53 int
54 siba_probe(device_t dev)
55 {
56 	device_set_desc(dev, "SIBA BHND bus");
57 	return (BUS_PROBE_DEFAULT);
58 }
59 
60 /**
61  * Default siba(4) bus driver implementation of DEVICE_ATTACH().
62  *
63  * This implementation initializes internal siba(4) state and performs
64  * bus enumeration, and must be called by subclassing drivers in
65  * DEVICE_ATTACH() before any other bus methods.
66  */
67 int
68 siba_attach(device_t dev)
69 {
70 	struct siba_softc	*sc;
71 	int			 error;
72 
73 	sc = device_get_softc(dev);
74 	sc->dev = dev;
75 
76 	/* Enumerate children */
77 	if ((error = siba_add_children(dev))) {
78 		device_delete_children(dev);
79 		return (error);
80 	}
81 
82 	return (0);
83 }
84 
85 int
86 siba_detach(device_t dev)
87 {
88 	return (bhnd_generic_detach(dev));
89 }
90 
91 int
92 siba_resume(device_t dev)
93 {
94 	return (bhnd_generic_resume(dev));
95 }
96 
97 int
98 siba_suspend(device_t dev)
99 {
100 	return (bhnd_generic_suspend(dev));
101 }
102 
103 static int
104 siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
105 {
106 	const struct siba_devinfo *dinfo;
107 	const struct bhnd_core_info *cfg;
108 
109 	dinfo = device_get_ivars(child);
110 	cfg = &dinfo->core_id.core_info;
111 
112 	switch (index) {
113 	case BHND_IVAR_VENDOR:
114 		*result = cfg->vendor;
115 		return (0);
116 	case BHND_IVAR_DEVICE:
117 		*result = cfg->device;
118 		return (0);
119 	case BHND_IVAR_HWREV:
120 		*result = cfg->hwrev;
121 		return (0);
122 	case BHND_IVAR_DEVICE_CLASS:
123 		*result = bhnd_core_class(cfg);
124 		return (0);
125 	case BHND_IVAR_VENDOR_NAME:
126 		*result = (uintptr_t) bhnd_vendor_name(cfg->vendor);
127 		return (0);
128 	case BHND_IVAR_DEVICE_NAME:
129 		*result = (uintptr_t) bhnd_core_name(cfg);
130 		return (0);
131 	case BHND_IVAR_CORE_INDEX:
132 		*result = cfg->core_idx;
133 		return (0);
134 	case BHND_IVAR_CORE_UNIT:
135 		*result = cfg->unit;
136 		return (0);
137 	default:
138 		return (ENOENT);
139 	}
140 }
141 
142 static int
143 siba_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
144 {
145 	switch (index) {
146 	case BHND_IVAR_VENDOR:
147 	case BHND_IVAR_DEVICE:
148 	case BHND_IVAR_HWREV:
149 	case BHND_IVAR_DEVICE_CLASS:
150 	case BHND_IVAR_VENDOR_NAME:
151 	case BHND_IVAR_DEVICE_NAME:
152 	case BHND_IVAR_CORE_INDEX:
153 	case BHND_IVAR_CORE_UNIT:
154 		return (EINVAL);
155 	default:
156 		return (ENOENT);
157 	}
158 }
159 
160 static struct resource_list *
161 siba_get_resource_list(device_t dev, device_t child)
162 {
163 	struct siba_devinfo *dinfo = device_get_ivars(child);
164 	return (&dinfo->resources);
165 }
166 
167 static int
168 siba_reset_core(device_t dev, device_t child, uint16_t flags)
169 {
170 	struct siba_devinfo *dinfo;
171 
172 	if (device_get_parent(child) != dev)
173 		BHND_BUS_RESET_CORE(device_get_parent(dev), child, flags);
174 
175 	dinfo = device_get_ivars(child);
176 
177 	/* Can't reset the core without access to the CFG0 registers */
178 	if (dinfo->cfg[0] == NULL)
179 		return (ENODEV);
180 
181 	// TODO - perform reset
182 
183 	return (ENXIO);
184 }
185 
186 static int
187 siba_suspend_core(device_t dev, device_t child)
188 {
189 	struct siba_devinfo *dinfo;
190 
191 	if (device_get_parent(child) != dev)
192 		BHND_BUS_SUSPEND_CORE(device_get_parent(dev), child);
193 
194 	dinfo = device_get_ivars(child);
195 
196 	/* Can't suspend the core without access to the CFG0 registers */
197 	if (dinfo->cfg[0] == NULL)
198 		return (ENODEV);
199 
200 	// TODO - perform suspend
201 
202 	return (ENXIO);
203 }
204 
205 static uint32_t
206 siba_read_config(device_t dev, device_t child, bus_size_t offset, u_int width)
207 {
208 	struct siba_devinfo	*dinfo;
209 	rman_res_t		 r_size;
210 
211 	/* Must be directly attached */
212 	if (device_get_parent(child) != dev)
213 		return (UINT32_MAX);
214 
215 	/* CFG0 registers must be available */
216 	dinfo = device_get_ivars(child);
217 	if (dinfo->cfg[0] == NULL)
218 		return (UINT32_MAX);
219 
220 	/* Offset must fall within CFG0 */
221 	r_size = rman_get_size(dinfo->cfg[0]->res);
222 	if (r_size < offset || r_size - offset < width)
223 		return (UINT32_MAX);
224 
225 	switch (width) {
226 	case 1:
227 		return (bhnd_bus_read_1(dinfo->cfg[0], offset));
228 	case 2:
229 		return (bhnd_bus_read_2(dinfo->cfg[0], offset));
230 	case 4:
231 		return (bhnd_bus_read_4(dinfo->cfg[0], offset));
232 	}
233 
234 	/* Unsuported */
235 	return (UINT32_MAX);
236 }
237 
238 static void
239 siba_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
240     u_int width)
241 {
242 	struct siba_devinfo	*dinfo;
243 	rman_res_t		 r_size;
244 
245 	/* Must be directly attached */
246 	if (device_get_parent(child) != dev)
247 		return;
248 
249 	/* CFG0 registers must be available */
250 	dinfo = device_get_ivars(child);
251 	if (dinfo->cfg[0] == NULL)
252 		return;
253 
254 	/* Offset must fall within CFG0 */
255 	r_size = rman_get_size(dinfo->cfg[0]->res);
256 	if (r_size < offset || r_size - offset < width)
257 		return;
258 
259 	switch (width) {
260 	case 1:
261 		bhnd_bus_write_1(dinfo->cfg[0], offset, val);
262 	case 2:
263 		bhnd_bus_write_2(dinfo->cfg[0], offset, val);
264 	case 4:
265 		bhnd_bus_write_4(dinfo->cfg[0], offset, val);
266 	}
267 }
268 
269 static u_int
270 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
271 {
272 	struct siba_devinfo *dinfo;
273 
274 	/* delegate non-bus-attached devices to our parent */
275 	if (device_get_parent(child) != dev)
276 		return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
277 		    type));
278 
279 	dinfo = device_get_ivars(child);
280 	return (siba_addrspace_port_count(dinfo->core_id.num_addrspace));
281 }
282 
283 static u_int
284 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
285     u_int port)
286 {
287 	struct siba_devinfo	*dinfo;
288 
289 	/* delegate non-bus-attached devices to our parent */
290 	if (device_get_parent(child) != dev)
291 		return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
292 		    type, port));
293 
294 	dinfo = device_get_ivars(child);
295 	if (!siba_is_port_valid(dinfo->core_id.num_addrspace, type, port))
296 		return (0);
297 
298 	return (siba_addrspace_region_count(dinfo->core_id.num_addrspace,
299 	    port));
300 }
301 
302 static int
303 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
304     u_int port_num, u_int region_num)
305 {
306 	struct siba_devinfo	*dinfo;
307 	struct siba_addrspace	*addrspace;
308 
309 	/* delegate non-bus-attached devices to our parent */
310 	if (device_get_parent(child) != dev)
311 		return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
312 		    port_type, port_num, region_num));
313 
314 	dinfo = device_get_ivars(child);
315 	addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
316 	if (addrspace == NULL)
317 		return (-1);
318 
319 	return (addrspace->sa_rid);
320 }
321 
322 static int
323 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
324     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
325 {
326 	struct siba_devinfo	*dinfo;
327 
328 	/* delegate non-bus-attached devices to our parent */
329 	if (device_get_parent(child) != dev)
330 		return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
331 		    type, rid, port_type, port_num, region_num));
332 
333 	dinfo = device_get_ivars(child);
334 
335 	/* Ports are always memory mapped */
336 	if (type != SYS_RES_MEMORY)
337 		return (EINVAL);
338 
339 	for (int i = 0; i < dinfo->core_id.num_addrspace; i++) {
340 		if (dinfo->addrspace[i].sa_rid != rid)
341 			continue;
342 
343 		*port_type = BHND_PORT_DEVICE;
344 		*port_num = siba_addrspace_port(i);
345 		*region_num = siba_addrspace_region(i);
346 		return (0);
347 	}
348 
349 	/* Not found */
350 	return (ENOENT);
351 }
352 
353 static int
354 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
355     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
356 {
357 	struct siba_devinfo	*dinfo;
358 	struct siba_addrspace	*addrspace;
359 
360 	/* delegate non-bus-attached devices to our parent */
361 	if (device_get_parent(child) != dev) {
362 		return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
363 		    port_type, port_num, region_num, addr, size));
364 	}
365 
366 	dinfo = device_get_ivars(child);
367 	addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
368 	if (addrspace == NULL)
369 		return (ENOENT);
370 
371 	*addr = addrspace->sa_base;
372 	*size = addrspace->sa_size - addrspace->sa_bus_reserved;
373 	return (0);
374 }
375 
376 /**
377  * Default siba(4) bus driver implementation of BHND_BUS_GET_INTR_COUNT().
378  *
379  * This implementation consults @p child's configuration block mapping,
380  * returning SIBA_CORE_NUM_INTR if a valid CFG0 block is mapped.
381  */
382 int
383 siba_get_intr_count(device_t dev, device_t child)
384 {
385 	struct siba_devinfo *dinfo;
386 
387 	/* delegate non-bus-attached devices to our parent */
388 	if (device_get_parent(child) != dev)
389 		return (BHND_BUS_GET_INTR_COUNT(device_get_parent(dev), child));
390 
391 	dinfo = device_get_ivars(child);
392 
393 	/* We can get/set interrupt sbflags on any core with a valid cfg0
394 	 * block; whether the core actually makes use of it is another matter
395 	 * entirely */
396 	if (dinfo->cfg[0] == NULL)
397 		return (0);
398 
399 	return (SIBA_CORE_NUM_INTR);
400 }
401 
402 /**
403  * Default siba(4) bus driver implementation of BHND_BUS_GET_CORE_IVEC().
404  *
405  * This implementation consults @p child's CFG0 register block,
406  * returning the interrupt flag assigned to @p child.
407  */
408 int
409 siba_get_core_ivec(device_t dev, device_t child, u_int intr, uint32_t *ivec)
410 {
411 	struct siba_devinfo	*dinfo;
412 	uint32_t		 tpsflag;
413 
414 	/* delegate non-bus-attached devices to our parent */
415 	if (device_get_parent(child) != dev)
416 		return (BHND_BUS_GET_CORE_IVEC(device_get_parent(dev), child,
417 		    intr, ivec));
418 
419 	/* Must be a valid interrupt ID */
420 	if (intr >= siba_get_intr_count(dev, child))
421 		return (ENXIO);
422 
423 	/* Fetch sbflag number */
424 	dinfo = device_get_ivars(child);
425 	tpsflag = bhnd_bus_read_4(dinfo->cfg[0], SIBA_CFG0_TPSFLAG);
426 	*ivec = SIBA_REG_GET(tpsflag, TPS_NUM0);
427 
428 	return (0);
429 }
430 
431 /**
432  * Register all address space mappings for @p di.
433  *
434  * @param dev The siba bus device.
435  * @param di The device info instance on which to register all address
436  * space entries.
437  * @param r A resource mapping the enumeration table block for @p di.
438  */
439 static int
440 siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
441     struct bhnd_resource *r)
442 {
443 	struct siba_core_id	*cid;
444 	uint32_t		 addr;
445 	uint32_t		 size;
446 	int			 error;
447 
448 	cid = &di->core_id;
449 
450 
451 	/* Register the device address space entries */
452 	for (uint8_t i = 0; i < di->core_id.num_addrspace; i++) {
453 		uint32_t	adm;
454 		u_int		adm_offset;
455 		uint32_t	bus_reserved;
456 
457 		/* Determine the register offset */
458 		adm_offset = siba_admatch_offset(i);
459 		if (adm_offset == 0) {
460 		    device_printf(dev, "addrspace %hhu is unsupported", i);
461 		    return (ENODEV);
462 		}
463 
464 		/* Fetch the address match register value */
465 		adm = bhnd_bus_read_4(r, adm_offset);
466 
467 		/* Parse the value */
468 		if ((error = siba_parse_admatch(adm, &addr, &size))) {
469 			device_printf(dev, "failed to decode address "
470 			    " match register value 0x%x\n", adm);
471 			return (error);
472 		}
473 
474 		/* If this is the device's core/enumeration addrespace,
475 		 * reserve the Sonics configuration register blocks for the
476 		 * use of our bus. */
477 		bus_reserved = 0;
478 		if (i == SIBA_CORE_ADDRSPACE)
479 			bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
480 
481 		/* Append the region info */
482 		error = siba_append_dinfo_region(di, i, addr, size,
483 		    bus_reserved);
484 		if (error)
485 			return (error);
486 	}
487 
488 	return (0);
489 }
490 
491 /**
492  * Map per-core configuration blocks for @p dinfo.
493  *
494  * @param dev The siba bus device.
495  * @param dinfo The device info instance on which to map all per-core
496  * configuration blocks.
497  */
498 static int
499 siba_map_cfg_resources(device_t dev, struct siba_devinfo *dinfo)
500 {
501 	struct siba_addrspace	*addrspace;
502 	rman_res_t		 r_start, r_count, r_end;
503 	uint8_t			 num_cfg;
504 
505 	num_cfg = dinfo->core_id.num_cfg_blocks;
506 	if (num_cfg > SIBA_MAX_CFG) {
507 		device_printf(dev, "config block count %hhu out of range\n",
508 		    num_cfg);
509 		return (ENXIO);
510 	}
511 
512 	/* Fetch the core register address space */
513 	addrspace = siba_find_addrspace(dinfo, BHND_PORT_DEVICE, 0, 0);
514 	if (addrspace == NULL) {
515 		device_printf(dev, "missing device registers\n");
516 		return (ENXIO);
517 	}
518 
519 	/*
520 	 * Map the per-core configuration blocks
521 	 */
522 	for (uint8_t i = 0; i < num_cfg; i++) {
523 		/* Determine the config block's address range; configuration
524 		 * blocks are allocated starting at SIBA_CFG0_OFFSET,
525 		 * growing downwards. */
526 		r_start = addrspace->sa_base + SIBA_CFG0_OFFSET;
527 		r_start -= i * SIBA_CFG_SIZE;
528 
529 		r_count = SIBA_CFG_SIZE;
530 		r_end = r_start + r_count - 1;
531 
532 		/* Allocate the config resource */
533 		dinfo->cfg_rid[i] = SIBA_CFG_RID(dinfo, i);
534 		dinfo->cfg[i] = BHND_BUS_ALLOC_RESOURCE(dev, dev,
535 		    SYS_RES_MEMORY, &dinfo->cfg_rid[i], r_start, r_end,
536 		    r_count, RF_ACTIVE);
537 
538 		if (dinfo->cfg[i] == NULL) {
539 			device_printf(dev, "failed to allocate SIBA_CFG%hhu\n",
540 			    i);
541 			return (ENXIO);
542 		}
543 	}
544 
545 	return (0);
546 }
547 
548 
549 static struct bhnd_devinfo *
550 siba_alloc_bhnd_dinfo(device_t dev)
551 {
552 	struct siba_devinfo *dinfo = siba_alloc_dinfo(dev);
553 	return ((struct bhnd_devinfo *)dinfo);
554 }
555 
556 static void
557 siba_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo)
558 {
559 	siba_free_dinfo(dev, (struct siba_devinfo *)dinfo);
560 }
561 
562 /**
563  * Scan the core table and add all valid discovered cores to
564  * the bus.
565  *
566  * @param dev The siba bus device.
567  */
568 int
569 siba_add_children(device_t dev)
570 {
571 	const struct bhnd_chipid	*chipid;
572 	struct bhnd_core_info		*cores;
573 	struct siba_devinfo		*dinfo;
574 	struct bhnd_resource		*r;
575 	int				 rid;
576 	int				 error;
577 
578 	dinfo = NULL;
579 	cores = NULL;
580 	r = NULL;
581 
582 	chipid = BHND_BUS_GET_CHIPID(dev, dev);
583 
584 	/* Allocate our temporary core table and enumerate all cores */
585 	cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
586 	if (cores == NULL)
587 		return (ENOMEM);
588 
589 	/* Add all cores. */
590 	for (u_int i = 0; i < chipid->ncores; i++) {
591 		struct siba_core_id	 cid;
592 		device_t		 child;
593 		uint32_t		 idhigh, idlow;
594 		rman_res_t		 r_count, r_end, r_start;
595 		int			 nintr;
596 
597 		/* Map the core's register block */
598 		rid = 0;
599 		r_start = SIBA_CORE_ADDR(i);
600 		r_count = SIBA_CORE_SIZE;
601 		r_end = r_start + SIBA_CORE_SIZE - 1;
602 		r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
603 		    r_end, r_count, RF_ACTIVE);
604 		if (r == NULL) {
605 			error = ENXIO;
606 			goto cleanup;
607 		}
608 
609 		/* Add the child device */
610 		child = BUS_ADD_CHILD(dev, 0, NULL, -1);
611 		if (child == NULL) {
612 			error = ENXIO;
613 			goto cleanup;
614 		}
615 
616 		/* Read the core info */
617 		idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
618 		idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
619 
620 		cid = siba_parse_core_id(idhigh, idlow, i, 0);
621 		cores[i] = cid.core_info;
622 
623 		/* Determine unit number */
624 		for (u_int j = 0; j < i; j++) {
625 			if (cores[j].vendor == cores[i].vendor &&
626 			    cores[j].device == cores[i].device)
627 				cores[i].unit++;
628 		}
629 
630 		/* Initialize per-device bus info */
631 		if ((dinfo = device_get_ivars(child)) == NULL) {
632 			error = ENXIO;
633 			goto cleanup;
634 		}
635 
636 		if ((error = siba_init_dinfo(dev, dinfo, &cid)))
637 			goto cleanup;
638 
639 		/* Register the core's address space(s). */
640 		if ((error = siba_register_addrspaces(dev, dinfo, r)))
641 			goto cleanup;
642 
643 		/* Release our resource covering the register blocks
644 		 * we're about to map */
645 		bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
646 		r = NULL;
647 
648 		/* Map the core's config blocks */
649 		if ((error = siba_map_cfg_resources(dev, dinfo)))
650 			goto cleanup;
651 
652 		/* Assign interrupts */
653 		nintr = bhnd_get_intr_count(child);
654 		for (int rid = 0; rid < nintr; rid++) {
655 			error = BHND_BUS_ASSIGN_INTR(dev, child, rid);
656 			if (error) {
657 				device_printf(dev, "failed to assign interrupt "
658 				    "%d to core %u: %d\n", rid, i, error);
659 			}
660 		}
661 
662 		/* If pins are floating or the hardware is otherwise
663 		 * unpopulated, the device shouldn't be used. */
664 		if (bhnd_is_hw_disabled(child))
665 			device_disable(child);
666 
667 		/* Issue bus callback for fully initialized child. */
668 		BHND_BUS_CHILD_ADDED(dev, child);
669 	}
670 
671 cleanup:
672 	if (cores != NULL)
673 		free(cores, M_BHND);
674 
675 	if (r != NULL)
676 		bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
677 
678 	return (error);
679 }
680 
681 static device_method_t siba_methods[] = {
682 	/* Device interface */
683 	DEVMETHOD(device_probe,			siba_probe),
684 	DEVMETHOD(device_attach,		siba_attach),
685 	DEVMETHOD(device_detach,		siba_detach),
686 	DEVMETHOD(device_resume,		siba_resume),
687 	DEVMETHOD(device_suspend,		siba_suspend),
688 
689 	/* Bus interface */
690 	DEVMETHOD(bus_read_ivar,		siba_read_ivar),
691 	DEVMETHOD(bus_write_ivar,		siba_write_ivar),
692 	DEVMETHOD(bus_get_resource_list,	siba_get_resource_list),
693 
694 	/* BHND interface */
695 	DEVMETHOD(bhnd_bus_get_erom_class,	siba_get_erom_class),
696 	DEVMETHOD(bhnd_bus_alloc_devinfo,	siba_alloc_bhnd_dinfo),
697 	DEVMETHOD(bhnd_bus_free_devinfo,	siba_free_bhnd_dinfo),
698 	DEVMETHOD(bhnd_bus_reset_core,		siba_reset_core),
699 	DEVMETHOD(bhnd_bus_suspend_core,	siba_suspend_core),
700 	DEVMETHOD(bhnd_bus_read_config,		siba_read_config),
701 	DEVMETHOD(bhnd_bus_write_config,	siba_write_config),
702 	DEVMETHOD(bhnd_bus_get_port_count,	siba_get_port_count),
703 	DEVMETHOD(bhnd_bus_get_region_count,	siba_get_region_count),
704 	DEVMETHOD(bhnd_bus_get_port_rid,	siba_get_port_rid),
705 	DEVMETHOD(bhnd_bus_decode_port_rid,	siba_decode_port_rid),
706 	DEVMETHOD(bhnd_bus_get_region_addr,	siba_get_region_addr),
707 	DEVMETHOD(bhnd_bus_get_intr_count,	siba_get_intr_count),
708 	DEVMETHOD(bhnd_bus_get_core_ivec,	siba_get_core_ivec),
709 
710 	DEVMETHOD_END
711 };
712 
713 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
714 
715 MODULE_VERSION(siba, 1);
716 MODULE_DEPEND(siba, bhnd, 1, 1, 1);
717