]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/bhnd/siba/siba.c
Update compiler-rt to 3.9.0 release, and update the build glue for
[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 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         struct siba_devinfo     *dinfo;
267         rman_res_t               r_size;
268
269         /* Must be directly attached */
270         if (device_get_parent(child) != dev)
271                 return (UINT32_MAX);
272
273         /* CFG0 registers must be available */
274         dinfo = device_get_ivars(child);
275         if (dinfo->cfg[0] == NULL)
276                 return (UINT32_MAX);
277
278         /* Offset must fall within CFG0 */
279         r_size = rman_get_size(dinfo->cfg[0]->res);
280         if (r_size < offset || r_size - offset < width)
281                 return (UINT32_MAX);
282
283         switch (width) {
284         case 1:
285                 return (bhnd_bus_read_1(dinfo->cfg[0], offset));
286         case 2:
287                 return (bhnd_bus_read_2(dinfo->cfg[0], offset));
288         case 4:
289                 return (bhnd_bus_read_4(dinfo->cfg[0], offset));
290         }
291         
292         /* Unsuported */
293         return (UINT32_MAX);
294 }
295
296 static void
297 siba_write_config(device_t dev, device_t child, bus_size_t offset, uint32_t val,
298     u_int width)
299 {
300         struct siba_devinfo     *dinfo;
301         rman_res_t               r_size;
302
303         /* Must be directly attached */
304         if (device_get_parent(child) != dev)
305                 return;
306
307         /* CFG0 registers must be available */
308         dinfo = device_get_ivars(child);
309         if (dinfo->cfg[0] == NULL)
310                 return;
311
312         /* Offset must fall within CFG0 */
313         r_size = rman_get_size(dinfo->cfg[0]->res);
314         if (r_size < offset || r_size - offset < width)
315                 return;
316
317         switch (width) {
318         case 1:
319                 bhnd_bus_write_1(dinfo->cfg[0], offset, val);
320         case 2:
321                 bhnd_bus_write_2(dinfo->cfg[0], offset, val);
322         case 4:
323                 bhnd_bus_write_4(dinfo->cfg[0], offset, val);
324         }
325 }
326
327 static u_int
328 siba_get_port_count(device_t dev, device_t child, bhnd_port_type type)
329 {
330         struct siba_devinfo *dinfo;
331
332         /* delegate non-bus-attached devices to our parent */
333         if (device_get_parent(child) != dev)
334                 return (BHND_BUS_GET_PORT_COUNT(device_get_parent(dev), child,
335                     type));
336
337         dinfo = device_get_ivars(child);
338         return (siba_addrspace_port_count(dinfo));
339 }
340
341 static u_int
342 siba_get_region_count(device_t dev, device_t child, bhnd_port_type type,
343     u_int port)
344 {
345         struct siba_devinfo     *dinfo;
346
347         /* delegate non-bus-attached devices to our parent */
348         if (device_get_parent(child) != dev)
349                 return (BHND_BUS_GET_REGION_COUNT(device_get_parent(dev), child,
350                     type, port));
351
352         dinfo = device_get_ivars(child);
353         if (!siba_is_port_valid(dinfo, type, port))
354                 return (0);
355
356         return (siba_addrspace_region_count(dinfo, port));
357 }
358
359 static int
360 siba_get_port_rid(device_t dev, device_t child, bhnd_port_type port_type,
361     u_int port_num, u_int region_num)
362 {
363         struct siba_devinfo     *dinfo;
364         struct siba_addrspace   *addrspace;
365
366         /* delegate non-bus-attached devices to our parent */
367         if (device_get_parent(child) != dev)
368                 return (BHND_BUS_GET_PORT_RID(device_get_parent(dev), child,
369                     port_type, port_num, region_num));
370
371         dinfo = device_get_ivars(child);
372         addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
373         if (addrspace == NULL)
374                 return (-1);
375
376         return (addrspace->sa_rid);
377 }
378
379 static int
380 siba_decode_port_rid(device_t dev, device_t child, int type, int rid,
381     bhnd_port_type *port_type, u_int *port_num, u_int *region_num)
382 {
383         struct siba_devinfo     *dinfo;
384
385         /* delegate non-bus-attached devices to our parent */
386         if (device_get_parent(child) != dev)
387                 return (BHND_BUS_DECODE_PORT_RID(device_get_parent(dev), child,
388                     type, rid, port_type, port_num, region_num));
389
390         dinfo = device_get_ivars(child);
391
392         /* Ports are always memory mapped */
393         if (type != SYS_RES_MEMORY)
394                 return (EINVAL);
395
396         for (int i = 0; i < dinfo->core_id.num_addrspace; i++) {
397                 if (dinfo->addrspace[i].sa_rid != rid)
398                         continue;
399
400                 *port_type = BHND_PORT_DEVICE;
401                 *port_num = siba_addrspace_port(i);
402                 *region_num = siba_addrspace_region(i);
403                 return (0);
404         }
405
406         /* Not found */
407         return (ENOENT);
408 }
409
410 static int
411 siba_get_region_addr(device_t dev, device_t child, bhnd_port_type port_type,
412     u_int port_num, u_int region_num, bhnd_addr_t *addr, bhnd_size_t *size)
413 {
414         struct siba_devinfo     *dinfo;
415         struct siba_addrspace   *addrspace;
416
417         /* delegate non-bus-attached devices to our parent */
418         if (device_get_parent(child) != dev) {
419                 return (BHND_BUS_GET_REGION_ADDR(device_get_parent(dev), child,
420                     port_type, port_num, region_num, addr, size));
421         }
422
423         dinfo = device_get_ivars(child);
424         addrspace = siba_find_addrspace(dinfo, port_type, port_num, region_num);
425         if (addrspace == NULL)
426                 return (ENOENT);
427
428         *addr = addrspace->sa_base;
429         *size = addrspace->sa_size - addrspace->sa_bus_reserved;
430         return (0);
431 }
432
433
434 /**
435  * Register all address space mappings for @p di.
436  *
437  * @param dev The siba bus device.
438  * @param di The device info instance on which to register all address
439  * space entries.
440  * @param r A resource mapping the enumeration table block for @p di.
441  */
442 static int
443 siba_register_addrspaces(device_t dev, struct siba_devinfo *di,
444     struct resource *r)
445 {
446         struct siba_core_id     *cid;
447         uint32_t                 addr;
448         uint32_t                 size;
449         int                      error;
450
451         cid = &di->core_id;
452
453
454         /* Register the device address space entries */
455         for (uint8_t i = 0; i < di->core_id.num_addrspace; i++) {
456                 uint32_t        adm;
457                 u_int           adm_offset;
458                 uint32_t        bus_reserved;
459
460                 /* Determine the register offset */
461                 adm_offset = siba_admatch_offset(i);
462                 if (adm_offset == 0) {
463                     device_printf(dev, "addrspace %hhu is unsupported", i);
464                     return (ENODEV);
465                 }
466
467                 /* Fetch the address match register value */
468                 adm = bus_read_4(r, adm_offset);
469
470                 /* Parse the value */
471                 if ((error = siba_parse_admatch(adm, &addr, &size))) {
472                         device_printf(dev, "failed to decode address "
473                             " match register value 0x%x\n", adm);
474                         return (error);
475                 }
476
477                 /* If this is the device's core/enumeration addrespace,
478                  * reserve the Sonics configuration register blocks for the
479                  * use of our bus. */
480                 bus_reserved = 0;
481                 if (i == SIBA_CORE_ADDRSPACE)
482                         bus_reserved = cid->num_cfg_blocks * SIBA_CFG_SIZE;
483
484                 /* Append the region info */
485                 error = siba_append_dinfo_region(di, i, addr, size,
486                     bus_reserved);
487                 if (error)
488                         return (error);
489         }
490
491         return (0);
492 }
493
494 static struct bhnd_devinfo *
495 siba_alloc_bhnd_dinfo(device_t dev)
496 {
497         struct siba_devinfo *dinfo = siba_alloc_dinfo(dev);
498         return ((struct bhnd_devinfo *)dinfo);
499 }
500
501 static void
502 siba_free_bhnd_dinfo(device_t dev, struct bhnd_devinfo *dinfo)
503 {
504         siba_free_dinfo(dev, (struct siba_devinfo *)dinfo);
505 }
506
507
508 static int
509 siba_get_core_table(device_t dev, device_t child, struct bhnd_core_info **cores,
510     u_int *num_cores)
511 {
512         const struct bhnd_chipid        *chipid;
513         struct bhnd_core_info           *table;
514         struct bhnd_resource            *r;
515         int                              error;
516         int                              rid;
517
518         /* Fetch the core count from our chip identification */
519         chipid = BHND_BUS_GET_CHIPID(dev, dev);
520
521         /* Allocate our local core table */
522         table = malloc(sizeof(*table) * chipid->ncores, M_BHND, M_NOWAIT);
523         if (table == NULL)
524                 return (ENOMEM);
525
526         /* Enumerate all cores. */
527         for (u_int i = 0; i < chipid->ncores; i++) {
528                 struct siba_core_id      cid;
529                 uint32_t                 idhigh, idlow;
530
531                 /* Map the core's register block */
532                 rid = 0;
533                 r = bhnd_alloc_resource(dev, SYS_RES_MEMORY, &rid,
534                     SIBA_CORE_ADDR(i), SIBA_CORE_ADDR(i) + SIBA_CORE_SIZE - 1,
535                     SIBA_CORE_SIZE, RF_ACTIVE);
536                 if (r == NULL) {
537                         error = ENXIO;
538                         goto failed;
539                 }
540
541                 /* Read the core info */
542                 idhigh = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
543                 idlow = bhnd_bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
544
545                 cid = siba_parse_core_id(idhigh, idlow, i, 0);
546                 table[i] = cid.core_info;
547
548                 /* Determine unit number */
549                 for (u_int j = 0; j < i; j++) {
550                         if (table[j].vendor == table[i].vendor &&
551                             table[j].device == table[i].device)
552                                 table[i].unit++;
553                 }
554                                 
555                 /* Release our resource */
556                 bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
557                 r = NULL;
558         }
559
560         /* Provide the result values (performed last to avoid modifying
561          * cores/num_cores if enumeration failed). */
562         *cores = table;
563         *num_cores = chipid->ncores;
564
565         return (0);
566
567 failed:
568         if (table != NULL)
569                 free(table, M_BHND);
570
571         if (r != NULL)
572                 bhnd_release_resource(dev, SYS_RES_MEMORY, rid, r);
573
574         return (error);
575 }
576
577 /**
578  * Scan the core table and add all valid discovered cores to
579  * the bus.
580  * 
581  * @param dev The siba bus device.
582  * @param chipid The chip identifier, if the device does not provide a
583  * ChipCommon core. Should o NULL otherwise.
584  */
585 int
586 siba_add_children(device_t dev, const struct bhnd_chipid *chipid)
587 {
588         struct bhnd_chipid       ccid;
589         struct bhnd_core_info   *cores;
590         struct siba_devinfo     *dinfo;
591         struct resource         *r;
592         int                      rid;
593         int                      error;
594
595         dinfo = NULL;
596         cores = NULL;
597         r = NULL;
598         
599         /*
600          * Try to determine the number of device cores via the ChipCommon
601          * identification registers.
602          * 
603          * A small number of very early devices do not include a ChipCommon
604          * core, in which case our caller must supply the chip identification
605          * information via a non-NULL chipid parameter.
606          */
607         if (chipid == NULL) {
608                 uint32_t        idhigh, ccreg;
609                 uint16_t        vendor, device;
610                 uint8_t         ccrev;
611
612                 /* Map the first core's register block. If the ChipCommon core
613                  * exists, it will always be the first core. */
614                 rid = 0;
615                 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
616                     SIBA_CORE_ADDR(0), SIBA_CORE_SIZE, 
617                     SIBA_CORE_ADDR(0) + SIBA_CORE_SIZE - 1,
618                     RF_ACTIVE);
619
620                 /* Identify the core */
621                 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
622                 vendor = SIBA_REG_GET(idhigh, IDH_VENDOR);
623                 device = SIBA_REG_GET(idhigh, IDH_DEVICE);
624                 ccrev = SIBA_IDH_CORE_REV(idhigh);
625
626                 if (vendor != OCP_VENDOR_BCM || device != BHND_COREID_CC) {
627                         device_printf(dev,
628                             "cannot identify device: no chipcommon core "
629                             "found\n");
630                         error = ENXIO;
631                         goto cleanup;
632                 }
633
634                 /* Identify the chipset */
635                 ccreg = bus_read_4(r, CHIPC_ID);
636                 ccid = bhnd_parse_chipid(ccreg, SIBA_ENUM_ADDR);
637
638                 /* Fix up the core count */
639                 error = bhnd_chipid_fixed_ncores(&ccid, ccrev, &ccid.ncores);
640                 if (error) {
641                         device_printf(dev, "unable to determine core count for "
642                             "chipset 0x%hx\n", ccid.chip_id);
643                         goto cleanup;
644                 }
645
646                 chipid = &ccid;
647                 bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
648         }
649
650         /* Allocate our temporary core table and enumerate all cores */
651         cores = malloc(sizeof(*cores) * chipid->ncores, M_BHND, M_NOWAIT);
652         if (cores == NULL)
653                 return (ENOMEM);
654
655         /* Add all cores. */
656         for (u_int i = 0; i < chipid->ncores; i++) {
657                 struct siba_core_id      cid;
658                 device_t                 child;
659                 uint32_t                 idhigh, idlow;
660                 rman_res_t               r_count, r_end, r_start;
661
662                 /* Map the core's register block */
663                 rid = 0;
664                 r_start = SIBA_CORE_ADDR(i);
665                 r_count = SIBA_CORE_SIZE;
666                 r_end = r_start + SIBA_CORE_SIZE - 1;
667                 r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, r_start,
668                     r_end, r_count, RF_ACTIVE);
669                 if (r == NULL) {
670                         error = ENXIO;
671                         goto cleanup;
672                 }
673
674                 /* Add the child device */
675                 child = BUS_ADD_CHILD(dev, 0, NULL, -1);
676                 if (child == NULL) {
677                         error = ENXIO;
678                         goto cleanup;
679                 }
680                 
681                 /* Read the core info */
682                 idhigh = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDHIGH));
683                 idlow = bus_read_4(r, SB0_REG_ABS(SIBA_CFG0_IDLOW));
684
685                 cid = siba_parse_core_id(idhigh, idlow, i, 0);
686                 cores[i] = cid.core_info;
687
688                 /* Determine unit number */
689                 for (u_int j = 0; j < i; j++) {
690                         if (cores[j].vendor == cores[i].vendor &&
691                             cores[j].device == cores[i].device)
692                                 cores[i].unit++;
693                 }
694
695                 /* Initialize per-device bus info */
696                 if ((dinfo = device_get_ivars(child)) == NULL) {
697                         error = ENXIO;
698                         goto cleanup;
699                 }
700
701                 if ((error = siba_init_dinfo(dev, dinfo, &cid)))
702                         goto cleanup;
703
704                 /* Register the core's address space(s). */
705                 if ((error = siba_register_addrspaces(dev, dinfo, r)))
706                         goto cleanup;
707
708                 /* If pins are floating or the hardware is otherwise
709                  * unpopulated, the device shouldn't be used. */
710                 if (bhnd_is_hw_disabled(child))
711                         device_disable(child);
712                                 
713                 /* Release our resource */
714                 bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
715                 r = NULL;
716
717                 /* Issue bus callback for fully initialized child. */
718                 BHND_BUS_CHILD_ADDED(dev, child);
719         }
720         
721 cleanup:
722         if (cores != NULL)
723                 free(cores, M_BHND);
724
725         if (r != NULL)
726                 bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
727
728         return (error);
729 }
730
731 static device_method_t siba_methods[] = {
732         /* Device interface */
733         DEVMETHOD(device_probe,                 siba_probe),
734         DEVMETHOD(device_attach,                siba_attach),
735         DEVMETHOD(device_detach,                siba_detach),
736         DEVMETHOD(device_resume,                siba_resume),
737         DEVMETHOD(device_suspend,               siba_suspend),
738         
739         /* Bus interface */
740         DEVMETHOD(bus_read_ivar,                siba_read_ivar),
741         DEVMETHOD(bus_write_ivar,               siba_write_ivar),
742         DEVMETHOD(bus_get_resource_list,        siba_get_resource_list),
743
744         /* BHND interface */
745         DEVMETHOD(bhnd_bus_find_hostb_device,   siba_find_hostb_device),
746         DEVMETHOD(bhnd_bus_get_core_table,      siba_get_core_table),
747         DEVMETHOD(bhnd_bus_alloc_devinfo,       siba_alloc_bhnd_dinfo),
748         DEVMETHOD(bhnd_bus_free_devinfo,        siba_free_bhnd_dinfo),
749         DEVMETHOD(bhnd_bus_reset_core,          siba_reset_core),
750         DEVMETHOD(bhnd_bus_suspend_core,        siba_suspend_core),
751         DEVMETHOD(bhnd_bus_read_config,         siba_read_config),
752         DEVMETHOD(bhnd_bus_write_config,        siba_write_config),
753         DEVMETHOD(bhnd_bus_get_port_count,      siba_get_port_count),
754         DEVMETHOD(bhnd_bus_get_region_count,    siba_get_region_count),
755         DEVMETHOD(bhnd_bus_get_port_rid,        siba_get_port_rid),
756         DEVMETHOD(bhnd_bus_decode_port_rid,     siba_decode_port_rid),
757         DEVMETHOD(bhnd_bus_get_region_addr,     siba_get_region_addr),
758
759         DEVMETHOD_END
760 };
761
762 DEFINE_CLASS_1(bhnd, siba_driver, siba_methods, sizeof(struct siba_softc), bhnd_driver);
763
764 MODULE_VERSION(siba, 1);
765 MODULE_DEPEND(siba, bhnd, 1, 1, 1);