Bug Summary

File:dev/ocs_fc/ocs_mgmt.c
Warning:line 855, column 7
Copies out a struct with a partially unsanitized field

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-freebsd11.2 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ocs_mgmt.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model static -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -masm-verbose -mconstructor-aliases -ffreestanding -mcode-model kernel -target-cpu x86-64 -target-feature -mmx -target-feature -sse -target-feature -aes -target-feature -avx -disable-red-zone -no-implicit-float -dwarf-column-info -debugger-tuning=gdb -nostdsysteminc -nobuiltininc -resource-dir /root/kernel-uninitialized-memory-checker/build/lib/clang/8.0.0 -include /usr/obj/root/freebsd/amd64.amd64/sys/GENERIC/opt_global.h -D _KERNEL -D KLD_MODULE -D KLD_TIED -D HAVE_KERNEL_OPTION_HEADERS -I . -I /root/freebsd/sys -I /root/freebsd/sys/contrib/ck/include -I /usr/obj/root/freebsd/amd64.amd64/sys/GENERIC -D __printf__=__freebsd_kprintf__ -O2 -Wno-pointer-sign -Wno-unknown-pragmas -Wno-error-tautological-compare -Wno-error-empty-body -Wno-error-parentheses-equality -Wno-error-unused-function -Wno-error-pointer-sign -Wno-error-shift-negative-value -Wno-address-of-packed-member -std=iso9899:1999 -fdebug-compilation-dir /usr/obj/root/freebsd/amd64.amd64/sys/GENERIC/modules/root/freebsd/sys/modules/ocs_fc -ferror-limit 19 -fmessage-length 0 -fwrapv -stack-protector 1 -fobjc-runtime=gnustep -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker alpha.security.KernelMemoryDisclosure -analyzer-disable-checker core,unix,deadcode,nullability -analyzer-output=html -o /root/analyzer/2018-12-28-044519-76292-1 -x c /root/freebsd/sys/dev/ocs_fc/ocs_mgmt.c -faddrsig
1/*-
2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34/**
35 * @file
36 * The ocs_mgmt top level functions for Fibre Channel.
37 */
38
39/**
40 * @defgroup mgmt Management Functions
41 */
42
43#include "ocs.h"
44#include "ocs_mgmt.h"
45#include "ocs_vpd.h"
46
47#define SFP_PAGE_SIZE128 128
48
49/* Executables*/
50
51static int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
52static int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
53static int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
54
55static void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg);
56static int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
57
58#if defined(OCS_INCLUDE_RAMD)
59static int32_t
60ocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
61#endif
62
63
64/* Getters */
65
66static void get_nodes_count(ocs_t *, char *, ocs_textbuf_t*);
67static void get_desc(ocs_t *, char *, ocs_textbuf_t*);
68static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t*);
69static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t*);
70static void get_ipl(ocs_t *, char *, ocs_textbuf_t*);
71static void get_wwnn(ocs_t *, char *, ocs_textbuf_t*);
72static void get_wwpn(ocs_t *, char *, ocs_textbuf_t*);
73static void get_fcid(ocs_t *, char *, ocs_textbuf_t *);
74static void get_sn(ocs_t *, char *, ocs_textbuf_t*);
75static void get_pn(ocs_t *, char *, ocs_textbuf_t*);
76static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t*);
77static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t*);
78static void get_asic_id(ocs_t *, char *, ocs_textbuf_t*);
79static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t*);
80static void get_pci_device(ocs_t *, char *, ocs_textbuf_t*);
81static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t*);
82static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t*);
83static void get_businfo(ocs_t *, char *, ocs_textbuf_t*);
84static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t*);
85static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t*);
86static void get_hw_rev1(ocs_t *, char *, ocs_textbuf_t*);
87static void get_hw_rev2(ocs_t *, char *, ocs_textbuf_t*);
88static void get_hw_rev3(ocs_t *, char *, ocs_textbuf_t*);
89static void get_debug_mq_dump(ocs_t*, char*, ocs_textbuf_t*);
90static void get_debug_cq_dump(ocs_t*, char*, ocs_textbuf_t*);
91static void get_debug_wq_dump(ocs_t*, char*, ocs_textbuf_t*);
92static void get_debug_eq_dump(ocs_t*, char*, ocs_textbuf_t*);
93static void get_logmask(ocs_t*, char*, ocs_textbuf_t*);
94static void get_current_speed(ocs_t*, char*, ocs_textbuf_t*);
95static void get_current_topology(ocs_t*, char*, ocs_textbuf_t*);
96static void get_current_link_state(ocs_t*, char*, ocs_textbuf_t*);
97static void get_configured_speed(ocs_t*, char*, ocs_textbuf_t*);
98static void get_configured_topology(ocs_t*, char*, ocs_textbuf_t*);
99static void get_configured_link_state(ocs_t*, char*, ocs_textbuf_t*);
100static void get_linkcfg(ocs_t*, char*, ocs_textbuf_t*);
101static void get_req_wwnn(ocs_t*, char*, ocs_textbuf_t*);
102static void get_req_wwpn(ocs_t*, char*, ocs_textbuf_t*);
103static void get_nodedb_mask(ocs_t*, char*, ocs_textbuf_t*);
104static void get_profile_list(ocs_t*, char*, ocs_textbuf_t*);
105static void get_active_profile(ocs_t*, char*, ocs_textbuf_t*);
106static void get_port_protocol(ocs_t*, char*, ocs_textbuf_t*);
107static void get_driver_version(ocs_t*, char*, ocs_textbuf_t*);
108static void get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
109static void get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
110static void get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
111static void get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
112static void get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
113static void get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
114static void get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
115static void get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
116static void get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
117static void get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
118static void get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
119static void get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
120static void get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
121
122/* Setters */
123static int set_debug_mq_dump(ocs_t*, char*, char*);
124static int set_debug_cq_dump(ocs_t*, char*, char*);
125static int set_debug_wq_dump(ocs_t*, char*, char*);
126static int set_debug_eq_dump(ocs_t*, char*, char*);
127static int set_logmask(ocs_t*, char*, char*);
128static int set_configured_link_state(ocs_t*, char*, char*);
129static int set_linkcfg(ocs_t*, char*, char*);
130static int set_nodedb_mask(ocs_t*, char*, char*);
131static int set_port_protocol(ocs_t*, char*, char*);
132static int set_active_profile(ocs_t*, char*, char*);
133static int set_tgt_rscn_delay(ocs_t*, char*, char*);
134static int set_tgt_rscn_period(ocs_t*, char*, char*);
135static int set_inject_drop_cmd(ocs_t*, char*, char*);
136static int set_inject_free_drop_cmd(ocs_t*, char*, char*);
137static int set_inject_drop_data(ocs_t*, char*, char*);
138static int set_inject_drop_resp(ocs_t*, char*, char*);
139static int set_cmd_err_inject(ocs_t*, char*, char*);
140static int set_cmd_delay_value(ocs_t*, char*, char*);
141static int set_nv_wwn(ocs_t*, char*, char*);
142static int set_loglevel(ocs_t*, char*, char*);
143
144static void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg);
145#if defined(OCS_INCLUDE_RAMD)
146static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr);
147#endif
148
149ocs_mgmt_table_entry_t mgmt_table[] = {
150 {"nodes_count", get_nodes_count, NULL((void *)0), NULL((void *)0)},
151 {"desc", get_desc, NULL((void *)0), NULL((void *)0)},
152 {"fw_rev", get_fw_rev, NULL((void *)0), NULL((void *)0)},
153 {"fw_rev2", get_fw_rev2, NULL((void *)0), NULL((void *)0)},
154 {"ipl", get_ipl, NULL((void *)0), NULL((void *)0)},
155 {"hw_rev1", get_hw_rev1, NULL((void *)0), NULL((void *)0)},
156 {"hw_rev2", get_hw_rev2, NULL((void *)0), NULL((void *)0)},
157 {"hw_rev3", get_hw_rev3, NULL((void *)0), NULL((void *)0)},
158 {"wwnn", get_wwnn, NULL((void *)0), NULL((void *)0)},
159 {"wwpn", get_wwpn, NULL((void *)0), NULL((void *)0)},
160 {"fc_id", get_fcid, NULL((void *)0), NULL((void *)0)},
161 {"sn", get_sn, NULL((void *)0), NULL((void *)0)},
162 {"pn", get_pn, NULL((void *)0), NULL((void *)0)},
163 {"sli4_intf_reg", get_sli4_intf_reg, NULL((void *)0), NULL((void *)0)},
164 {"phy_port_num", get_phy_port_num, NULL((void *)0), NULL((void *)0)},
165 {"asic_id_reg", get_asic_id, NULL((void *)0), NULL((void *)0)},
166 {"pci_vendor", get_pci_vendor, NULL((void *)0), NULL((void *)0)},
167 {"pci_device", get_pci_device, NULL((void *)0), NULL((void *)0)},
168 {"pci_subsystem_vendor", get_pci_subsystem_vendor, NULL((void *)0), NULL((void *)0)},
169 {"pci_subsystem_device", get_pci_subsystem_device, NULL((void *)0), NULL((void *)0)},
170 {"businfo", get_businfo, NULL((void *)0), NULL((void *)0)},
171 {"sfp_a0", get_sfp_a0, NULL((void *)0), NULL((void *)0)},
172 {"sfp_a2", get_sfp_a2, NULL((void *)0), NULL((void *)0)},
173 {"profile_list", get_profile_list, NULL((void *)0), NULL((void *)0)},
174 {"driver_version", get_driver_version, NULL((void *)0), NULL((void *)0)},
175 {"current_speed", get_current_speed, NULL((void *)0), NULL((void *)0)},
176 {"current_topology", get_current_topology, NULL((void *)0), NULL((void *)0)},
177 {"current_link_state", get_current_link_state, NULL((void *)0), NULL((void *)0)},
178 {"chip_type", get_chip_type, NULL((void *)0), NULL((void *)0)},
179 {"configured_speed", get_configured_speed, set_configured_speed, NULL((void *)0)},
180 {"configured_topology", get_configured_topology, set_configured_topology, NULL((void *)0)},
181 {"configured_link_state", get_configured_link_state, set_configured_link_state, NULL((void *)0)},
182 {"debug_mq_dump", get_debug_mq_dump, set_debug_mq_dump, NULL((void *)0)},
183 {"debug_cq_dump", get_debug_cq_dump, set_debug_cq_dump, NULL((void *)0)},
184 {"debug_wq_dump", get_debug_wq_dump, set_debug_wq_dump, NULL((void *)0)},
185 {"debug_eq_dump", get_debug_eq_dump, set_debug_eq_dump, NULL((void *)0)},
186 {"logmask", get_logmask, set_logmask, NULL((void *)0)},
187 {"loglevel", get_loglevel, set_loglevel, NULL((void *)0)},
188 {"linkcfg", get_linkcfg, set_linkcfg, NULL((void *)0)},
189 {"requested_wwnn", get_req_wwnn, set_req_wwnn, NULL((void *)0)},
190 {"requested_wwpn", get_req_wwpn, set_req_wwpn, NULL((void *)0)},
191 {"nodedb_mask", get_nodedb_mask, set_nodedb_mask, NULL((void *)0)},
192 {"port_protocol", get_port_protocol, set_port_protocol, NULL((void *)0)},
193 {"active_profile", get_active_profile, set_active_profile, NULL((void *)0)},
194 {"firmware_write", NULL((void *)0), NULL((void *)0), ocs_mgmt_firmware_write},
195 {"firmware_reset", NULL((void *)0), NULL((void *)0), ocs_mgmt_firmware_reset},
196 {"function_reset", NULL((void *)0), NULL((void *)0), ocs_mgmt_function_reset},
197#if defined(OCS_INCLUDE_RAMD)
198 {"read_phys", NULL((void *)0), NULL((void *)0), ocs_mgmt_read_phys},
199#endif
200 {"force_assert", NULL((void *)0), NULL((void *)0), ocs_mgmt_force_assert},
201
202 {"tgt_rscn_delay", get_tgt_rscn_delay, set_tgt_rscn_delay, NULL((void *)0)},
203 {"tgt_rscn_period", get_tgt_rscn_period, set_tgt_rscn_period, NULL((void *)0)},
204 {"inject_drop_cmd", get_inject_drop_cmd, set_inject_drop_cmd, NULL((void *)0)},
205 {"inject_free_drop_cmd", get_inject_free_drop_cmd, set_inject_free_drop_cmd, NULL((void *)0)},
206 {"inject_drop_data", get_inject_drop_data, set_inject_drop_data, NULL((void *)0)},
207 {"inject_drop_resp", get_inject_drop_resp, set_inject_drop_resp, NULL((void *)0)},
208 {"cmd_err_inject", get_cmd_err_inject, set_cmd_err_inject, NULL((void *)0)},
209 {"cmd_delay_value", get_cmd_delay_value, set_cmd_delay_value, NULL((void *)0)},
210 {"nv_wwpn", get_nv_wwpn, NULL((void *)0), NULL((void *)0)},
211 {"nv_wwnn", get_nv_wwnn, NULL((void *)0), NULL((void *)0)},
212 {"nv_wwn", NULL((void *)0), set_nv_wwn, NULL((void *)0)},
213 {"node_abort_cnt", get_node_abort_cnt, NULL((void *)0), NULL((void *)0)},
214};
215
216/**
217 * @ingroup mgmt
218 * @brief Get a list of options supported by the driver.
219 *
220 * @par Description
221 * This is the top level "get list" handler for the driver. It
222 * performs the following:
223 * - Adds entries to the textbuf for any actions supported by this level in the driver.
224 * - Calls a back-end function to add any actions supported by the back-end.
225 * - Calls a function on each child (domain) to recursively add supported actions.
226 *
227 * @param ocs Pointer to the ocs structure.
228 * @param textbuf Pointer to an ocs_textbuf, which is used to accumulate the results.
229 *
230 * @return Returns 0 on success, or a negative value on failure.
231 */
232
233void
234ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
235{
236 ocs_domain_t *domain;
237 uint32_t i;
238 int access;
239
240 ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
241
242 for (i=0;i<ARRAY_SIZE(mgmt_table)(sizeof(mgmt_table) / sizeof((mgmt_table)[0]));i++) {
243 access = 0;
244 if (mgmt_table[i].get_handler) {
245 access |= MGMT_MODE_RD4;
246 }
247 if (mgmt_table[i].set_handler) {
248 access |= MGMT_MODE_WR2;
249 }
250 if (mgmt_table[i].action_handler) {
251 access |= MGMT_MODE_EX1;
252 }
253 ocs_mgmt_emit_property_name(textbuf, access, mgmt_table[i].name);
254 }
255
256 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_list_handler)) {
257 ocs->mgmt_functions->get_list_handler(textbuf, ocs);
258 }
259
260 if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_list_handler)) {
261 ocs->tgt_mgmt_functions->get_list_handler(textbuf, &(ocs->tgt_ocs));
262 }
263
264 /* Have each of my children add their actions */
265 if (ocs_device_lock_try(ocs) == TRUE1) {
266
267 /* If we get here then we are holding the device lock */
268 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
269 if ((domain->mgmt_functions) && (domain->mgmt_functions->get_list_handler)) {
270 domain->mgmt_functions->get_list_handler(textbuf, domain);
271 }
272 }
273 ocs_device_unlock(ocs);
274 }
275
276 ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
277
278}
279
280/**
281 * @ingroup mgmt
282 * @brief Return the value of a management item.
283 *
284 * @par Description
285 * This is the top level "get" handler for the driver. It
286 * performs the following:
287 * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
288 * - If the remaining part of the name matches a parameter that is known at this level,
289 * writes the value into textbuf.
290 * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
291 * - If the request has not been fulfilled by the back-end,
292 * passes the request to each of the children (domains) to
293 * have them (recursively) try to respond.
294 *
295 * In passing the request to other entities, the request is considered to be answered
296 * when a response has been written into textbuf, indicated by textbuf->buffer_written
297 * being non-zero.
298 *
299 * @param ocs Pointer to the ocs structure.
300 * @param name Name of the status item to be retrieved.
301 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
302 *
303 * @return Returns 0 if the value was found and returned, or -1 if an error occurred.
304 */
305
306
307int
308ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
309{
310 ocs_domain_t *domain;
311 char qualifier[6];
312 int retval = -1;
313 uint32_t i;
314
315 ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
316
317
318 snprintf(qualifier, sizeof(qualifier), "/ocs");
319
320 /* See if the name starts with my qualifier. If not then this request isn't for me */
321 if (ocs_strncmp(name, qualifier, strlen(qualifier))strncmp(name,qualifier,strlen(qualifier)) == 0) {
322 char *unqualified_name = name + strlen(qualifier) + 1;
323
324 for (i=0;i<ARRAY_SIZE(mgmt_table)(sizeof(mgmt_table) / sizeof((mgmt_table)[0]));i++) {
325 if (ocs_strcmp(unqualified_name, mgmt_table[i].name)strcmp(unqualified_name,mgmt_table[i].name) == 0) {
326 if (mgmt_table[i].get_handler) {
327 mgmt_table[i].get_handler(ocs, name, textbuf);
328 ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
329 return 0;
330 }
331 }
332 }
333
334 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_handler)) {
335 retval = ocs->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, ocs);
336 }
337
338 if (retval != 0) {
339 if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_handler)) {
340 retval = ocs->tgt_mgmt_functions->get_handler(textbuf, qualifier,
341 (char*)name, &(ocs->tgt_ocs));
342 }
343 }
344
345 if (retval != 0) {
346 /* The driver didn't handle it, pass it to each domain */
347
348 ocs_device_lock(ocs);
349 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
350 if ((domain->mgmt_functions) && (domain->mgmt_functions->get_handler)) {
351 retval = domain->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, domain);
352 }
353
354 if (retval == 0) {
355 break;
356 }
357
358
359 }
360 ocs_device_unlock(ocs);
361 }
362
363 }
364
365 ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
366
367 return retval;
368}
369
370
371/**
372 * @ingroup mgmt
373 * @brief Set the value of a mgmt item.
374 *
375 * @par Description
376 * This is the top level "set" handler for the driver. It
377 * performs the following:
378 * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
379 * - If the remaining part of the name matches a parameter that is known at this level,
380 * calls the correct function to change the configuration.
381 * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
382 * - If the request has not been fulfilled by the back-end, passes the request to each of the
383 * children (domains) to have them (recursively) try to respond.
384 *
385 * In passing the request to other entities, the request is considered to be handled
386 * if the function returns 0.
387 *
388 * @param ocs Pointer to the ocs structure.
389 * @param name Name of the property to be changed.
390 * @param value Requested new value of the property.
391 *
392 * @return Returns 0 if the configuration value was updated, or -1 otherwise.
393 */
394
395int
396ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
397{
398 ocs_domain_t *domain;
399 int result = -1;
400 char qualifier[80];
401 uint32_t i;
402
403 snprintf(qualifier, sizeof(qualifier), "/ocs");
404
405 /* If it doesn't start with my qualifier I don't know what to do with it */
406 if (ocs_strncmp(name, qualifier, strlen(qualifier))strncmp(name,qualifier,strlen(qualifier)) == 0) {
407 char *unqualified_name = name + strlen(qualifier) +1;
408
409 /* See if it's a value I can set */
410 for (i=0;i<ARRAY_SIZE(mgmt_table)(sizeof(mgmt_table) / sizeof((mgmt_table)[0]));i++) {
411 if (ocs_strcmp(unqualified_name, mgmt_table[i].name)strcmp(unqualified_name,mgmt_table[i].name) == 0) {
412 if (mgmt_table[i].set_handler) {
413 return mgmt_table[i].set_handler(ocs, name, value);
414 }
415 }
416 }
417
418 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->set_handler)) {
419 result = ocs->mgmt_functions->set_handler(qualifier, name, (char *)value, ocs);
420 }
421
422 if (result != 0) {
423 if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->set_handler)) {
424 result = ocs->tgt_mgmt_functions->set_handler(qualifier, name,
425 (char *)value, &(ocs->tgt_ocs));
426 }
427 }
428
429 /* If I didn't know how to set this config value pass the request to each of my children */
430 if (result != 0) {
431 ocs_device_lock(ocs);
432 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
433 if ((domain->mgmt_functions) && (domain->mgmt_functions->set_handler)) {
434 result = domain->mgmt_functions->set_handler(qualifier, name, (char*)value, domain);
435 }
436 if (result == 0) {
437 break;
438 }
439 }
440 ocs_device_unlock(ocs);
441 }
442
443
444 }
445
446 return result;
447}
448
449/**
450 * @ingroup mgmt
451 * @brief Perform a management action.
452 *
453 * @par Description
454 * This is the top level "exec" handler for the driver. It
455 * performs the following:
456 * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
457 * - If the remaining part of the name matches an action that is known at this level,
458 * calls the correct function to perform the action.
459 * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
460 * - If the request has not been fulfilled by the back-end, passes the request to each of the
461 * children (domains) to have them (recursively) try to respond.
462 *
463 * In passing the request to other entities, the request is considered to be handled
464 * if the function returns 0.
465 *
466 * @param ocs Pointer to the ocs structure.
467 * @param action Name of the action to be performed.
468 * @param arg_in Pointer to an argument being passed to the action.
469 * @param arg_in_length Length of the argument pointed to by @c arg_in.
470 * @param arg_out Pointer to an argument being passed to the action.
471 * @param arg_out_length Length of the argument pointed to by @c arg_out.
472 *
473 * @return Returns 0 if the action was completed, or -1 otherwise.
474 *
475 *
476 */
477
478int
479ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in,
480 uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
481{
482 ocs_domain_t *domain;
483 int result = -1;
484 char qualifier[80];
485 uint32_t i;
486
487 snprintf(qualifier, sizeof(qualifier), "/ocs");
488
489 /* If it doesn't start with my qualifier I don't know what to do with it */
490 if (ocs_strncmp(action, qualifier, strlen(qualifier))strncmp(action,qualifier,strlen(qualifier)) == 0) {
491 char *unqualified_name = action + strlen(qualifier) +1;
492
493 /* See if it's an action I can perform */
494 for (i=0;i<ARRAY_SIZE(mgmt_table)(sizeof(mgmt_table) / sizeof((mgmt_table)[0])); i++) {
495 if (ocs_strcmp(unqualified_name, mgmt_table[i].name)strcmp(unqualified_name,mgmt_table[i].name) == 0) {
496 if (mgmt_table[i].action_handler) {
497 return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length,
498 arg_out, arg_out_length);
499 }
500
501 }
502 }
503
504 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) {
505 result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
506 arg_out, arg_out_length, ocs);
507 }
508
509 if (result != 0) {
510 if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->exec_handler)) {
511 result = ocs->tgt_mgmt_functions->exec_handler(qualifier, action,
512 arg_in, arg_in_length, arg_out, arg_out_length,
513 &(ocs->tgt_ocs));
514 }
515 }
516
517 /* If I didn't know how to do this action pass the request to each of my children */
518 if (result != 0) {
519 ocs_device_lock(ocs);
520 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
521 if ((domain->mgmt_functions) && (domain->mgmt_functions->exec_handler)) {
522 result = domain->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, arg_out,
523 arg_out_length, domain);
524 }
525 if (result == 0) {
526 break;
527 }
528 }
529 ocs_device_unlock(ocs);
530 }
531
532 }
533
534 return result;
535}
536
537void
538ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
539{
540 ocs_domain_t *domain;
541 uint32_t i;
542
543 ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
544
545 for (i=0;i<ARRAY_SIZE(mgmt_table)(sizeof(mgmt_table) / sizeof((mgmt_table)[0]));i++) {
546 if (mgmt_table[i].get_handler) {
547 mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
548 } else if (mgmt_table[i].action_handler) {
549 /* No get_handler, but there's an action_handler. Just report
550 the name */
551 ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX1, mgmt_table[i].name);
552 }
553 }
554
555 if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_all_handler)) {
556 ocs->mgmt_functions->get_all_handler(textbuf, ocs);
557 }
558
559 if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_all_handler)) {
560 ocs->tgt_mgmt_functions->get_all_handler(textbuf, &(ocs->tgt_ocs));
561 }
562
563 ocs_device_lock(ocs);
564 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
565 if ((domain->mgmt_functions) && (domain->mgmt_functions->get_all_handler)) {
566 domain->mgmt_functions->get_all_handler(textbuf, domain);
567 }
568 }
569 ocs_device_unlock(ocs);
570
571 ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
572}
573
574#if defined(OCS_INCLUDE_RAMD)
575static int32_t
576ocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
577{
578 uint32_t length;
579 char addr_str[80];
580 uintptr_t target_addr;
581 void* vaddr = NULL((void *)0);
582 ocs_ramdisc_t **ramdisc_array;
583 uint32_t ramdisc_count;
584
585
586 if ((arg_in == NULL((void *)0)) ||
587 (arg_in_length == 0) ||
588 (arg_out == NULL((void *)0)) ||
589 (arg_out_length == 0)) {
590 return -1;
591 }
592
593 if (arg_in_length > 80) {
594 arg_in_length = 80;
595 }
596
597 if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)copyin(arg_in, addr_str, arg_in_length)) {
598 ocs_log_test(ocs, "Failed to copy addr from user\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 598, "Failed to copy addr from user\n"
); } } while (0);
;
599 return -EFAULT14;
600 }
601
602 target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0)strtoul(addr_str,((void *)0),0);
603 /* addr_str must be the physical address of a buffer that was reported
604 * in an SGL. Search ramdiscs looking for a segment that contains that
605 * physical address
606 */
607
608 if (ocs->tgt_ocs.use_global_ramd) {
609 /* Only one target */
610 ramdisc_count = ocs->tgt_ocs.rdisc_count;
611 ramdisc_array = ocs->tgt_ocs.rdisc;
612 vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
613 } else {
614 /* Multiple targets. Each target is on a sport */
615 uint32_t domain_idx;
616
617 for (domain_idx=0; domain_idx<ocs->domain_instance_count; domain_idx++) {
618 ocs_domain_t *domain;
619 uint32_t sport_idx;
620
621 domain = ocs_domain_get_instance(ocs, domain_idx);
622 for (sport_idx=0; sport_idx < domain->sport_instance_count; sport_idx++) {
623 ocs_sport_t *sport;
624
625 sport = ocs_sport_get_instance(domain, sport_idx);
626 ramdisc_count = sport->tgt_sport.rdisc_count;
627 ramdisc_array = sport->tgt_sport.rdisc;
628 vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
629
630 if (vaddr != NULL((void *)0)) {
631 break;
632 }
633 }
634 }
635 }
636
637
638
639
640 length = arg_out_length;
641
642 if (vaddr != NULL((void *)0)) {
643
644 if (ocs_copy_to_user(arg_out, vaddr, length)copyout(vaddr, arg_out, length)) {
645 ocs_log_test(ocs, "Failed to copy buffer to user\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 645, "Failed to copy buffer to user\n"
); } } while (0);
;
646 return -EFAULT14;
647 }
648
649 return 0;
650 } else {
651
652 return -EFAULT14;
653 }
654
655}
656
657/*
658 * This function searches a target for a given physical address.
659 * The target is made up of a number of LUNs, each represented by
660 * a ocs_ramdisc_t.
661 */
662static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr)
663{
664 void *vaddr = NULL((void *)0);
665 uint32_t ramdisc_idx;
666
667 /* Check each ramdisc */
668 for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) {
669 uint32_t segment_idx;
670 ocs_ramdisc_t *rdisc;
671 rdisc = ramdisc_array[ramdisc_idx];
672 /* Check each segment in the ramdisc */
673 for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) {
674 ramdisc_segment_t *segment = rdisc->segments[segment_idx];
675 uintptr_t segment_start;
676 uintptr_t segment_end;
677 uint32_t offset;
678
679 segment_start = segment->data_segment.phys;
680 segment_end = segment->data_segment.phys + segment->data_segment.size - 1;
681 if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
682 /* Found the target address */
683 offset = target_addr - segment_start;
684 vaddr = (uint32_t*)segment->data_segment.virt + offset;
685 }
686
687 if (rdisc->dif_separate) {
688 segment_start = segment->dif_segment.phys;
689 segment_end = segment->data_segment.phys + segment->dif_segment.size - 1;
690 if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
691 /* Found the target address */
692 offset = target_addr - segment_start;
693 vaddr = (uint32_t*)segment->dif_segment.virt + offset;
694 }
695 }
696
697 if (vaddr != NULL((void *)0)) {
698 break;
699 }
700
701 }
702
703 if (vaddr != NULL((void *)0)) {
704 break;
705 }
706
707
708 }
709
710 return vaddr;
711}
712#endif
713
714
715
716static int32_t
717ocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
718{
719 int rc = 0;
720 int index = 0;
721 uint8_t bus, dev, func;
722 ocs_t *other_ocs;
723
724 ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
725
726 ocs_log_debug(ocs, "Resetting port\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 726, "Resetting port\n"
); } } while (0);
;
727 if (ocs_hw_reset(&ocs->hw, OCS_HW_RESET_FIRMWARE)) {
728 ocs_log_test(ocs, "failed to reset port\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 728, "failed to reset port\n"
); } } while (0);
;
729 rc = -1;
730 } else {
731 ocs_log_debug(ocs, "successfully reset port\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 731, "successfully reset port\n"
); } } while (0);
;
732
733 /* now reset all functions on the same device */
734
735 while ((other_ocs = ocs_get_instance(index++)) != NULL((void *)0)) {
736 uint8_t other_bus, other_dev, other_func;
737
738 ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func);
739
740 if ((bus == other_bus) && (dev == other_dev)) {
741 if (other_ocs->hw.state !=
742 OCS_HW_STATE_UNINITIALIZED) {
743 other_ocs->hw.state =
744 OCS_HW_STATE_QUEUES_ALLOCATED;
745 }
746
747 ocs_device_detach(other_ocs);
748 if (ocs_device_attach(other_ocs)) {
749 ocs_log_err(other_ocs,do { if (1 <= loglevel) { _ocs_log(other_ocs, __func__, 750
, "device %d attach failed \n", index); } } while (0);
750 "device %d attach failed \n", index)do { if (1 <= loglevel) { _ocs_log(other_ocs, __func__, 750
, "device %d attach failed \n", index); } } while (0);
;
751 rc = -1;
752 }
753 }
754 }
755 }
756 return rc;
757}
758
759static int32_t
760ocs_mgmt_function_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
761{
762 int32_t rc;
763
764 ocs_device_detach(ocs);
765 rc = ocs_device_attach(ocs);
766
767 return rc;
768}
769
770static int32_t
771ocs_mgmt_firmware_write(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
772{
773 int rc = 0;
774 uint32_t bytes_left;
775 uint32_t xfer_size;
776 uint32_t offset;
777 uint8_t *userp;
778 ocs_dma_t dma;
779 int last = 0;
780 ocs_mgmt_fw_write_result_t result;
781 uint32_t change_status = 0;
782 char status_str[80];
783
784 ocs_sem_init(&(result.semaphore), 0, "fw_write");
785
786 bytes_left = buf_len;
787 offset = 0;
788 userp = (uint8_t *)buf;
789
790 if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE64*1024, 4096)) {
1
Assuming the condition is false
2
Taking false branch
791 ocs_log_err(ocs, "ocs_mgmt_firmware_write: malloc failed")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 791, "ocs_mgmt_firmware_write: malloc failed"
); } } while (0);
;
792 return -ENOMEM12;
793 }
794
795 while (bytes_left > 0) {
3
Assuming 'bytes_left' is <= 0
4
Loop condition is false. Execution continues on line 850
796
797
798 if (bytes_left > FW_WRITE_BUFSIZE64*1024) {
799 xfer_size = FW_WRITE_BUFSIZE64*1024;
800 } else {
801 xfer_size = bytes_left;
802 }
803
804 /* Copy xfer_size bytes from user space to kernel buffer */
805 if (ocs_copy_from_user(dma.virt, userp, xfer_size)copyin(userp, dma.virt, xfer_size)) {
806 rc = -EFAULT14;
807 break;
808 }
809
810 /* See if this is the last block */
811 if (bytes_left == xfer_size) {
812 last = 1;
813 }
814
815 /* Send the HW command */
816 ocs_hw_firmware_write(&ocs->hw, &dma, xfer_size, offset, last, ocs_mgmt_fw_write_cb, &result);
817
818 /* Wait for semaphore to be signaled when the command completes
819 * TODO: Should there be a timeout on this? If so, how long? */
820 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
821 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 821, "ocs_sem_p failed\n"
); } } while (0);
;
822 rc = -ENXIO6;
823 break;
824 }
825
826 if (result.actual_xfer == 0) {
827 ocs_log_test(ocs, "actual_write_length is %d\n", result.actual_xfer)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 827, "actual_write_length is %d\n"
, result.actual_xfer); } } while (0);
;
828 rc = -EFAULT14;
829 break;
830 }
831
832 /* Check status */
833 if (result.status != 0) {
834 ocs_log_test(ocs, "write returned status %d\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 834, "write returned status %d\n"
, result.status); } } while (0);
;
835 rc = -EFAULT14;
836 break;
837 }
838
839 if (last) {
840 change_status = result.change_status;
841 }
842
843 bytes_left -= result.actual_xfer;
844 offset += result.actual_xfer;
845 userp += result.actual_xfer;
846
847 }
848
849 /* Create string with status and copy to userland */
850 if ((arg_out_length > 0) && (arg_out != NULL((void *)0))) {
5
Assuming 'arg_out_length' is > 0
6
Assuming 'arg_out' is not equal to NULL
7
Taking true branch
851 if (arg_out_length > sizeof(status_str)) {
8
Assuming the condition is true
9
Taking true branch
852 arg_out_length = sizeof(status_str);
853 }
854 ocs_snprintf(status_str, arg_out_length, "%d", change_status)snprintf(status_str, arg_out_length, "%d", change_status);
10
Partial initialization occurs here
855 if (ocs_copy_to_user(arg_out, status_str, arg_out_length)copyout(status_str, arg_out, arg_out_length)) {
11
Copies out a struct with a partially unsanitized field
856 ocs_log_test(ocs, "copy to user failed for change_status\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 856, "copy to user failed for change_status\n"
); } } while (0);
;
857 }
858 }
859
860
861 ocs_dma_free(ocs, &dma);
862
863 return rc;
864}
865
866static void
867ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg)
868{
869 ocs_mgmt_fw_write_result_t *result = arg;
870
871 result->status = status;
872 result->actual_xfer = actual_write_length;
873 result->change_status = change_status;
874
875 ocs_sem_v(&(result->semaphore));
876}
877
878typedef struct ocs_mgmt_sfp_result {
879 ocs_sem_t semaphore;
880 ocs_lock_t cb_lock;
881 int32_t running;
882 int32_t status;
883 uint32_t bytes_read;
884 uint32_t page_data[32];
885} ocs_mgmt_sfp_result_t;
886
887static void
888ocs_mgmt_sfp_cb(void *os, int32_t status, uint32_t bytes_read, uint32_t *data, void *arg)
889{
890 ocs_mgmt_sfp_result_t *result = arg;
891 ocs_t *ocs = os;
892
893 ocs_lock(&(result->cb_lock));
894 result->running++;
895 if(result->running == 2) {
896 /* get_sfp() has timed out */
897 ocs_unlock(&(result->cb_lock));
898 ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
899 return;
900 }
901
902 result->status = status;
903 result->bytes_read = bytes_read;
904 ocs_memcpy(&result->page_data, data, SFP_PAGE_SIZE)__builtin_memcpy((&result->page_data), (data), (128));
905
906 ocs_sem_v(&(result->semaphore));
907 ocs_unlock(&(result->cb_lock));
908}
909
910static int32_t
911ocs_mgmt_get_sfp(ocs_t *ocs, uint16_t page, void *buf, uint32_t buf_len)
912{
913 int rc = 0;
914 ocs_mgmt_sfp_result_t *result = ocs_malloc(ocs, sizeof(ocs_mgmt_sfp_result_t), OCS_M_ZERO0x0100 | OCS_M_NOWAIT0x0001);;
915
916 ocs_sem_init(&(result->semaphore), 0, "get_sfp");
917 ocs_lock_init(ocs, &(result->cb_lock), "get_sfp");
918
919 /* Send the HW command */
920 ocs_hw_get_sfp(&ocs->hw, page, ocs_mgmt_sfp_cb, result);
921
922 /* Wait for semaphore to be signaled when the command completes */
923 if (ocs_sem_p(&(result->semaphore), 5 * 1000 * 1000) != 0) {
924 /* Timed out, callback will free memory */
925 ocs_lock(&(result->cb_lock));
926 result->running++;
927 if(result->running == 1) {
928 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 928, "ocs_sem_p failed\n"
); } } while (0);
;
929 ocs_unlock(&(result->cb_lock));
930 return (-ENXIO6);
931 }
932 /* sfp_cb() has already executed, proceed as normal */
933 ocs_unlock(&(result->cb_lock));
934 }
935
936 /* Check status */
937 if (result->status != 0) {
938 ocs_log_test(ocs, "read_transceiver_data returned status %d\n",do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 939, "read_transceiver_data returned status %d\n"
, result->status); } } while (0);
939 result->status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 939, "read_transceiver_data returned status %d\n"
, result->status); } } while (0);
;
940 rc = -EFAULT14;
941 }
942
943 if (rc == 0) {
944 rc = (result->bytes_read > buf_len ? buf_len : result->bytes_read);
945 /* Copy the results back to the supplied buffer */
946 ocs_memcpy(buf, result->page_data, rc)__builtin_memcpy((buf), (result->page_data), (rc));
947 }
948
949 ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
950 return rc;
951}
952
953static int32_t
954ocs_mgmt_force_assert(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
955{
956 ocs_assert(FALSE, 0)do { if (!(0)) { _ocs_assert("FALSE", "/root/freebsd/sys/dev/ocs_fc/ocs_mgmt.c"
, 956); return 0; } } while (0)
;
957}
958
959static void
960get_nodes_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
961{
962 ocs_xport_t *xport = ocs->xport;
963
964 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "nodes_count", "%d", xport->nodes_count);
965}
966
967static void
968get_driver_version(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
969{
970 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "driver_version", ocs->driver_version);
971}
972
973static void
974get_desc(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
975{
976 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "desc", ocs->desc);
977}
978
979static void
980get_fw_rev(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
981{
982 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "fw_rev", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV));
983}
984
985static void
986get_fw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
987{
988 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "fw_rev2", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV2));
989}
990
991static void
992get_ipl(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
993{
994 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "ipl", ocs_hw_get_ptr(&ocs->hw, OCS_HW_IPL));
995}
996
997static void
998get_hw_rev1(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
999{
1000 uint32_t value;
1001
1002 ocs_hw_get(&ocs->hw, OCS_HW_HW_REV1, &value);
1003
1004 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "hw_rev1", "%u", value);
1005}
1006
1007static void
1008get_hw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1009{
1010 uint32_t value;
1011
1012 ocs_hw_get(&ocs->hw, OCS_HW_HW_REV2, &value);
1013
1014 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "hw_rev2", "%u", value);
1015}
1016
1017static void
1018get_hw_rev3(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1019{
1020 uint32_t value;
1021 ocs_hw_get(&ocs->hw, OCS_HW_HW_REV3, &value);
1022
1023 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "hw_rev3", "%u", value);
1024}
1025
1026static void
1027get_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1028{
1029 uint64_t *wwnn;
1030
1031 wwnn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_NODE);
1032
1033 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "wwnn", "0x%llx", (unsigned long long)ocs_htobe64(*wwnn)(__builtin_constant_p((*wwnn)) ? (((__uint64_t)(__builtin_constant_p
(((__uint64_t)((*wwnn))) & 0xffffffff) ? (((__uint32_t)((
__uint16_t)(__builtin_constant_p(((__uint32_t)(((__uint64_t)(
(*wwnn))) & 0xffffffff)) & 0xffff) ? (__uint16_t)(((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwnn))) & 0xffffffff)) &
0xffff)) << 8 | ((__uint16_t)(((__uint32_t)(((__uint64_t
)((*wwnn))) & 0xffffffff)) & 0xffff)) >> 8) : __bswap16_var
(((__uint32_t)(((__uint64_t)((*wwnn))) & 0xffffffff)) &
0xffff))) << 16) | ((__uint16_t)(__builtin_constant_p(
((__uint32_t)(((__uint64_t)((*wwnn))) & 0xffffffff)) >>
16) ? (__uint16_t)(((__uint16_t)(((__uint32_t)(((__uint64_t)
((*wwnn))) & 0xffffffff)) >> 16)) << 8 | ((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwnn))) & 0xffffffff)) >>
16)) >> 8) : __bswap16_var(((__uint32_t)(((__uint64_t)
((*wwnn))) & 0xffffffff)) >> 16)))) : __bswap32_var
(((__uint64_t)((*wwnn))) & 0xffffffff)) << 32) | (__builtin_constant_p
(((__uint64_t)((*wwnn))) >> 32) ? (((__uint32_t)((__uint16_t
)(__builtin_constant_p(((__uint32_t)(((__uint64_t)((*wwnn))) >>
32)) & 0xffff) ? (__uint16_t)(((__uint16_t)(((__uint32_t
)(((__uint64_t)((*wwnn))) >> 32)) & 0xffff)) <<
8 | ((__uint16_t)(((__uint32_t)(((__uint64_t)((*wwnn))) >>
32)) & 0xffff)) >> 8) : __bswap16_var(((__uint32_t
)(((__uint64_t)((*wwnn))) >> 32)) & 0xffff))) <<
16) | ((__uint16_t)(__builtin_constant_p(((__uint32_t)(((__uint64_t
)((*wwnn))) >> 32)) >> 16) ? (__uint16_t)(((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwnn))) >> 32)) >>
16)) << 8 | ((__uint16_t)(((__uint32_t)(((__uint64_t)(
(*wwnn))) >> 32)) >> 16)) >> 8) : __bswap16_var
(((__uint32_t)(((__uint64_t)((*wwnn))) >> 32)) >>
16)))) : __bswap32_var(((__uint64_t)((*wwnn))) >> 32))
) : __bswap64_var((*wwnn)))
);
1034}
1035
1036static void
1037get_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1038{
1039 uint64_t *wwpn;
1040
1041 wwpn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_PORT);
1042
1043 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "wwpn", "0x%llx", (unsigned long long)ocs_htobe64(*wwpn)(__builtin_constant_p((*wwpn)) ? (((__uint64_t)(__builtin_constant_p
(((__uint64_t)((*wwpn))) & 0xffffffff) ? (((__uint32_t)((
__uint16_t)(__builtin_constant_p(((__uint32_t)(((__uint64_t)(
(*wwpn))) & 0xffffffff)) & 0xffff) ? (__uint16_t)(((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwpn))) & 0xffffffff)) &
0xffff)) << 8 | ((__uint16_t)(((__uint32_t)(((__uint64_t
)((*wwpn))) & 0xffffffff)) & 0xffff)) >> 8) : __bswap16_var
(((__uint32_t)(((__uint64_t)((*wwpn))) & 0xffffffff)) &
0xffff))) << 16) | ((__uint16_t)(__builtin_constant_p(
((__uint32_t)(((__uint64_t)((*wwpn))) & 0xffffffff)) >>
16) ? (__uint16_t)(((__uint16_t)(((__uint32_t)(((__uint64_t)
((*wwpn))) & 0xffffffff)) >> 16)) << 8 | ((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwpn))) & 0xffffffff)) >>
16)) >> 8) : __bswap16_var(((__uint32_t)(((__uint64_t)
((*wwpn))) & 0xffffffff)) >> 16)))) : __bswap32_var
(((__uint64_t)((*wwpn))) & 0xffffffff)) << 32) | (__builtin_constant_p
(((__uint64_t)((*wwpn))) >> 32) ? (((__uint32_t)((__uint16_t
)(__builtin_constant_p(((__uint32_t)(((__uint64_t)((*wwpn))) >>
32)) & 0xffff) ? (__uint16_t)(((__uint16_t)(((__uint32_t
)(((__uint64_t)((*wwpn))) >> 32)) & 0xffff)) <<
8 | ((__uint16_t)(((__uint32_t)(((__uint64_t)((*wwpn))) >>
32)) & 0xffff)) >> 8) : __bswap16_var(((__uint32_t
)(((__uint64_t)((*wwpn))) >> 32)) & 0xffff))) <<
16) | ((__uint16_t)(__builtin_constant_p(((__uint32_t)(((__uint64_t
)((*wwpn))) >> 32)) >> 16) ? (__uint16_t)(((__uint16_t
)(((__uint32_t)(((__uint64_t)((*wwpn))) >> 32)) >>
16)) << 8 | ((__uint16_t)(((__uint32_t)(((__uint64_t)(
(*wwpn))) >> 32)) >> 16)) >> 8) : __bswap16_var
(((__uint32_t)(((__uint64_t)((*wwpn))) >> 32)) >>
16)))) : __bswap32_var(((__uint64_t)((*wwpn))) >> 32))
) : __bswap64_var((*wwpn)))
);
1044}
1045
1046static void
1047get_fcid(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1048{
1049
1050 if (ocs->domain && ocs->domain->attached) {
1051 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "fc_id", "0x%06x",
1052 ocs->domain->sport->fc_id);
1053 } else {
1054 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "fc_id", "UNKNOWN");
1055 }
1056
1057}
1058
1059static void
1060get_sn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1061{
1062 uint8_t *pserial;
1063 uint32_t len;
1064 char sn_buf[256];
1065
1066 pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_SERIALNUMBER);
1067 if (pserial) {
1068 len = *pserial ++;
1069 strncpy(sn_buf, (char*)pserial, len);
1070 sn_buf[len] = '\0';
1071 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "sn", sn_buf);
1072 }
1073}
1074
1075static void
1076get_pn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1077{
1078 uint8_t *pserial;
1079 uint32_t len;
1080 char sn_buf[256];
1081
1082 pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PARTNUMBER);
1083 if (pserial) {
1084 len = *pserial ++;
1085 strncpy(sn_buf, (char*)pserial, len);
1086 sn_buf[len] = '\0';
1087 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "pn", sn_buf);
1088 } else {
1089 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "pn", ocs->model);
1090 }
1091}
1092
1093static void
1094get_sli4_intf_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1095{
1096
1097 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "sli4_intf_reg", "0x%04x",
1098 ocs_config_read32(ocs, SLI4_INTF_REG0x0058));
1099}
1100
1101static void
1102get_phy_port_num(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1103{
1104 char *phy_port = NULL((void *)0);
1105
1106 phy_port = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PORTNUM);
1107 if (phy_port) {
1108 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "phy_port_num", phy_port);
1109 } else {
1110 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "phy_port_num", "unknown");
1111 }
1112}
1113static void
1114get_asic_id(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1115{
1116
1117 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "asic_id_reg", "0x%04x",
1118 ocs_config_read32(ocs, SLI4_ASIC_ID_REG0x009c));
1119}
1120
1121static void
1122get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1123{
1124 uint32_t family;
1125 uint32_t asic_id;
1126 uint32_t asic_gen_num;
1127 uint32_t asic_rev_num;
1128 uint32_t rev_id;
1129 char result_buf[80];
1130 char tmp_buf[80];
1131
1132 family = (ocs_config_read32(ocs, SLI4_INTF_REG0x0058) & 0x00000f00) >> 8;
1133 asic_id = ocs_config_read32(ocs, SLI4_ASIC_ID_REG0x009c);
1134 asic_rev_num = asic_id & 0xff;
1135 asic_gen_num = (asic_id & 0xff00) >> 8;
1136
1137 rev_id = ocs_config_read32(ocs, SLI4_PCI_CLASS_REVISION0x0008) & 0xff;
1138
1139 switch(family) {
1140 case 0x00:
1141 /* BE2 */
1142 ocs_strncpy(result_buf, "BE2 A", sizeof(result_buf))strncpy(result_buf, "BE2 A", sizeof(result_buf));
1143 ocs_snprintf(tmp_buf, 2, "%d", rev_id)snprintf(tmp_buf, 2, "%d", rev_id);
1144 strcat(result_buf, tmp_buf);
1145 break;
1146 case 0x01:
1147 /* BE3 */
1148 ocs_strncpy(result_buf, "BE3", sizeof(result_buf))strncpy(result_buf, "BE3", sizeof(result_buf));
1149 if (rev_id >= 0x10) {
1150 strcat(result_buf, "-R");
1151 }
1152 ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A')snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) +
'A')
;
1153 strcat(result_buf, tmp_buf);
1154 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f)snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1155 strcat(result_buf, tmp_buf);
1156 break;
1157 case 0x02:
1158 /* Skyhawk A0 */
1159 ocs_strncpy(result_buf, "Skyhawk A0", sizeof(result_buf))strncpy(result_buf, "Skyhawk A0", sizeof(result_buf));
1160 break;
1161 case 0x0a:
1162 /* Lancer A0 */
1163 ocs_strncpy(result_buf, "Lancer A", sizeof(result_buf))strncpy(result_buf, "Lancer A", sizeof(result_buf));
1164 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f)snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1165 strcat(result_buf, tmp_buf);
1166 break;
1167 case 0x0b:
1168 /* Lancer B0 or D0 */
1169 ocs_strncpy(result_buf, "Lancer", sizeof(result_buf))strncpy(result_buf, "Lancer", sizeof(result_buf));
1170 ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A')snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) +
'A')
;
1171 strcat(result_buf, tmp_buf);
1172 ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f)snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1173 strcat(result_buf, tmp_buf);
1174 break;
1175 case 0x0c:
1176 ocs_strncpy(result_buf, "Lancer G6", sizeof(result_buf))strncpy(result_buf, "Lancer G6", sizeof(result_buf));
1177 break;
1178 case 0x0f:
1179 /* Refer to ASIC_ID */
1180 switch(asic_gen_num) {
1181 case 0x00:
1182 ocs_strncpy(result_buf, "BE2", sizeof(result_buf))strncpy(result_buf, "BE2", sizeof(result_buf));
1183 break;
1184 case 0x03:
1185 ocs_strncpy(result_buf, "BE3-R", sizeof(result_buf))strncpy(result_buf, "BE3-R", sizeof(result_buf));
1186 break;
1187 case 0x04:
1188 ocs_strncpy(result_buf, "Skyhawk-R", sizeof(result_buf))strncpy(result_buf, "Skyhawk-R", sizeof(result_buf));
1189 break;
1190 case 0x05:
1191 ocs_strncpy(result_buf, "Corsair", sizeof(result_buf))strncpy(result_buf, "Corsair", sizeof(result_buf));
1192 break;
1193 case 0x0b:
1194 ocs_strncpy(result_buf, "Lancer", sizeof(result_buf))strncpy(result_buf, "Lancer", sizeof(result_buf));
1195 break;
1196 case 0x0c:
1197 ocs_strncpy(result_buf, "LancerG6", sizeof(result_buf))strncpy(result_buf, "LancerG6", sizeof(result_buf));
1198 break;
1199 default:
1200 ocs_strncpy(result_buf, "Unknown", sizeof(result_buf))strncpy(result_buf, "Unknown", sizeof(result_buf));
1201 }
1202 if (ocs_strcmp(result_buf, "Unknown")strcmp(result_buf,"Unknown") != 0) {
1203 ocs_snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >> 4) + 'A')snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >>
4) + 'A')
;
1204 strcat(result_buf, tmp_buf);
1205 ocs_snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f)snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f);
1206 strcat(result_buf, tmp_buf);
1207 }
1208 break;
1209 default:
1210 ocs_strncpy(result_buf, "Unknown", sizeof(result_buf))strncpy(result_buf, "Unknown", sizeof(result_buf));
1211 }
1212
1213 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "chip_type", result_buf);
1214
1215}
1216
1217static void
1218get_pci_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1219{
1220
1221 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "pci_vendor", "0x%04x", ocs->pci_vendor);
1222}
1223
1224static void
1225get_pci_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1226{
1227
1228 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "pci_device", "0x%04x", ocs->pci_device);
1229}
1230
1231static void
1232get_pci_subsystem_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1233{
1234
1235 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "pci_subsystem_vendor", "0x%04x", ocs->pci_subsystem_vendor);
1236}
1237
1238static void
1239get_pci_subsystem_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1240{
1241
1242 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "pci_subsystem_device", "0x%04x", ocs->pci_subsystem_device);
1243}
1244
1245static void
1246get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1247{
1248 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "tgt_rscn_delay", "%ld", (unsigned long)ocs->tgt_rscn_delay_msec / 1000);
1249}
1250
1251static void
1252get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1253{
1254 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "tgt_rscn_period", "%ld", (unsigned long)ocs->tgt_rscn_period_msec / 1000);
1255}
1256
1257static void
1258get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1259{
1260 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "inject_drop_cmd", "%d",
1261 (ocs->err_injection == INJECT_DROP_CMD ? 1:0));
1262}
1263
1264static void
1265get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1266{
1267 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "inject_free_drop_cmd", "%d",
1268 (ocs->err_injection == INJECT_FREE_DROPPED ? 1:0));
1269}
1270
1271static void
1272get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1273{
1274 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "inject_drop_data", "%d",
1275 (ocs->err_injection == INJECT_DROP_DATA ? 1:0));
1276}
1277
1278static void
1279get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1280{
1281 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "inject_drop_resp", "%d",
1282 (ocs->err_injection == INJECT_DROP_RESP ? 1:0));
1283}
1284
1285static void
1286get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1287{
1288 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "cmd_err_inject", "0x%02x", ocs->cmd_err_inject);
1289}
1290
1291static void
1292get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1293{
1294 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "cmd_delay_value", "%ld", (unsigned long)ocs->delay_value_msec);
1295}
1296
1297static void
1298get_businfo(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1299{
1300 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "businfo", ocs->businfo);
1301}
1302
1303static void
1304get_sfp_a0(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1305{
1306 uint8_t *page_data;
1307 char *buf;
1308 int i;
1309 int32_t bytes_read;
1310
1311 page_data = ocs_malloc(ocs, SFP_PAGE_SIZE128, OCS_M_ZERO0x0100 | OCS_M_NOWAIT0x0001);
1312 if (page_data == NULL((void *)0)) {
1313 return;
1314 }
1315
1316 buf = ocs_malloc(ocs, (SFP_PAGE_SIZE128 * 3) + 1, OCS_M_ZERO0x0100 | OCS_M_NOWAIT0x0001);
1317 if (buf == NULL((void *)0)) {
1318 ocs_free(ocs, page_data, SFP_PAGE_SIZE128);
1319 return;
1320 }
1321
1322 bytes_read = ocs_mgmt_get_sfp(ocs, 0xa0, page_data, SFP_PAGE_SIZE128);
1323
1324 if (bytes_read <= 0) {
1325 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "sfp_a0", "(unknown)");
1326 } else {
1327 char *d = buf;
1328 uint8_t *s = page_data;
1329 int buffer_remaining = (SFP_PAGE_SIZE128 * 3) + 1;
1330 int bytes_added;
1331
1332 for (i = 0; i < bytes_read; i++) {
1333 bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s)snprintf(d, buffer_remaining, "%02x ", *s);
1334 ++s;
1335 d += bytes_added;
1336 buffer_remaining -= bytes_added;
1337 }
1338 *d = '\0';
1339 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "sfp_a0", buf);
1340 }
1341
1342 ocs_free(ocs, page_data, SFP_PAGE_SIZE128);
1343 ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE128) + 1);
1344}
1345
1346static void
1347get_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1348{
1349 uint8_t *page_data;
1350 char *buf;
1351 int i;
1352 int32_t bytes_read;
1353
1354 page_data = ocs_malloc(ocs, SFP_PAGE_SIZE128, OCS_M_ZERO0x0100 | OCS_M_NOWAIT0x0001);
1355 if (page_data == NULL((void *)0)) {
1356 return;
1357 }
1358
1359 buf = ocs_malloc(ocs, (SFP_PAGE_SIZE128 * 3) + 1, OCS_M_ZERO0x0100 | OCS_M_NOWAIT0x0001);
1360 if (buf == NULL((void *)0)) {
1361 ocs_free(ocs, page_data, SFP_PAGE_SIZE128);
1362 return;
1363 }
1364
1365 bytes_read = ocs_mgmt_get_sfp(ocs, 0xa2, page_data, SFP_PAGE_SIZE128);
1366
1367 if (bytes_read <= 0) {
1368 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "sfp_a2", "(unknown)");
1369 } else {
1370 char *d = buf;
1371 uint8_t *s = page_data;
1372 int buffer_remaining = (SFP_PAGE_SIZE128 * 3) + 1;
1373 int bytes_added;
1374
1375 for (i=0; i < bytes_read; i++) {
1376 bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s)snprintf(d, buffer_remaining, "%02x ", *s);
1377 ++s;
1378 d += bytes_added;
1379 buffer_remaining -= bytes_added;
1380 }
1381 *d = '\0';
1382 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "sfp_a2", buf);
1383 }
1384
1385 ocs_free(ocs, page_data, SFP_PAGE_SIZE128);
1386 ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE128) + 1);
1387}
1388
1389static void
1390get_debug_mq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1391{
1392
1393 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW(4 | 2), "debug_mq_dump",
1394 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP(1U << 1)));
1395}
1396
1397static void
1398get_debug_cq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1399{
1400
1401 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW(4 | 2), "debug_cq_dump",
1402 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_CQ_DUMP(1U << 2)));
1403}
1404
1405static void
1406get_debug_wq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1407{
1408 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW(4 | 2), "debug_wq_dump",
1409 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_WQ_DUMP(1U << 3)));
1410}
1411
1412static void
1413get_debug_eq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1414{
1415 ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW(4 | 2), "debug_eq_dump",
1416 ocs_debug_is_enabled(OCS_DEBUG_ENABLE_EQ_DUMP(1U << 4)));
1417}
1418
1419static void
1420get_logmask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1421{
1422
1423 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "logmask", "0x%02x", ocs->logmask);
1424
1425}
1426
1427static void
1428get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1429{
1430
1431 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "loglevel", "%d", loglevel);
1432
1433}
1434
1435static void
1436get_current_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1437{
1438 uint32_t value;
1439
1440 ocs_hw_get(&(ocs->hw), OCS_HW_LINK_SPEED, &value);
1441
1442 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "current_speed", "%d", value);
1443}
1444
1445static void
1446get_configured_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1447{
1448 uint32_t value;
1449
1450 ocs_hw_get(&(ocs->hw), OCS_HW_LINK_CONFIG_SPEED, &value);
1451 if (value == 0) {
1452 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "configured_speed", "auto");
1453 } else {
1454 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "configured_speed", "%d", value);
1455 }
1456
1457}
1458
1459static void
1460get_current_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1461{
1462 uint32_t value;
1463
1464 ocs_hw_get(&(ocs->hw), OCS_HW_TOPOLOGY, &value);
1465 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "current_topology", "%d", value);
1466
1467}
1468
1469static void
1470get_configured_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1471{
1472 uint32_t value;
1473
1474 ocs_hw_get(&(ocs->hw), OCS_HW_CONFIG_TOPOLOGY, &value);
1475 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "configured_topology", "%d", value);
1476
1477}
1478
1479static void
1480get_current_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1481{
1482 ocs_xport_stats_t value;
1483
1484 if (ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value) == 0) {
1485 if (value.value == OCS_XPORT_PORT_ONLINE) {
1486 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "current_link_state", "online");
1487 } else {
1488 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "current_link_state", "offline");
1489 }
1490 }
1491}
1492
1493static void
1494get_configured_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1495{
1496 ocs_xport_stats_t value;
1497
1498 if (ocs_xport_status(ocs->xport, OCS_XPORT_CONFIG_PORT_STATUS, &value) == 0) {
1499 if (value.value == OCS_XPORT_PORT_ONLINE) {
1500 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "configured_link_state", "online");
1501 } else {
1502 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "configured_link_state", "offline");
1503 }
1504 }
1505}
1506
1507/**
1508 * @brief HW link config enum to mgmt string value mapping.
1509 *
1510 * This structure provides a mapping from the ocs_hw_linkcfg_e
1511 * enum (enum exposed for the OCS_HW_PORT_SET_LINK_CONFIG port
1512 * control) to the mgmt string that is passed in by the mgmt application
1513 * (elxsdkutil).
1514 */
1515typedef struct ocs_mgmt_linkcfg_map_s {
1516 ocs_hw_linkcfg_e linkcfg;
1517 const char *mgmt_str;
1518} ocs_mgmt_linkcfg_map_t;
1519
1520static ocs_mgmt_linkcfg_map_t mgmt_linkcfg_map[] = {
1521 {OCS_HW_LINKCFG_4X10G, OCS_CONFIG_LINKCFG_4X10G"ETH_4x10G"},
1522 {OCS_HW_LINKCFG_1X40G, OCS_CONFIG_LINKCFG_1X40G"ETH_1x40G"},
1523 {OCS_HW_LINKCFG_2X16G, OCS_CONFIG_LINKCFG_2X16G"FC_2x16G"},
1524 {OCS_HW_LINKCFG_4X8G, OCS_CONFIG_LINKCFG_4X8G"FC_4x8G"},
1525 {OCS_HW_LINKCFG_4X1G, OCS_CONFIG_LINKCFG_4X1G"FC_4x1G"},
1526 {OCS_HW_LINKCFG_2X10G, OCS_CONFIG_LINKCFG_2X10G"ETH_2x10G"},
1527 {OCS_HW_LINKCFG_2X10G_2X8G, OCS_CONFIG_LINKCFG_2X10G_2X8G"ETH_2x10G_FC_2x8G"}};
1528
1529/**
1530 * @brief Get the HW linkcfg enum from the mgmt config string.
1531 *
1532 * @param mgmt_str mgmt string value.
1533 *
1534 * @return Returns the HW linkcfg enum corresponding to clp_str.
1535 */
1536static ocs_hw_linkcfg_e
1537ocs_hw_linkcfg_from_mgmt(const char *mgmt_str)
1538{
1539 uint32_t i;
1540 for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map)(sizeof(mgmt_linkcfg_map) / sizeof((mgmt_linkcfg_map)[0])); i++) {
1541 if (ocs_strncmp(mgmt_linkcfg_map[i].mgmt_str,strncmp(mgmt_linkcfg_map[i].mgmt_str,mgmt_str,strlen(mgmt_str
))
1542 mgmt_str, ocs_strlen(mgmt_str))strncmp(mgmt_linkcfg_map[i].mgmt_str,mgmt_str,strlen(mgmt_str
))
== 0) {
1543 return mgmt_linkcfg_map[i].linkcfg;
1544 }
1545 }
1546 return OCS_HW_LINKCFG_NA;
1547}
1548
1549/**
1550 * @brief Get the mgmt string value from the HW linkcfg enum.
1551 *
1552 * @param linkcfg HW linkcfg enum.
1553 *
1554 * @return Returns the mgmt string value corresponding to the given HW linkcfg.
1555 */
1556static const char *
1557ocs_mgmt_from_hw_linkcfg(ocs_hw_linkcfg_e linkcfg)
1558{
1559 uint32_t i;
1560 for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map)(sizeof(mgmt_linkcfg_map) / sizeof((mgmt_linkcfg_map)[0])); i++) {
1561 if (mgmt_linkcfg_map[i].linkcfg == linkcfg) {
1562 return mgmt_linkcfg_map[i].mgmt_str;
1563 }
1564 }
1565 return OCS_CONFIG_LINKCFG_UNKNOWN"UNKNOWN";
1566}
1567
1568/**
1569 * @brief Link configuration callback argument
1570 */
1571typedef struct ocs_mgmt_linkcfg_arg_s {
1572 ocs_sem_t semaphore;
1573 int32_t status;
1574 ocs_hw_linkcfg_e linkcfg;
1575} ocs_mgmt_linkcfg_arg_t;
1576
1577/**
1578 * @brief Get linkcfg config value
1579 *
1580 * @param ocs Pointer to the ocs structure.
1581 * @param name Not used.
1582 * @param textbuf The textbuf to which the result is written.
1583 *
1584 * @return None.
1585 */
1586static void
1587get_linkcfg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1588{
1589 const char *linkcfg_str = NULL((void *)0);
1590 uint32_t value;
1591 ocs_hw_linkcfg_e linkcfg;
1592 ocs_hw_get(&ocs->hw, OCS_HW_LINKCFG, &value);
1593 linkcfg = (ocs_hw_linkcfg_e)value;
1594 linkcfg_str = ocs_mgmt_from_hw_linkcfg(linkcfg);
1595 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "linkcfg", linkcfg_str);
1596}
1597
1598/**
1599 * @brief Get requested WWNN config value
1600 *
1601 * @param ocs Pointer to the ocs structure.
1602 * @param name Not used.
1603 * @param textbuf The textbuf to which the result is written.
1604 *
1605 * @return None.
1606 */
1607static void
1608get_req_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1609{
1610 ocs_xport_t *xport = ocs->xport;
1611
1612 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "requested_wwnn", "0x%llx", (unsigned long long)xport->req_wwnn);
1613}
1614
1615/**
1616 * @brief Get requested WWPN config value
1617 *
1618 * @param ocs Pointer to the ocs structure.
1619 * @param name Not used.
1620 * @param textbuf The textbuf to which the result is written.
1621 *
1622 * @return None.
1623 */
1624static void
1625get_req_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1626{
1627 ocs_xport_t *xport = ocs->xport;
1628
1629 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "requested_wwpn", "0x%llx", (unsigned long long)xport->req_wwpn);
1630}
1631
1632/**
1633 * @brief Get requested nodedb_mask config value
1634 *
1635 * @param ocs Pointer to the ocs structure.
1636 * @param name Not used.
1637 * @param textbuf The textbuf to which the result is written.
1638 *
1639 * @return None.
1640 */
1641static void
1642get_nodedb_mask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1643{
1644 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW(4 | 2), "nodedb_mask", "0x%08x", ocs->nodedb_mask);
1645}
1646
1647/**
1648 * @brief Set requested WWNN value.
1649 *
1650 * @param ocs Pointer to the ocs structure.
1651 * @param name Not used.
1652 * @param value Value to which the linkcfg is set.
1653 *
1654 * @return Returns 0 on success.
1655 */
1656
1657int
1658set_req_wwnn(ocs_t *ocs, char *name, char *value)
1659{
1660 int rc;
1661 uint64_t wwnn;
1662
1663 if (ocs_strcasecmp(value, "default")strcasecmp(value,"default") == 0) {
1664 wwnn = 0;
1665 }
1666 else if (parse_wwn(value, &wwnn) != 0) {
1667 ocs_log_test(ocs, "Invalid WWNN: %s\n", value)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1667, "Invalid WWNN: %s\n"
, value); } } while (0);
;
1668 return 1;
1669 }
1670
1671 rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWNN_SET, wwnn);
1672
1673 if(rc) {
1674 ocs_log_test(ocs, "OCS_XPORT_WWNN_SET failed: %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1674, "OCS_XPORT_WWNN_SET failed: %d\n"
, rc); } } while (0);
;
1675 return rc;
1676 }
1677
1678 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1679 if (rc) {
1680 ocs_log_test(ocs, "port offline failed : %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1680, "port offline failed : %d\n"
, rc); } } while (0);
;
1681 }
1682
1683 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1684 if (rc) {
1685 ocs_log_test(ocs, "port online failed : %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1685, "port online failed : %d\n"
, rc); } } while (0);
;
1686 }
1687
1688 return rc;
1689}
1690
1691/**
1692 * @brief Set requested WWNP value.
1693 *
1694 * @param ocs Pointer to the ocs structure.
1695 * @param name Not used.
1696 * @param value Value to which the linkcfg is set.
1697 *
1698 * @return Returns 0 on success.
1699 */
1700
1701int
1702set_req_wwpn(ocs_t *ocs, char *name, char *value)
1703{
1704 int rc;
1705 uint64_t wwpn;
1706
1707 if (ocs_strcasecmp(value, "default")strcasecmp(value,"default") == 0) {
1708 wwpn = 0;
1709 }
1710 else if (parse_wwn(value, &wwpn) != 0) {
1711 ocs_log_test(ocs, "Invalid WWPN: %s\n", value)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1711, "Invalid WWPN: %s\n"
, value); } } while (0);
;
1712 return 1;
1713 }
1714
1715 rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWPN_SET, wwpn);
1716
1717 if(rc) {
1718 ocs_log_test(ocs, "OCS_XPORT_WWPN_SET failed: %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1718, "OCS_XPORT_WWPN_SET failed: %d\n"
, rc); } } while (0);
;
1719 return rc;
1720 }
1721
1722 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1723 if (rc) {
1724 ocs_log_test(ocs, "port offline failed : %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1724, "port offline failed : %d\n"
, rc); } } while (0);
;
1725 }
1726
1727 rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1728 if (rc) {
1729 ocs_log_test(ocs, "port online failed : %d\n", rc)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1729, "port online failed : %d\n"
, rc); } } while (0);
;
1730 }
1731
1732 return rc;
1733}
1734
1735/**
1736 * @brief Set node debug mask value
1737 *
1738 * @param ocs Pointer to the ocs structure.
1739 * @param name Not used.
1740 * @param value Value to which the nodedb_mask is set.
1741 *
1742 * @return Returns 0 on success.
1743 */
1744static int
1745set_nodedb_mask(ocs_t *ocs, char *name, char *value)
1746{
1747 ocs->nodedb_mask = ocs_strtoul(value, 0, 0)strtoul(value,0,0);
1748 return 0;
1749}
1750
1751/**
1752 * @brief Set linkcfg config value.
1753 *
1754 * @param ocs Pointer to the ocs structure.
1755 * @param name Not used.
1756 * @param value Value to which the linkcfg is set.
1757 *
1758 * @return Returns 0 on success.
1759 */
1760static int
1761set_linkcfg(ocs_t *ocs, char *name, char *value)
1762{
1763 ocs_hw_linkcfg_e linkcfg;
1764 ocs_mgmt_linkcfg_arg_t cb_arg;
1765 ocs_hw_rtn_e status;
1766
1767 ocs_sem_init(&cb_arg.semaphore, 0, "mgmt_linkcfg");
1768
1769 /* translate mgmt linkcfg string to HW linkcfg enum */
1770 linkcfg = ocs_hw_linkcfg_from_mgmt(value);
1771
1772 /* set HW linkcfg */
1773 status = ocs_hw_port_control(&ocs->hw, OCS_HW_PORT_SET_LINK_CONFIG,
1774 (uintptr_t)linkcfg, ocs_mgmt_linkcfg_cb, &cb_arg);
1775 if (status) {
1776 ocs_log_test(ocs, "ocs_hw_set_linkcfg failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1776, "ocs_hw_set_linkcfg failed\n"
); } } while (0);
;
1777 return -1;
1778 }
1779
1780 if (ocs_sem_p(&cb_arg.semaphore, OCS_SEM_FOREVER(-1))) {
1781 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 1781, "ocs_sem_p failed\n"
); } } while (0);
;
1782 return -1;
1783 }
1784
1785 if (cb_arg.status) {
1786 ocs_log_test(ocs, "failed to set linkcfg from HW status=%d\n",do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1787, "failed to set linkcfg from HW status=%d\n"
, cb_arg.status); } } while (0);
1787 cb_arg.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1787, "failed to set linkcfg from HW status=%d\n"
, cb_arg.status); } } while (0);
;
1788 return -1;
1789 }
1790
1791 return 0;
1792}
1793
1794/**
1795 * @brief Linkcfg callback
1796 *
1797 * @param status Result of the linkcfg get/set operation.
1798 * @param value Resulting linkcfg value.
1799 * @param arg Callback argument.
1800 *
1801 * @return None.
1802 */
1803static void
1804ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg)
1805{
1806 ocs_mgmt_linkcfg_arg_t *cb_arg = (ocs_mgmt_linkcfg_arg_t *)arg;
1807 cb_arg->status = status;
1808 cb_arg->linkcfg = (ocs_hw_linkcfg_e)value;
1809 ocs_sem_v(&cb_arg->semaphore);
1810}
1811
1812static int
1813set_debug_mq_dump(ocs_t *ocs, char *name, char *value)
1814{
1815 int result;
1816
1817 if (ocs_strcasecmp(value, "false")strcasecmp(value,"false") == 0) {
1818 ocs_debug_disable(OCS_DEBUG_ENABLE_MQ_DUMP(1U << 1));
1819 result = 0;
1820 } else if (ocs_strcasecmp(value, "true")strcasecmp(value,"true") == 0) {
1821 ocs_debug_enable(OCS_DEBUG_ENABLE_MQ_DUMP(1U << 1));
1822 result = 0;
1823 } else {
1824 result = -1;
1825 }
1826
1827 return result;
1828}
1829
1830static int
1831set_debug_cq_dump(ocs_t *ocs, char *name, char *value)
1832{
1833 int result;
1834
1835 if (ocs_strcasecmp(value, "false")strcasecmp(value,"false") == 0) {
1836 ocs_debug_disable(OCS_DEBUG_ENABLE_CQ_DUMP(1U << 2));
1837 result = 0;
1838 } else if (ocs_strcasecmp(value, "true")strcasecmp(value,"true") == 0) {
1839 ocs_debug_enable(OCS_DEBUG_ENABLE_CQ_DUMP(1U << 2));
1840 result = 0;
1841 } else {
1842 result = -1;
1843 }
1844
1845 return result;
1846}
1847
1848static int
1849set_debug_wq_dump(ocs_t *ocs, char *name, char *value)
1850{
1851 int result;
1852
1853 if (ocs_strcasecmp(value, "false")strcasecmp(value,"false") == 0) {
1854 ocs_debug_disable(OCS_DEBUG_ENABLE_WQ_DUMP(1U << 3));
1855 result = 0;
1856 } else if (ocs_strcasecmp(value, "true")strcasecmp(value,"true") == 0) {
1857 ocs_debug_enable(OCS_DEBUG_ENABLE_WQ_DUMP(1U << 3));
1858 result = 0;
1859 } else {
1860 result = -1;
1861 }
1862
1863 return result;
1864}
1865
1866static int
1867set_debug_eq_dump(ocs_t *ocs, char *name, char *value)
1868{
1869 int result;
1870
1871 if (ocs_strcasecmp(value, "false")strcasecmp(value,"false") == 0) {
1872 ocs_debug_disable(OCS_DEBUG_ENABLE_EQ_DUMP(1U << 4));
1873 result = 0;
1874 } else if (ocs_strcasecmp(value, "true")strcasecmp(value,"true") == 0) {
1875 ocs_debug_enable(OCS_DEBUG_ENABLE_EQ_DUMP(1U << 4));
1876 result = 0;
1877 } else {
1878 result = -1;
1879 }
1880
1881 return result;
1882}
1883
1884static int
1885set_logmask(ocs_t *ocs, char *name, char *value)
1886{
1887
1888 ocs->logmask = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
1889
1890 return 0;
1891}
1892
1893static int
1894set_loglevel(ocs_t *ocs, char *name, char *value)
1895{
1896
1897 loglevel = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
1898
1899 return 0;
1900}
1901
1902int
1903set_configured_speed(ocs_t *ocs, char *name, char *value)
1904{
1905 int result = 0;
1906 ocs_hw_rtn_e hw_rc;
1907 int xport_rc;
1908 uint32_t spd;
1909
1910 spd = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
1911
1912 if ((spd != 0) && (spd != 2000) && (spd != 4000) &&
1913 (spd != 8000) && (spd != 16000) && (spd != 32000)) {
1914 ocs_log_test(ocs, "unsupported speed %d\n", spd)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1914, "unsupported speed %d\n"
, spd); } } while (0);
;
1915 return 1;
1916 }
1917
1918 ocs_log_debug(ocs, "Taking port offline\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1918, "Taking port offline\n"
); } } while (0);
;
1919 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1920 if (xport_rc != 0) {
1921 ocs_log_test(ocs, "Port offline failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1921, "Port offline failed\n"
); } } while (0);
;
1922 result = 1;
1923 } else {
1924 ocs_log_debug(ocs, "Setting port to speed %d\n", spd)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1924, "Setting port to speed %d\n"
, spd); } } while (0);
;
1925 hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_LINK_SPEED, spd);
1926 if (hw_rc != OCS_HW_RTN_SUCCESS) {
1927 ocs_log_test(ocs, "Speed set failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1927, "Speed set failed\n"
); } } while (0);
;
1928 result = 1;
1929 }
1930
1931 /* If we failed to set the speed we still want to try to bring
1932 * the port back online */
1933
1934 ocs_log_debug(ocs, "Bringing port online\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1934, "Bringing port online\n"
); } } while (0);
;
1935 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1936 if (xport_rc != 0) {
1937 result = 1;
1938 }
1939 }
1940
1941 return result;
1942}
1943
1944int
1945set_configured_topology(ocs_t *ocs, char *name, char *value)
1946{
1947 int result = 0;
1948 ocs_hw_rtn_e hw_rc;
1949 int xport_rc;
1950 uint32_t topo;
1951
1952 topo = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
1953 if (topo >= OCS_HW_TOPOLOGY_NONE) {
1954 return 1;
1955 }
1956
1957 ocs_log_debug(ocs, "Taking port offline\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1957, "Taking port offline\n"
); } } while (0);
;
1958 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1959 if (xport_rc != 0) {
1960 ocs_log_test(ocs, "Port offline failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1960, "Port offline failed\n"
); } } while (0);
;
1961 result = 1;
1962 } else {
1963 ocs_log_debug(ocs, "Setting port to topology %d\n", topo)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1963, "Setting port to topology %d\n"
, topo); } } while (0);
;
1964 hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_TOPOLOGY, topo);
1965 if (hw_rc != OCS_HW_RTN_SUCCESS) {
1966 ocs_log_test(ocs, "Topology set failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1966, "Topology set failed\n"
); } } while (0);
;
1967 result = 1;
1968 }
1969
1970 /* If we failed to set the topology we still want to try to bring
1971 * the port back online */
1972
1973 ocs_log_debug(ocs, "Bringing port online\n")do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1973, "Bringing port online\n"
); } } while (0);
;
1974 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1975 if (xport_rc != 0) {
1976 result = 1;
1977 }
1978 }
1979
1980 return result;
1981}
1982
1983static int
1984set_configured_link_state(ocs_t *ocs, char *name, char *value)
1985{
1986 int result = 0;
1987 int xport_rc;
1988
1989 if (ocs_strcasecmp(value, "offline")strcasecmp(value,"offline") == 0) {
1990 ocs_log_debug(ocs, "Setting port to %s\n", value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1990, "Setting port to %s\n"
, value); } } while (0);
;
1991 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
1992 if (xport_rc != 0) {
1993 ocs_log_test(ocs, "Setting port to offline failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 1993, "Setting port to offline failed\n"
); } } while (0);
;
1994 result = -1;
1995 }
1996 } else if (ocs_strcasecmp(value, "online")strcasecmp(value,"online") == 0) {
1997 ocs_log_debug(ocs, "Setting port to %s\n", value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 1997, "Setting port to %s\n"
, value); } } while (0);
;
1998 xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
1999 if (xport_rc != 0) {
2000 ocs_log_test(ocs, "Setting port to online failed\n")do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2000, "Setting port to online failed\n"
); } } while (0);
;
2001 result = -1;
2002 }
2003 } else {
2004 ocs_log_test(ocs, "Unsupported link state \"%s\"\n", value)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2004, "Unsupported link state \"%s\"\n"
, value); } } while (0);
;
2005 result = -1;
2006 }
2007
2008 return result;
2009}
2010
2011typedef struct ocs_mgmt_get_port_protocol_result {
2012 ocs_sem_t semaphore;
2013 int32_t status;
2014 ocs_hw_port_protocol_e port_protocol;
2015} ocs_mgmt_get_port_protocol_result_t;
2016
2017
2018static void
2019ocs_mgmt_get_port_protocol_cb(int32_t status,
2020 ocs_hw_port_protocol_e port_protocol,
2021 void *arg)
2022{
2023 ocs_mgmt_get_port_protocol_result_t *result = arg;
2024
2025 result->status = status;
2026 result->port_protocol = port_protocol;
2027
2028 ocs_sem_v(&(result->semaphore));
2029}
2030
2031static void
2032get_port_protocol(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2033{
2034 ocs_mgmt_get_port_protocol_result_t result;
2035 uint8_t bus;
2036 uint8_t dev;
2037 uint8_t func;
2038
2039 ocs_sem_init(&(result.semaphore), 0, "get_port_protocol");
2040
2041 ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
2042
2043 if(ocs_hw_get_port_protocol(&ocs->hw, func, ocs_mgmt_get_port_protocol_cb, &result) == OCS_HW_RTN_SUCCESS) {
2044 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2045 /* Undefined failure */
2046 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2046, "ocs_sem_p failed\n"
); } } while (0);
;
2047 }
2048 if (result.status == 0) {
2049 switch (result.port_protocol) {
2050 case OCS_HW_PORT_PROTOCOL_ISCSI:
2051 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "port_protocol", "iSCSI");
2052 break;
2053 case OCS_HW_PORT_PROTOCOL_FCOE:
2054 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "port_protocol", "FCoE");
2055 break;
2056 case OCS_HW_PORT_PROTOCOL_FC:
2057 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "port_protocol", "FC");
2058 break;
2059 case OCS_HW_PORT_PROTOCOL_OTHER:
2060 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "port_protocol", "Other");
2061 break;
2062 }
2063 } else {
2064 ocs_log_test(ocs, "getting port profile status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2064, "getting port profile status 0x%x\n"
, result.status); } } while (0);
;
2065 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "port_protocol", "Unknown");
2066 }
2067 }
2068}
2069
2070typedef struct ocs_mgmt_set_port_protocol_result {
2071 ocs_sem_t semaphore;
2072 int32_t status;
2073} ocs_mgmt_set_port_protocol_result_t;
2074
2075
2076
2077static void
2078ocs_mgmt_set_port_protocol_cb(int32_t status,
2079 void *arg)
2080{
2081 ocs_mgmt_get_port_protocol_result_t *result = arg;
2082
2083 result->status = status;
2084
2085 ocs_sem_v(&(result->semaphore));
2086}
2087
2088/**
2089 * @brief Set port protocol
2090 * @par Description
2091 * This is a management action handler to set the current
2092 * port protocol. Input value should be one of iSCSI,
2093 * FC, or FCoE.
2094 *
2095 * @param ocs Pointer to the ocs structure.
2096 * @param name Name of the action being performed.
2097 * @param value The value to be assigned
2098 *
2099 * @return Returns 0 on success, non-zero on failure.
2100 */
2101static int32_t
2102set_port_protocol(ocs_t *ocs, char *name, char *value)
2103{
2104 ocs_mgmt_set_port_protocol_result_t result;
2105 int32_t rc = 0;
2106 ocs_hw_port_protocol_e new_protocol;
2107 uint8_t bus;
2108 uint8_t dev;
2109 uint8_t func;
2110
2111 ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
2112
2113 ocs_sem_init(&(result.semaphore), 0, "set_port_protocol");
2114
2115 if (ocs_strcasecmp(value, "iscsi")strcasecmp(value,"iscsi") == 0) {
2116 new_protocol = OCS_HW_PORT_PROTOCOL_ISCSI;
2117 } else if (ocs_strcasecmp(value, "fc")strcasecmp(value,"fc") == 0) {
2118 new_protocol = OCS_HW_PORT_PROTOCOL_FC;
2119 } else if (ocs_strcasecmp(value, "fcoe")strcasecmp(value,"fcoe") == 0) {
2120 new_protocol = OCS_HW_PORT_PROTOCOL_FCOE;
2121 } else {
2122 return -1;
2123 }
2124
2125 rc = ocs_hw_set_port_protocol(&ocs->hw, new_protocol, func,
2126 ocs_mgmt_set_port_protocol_cb, &result);
2127 if (rc == OCS_HW_RTN_SUCCESS) {
2128 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2129 /* Undefined failure */
2130 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2130, "ocs_sem_p failed\n"
); } } while (0);
;
2131 rc = -ENXIO6;
2132 }
2133 if (result.status == 0) {
2134 /* Success. */
2135 rc = 0;
2136 } else {
2137 rc = -1;
2138 ocs_log_test(ocs, "setting active profile status 0x%x\n",do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2139, "setting active profile status 0x%x\n"
, result.status); } } while (0);
2139 result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2139, "setting active profile status 0x%x\n"
, result.status); } } while (0);
;
2140 }
2141 }
2142
2143 return rc;
2144}
2145
2146typedef struct ocs_mgmt_get_profile_list_result_s {
2147 ocs_sem_t semaphore;
2148 int32_t status;
2149 ocs_hw_profile_list_t *list;
2150} ocs_mgmt_get_profile_list_result_t;
2151
2152static void
2153ocs_mgmt_get_profile_list_cb(int32_t status, ocs_hw_profile_list_t *list, void *ul_arg)
2154{
2155 ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2156
2157 result->status = status;
2158 result->list = list;
2159
2160 ocs_sem_v(&(result->semaphore));
2161}
2162
2163/**
2164 * @brief Get list of profiles
2165 * @par Description
2166 * This is a management action handler to get the list of
2167 * profiles supported by the SLI port. Although the spec says
2168 * that all SLI platforms support this, only Skyhawk actually
2169 * has a useful implementation.
2170 *
2171 * @param ocs Pointer to the ocs structure.
2172 * @param name Name of the action being performed.
2173 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2174 *
2175 * @return none
2176 */
2177static void
2178get_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2179{
2180 ocs_mgmt_get_profile_list_result_t result;
2181
2182 ocs_sem_init(&(result.semaphore), 0, "get_profile_list");
2183
2184 if(ocs_hw_get_profile_list(&ocs->hw, ocs_mgmt_get_profile_list_cb, &result) == OCS_HW_RTN_SUCCESS) {
2185 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2186 /* Undefined failure */
2187 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2187, "ocs_sem_p failed\n"
); } } while (0);
;
2188 }
2189 if (result.status == 0) {
2190 /* Success. */
2191#define MAX_LINE_SIZE520 520
2192#define BUFFER_SIZE520*40 MAX_LINE_SIZE520*40
2193 char *result_buf;
2194 char result_line[MAX_LINE_SIZE520];
2195 uint32_t bytes_left;
2196 uint32_t i;
2197
2198 result_buf = ocs_malloc(ocs, BUFFER_SIZE520*40, OCS_M_ZERO0x0100);
2199 bytes_left = BUFFER_SIZE520*40;
2200
2201 for (i=0; i<result.list->num_descriptors; i++) {
2202 sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id,
2203 result.list->descriptors[i].profile_description);
2204 if (strlen(result_line) < bytes_left) {
2205 strcat(result_buf, result_line);
2206 bytes_left -= strlen(result_line);
2207 }
2208 }
2209
2210
2211 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD4, "profile_list", result_buf);
2212
2213 ocs_free(ocs, result_buf, BUFFER_SIZE520*40);
2214 ocs_free(ocs, result.list, sizeof(ocs_hw_profile_list_t));
2215 } else {
2216 ocs_log_test(ocs, "getting profile list status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2216, "getting profile list status 0x%x\n"
, result.status); } } while (0);
;
2217 }
2218 }
2219}
2220
2221typedef struct ocs_mgmt_get_active_profile_result {
2222 ocs_sem_t semaphore;
2223 int32_t status;
2224 uint32_t active_profile_id;
2225} ocs_mgmt_get_active_profile_result_t;
2226
2227static void
2228ocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul_arg)
2229{
2230 ocs_mgmt_get_active_profile_result_t *result = ul_arg;
2231
2232 result->status = status;
2233 result->active_profile_id = active_profile;
2234
2235 ocs_sem_v(&(result->semaphore));
2236}
2237
2238#define MAX_PROFILE_LENGTH5 5
2239
2240/**
2241 * @brief Get active profile
2242 * @par Description
2243 * This is a management action handler to get the currently
2244 * active profile for an SLI port. Although the spec says that
2245 * all SLI platforms support this, only Skyhawk actually has a
2246 * useful implementation.
2247 *
2248 * @param ocs Pointer to the ocs structure.
2249 * @param name Name of the action being performed.
2250 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2251 *
2252 * @return none
2253 */
2254static void
2255get_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2256{
2257 char result_string[MAX_PROFILE_LENGTH5];
2258 ocs_mgmt_get_active_profile_result_t result;
2259
2260 ocs_sem_init(&(result.semaphore), 0, "get_active_profile");
2261
2262 if(ocs_hw_get_active_profile(&ocs->hw, ocs_mgmt_get_active_profile_cb, &result) == OCS_HW_RTN_SUCCESS) {
2263 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2264 /* Undefined failure */
2265 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2265, "ocs_sem_p failed\n"
); } } while (0);
;
2266 }
2267 if (result.status == 0) {
2268 /* Success. */
2269 sprintf(result_string, "0x%02x", result.active_profile_id);
2270 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "active_profile", result_string);
2271 } else {
2272 ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2272, "getting active profile status 0x%x\n"
, result.status); } } while (0);
;
2273 }
2274 }
2275}
2276
2277typedef struct ocs_mgmt_set_active_profile_result {
2278 ocs_sem_t semaphore;
2279 int32_t status;
2280} ocs_mgmt_set_active_profile_result_t;
2281
2282
2283static void
2284ocs_mgmt_set_active_profile_cb(int32_t status, void *ul_arg)
2285{
2286 ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2287
2288 result->status = status;
2289
2290 ocs_sem_v(&(result->semaphore));
2291}
2292
2293/**
2294 * @brief Set active profile
2295 * @par Description
2296 * This is a management action handler to set the currently
2297 * active profile for an SLI port. Although the spec says that
2298 * all SLI platforms support this, only Skyhawk actually has a
2299 * useful implementation.
2300 *
2301 * @param ocs Pointer to the ocs structure.
2302 * @param name Name of the action being performed.
2303 * @param value Requested new value of the property.
2304 *
2305 * @return Returns 0 on success, non-zero on failure.
2306 */
2307static int32_t
2308set_active_profile(ocs_t *ocs, char *name, char *value)
2309{
2310 ocs_mgmt_set_active_profile_result_t result;
2311 int32_t rc = 0;
2312 int32_t new_profile;
2313
2314 new_profile = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
2315
2316 ocs_sem_init(&(result.semaphore), 0, "set_active_profile");
2317
2318 rc = ocs_hw_set_active_profile(&ocs->hw, ocs_mgmt_set_active_profile_cb, new_profile, &result);
2319 if (rc == OCS_HW_RTN_SUCCESS) {
2320 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2321 /* Undefined failure */
2322 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2322, "ocs_sem_p failed\n"
); } } while (0);
;
2323 rc = -ENXIO6;
2324 }
2325 if (result.status == 0) {
2326 /* Success. */
2327 rc = 0;
2328 } else {
2329 rc = -1;
2330 ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2330, "setting active profile status 0x%x\n"
, result.status); } } while (0);
;
2331 }
2332 }
2333
2334 return rc;
2335}
2336
2337typedef struct ocs_mgmt_get_nvparms_result {
2338 ocs_sem_t semaphore;
2339 int32_t status;
2340 uint8_t wwpn[8];
2341 uint8_t wwnn[8];
2342 uint8_t hard_alpa;
2343 uint32_t preferred_d_id;
2344} ocs_mgmt_get_nvparms_result_t;
2345
2346static void
2347ocs_mgmt_get_nvparms_cb(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
2348 uint32_t preferred_d_id, void *ul_arg)
2349{
2350 ocs_mgmt_get_nvparms_result_t *result = ul_arg;
2351
2352 result->status = status;
2353 ocs_memcpy(result->wwpn, wwpn, sizeof(result->wwpn))__builtin_memcpy((result->wwpn), (wwpn), (sizeof(result->
wwpn)))
;
2354 ocs_memcpy(result->wwnn, wwnn, sizeof(result->wwnn))__builtin_memcpy((result->wwnn), (wwnn), (sizeof(result->
wwnn)))
;
2355 result->hard_alpa = hard_alpa;
2356 result->preferred_d_id = preferred_d_id;
2357
2358 ocs_sem_v(&(result->semaphore));
2359}
2360
2361/**
2362 * @brief Get wwpn
2363 * @par Description
2364 *
2365 *
2366 * @param ocs Pointer to the ocs structure.
2367 * @param name Name of the action being performed.
2368 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2369 *
2370 * @return none
2371 */
2372static void
2373get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2374{
2375 char result_string[24];
2376 ocs_mgmt_get_nvparms_result_t result;
2377
2378 ocs_sem_init(&(result.semaphore), 0, "get_nv_wwpn");
2379
2380 if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) {
2381 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2382 /* Undefined failure */
2383 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2383, "ocs_sem_p failed\n"
); } } while (0);
;
2384 return;
2385 }
2386 if (result.status == 0) {
2387 /* Success. Copy wwpn from result struct to result string */
2388 sprintf(result_string, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
2389 result.wwpn[0], result.wwpn[1], result.wwpn[2],
2390 result.wwpn[3], result.wwpn[4], result.wwpn[5],
2391 result.wwpn[6], result.wwpn[7]);
2392 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "nv_wwpn", result_string);
2393 } else {
2394 ocs_log_test(ocs, "getting wwpn status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2394, "getting wwpn status 0x%x\n"
, result.status); } } while (0);
;
2395 }
2396 }
2397}
2398
2399/**
2400 * @brief Get wwnn
2401 * @par Description
2402 *
2403 *
2404 * @param ocs Pointer to the ocs structure.
2405 * @param name Name of the action being performed.
2406 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2407 *
2408 * @return none
2409 */
2410static void
2411get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2412{
2413 char result_string[24];
2414 ocs_mgmt_get_nvparms_result_t result;
2415
2416 ocs_sem_init(&(result.semaphore), 0, "get_nv_wwnn");
2417
2418 if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) {
2419 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2420 /* Undefined failure */
2421 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2421, "ocs_sem_p failed\n"
); } } while (0);
;
2422 return;
2423 }
2424 if (result.status == 0) {
2425 /* Success. Copy wwnn from result struct to result string */
2426 ocs_snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
, result.wwnn[0], result.wwnn[1], result.wwnn[2], result.wwnn
[3], result.wwnn[4], result.wwnn[5], result.wwnn[6], result.wwnn
[7])
2427 result.wwnn[0], result.wwnn[1], result.wwnn[2],snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
, result.wwnn[0], result.wwnn[1], result.wwnn[2], result.wwnn
[3], result.wwnn[4], result.wwnn[5], result.wwnn[6], result.wwnn
[7])
2428 result.wwnn[3], result.wwnn[4], result.wwnn[5],snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
, result.wwnn[0], result.wwnn[1], result.wwnn[2], result.wwnn
[3], result.wwnn[4], result.wwnn[5], result.wwnn[6], result.wwnn
[7])
2429 result.wwnn[6], result.wwnn[7])snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
, result.wwnn[0], result.wwnn[1], result.wwnn[2], result.wwnn
[3], result.wwnn[4], result.wwnn[5], result.wwnn[6], result.wwnn
[7])
;
2430 ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW(4 | 2), "nv_wwnn", result_string);
2431 } else {
2432 ocs_log_test(ocs, "getting wwnn status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2432, "getting wwnn status 0x%x\n"
, result.status); } } while (0);
;
2433 }
2434 }
2435}
2436
2437/**
2438 * @brief Get accumulated node abort counts
2439 * @par Description Get the sum of all nodes abort count.
2440 *
2441 * @param ocs Pointer to the ocs structure.
2442 * @param name Name of the action being performed.
2443 * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2444 *
2445 * @return None.
2446 */
2447static void
2448get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2449{
2450 uint32_t abort_counts = 0;
2451 ocs_domain_t *domain;
2452 ocs_sport_t *sport;
2453 ocs_node_t *node;
2454
2455 if (ocs_device_lock_try(ocs) != TRUE1) {
2456 /* Didn't get the lock */
2457 return;
2458 }
2459
2460 /* Here the Device lock is held */
2461 ocs_list_foreach(&ocs->domain_list, domain)for (domain = ocs_list_get_head((&ocs->domain_list)); domain
; domain = ocs_list_next((&ocs->domain_list), domain) )
{
2462 if (ocs_domain_lock_try(domain) != TRUE1) {
2463 /* Didn't get the lock */
2464 ocs_device_unlock(ocs);
2465 return;
2466 }
2467
2468 /* Here the Domain lock is held */
2469 ocs_list_foreach(&domain->sport_list, sport)for (sport = ocs_list_get_head((&domain->sport_list));
sport; sport = ocs_list_next((&domain->sport_list), sport
) )
{
2470 if (ocs_sport_lock_try(sport) != TRUE1) {
2471 /* Didn't get the lock */
2472 ocs_domain_unlock(domain);
2473 ocs_device_unlock(ocs);
2474 return;
2475 }
2476
2477 /* Here the sport lock is held */
2478 ocs_list_foreach(&sport->node_list, node)for (node = ocs_list_get_head((&sport->node_list)); node
; node = ocs_list_next((&sport->node_list), node) )
{
2479 abort_counts += node->abort_cnt;
2480 }
2481
2482 ocs_sport_unlock(sport);
2483 }
2484
2485 ocs_domain_unlock(domain);
2486 }
2487
2488 ocs_device_unlock(ocs);
2489
2490 ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD4, "node_abort_cnt", "%d" , abort_counts);
2491}
2492
2493typedef struct ocs_mgmt_set_nvparms_result {
2494 ocs_sem_t semaphore;
2495 int32_t status;
2496} ocs_mgmt_set_nvparms_result_t;
2497
2498
2499static void
2500ocs_mgmt_set_nvparms_cb(int32_t status, void *ul_arg)
2501{
2502 ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2503
2504 result->status = status;
2505
2506 ocs_sem_v(&(result->semaphore));
2507}
2508
2509/**
2510 * @brief Set wwn
2511 * @par Description Sets the Non-volatile worldwide names,
2512 * if provided.
2513 *
2514 * @param ocs Pointer to the ocs structure.
2515 * @param name Name of the action being performed.
2516 * @param wwn_p Requested new WWN values.
2517 *
2518 * @return Returns 0 on success, non-zero on failure.
2519 */
2520static int32_t
2521set_nv_wwn(ocs_t *ocs, char *name, char *wwn_p)
2522{
2523 ocs_mgmt_get_nvparms_result_t result;
2524 uint8_t new_wwpn[8];
2525 uint8_t new_wwnn[8];
2526 char *wwpn_p = NULL((void *)0);
2527 char *wwnn_p = NULL((void *)0);
2528 int32_t rc = -1;
2529 int wwpn;
2530 int wwnn;
2531 int i;
2532
2533 /* This is a read-modify-write operation, so first we have to read
2534 * the current values
2535 */
2536 ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn1");
2537
2538 rc = ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result);
2539
2540 if (rc == OCS_HW_RTN_SUCCESS) {
2541 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2542 /* Undefined failure */
2543 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2543, "ocs_sem_p failed\n"
); } } while (0);
;
2544 return -ENXIO6;
2545 }
2546 if (result.status != 0) {
2547 ocs_log_test(ocs, "getting nvparms status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2547, "getting nvparms status 0x%x\n"
, result.status); } } while (0);
;
2548 return -1;
2549 }
2550 }
2551
2552 /* wwn_p contains wwpn_p@wwnn_p values */
2553 if (wwn_p != NULL((void *)0)) {
2554 wwpn_p = ocs_strsep(&wwn_p, "@")strsep(&wwn_p, "@");
2555 wwnn_p = wwn_p;
2556 }
2557
2558 wwpn = ocs_strcmp(wwpn_p, "NA")strcmp(wwpn_p,"NA");
2559 wwnn = ocs_strcmp(wwnn_p, "NA")strcmp(wwnn_p,"NA");
2560
2561 /* Parse the new WWPN */
2562 if ((wwpn_p != NULL((void *)0)) && (wwpn != 0)) {
2563 if (ocs_sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
&(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]), &
(new_wwpn[6]), &(new_wwpn[7]))
2564 &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
&(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]), &
(new_wwpn[6]), &(new_wwpn[7]))
2565 &(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]),sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
&(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]), &
(new_wwpn[6]), &(new_wwpn[7]))
2566 &(new_wwpn[6]), &(new_wwpn[7]))sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
&(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]), &
(new_wwpn[6]), &(new_wwpn[7]))
!= 8) {
2567 ocs_log_test(ocs, "can't parse WWPN %s\n", wwpn_p)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2567, "can't parse WWPN %s\n"
, wwpn_p); } } while (0);
;
2568 return -1;
2569 }
2570 }
2571
2572 /* Parse the new WWNN */
2573 if ((wwnn_p != NULL((void *)0)) && (wwnn != 0 )) {
2574 if (ocs_sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
&(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]), &
(new_wwnn[6]), &(new_wwnn[7]))
2575 &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
&(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]), &
(new_wwnn[6]), &(new_wwnn[7]))
2576 &(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]),sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
&(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]), &
(new_wwnn[6]), &(new_wwnn[7]))
2577 &(new_wwnn[6]), &(new_wwnn[7]))sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
, &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
&(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]), &
(new_wwnn[6]), &(new_wwnn[7]))
!= 8) {
2578 ocs_log_test(ocs, "can't parse WWNN %s\n", wwnn_p)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2578, "can't parse WWNN %s\n"
, wwnn_p); } } while (0);
;
2579 return -1;
2580 }
2581 }
2582
2583 for (i = 0; i < 8; i++) {
2584 /* Use active wwpn, if new one is not provided */
2585 if (wwpn == 0) {
2586 new_wwpn[i] = result.wwpn[i];
2587 }
2588
2589 /* Use active wwnn, if new one is not provided */
2590 if (wwnn == 0) {
2591 new_wwnn[i] = result.wwnn[i];
2592 }
2593 }
2594
2595 /* Modify the nv_wwnn and nv_wwpn, then write it back */
2596 ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn2");
2597
2598 rc = ocs_hw_set_nvparms(&ocs->hw, ocs_mgmt_set_nvparms_cb, new_wwpn,
2599 new_wwnn, result.hard_alpa, result.preferred_d_id,
2600 &result);
2601 if (rc == OCS_HW_RTN_SUCCESS) {
2602 if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER(-1)) != 0) {
2603 /* Undefined failure */
2604 ocs_log_err(ocs, "ocs_sem_p failed\n")do { if (1 <= loglevel) { _ocs_log(ocs, __func__, 2604, "ocs_sem_p failed\n"
); } } while (0);
;
2605 return -ENXIO6;
2606 }
2607 if (result.status != 0) {
2608 ocs_log_test(ocs, "setting wwn status 0x%x\n", result.status)do { if (4 <= loglevel) { _ocs_log(ocs, __func__, 2608, "setting wwn status 0x%x\n"
, result.status); } } while (0);
;
2609 return -1;
2610 }
2611 }
2612
2613 return rc;
2614}
2615
2616static int
2617set_tgt_rscn_delay(ocs_t *ocs, char *name, char *value)
2618{
2619 ocs->tgt_rscn_delay_msec = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) * 1000;
2620 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2620, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2621 return 0;
2622}
2623
2624static int
2625set_tgt_rscn_period(ocs_t *ocs, char *name, char *value)
2626{
2627 ocs->tgt_rscn_period_msec = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) * 1000;
2628 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2628, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2629 return 0;
2630}
2631
2632static int
2633set_inject_drop_cmd(ocs_t *ocs, char *name, char *value)
2634{
2635 ocs->err_injection = (ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) == 0 ? NO_ERR_INJECT : INJECT_DROP_CMD);
2636 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2636, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2637 return 0;
2638}
2639
2640static int
2641set_inject_free_drop_cmd(ocs_t *ocs, char *name, char *value)
2642{
2643 ocs->err_injection = (ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) == 0 ? NO_ERR_INJECT : INJECT_FREE_DROPPED);
2644 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2644, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2645 return 0;
2646}
2647
2648static int
2649set_inject_drop_data(ocs_t *ocs, char *name, char *value)
2650{
2651 ocs->err_injection = (ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) == 0 ? NO_ERR_INJECT : INJECT_DROP_DATA);
2652 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2652, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2653 return 0;
2654}
2655
2656static int
2657set_inject_drop_resp(ocs_t *ocs, char *name, char *value)
2658{
2659 ocs->err_injection = (ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0) == 0 ? NO_ERR_INJECT : INJECT_DROP_RESP);
2660 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2660, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2661 return 0;
2662}
2663
2664static int
2665set_cmd_err_inject(ocs_t *ocs, char *name, char *value)
2666{
2667 ocs->cmd_err_inject = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
2668 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2668, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2669 return 0;
2670}
2671
2672static int
2673set_cmd_delay_value(ocs_t *ocs, char *name, char *value)
2674{
2675 ocs->delay_value_msec = ocs_strtoul(value, NULL, 0)strtoul(value,((void *)0),0);
2676 ocs->err_injection = (ocs->delay_value_msec == 0 ? NO_ERR_INJECT : INJECT_DELAY_CMD);
2677 ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value)do { if (5 <= loglevel) { _ocs_log(ocs, __func__, 2677, "mgmt set: %s %s\n"
, name, value); } } while (0);
;
2678 return 0;
2679}
2680
2681/**
2682 * @brief parse a WWN from a string into a 64-bit value
2683 *
2684 * Given a pointer to a string, parse the string into a 64-bit
2685 * WWN value. The format of the string must be xx:xx:xx:xx:xx:xx:xx:xx
2686 *
2687 * @param wwn_in pointer to the string to be parsed
2688 * @param wwn_out pointer to uint64_t in which to put the parsed result
2689 *
2690 * @return 0 if successful, non-zero if the WWN is malformed and couldn't be parsed
2691 */
2692int
2693parse_wwn(char *wwn_in, uint64_t *wwn_out)
2694{
2695 uint8_t byte0;
2696 uint8_t byte1;
2697 uint8_t byte2;
2698 uint8_t byte3;
2699 uint8_t byte4;
2700 uint8_t byte5;
2701 uint8_t byte6;
2702 uint8_t byte7;
2703 int rc;
2704
2705 rc = ocs_sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", &
byte0, &byte1, &byte2, &byte3, &byte4, &byte5
, &byte6, &byte7)
2706 &byte0, &byte1, &byte2, &byte3,sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", &
byte0, &byte1, &byte2, &byte3, &byte4, &byte5
, &byte6, &byte7)
2707 &byte4, &byte5, &byte6, &byte7)sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", &
byte0, &byte1, &byte2, &byte3, &byte4, &byte5
, &byte6, &byte7)
;
2708
2709 if (rc == 8) {
2710 *wwn_out = ((uint64_t)byte0 << 56) |
2711 ((uint64_t)byte1 << 48) |
2712 ((uint64_t)byte2 << 40) |
2713 ((uint64_t)byte3 << 32) |
2714 ((uint64_t)byte4 << 24) |
2715 ((uint64_t)byte5 << 16) |
2716 ((uint64_t)byte6 << 8) |
2717 ((uint64_t)byte7);
2718 return 0;
2719
2720 } else {
2721 return 1;
2722 }
2723}
2724
2725
2726
2727static char *mode_string(int mode);
2728
2729
2730/**
2731 * @ingroup mgmt
2732 * @brief Generate the beginning of a numbered section in a management XML document.
2733 *
2734 * @par Description
2735 * This function begins a section. The XML information is appended to
2736 * the textbuf. This form of the function is used for sections that might have
2737 * multiple instances, such as a node or a SLI Port (sport). The index number
2738 * is appended to the name.
2739 *
2740 * @param textbuf Pointer to the driver dump text buffer.
2741 * @param name Name of the section.
2742 * @param index Index number of this instance of the section.
2743 *
2744 * @return None.
2745 */
2746
2747extern void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index)
2748{
2749 ocs_textbuf_printf(textbuf, "<%s instance=\"%d\">\n", name, index);
2750}
2751
2752/**
2753 * @ingroup mgmt
2754 * @brief Generate the beginning of an unnumbered section in a management XML document.
2755 *
2756 * @par Description
2757 * This function begins a section. The XML information is appended to
2758 * the textbuf. This form of the function is used for sections that have
2759 * a single instance only. Therefore, no index number is needed.
2760 *
2761 * @param textbuf Pointer to the driver dump text buffer.
2762 * @param name Name of the section.
2763 *
2764 * @return None.
2765 */
2766
2767extern void ocs_mgmt_start_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
2768{
2769 ocs_textbuf_printf(textbuf, "<%s>\n", name);
2770}
2771
2772/**
2773 * @ingroup mgmt
2774 * @brief Generate the end of a section in a management XML document.
2775 *
2776 * @par Description
2777 * This function ends a section. The XML information is appended to
2778 * the textbuf.
2779 *
2780 * @param textbuf Pointer to the driver dump text buffer.
2781 * @param name Name of the section.
2782 *
2783 * @return None.
2784 */
2785
2786void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
2787{
2788 ocs_textbuf_printf(textbuf, "</%s>\n", name);
2789}
2790
2791/**
2792 * @ingroup mgmt
2793 * @brief Generate the indexed end of a section in a management XML document.
2794 *
2795 * @par Description
2796 * This function ends a section. The XML information is appended to
2797 * the textbuf.
2798 *
2799 * @param textbuf Pointer to the driver dump text buffer.
2800 * @param name Name of the section.
2801 * @param index Index number of this instance of the section.
2802 *
2803 * @return None.
2804 */
2805
2806void ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index)
2807{
2808
2809 ocs_textbuf_printf(textbuf, "</%s>\n", name);
2810
2811}
2812
2813/**
2814 * @ingroup mgmt
2815 * @brief Generate a property, with no value, in a management XML document.
2816 *
2817 * @par Description
2818 * This function generates a property name. The XML information is appended to
2819 * the textbuf. This form of the function is used by the list functions
2820 * when the property name only (and not the current value) is given.
2821 *
2822 * @param textbuf Pointer to the driver dump text buffer.
2823 * @param mode Defines whether the property is read(r)/write(w)/executable(x).
2824 * @param name Name of the property.
2825 *
2826 * @return None.
2827 */
2828
2829void ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int mode, const char *name)
2830{
2831 ocs_textbuf_printf(textbuf, "<%s mode=\"%s\"/>\n", name, mode_string(mode));
2832}
2833
2834/**
2835 * @ingroup mgmt
2836 * @brief Generate a property with a string value in a management XML document.
2837 *
2838 * @par Description
2839 * This function generates a property name and a string value.
2840 * The XML information is appended to the textbuf.
2841 *
2842 * @param textbuf Pointer to the driver dump text buffer.
2843 * @param mode Defines whether the property is read(r)/write(w)/executable(x).
2844 * @param name Name of the property.
2845 * @param value Value of the property.
2846 *
2847 * @return None.
2848 */
2849
2850void ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int mode, const char *name, const char *value)
2851{
2852 ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), value, name);
2853}
2854
2855/**
2856 * @ingroup mgmt
2857 * @brief Generate a property with an integer value in a management XML document.
2858 *
2859 * @par Description
2860 * This function generates a property name and an integer value.
2861 * The XML information is appended to the textbuf.
2862 *
2863 * @param textbuf Pointer to driver dump text buffer.
2864 * @param mode Defines whether the property is read(r)/write(w)/executable(x).
2865 * @param name Name of the property.
2866 * @param fmt A printf format for formatting the integer value.
2867 *
2868 * @return none
2869 */
2870
2871void ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt, ...)
2872{
2873 va_list ap;
2874 char valuebuf[64];
2875
2876 va_start(ap, fmt)__builtin_va_start((ap), (fmt));
2877 ocs_vsnprintf(valuebuf, sizeof(valuebuf), fmt, ap)vsnprintf((char*)valuebuf, sizeof(valuebuf), fmt, ap);
2878 va_end(ap)__builtin_va_end(ap);
2879
2880 ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name);
2881}
2882
2883/**
2884 * @ingroup mgmt
2885 * @brief Generate a property with a boolean value in a management XML document.
2886 *
2887 * @par Description
2888 * This function generates a property name and a boolean value.
2889 * The XML information is appended to the textbuf.
2890 *
2891 * @param textbuf Pointer to the driver dump text buffer.
2892 * @param mode Defines whether the property is read(r)/write(w)/executable(x).
2893 * @param name Name of the property.
2894 * @param value Boolean value to be added to the textbuf.
2895 *
2896 * @return None.
2897 */
2898
2899void ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int mode, const char *name, int value)
2900{
2901 char *valuebuf = value ? "true" : "false";
2902
2903 ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name);
2904}
2905
2906static char *mode_string(int mode)
2907{
2908 static char mode_str[4];
2909
2910 mode_str[0] = '\0';
2911 if (mode & MGMT_MODE_RD4) {
2912 strcat(mode_str, "r");
2913 }
2914 if (mode & MGMT_MODE_WR2) {
2915 strcat(mode_str, "w");
2916 }
2917 if (mode & MGMT_MODE_EX1) {
2918 strcat(mode_str, "x");
2919 }
2920
2921 return mode_str;
2922
2923}