Shad Ansari | 2f7f9be | 2017-06-07 13:34:53 -0700 | [diff] [blame] | 1 | /* |
| 2 | <:copyright-BRCM:2016:DUAL/GPL:standard |
| 3 | |
| 4 | Broadcom Proprietary and Confidential.(c) 2016 Broadcom |
| 5 | All Rights Reserved |
| 6 | |
| 7 | Unless you and Broadcom execute a separate written software license |
| 8 | agreement governing use of this software, this software is licensed |
| 9 | to you under the terms of the GNU General Public License version 2 |
| 10 | (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php, |
| 11 | with the following added to such license: |
| 12 | |
| 13 | As a special exception, the copyright holders of this software give |
| 14 | you permission to link this software with independent modules, and |
| 15 | to copy and distribute the resulting executable under terms of your |
| 16 | choice, provided that you also meet, for each linked independent |
| 17 | module, the terms and conditions of the license of that module. |
| 18 | An independent module is a module which is not derived from this |
| 19 | software. The special exception does not apply to any modifications |
| 20 | of the software. |
| 21 | |
| 22 | Not withstanding the above, under no circumstances may you combine |
| 23 | this software in any way with any other Broadcom software provided |
| 24 | under a license other than the GPL, without Broadcom's express prior |
| 25 | written consent. |
| 26 | |
| 27 | :> |
| 28 | */ |
| 29 | |
| 30 | #ifndef BCMOLT_MSG_H_ |
| 31 | #define BCMOLT_MSG_H_ |
| 32 | |
| 33 | #include "bcmos_system.h" |
| 34 | #include "bcmolt_buf.h" |
| 35 | #include "bcmolt_model_ids.h" |
| 36 | #include "bcm_dev_log_task.h" |
| 37 | |
| 38 | /** \defgroup \api_data_types Data Types |
| 39 | * \ingroup api |
| 40 | * @{ |
| 41 | */ |
| 42 | |
| 43 | /** Device ID */ |
| 44 | typedef uint8_t bcmolt_devid; |
| 45 | |
| 46 | /** Bitmask of fields that are present in a message */ |
| 47 | typedef uint64_t bcmolt_presence_mask; |
| 48 | |
| 49 | /** Presence mask indicating all fields present */ |
| 50 | #define BCMOLT_PRESENCE_MASK_ALL ((bcmolt_presence_mask)0xFFFFFFFFFFFFFFFF) |
| 51 | |
| 52 | /** Message direction - request or response */ |
| 53 | typedef enum bcmolt_msg_dir |
| 54 | { |
| 55 | BCMOLT_MSG_DIR_REQUEST, |
| 56 | BCMOLT_MSG_DIR_RESPONSE |
| 57 | } bcmolt_msg_dir; |
| 58 | |
| 59 | /** Message type. Can be a combination of flags */ |
| 60 | typedef enum bcmolt_msg_type |
| 61 | { |
| 62 | BCMOLT_MSG_TYPE_GET = 0x01, /**< Get: configuration or statistics */ |
| 63 | BCMOLT_MSG_TYPE_SET = 0x02, /**< Set: Configuration, Statistics, Auto, Proxy */ |
| 64 | BCMOLT_MSG_TYPE_CLEAR= 0x04, /**< Clear: configuration */ |
| 65 | BCMOLT_MSG_TYPE_MULTI= 0x08, /**< Multi-object: configuration, statistics */ |
| 66 | |
| 67 | BCMOLT_MSG_TYPE_GET_MULTI = BCMOLT_MSG_TYPE_GET | BCMOLT_MSG_TYPE_MULTI, |
| 68 | } bcmolt_msg_type; |
| 69 | |
| 70 | /** Management group - key, config, operation, etc */ |
| 71 | typedef enum bcmolt_mgt_group |
| 72 | { |
| 73 | BCMOLT_MGT_GROUP_KEY, /**< key that uniquely identifies object instance */ |
| 74 | BCMOLT_MGT_GROUP_CFG, /**< Configuration */ |
| 75 | BCMOLT_MGT_GROUP_STAT, /**< Statistics */ |
| 76 | BCMOLT_MGT_GROUP_STAT_CFG, /**< Statistics threshold configuration */ |
| 77 | BCMOLT_MGT_GROUP_AUTO, /**< Autonomous indications */ |
| 78 | BCMOLT_MGT_GROUP_AUTO_CFG, /**< Autonomous indication configuration */ |
| 79 | BCMOLT_MGT_GROUP_OPER, /**< Operations */ |
| 80 | BCMOLT_MGT_GROUP_PROXY, /**< Messages to ONU */ |
| 81 | BCMOLT_MGT_GROUP_PROXY_RX, /**< Messages from ONU */ |
| 82 | BCMOLT_MGT_GROUP__NUM_OF |
| 83 | } bcmolt_mgt_group; |
| 84 | |
| 85 | /** Any object */ |
| 86 | #define BCMOLT_OBJECT_ANY (bcmolt_obj_id)0xffff |
| 87 | |
| 88 | /** Any group */ |
| 89 | #define BCMOLT_MGT_GROUP_ANY (bcmolt_mgt_group)0xffff |
| 90 | |
| 91 | /** Any subgroup */ |
| 92 | #define BCMOLT_SUBGROUP_ANY 0xffff |
| 93 | |
| 94 | /** Indicator that no fields contained errors */ |
| 95 | #define BCMOLT_ERR_FIELD_NONE 0xffff |
| 96 | |
| 97 | /** Max error text length */ |
| 98 | #define BCMOLT_MAX_ERR_TEXT_LENGTH 256 |
| 99 | |
| 100 | /* Transport sub-channel handle */ |
| 101 | typedef uint16_t bcmolt_subchannel; |
| 102 | |
| 103 | /** Message set - for multi-instance APIs */ |
| 104 | typedef struct bcmolt_msg_set bcmolt_msg_set; |
| 105 | |
| 106 | /** Common message header */ |
| 107 | typedef struct bcmolt_msg |
| 108 | { |
| 109 | bcmolt_obj_id obj_type; /**< Object type */ |
| 110 | bcmolt_mgt_group group; /**< Management group */ |
| 111 | uint16_t subgroup; /**< Subgroup: for operations, autonomous messages, proxy */ |
| 112 | bcmolt_msg_type type; /**< Set, Get, Clear */ |
| 113 | bcmolt_msg_dir dir; /**< Request/autonomous or Response */ |
| 114 | bcmos_errno err; /**< Remote error code */ |
| 115 | uint16_t err_field_idx; /**< If not BCMOLT_ERR_FIELD_NONE, index of erroneous field within struct */ |
| 116 | uint16_t corr_tag; /**< Correlation tag */ |
| 117 | bcmolt_presence_mask presence_mask; /**< Indicates which parameters are present */ |
| 118 | char err_text[BCMOLT_MAX_ERR_TEXT_LENGTH]; /**< Error text - if err != 0 */ |
| 119 | /* The following fields are internal. They are not sent on the line */ |
| 120 | bcmolt_subchannel subch; /* Transport sub-channel via which the message arrived */ |
| 121 | bcmos_msg os_msg; /* Internal OS message for easy task routing */ |
| 122 | void *list_buf; /* Memory buffer in which to store variable-sized lists when unpacking */ |
| 123 | uint32_t list_buf_size; /* Number of bytes in the variable-sized list buffer */ |
| 124 | bcmolt_msg_set *msg_set; /* Message set the message belongs to */ |
| 125 | } bcmolt_msg; |
| 126 | |
| 127 | /** Configuration group message header */ |
| 128 | typedef struct bcmolt_cfg |
| 129 | { |
| 130 | bcmolt_msg hdr; /** Common header */ |
| 131 | } bcmolt_cfg; |
| 132 | |
| 133 | /** Statistic flags */ |
| 134 | typedef enum |
| 135 | { |
| 136 | BCMOLT_STAT_FLAGS_NONE = 0x0000, /**< No statistics options set (no clear on read, etc) */ |
| 137 | BCMOLT_STAT_FLAGS_CLEAR_ON_READ = 0x0001, /**< Clear the requested statistics as part of the read operation */ |
| 138 | } bcmolt_stat_flags; |
| 139 | |
| 140 | /** Statistics group message header */ |
| 141 | typedef struct bcmolt_stat |
| 142 | { |
| 143 | bcmolt_msg hdr; /** Common header */ |
| 144 | } bcmolt_stat; |
| 145 | |
| 146 | /** Statistics configuration message header */ |
| 147 | typedef struct bcmolt_stat_cfg |
| 148 | { |
| 149 | bcmolt_msg hdr; /** Common header */ |
| 150 | } bcmolt_stat_cfg; |
| 151 | |
| 152 | /** Operation group message header */ |
| 153 | typedef struct bcmolt_oper |
| 154 | { |
| 155 | bcmolt_msg hdr; /** Common header */ |
| 156 | } bcmolt_oper; |
| 157 | |
| 158 | /** Autonomous message header */ |
| 159 | typedef struct bcmolt_auto |
| 160 | { |
| 161 | bcmolt_msg hdr; /** Common header */ |
| 162 | } bcmolt_auto; |
| 163 | |
| 164 | /** Autonomous message configuration header */ |
| 165 | typedef struct bcmolt_auto_cfg |
| 166 | { |
| 167 | bcmolt_msg hdr; /** Common header */ |
| 168 | } bcmolt_auto_cfg; |
| 169 | |
| 170 | /** Message handler */ |
| 171 | typedef void (*f_bcmolt_msg_handler)(bcmolt_devid olt, bcmolt_msg *msg); |
| 172 | |
| 173 | /** Autonomous message flags */ |
| 174 | typedef enum |
| 175 | { |
| 176 | BCMOLT_AUTO_FLAGS_NONE = 0, /**< Invoke callback in context of RX task */ |
| 177 | BCMOLT_AUTO_FLAGS_DISPATCH = 0x0001, /**< Dispatch message to application module */ |
| 178 | } bcmolt_auto_flags; |
| 179 | |
| 180 | /** Proxy message header */ |
| 181 | typedef struct bcmolt_proxy |
| 182 | { |
| 183 | bcmolt_msg hdr; /** Common header */ |
| 184 | } bcmolt_proxy; |
| 185 | |
| 186 | /** Proxy RX message header */ |
| 187 | typedef struct bcmolt_proxy_rx |
| 188 | { |
| 189 | bcmolt_msg hdr; /** Common header */ |
| 190 | } bcmolt_proxy_rx; |
| 191 | |
| 192 | /** Filter flags */ |
| 193 | typedef enum |
| 194 | { |
| 195 | BCMOLT_FILTER_FLAGS_NONE = 0, |
| 196 | BCMOLT_FILTER_FLAGS_INVERT_SELECTION = 0x00000001 /** Return objects NOT selected by filter */ |
| 197 | } bcmolt_filter_flags; |
| 198 | |
| 199 | /* Message set */ |
| 200 | struct bcmolt_msg_set |
| 201 | { |
| 202 | uint16_t max_instances; /**< Max number of instances in the set. Set when set is created and doesn't change */ |
| 203 | bcmolt_mgt_group group; /**< Management group */ |
| 204 | bcmolt_presence_mask presence_mask; /**< Indicates which parameters should be fetched */ |
| 205 | bcmolt_filter_flags filter_flags; /**< Filter flags */ |
| 206 | |
| 207 | /* Multi-msg API output */ |
| 208 | uint16_t num_instances; /**< Number of instances in the set. */ |
| 209 | bcmos_bool more; /**< BCMOS_TRUE if not all instances have been retrieved by the last |
| 210 | bcmolt_get_multi() call. */ |
| 211 | void *next_key; /**< Key of the next object instance after those that were returned. Only valid if |
| 212 | 'more' is BCMOS_FALSE. Treat this as a pointer to the object's key struct. This |
| 213 | can be used for subsequent invocations of bcmolt_cfg_get_multiple() by copying this |
| 214 | into the filter's key field. */ |
| 215 | #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /**< Check whether C99 is supported */ |
| 216 | bcmolt_msg *msg[]; /**< Set of API objects returned by bcmolt_cfg_get_multiple(). */ |
| 217 | #else |
| 218 | bcmolt_msg *msg[0]; /**< Set of API objects returned by bcmolt_cfg_get_multiple(). */ |
| 219 | #endif |
| 220 | }; |
| 221 | |
| 222 | /** @} */ |
| 223 | |
| 224 | |
| 225 | /*lint -ecall(633, bcmolt_msg_err) - 4th argument will be a specific enum type, but must be treated as a uint16. */ |
| 226 | /** Set message error. Cannot be static inline, as it uses variable argument list. */ |
| 227 | bcmos_errno bcmolt_msg_err(bcmolt_msg *msg, dev_log_id log_id, bcmos_errno err, uint16_t err_field_idx, const char *fmt, ...)__attribute__((format(__printf__, 5, 6))); |
| 228 | |
| 229 | /** Whether we pack the entire structure of a message */ |
| 230 | static inline bcmos_bool bcmolt_msg_should_pack_data(const bcmolt_msg *msg) |
| 231 | { |
| 232 | switch (msg->group) |
| 233 | { |
| 234 | case BCMOLT_MGT_GROUP_CFG: |
| 235 | case BCMOLT_MGT_GROUP_STAT: |
| 236 | case BCMOLT_MGT_GROUP_STAT_CFG: |
| 237 | case BCMOLT_MGT_GROUP_AUTO_CFG: |
| 238 | if ((msg->type & BCMOLT_MSG_TYPE_GET)) |
| 239 | { |
| 240 | bcmos_bool should_pack = (msg->dir == BCMOLT_MSG_DIR_RESPONSE); |
| 241 | /* For multi-message get request should_pack must be inverted because the 1st part |
| 242 | * of multi-object request is filter |
| 243 | */ |
| 244 | return (msg->type & BCMOLT_MSG_TYPE_MULTI) ? !should_pack : should_pack; |
| 245 | } |
| 246 | else if ((msg->type & BCMOLT_MSG_TYPE_SET)) |
| 247 | { |
| 248 | return (msg->dir == BCMOLT_MSG_DIR_REQUEST); |
| 249 | } |
| 250 | else |
| 251 | { |
| 252 | return BCMOS_FALSE; |
| 253 | } |
| 254 | |
| 255 | case BCMOLT_MGT_GROUP_OPER: |
| 256 | case BCMOLT_MGT_GROUP_PROXY: |
| 257 | return (msg->dir == BCMOLT_MSG_DIR_REQUEST); |
| 258 | |
| 259 | default: |
| 260 | return BCMOS_TRUE; |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | /** Get the length of the header portion of a message */ |
| 265 | static inline int32_t bcmolt_msg_hdr_get_packed_length(const bcmolt_msg *msg) |
| 266 | { |
| 267 | return 18 + (msg->err ? strlen(msg->err_text) + 2 : 0); |
| 268 | } |
| 269 | |
| 270 | /** Pack a message header to a byte stream */ |
| 271 | static inline bcmos_errno bcmolt_msg_hdr_pack(const bcmolt_msg *msg, bcmolt_buf *buf) |
| 272 | { |
| 273 | bcmos_bool ret; |
| 274 | |
| 275 | ret = bcmolt_buf_write_u8(buf, (uint8_t)msg->obj_type); |
| 276 | ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->group); |
| 277 | ret = ret && bcmolt_buf_write_u16(buf, msg->subgroup); |
| 278 | ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->type); |
| 279 | ret = ret && bcmolt_buf_write_u8(buf, (uint8_t)msg->dir); |
| 280 | ret = ret && bcmolt_buf_write_s16(buf, (int16_t)msg->err); |
| 281 | ret = ret && bcmolt_buf_write_u64(buf, (uint64_t)msg->presence_mask); |
| 282 | ret = ret && bcmolt_buf_write_u16(buf, msg->err_field_idx); |
| 283 | if (msg->err) |
| 284 | { |
| 285 | uint16_t len = strlen(msg->err_text); |
| 286 | ret = ret && bcmolt_buf_write_u16(buf, len); |
| 287 | ret = ret && bcmolt_buf_write(buf, msg->err_text, len); |
| 288 | } |
| 289 | |
| 290 | return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW; |
| 291 | } |
| 292 | |
| 293 | /** Unpack a message header from a byte stream */ |
| 294 | static inline bcmos_errno bcmolt_msg_hdr_unpack(bcmolt_msg *msg, bcmolt_buf *buf) |
| 295 | { |
| 296 | uint8_t obj_type; |
| 297 | uint8_t group; |
| 298 | uint16_t subgroup; |
| 299 | uint8_t type; |
| 300 | uint8_t dir; |
| 301 | int16_t err = 0; |
| 302 | uint64_t presence_mask; |
| 303 | uint16_t err_field_idx; |
| 304 | bcmos_bool ret; |
| 305 | |
| 306 | ret = bcmolt_buf_read_u8(buf, &obj_type); |
| 307 | ret = ret && bcmolt_buf_read_u8(buf, &group); |
| 308 | ret = ret && bcmolt_buf_read_u16(buf, &subgroup); |
| 309 | ret = ret && bcmolt_buf_read_u8(buf, &type); |
| 310 | ret = ret && bcmolt_buf_read_u8(buf, &dir); |
| 311 | ret = ret && bcmolt_buf_read_s16(buf, &err); |
| 312 | ret = ret && bcmolt_buf_read_u64(buf, &presence_mask); |
| 313 | ret = ret && bcmolt_buf_read_u16(buf, &err_field_idx); |
| 314 | if (err) |
| 315 | { |
| 316 | uint16_t len = 0; |
| 317 | ret = ret && bcmolt_buf_read_u16(buf, &len); |
| 318 | if (len >= sizeof(msg->err_text)) |
| 319 | len = sizeof(msg->err_text) - 1; |
| 320 | ret = ret && bcmolt_buf_read(buf, msg->err_text, len); |
| 321 | msg->err_text[len] = 0; |
| 322 | } |
| 323 | else |
| 324 | { |
| 325 | msg->err_text[0] = 0; |
| 326 | } |
| 327 | |
| 328 | if (ret) |
| 329 | { |
| 330 | msg->obj_type = (bcmolt_obj_id)obj_type; |
| 331 | msg->group = (bcmolt_mgt_group)group; |
| 332 | msg->subgroup = subgroup; |
| 333 | msg->type = (bcmolt_msg_type)type; |
| 334 | msg->dir = (bcmolt_msg_dir)dir; |
| 335 | msg->err = (bcmos_errno)err; |
| 336 | msg->presence_mask = (bcmolt_presence_mask)presence_mask; |
| 337 | msg->err_field_idx = err_field_idx; |
| 338 | msg->msg_set = NULL; |
| 339 | } |
| 340 | |
| 341 | return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW; |
| 342 | } |
| 343 | |
| 344 | /* Create message set |
| 345 | * |
| 346 | * \param[in] obj Object id |
| 347 | * \param[in] group Management group |
| 348 | * \param[in] max_instances Max number of objects returned by a single API call |
| 349 | * \param[out] msg_set Message set |
| 350 | * \returns error code |
| 351 | */ |
| 352 | bcmos_errno bcmolt_msg_set_alloc(bcmolt_obj_id obj, bcmolt_mgt_group group, |
| 353 | uint32_t max_instances, bcmolt_msg_set **msg_set); |
| 354 | |
| 355 | /* Release message set |
| 356 | * \param[in] msg_set |
| 357 | */ |
| 358 | void bcmolt_msg_set_free(bcmolt_msg_set *msg_set); |
| 359 | |
| 360 | /* Release dynamically allocated message. |
| 361 | */ |
| 362 | static inline void bcmolt_msg_free(bcmolt_msg *msg) |
| 363 | { |
| 364 | if (msg->msg_set) |
| 365 | { |
| 366 | bcmolt_msg_set_free(msg->msg_set); |
| 367 | } |
| 368 | bcmos_free(msg); |
| 369 | } |
| 370 | |
| 371 | static inline void bcmolt_os_msg_release_cb(bcmos_msg *os_msg) |
| 372 | { |
| 373 | bcmolt_msg *msg = os_msg->data; |
| 374 | |
| 375 | /* We can be here if target module or transport queue overflows. |
| 376 | Release the message |
| 377 | */ |
| 378 | bcmolt_msg_free(msg); |
| 379 | } |
| 380 | |
| 381 | static inline bcmos_module_id bcmos_module_id_for_device(bcmos_module_id module, bcmolt_devid devid) |
| 382 | { |
| 383 | return module + (bcmos_module_id)devid; |
| 384 | } |
| 385 | #endif |