Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/bhnd/bhndb/bhndb_subr.c
| Context not available. | |||||
| #include <sys/param.h> | #include <sys/param.h> | ||||
| #include <sys/kernel.h> | #include <sys/kernel.h> | ||||
| #include <dev/bhnd/bhnd_types.h> | |||||
| #include "bhndb_private.h" | #include "bhndb_private.h" | ||||
| #include "bhndbvar.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. | * Attach a BHND bridge device to @p parent. | ||||
| * | * | ||||
| * @param parent A parent PCI device. | * @param parent A parent PCI device. | ||||
| * @param[out] bhndb On success, the probed and attached bhndb bridge 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 | * @param unit The device unit number, or -1 to select the next available unit | ||||
| * number. | * number. | ||||
| * | * | ||||
| * @retval 0 success | * @retval 0 success | ||||
| * @retval non-zero Failed to attach the bhndb device. | * @retval non-zero Failed to attach the bhndb device. | ||||
| */ | */ | ||||
| int | int | ||||
| bhndb_attach_bridge(device_t parent, device_t *bhndb, int unit) | bhndb_attach_bridge(device_t parent, device_t *bhndb, int unit) | ||||
| { | { | ||||
| int error; | return bhndb_attach_by_class(parent, bhndb, unit, bhndb_devclass); | ||||
| *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); | |||||
| } | } | ||||
| /* | /* | ||||
| * Call BHNDB_SUSPEND_RESOURCE() for all resources in @p rl. | * Call BHNDB_SUSPEND_RESOURCE() for all resources in @p rl. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Helper function for implementing BUS_RESUME_CHILD() on bridged | * Helper function for implementing BUS_RESUME_CHILD() on bridged | ||||
| * bhnd(4) buses. | * bhnd(4) buses. | ||||
| * | * | ||||
| * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() | * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() | ||||
| * to find the child's resources and call BHNDB_SUSPEND_RESOURCE() for all | * to find the child's resources and call BHNDB_SUSPEND_RESOURCE() for all | ||||
| * child resources, ensuring that the device's allocated bridge resources | * child resources, ensuring that the device's allocated bridge resources | ||||
| * will be available to other devices during bus resumption. | * 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(). | * calling bhnd_generic_suspend_child(). | ||||
| * | * | ||||
| * If @p child is not a direct child of @p dev, suspension is delegated to | * If @p child is not a direct child of @p dev, suspension is delegated to | ||||
| * the @p dev parent. | * the @p dev parent. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Helper function for implementing BUS_RESUME_CHILD() on bridged | * Helper function for implementing BUS_RESUME_CHILD() on bridged | ||||
| * bhnd(4) bus devices. | * bhnd(4) bus devices. | ||||
| * | * | ||||
| * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() | * This implementation of BUS_RESUME_CHILD() uses BUS_GET_RESOURCE_LIST() | ||||
| * to find the child's resources and call BHNDB_RESUME_RESOURCE() for all | * to find the child's resources and call BHNDB_RESUME_RESOURCE() for all | ||||
| * child resources, before delegating to bhnd_generic_resume_child(). | * child resources, before delegating to bhnd_generic_resume_child(). | ||||
| * | * | ||||
| * If resource resumption fails, @p child will not be resumed. | * 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 | * If @p child is not a direct child of @p dev, suspension is delegated to | ||||
| * the @p dev parent. | * the @p dev parent. | ||||
| */ | */ | ||||
| Context not available. | |||||
| struct resource_list *rl; | struct resource_list *rl; | ||||
| struct resource_list_entry *rle; | struct resource_list_entry *rle; | ||||
| int error; | int error; | ||||
| if (device_get_parent(child) != dev) | if (device_get_parent(child) != dev) | ||||
| BUS_RESUME_CHILD(device_get_parent(dev), child); | BUS_RESUME_CHILD(device_get_parent(dev), child); | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Find the resource containing @p win. | * Find the resource containing @p win. | ||||
| * | * | ||||
| * @param br The bhndb resource state to search. | * @param br The bhndb resource state to search. | ||||
| * @param win A register window. | * @param win A register window. | ||||
| * | * | ||||
| * @retval resource the resource containing @p win. | * @retval resource the resource containing @p win. | ||||
| * @retval NULL if no resource containing @p win can be found. | * @retval NULL if no resource containing @p win can be found. | ||||
| */ | */ | ||||
| Context not available. | |||||
| const struct resource_spec *rspecs; | const struct resource_spec *rspecs; | ||||
| rspecs = br->cfg->resource_specs; | 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) | if (win->res.type != rspecs[i].type) | ||||
| continue; | continue; | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Allocate and initialize a new resource state structure, allocating | * Allocate and initialize a new resource state structure, allocating | ||||
| * bus resources from @p parent_dev according to @p cfg. | * bus resources from @p parent_dev according to @p cfg. | ||||
| * | * | ||||
| * @param dev The bridge device. | * @param dev The bridge device. | ||||
| * @param parent_dev The parent device from which resources will be allocated. | * @param parent_dev The parent device from which resources will be allocated. | ||||
| * @param cfg The hardware configuration to be used. | * @param cfg The hardware configuration to be used. | ||||
| Context not available. | |||||
| r->cfg = cfg; | r->cfg = cfg; | ||||
| r->min_prio = BHNDB_PRIORITY_NONE; | r->min_prio = BHNDB_PRIORITY_NONE; | ||||
| STAILQ_INIT(&r->bus_regions); | STAILQ_INIT(&r->bus_regions); | ||||
| /* Determine our bridge resource count from the hardware config. */ | /* Determine our bridge resource count from the hardware config. */ | ||||
| res_num = 0; | res_num = 0; | ||||
| for (size_t i = 0; cfg->resource_specs[i].type != -1; i++) | for (size_t i = 0; cfg->resource_specs[i].type != -1; i++) | ||||
| Context not available. | |||||
| /* Initialize and terminate the table */ | /* Initialize and terminate the table */ | ||||
| for (size_t i = 0; i < res_num; i++) | for (size_t i = 0; i < res_num; i++) | ||||
| r->res_spec[i] = cfg->resource_specs[i]; | r->res_spec[i] = cfg->resource_specs[i]; | ||||
| r->res_spec[res_num].type = -1; | r->res_spec[res_num].type = -1; | ||||
| /* Allocate space for our resource references */ | /* Allocate space for our resource references */ | ||||
| Context not available. | |||||
| device_printf(r->dev, "max dynamic regwin count exceeded\n"); | device_printf(r->dev, "max dynamic regwin count exceeded\n"); | ||||
| goto failed; | goto failed; | ||||
| } | } | ||||
| /* Allocate the dynamic window allocation table. */ | /* Allocate the dynamic window allocation table. */ | ||||
| r->dw_alloc = malloc(sizeof(r->dw_alloc[0]) * r->dwa_count, M_BHND, | r->dw_alloc = malloc(sizeof(r->dw_alloc[0]) * r->dwa_count, M_BHND, | ||||
| M_NOWAIT); | M_NOWAIT); | ||||
| Context not available. | |||||
| { | { | ||||
| struct bhndb_dw_alloc *dwa; | struct bhndb_dw_alloc *dwa; | ||||
| /* Skip non-DYN windows */ | /* Skip non-DYN windows and process FIXED windows */ | ||||
| if (win->win_type != BHNDB_REGWIN_T_DYN) | 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; | continue; | ||||
| } | |||||
| /* Validate the window size */ | /* Validate the window size */ | ||||
| if (win->win_size == 0) { | if (win->win_size == 0) { | ||||
| Context not available. | |||||
| } else if (last_window_size == 0) { | } else if (last_window_size == 0) { | ||||
| last_window_size = win->win_size; | last_window_size = win->win_size; | ||||
| } else if (last_window_size != win->win_size) { | } else if (last_window_size != win->win_size) { | ||||
| /* | /* | ||||
| * No existing hardware should trigger this. | * No existing hardware should trigger this. | ||||
| * | * | ||||
| * If you run into this in the future, the dynamic | * If you run into this in the future, the dynamic | ||||
| * window allocator and the resource priority system | * window allocator and the resource priority system | ||||
| * will need to be extended to support multiple register | * will need to be extended to support multiple register | ||||
| * window allocation pools. | * window allocation pools. | ||||
| */ | */ | ||||
| device_printf(r->dev, "devices that vend multiple " | device_printf(r->dev, "devices that vend multiple " | ||||
| "dynamic register window sizes are not currently " | "dynamic register window sizes are not currently " | ||||
| Context not available. | |||||
| dwa->parent_res = NULL; | dwa->parent_res = NULL; | ||||
| dwa->rnid = rnid; | dwa->rnid = rnid; | ||||
| dwa->target = 0x0; | dwa->target = 0x0; | ||||
| LIST_INIT(&dwa->refs); | LIST_INIT(&dwa->refs); | ||||
| /* Find and validate corresponding resource. */ | /* Find and validate corresponding resource. */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Deallocate the given bridge resource structure and any associated resources. | * Deallocate the given bridge resource structure and any associated resources. | ||||
| * | * | ||||
| * @param br Resource state to be deallocated. | * @param br Resource state to be deallocated. | ||||
| */ | */ | ||||
| void | void | ||||
| Context not available. | |||||
| struct bhndb_dw_rentry *dwr, *dwr_next; | struct bhndb_dw_rentry *dwr, *dwr_next; | ||||
| /* No window regions may still be held */ | /* 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", | device_printf(br->dev, "leaked %llu dynamic register regions\n", | ||||
| (unsigned long long) br->dwa_count - br->dwa_freelist); | (unsigned long long) br->dwa_count - br->dwa_freelist); | ||||
| } | } | ||||
| Context not available. | |||||
| free(dwr, M_BHND); | free(dwr, M_BHND); | ||||
| } | } | ||||
| } | } | ||||
| /* Release bus regions */ | /* Release bus regions */ | ||||
| STAILQ_FOREACH_SAFE(region, &br->bus_regions, link, r_next) { | STAILQ_FOREACH_SAFE(region, &br->bus_regions, link, r_next) { | ||||
| STAILQ_REMOVE(&br->bus_regions, region, bhndb_region, link); | STAILQ_REMOVE(&br->bus_regions, region, bhndb_region, link); | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Add a bus region entry to @p r for the given base @p addr and @p size. | * 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 br The resource state to which the bus region entry will be added. | ||||
| * @param addr The base address of this region. | * @param addr The base address of this region. | ||||
| * @param size The size of this region. | * @param size The size of this region. | ||||
| Context not available. | |||||
| * made within this bus region. | * made within this bus region. | ||||
| * @param static_regwin If available, a static register window mapping this | * @param static_regwin If available, a static register window mapping this | ||||
| * bus region entry. If not available, NULL. | * bus region entry. If not available, NULL. | ||||
| * | * | ||||
| * @retval 0 success | * @retval 0 success | ||||
| * @retval non-zero if adding the bus region fails. | * @retval non-zero if adding the bus region fails. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Find a bus region that maps @p size bytes at @p addr. | * Find a bus region that maps @p size bytes at @p addr. | ||||
| * | * | ||||
| * @param br The resource state to search. | * @param br The resource state to search. | ||||
| * @param addr The requested starting address. | * @param addr The requested starting address. | ||||
| * @param size The requested size. | * @param size The requested size. | ||||
| * | * | ||||
| * @retval bhndb_region A region that fully contains the requested range. | * @retval bhndb_region A region that fully contains the requested range. | ||||
| * @retval NULL If no mapping region can be found. | * @retval NULL If no mapping region can be found. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Find the entry matching @p r in @p dwa's references, if any. | * Find the entry matching @p r in @p dwa's references, if any. | ||||
| * | * | ||||
| * @param dwa The dynamic window allocation to search | * @param dwa The dynamic window allocation to search | ||||
| * @param r The resource to search for in @p dwa. | * @param r The resource to search for in @p dwa. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Find the dynamic region allocated for @p r, if any. | * Find the dynamic region allocated for @p r, if any. | ||||
| * | * | ||||
| * @param br The resource state to search. | * @param br The resource state to search. | ||||
| * @param r The resource to search for. | * @param r The resource to search for. | ||||
| * | * | ||||
| * @retval bhndb_dw_alloc The allocation record for @p r. | * @retval bhndb_dw_alloc The allocation record for @p r. | ||||
| * @retval NULL if no dynamic window is allocated for @p r. | * @retval NULL if no dynamic window is allocated for @p r. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Find an existing dynamic window mapping @p size bytes | * Find an existing dynamic window mapping @p size bytes | ||||
| * at @p addr. The window may or may not be free. | * at @p addr. The window may or may not be free. | ||||
| * | * | ||||
| * @param br The resource state to search. | * @param br The resource state to search. | ||||
| * @param addr The requested starting address. | * @param addr The requested starting address. | ||||
| * @param size The requested size. | * @param size The requested size. | ||||
| * | * | ||||
| * @retval bhndb_dw_alloc A window allocation that fully contains the requested | * @retval bhndb_dw_alloc A window allocation that fully contains the requested | ||||
| * range. | * range. | ||||
| * @retval NULL If no mapping region can be found. | * @retval NULL If no mapping region can be found. | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Retain a reference to @p dwa for use by @p res. | * Retain a reference to @p dwa for use by @p res. | ||||
| * | * | ||||
| * @param br The resource state owning @p dwa. | * @param br The resource state owning @p dwa. | ||||
| * @param dwa The allocation record to be retained. | * @param dwa The allocation record to be retained. | ||||
| * @param res The resource that will own a reference to @p dwa. | * @param res The resource that will own a reference to @p dwa. | ||||
| * | * | ||||
| * @retval 0 success | * @retval 0 success | ||||
| * @retval ENOMEM Failed to allocate a new reference structure. | * @retval ENOMEM Failed to allocate a new reference structure. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /* Update the free list */ | /* Update the free list */ | ||||
| br->dwa_freelist &= ~(1 << (dwa->rnid)); | br->dwa_freelist &= ~(1 << (dwa->rnid)); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| Context not available. | |||||
| * Release a reference to @p dwa previously retained by @p res. If the | * 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 | * reference count of @p dwa reaches zero, it will be added to the | ||||
| * free list. | * free list. | ||||
| * | * | ||||
| * @param br The resource state owning @p dwa. | * @param br The resource state owning @p dwa. | ||||
| * @param dwa The allocation record to be released. | * @param dwa The allocation record to be released. | ||||
| * @param res The resource that currently owns a reference to @p dwa. | * @param res The resource that currently owns a reference to @p dwa. | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Attempt to set (or reset) the target address of @p dwa to map @p size bytes | * Attempt to set (or reset) the target address of @p dwa to map @p size bytes | ||||
| * at @p addr. | * at @p addr. | ||||
| * | * | ||||
| * This will apply any necessary window alignment and verify that | * This will apply any necessary window alignment and verify that | ||||
| * the window is capable of mapping the requested range prior to modifying | * the window is capable of mapping the requested range prior to modifying | ||||
| * therecord. | * therecord. | ||||
| * | * | ||||
| * @param dev The device on which to issue the BHNDB_SET_WINDOW_ADDR() request. | * @param dev The device on which to issue the BHNDB_SET_WINDOW_ADDR() request. | ||||
| * @param br The resource state owning @p dwa. | * @param br The resource state owning @p dwa. | ||||
| * @param dwa The allocation record to be configured. | * @param dwa The allocation record to be configured. | ||||
| Context not available. | |||||
| /* Verify that the window is large enough for the full target */ | /* Verify that the window is large enough for the full target */ | ||||
| if (rw->win_size - offset < size) | if (rw->win_size - offset < size) | ||||
| return (ENOMEM); | return (ENOMEM); | ||||
| /* Update the window target */ | /* Update the window target */ | ||||
| error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target); | error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target); | ||||
| if (error) { | if (error) { | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Return the count of @p type register windows in @p table. | * Return the count of @p type register windows in @p table. | ||||
| * | * | ||||
| * @param table The table to search. | * @param table The table to search. | ||||
| * @param type The required window type, or BHNDB_REGWIN_T_INVALID to | * @param type The required window type, or BHNDB_REGWIN_T_INVALID to | ||||
| * count all register window types. | * count all register window types. | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Search @p table for the first window with the given @p type. | * Search @p table for the first window with the given @p type. | ||||
| * | * | ||||
| * @param table The table to search. | * @param table The table to search. | ||||
| * @param type The required window type. | * @param type The required window type. | ||||
| * @param min_size The minimum window size. | * @param min_size The minimum window size. | ||||
| * | * | ||||
| * @retval bhndb_regwin The first matching window. | * @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 * | const struct bhndb_regwin * | ||||
| bhndb_regwin_find_type(const struct bhndb_regwin *table, | bhndb_regwin_find_type(const struct bhndb_regwin *table, | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Search @p windows for the first matching core window. | * Search @p windows for the first matching core window. | ||||
| * | * | ||||
| * @param table The table to search. | * @param table The table to search. | ||||
| * @param class The required core class. | * @param class The required core class. | ||||
| * @param unit The required core unit, or -1. | * @param unit The required core unit, or -1. | ||||
| Context not available. | |||||
| * @param region The required region. | * @param region The required region. | ||||
| * | * | ||||
| * @retval bhndb_regwin The first matching window. | * @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 * | const struct bhndb_regwin * | ||||
| bhndb_regwin_find_core(const struct bhndb_regwin *table, bhnd_devclass_t class, | 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) | int unit, bhnd_port_type port_type, u_int port, u_int region) | ||||
| { | { | ||||
| const struct bhndb_regwin *rw; | const struct bhndb_regwin *rw; | ||||
| for (rw = table; rw->win_type != BHNDB_REGWIN_T_INVALID; rw++) | for (rw = table; rw->win_type != BHNDB_REGWIN_T_INVALID; rw++) | ||||
| { | { | ||||
| if (rw->win_type != BHNDB_REGWIN_T_CORE) | if (rw->win_type != BHNDB_REGWIN_T_CORE) | ||||
| continue; | continue; | ||||
| if (rw->core.class != class) | if (rw->win_spec.core.class != class) | ||||
| continue; | continue; | ||||
| if (unit != -1 && rw->core.unit != unit) | if (unit != -1 && rw->win_spec.core.unit != unit) | ||||
| continue; | continue; | ||||
| if (rw->core.port_type != port_type) | if (rw->win_spec.core.port_type != port_type) | ||||
| continue; | continue; | ||||
| if (rw->core.port != port) | if (rw->win_spec.core.port != port) | ||||
| continue; | continue; | ||||
| if (rw->core.region != region) | if (rw->win_spec.core.region != region) | ||||
| continue; | continue; | ||||
| return (rw); | return (rw); | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Search @p windows for the best available window of at least @p min_size. | * Search @p windows for the best available window of at least @p min_size. | ||||
| * | * | ||||
| * Search order: | * Search order: | ||||
| * - BHND_REGWIN_T_CORE | * - BHND_REGWIN_T_CORE | ||||
| * - BHND_REGWIN_T_DYN | * - BHND_REGWIN_T_DYN | ||||
| * | * | ||||
| * @param table The table to search. | * @param table The table to search. | ||||
| * @param class The required core class. | * @param class The required core class. | ||||
| * @param unit The required core unit, or -1. | * @param unit The required core unit, or -1. | ||||
| Context not available. | |||||
| * @param min_size The minimum window size. | * @param min_size The minimum window size. | ||||
| * | * | ||||
| * @retval bhndb_regwin The first matching window. | * @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 * | const struct bhndb_regwin * | ||||
| bhndb_regwin_find_best(const struct bhndb_regwin *table, | bhndb_regwin_find_best(const struct bhndb_regwin *table, | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Return true if @p regw defines a static port register window, and | * Return true if @p regw defines a static port register window, and | ||||
| * the mapped port is actually defined on @p dev. | * the mapped port is actually defined on @p dev. | ||||
| * | * | ||||
| * @param regw A register window to match against. | * @param regw A register window to match against. | ||||
| * @param dev A bhnd(4) bus device. | * @param dev A bhnd(4) bus device. | ||||
| */ | */ | ||||
| Context not available. | |||||
| return (false); | return (false); | ||||
| /* Device class must match */ | /* Device class must match */ | ||||
| if (bhnd_get_class(dev) != regw->core.class) | if (bhnd_get_class(dev) != regw->win_spec.core.class) | ||||
| return (false); | return (false); | ||||
| /* Device unit must match */ | /* 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); | return (false); | ||||
| /* The regwin port/region must be defined. */ | /* The regwin port/region must be defined. */ | ||||
| if (!bhnd_is_region_valid(dev, regw->core.port_type, regw->core.port, | if (!bhnd_is_region_valid(dev, regw->win_spec.core.port_type, regw->win_spec.core.port, | ||||
| regw->core.region)) | regw->win_spec.core.region)) | ||||
| { | { | ||||
| return (false); | return (false); | ||||
| } | } | ||||
| Context not available. | |||||
| /** | /** | ||||
| * Search for a core resource priority descriptor in @p table that matches | * Search for a core resource priority descriptor in @p table that matches | ||||
| * @p device. | * @p device. | ||||
| * | * | ||||
| * @param table The table to search. | * @param table The table to search. | ||||
| * @param device A bhnd(4) bus device. | * @param device A bhnd(4) bus device. | ||||
| */ | */ | ||||
| Context not available. | |||||
| /* not found */ | /* not found */ | ||||
| return (NULL); | 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"); | |||||
| } | |||||
| Context not available. | |||||