Index: sys/dev/bhnd/bhndb/bhndb.h =================================================================== --- sys/dev/bhnd/bhndb/bhndb.h +++ sys/dev/bhnd/bhndb/bhndb.h @@ -46,6 +46,7 @@ extern devclass_t bhndb_devclass; int bhndb_attach_bridge(device_t parent, device_t *bhndb, int unit); +int bhndb_attach_by_class(device_t parent, device_t *child, int unit, devclass_t child_devclass); /** * bhndb register window types. @@ -54,6 +55,7 @@ BHNDB_REGWIN_T_CORE, /**< Fixed mapping of a core port region. */ BHNDB_REGWIN_T_SPROM, /**< Fixed mapping of device SPROM */ BHNDB_REGWIN_T_DYN, /**< A dynamically configurable window */ + BHNDB_REGWIN_T_FIXED, /**< Memory mapped direct window */ BHNDB_REGWIN_T_INVALID /**< Invalid type */ } bhndb_regwin_type_t; @@ -64,7 +66,8 @@ */ #define BHNDB_REGWIN_T_IS_STATIC(_rt) \ ((_rt) == BHNDB_REGWIN_T_CORE || \ - (_rt) == BHNDB_REGWIN_T_SPROM) + (_rt) == BHNDB_REGWIN_T_SPROM || \ + (_rt) == BHNDB_REGWIN_T_FIXED) /** * bhndb register window definition. @@ -80,8 +83,8 @@ int rid; /**< resource id */ } res; - - union { + /** changed from unnamed to named to meet C99 */ + union specific { /** Core-specific register window (BHNDB_REGWIN_T_CORE). */ struct { bhnd_devclass_t class; /**< mapped core's class */ @@ -91,6 +94,9 @@ u_int region; /**< mapped region number */ } core; + /** Fixed memory mapped bus windows */ + struct{} direct; + /** SPROM register window (BHNDB_REGWIN_T_SPROM). */ struct {} sprom; @@ -98,7 +104,7 @@ struct { bus_size_t cfg_offset; /**< window address config offset. */ } dyn; - }; + } win_spec; }; #define BHNDB_REGWIN_TABLE_END { BHNDB_REGWIN_T_INVALID, 0, 0, { 0, 0 } } @@ -110,6 +116,7 @@ * via which those mappings may be accessed. */ struct bhndb_hwcfg { + bool is_hostb_required; const struct resource_spec *resource_specs; const struct bhndb_regwin *register_windows; }; @@ -170,4 +177,4 @@ #define BHNDB_HW_PRIORITY_TABLE_END { {}, BHNDB_PRIORITY_NONE, NULL, 0 } -#endif /* _BHND_BHNDB_H_ */ \ No newline at end of file +#endif /* _BHND_BHNDB_H_ */ Index: sys/dev/bhnd/bhndb/bhndb.c =================================================================== --- sys/dev/bhnd/bhndb/bhndb.c +++ sys/dev/bhnd/bhndb/bhndb.c @@ -257,8 +257,8 @@ /* Fetch the base address of the mapped port. */ error = bhnd_get_region_addr(child, - regw->core.port_type, regw->core.port, - regw->core.region, &addr, &size); + regw->win_spec.core.port_type, regw->win_spec.core.port, + regw->win_spec.core.region, &addr, &size); if (error) return (error); @@ -614,9 +614,12 @@ } if (hostb == NULL) { - device_printf(sc->dev, "no host bridge core found\n"); - error = ENODEV; - goto cleanup; + if(sc->bus_res->cfg->is_hostb_required){ + device_printf(sc->dev, "no host bridge core found\n"); + error = ENODEV; + goto cleanup; + } + device_printf(sc->dev, "WARNING: no host bridge core found\n"); } /* Find our full register window configuration */ @@ -1080,8 +1083,8 @@ if (error) { device_printf(dev, "failed to activate entry %#x type %d for " - "child %s\n", - *rid, type, device_get_nameunit(child)); + "child %s: %d\n", + *rid, type, device_get_nameunit(child), error); rman_release_resource(rv); @@ -1342,17 +1345,37 @@ /* Look for a bus region matching the resource's address range */ r_start = rman_get_start(r); r_size = rman_get_size(r); + + if(bootverbose){ + device_printf(sc->dev, "%s: trying to activate %p (%ld) : rid=%d for %s\n", + __func__, + (void *)(uintptr_t)r_start, r_size, rid, device_get_nameunit(child)); + + bhndb_print_resources(sc->bus_res); + } + region = bhndb_find_resource_region(sc->bus_res, r_start, r_size); if (region != NULL) dw_priority = region->priority; + if(bootverbose){ + if(region == NULL){ + device_printf(sc->dev, "%s: no region found\n", __func__); + }else{ + device_printf(sc->dev, "%s: found %s region %p (%lld)\n", __func__ , + ((region->static_regwin) ? "static" : "dynamic"), + (void *)(uintptr_t)region->addr, region->size); + } + } + /* Prefer static mappings over consuming a dynamic windows. */ if (region && region->static_regwin) { error = bhndb_activate_static_region(sc, region, child, type, rid, r); if (error) - device_printf(sc->dev, "static window allocation " + device_printf(sc->dev, "%s: static window allocation " "for 0x%llx-0x%llx failed\n", + __func__, (unsigned long long) r_start, (unsigned long long) r_start + r_size - 1); return (error); @@ -1361,18 +1384,25 @@ /* A dynamic window will be required; is this resource high enough * priority to be reserved a dynamic window? */ if (dw_priority < sc->bus_res->min_prio) { + device_printf(sc->dev, "%s: priority %d is lower than min priority %d\n", + __func__, dw_priority, sc->bus_res->min_prio); if (indirect) *indirect = true; return (ENOMEM); } + if(bootverbose){ + device_printf(sc->dev, "%s: trying to find and retain window...\n", __func__); + } + /* Find and retain a usable window */ BHNDB_LOCK(sc); { dwa = bhndb_retain_dynamic_window(sc, r); } BHNDB_UNLOCK(sc); if (dwa == NULL) { + device_printf(sc->dev, "%s: no window is found...\n", __func__); if (indirect) *indirect = true; return (ENOMEM); @@ -1382,6 +1412,10 @@ parent_offset = dwa->win->win_offset; parent_offset += r_start - dwa->target; + if(bootverbose){ + device_printf(sc->dev, "%s: parent_offset=%p\n", __func__ , (void*)(uintptr_t)parent_offset); + } + error = bhndb_init_child_resource(r, dwa->parent_res, parent_offset, dwa->win->win_size); if (error) @@ -1922,7 +1956,7 @@ DEVMETHOD(bhnd_bus_alloc_resource, bhndb_alloc_bhnd_resource), DEVMETHOD(bhnd_bus_release_resource, bhndb_release_bhnd_resource), DEVMETHOD(bhnd_bus_activate_resource, bhndb_activate_bhnd_resource), - DEVMETHOD(bhnd_bus_activate_resource, bhndb_deactivate_bhnd_resource), + DEVMETHOD(bhnd_bus_deactivate_resource, bhndb_deactivate_bhnd_resource), DEVMETHOD(bhnd_bus_read_1, bhndb_bus_read_1), DEVMETHOD(bhnd_bus_read_2, bhndb_bus_read_2), DEVMETHOD(bhnd_bus_read_4, bhndb_bus_read_4), Index: sys/dev/bhnd/bhndb/bhndb_pci.c =================================================================== --- sys/dev/bhnd/bhndb/bhndb_pci.c +++ sys/dev/bhnd/bhndb/bhndb_pci.c @@ -775,7 +775,7 @@ if ((error = bhndb_pci_fast_setregwin(sc, rw, addr))) return (error); - if (pci_read_config(parent, rw->dyn.cfg_offset, 4) == addr) + if (pci_read_config(parent, rw->win_spec.dyn.cfg_offset, 4) == addr) return (0); DELAY(10); @@ -805,7 +805,7 @@ if (addr % rw->win_size != 0) return (EINVAL); - pci_write_config(parent, rw->dyn.cfg_offset, addr, 4); + pci_write_config(parent, rw->win_spec.dyn.cfg_offset, addr, 4); break; default: return (ENODEV); Index: sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c =================================================================== --- sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c +++ sys/dev/bhnd/bhndb/bhndb_pci_hwdata.c @@ -82,6 +82,7 @@ * at the default enumeration address (0x18000000). */ const struct bhndb_hwcfg bhndb_pci_siba_generic_hwcfg = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -93,7 +94,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, BHNDB_REGWIN_TABLE_END @@ -111,6 +112,7 @@ * - Compatible with both siba(4) and bcma(4) bus enumeration. */ const struct bhndb_hwcfg bhndb_pci_bcma_generic_hwcfg = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -122,7 +124,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -131,7 +133,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -316,6 +318,7 @@ * - PCI (cid=0x804, revision <= 12) */ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v0 = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -327,7 +330,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V0_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V0_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V0_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V0_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -344,7 +347,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V0_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V0_BAR0_PCIREG_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_PCI, .unit = 0, .port = 0, @@ -364,6 +367,7 @@ * - PCI (cid=0x804, revision >= 13) */ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pci = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -375,7 +379,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -392,7 +396,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_PCIREG_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_PCI, .unit = 0, .port = 0, @@ -407,7 +411,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -428,6 +432,7 @@ * - PCIE (cid=0x820) with ChipCommon (revision <= 31) */ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v1_pcie = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -439,7 +444,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V1_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V1_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -456,7 +461,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_PCIREG_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -471,7 +476,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V1_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V1_BAR0_CCREGS_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -492,6 +497,7 @@ * - PCIE (cid=0x820) with ChipCommon (revision >= 32) */ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v2 = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -503,7 +509,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V2_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -512,7 +518,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V2_BAR0_WIN1_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_WIN1_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN1_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V2_BAR0_WIN1_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -521,7 +527,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V2_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_PCIREG_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -536,7 +542,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V2_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V2_BAR0_CCREGS_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, @@ -557,6 +563,7 @@ * - PCIE2 (cid=0x83c) */ static const struct bhndb_hwcfg bhndb_pci_hwcfg_v3 = { + .is_hostb_required = true, .resource_specs = (const struct resource_spec[]) { { SYS_RES_MEMORY, PCIR_BAR(0), RF_ACTIVE }, { -1, 0, 0 } @@ -568,7 +575,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V3_BAR0_WIN0_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_WIN0_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN0_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN0_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -577,7 +584,7 @@ .win_type = BHNDB_REGWIN_T_DYN, .win_offset = BHNDB_PCI_V3_BAR0_WIN1_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_WIN1_SIZE, - .dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN1_CONTROL, + .win_spec.dyn.cfg_offset = BHNDB_PCI_V3_BAR0_WIN1_CONTROL, .res = { SYS_RES_MEMORY, PCIR_BAR(0) } }, @@ -586,7 +593,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V3_BAR0_PCIREG_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_PCIREG_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_PCIE, .unit = 0, .port = 0, @@ -601,7 +608,7 @@ .win_type = BHNDB_REGWIN_T_CORE, .win_offset = BHNDB_PCI_V3_BAR0_CCREGS_OFFSET, .win_size = BHNDB_PCI_V3_BAR0_CCREGS_SIZE, - .core = { + .win_spec.core = { .class = BHND_DEVCLASS_CC, .unit = 0, .port = 0, Index: sys/dev/bhnd/bhndb/bhndb_private.h =================================================================== --- sys/dev/bhnd/bhndb/bhndb_private.h +++ sys/dev/bhnd/bhndb/bhndb_private.h @@ -124,6 +124,8 @@ const struct bhndb_hw_priority *table, device_t device); +void bhndb_print_resources(struct bhndb_resources* res); +char* bhndb_print_class(bhnd_devclass_t class); /** * Dynamic register window allocation reference. @@ -189,6 +191,37 @@ return (br->dwa_freelist == 0); } +#define CTZ32_BSEARCH(x, n, MASK, SHIFT) if( (x & MASK) == 0){ x<<= SHIFT; n+= SHIFT; } +static inline int bhndb_ctz32(u_int32_t y){ + int n = 0; + if(y == 0) return 32; + + int x = y; + + CTZ32_BSEARCH(x, n, 0x0000FFFF, 16); + CTZ32_BSEARCH(x, n, 0x000000FF, 8); + CTZ32_BSEARCH(x, n, 0x0000000F, 4); + CTZ32_BSEARCH(x, n, 0x00000003, 2); + CTZ32_BSEARCH(x, n, 0x00000001, 1); + + return n; +} + +static inline int bhndb_popcount(u_int32_t y) +{ + u_int32_t x = y; + x = x - ((x >> 1) & 0x55555555); + /* Every 2 bits holds the sum of every pair of bits */ + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); // 0011001100110011 + /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) */ + x = (x + (x >> 4)) & 0x0F0F0F0F; + /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) */ + x = (x + (x >> 16)); + /* The lower 16 bits hold two 8 bit sums (5 significant bits).*/ + /* Upper 16 bits are garbage */ + return (x + (x >> 8)) & 0x0000003F; /* (6 significant bits) */ +} + /** * Find the next free dynamic window region in @p br. * @@ -202,7 +235,7 @@ if (bhndb_dw_exhausted(br)) return (NULL); - dw_free = &br->dw_alloc[__builtin_ctz(br->dwa_freelist)]; + dw_free = &br->dw_alloc[bhndb_ctz32(br->dwa_freelist)]; KASSERT(LIST_EMPTY(&dw_free->refs), ("free list out of sync with refs")); Index: sys/dev/bhnd/bhndb/bhndb_subr.c =================================================================== --- sys/dev/bhnd/bhndb/bhndb_subr.c +++ sys/dev/bhnd/bhndb/bhndb_subr.c @@ -33,39 +33,49 @@ #include #include +#include #include "bhndb_private.h" #include "bhndbvar.h" + +int +bhndb_attach_by_class(device_t parent, device_t *child, int unit, devclass_t child_devclass) +{ + int error; + + *child = device_add_child(parent, devclass_get_name(child_devclass), + unit); + if (*child == NULL) + return (ENXIO); + + if (!(error = device_probe_and_attach(*child))) + return (0); + + if ((device_delete_child(parent, *child))) + device_printf(parent, "failed to detach bhndb child\n"); + + return (error); + +} + /** * Attach a BHND bridge device to @p parent. - * + * * @param parent A parent PCI device. * @param[out] bhndb On success, the probed and attached bhndb bridge device. * @param unit The device unit number, or -1 to select the next available unit * number. - * + * * @retval 0 success * @retval non-zero Failed to attach the bhndb device. */ int bhndb_attach_bridge(device_t parent, device_t *bhndb, int unit) { - int error; - - *bhndb = device_add_child(parent, devclass_get_name(bhndb_devclass), - unit); - if (*bhndb == NULL) - return (ENXIO); - - if (!(error = device_probe_and_attach(*bhndb))) - return (0); - - if ((device_delete_child(parent, *bhndb))) - device_printf(parent, "failed to detach bhndb child\n"); - - return (error); + return bhndb_attach_by_class(parent, bhndb, unit, bhndb_devclass); } + /* * Call BHNDB_SUSPEND_RESOURCE() for all resources in @p rl. */ @@ -88,15 +98,15 @@ /** * Helper function for implementing BUS_RESUME_CHILD() on bridged * bhnd(4) buses. - * + * * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() * to find the child's resources and call BHNDB_SUSPEND_RESOURCE() for all * child resources, ensuring that the device's allocated bridge resources * will be available to other devices during bus resumption. - * - * Before suspending any resources, @p child is suspended by + * + * Before suspending any resources, @p child is suspended by * calling bhnd_generic_suspend_child(). - * + * * If @p child is not a direct child of @p dev, suspension is delegated to * the @p dev parent. */ @@ -130,13 +140,13 @@ /** * Helper function for implementing BUS_RESUME_CHILD() on bridged * bhnd(4) bus devices. - * + * * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() * to find the child's resources and call BHNDB_RESUME_RESOURCE() for all * child resources, before delegating to bhnd_generic_resume_child(). - * + * * If resource resumption fails, @p child will not be resumed. - * + * * If @p child is not a direct child of @p dev, suspension is delegated to * the @p dev parent. */ @@ -146,7 +156,7 @@ struct resource_list *rl; struct resource_list_entry *rle; int error; - + if (device_get_parent(child) != dev) BUS_RESUME_CHILD(device_get_parent(dev), child); @@ -184,10 +194,10 @@ /** * Find the resource containing @p win. - * + * * @param br The bhndb resource state to search. * @param win A register window. - * + * * @retval resource the resource containing @p win. * @retval NULL if no resource containing @p win can be found. */ @@ -198,7 +208,7 @@ const struct resource_spec *rspecs; rspecs = br->cfg->resource_specs; - for (u_int i = 0; rspecs[i].type != -1; i++) { + for (u_int i = 0; rspecs[i].type != -1; i++) { if (win->res.type != rspecs[i].type) continue; @@ -219,7 +229,7 @@ /** * Allocate and initialize a new resource state structure, allocating * bus resources from @p parent_dev according to @p cfg. - * + * * @param dev The bridge device. * @param parent_dev The parent device from which resources will be allocated. * @param cfg The hardware configuration to be used. @@ -248,7 +258,7 @@ r->cfg = cfg; r->min_prio = BHNDB_PRIORITY_NONE; STAILQ_INIT(&r->bus_regions); - + /* Determine our bridge resource count from the hardware config. */ res_num = 0; for (size_t i = 0; cfg->resource_specs[i].type != -1; i++) @@ -265,7 +275,7 @@ /* Initialize and terminate the table */ for (size_t i = 0; i < res_num; i++) r->res_spec[i] = cfg->resource_specs[i]; - + r->res_spec[res_num].type = -1; /* Allocate space for our resource references */ @@ -292,7 +302,7 @@ device_printf(r->dev, "max dynamic regwin count exceeded\n"); goto failed; } - + /* Allocate the dynamic window allocation table. */ r->dw_alloc = malloc(sizeof(r->dw_alloc[0]) * r->dwa_count, M_BHND, M_NOWAIT); @@ -308,9 +318,18 @@ { struct bhndb_dw_alloc *dwa; - /* Skip non-DYN windows */ - if (win->win_type != BHNDB_REGWIN_T_DYN) + /* Skip non-DYN windows and process FIXED windows */ + if (win->win_type != BHNDB_REGWIN_T_DYN){ + if(win->win_type != BHNDB_REGWIN_T_FIXED) + continue; + + int error = bhndb_add_resource_region(r, + win->win_offset,win->win_size, BHNDB_PRIORITY_DEFAULT, win); + if(error) + goto failed; + continue; + } /* Validate the window size */ if (win->win_size == 0) { @@ -320,13 +339,13 @@ } else if (last_window_size == 0) { last_window_size = win->win_size; } else if (last_window_size != win->win_size) { - /* + /* * No existing hardware should trigger this. - * + * * If you run into this in the future, the dynamic * window allocator and the resource priority system * will need to be extended to support multiple register - * window allocation pools. + * window allocation pools. */ device_printf(r->dev, "devices that vend multiple " "dynamic register window sizes are not currently " @@ -339,7 +358,7 @@ dwa->parent_res = NULL; dwa->rnid = rnid; dwa->target = 0x0; - + LIST_INIT(&dwa->refs); /* Find and validate corresponding resource. */ @@ -388,7 +407,7 @@ /** * Deallocate the given bridge resource structure and any associated resources. - * + * * @param br Resource state to be deallocated. */ void @@ -399,7 +418,7 @@ struct bhndb_dw_rentry *dwr, *dwr_next; /* No window regions may still be held */ - if (__builtin_popcount(br->dwa_freelist) != br->dwa_count) { + if (bhndb_popcount(br->dwa_freelist) != br->dwa_count) { device_printf(br->dev, "leaked %llu dynamic register regions\n", (unsigned long long) br->dwa_count - br->dwa_freelist); } @@ -416,7 +435,7 @@ free(dwr, M_BHND); } } - + /* Release bus regions */ STAILQ_FOREACH_SAFE(region, &br->bus_regions, link, r_next) { STAILQ_REMOVE(&br->bus_regions, region, bhndb_region, link); @@ -431,7 +450,7 @@ /** * Add a bus region entry to @p r for the given base @p addr and @p size. - * + * * @param br The resource state to which the bus region entry will be added. * @param addr The base address of this region. * @param size The size of this region. @@ -439,7 +458,7 @@ * made within this bus region. * @param static_regwin If available, a static register window mapping this * bus region entry. If not available, NULL. - * + * * @retval 0 success * @retval non-zero if adding the bus region fails. */ @@ -469,11 +488,11 @@ /** * Find a bus region that maps @p size bytes at @p addr. - * + * * @param br The resource state to search. * @param addr The requested starting address. * @param size The requested size. - * + * * @retval bhndb_region A region that fully contains the requested range. * @retval NULL If no mapping region can be found. */ @@ -500,7 +519,7 @@ /** * Find the entry matching @p r in @p dwa's references, if any. - * + * * @param dwa The dynamic window allocation to search * @param r The resource to search for in @p dwa. */ @@ -530,10 +549,10 @@ /** * Find the dynamic region allocated for @p r, if any. - * + * * @param br The resource state to search. * @param r The resource to search for. - * + * * @retval bhndb_dw_alloc The allocation record for @p r. * @retval NULL if no dynamic window is allocated for @p r. */ @@ -560,11 +579,11 @@ /** * Find an existing dynamic window mapping @p size bytes * at @p addr. The window may or may not be free. - * + * * @param br The resource state to search. * @param addr The requested starting address. * @param size The requested size. - * + * * @retval bhndb_dw_alloc A window allocation that fully contains the requested * range. * @retval NULL If no mapping region can be found. @@ -598,11 +617,11 @@ /** * Retain a reference to @p dwa for use by @p res. - * + * * @param br The resource state owning @p dwa. * @param dwa The allocation record to be retained. * @param res The resource that will own a reference to @p dwa. - * + * * @retval 0 success * @retval ENOMEM Failed to allocate a new reference structure. */ @@ -626,7 +645,7 @@ /* Update the free list */ br->dwa_freelist &= ~(1 << (dwa->rnid)); - + return (0); } @@ -634,7 +653,7 @@ * Release a reference to @p dwa previously retained by @p res. If the * reference count of @p dwa reaches zero, it will be added to the * free list. - * + * * @param br The resource state owning @p dwa. * @param dwa The allocation record to be released. * @param res The resource that currently owns a reference to @p dwa. @@ -660,11 +679,11 @@ /** * Attempt to set (or reset) the target address of @p dwa to map @p size bytes * at @p addr. - * + * * This will apply any necessary window alignment and verify that * the window is capable of mapping the requested range prior to modifying * therecord. - * + * * @param dev The device on which to issue the BHNDB_SET_WINDOW_ADDR() request. * @param br The resource state owning @p dwa. * @param dwa The allocation record to be configured. @@ -694,7 +713,7 @@ /* Verify that the window is large enough for the full target */ if (rw->win_size - offset < size) return (ENOMEM); - + /* Update the window target */ error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target); if (error) { @@ -707,7 +726,7 @@ /** * Return the count of @p type register windows in @p table. - * + * * @param table The table to search. * @param type The required window type, or BHNDB_REGWIN_T_INVALID to * count all register window types. @@ -730,13 +749,13 @@ /** * Search @p table for the first window with the given @p type. - * + * * @param table The table to search. * @param type The required window type. * @param min_size The minimum window size. - * + * * @retval bhndb_regwin The first matching window. - * @retval NULL If no window of the requested type could be found. + * @retval NULL If no window of the requested type could be found. */ const struct bhndb_regwin * bhndb_regwin_find_type(const struct bhndb_regwin *table, @@ -755,7 +774,7 @@ /** * Search @p windows for the first matching core window. - * + * * @param table The table to search. * @param class The required core class. * @param unit The required core unit, or -1. @@ -764,32 +783,32 @@ * @param region The required region. * * @retval bhndb_regwin The first matching window. - * @retval NULL If no matching window was found. + * @retval NULL If no matching window was found. */ const struct bhndb_regwin * bhndb_regwin_find_core(const struct bhndb_regwin *table, bhnd_devclass_t class, int unit, bhnd_port_type port_type, u_int port, u_int region) { const struct bhndb_regwin *rw; - + for (rw = table; rw->win_type != BHNDB_REGWIN_T_INVALID; rw++) { if (rw->win_type != BHNDB_REGWIN_T_CORE) continue; - if (rw->core.class != class) + if (rw->win_spec.core.class != class) continue; - - if (unit != -1 && rw->core.unit != unit) + + if (unit != -1 && rw->win_spec.core.unit != unit) continue; - if (rw->core.port_type != port_type) + if (rw->win_spec.core.port_type != port_type) continue; - if (rw->core.port != port) + if (rw->win_spec.core.port != port) continue; - - if (rw->core.region != region) + + if (rw->win_spec.core.region != region) continue; return (rw); @@ -800,11 +819,11 @@ /** * Search @p windows for the best available window of at least @p min_size. - * + * * Search order: * - BHND_REGWIN_T_CORE * - BHND_REGWIN_T_DYN - * + * * @param table The table to search. * @param class The required core class. * @param unit The required core unit, or -1. @@ -814,7 +833,7 @@ * @param min_size The minimum window size. * * @retval bhndb_regwin The first matching window. - * @retval NULL If no matching window was found. + * @retval NULL If no matching window was found. */ const struct bhndb_regwin * bhndb_regwin_find_best(const struct bhndb_regwin *table, @@ -836,7 +855,7 @@ /** * Return true if @p regw defines a static port register window, and * the mapped port is actually defined on @p dev. - * + * * @param regw A register window to match against. * @param dev A bhnd(4) bus device. */ @@ -848,16 +867,16 @@ return (false); /* Device class must match */ - if (bhnd_get_class(dev) != regw->core.class) + if (bhnd_get_class(dev) != regw->win_spec.core.class) return (false); /* Device unit must match */ - if (bhnd_get_core_unit(dev) != regw->core.unit) + if (bhnd_get_core_unit(dev) != regw->win_spec.core.unit) return (false); - + /* The regwin port/region must be defined. */ - if (!bhnd_is_region_valid(dev, regw->core.port_type, regw->core.port, - regw->core.region)) + if (!bhnd_is_region_valid(dev, regw->win_spec.core.port_type, regw->win_spec.core.port, + regw->win_spec.core.region)) { return (false); } @@ -869,7 +888,7 @@ /** * Search for a core resource priority descriptor in @p table that matches * @p device. - * + * * @param table The table to search. * @param device A bhnd(4) bus device. */ @@ -887,3 +906,88 @@ /* not found */ return (NULL); } + + +char* bhndb_print_class(bhnd_devclass_t class){ + switch (class) { + case BHND_DEVCLASS_CC: + return "ChipCommon IO controller"; + case BHND_DEVCLASS_CC_B: + return "ChipCommon Auxiliary controller"; + case BHND_DEVCLASS_PMU: + return "PMU Controller"; + case BHND_DEVCLASS_PCI: + return "PCI host/device bridge"; + case BHND_DEVCLASS_PCIE: + return "pcie host/device bridge"; + case BHND_DEVCLASS_PCCARD: + return "pcmcia host/device bridge"; + case BHND_DEVCLASS_RAM: + return "internal RAM/SRAM"; + case BHND_DEVCLASS_MEMC: + return "memory controller"; + case BHND_DEVCLASS_ENET: + return "802.3 MAC/PHY"; + case BHND_DEVCLASS_ENET_MAC: + return "802.3 MAC "; + case BHND_DEVCLASS_ENET_PHY: + return "802.3 PHY "; + case BHND_DEVCLASS_WLAN: + return "802.11 MAC/PHY/Radio "; + case BHND_DEVCLASS_WLAN_MAC: + return "802.11 MAC "; + case BHND_DEVCLASS_WLAN_PHY: + return "802.11 PHY "; + case BHND_DEVCLASS_CPU: + return "cpu core "; + case BHND_DEVCLASS_SOC_ROUTER: + return "interconnect router "; + case BHND_DEVCLASS_SOC_BRIDGE: + return "interconnect host bridge "; + case BHND_DEVCLASS_EROM: + return "bus device enumeration ROM "; + case BHND_DEVCLASS_NVRAM: + return "nvram/flash controller "; + case BHND_DEVCLASS_OTHER: + return "other / unknown "; + default: + return "invalid"; + } +} + +void bhndb_print_resources(struct bhndb_resources* res){ + + device_t dev = res->dev; + device_t parent = res->parent_dev; + const struct bhndb_hwcfg* cfg = res->cfg; + + printf("============ DUMP bridge resources ===========\n"); + printf(" owner %s / parent %s =\n", device_get_nameunit(dev), device_get_nameunit(parent)); + printf("--------------- Configurations ---------------\n"); + const struct resource_spec* res_spec = cfg->resource_specs; + while(res_spec->type >= 0 ){ + printf(" -> %d (type %d)\n", res_spec->rid, res_spec->type); + res_spec++; + } + + const struct bhndb_regwin* rw = cfg->register_windows; + while(rw->win_type != BHNDB_REGWIN_T_INVALID){ + printf(" -> [%p-%p]", (void*)rw->win_offset, (void*)(rw->win_offset + rw->win_size)); + if(rw->win_type == BHNDB_REGWIN_T_CORE){ + printf("(core %s port %d)", bhndb_print_class(rw->win_spec.core.class), rw->win_spec.core.port); + } + printf("\n"); + rw++; + } + + //TODO: print cfg and other fields + + printf("--------------- Bus regions ------------------\n"); + struct bhndb_region *region; + STAILQ_FOREACH(region, &res->bus_regions, link){ + printf(" * %p-%p (%s prio=%d)\n", + (void*)(uintptr_t)region->addr, (void*)(uintptr_t)(region->addr+region->size-1), + ((region->static_regwin) ? "static" : ""), region->priority); + } + printf("==============================================\n"); +}