BHND_EROM(9)
BHND_EROM π (section 9, Kernel Developer's Manual)
okay bestie, sit down, hydrate, because we're about to talk about bhnd_erom β the BHND device enumeration table parsing framework. she's a kernel developer's manual girlie, she lives in section 9, and she's honestly so iconic. no cap. π
β¨ NAME β¨
so like, this whole squad right here:
bhnd_erom, bhnd_erom_alloc, bhnd_erom_dump, bhnd_erom_fini_static, bhnd_erom_free, bhnd_erom_free_core_table, bhnd_erom_get_core_table, bhnd_erom_init_static, bhnd_erom_io, bhnd_erom_io_fini, bhnd_erom_io_map, bhnd_erom_io_read, bhnd_erom_iobus_init, bhnd_erom_iores_new, bhnd_erom_lookup_core, bhnd_erom_lookup_core_addr, bhnd_erom_probe, bhnd_erom_probe_driver_classes
...are all here to do exactly one thing: BHND device enumeration table parsing. periodt. π
πΈ SYNOPSIS πΈ
#include <dev/bhnd/bhnd.h>
#include <dev/bhnd/bhnd_erom.h>
typedef struct bhnd_erom bhnd_erom_t;
typedef struct kobj_class bhnd_erom_class_t;
typedef struct bhnd_erom_static bhnd_erom_static_t;
int
bhnd_erom_probe(bhnd_erom_class_t *cls, struct bhnd_erom_io *eio,
const struct bhnd_chipid *hint, struct bhnd_chipid *cid);
bhnd_erom_class_t *
bhnd_erom_probe_driver_classes(devclass_t bus_devclass,
struct bhnd_erom_io *eio, const struct bhnd_chipid *hint,
struct bhnd_chipid *cid);
bhnd_erom_t *
bhnd_erom_alloc(bhnd_erom_class_t *cls, const struct bhnd_chipid *cid,
struct bhnd_erom_io *eio);
void
bhnd_erom_free(bhnd_erom_t *erom);
int
bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom,
size_t esize, const struct bhnd_chipid *cid,
struct bhnd_erom_io *eio);
void
bhnd_erom_fini_static(bhnd_erom_t *erom);
int
bhnd_erom_dump(bhnd_erom_t *erom);
int
bhnd_erom_get_core_table(bhnd_erom_t *erom,
struct bhnd_core_info **cores, u_int *num_cores);
void
bhnd_erom_free_core_table(bhnd_erom_t *erom,
struct bhnd_core_info *cores);
int
bhnd_erom_lookup_core(bhnd_erom_t *erom,
const struct bhnd_core_match *desc, struct bhnd_core_info *core);
int
bhnd_erom_lookup_core_addr(bhnd_erom_t *erom,
const struct bhnd_core_match *desc, bhnd_port_type type, u_int port,
u_int region, struct bhnd_core_info *core, bhnd_addr_t *addr,
bhnd_size_t *size);
π¦ Bus Space I/O π¦
struct bhnd_erom_io *
bhnd_erom_iores_new(device_t dev, int rid);
int
bhnd_erom_iobus_init(struct bhnd_erom_iobus *iobus, bhnd_addr_t addr,
bhnd_size_t size, bus_space_tag_t bst, bus_space_handle_t bsh);
void
bhnd_erom_io_fini(struct bhnd_erom_io *eio);
int
bhnd_erom_io_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
bhnd_size_t size);
uint32_t
bhnd_erom_io_read(struct bhnd_erom_io *eio, bhnd_size_t offset,
u_int width);
#include <dev/bhnd/bhnd_eromvar.h>
struct bhnd_erom_io {
bhnd_erom_io_map_t *map;
bhnd_erom_io_read_t *read;
bhnd_erom_io_fini_t *fini;
};
typedef int
(bhnd_erom_io_map_t)(struct bhnd_erom_io *eio, bhnd_addr_t addr,
bhnd_size_t size);
typedef uint32_t
(bhnd_erom_io_read_t)(struct bhnd_erom_io *eio, bhnd_size_t offset,
u_int width);
typedef void
(bhnd_erom_io_fini_t)(struct bhnd_erom_io *eio);
π DESCRIPTION π
so the bhnd_erom framework is literally giving "one common parser interface to rule them all" β it's the shared interface to the BHND device enumeration table formats that bhnd(4) bus drivers support. she's a unifier. a connector. a main character. π
The bhnd_erom_probe() function is how you figure out whether a bhnd(4) bus device is actually a bhnd(4) bus device, and whether the erom class cls can parse its device enumeration table. slay. If it works out, the probed chip identification gets written to wherever cid points. π«Ά
You have to hand over a pointer to a bus I/O instance that maps the device registers of the first hardware core, and that goes in the eio argument. You can map those registers with bhnd_erom_io_map(9).
okay but listen β on devices that don't provide standardbhnd_chipc(4)chip identification registers through that first hardware core, you must pass a pointer to chip information for the device via thehintargument. Otherwisehintshould beNULL. don't skip this one bestie, it's not optional.
The bhnd_erom_probe_driver_classes() function is just a lil convenience wrapper around bhnd_erom_probe() β she's doing the most so you don't have to. She iterates over all driver instances in the device class bus_devclass, using bhnd_driver_get_erom_class(9) to grab each driver's erom class and probe the hardware core mapped by eio. On success you get back a pointer to the erom class with the highest probe priority (queen behavior tbh π). If literally none of the erom classes probe successfully, she returns NULL. it's giving "no thoughts, empty result".
The bhnd_erom_alloc() function allocates and returns a brand new parser instance of the device enumeration class cls, for the chip identified by cid, and it uses the bus I/O instance eio to map and read the device table. On success, the returned bhnd_erom_t assumes ownership of eio. she said "mine now". π
The bhnd_erom_free() function releases all resources held by an erom parser that was successfully allocated with bhnd_erom_alloc(). clean up after yourself, bestie.
If you're the DIY type, clients can manage memory allocation themselves with bhnd_erom_init_static(). This is genuinely useful in cases like performing device enumeration before malloc(9) initialization (yes, that's a real situation, and yes, it's stressful π). You call bhnd_erom_init_static() with erom set to a pointer to the memory for the instance, and esize set to the total available bytes.
The bhnd_erom_static structure is large enough to statically allocate any supported parser class instance state. Pointers to a bhnd_erom_static structure can be cast to bhnd_erom_t. casting icon behavior β¨
The bhnd_erom_fini_static() function releases all resources held by an erom parser that was successfully initialized using bhnd_erom_init_static().
The bhnd_erom_dump() function enumerates and prints all device table entries in erom. it's a full reveal. π
The bhnd_erom_get_core_table() function enumerates all device table entries in erom and returns a table of core information structures in cores, plus the count in num_cores. The memory allocated for that table must be freed using bhnd_erom_free_core_table(). don't forget. I'm watching. π
The bhnd_erom_free_core_table() function frees any memory allocated in a previous call to bhnd_erom_get_core_table(). that's it, that's her job, and she does it flawlessly.
The bhnd_erom_lookup_core() function locates the first device table entry in erom that matches the core match descriptor desc, and writes the core information of the matching entry to core. first come, first served, she's not scrolling further. π
The bhnd_erom_lookup_core_addr() function locates the first device table entry in erom matching the core match descriptor desc, and fetches the base address and size of the memory region region mapped to the port port of type type. On success: the core information of the matching entry goes to core, the base address of the port region goes to addr, and the total size of the port region goes to size. If you don't actually want the core info, just set core to NULL. low maintenance. we love that. π¦
π Bus Space I/O π
The bhnd_erom_io structure provides a set of I/O callbacks that bhnd_erom uses to map and read the device enumeration table. Clients have two options: use the existing bhnd_erom_iores_new() or bhnd_erom_iobus_init() functions to allocate a bus I/O instance, or implement the bhnd_erom_io callbacks directly. choose your fighter. β¨
The bhnd_erom_io structure contains these required fields:
mapβ a function implementingbhnd_erom_io_map().readβ a function implementingbhnd_erom_io_read().finiβ a function implementingbhnd_erom_io_fini().
The bhnd_erom_iores_new() function allocates and returns a new bus I/O instance that performs mapping by using bhnd_alloc_resource(9) to allocate SYS_RES_MEMORY bus resources on demand from the device dev, using a resource ID of rid. she's on-demand, she's efficient, she's booked and busy.
The bhnd_erom_iobus_init() function initializes a caller-allocated bus I/O instance iobus that will perform bus I/O using the bus space tag bst and handle bsh. The base address and total size mapped by bsh should be specified using the addr and size arguments.
The bhnd_erom_io_fini() function frees all resources held by the bus I/O instance eio.
The bhnd_erom_io_map() function is how you request that the bus I/O instance eio map bhnd(4) bus space at bus address addr with a mapping of size size.
The bhnd_erom_io_read() function reads a data item of width bytes from the bus I/O instance eio at offset, relative to the bus address previously mapped using bhnd_erom_io_map().
β οΈwidthmust be one of1,2, or4bytes. that's the whole menu. no substitutions, no custom orders, bestie.
π RETURN VALUES π
The bhnd_erom_probe() function returns a standard DEVICE_PROBE(9) result. here's the vibe check:
- A return value equal to or less than zero means success.
- Values greater than zero mean an error, and it'll be an appropriate error code.
- For values less than or equal to zero, the erom class returning the highest value is the one you should use to parse the erom table. π
ENXIOis returned if the device is not supported by the parser. (not her problem, respectfully.)
The bhnd_erom_probe_driver_classes() function returns a pointer to the probed bhnd_erom_class_t instance on success, and a null pointer otherwise.
The bhnd_erom_alloc() function returns a pointer to bhnd_erom_t on success, or NULL if an error happened while allocating or initializing the EROM parser.
The bhnd_erom_init_static() function returns 0 on success, ENOMEM if the allocation size is smaller than required by the erom class, or an appropriate error code if initialization otherwise fails. size matters, apparently. π
The bhnd_erom_lookup_core() function returns 0 on success, ENOENT if no matching core is found (ghosted fr fr π), or an appropriate error code if parsing the device table otherwise fails.
The bhnd_erom_dump(), bhnd_erom_get_core_table(), bhnd_erom_iobus_init(), bhnd_erom_io_map() functions return 0 on success, otherwise an appropriate error code is returned. π
π«Ά SEE ALSO π«Ά
go read those too, bestie. iykyk. π
π AUTHORS π
The bhnd_erom framework and this manual page were written by Landon Fuller <landonf@FreeBSD.org>. an absolute legend, we stan. π
and that's the whole page!! this cutie is from the Debian distribution and she's dated November 9, 2017 π β mwah, love her, go parse some enumeration tables bestie π β¨π¦
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org>
- Copyright (c) 2017 The FreeBSD Foundation
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms