1 /* 2 * bcmiov.h 3 * Common iovar handling/parsing support - batching, parsing, sub-cmd dispatch etc. 4 * To be used in firmware and host apps or dhd - reducing code size, 5 * duplication, and maintenance overhead. 6 * 7 * Portions of this code are copyright (c) 2021 Cypress Semiconductor Corporation 8 * 9 * Copyright (C) 1999-2017, Broadcom Corporation 10 * 11 * Unless you and Broadcom execute a separate written software license 12 * agreement governing use of this software, this software is licensed to you 13 * under the terms of the GNU General Public License version 2 (the "GPL"), 14 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 15 * following added to such license: 16 * 17 * As a special exception, the copyright holders of this software give you 18 * permission to link this software with independent modules, and to copy and 19 * distribute the resulting executable under terms of your choice, provided that 20 * you also meet, for each linked independent module, the terms and conditions of 21 * the license of that module. An independent module is a module which is not 22 * derived from this software. The special exception does not apply to any 23 * modifications of the software. 24 * 25 * Notwithstanding the above, under no circumstances may you combine this 26 * software in any way with any other Broadcom software provided under a license 27 * other than the GPL, without Broadcom's express prior written consent. 28 * 29 * 30 * <<Broadcom-WL-IPTag/Open:>> 31 * 32 * $Id$ 33 */ 34 35 #ifndef _bcmiov_h_ 36 #define _bcmiov_h_ 37 38 #include <typedefs.h> 39 #include <bcmutils.h> 40 #include <wlioctl.h> 41 #ifdef BCMDRIVER 42 #include <osl.h> 43 #else 44 #include <stddef.h> /* For size_t */ 45 #endif /* BCMDRIVER */ 46 47 /* Forward declarations */ 48 typedef uint16 bcm_iov_cmd_id_t; 49 typedef uint16 bcm_iov_cmd_flags_t; 50 typedef uint16 bcm_iov_cmd_mflags_t; 51 typedef struct bcm_iov_cmd_info bcm_iov_cmd_info_t; 52 typedef struct bcm_iov_cmd_digest bcm_iov_cmd_digest_t; 53 typedef struct bcm_iov_cmd_tlv_info bcm_iov_cmd_tlv_info_t; 54 typedef struct bcm_iov_buf bcm_iov_buf_t; 55 typedef struct bcm_iov_batch_buf bcm_iov_batch_buf_t; 56 typedef struct bcm_iov_parse_context bcm_iov_parse_context_t; 57 typedef struct bcm_iov_sub_cmd_context bcm_iov_sub_cmd_context_t; 58 59 typedef void* (*bcm_iov_malloc_t)(void* alloc_ctx, size_t len); 60 typedef void (*bcm_iov_free_t)(void* alloc_ctx, void *buf, size_t len); 61 62 typedef uint8 bcm_iov_tlp_data_type_t; 63 typedef struct bcm_iov_tlp bcm_iov_tlp_t; 64 typedef struct bcm_iov_tlp_node bcm_iov_tlp_node_t; 65 typedef struct bcm_iov_batch_subcmd bcm_iov_batch_subcmd_t; 66 67 /* 68 * iov validation handler - All the common checks that are required 69 * for processing of iovars for any given command. 70 */ 71 typedef int (*bcm_iov_cmd_validate_t)(const bcm_iov_cmd_digest_t *dig, 72 uint32 actionid, const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); 73 74 /* iov get handler - process subcommand specific input and return output. 75 * input and output may overlap, so the callee needs to check if 76 * that is supported. For xtlv data a tlv digest is provided to make 77 * parsing simpler. Output tlvs may be packed into output buffer using 78 * bcm xtlv support. olen is input/output parameter. On input contains 79 * max available obuf length and callee must fill the correct length 80 * to represent the length of output returned. 81 */ 82 typedef int (*bcm_iov_cmd_get_t)(const bcm_iov_cmd_digest_t *dig, 83 const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); 84 85 /* iov set handler - process subcommand specific input and return output 86 * input and output may overlap, so the callee needs to check if 87 * that is supported. olen is input/output parameter. On input contains 88 * max available obuf length and callee must fill the correct length 89 * to represent the length of output returned. 90 */ 91 typedef int (*bcm_iov_cmd_set_t)(const bcm_iov_cmd_digest_t *dig, 92 const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); 93 94 /* iov (sub-cmd) batch - a vector of commands. count can be zero 95 * to support a version query. Each command is a tlv - whose data 96 * portion may have an optional return status, followed by a fixed 97 * length data header, optionally followed by tlvs. 98 * cmd = type|length|<status|options>[header][tlvs] 99 */ 100 101 /* 102 * Batch sub-commands have status length included in the 103 * response length packed in TLV. 104 */ 105 #define BCM_IOV_STATUS_LEN sizeof(uint32) 106 107 /* batch version is indicated by setting high bit. */ 108 #define BCM_IOV_BATCH_MASK 0x8000 109 110 /* 111 * Batched commands will have the following memory layout 112 * +--------+---------+--------+-------+ 113 * |version |count | is_set |sub-cmd| 114 * +--------+---------+--------+-------+ 115 * version >= 0x8000 116 * count = number of sub-commands encoded in the iov buf 117 * sub-cmd one or more sub-commands for processing 118 * Where sub-cmd is padded byte buffer with memory layout as follows 119 * +--------+---------+-----------------------+-------------+------ 120 * |cmd-id |length |IN(options) OUT(status)|command data |...... 121 * +--------+---------+-----------------------+-------------+------ 122 * cmd-id =sub-command ID 123 * length = length of this sub-command 124 * IN(options) = On input processing options/flags for this command 125 * OUT(status) on output processing status for this command 126 * command data = encapsulated IOVAR data as a single structure or packed TLVs for each 127 * individual sub-command. 128 */ 129 struct bcm_iov_batch_subcmd { 130 uint16 id; 131 uint16 len; 132 union { 133 uint32 options; 134 uint32 status; 135 } u; 136 uint8 data[1]; 137 }; 138 139 struct bcm_iov_batch_buf { 140 uint16 version; 141 uint8 count; 142 uint8 is_set; /* to differentiate set or get */ 143 struct bcm_iov_batch_subcmd cmds[0]; 144 }; 145 146 /* non-batched command version = major|minor w/ major <= 127 */ 147 struct bcm_iov_buf { 148 uint16 version; 149 uint16 len; 150 bcm_iov_cmd_id_t id; 151 uint16 data[1]; /* 32 bit alignment may be repurposed by the command */ 152 /* command specific data follows */ 153 }; 154 155 /* iov options flags */ 156 enum { 157 BCM_IOV_CMD_OPT_ALIGN_NONE = 0x0000, 158 BCM_IOV_CMD_OPT_ALIGN32 = 0x0001, 159 BCM_IOV_CMD_OPT_TERMINATE_SUB_CMDS = 0x0002 160 }; 161 162 /* iov command flags */ 163 enum { 164 BCM_IOV_CMD_FLAG_NONE = 0, 165 BCM_IOV_CMD_FLAG_STATUS_PRESENT = (1 << 0), /* status present at data start - output only */ 166 BCM_IOV_CMD_FLAG_XTLV_DATA = (1 << 1), /* data is a set of xtlvs */ 167 BCM_IOV_CMD_FLAG_HDR_IN_LEN = (1 << 2), /* length starts at version - non-bacthed only */ 168 BCM_IOV_CMD_FLAG_NOPAD = (1 << 3) /* No padding needed after iov_buf */ 169 }; 170 171 /* information about the command, xtlv options and xtlvs_off are meaningful 172 * only if XTLV_DATA cmd flag is selected 173 */ 174 struct bcm_iov_cmd_info { 175 bcm_iov_cmd_id_t cmd; /* the (sub)command - module specific */ 176 bcm_iov_cmd_flags_t flags; /* checked by bcmiov but set by module */ 177 bcm_iov_cmd_mflags_t mflags; /* owned and checked by module */ 178 bcm_xtlv_opts_t xtlv_opts; 179 bcm_iov_cmd_validate_t validate_h; /* command validation handler */ 180 bcm_iov_cmd_get_t get_h; 181 bcm_iov_cmd_set_t set_h; 182 uint16 xtlvs_off; /* offset to beginning of xtlvs in cmd data */ 183 uint16 min_len_set; 184 uint16 max_len_set; 185 uint16 min_len_get; 186 uint16 max_len_get; 187 }; 188 189 /* tlv digest to support parsing of xtlvs for commands w/ tlv data; the tlv 190 * digest is available in the handler for the command. The count and order in 191 * which tlvs appear in the digest are exactly the same as the order of tlvs 192 * passed in the registration for the command. Unknown tlvs are ignored. 193 * If registered tlvs are missing datap will be NULL. common iov rocessing 194 * acquires an input digest to process input buffer. The handler is responsible 195 * for constructing an output digest and use packing functions to generate 196 * the output buffer. The handler may use the input digest as output digest once 197 * the tlv data is extracted and used. Multiple tlv support involves allocation of 198 * tlp nodes, except the first, as required, 199 */ 200 201 /* tlp data type indicates if the data is not used/invalid, input or output */ 202 enum { 203 BCM_IOV_TLP_NODE_INVALID = 0, 204 BCM_IOV_TLP_NODE_IN = 1, 205 BCM_IOV_TLP_NODE_OUT = 2 206 }; 207 208 struct bcm_iov_tlp { 209 uint16 type; 210 uint16 len; 211 uint16 nodeix; /* node index */ 212 }; 213 214 /* tlp data for a given tlv - multiple tlvs of same type chained */ 215 struct bcm_iov_tlp_node { 216 uint8 *next; /* multiple tlv support */ 217 bcm_iov_tlp_data_type_t type; 218 uint8 *data; /* pointer to data in buffer or state */ 219 }; 220 221 struct bcm_iov_cmd_digest { 222 uint32 version; /* Version */ 223 void *cmd_ctx; 224 struct wlc_bsscfg *bsscfg; 225 const bcm_iov_cmd_info_t *cmd_info; 226 uint16 max_tlps; /* number of tlps allocated */ 227 uint16 max_nodes; /* number of nods allocated */ 228 uint16 num_tlps; /* number of tlps valid */ 229 uint16 num_nodes; /* number of nods valid */ 230 uint16 tlps_off; /* offset to tlps */ 231 uint16 nodes_off; /* offset to nodes */ 232 /* 233 * bcm_iov_tlp_t tlps[max_tlps]; 234 * bcm_iov_tlp_node_t nodes[max_nodes] 235 */ 236 }; 237 238 /* get length callback - default length is min_len taken from digest */ 239 typedef size_t (*bcm_iov_xtlv_get_len_t)(const bcm_iov_cmd_digest_t *dig, 240 const bcm_iov_cmd_tlv_info_t *tlv_info); 241 242 /* pack to buffer data callback. under some conditions it might 243 * not be a straight copy and can refer to context(ual) information and 244 * endian conversions... 245 */ 246 typedef void (*bcm_iov_xtlv_pack_t)(const bcm_iov_cmd_digest_t *dig, 247 const bcm_iov_cmd_tlv_info_t *tlv_info, 248 uint8 *out_buf, const uint8 *in_data, size_t len); 249 250 struct bcm_iov_cmd_tlv_info { 251 uint16 id; 252 uint16 min_len; /* inclusive */ 253 uint16 max_len; /* inclusive */ 254 bcm_iov_xtlv_get_len_t get_len; 255 bcm_iov_xtlv_pack_t pack; 256 }; 257 258 /* 259 * module private parse context. Default version type len is uint16 260 */ 261 enum { 262 BCM_IOV_PARSE_CMD_NONE = 0 263 }; 264 typedef uint32 parse_context_opts_t; 265 266 /* get digest callback */ 267 typedef int (*bcm_iov_get_digest_t)(void *cmd_ctx, bcm_iov_cmd_digest_t **dig); 268 269 typedef struct bcm_iov_parse_config { 270 parse_context_opts_t options; /* to handle different ver lengths */ 271 bcm_iov_malloc_t alloc_fn; 272 bcm_iov_free_t free_fn; 273 bcm_iov_get_digest_t dig_fn; 274 int max_regs; 275 void *alloc_ctx; 276 } bcm_iov_parse_config_t; 277 278 /* API */ 279 280 /* All calls return an integer status code BCME_* unless otherwise indicated */ 281 282 /* return length of allocation for 'num_cmds' commands. data_len 283 * includes length of data for all the commands excluding the headers 284 */ 285 size_t bcm_iov_get_alloc_len(int num_cmds, size_t data_len); 286 287 /* create parsing context using allocator provided; max_regs provides 288 * the number of allowed registrations for commands using the context 289 * sub-components of a module may register their own commands indepdently 290 * using the parsing context. If digest callback is NULL or returns NULL, 291 * the (input) digest is allocated using the provided allocators and released on 292 * completion of processing. 293 */ 294 int bcm_iov_create_parse_context(const bcm_iov_parse_config_t *parse_cfg, 295 bcm_iov_parse_context_t **parse_ctx); 296 297 /* free the parsing context; ctx is set to NULL on exit */ 298 int bcm_iov_free_parse_context(bcm_iov_parse_context_t **ctx, bcm_iov_free_t free_fn); 299 300 /* Return the command context for the module */ 301 void *bcm_iov_get_cmd_ctx_info(bcm_iov_parse_context_t *parse_ctx); 302 303 /* register a command info vector along with supported tlvs. Each command 304 * may support a subset of tlvs 305 */ 306 int bcm_iov_register_commands(bcm_iov_parse_context_t *parse_ctx, void *cmd_ctx, 307 const bcm_iov_cmd_info_t *info, size_t num_cmds, 308 const bcm_iov_cmd_tlv_info_t *tlv_info, size_t num_tlvs); 309 310 /* pack the xtlvs provided in the digest. may returns BCME_BUFTOOSHORT, but the 311 * out_len is set to required length in that case. 312 */ 313 int bcm_iov_pack_xtlvs(const bcm_iov_cmd_digest_t *dig, bcm_xtlv_opts_t xtlv_opts, 314 uint8 *out_buf, size_t out_size, size_t *out_len); 315 316 #ifdef BCMDRIVER 317 /* wlc modules register their iovar(s) using the parsing context w/ wlc layer 318 * during attach. 319 */ 320 struct wlc_if; 321 struct wlc_info; 322 extern struct wlc_bsscfg *bcm_iov_bsscfg_find_from_wlcif(struct wlc_info *wlc, 323 struct wlc_if *wlcif); 324 int bcm_iov_doiovar(void *parse_ctx, uint32 id, void *params, uint params_len, 325 void *arg, uint arg_len, uint vsize, struct wlc_if *intf); 326 #endif /* BCMDRIVER */ 327 328 /* parsing context helpers */ 329 330 /* get the maximum number of tlvs - can be used to allocate digest for all 331 * commands. the digest can be shared. Negative values are BCM_*, >=0, the 332 * number of tlvs 333 */ 334 int bcm_iov_parse_get_max_tlvs(const bcm_iov_parse_context_t *ctx); 335 336 /* common packing support */ 337 338 /* pack a buffer of uint8s - memcpy wrapper */ 339 int bcm_iov_pack_buf(const bcm_iov_cmd_digest_t *dig, uint8 *buf, 340 const uint8 *data, size_t len); 341 342 #define bcm_iov_packv_u8 bcm_iov_pack_buf 343 344 /* 345 * pack a buffer with uint16s - serialized in LE order, data points to uint16 346 * length is not checked. 347 */ 348 int bcm_iov_packv_u16(const bcm_iov_cmd_digest_t *dig, uint8 *buf, 349 const uint16 *data, int n); 350 351 /* 352 * pack a buffer with uint32s - serialized in LE order - data points to uint32 353 * length is not checked. 354 */ 355 int bcm_iov_packv_u32(const bcm_iov_cmd_digest_t *dig, uint8 *buf, 356 const uint32 *data, int n); 357 358 #endif /* _bcmiov_h_ */ 359