]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/siba/siba.c
Merge OpenSSL 1.0.2i.
[FreeBSD/FreeBSD.git] / sys / dev / bhnd / siba / siba.c
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);