Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/bhnd/bhnd_subr.c
Show All 24 Lines | |||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||||
* THE POSSIBILITY OF SUCH DAMAGES. | * THE POSSIBILITY OF SUCH DAMAGES. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/types.h> | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
▲ Show 20 Lines • Show All 834 Lines • ▼ Show 20 Lines | |||||
cleanup: | cleanup: | ||||
/* Clean up */ | /* Clean up */ | ||||
bus_release_resource(dev, rtype, rid, res); | bus_release_resource(dev, rtype, rid, res); | ||||
return (error); | return (error); | ||||
} | } | ||||
/** | /** | ||||
* Read an NVRAM variable's NUL-terminated string value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] buf A buffer large enough to hold @p len bytes. On | |||||
* success, the NUL-terminated string value will be | |||||
* written to this buffer. This argment may be NULL if | |||||
* the value is not desired. | |||||
* @param len The maximum capacity of @p buf. | |||||
* @param[out] rlen On success, will be set to the actual size of | |||||
* the requested value (including NUL termination). This | |||||
* argment may be NULL if the size is not desired. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval ENOMEM If @p buf is non-NULL and a buffer of @p len is too | |||||
* small to hold the requested value. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a valid | |||||
* string representation. | |||||
* @retval ERANGE If value coercion would overflow @p type. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_str(device_t dev, const char *name, char *buf, size_t len, | |||||
size_t *rlen) | |||||
{ | |||||
size_t larg; | |||||
int error; | |||||
larg = len; | |||||
error = bhnd_nvram_getvar(dev, name, buf, &larg, BHND_NVRAM_TYPE_CSTR); | |||||
if (rlen != NULL) | |||||
*rlen = larg; | |||||
return (error); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's unsigned integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* @param width The output integer type width (1, 2, or | |||||
* 4 bytes). | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid unsigned integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) an | |||||
* unsigned representation of the given @p width. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_uint(device_t dev, const char *name, void *value, int width) | |||||
{ | |||||
bhnd_nvram_type type; | |||||
size_t len; | |||||
switch (width) { | |||||
case 1: | |||||
type = BHND_NVRAM_TYPE_UINT8; | |||||
break; | |||||
case 2: | |||||
type = BHND_NVRAM_TYPE_UINT16; | |||||
break; | |||||
case 4: | |||||
type = BHND_NVRAM_TYPE_UINT32; | |||||
break; | |||||
default: | |||||
device_printf(dev, "unsupported NVRAM integer width: %d\n", | |||||
width); | |||||
return (EINVAL); | |||||
} | |||||
len = width; | |||||
return (bhnd_nvram_getvar(dev, name, value, &len, type)); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's unsigned 8-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid unsigned integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) uint8_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_uint8(device_t dev, const char *name, uint8_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's unsigned 16-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid unsigned integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) | |||||
* uint16_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_uint16(device_t dev, const char *name, uint16_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's unsigned 32-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid unsigned integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) | |||||
* uint32_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_uint32(device_t dev, const char *name, uint32_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_uint(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's signed integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* @param width The output integer type width (1, 2, or | |||||
* 4 bytes). | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) an | |||||
* signed representation of the given @p width. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_int(device_t dev, const char *name, void *value, int width) | |||||
{ | |||||
bhnd_nvram_type type; | |||||
size_t len; | |||||
switch (width) { | |||||
case 1: | |||||
type = BHND_NVRAM_TYPE_INT8; | |||||
break; | |||||
case 2: | |||||
type = BHND_NVRAM_TYPE_INT16; | |||||
break; | |||||
case 4: | |||||
type = BHND_NVRAM_TYPE_INT32; | |||||
break; | |||||
default: | |||||
device_printf(dev, "unsupported NVRAM integer width: %d\n", | |||||
width); | |||||
return (EINVAL); | |||||
} | |||||
len = width; | |||||
return (bhnd_nvram_getvar(dev, name, value, &len, type)); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's signed 8-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) int8_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_int8(device_t dev, const char *name, int8_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's signed 16-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) | |||||
* int16_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_int16(device_t dev, const char *name, int16_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's signed 32-bit integer value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] value On success, the requested value will be written | |||||
* to this pointer. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid integer representation. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) | |||||
* int32_t. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_int32(device_t dev, const char *name, int32_t *value) | |||||
{ | |||||
return (bhnd_nvram_getvar_int(dev, name, value, sizeof(*value))); | |||||
} | |||||
/** | |||||
* Read an NVRAM variable's array value. | |||||
* | |||||
* @param dev A bhnd bus child device. | |||||
* @param name The NVRAM variable name. | |||||
* @param[out] buf A buffer large enough to hold @p size bytes. | |||||
* On success, the requested value will be written | |||||
* to this buffer. | |||||
* @param[in,out] size The required number of bytes to write to | |||||
* @p buf. | |||||
* @param type The desired array element data representation. | |||||
* | |||||
* @retval 0 success | |||||
* @retval ENOENT The requested variable was not found. | |||||
* @retval ENODEV No valid NVRAM source could be found. | |||||
* @retval ENXIO If less than @p size bytes are available. | |||||
* @retval ENOMEM If a buffer of @p size is too small to hold the | |||||
* requested value. | |||||
* @retval EFTYPE If the variable data cannot be coerced to a | |||||
* a valid instance of @p type. | |||||
* @retval ERANGE If value coercion would overflow (or underflow) a | |||||
* representation of @p type. | |||||
* @retval non-zero If reading @p name otherwise fails, a regular unix | |||||
* error code will be returned. | |||||
*/ | |||||
int | |||||
bhnd_nvram_getvar_array(device_t dev, const char *name, void *buf, size_t size, | |||||
bhnd_nvram_type type) | |||||
{ | |||||
size_t nbytes; | |||||
int error; | |||||
/* Attempt read */ | |||||
nbytes = size; | |||||
if ((error = bhnd_nvram_getvar(dev, name, buf, &nbytes, type))) | |||||
return (error); | |||||
/* Verify that the expected number of bytes were fetched */ | |||||
if (nbytes < size) | |||||
return (ENXIO); | |||||
return (0); | |||||
} | |||||
/** | |||||
* Using the bhnd(4) bus-level core information and a custom core name, | * Using the bhnd(4) bus-level core information and a custom core name, | ||||
* populate @p dev's device description. | * populate @p dev's device description. | ||||
* | * | ||||
* @param dev A bhnd-bus attached device. | * @param dev A bhnd-bus attached device. | ||||
* @param dev_name The core's name (e.g. "SDIO Device Core") | * @param dev_name The core's name (e.g. "SDIO Device Core") | ||||
*/ | */ | ||||
void | void | ||||
bhnd_set_custom_core_desc(device_t dev, const char *dev_name) | bhnd_set_custom_core_desc(device_t dev, const char *dev_name) | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | bhnd_bus_generic_get_chipid(device_t dev, device_t child) | ||||
if (device_get_parent(dev) != NULL) | if (device_get_parent(dev) != NULL) | ||||
return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child)); | return (BHND_BUS_GET_CHIPID(device_get_parent(dev), child)); | ||||
panic("missing BHND_BUS_GET_CHIPID()"); | panic("missing BHND_BUS_GET_CHIPID()"); | ||||
} | } | ||||
/* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ | /* nvram board_info population macros for bhnd_bus_generic_read_board_info() */ | ||||
#define BHND_GV(_dest, _name) \ | #define BHND_GV(_dest, _name) \ | ||||
bhnd_nvram_getvar(child, BHND_NVAR_ ## _name, &_dest, sizeof(_dest)) | bhnd_nvram_getvar_uint(child, BHND_NVAR_ ## _name, &_dest, \ | ||||
sizeof(_dest)) | |||||
#define REQ_BHND_GV(_dest, _name) do { \ | #define REQ_BHND_GV(_dest, _name) do { \ | ||||
if ((error = BHND_GV(_dest, _name))) { \ | if ((error = BHND_GV(_dest, _name))) { \ | ||||
device_printf(dev, \ | device_printf(dev, \ | ||||
"error reading " __STRING(_name) ": %d\n", error); \ | "error reading " __STRING(_name) ": %d\n", error); \ | ||||
return (error); \ | return (error); \ | ||||
} \ | } \ | ||||
} while(0) | } while(0) | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* This implementation searches @p dev for a usable NVRAM child device. | * This implementation searches @p dev for a usable NVRAM child device. | ||||
* | * | ||||
* If no usable child device is found on @p dev, the request is delegated to | * If no usable child device is found on @p dev, the request is delegated to | ||||
* the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. | * the BHND_BUS_GET_NVRAM_VAR() method on the parent of @p dev. | ||||
*/ | */ | ||||
int | int | ||||
bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, | bhnd_bus_generic_get_nvram_var(device_t dev, device_t child, const char *name, | ||||
void *buf, size_t *size) | void *buf, size_t *size, bhnd_nvram_type type) | ||||
{ | { | ||||
device_t nvram; | device_t nvram; | ||||
device_t parent; | device_t parent; | ||||
/* Make sure we're holding Giant for newbus */ | /* Make sure we're holding Giant for newbus */ | ||||
GIANT_REQUIRED; | GIANT_REQUIRED; | ||||
/* Look for a directly-attached NVRAM child */ | /* Look for a directly-attached NVRAM child */ | ||||
if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL) | if ((nvram = device_find_child(dev, "bhnd_nvram", -1)) != NULL) | ||||
return BHND_NVRAM_GETVAR(nvram, name, buf, size); | return BHND_NVRAM_GETVAR(nvram, name, buf, size, type); | ||||
/* Try to delegate to parent */ | /* Try to delegate to parent */ | ||||
if ((parent = device_get_parent(dev)) == NULL) | if ((parent = device_get_parent(dev)) == NULL) | ||||
return (ENODEV); | return (ENODEV); | ||||
return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, | return (BHND_BUS_GET_NVRAM_VAR(device_get_parent(dev), child, | ||||
name, buf, size)); | name, buf, size, type)); | ||||
} | } | ||||
/** | /** | ||||
* Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). | * Helper function for implementing BHND_BUS_ALLOC_RESOURCE(). | ||||
* | * | ||||
* This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation | * This implementation of BHND_BUS_ALLOC_RESOURCE() delegates allocation | ||||
* of the underlying resource to BUS_ALLOC_RESOURCE(), and activation | * of the underlying resource to BUS_ALLOC_RESOURCE(), and activation | ||||
* to @p dev's BHND_BUS_ACTIVATE_RESOURCE(). | * to @p dev's BHND_BUS_ACTIVATE_RESOURCE(). | ||||
▲ Show 20 Lines • Show All 99 Lines • Show Last 20 Lines |