BHND(9)
π BHND(9) π
Okay bestie, welcome to BHND(9) from the Kernel Developer's Manual β the BHND driver programming interface. This is the part where we lay out every signature exactly as it is, because messing with prototypes is not the vibe. π«Άβ¨
πΈ NAME πΈ
bhnd β BHND driver programming interface. Short, iconic, to the point. π
β¨ SYNOPSIS β¨
First, the include line that starts the whole thing:
#include <dev/bhnd/bhnd.h>
Then the function lineup, organized subsection by subsection. Copy these exactly, no cap β names, argument types, pointers, all of it. π
π¦ Bus Resource Functions π¦
The bus resource squad:
int
bhnd_activate_resource(device_t dev, int type, int rid,
struct bhnd_resource *r);
struct bhnd_resource *
bhnd_alloc_resource(device_t dev, int type, int *rid, rman_res_t start,
rman_res_t end, rman_res_t count, u_int flags);
struct bhnd_resource *
bhnd_alloc_resource_any(device_t dev, int type, int *rid, u_int flags);
int
bhnd_alloc_resources(device_t dev, struct resource_spec *rs,
struct bhnd_resource **res);
int
bhnd_deactivate_resource(device_t dev, int type, int rid,
struct bhnd_resource *r);
int
bhnd_release_resource(device_t dev, int type, int rid,
struct bhnd_resource *r);
void
bhnd_release_resources(device_t dev, const struct resource_spec *rs,
struct bhnd_resource **res);
π Bus Space Functions π
This is the bus space lineup, and yes, there are a lot of them β every single one is here. π
void
bhnd_bus_barrier(struct bhnd_resource *r, bus_size_t offset,
bus_size_t length, int flags);
uint8_t
bhnd_bus_read_1(struct bhnd_resource *r, bus_size_t offset);
uint16_t
bhnd_bus_read_2(struct bhnd_resource *r, bus_size_t offset);
uint32_t
bhnd_bus_read_4(struct bhnd_resource *r, bus_size_t offset);
void
bhnd_bus_read_multi_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t *datap, bus_size_t count);
void
bhnd_bus_read_multi_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t *datap, bus_size_t count);
void
bhnd_bus_read_multi_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t *datap, bus_size_t count);
void
bhnd_bus_read_multi_stream_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t *datap, bus_size_t count);
void
bhnd_bus_read_multi_stream_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t *datap, bus_size_t count);
void
bhnd_bus_read_multi_stream_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t *datap, bus_size_t count);
void
bhnd_bus_read_region_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t *datap, bus_size_t count);
void
bhnd_bus_read_region_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t *datap, bus_size_t count);
void
bhnd_bus_read_region_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t *datap, bus_size_t count);
void
bhnd_bus_read_region_stream_1(struct bhnd_resource *r,
bus_size_t offset, uint8_t *datap, bus_size_t count);
void
bhnd_bus_read_region_stream_2(struct bhnd_resource *r,
bus_size_t offset, uint16_t *datap, bus_size_t count);
void
bhnd_bus_read_region_stream_4(struct bhnd_resource *r,
bus_size_t offset, uint32_t *datap, bus_size_t count);
void
bhnd_bus_read_stream_1(struct bhnd_resource *r, bus_size_t offset);
void
bhnd_bus_read_stream_2(struct bhnd_resource *r, bus_size_t offset);
uint32_t
bhnd_bus_read_stream_4(struct bhnd_resource *r, bus_size_t offset);
void
bhnd_bus_set_multi_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t value, bus_size_t count);
void
bhnd_bus_set_multi_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t value, bus_size_t count);
void
bhnd_bus_set_multi_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t value, bus_size_t count);
void
bhnd_bus_set_region_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t value, bus_size_t count);
void
bhnd_bus_set_region_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t value, bus_size_t count);
void
bhnd_bus_set_region_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t value, bus_size_t count);
void
bhnd_bus_write_1(struct bhnd_resource *r, uint8_t value);
void
bhnd_bus_write_2(struct bhnd_resource *r, uint16_t value);
void
bhnd_bus_write_4(struct bhnd_resource *r, uint32_t value);
void
bhnd_bus_write_multi_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t *datap, bus_size_t count);
void
bhnd_bus_write_multi_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t *datap, bus_size_t count);
void
bhnd_bus_write_multi_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t *datap, bus_size_t count);
void
bhnd_bus_write_multi_stream_1(struct bhnd_resource *r,
bus_size_t offset, uint8_t *datap, bus_size_t count);
void
bhnd_bus_write_multi_stream_2(struct bhnd_resource *r,
bus_size_t offset, uint16_t *datap, bus_size_t count);
void
bhnd_bus_write_multi_stream_4(struct bhnd_resource *r,
bus_size_t offset, uint32_t *datap, bus_size_t count);
void
bhnd_bus_write_region_1(struct bhnd_resource *r, bus_size_t offset,
uint8_t *datap, bus_size_t count);
void
bhnd_bus_write_region_2(struct bhnd_resource *r, bus_size_t offset,
uint16_t *datap, bus_size_t count);
void
bhnd_bus_write_region_4(struct bhnd_resource *r, bus_size_t offset,
uint32_t *datap, bus_size_t count);
void
bhnd_bus_write_region_stream_1(struct bhnd_resource *r,
bus_size_t offset, uint8_t *datap, bus_size_t count);
void
bhnd_bus_write_region_stream_2(struct bhnd_resource *r,
bus_size_t offset, uint16_t *datap, bus_size_t count);
void
bhnd_bus_write_region_stream_4(struct bhnd_resource *r,
bus_size_t offset, uint32_t *datap, bus_size_t count);
void
bhnd_bus_write_stream_1(struct bhnd_resource *r, uint8_t value);
void
bhnd_bus_write_stream_2(struct bhnd_resource *r, uint16_t value);
void
bhnd_bus_write_stream_4(struct bhnd_resource *r, uint32_t value);
β Device Configuration Functions β
Device configuration prototypes, looking all official and put-together:
int
bhnd_read_ioctl(device_t dev, uint16_t *ioctl);
int
bhnd_write_ioctl(device_t dev, uint16_t value, uint16_t mask);
int
bhnd_read_iost(device_t dev, uint16_t *iost);
uint32_t
bhnd_read_config(device_t dev, bus_size_t offset, void *value,
u_int width);
int
bhnd_write_config(device_t dev, bus_size_t offset, const void *value,
u_int width);
int
bhnd_reset_hw(device_t dev, uint16_t ioctl, uint16_t reset_ioctl);
int
bhnd_suspend_hw(device_t dev, uint16_t ioctl);
bool
bhnd_is_hw_suspended(device_t dev);
π¦ Device Information Functions π¦
Info-gathering functions, main character energy only:
bhnd_attach_type
bhnd_get_attach_type(device_t dev);
const struct bhnd_chipid *
bhnd_get_chipid(device_t dev);
bhnd_devclass_t
bhnd_get_class(device_t dev);
u_int
bhnd_get_core_index(device_t dev);
struct bhnd_core_info
bhnd_get_core_info(device_t dev);
int
bhnd_get_core_unit(device_t dev);
uint16_t
bhnd_get_device(device_t dev);
const char *
bhnd_get_device_name(device_t dev);
uint8_t
bhnd_get_hwrev(device_t dev);
uint16_t
bhnd_get_vendor(device_t dev);
const char *
bhnd_get_vendor_name(device_t dev);
int
bhnd_read_board_info(device_t dev, struct bhnd_board_info *info);
π Device Matching Functions π
Matching functions, doing their little compare-and-match thing:
bool
bhnd_board_matches(const struct bhnd_board_info *board,
const struct bhnd_board_match *desc);
device_t
bhnd_bus_match_child(device_t bus, const struct bhnd_core_match *desc);
bool
bhnd_chip_matches(const struct bhnd_chipid *chip,
const struct bhnd_chip_match *desc);
struct bhnd_core_match
bhnd_core_get_match_desc(const struct bhnd_core_info *core);
bool
bhnd_core_matches(const struct bhnd_core_info *core,
const struct bhnd_core_match *desc);
bool
bhnd_cores_equal(const struct bhnd_core_info *lhs,
const struct bhnd_core_info *rhs);
bool
bhnd_hwrev_matches(uint16_t hwrev, const struct bhnd_hwrev_match *desc);
const struct bhnd_core_info *
bhnd_match_core(const struct bhnd_core_info *cores, u_int num_cores,
const struct bhnd_core_match *desc);
π Device Table Functions π
Device table functions, plus the macros, structs, enum, and defines β all of them, bestie, not a single one skipped:
const struct bhnd_device *
bhnd_device_lookup(device_t dev, const struct bhnd_device *table,
size_t entry_size);
bool
bhnd_device_matches(device_t dev, const struct bhnd_device_match *desc);
uint32_t
bhnd_device_quirks(device_t dev, const struct bhnd_device *table,
size_t entry_size);
BHND_BOARD_QUIRK(board, flags);
BHND_CHIP_QUIRK(chip, hwrev, flags);
BHND_CORE_QUIRK(hwrev, flags);
BHND_DEVICE(vendor, device, desc, quirks, ...);
BHND_DEVICE_IS_END(struct bhnd_device *d);
BHND_DEVICE_QUIRK_IS_END(struct bhnd_device_quirk *q);
BHND_PKG_QUIRK(chip, pkg, flags);
struct bhnd_device_quirk {
struct bhnd_device_match desc;
uint32_t quirks;
};
struct bhnd_device {
const struct bhnd_device_match core;
const char *desc;
const struct bhnd_device_quirk *quirks_table;
uint32_t device_flags;
};
enum {
BHND_DF_ANY = 0,
BHND_DF_HOSTB = (1 << 0),
BHND_DF_SOC = (1 << 1),
BHND_DF_ADAPTER = (1 << 2)
};
#define BHND_DEVICE_END { { BHND_MATCH_ANY }, NULL, NULL, 0 }
#define BHND_DEVICE_QUIRK_END { { BHND_MATCH_ANY }, 0 }
πΈ DMA Address Translation Functions πΈ
DMA address translation, with the function, struct, enum, and flags all present and accounted for:
int
bhnd_get_dma_translation(device_t dev, u_int width, uint32_t flags,
bus_dma_tag_t *dmat, struct bhnd_dma_translation *translation);
struct bhnd_dma_translation {
bhnd_addr_t base_addr;
bhnd_addr_t addr_mask;
bhnd_addr_t addrext_mask;
uint32_t flags;
};
typedef enum {
BHND_DMA_ADDR_30BIT = 30,
BHND_DMA_ADDR_32BIT = 32,
BHND_DMA_ADDR_64BIT = 64
} bhnd_dma_addrwidth;
enum bhnd_dma_translation_flags {
BHND_DMA_TRANSLATION_PHYSMAP = (1<<0),
BHND_DMA_TRANSLATION_BYTESWAPPED = (1<<1)
};
π₯ Interrupt Functions π₯
Interrupt functions, serving looks and signatures:
u_int
bhnd_get_intr_count(device_t dev);
int
bhnd_get_intr_ivec(device_t dev, u_int intr, u_int *ivec);
int
bhnd_map_intr(device_t dev, u_int intr, rman_res_t *irq);
void
bhnd_unmap_intr(device_t dev, rman_res_t irq);
π NVRAM Functions π
NVRAM functions, all lined up:
int
bhnd_nvram_getvar(device_t dev, const char *name, void *buf,
size_t *len, bhnd_nvram_type type);
int
bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf,
size_t size, bhnd_nvram_type type);
int
bhnd_nvram_getvar_int(device_t dev, const char *name, void *value,
int width);
int
bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value);
int
bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value);
int
bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value);
int
bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value,
int width);
int
bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value);
int
bhnd_nvram_getvar_uint16(device_t dev, const char *name,
uint16_t *value);
int
bhnd_nvram_getvar_uint32(device_t dev, const char *name,
uint32_t *value);
int
bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf,
size_t len, size_t *rlen);
const char *
bhnd_nvram_string_array_next(const char *inp, size_t ilen,
const char *prev, size_t *olen);
typedef enum {
BHND_NVRAM_TYPE_UINT8 = 0,
BHND_NVRAM_TYPE_UINT16 = 1,
BHND_NVRAM_TYPE_UINT32 = 2,
BHND_NVRAM_TYPE_UINT64 = 3,
BHND_NVRAM_TYPE_INT8 = 4,
BHND_NVRAM_TYPE_INT16 = 5,
BHND_NVRAM_TYPE_INT32 = 6,
BHND_NVRAM_TYPE_INT64 = 7,
BHND_NVRAM_TYPE_CHAR = 8,
BHND_NVRAM_TYPE_STRING = 9,
BHND_NVRAM_TYPE_BOOL = 10,
BHND_NVRAM_TYPE_NULL = 11,
BHND_NVRAM_TYPE_DATA = 12
BHND_NVRAM_TYPE_UINT8_ARRAY = 16,
BHND_NVRAM_TYPE_UINT16_ARRAY = 17,
BHND_NVRAM_TYPE_UINT32_ARRAY = 18,
BHND_NVRAM_TYPE_UINT64_ARRAY = 19,
BHND_NVRAM_TYPE_INT8_ARRAY = 20,
BHND_NVRAM_TYPE_INT16_ARRAY = 21,
BHND_NVRAM_TYPE_INT32_ARRAY = 22,
BHND_NVRAM_TYPE_INT64_ARRAY = 23,
BHND_NVRAM_TYPE_CHAR_ARRAY = 24,
BHND_NVRAM_TYPE_STRING_ARRAY = 25,
BHND_NVRAM_TYPE_BOOL_ARRAY = 26
} bhnd_nvram_type;
π§΅ Port/Region Functions
int
bhnd_decode_port_rid(device_t dev, int type, int rid,
bhnd_port_type *port_type, u_int *port, u_int *region);
u_int
bhnd_get_port_count(device_t dev, bhnd_port_type type);
int
bhnd_get_port_rid(device_t dev, bhnd_port_type type, u_int port,
u_int region);
int
bhnd_get_region_addr(device_t dev, bhnd_port_type port_type, u_int port,
u_int region, bhnd_addr_t *region_addr, bhnd_size_t *region_size);
u_int
bhnd_get_region_count(device_t dev, bhnd_port_type type, u_int port);
bool
bhnd_is_region_valid(device_t dev, bhnd_port_type type, u_int port,
u_int region);
typedef enum {
BHND_PORT_DEVICE = 0,
BHND_PORT_BRIDGE = 1,
BHND_PORT_AGENT = 2
} bhnd_port_type;
β‘ Power Management Functions
int
bhnd_alloc_pmu(device_t dev);
int
bhnd_release_pmu(device_t dev);
int
bhnd_enable_clocks(device_t dev, uint32_t clocks);
int
bhnd_request_clock(device_t dev, bhnd_clock clock);
int
bhnd_get_clock_freq(device_t dev, bhnd_clock clock, u_int *freq);
int
bhnd_get_clock_latency(device_t dev, bhnd_clock clock, u_int *latency);
int
bhnd_request_ext_rsrc(device_t dev, u_int rsrc);
int
bhnd_release_ext_rsrc(device_t dev, u_int rsrc);
typedef enum {
BHND_CLOCK_DYN = (1 << 0),
BHND_CLOCK_ILP = (1 << 1),
BHND_CLOCK_ALP = (1 << 2),
BHND_CLOCK_HT = (1 << 3)
} bhnd_clock;
π«Ά Service Provider Functions
int
bhnd_register_provider(device_t dev, bhnd_service_t service);
int
bhnd_deregister_provider(device_t dev, bhnd_service_t service);
device_t
bhnd_retain_provider(device_t dev, bhnd_service_t service);
void
bhnd_release_provider(device_t dev, device_t provider,
bhnd_service_t service);
typedef enum {
BHND_SERVICE_CHIPC,
BHND_SERVICE_PWRCTL,
BHND_SERVICE_PMU,
BHND_SERVICE_NVRAM,
BHND_SERVICE_GPIO,
BHND_SERVICE_ANY = 1000
} bhnd_service_t;
π οΈ Utility Functions
bhnd_erom_class_t *
bhnd_driver_get_erom_class(driver_t *driver);
bhnd_devclass_t
bhnd_find_core_class(uint16_t vendor, uint16_t device);
const char *
bhnd_find_core_name(uint16_t vendor, uint16_t device);
bhnd_devclass_t
bhnd_core_class(const struct bhnd_core_info *ci);
const char *
bhnd_core_name(const struct bhnd_core_info *ci);
int
bhnd_format_chip_id(char *buffer, size_t size, uint16_t chip_id);
void
bhnd_set_custom_core_desc(device_t dev, const char *dev_name);
void
bhnd_set_default_core_desc(device_t dev);
const char *
bhnd_vendor_name(uint16_t vendor);
#define BHND_CHIPID_MAX_NAMELEN 32
β¨ DESCRIPTION β¨
okay so bhnd is your one-stop unified bus + driver programming interface for the on-chip interconnects and IP cores you find in Broadcom Home Networking Division (BHND) devices. it's giving glue layer, but make it iconic π
The BHND device family is literally the MIPS/ARM SoCs (System On a Chip) plus the host-connected chipsets β all built on a common library of Broadcom IP cores, hooked up through one of two on-chip backplane (hardware bus) architectures. two. not one. keep up bestie π¦
Hardware designed before 2009 used Broadcom's βSSBβ backplane architecture, which is based on Sonics Silicon's interconnect IP. every single core on that Sonics backplane vends a 4 KiB register block, and that block holds BOTH the device-specific CSRs AND the SSB-specific per-core device management (enable/reset/etc) registers. two things in one block, we love a multitasker π
Subsequent hardware switched to Broadcom's βBCMAβ backplane, which is based on ARM's AMBA IP. and the way they handled it? the IP cores from the earlier SSB-based devices were adapted for compatibility with the new backplane, and extra βwrapperβ cores showed up to provide the per-core device management functions β standing in for those SSB per-core management registers. character development, honestly π
When BHND hardware is used as a host-connected peripheral (e.g., in a PCI Wi-Fi card), the on-chip peripheral controller core gets configured to operate as an endpoint device, bridging access to the SoC hardware. and that bridge does a LOT:
- Host access to SoC address space is provided via a set of register windows (e.g., a set of configurable windows into SoC address space mapped via PCI BARs) πͺ
- DMA is supported by the bridge core's sparse mapping of host address space into the backplane address space. these address regions may be used as a target for the on-chip DMA engine. no cap π₯
- Any backplane interrupt vectors routed to the bridge core may be mapped by the bridge to host interrupts (e.g., PCI INTx/MSI/MSI-X). interrupt glow-up fr fr β‘
The bhnd driver programming interface β and bhndb(4) host bridge drivers β support the implementation of common drivers for Broadcom IP cores, whether attached via a BHND host bridge, or via the native SoC backplane. one driver, two attachment paths, main character energy π
πΈ Bus Resource Functions πΈ
The bhnd_resource functions are wrappers for the standard struct resource bus APIs, and they provide support for SYS_RES_MEMORY resources that β on bhndb(4) bridged chipsets β may require on-demand remapping of address windows before you access bus memory. heads up, that's an on-demand situation, not an always situation π«Ά
These functions are primarily used in the implementation of BHND platform device drivers that, on host-connected peripherals, must share a small set of register windows during initial setup and teardown. that's the specific scenario, bestie β initial setup and teardown π
BHND peripherals are designed to not require register window remapping during normal operation, and most drivers may safely use the standard struct resource APIs directly. so like... don't reach for the fancy wrappers unless you actually need them π
The bhnd_activate_resource() function activates a previously allocated resource.
The arguments are as follows:
devβ The device holding ownership of the allocated resource.typeβ The type of the resource.ridβ The bus-specific handle that identifies the resource being activated.rβ A pointer to the resource returned bybhnd_alloc_resource().
The bhnd_alloc_resource() function allocates a resource from a device's parent bhnd(4) bus.
The arguments are as follows:
devβ The device requesting resource ownership.typeβ The type of resource to allocate. This may be any type supported by the standardbus_alloc_resource(9)function.ridβ The bus-specific handle identifying the resource being allocated.startβ The start address of the resource.endβ The end address of the resource.countβ The size of the resource.flagsβ The flags for the resource to be allocated. These may be any values supported by the standardbus_alloc_resource(9)function.
To request that the bus supply the resource's default start, end, and count values, pass start and end values of 0ul and ~0ul respectively, and a count of 1. yes those exact values, write them down π
The bhnd_alloc_resource_any() function is a convenience wrapper for bhnd_alloc_resource(), using the resource's default start, end, and count values.
The arguments are as follows:
devβ The device requesting resource ownership.typeβ The type of resource to allocate. This may be any type supported by the standardbus_alloc_resource(9)function.ridβ The bus-specific handle identifying the resource being allocated.flagsβ The flags for the resource to be allocated. These may be any values supported by the standardbus_alloc_resource(9)function.
The bhnd_alloc_resources() function allocates resources defined in resource specification from a device's parent bhnd(4) bus.
The arguments are as follows:
devβ The device requesting ownership of the resources.rsβ A standard bus resource specification. If all requested resources, are successfully allocated, this will be updated with the allocated resource identifiers.resβ If all requested resources are successfully allocated, this will be populated with the allocatedstruct bhnd_resourceinstances.
The bhnd_deactivate_resource() function deactivates a resource previously activated by bhnd_activate_resource(). The arguments are as follows:
devβ The device holding ownership of the activated resource.typeβ The type of the resource.ridβ The bus-specific handle identifying the resource.rβ A pointer to the resource returned bybhnd_alloc_resource.
The bhnd_release_resource() function frees a resource previously returned by bhnd_alloc_resource(). The arguments are as follows:
devβ The device holding ownership of the resource.typeβ The type of the resource.ridβ The bus-specific handle identifying the resource.rβ A pointer to the resource returned bybhnd_alloc_resource.
The bhnd_release_resources() function frees resources previously returned by bhnd_alloc_resources(). The arguments are as follows:
devβ The device that owns the resources.rsβ A standard bus resource specification previously initialized bybhnd_alloc_resources().resβ The resources to be released.
The bhnd_resource structure contains the following fields:
resβ A pointer to the busstruct resource.directβ if this is true, the resource requires bus window remapping before itβs MMIO-accessible. π
β¨ Bus Space Functions β¨
okay so the bhnd_bus_space functions wrap their equivalent bus_space(9) counterparts, and they provide support for accessing bus memory via struct bhnd_resource. the whole roster, no cap:
bhnd_bus_barrier()
bhnd_bus_[read|write]_[1|2|4]()
bhnd_bus_[read_multi|write_multi]_[1|2|4]()
bhnd_bus_[read_multi_stream|write_multi_stream]_[1|2|4]()
bhnd_bus_[read_region|write_region]_[1|2|4]()
bhnd_bus_[read_region_stream|write_region_stream]_[1|2|4]()
bhnd_bus_[read_stream|write_stream]_[1|2|4]()
bhnd_bus_[set_multi|set_stream]_[1|2|4]()
Drivers that do not rely on struct bhnd_resource should use the standard struct resource and bus_space(9) APIs directly. π«Ά
π Device Configuration Functions π
The bhnd_read_ioctl() function is used to read the I/O control register value of device dev, returning the current value in ioctl.
The bhnd_write_ioctl() function is used to modify the I/O control register of dev. The new value of the register is computed by updating any bits set in mask to value. The following I/O control flags are supported:
BHND_IOCTL_BISTβ initiate a built-in self-test (BIST). must be cleared after BIST results are read via the IOST (I/O Status) register. donβt forget, bestie πBHND_IOCTL_PMEβ enable posting of power management events by the core.BHND_IOCTL_CLK_FORCEβ force disable of clock gating, resulting in all clocks being distributed within the core. should be set when asserting/deasserting reset to ensure the reset signal fully propagates to the entire core. iconic reset behavior tbh π₯BHND_IOCTL_CLK_ENβ if cleared, the core clock will be disabled. should be set during normal operation, and cleared when the core is held in reset.BHND_IOCTL_CFLAGSβ the mask of IOCTL bits reserved for additional core-specific I/O control flags.
The bhnd_read_iost() function is used to read the I/O status register of device dev, returning the current value in iost. The following I/O status flags are supported:
BHND_IOST_BIST_DONEβ set upon BIST completion. will be cleared when theBHND_IOCTL_BISTflag of the I/O control register is cleared usingbhnd_write_ioctl().BHND_IOST_BIST_FAILβ set upon detection of a BIST error; the value is unspecified if BIST has not completed andBHND_IOST_BIST_DONEis not also set. so likeβ¦ donβt trust it yet πBHND_IOST_CLKβ set if the core has required that clocked be ungated, or cleared otherwise. the value is undefined if a core does not support clock gating.BHND_IOST_DMA64β set if this core supports 64-bit DMA.BHND_IOST_CFLAGSβ the mask of IOST bits reserved for additional core-specific I/O status flags.
The bhnd_read_config() function is used to read a data item of width bytes at offset from the backplane-specific agent/config space of the device dev.
The bhnd_write_config() function is used to write a data item of width bytes with value at offset from the backplane-specific agent/config space of the device dev. the requested width must be one of 1, 2, or 4 bytes.
The agent/config space accessible via bhnd_read_config() and bhnd_write_config() is backplane-specific, and these functions should only be used for functionality that is not available via another bhnd function. lowkey niche access only π§
The bhnd_suspend_hw() function transitions the device dev to a low power βRESETβ state, writing ioctl to the I/O control flags of dev. the hardware may be brought out of this state using bhnd_reset_hw().
The bhnd_reset_hw() function first transitions the device dev to a low power RESET state, writing ioctl_reset to the I/O control flags of dev, and then brings the device out of RESET, writing ioctl to the deviceβs I/O control flags.
The bhnd_is_hw_suspended() function returns true if the device dev is currently held in a RESET state, or is otherwise not clocked. otherwise, it returns false.
Any outstanding per-device PMU requests made using bhnd_enable_clocks(), bhnd_request_clock(), or bhnd_request_ext_rsrc() will be released automatically upon placing a device into a RESET state. automatic cleanup? we love to see it π
π¦ Device Information Functions π¦
The bhnd_get_attach_type() function returns the attachment type of the parent bhnd(4) bus of device dev.
The following attachment types are supported:
BHND_ATTACH_ADAPTERβ the bus is resident on a bridged adapter, such as a PCI Wi-Fi device.BHND_ATTACH_NATIVEβ the bus is resident on the native host, such as the primary or secondary bus of an embedded SoC.
The bhnd_get_chipid() function returns chip information from the parent bhnd(4) bus of device dev. the returned bhnd_chipid struct contains the following fields:
chip_idβ the chip identifier.chip_revβ the chipβs hardware revision.chip_pkgβ the chipβs semiconductor package identifier.- several different physical semiconductor package variants may exist for a given chip, each of which may require driver workarounds for hardware errata, unpopulated components, etc. package lore fr fr π
chip_typeβ the interconnect architecture used by this chip.chip_capsβ the bhnd capability flags supported by this chip.enum_addrβ the backplane enumeration address. on SSB devices, this will be the base address of the first SSB core. on BCMA devices, this will be the address of the enumeration ROM (EROM) core.ncoresβ the number of cores on the chip backplane, or 0 if unknown.
The following constants are defined for known chip_type values:
BHND_CHIPTYPE_SIBAβ SSB interconnect.BHND_CHIPTYPE_BCMAβ BCMA interconnect.BHND_CHIPTYPE_BCMA_ALTβ BCMA-compatible variant found in Broadcom Northstar ARM SoCs.BHND_CHIPTYPE_UBUSβ UBUS interconnect. this BCMA-derived interconnect is found in Broadcom BCM33xx DOCSIS SoCs, and BCM63xx xDSL SoCs. UBUS is not currently supported bybhnd(4). sad but true π
The following chip_caps flags are supported:
BHND_CAP_BP64β the backplane supports 64-bit addressing.BHND_CAP_PMUβ PMU is present.
Additional symbolic constants for known chip_id, chip_pkg, and chip_type values are defined in <dev/bhnd/bhnd_ids.h>.
The bhnd_get_class() function returns the BHND class of device dev, if the deviceβs vendor and device identifiers are recognized. otherwise, returns BHND_DEVCLASS_OTHER.
One of the following device classes will be returned:
BHND_DEVCLASS_CCβ ChipCommon I/O ControllerBHND_DEVCLASS_CC_Bβ ChipCommon Auxiliary ControllerBHND_DEVCLASS_PMUβ PMU ControllerBHND_DEVCLASS_PCIβ PCI Host/Device BridgeBHND_DEVCLASS_PCIEβ PCIe Host/Device BridgeBHND_DEVCLASS_PCCARDβ PCMCIA Host/Device BridgeBHND_DEVCLASS_RAMβ Internal RAM/SRAMBHND_DEVCLASS_MEMCβ Memory ControllerBHND_DEVCLASS_ENETβ IEEE 802.3 MAC/PHYBHND_DEVCLASS_ENET_MACβ IEEE 802.3 MACBHND_DEVCLASS_ENET_PHYβ IEEE 802.3 PHYBHND_DEVCLASS_WLANβ IEEE 802.11 MAC/PHY/RadioBHND_DEVCLASS_WLAN_MACβ IEEE 802.11 MACBHND_DEVCLASS_WLAN_PHYβ IEEE 802.11 PHYBHND_DEVCLASS_CPUβ CPU CoreBHND_DEVCLASS_SOC_ROUTERβ Interconnect RouterBHND_DEVCLASS_SOC_BRIDGEβ Interconnect Host BridgeBHND_DEVCLASS_EROMβ Device Enumeration ROMBHND_DEVCLASS_NVRAMβ NVRAM/Flash ControllerBHND_DEVCLASS_SOFTMODEMβ Analog/PSTN SoftModem CodecBHND_DEVCLASS_USB_HOSTβ USB Host ControllerBHND_DEVCLASS_USB_DEVβ USB Device ControllerBHND_DEVCLASS_USB_DUALβ USB Host/Device ControllerBHND_DEVCLASS_OTHERβ Other / UnknownBHND_DEVCLASS_INVALIDβ Invalid Class
The bhnd_get_core_info() function returns the core information for device dev. the returned bhnd_core_info structure contains the following fields:
vendorβ vendor identifier (JEP-106, ARM 4-bit continuation encoded)deviceβ device identifierhwrevβ hardware revisioncore_idxβ core indexunitβ core unit
Symbolic constants for common vendor and device identifiers are defined in <dev/bhnd/bhnd_ids.h>. common vendor identifiers include:
BHND_MFGID_ARMβ ARMBHND_MFGID_BCMβ BroadcomBHND_MFGID_MIPSβ MIPS
The bhnd_get_core_index(), bhnd_get_core_unit(), bhnd_get_device(), bhnd_get_hwrev(), and bhnd_get_vendor() functions are convenience wrappers for bhnd_get_core_info(), returning the core_idx, core_unit, device, hwrev, or vendor field from the bhnd_core_info structure. little shortcut besties π
The bhnd_get_device_name() function returns a human readable name for device dev.
The bhnd_get_vendor_name() function returns a human readable name for the vendor of device dev.
The bhnd_read_board_info() function attempts to read the board information for device dev. the board information will be returned in the location pointed to by info on success.
The bhnd_board_info structure contains the following fields:
board_vendorβ Vendor ID of the board manufacturer (PCI-SIG assigned).board_typeβ Board ID.board_devidβ Device ID.board_revβ Board revision.board_srom_revβ Board SROM format revision.board_flagsβ Board flags (1)board_flags2β Board flags (2)board_flags3β Board flags (3)
The board_devid field is the Broadcom PCI device ID that most closely matches the capabilities of the BHND device (if any).
On PCI devices, the board_vendor, board_type, and board_devid fields default to the PCI Subsystem Vendor ID, PCI Subsystem ID, and PCI device ID, unless overridden in device NVRAM.
On other devices β SoCs included β the board_vendor, board_type, and board_devid fields get populated from device NVRAM. The symbolic constants for common board flags are defined in <dev/bhnd/bhnd_ids.h>. π«Ά
β¨ Device Matching Functions β¨
Okay so the bhnd device matching functions are your little matchmakers for core-, chip-, and board-level attributes. You spell out what you want using these match descriptor structs: struct bhnd_board_match, struct bhnd_chip_match, struct bhnd_core_match, struct bhnd_device_match, and struct bhnd_hwrev_match. Bestie, itβs giving very βtell me exactly what youβre looking forβ energy. π
bhnd_board_matches()β returnstrueifboardmatches the board match descriptordesc. Otherwise, it returnsfalse.bhnd_chip_matches()β returnstrueifchipmatches the chip match descriptordesc. Otherwise, it returnsfalse.bhnd_core_matches()β returnstrueifcorematches the core match descriptordesc. Otherwise, it returnsfalse.bhnd_device_matches()β returnstrueif the devicedevmatches the device match descriptordesc. Otherwise, it returnsfalse.bhnd_hwrev_matches()β returnstrueifhwrevmatches the hwrev match descriptordesc. Otherwise, it returnsfalse.bhnd_bus_match_child()β returns the first child device ofbusthat matches the device match descriptordesc. If no matching child is found,NULLis returned.bhnd_core_get_match_desc()β returns an equality match descriptor for the core info incore. The returned descriptor will match only on core attributes identical to those defined bycore.bhnd_cores_equal()β is a convenience wrapper forbhnd_core_matches()andbhnd_core_get_match_desc(). This function returnstrueif thebhnd_core_infostructureslhsandrhsare equal. Otherwise, it returnsfalse.bhnd_match_core()β returns a pointer to the first entry in the arraycoresof lengthnum_coresthat matchesdesc. If no matching core is found,NULLis returned.
A bhnd_board_match match descriptor may be initialized using one or more of the following macros:
BHND_MATCH_BOARD_VENDOR(vendor)β Match on boards with a vendor equal tovendor.BHND_MATCH_BOARD_TYPE(type)β Match on boards with a type equal toBHND_BOARD_ ## typeBHND_MATCH_SROMREV(sromrev)β Match on boards with asromrevthat matchesBHND_HWREV_ ## sromrev.BHND_MATCH_BOARD_REV(hwrev)β Match on boards with hardware revisions that matchBHND_ ## hwrev.BHND_MATCH_BOARD(vendor, type)β A convenience wrapper forBHND_MATCH_BOARD_VENDOR()andBHND_MATCH_BOARD_TYPE().
For example:
struct bhnd_board_match board_desc = {
BHND_MATCH_BOARD_VENDOR(BHND_MFGID_BROADCOM),
BHND_MATCH_BOARD_TYPE(BCM94360X52C),
BHND_MATCH_BOARD_REV(HWREV_ANY),
BHND_MATCH_SROMREV(RANGE(0, 10))
};
A bhnd_chip_match match descriptor may be initialized using one or more of the following macros:
BHND_MATCH_CHIP_ID(id)β Match on chips with an ID equal toBHND_CHIPID_ ## idBHND_MATCH_CHIP_REV(hwrev)β Match on chips with hardware revisions that matchBHND_ ## hwrev.BHND_MATCH_CHIP_PKG(pkg)β Match on chips with a package ID equal toBHND_PKGID_ ## pkgBHND_MATCH_CHIP_TYPE(type)β Match on chips with a chip type equal toBHND_CHIPTYPE_ ## typeBHND_MATCH_CHIP_IP(id, pkg)β A convenience wrapper forBHND_MATCH_CHIP_ID()andBHND_MATCH_CHIP_PKG().BHND_MATCH_CHIP_IPR(id, pkg, hwrev)β A convenience wrapper forBHND_MATCH_CHIP_ID(),BHND_MATCH_CHIP_PKG(), andBHND_MATCH_CHIP_REV().BHND_MATCH_CHIP_IR(id, hwrev)β A convenience wrapper forBHND_MATCH_CHIP_ID()andBHND_MATCH_CHIP_REV().
For example:
struct bhnd_chip_match chip_desc = {
BHND_MATCH_CHIP_IP(BCM4329, BCM4329_289PIN),
BHND_MATCH_CHIP_TYPE(SIBA)
};
A bhnd_core_match match descriptor may be initialized using one or more of the following macros:
BHND_MATCH_CORE_VENDOR(vendor)β Match on cores with a vendor ID equal tovendorBHND_MATCH_CORE_ID(id)β Match on cores with a device ID equal toidBHND_MATCH_CORE_REV(hwrev)β Match on cores with hardware revisions that matchBHND_ ## hwrev.BHND_MATCH_CORE_CLASS(class)β Match on cores with a core device class equal toclassBHND_MATCH_CORE_IDX(idx)β Match on cores with a core index equal toidxBHND_MATCH_CORE_UNIT(unit)β Match on cores with a core unit equal tounitBHND_MATCH_CORE(vendor, id)β A convenience wrapper forBHND_MATCH_CORE_VENDOR()andBHND_MATCH_CORE_ID().
For example:
struct bhnd_core_match core_desc = {
BHND_MATCH_CORE(BHND_MFGID_BROADCOM, BHND_COREID_CC),
BHND_MATCH_CORE_REV(HWREV_RANGE(0, 10))
};
The bhnd_device_match match descriptor supports matching on all board, chip, and core attributes, and may be initialized using any of the bhnd_board_match, bhnd_chip_match, or bhnd_core_match macros.
For example:
struct bhnd_device_match device_desc = {
BHND_MATCH_CHIP_IP(BCM4329, BCM4329_289PIN),
BHND_MATCH_BOARD_VENDOR(BHND_MFGID_BROADCOM),
BHND_MATCH_BOARD_TYPE(BCM94329AGB),
BHND_MATCH_CORE(BHND_MFGID_BROADCOM, BHND_COREID_CC),
};
A bhnd_hwrev_match match descriptor may be initialized using one of the following macros:
BHND_HWREV_ANYβ Matches any hardware revision.BHND_HWREV_EQ(hwrev)β Matches any hardware revision equal tohwrevBHND_HWREV_GTE(hwrev)β Matches any hardware revision greater than or equal tohwrevBHND_HWREV_LTE(hwrev)β Matches any hardware revision less than or equal tohwrevBHND_HWREV_RANGE(start, end)β Matches any hardware revision within an inclusive range. IfBHND_HWREV_INVALIDis specified as theendvalue, will match on any revision equal to or greater thanstart
π Device Table Functions π
The bhnd device table functions are used to query device and quirk tables. Itβs lowkey the lookup squad. π¦
bhnd_device_lookup()β returns a pointer to the first entry in device tabletablethat matches the devicedev. The table entry size is specified byentry_size.bhnd_device_quirks()β scans the device tabletablefor all quirk entries that match the devicedev, returning the bitwise OR of all matching quirk flags. The table entry size is specified byentry_size.
The bhnd_device structure contains the following fields:
coreβ Abhnd_device_matchdescriptor.descβ A verbose device description suitable for use withdevice_set_desc(9), orNULL.quirks_tableβ The quirks table for this device, orNULL.device_flagsβ The device flags required when matching this entry.
The following device flags are supported:
BHND_DF_ANYβ Match on any device.BHND_DF_HOSTBβ Match only if the device is thebhndb(4)host bridge. ImpliesBHND_DF_ADAPTER.BHND_DF_SOCβ Match only if the device is attached to a native SoC backplane.BHND_DF_ADAPTERβ Match only if the device is attached to abhndb(4)bridged backplane.
A bhnd_device table entry may be initialized using one of the following macros:
BHND_DEVICE(vendor, device, desc, quirks, flags)β Match on devices with a vendor ID equal toBHND_MFGID_ ## vendorand a core device ID equal toBHND_COREID_ ## device.
The device's verbose description is specified by the desc argument, a pointer to the device-specific quirks table is specified by the quirks argument, and any required device flags may be provided in flags. The optional flags argument defaults to BHND_DF_ANY if omitted.
BHND_DEVICE_ENDβ Terminate thebhnd_devicetable.
For example:
struct bhnd_device bhnd_usb11_devices[] = {
BHND_DEVICE(BCM, USB, "Broadcom USB1.1 Controller",
bhnd_usb11_quirks),
BHND_DEVICE_END
};
The bhnd_device_quirk structure contains the following fields:
descβ Abhnd_device_matchdescriptor.quirksβ Applicable quirk flags.
A bhnd_device_quirk table entry may be initialized using one of the following convenience macros:
BHND_BOARD_QUIRK(board, flags)β Set quirk flagsflagson devices with a board type equal toBHND_BOARD_ ## board.BHND_CHIP_QUIRK(chip, hwrev, flags)β Set quirk flagsflagson devices with a chip ID equal toBHND_CHIPID_BCM ## chipand chip hardware revision that matchesBHND_ ## hwrev.
okay so, picking up mid-flow with the quirk macros β these are the little matchmakers that slap quirk flags onto the right devices π
BHND_PKG_QUIRK(chip, pkg, flags")β sets the quirk flagsflagson devices with a chip ID equal toBHND_CHIPID_BCM ## chipand chip package equal toBHND_ ## chip ## pkg.BHND_CORE_QUIRK(hwrev, flags")β sets the quirk flagsflagson devices with a core hardware revision that matchesBHND_ ## hwrev.
For example, bestie:
struct bhnd_device_quirk bhnd_usb11_quirks[] = {
BHND_DEVICE(BCM, USB, "Broadcom USB1.1 Controller",
bhnd_usb11_quirks),
BHND_DEVICE_END
};
β¨ DMA Address Translation Functions β¨
bhnd_get_dma_translation() is the function you call when you want a DMA address translation descriptor that works with a maximum DMA address width of width, and that supports the translation flags you asked for. π«Ά
If a suitable DMA address translation descriptor is found, it gets stored in translation, and a bus DMA tag specifying the DMA translation's address restrictions gets stored in dmat. The translation and dmat arguments may be NULL if you don't want the translation descriptor or DMA tag. No pressure.
The following DMA translation flags are supported:
BHND_DMA_TRANSLATION_PHYSMAPβ the translation remaps the device's physical address space. This is used in conjunction withBHND_DMA_TRANSLATION_BYTESWAPPEDto define a DMA translation that provides byteswapped access to physical memory on big-endian MIPS SoCs.BHND_DMA_TRANSLATION_BYTESWAPPEDβ the translation provides a byte-swapped mapping; write requests will be byte-swapped before being written to memory, and read requests will be byte-swapped before being returned. This is primarily used to perform efficient byte swapping of DMA data on embedded MIPS SoCs executing in big-endian mode.
The following symbolic constants are defined for common DMA address widths:
BHND_DMA_ADDR_30BITβ 30-bit DMABHND_DMA_ADDR_32BITβ 32-bit DMABHND_DMA_ADDR_64BITβ 64-bit DMA
The bhnd_dma_translation structure contains the following fields:
base_addrβ Host-to-device physical address translation. This may be added to a host physical address to produce a device DMA address.addr_maskβ Device-addressable address mask. This defines the device DMA address range, and excludes any bits reserved for mapping the address within the translation window atbase_addr.addrext_maskβ Device-addressable extended address mask. If the per-core BHND DMA engine supports theaddrextcontrol field, it can be used to provide address bits excluded byaddr_mask. Support for DMA extended address changes β including coordination with the core providing device-to-host DMA address translation β is handled transparently by the DMA engine. For example, on PCI Wi-Fi devices, the Wi-Fi core's DMA engine will (in effect) update the PCI host bridge core's DMAsbtopcitranslationbase address to map the target address prior to performing a DMA transaction.flagsβ Translation flags.
β¨ Interrupt Functions β¨
bhnd_get_intr_count() is used to determine the number of backplane interrupt lines assigned to the device dev. Interrupt line identifiers are allocated in monotonically increasing order, starting with 0.
bhnd_get_intr_ivec() is used to determine the backplane interrupt vector assigned to interrupt line intr on the device dev, writing the result to ivec. Interrupt vector assignments are backplane-specific: on BCMA devices, this function returns the OOB bus line assigned to the interrupt. On SIBA devices, it returns the target OCP slave flag number assigned to the interrupt.
bhnd_map_intr() is used to map interrupt line intr assigned to device dev to an IRQ number, writing the result to irq. Until unmapped, this IRQ may be used when allocating a resource of type SYS_RES_IRQ.
Ownership of the interrupt mapping is assumed by the caller, and must be explicitly released using bhnd_unmap_intr.
bhnd_unmap_intr() is used to unmap bus IRQ irq previously mapped using bhnd_map_intr() by the device dev.
β¨ NVRAM Functions β¨
bhnd_nvram_getvar() is used to read the value of NVRAM variable name from the NVRAM provider(s) registered with the parent bhnd(4) bus of device dev, coerced to the desired data representation type, and written to the buffer specified by buf.
Before the call, the maximum capacity of buf is specified by len. After a successful call β or if ENOMEM is returned β the size of the available data will be written to len. The size of the desired data representation can be determined by calling bhnd_nvram_getvar() with a NULL argument for buf.
The following NVRAM data types are supported:
BHND_NVRAM_TYPE_UINT8β unsigned 8-bit integerBHND_NVRAM_TYPE_UINT16β unsigned 16-bit integerBHND_NVRAM_TYPE_UINT32β unsigned 32-bit integerBHND_NVRAM_TYPE_UINT64β signed 64-bit integerBHND_NVRAM_TYPE_INT8β signed 8-bit integerBHND_NVRAM_TYPE_INT16β signed 16-bit integerBHND_NVRAM_TYPE_INT32β signed 32-bit integerBHND_NVRAM_TYPE_INT64β signed 64-bit integerBHND_NVRAM_TYPE_CHARβ UTF-8 characterBHND_NVRAM_TYPE_STRINGβ UTF-8 NUL-terminated stringBHND_NVRAM_TYPE_BOOLβ uint8 boolean valueBHND_NVRAM_TYPE_NULLβ NULL (empty) valueBHND_NVRAM_TYPE_DATAβ opaque octet stringBHND_NVRAM_TYPE_UINT8_ARRAYβ array of uint8 integersBHND_NVRAM_TYPE_UINT16_ARRAYβ array of uint16 integersBHND_NVRAM_TYPE_UINT32_ARRAYβ array of uint32 integersBHND_NVRAM_TYPE_UINT64_ARRAYβ array of uint64 integersBHND_NVRAM_TYPE_INT8_ARRAYβ array of int8 integersBHND_NVRAM_TYPE_INT16_ARRAYβ array of int16 integersBHND_NVRAM_TYPE_INT32_ARRAYβ array of int32 integersBHND_NVRAM_TYPE_INT64_ARRAYβ array of int64 integersBHND_NVRAM_TYPE_CHAR_ARRAYβ array of UTF-8 charactersBHND_NVRAM_TYPE_STRING_ARRAYβ array of UTF-8 NUL-terminated stringsBHND_NVRAM_TYPE_BOOL_ARRAYβ array of uint8 boolean values
And the convenience wrappers for bhnd_nvram_getvar() are: bhnd_nvram_getvar_array(), bhnd_nvram_getvar_int(), bhnd_nvram_getvar_int8(), bhnd_nvram_getvar_int16(), bhnd_nvram_getvar_int32(), bhnd_nvram_getvar_uint(), bhnd_nvram_getvar_uint8(), bhnd_nvram_getvar_uint16(), bhnd_nvram_getvar_uint32(), and bhnd_nvram_getvar_str().
bhnd_nvram_getvar_array() returns either a value of exactly size in buf, or returns an error code of ENXIO if the data representation is not exactly size in length.
bhnd_nvram_getvar_int() and bhnd_nvram_getvar_uint() return the value of NVRAM variable name, coerced to a signed or unsigned integer type of width (1, 2, or 4 bytes).
bhnd_nvram_getvar_int8(), bhnd_nvram_getvar_int16(), bhnd_nvram_getvar_int32(), bhnd_nvram_getvar_uint(), bhnd_nvram_getvar_uint8(), bhnd_nvram_getvar_uint16(), and bhnd_nvram_getvar_uint32() return the value of NVRAM variable name, coerced to a signed or unsigned 8, 16, or 32-bit integer type.
bhnd_nvram_getvar_str() returns the value of NVRAM variable name, coerced to a NUL-terminated string.
bhnd_nvram_string_array_next() iterates over all strings in the inp BHND_NVRAM_TYPE_STRING_ARRAY value. The size of inp, including any terminating NUL character(s), is specified using the ilen argument. The prev argument should be either a string pointer previously returned by bhnd_nvram_string_array_next(), or NULL to begin iteration. If prev is not NULL, the olen argument must be a pointer to the length previously returned by bhnd_nvram_string_array_next(). On success, the next string element's length will be written to this pointer.
β¨ Port/Region Functions β¨
Per-device interconnect memory mappings are identified by a combination of port type, port number, and region number. Port and memory region identifiers are allocated in monotonically increasing order for each port type, starting with 0. Slay.
The following port types are supported:
BHND_PORT_DEVICEβ Device memory. The device's control/status registers are always mapped by the first device port and region, and will be assigned aSYS_RES_MEMORYresource ID of0.BHND_PORT_BRIDGEβ Bridge memory.BHND_PORT_AGENTβ Interconnect agent/wrapper.
bhnd_decode_port_rid() is used to decode the resource ID rid assigned to device dev, of resource type type, writing the port type to port_type, port number to port, and region number to region.
bhnd_get_port_count() returns the number of ports of type type assigned to device dev.
bhnd_get_port_rid() returns the resource ID for the SYS_RES_MEMORY resource mapping the port of type and region on device dev, or -1 if the port or region are invalid, or do not have an assigned resource ID.
bhnd_get_region_addr() is used to determine the base address and size of the memory region on port of type assigned to dev. The region's base device address will be written to region_addr, and the region size to region_size.
bhnd_get_region_count() returns the number of memory regions mapped to port of type on device dev.
bhnd_is_region_valid() returns true if region is a valid region mapped by port of type on device dev.
β¨ Power Management Functions β¨
Drivers must ask the parent bhnd(4) bus to allocate device PMU state using bhnd_alloc_pmu() before calling any other bhnd PMU functions. literally, do that first. π§
bhnd_alloc_pmu() is used to allocate per-device PMU state and enable PMU request handling for device dev. The memory region containing the device's PMU register block must be allocated using bus_alloc_resource(9) or bhnd_alloc_resource() before calling bhnd_alloc_pmu(), and must not be released until after calling bhnd_release_pmu().
highkey important: that memory region stays allocated until after bhnd_release_pmu() β no early release, bestie.
On all supported BHND hardware, the PMU register block is mapped by the device's control/status registers in the first device port and region.
The bhnd_release_pmu() function is the cleanup bestie for the per-device PMU state that was previously allocated for device dev using bhnd_alloc_pmu(). Any outstanding clock and external resource requests will be discarded when the device PMU state is released. π
The bhnd_enable_clocks() function is used to request that clocks be powered up and routed to the backplane on behalf of device dev. This will power any clock sources required (e.g., XTAL, PLL, etc) and wait until the requested clocks are stable. If the request succeeds, any previous clock requests issued by dev will be discarded. β¨
The following clocks are supported, and may be combined using bitwise OR to request multiple clocks:
BHND_CLOCK_DYNβ Dynamically select an appropriate clock source based on all outstanding clock requests by any device attached to the parentbhnd(4)bus.BHND_CLOCK_ILPβ Idle Low-Power (ILP) Clock. May be used if no register access is required, or long request latency is acceptable.BHND_CLOCK_ALPβ Active Low-Power (ALP) Clock. Supports low-latency register access and low-rate DMA.BHND_CLOCK_HTβ High Throughput (HT) Clock. Supports high bus throughput and lowest-latency register access.
The bhnd_request_clock() function is used to request that clock (or faster) be powered up and routed to device dev.
The bhnd_get_clock_freq() function is used to request the current clock frequency of clock, writing the frequency in Hz to freq.
The bhnd_get_clock_latency() function is used to determine the transition latency required for clock, writing the latency in microseconds to latency. The BHND_CLOCK_HT latency value is suitable for use as the D11 Wi-Fi core fastpwrup_dly value.
The bhnd_request_ext_rsrc() function is used to request that the external PMU-managed resource assigned to device dev, identified by device-specific identifier rsrc, be powered up. π«Ά
The bhnd_release_ext_rsrc() function releases any outstanding requests by device dev for the PMU-managed resource identified by device-specific identifier rsrc. If an external resource is shared by multiple devices, it will not be powered down until all device requests are released. No cap. π₯
π Service Provider Functions π
The bhnd_register_provider() function is used to register device dev as a provider for platform service with the parent bhnd(4) bus. π
The following service types are supported:
BHND_SERVICE_CHIPCβ ChipCommon service. The providing device must implement thebhnd_chipcinterface.BHND_SERVICE_PWRCTLβ Legacy PWRCTL service. The providing device must implement thebhnd_pwrctlinterface.BHND_SERVICE_PMUβ PMU service. The providing device must implement thebhnd_pmuinterface.BHND_SERVICE_NVRAMβ NVRAM service. The providing device must implement thebhnd_nvraminterface.BHND_SERVICE_GPIOβ GPIO service. The providing device must implement the standardgpio(4)interface.BHND_SERVICE_ANYβ Matches on any service type. May be used withbhnd_deregister_provider()to remove all service provider registrations for a device.
The bhnd_deregister_provider() function attempts to remove provider registration for the device dev and service. If a service argument of BHND_SERVICE_ANY is specified, this function will attempt to remove all service provider registrations for dev.
The bhnd_retain_provider() function retains and returns a reference to the provider registered for service with the parent bhnd(4) bus of device dev, if available. On success, the caller is responsible for releasing this provider reference using bhnd_release_provider(). The service provider is guaranteed to remain available until the provider reference is released.
The bhnd_release_provider() function releases a reference to a provider for service, previously retained by device dev using bhnd_retain_provider().
π§ Utility Functions π§
The bhnd_driver_get_erom_class() function returns the bhnd_erom(9) class for the device enumeration table format used by bhnd(4) bus driver instance driver. If the driver does not support bhnd_erom(9) device enumeration, NULL is returned.
The bhnd_find_core_class() function looks up the BHND class, if known, for the BHND vendor ID vendor and device ID device.
The bhnd_find_core_name() function is used to fetch the human-readable name, if known, for the BHND core with a vendor ID of vendor and device ID of device.
The bhnd_core_class() and bhnd_core_name() functions are convenience wrappers for bhnd_find_core_class() and bhnd_find_core_name(), that use the vendor and device fields of the core info structure ci.
The bhnd_format_chip_id() function writes a NUL-terminated human-readable representation of the BHND chip_id value to the specified buffer with a capacity of size. No more than size-1 characters will be written, with the size'th character set to '\0'. A buffer size of BHND_CHIPID_MAX_NAMELEN is sufficient for any string representation produced using bhnd_format_chip_id().
The bhnd_set_custom_core_desc() function uses the bhnd(4) device identification of dev, overriding the core name with the specified dev_name, to populate the device's verbose description using device_set_desc(9).
The bhnd_set_default_core_desc() function uses the bhnd(4) device identification of dev to populate the device's verbose description using device_set_desc(9).
The bhnd_vendor_name() function returns the human-readable name for the JEP-106, ARM 4-bit continuation encoded manufacturer ID vendor, if known. π¦
π₯ RETURN VALUES π₯
π Bus Resource Functions π
The bhnd_activate_resource(), bhnd_alloc_resources(), bhnd_deactivate_resource(), and bhnd_release_resource() functions return 0 on success, otherwise an appropriate error code is returned.
The bhnd_alloc_resource() and bhnd_alloc_resource_any() functions return a pointer to struct resource on success, a null pointer otherwise.
βοΈ Device Configuration Functions βοΈ
The bhnd_read_config() and bhnd_write_config() functions return 0 on success, or one of the following values on error:
[EINVAL]β The device is not a direct child of thebhnd(4)bus[EINVAL]β The requested width is not one of 1, 2, or 4 bytes.[ENODEV]β Accessing agent/config space for the device is unsupported.[EFAULT]β The requested offset or width exceeds the bounds of the mapped agent/config space.
The bhnd_read_ioctl(), bhnd_write_ioctl(), bhnd_read_iost(), bhnd_reset_hw(), and bhnd_suspend_hw() functions return 0 on success, otherwise an appropriate error code is returned.
π Device Information Functions π
The bhnd_read_board_info() function returns 0 on success, otherwise an appropriate error code is returned.
π§ DMA Address Translation Functions π§
The bhnd_get_dma_translation() function returns 0 on success, or one of the following values on error:
[ENODEV]β DMA is not supported.[ENOENT]β No DMA translation matching the requested address width and translation flags is available.
If fetching the requested DMA address translation otherwise fails, an appropriate error code will be returned.
β‘ Interrupt Functions β‘
The bhnd_get_intr_ivec() function returns 0 on success, or ENXIO if the requested interrupt line exceeds the number of interrupt lines assigned to the device.
The bhnd_map_intr() function returns 0 on success, otherwise an appropriate error code is returned.
π NVRAM Functions π
The bhnd_nvram_getvar(), bhnd_nvram_getvar_array(), bhnd_nvram_getvar_int(), bhnd_nvram_getvar_int8(), bhnd_nvram_getvar_int16(), bhnd_nvram_getvar_int32(), bhnd_nvram_getvar_uint(), bhnd_nvram_getvar_uint8(), bhnd_nvram_getvar_uint16(), and bhnd_nvram_getvar_uint32() functions return 0 on success, or one of the following values on error:
[ENODEV]β If an NVRAM provider has not been registered with the bus.[ENOENT]β The requested variable was not found.[ENOMEM]β If the buffer ofsizeis too small to hold the requested value.[EOPNOTSUPP]β If the value's native type is incompatible with and cannot be coerced to the requested type.[ERANGE]β If value coercion would overflow (or underflow) the requested type
If reading the variable otherwise fails, an appropriate error code will be returned.
πͺ Port/Region Functions πͺ
The bhnd_decode_port_rid() function returns 0 on success, or an appropriate error code if no matching port/region is found.
The bhnd_get_port_rid() function returns the resource ID for the requested port and region, or -1 if the port or region are invalid, or do not have an assigned resource ID.
The bhnd_get_region_addr() function returns 0 on success, or an appropriate error code if no matching port/region is found.
π PMU Functions π
The bhnd_alloc_pmu() function returns 0 on success, otherwise an appropriate error code is returned.
The bhnd_release_pmu() function returns 0 on success, otherwise an appropriate error code is returned, and the core state will be left unmodified.
The bhnd_enable_clocks() and bhnd_request_clock() functions return 0 on success, or one of the following values on error:
[ENODEV]β An unsupported clock was requested.[ENXIO]β No PMU or PWRCTL provider has been registered with the bus.
The bhnd_get_clock_freq() function returns 0 on success, or ENODEV if the frequency for the specified clock is not available.
The bhnd_get_clock_latency() function returns 0 on success, or ENODEV if the transition latency for the specified clock is not available.
The bhnd_request_ext_rsrc() and bhnd_release_ext_rsrc() functions return 0 on success, otherwise an appropriate error code is returned.
π«Ά Service Provider Functions π«Ά
The bhnd_register_provider() function returns 0 on success, EEXIST if an entry for service already exists, or an appropriate error code if service registration otherwise fails.
The bhnd_deregister_provider() function returns 0 on success, or EBUSY if active references to the service provider exist.
The bhnd_retain_provider() function returns a pointer to device_t on success, a null pointer if the requested provider is not registered.
π οΈ Utility Functions π οΈ
The bhnd_format_chip_id() function returns the total number of bytes written on success, or a negative integer on failure.
π SEE ALSO π
π AUTHORS π
okay so this whole entire thing β the bhnd driver programming interface and the manual page you're reading right now β was written by Landon Fuller <landonf@FreeBSD.org> π«Άβ¨
like, both of them. the code and the docs. main character energy fr fr π
and that's a wrap bestie!! π this page is from the Debian build, dated March 26, 2018, and it lives at BHND(9) in the manual β go forth and slay your Broadcom bhnd adventures π
πΈπ
π¦ where this page comes from
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
- Copyright (c) 2017 The FreeBSD Foundation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms