1*ef270ab1SKenneth D. Merry /*-
2*ef270ab1SKenneth D. Merry * Copyright (c) 2017 Broadcom. All rights reserved.
3*ef270ab1SKenneth D. Merry * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4*ef270ab1SKenneth D. Merry *
5*ef270ab1SKenneth D. Merry * Redistribution and use in source and binary forms, with or without
6*ef270ab1SKenneth D. Merry * modification, are permitted provided that the following conditions are met:
7*ef270ab1SKenneth D. Merry *
8*ef270ab1SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright notice,
9*ef270ab1SKenneth D. Merry * this list of conditions and the following disclaimer.
10*ef270ab1SKenneth D. Merry *
11*ef270ab1SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright notice,
12*ef270ab1SKenneth D. Merry * this list of conditions and the following disclaimer in the documentation
13*ef270ab1SKenneth D. Merry * and/or other materials provided with the distribution.
14*ef270ab1SKenneth D. Merry *
15*ef270ab1SKenneth D. Merry * 3. Neither the name of the copyright holder nor the names of its contributors
16*ef270ab1SKenneth D. Merry * may be used to endorse or promote products derived from this software
17*ef270ab1SKenneth D. Merry * without specific prior written permission.
18*ef270ab1SKenneth D. Merry *
19*ef270ab1SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*ef270ab1SKenneth D. Merry * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*ef270ab1SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*ef270ab1SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23*ef270ab1SKenneth D. Merry * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*ef270ab1SKenneth D. Merry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*ef270ab1SKenneth D. Merry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*ef270ab1SKenneth D. Merry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*ef270ab1SKenneth D. Merry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*ef270ab1SKenneth D. Merry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*ef270ab1SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGE.
30*ef270ab1SKenneth D. Merry */
31*ef270ab1SKenneth D. Merry
32*ef270ab1SKenneth D. Merry /**
33*ef270ab1SKenneth D. Merry * @file
34*ef270ab1SKenneth D. Merry *
35*ef270ab1SKenneth D. Merry */
36*ef270ab1SKenneth D. Merry
37*ef270ab1SKenneth D. Merry #include "ocs.h"
38*ef270ab1SKenneth D. Merry #include "ocs_os.h"
39*ef270ab1SKenneth D. Merry
40*ef270ab1SKenneth D. Merry #define DEFAULT_SLAB_LEN (64*1024)
41*ef270ab1SKenneth D. Merry
42*ef270ab1SKenneth D. Merry struct ocs_array_s {
43*ef270ab1SKenneth D. Merry ocs_os_handle_t os;
44*ef270ab1SKenneth D. Merry
45*ef270ab1SKenneth D. Merry uint32_t size;
46*ef270ab1SKenneth D. Merry uint32_t count;
47*ef270ab1SKenneth D. Merry
48*ef270ab1SKenneth D. Merry uint32_t n_rows;
49*ef270ab1SKenneth D. Merry uint32_t elems_per_row;
50*ef270ab1SKenneth D. Merry uint32_t bytes_per_row;
51*ef270ab1SKenneth D. Merry
52*ef270ab1SKenneth D. Merry void **array_rows;
53*ef270ab1SKenneth D. Merry uint32_t array_rows_len;
54*ef270ab1SKenneth D. Merry };
55*ef270ab1SKenneth D. Merry
56*ef270ab1SKenneth D. Merry static uint32_t slab_len = DEFAULT_SLAB_LEN;
57*ef270ab1SKenneth D. Merry
58*ef270ab1SKenneth D. Merry /**
59*ef270ab1SKenneth D. Merry * @brief Set array slab allocation length
60*ef270ab1SKenneth D. Merry *
61*ef270ab1SKenneth D. Merry * The slab length is the maximum allocation length that the array uses.
62*ef270ab1SKenneth D. Merry * The default 64k slab length may be overridden using this function.
63*ef270ab1SKenneth D. Merry *
64*ef270ab1SKenneth D. Merry * @param len new slab length.
65*ef270ab1SKenneth D. Merry *
66*ef270ab1SKenneth D. Merry * @return none
67*ef270ab1SKenneth D. Merry */
68*ef270ab1SKenneth D. Merry void
ocs_array_set_slablen(uint32_t len)69*ef270ab1SKenneth D. Merry ocs_array_set_slablen(uint32_t len)
70*ef270ab1SKenneth D. Merry {
71*ef270ab1SKenneth D. Merry slab_len = len;
72*ef270ab1SKenneth D. Merry }
73*ef270ab1SKenneth D. Merry
74*ef270ab1SKenneth D. Merry /**
75*ef270ab1SKenneth D. Merry * @brief Allocate an array object
76*ef270ab1SKenneth D. Merry *
77*ef270ab1SKenneth D. Merry * An array object of size and number of elements is allocated
78*ef270ab1SKenneth D. Merry *
79*ef270ab1SKenneth D. Merry * @param os OS handle
80*ef270ab1SKenneth D. Merry * @param size size of array elements in bytes
81*ef270ab1SKenneth D. Merry * @param count number of elements in array
82*ef270ab1SKenneth D. Merry *
83*ef270ab1SKenneth D. Merry * @return pointer to array object or NULL
84*ef270ab1SKenneth D. Merry */
85*ef270ab1SKenneth D. Merry ocs_array_t *
ocs_array_alloc(ocs_os_handle_t os,uint32_t size,uint32_t count)86*ef270ab1SKenneth D. Merry ocs_array_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count)
87*ef270ab1SKenneth D. Merry {
88*ef270ab1SKenneth D. Merry ocs_array_t *array = NULL;
89*ef270ab1SKenneth D. Merry uint32_t i;
90*ef270ab1SKenneth D. Merry
91*ef270ab1SKenneth D. Merry /* Fail if the item size exceeds slab_len - caller should increase slab_size,
92*ef270ab1SKenneth D. Merry * or not use this API.
93*ef270ab1SKenneth D. Merry */
94*ef270ab1SKenneth D. Merry if (size > slab_len) {
95*ef270ab1SKenneth D. Merry ocs_log_err(NULL, "Error: size exceeds slab length\n");
96*ef270ab1SKenneth D. Merry return NULL;
97*ef270ab1SKenneth D. Merry }
98*ef270ab1SKenneth D. Merry
99*ef270ab1SKenneth D. Merry array = ocs_malloc(os, sizeof(*array), OCS_M_ZERO | OCS_M_NOWAIT);
100*ef270ab1SKenneth D. Merry if (array == NULL) {
101*ef270ab1SKenneth D. Merry return NULL;
102*ef270ab1SKenneth D. Merry }
103*ef270ab1SKenneth D. Merry
104*ef270ab1SKenneth D. Merry array->os = os;
105*ef270ab1SKenneth D. Merry array->size = size;
106*ef270ab1SKenneth D. Merry array->count = count;
107*ef270ab1SKenneth D. Merry array->elems_per_row = slab_len / size;
108*ef270ab1SKenneth D. Merry array->n_rows = (count + array->elems_per_row - 1) / array->elems_per_row;
109*ef270ab1SKenneth D. Merry array->bytes_per_row = array->elems_per_row * array->size;
110*ef270ab1SKenneth D. Merry
111*ef270ab1SKenneth D. Merry array->array_rows_len = array->n_rows * sizeof(*array->array_rows);
112*ef270ab1SKenneth D. Merry array->array_rows = ocs_malloc(os, array->array_rows_len, OCS_M_ZERO | OCS_M_NOWAIT);
113*ef270ab1SKenneth D. Merry if (array->array_rows == NULL) {
114*ef270ab1SKenneth D. Merry ocs_array_free(array);
115*ef270ab1SKenneth D. Merry return NULL;
116*ef270ab1SKenneth D. Merry }
117*ef270ab1SKenneth D. Merry for (i = 0; i < array->n_rows; i++) {
118*ef270ab1SKenneth D. Merry array->array_rows[i] = ocs_malloc(os, array->bytes_per_row, OCS_M_ZERO | OCS_M_NOWAIT);
119*ef270ab1SKenneth D. Merry if (array->array_rows[i] == NULL) {
120*ef270ab1SKenneth D. Merry ocs_array_free(array);
121*ef270ab1SKenneth D. Merry return NULL;
122*ef270ab1SKenneth D. Merry }
123*ef270ab1SKenneth D. Merry }
124*ef270ab1SKenneth D. Merry
125*ef270ab1SKenneth D. Merry return array;
126*ef270ab1SKenneth D. Merry }
127*ef270ab1SKenneth D. Merry
128*ef270ab1SKenneth D. Merry /**
129*ef270ab1SKenneth D. Merry * @brief Free an array object
130*ef270ab1SKenneth D. Merry *
131*ef270ab1SKenneth D. Merry * Frees a prevously allocated array object
132*ef270ab1SKenneth D. Merry *
133*ef270ab1SKenneth D. Merry * @param array pointer to array object
134*ef270ab1SKenneth D. Merry *
135*ef270ab1SKenneth D. Merry * @return none
136*ef270ab1SKenneth D. Merry */
137*ef270ab1SKenneth D. Merry void
ocs_array_free(ocs_array_t * array)138*ef270ab1SKenneth D. Merry ocs_array_free(ocs_array_t *array)
139*ef270ab1SKenneth D. Merry {
140*ef270ab1SKenneth D. Merry uint32_t i;
141*ef270ab1SKenneth D. Merry
142*ef270ab1SKenneth D. Merry if (array != NULL) {
143*ef270ab1SKenneth D. Merry if (array->array_rows != NULL) {
144*ef270ab1SKenneth D. Merry for (i = 0; i < array->n_rows; i++) {
145*ef270ab1SKenneth D. Merry if (array->array_rows[i] != NULL) {
146*ef270ab1SKenneth D. Merry ocs_free(array->os, array->array_rows[i], array->bytes_per_row);
147*ef270ab1SKenneth D. Merry }
148*ef270ab1SKenneth D. Merry }
149*ef270ab1SKenneth D. Merry ocs_free(array->os, array->array_rows, array->array_rows_len);
150*ef270ab1SKenneth D. Merry }
151*ef270ab1SKenneth D. Merry ocs_free(array->os, array, sizeof(*array));
152*ef270ab1SKenneth D. Merry }
153*ef270ab1SKenneth D. Merry }
154*ef270ab1SKenneth D. Merry
155*ef270ab1SKenneth D. Merry /**
156*ef270ab1SKenneth D. Merry * @brief Return reference to an element of an array object
157*ef270ab1SKenneth D. Merry *
158*ef270ab1SKenneth D. Merry * Return the address of an array element given an index
159*ef270ab1SKenneth D. Merry *
160*ef270ab1SKenneth D. Merry * @param array pointer to array object
161*ef270ab1SKenneth D. Merry * @param idx array element index
162*ef270ab1SKenneth D. Merry *
163*ef270ab1SKenneth D. Merry * @return rointer to array element, or NULL if index out of range
164*ef270ab1SKenneth D. Merry */
ocs_array_get(ocs_array_t * array,uint32_t idx)165*ef270ab1SKenneth D. Merry void *ocs_array_get(ocs_array_t *array, uint32_t idx)
166*ef270ab1SKenneth D. Merry {
167*ef270ab1SKenneth D. Merry void *entry = NULL;
168*ef270ab1SKenneth D. Merry
169*ef270ab1SKenneth D. Merry if (idx < array->count) {
170*ef270ab1SKenneth D. Merry uint32_t row = idx / array->elems_per_row;
171*ef270ab1SKenneth D. Merry uint32_t offset = idx % array->elems_per_row;
172*ef270ab1SKenneth D. Merry entry = ((uint8_t*)array->array_rows[row]) + (offset * array->size);
173*ef270ab1SKenneth D. Merry }
174*ef270ab1SKenneth D. Merry return entry;
175*ef270ab1SKenneth D. Merry }
176*ef270ab1SKenneth D. Merry
177*ef270ab1SKenneth D. Merry /**
178*ef270ab1SKenneth D. Merry * @brief Return number of elements in an array
179*ef270ab1SKenneth D. Merry *
180*ef270ab1SKenneth D. Merry * Return the number of elements in an array
181*ef270ab1SKenneth D. Merry *
182*ef270ab1SKenneth D. Merry * @param array pointer to array object
183*ef270ab1SKenneth D. Merry *
184*ef270ab1SKenneth D. Merry * @return returns count of elements in an array
185*ef270ab1SKenneth D. Merry */
186*ef270ab1SKenneth D. Merry uint32_t
ocs_array_get_count(ocs_array_t * array)187*ef270ab1SKenneth D. Merry ocs_array_get_count(ocs_array_t *array)
188*ef270ab1SKenneth D. Merry {
189*ef270ab1SKenneth D. Merry return array->count;
190*ef270ab1SKenneth D. Merry }
191*ef270ab1SKenneth D. Merry
192*ef270ab1SKenneth D. Merry /**
193*ef270ab1SKenneth D. Merry * @brief Return size of array elements in bytes
194*ef270ab1SKenneth D. Merry *
195*ef270ab1SKenneth D. Merry * Returns the size in bytes of each array element
196*ef270ab1SKenneth D. Merry *
197*ef270ab1SKenneth D. Merry * @param array pointer to array object
198*ef270ab1SKenneth D. Merry *
199*ef270ab1SKenneth D. Merry * @return size of array element
200*ef270ab1SKenneth D. Merry */
201*ef270ab1SKenneth D. Merry uint32_t
ocs_array_get_size(ocs_array_t * array)202*ef270ab1SKenneth D. Merry ocs_array_get_size(ocs_array_t *array)
203*ef270ab1SKenneth D. Merry {
204*ef270ab1SKenneth D. Merry return array->size;
205*ef270ab1SKenneth D. Merry }
206*ef270ab1SKenneth D. Merry
207*ef270ab1SKenneth D. Merry /**
208*ef270ab1SKenneth D. Merry * @brief Void pointer array structure
209*ef270ab1SKenneth D. Merry *
210*ef270ab1SKenneth D. Merry * This structure describes an object consisting of an array of void
211*ef270ab1SKenneth D. Merry * pointers. The object is allocated with a maximum array size, entries
212*ef270ab1SKenneth D. Merry * are then added to the array with while maintaining an entry count. A set of
213*ef270ab1SKenneth D. Merry * iterator APIs are included to allow facilitate cycling through the array
214*ef270ab1SKenneth D. Merry * entries in a circular fashion.
215*ef270ab1SKenneth D. Merry *
216*ef270ab1SKenneth D. Merry */
217*ef270ab1SKenneth D. Merry struct ocs_varray_s {
218*ef270ab1SKenneth D. Merry ocs_os_handle_t os;
219*ef270ab1SKenneth D. Merry uint32_t array_count; /*>> maximum entry count in array */
220*ef270ab1SKenneth D. Merry void **array; /*>> pointer to allocated array memory */
221*ef270ab1SKenneth D. Merry uint32_t entry_count; /*>> number of entries added to the array */
222*ef270ab1SKenneth D. Merry uint32_t next_index; /*>> iterator next index */
223*ef270ab1SKenneth D. Merry ocs_lock_t lock; /*>> iterator lock */
224*ef270ab1SKenneth D. Merry };
225*ef270ab1SKenneth D. Merry
226*ef270ab1SKenneth D. Merry /**
227*ef270ab1SKenneth D. Merry * @brief Allocate a void pointer array
228*ef270ab1SKenneth D. Merry *
229*ef270ab1SKenneth D. Merry * A void pointer array of given length is allocated.
230*ef270ab1SKenneth D. Merry *
231*ef270ab1SKenneth D. Merry * @param os OS handle
232*ef270ab1SKenneth D. Merry * @param array_count Array size
233*ef270ab1SKenneth D. Merry *
234*ef270ab1SKenneth D. Merry * @return returns a pointer to the ocs_varray_t object, other NULL on error
235*ef270ab1SKenneth D. Merry */
236*ef270ab1SKenneth D. Merry ocs_varray_t *
ocs_varray_alloc(ocs_os_handle_t os,uint32_t array_count)237*ef270ab1SKenneth D. Merry ocs_varray_alloc(ocs_os_handle_t os, uint32_t array_count)
238*ef270ab1SKenneth D. Merry {
239*ef270ab1SKenneth D. Merry ocs_varray_t *va;
240*ef270ab1SKenneth D. Merry
241*ef270ab1SKenneth D. Merry va = ocs_malloc(os, sizeof(*va), OCS_M_ZERO | OCS_M_NOWAIT);
242*ef270ab1SKenneth D. Merry if (va != NULL) {
243*ef270ab1SKenneth D. Merry va->os = os;
244*ef270ab1SKenneth D. Merry va->array_count = array_count;
245*ef270ab1SKenneth D. Merry va->array = ocs_malloc(os, sizeof(*va->array) * va->array_count, OCS_M_ZERO | OCS_M_NOWAIT);
246*ef270ab1SKenneth D. Merry if (va->array != NULL) {
247*ef270ab1SKenneth D. Merry va->next_index = 0;
248*ef270ab1SKenneth D. Merry ocs_lock_init(os, &va->lock, "varray:%p", va);
249*ef270ab1SKenneth D. Merry } else {
250*ef270ab1SKenneth D. Merry ocs_free(os, va, sizeof(*va));
251*ef270ab1SKenneth D. Merry va = NULL;
252*ef270ab1SKenneth D. Merry }
253*ef270ab1SKenneth D. Merry }
254*ef270ab1SKenneth D. Merry return va;
255*ef270ab1SKenneth D. Merry }
256*ef270ab1SKenneth D. Merry
257*ef270ab1SKenneth D. Merry /**
258*ef270ab1SKenneth D. Merry * @brief Free a void pointer array
259*ef270ab1SKenneth D. Merry *
260*ef270ab1SKenneth D. Merry * The void pointer array object is free'd
261*ef270ab1SKenneth D. Merry *
262*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
263*ef270ab1SKenneth D. Merry *
264*ef270ab1SKenneth D. Merry * @return none
265*ef270ab1SKenneth D. Merry */
266*ef270ab1SKenneth D. Merry void
ocs_varray_free(ocs_varray_t * va)267*ef270ab1SKenneth D. Merry ocs_varray_free(ocs_varray_t *va)
268*ef270ab1SKenneth D. Merry {
269*ef270ab1SKenneth D. Merry if (va != NULL) {
270*ef270ab1SKenneth D. Merry ocs_lock_free(&va->lock);
271*ef270ab1SKenneth D. Merry if (va->array != NULL) {
272*ef270ab1SKenneth D. Merry ocs_free(va->os, va->array, sizeof(*va->array) * va->array_count);
273*ef270ab1SKenneth D. Merry }
274*ef270ab1SKenneth D. Merry ocs_free(va->os, va, sizeof(*va));
275*ef270ab1SKenneth D. Merry }
276*ef270ab1SKenneth D. Merry }
277*ef270ab1SKenneth D. Merry
278*ef270ab1SKenneth D. Merry /**
279*ef270ab1SKenneth D. Merry * @brief Add an entry to a void pointer array
280*ef270ab1SKenneth D. Merry *
281*ef270ab1SKenneth D. Merry * An entry is added to the void pointer array
282*ef270ab1SKenneth D. Merry *
283*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
284*ef270ab1SKenneth D. Merry * @param entry Pointer to entry to add
285*ef270ab1SKenneth D. Merry *
286*ef270ab1SKenneth D. Merry * @return returns 0 if entry was added, -1 if there is no more space in the array
287*ef270ab1SKenneth D. Merry */
288*ef270ab1SKenneth D. Merry int32_t
ocs_varray_add(ocs_varray_t * va,void * entry)289*ef270ab1SKenneth D. Merry ocs_varray_add(ocs_varray_t *va, void *entry)
290*ef270ab1SKenneth D. Merry {
291*ef270ab1SKenneth D. Merry uint32_t rc = -1;
292*ef270ab1SKenneth D. Merry
293*ef270ab1SKenneth D. Merry ocs_lock(&va->lock);
294*ef270ab1SKenneth D. Merry if (va->entry_count < va->array_count) {
295*ef270ab1SKenneth D. Merry va->array[va->entry_count++] = entry;
296*ef270ab1SKenneth D. Merry rc = 0;
297*ef270ab1SKenneth D. Merry }
298*ef270ab1SKenneth D. Merry ocs_unlock(&va->lock);
299*ef270ab1SKenneth D. Merry
300*ef270ab1SKenneth D. Merry return rc;
301*ef270ab1SKenneth D. Merry }
302*ef270ab1SKenneth D. Merry
303*ef270ab1SKenneth D. Merry /**
304*ef270ab1SKenneth D. Merry * @brief Reset the void pointer array iterator
305*ef270ab1SKenneth D. Merry *
306*ef270ab1SKenneth D. Merry * The next index value of the void pointer array iterator is cleared.
307*ef270ab1SKenneth D. Merry *
308*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
309*ef270ab1SKenneth D. Merry *
310*ef270ab1SKenneth D. Merry * @return none
311*ef270ab1SKenneth D. Merry */
312*ef270ab1SKenneth D. Merry void
ocs_varray_iter_reset(ocs_varray_t * va)313*ef270ab1SKenneth D. Merry ocs_varray_iter_reset(ocs_varray_t *va)
314*ef270ab1SKenneth D. Merry {
315*ef270ab1SKenneth D. Merry ocs_lock(&va->lock);
316*ef270ab1SKenneth D. Merry va->next_index = 0;
317*ef270ab1SKenneth D. Merry ocs_unlock(&va->lock);
318*ef270ab1SKenneth D. Merry }
319*ef270ab1SKenneth D. Merry
320*ef270ab1SKenneth D. Merry /**
321*ef270ab1SKenneth D. Merry * @brief Return next entry from a void pointer array
322*ef270ab1SKenneth D. Merry *
323*ef270ab1SKenneth D. Merry * The next entry in the void pointer array is returned.
324*ef270ab1SKenneth D. Merry *
325*ef270ab1SKenneth D. Merry * @param va Pointer to void point array
326*ef270ab1SKenneth D. Merry *
327*ef270ab1SKenneth D. Merry * Note: takes the void pointer array lock
328*ef270ab1SKenneth D. Merry *
329*ef270ab1SKenneth D. Merry * @return returns next void pointer entry
330*ef270ab1SKenneth D. Merry */
331*ef270ab1SKenneth D. Merry void *
ocs_varray_iter_next(ocs_varray_t * va)332*ef270ab1SKenneth D. Merry ocs_varray_iter_next(ocs_varray_t *va)
333*ef270ab1SKenneth D. Merry {
334*ef270ab1SKenneth D. Merry void *rval = NULL;
335*ef270ab1SKenneth D. Merry
336*ef270ab1SKenneth D. Merry if (va != NULL) {
337*ef270ab1SKenneth D. Merry ocs_lock(&va->lock);
338*ef270ab1SKenneth D. Merry rval = _ocs_varray_iter_next(va);
339*ef270ab1SKenneth D. Merry ocs_unlock(&va->lock);
340*ef270ab1SKenneth D. Merry }
341*ef270ab1SKenneth D. Merry return rval;
342*ef270ab1SKenneth D. Merry }
343*ef270ab1SKenneth D. Merry
344*ef270ab1SKenneth D. Merry /**
345*ef270ab1SKenneth D. Merry * @brief Return next entry from a void pointer array
346*ef270ab1SKenneth D. Merry *
347*ef270ab1SKenneth D. Merry * The next entry in the void pointer array is returned.
348*ef270ab1SKenneth D. Merry *
349*ef270ab1SKenneth D. Merry * @param va Pointer to void point array
350*ef270ab1SKenneth D. Merry *
351*ef270ab1SKenneth D. Merry * Note: doesn't take the void pointer array lock
352*ef270ab1SKenneth D. Merry *
353*ef270ab1SKenneth D. Merry * @return returns next void pointer entry
354*ef270ab1SKenneth D. Merry */
355*ef270ab1SKenneth D. Merry void *
_ocs_varray_iter_next(ocs_varray_t * va)356*ef270ab1SKenneth D. Merry _ocs_varray_iter_next(ocs_varray_t *va)
357*ef270ab1SKenneth D. Merry {
358*ef270ab1SKenneth D. Merry void *rval;
359*ef270ab1SKenneth D. Merry
360*ef270ab1SKenneth D. Merry rval = va->array[va->next_index];
361*ef270ab1SKenneth D. Merry if (++va->next_index >= va->entry_count) {
362*ef270ab1SKenneth D. Merry va->next_index = 0;
363*ef270ab1SKenneth D. Merry }
364*ef270ab1SKenneth D. Merry return rval;
365*ef270ab1SKenneth D. Merry }
366*ef270ab1SKenneth D. Merry
367*ef270ab1SKenneth D. Merry /**
368*ef270ab1SKenneth D. Merry * @brief Take void pointer array lock
369*ef270ab1SKenneth D. Merry *
370*ef270ab1SKenneth D. Merry * Takes the lock for the given void pointer array
371*ef270ab1SKenneth D. Merry *
372*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
373*ef270ab1SKenneth D. Merry *
374*ef270ab1SKenneth D. Merry * @return none
375*ef270ab1SKenneth D. Merry */
376*ef270ab1SKenneth D. Merry void
ocs_varray_lock(ocs_varray_t * va)377*ef270ab1SKenneth D. Merry ocs_varray_lock(ocs_varray_t *va)
378*ef270ab1SKenneth D. Merry {
379*ef270ab1SKenneth D. Merry ocs_lock(&va->lock);
380*ef270ab1SKenneth D. Merry }
381*ef270ab1SKenneth D. Merry
382*ef270ab1SKenneth D. Merry /**
383*ef270ab1SKenneth D. Merry * @brief Release void pointer array lock
384*ef270ab1SKenneth D. Merry *
385*ef270ab1SKenneth D. Merry * Releases the lock for the given void pointer array
386*ef270ab1SKenneth D. Merry *
387*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
388*ef270ab1SKenneth D. Merry *
389*ef270ab1SKenneth D. Merry * @return none
390*ef270ab1SKenneth D. Merry */
391*ef270ab1SKenneth D. Merry void
ocs_varray_unlock(ocs_varray_t * va)392*ef270ab1SKenneth D. Merry ocs_varray_unlock(ocs_varray_t *va)
393*ef270ab1SKenneth D. Merry {
394*ef270ab1SKenneth D. Merry ocs_unlock(&va->lock);
395*ef270ab1SKenneth D. Merry }
396*ef270ab1SKenneth D. Merry
397*ef270ab1SKenneth D. Merry /**
398*ef270ab1SKenneth D. Merry * @brief Return entry count for a void pointer array
399*ef270ab1SKenneth D. Merry *
400*ef270ab1SKenneth D. Merry * The entry count for a void pointer array is returned
401*ef270ab1SKenneth D. Merry *
402*ef270ab1SKenneth D. Merry * @param va Pointer to void pointer array
403*ef270ab1SKenneth D. Merry *
404*ef270ab1SKenneth D. Merry * @return returns entry count
405*ef270ab1SKenneth D. Merry */
406*ef270ab1SKenneth D. Merry uint32_t
ocs_varray_get_count(ocs_varray_t * va)407*ef270ab1SKenneth D. Merry ocs_varray_get_count(ocs_varray_t *va)
408*ef270ab1SKenneth D. Merry {
409*ef270ab1SKenneth D. Merry uint32_t rc;
410*ef270ab1SKenneth D. Merry
411*ef270ab1SKenneth D. Merry ocs_lock(&va->lock);
412*ef270ab1SKenneth D. Merry rc = va->entry_count;
413*ef270ab1SKenneth D. Merry ocs_unlock(&va->lock);
414*ef270ab1SKenneth D. Merry return rc;
415*ef270ab1SKenneth D. Merry }
416*ef270ab1SKenneth D. Merry
417*ef270ab1SKenneth D. Merry struct ocs_cbuf_s {
418*ef270ab1SKenneth D. Merry ocs_os_handle_t os; /*<< OS handle */
419*ef270ab1SKenneth D. Merry uint32_t entry_count; /*<< entry count */
420*ef270ab1SKenneth D. Merry void **array; /*<< pointer to array of cbuf pointers */
421*ef270ab1SKenneth D. Merry uint32_t pidx; /*<< producer index */
422*ef270ab1SKenneth D. Merry uint32_t cidx; /*<< consumer index */
423*ef270ab1SKenneth D. Merry ocs_lock_t cbuf_plock; /*<< idx lock */
424*ef270ab1SKenneth D. Merry ocs_lock_t cbuf_clock; /*<< idx lock */
425*ef270ab1SKenneth D. Merry ocs_sem_t cbuf_psem; /*<< cbuf producer counting semaphore */
426*ef270ab1SKenneth D. Merry ocs_sem_t cbuf_csem; /*<< cbuf consumer counting semaphore */
427*ef270ab1SKenneth D. Merry };
428*ef270ab1SKenneth D. Merry
429*ef270ab1SKenneth D. Merry /**
430*ef270ab1SKenneth D. Merry * @brief Initialize a circular buffer queue
431*ef270ab1SKenneth D. Merry *
432*ef270ab1SKenneth D. Merry * A circular buffer with producer/consumer API is allocated
433*ef270ab1SKenneth D. Merry *
434*ef270ab1SKenneth D. Merry * @param os OS handle
435*ef270ab1SKenneth D. Merry * @param entry_count count of entries
436*ef270ab1SKenneth D. Merry *
437*ef270ab1SKenneth D. Merry * @return returns pointer to circular buffer, or NULL
438*ef270ab1SKenneth D. Merry */
439*ef270ab1SKenneth D. Merry ocs_cbuf_t*
ocs_cbuf_alloc(ocs_os_handle_t os,uint32_t entry_count)440*ef270ab1SKenneth D. Merry ocs_cbuf_alloc(ocs_os_handle_t os, uint32_t entry_count)
441*ef270ab1SKenneth D. Merry {
442*ef270ab1SKenneth D. Merry ocs_cbuf_t *cbuf;
443*ef270ab1SKenneth D. Merry
444*ef270ab1SKenneth D. Merry cbuf = ocs_malloc(os, sizeof(*cbuf), OCS_M_NOWAIT | OCS_M_ZERO);
445*ef270ab1SKenneth D. Merry if (cbuf == NULL) {
446*ef270ab1SKenneth D. Merry return NULL;
447*ef270ab1SKenneth D. Merry }
448*ef270ab1SKenneth D. Merry
449*ef270ab1SKenneth D. Merry cbuf->os = os;
450*ef270ab1SKenneth D. Merry cbuf->entry_count = entry_count;
451*ef270ab1SKenneth D. Merry cbuf->pidx = 0;
452*ef270ab1SKenneth D. Merry cbuf->cidx = 0;
453*ef270ab1SKenneth D. Merry
454*ef270ab1SKenneth D. Merry ocs_lock_init(NULL, &cbuf->cbuf_clock, "cbuf_c:%p", cbuf);
455*ef270ab1SKenneth D. Merry ocs_lock_init(NULL, &cbuf->cbuf_plock, "cbuf_p:%p", cbuf);
456*ef270ab1SKenneth D. Merry ocs_sem_init(&cbuf->cbuf_csem, 0, "cbuf:%p", cbuf);
457*ef270ab1SKenneth D. Merry ocs_sem_init(&cbuf->cbuf_psem, cbuf->entry_count, "cbuf:%p", cbuf);
458*ef270ab1SKenneth D. Merry
459*ef270ab1SKenneth D. Merry cbuf->array = ocs_malloc(os, entry_count * sizeof(*cbuf->array), OCS_M_NOWAIT | OCS_M_ZERO);
460*ef270ab1SKenneth D. Merry if (cbuf->array == NULL) {
461*ef270ab1SKenneth D. Merry ocs_cbuf_free(cbuf);
462*ef270ab1SKenneth D. Merry return NULL;
463*ef270ab1SKenneth D. Merry }
464*ef270ab1SKenneth D. Merry
465*ef270ab1SKenneth D. Merry return cbuf;
466*ef270ab1SKenneth D. Merry }
467*ef270ab1SKenneth D. Merry
468*ef270ab1SKenneth D. Merry /**
469*ef270ab1SKenneth D. Merry * @brief Free a circular buffer
470*ef270ab1SKenneth D. Merry *
471*ef270ab1SKenneth D. Merry * The memory resources of a circular buffer are free'd
472*ef270ab1SKenneth D. Merry *
473*ef270ab1SKenneth D. Merry * @param cbuf pointer to circular buffer
474*ef270ab1SKenneth D. Merry *
475*ef270ab1SKenneth D. Merry * @return none
476*ef270ab1SKenneth D. Merry */
477*ef270ab1SKenneth D. Merry void
ocs_cbuf_free(ocs_cbuf_t * cbuf)478*ef270ab1SKenneth D. Merry ocs_cbuf_free(ocs_cbuf_t *cbuf)
479*ef270ab1SKenneth D. Merry {
480*ef270ab1SKenneth D. Merry if (cbuf != NULL) {
481*ef270ab1SKenneth D. Merry if (cbuf->array != NULL) {
482*ef270ab1SKenneth D. Merry ocs_free(cbuf->os, cbuf->array, sizeof(*cbuf->array) * cbuf->entry_count);
483*ef270ab1SKenneth D. Merry }
484*ef270ab1SKenneth D. Merry ocs_lock_free(&cbuf->cbuf_clock);
485*ef270ab1SKenneth D. Merry ocs_lock_free(&cbuf->cbuf_plock);
486*ef270ab1SKenneth D. Merry ocs_free(cbuf->os, cbuf, sizeof(*cbuf));
487*ef270ab1SKenneth D. Merry }
488*ef270ab1SKenneth D. Merry }
489*ef270ab1SKenneth D. Merry
490*ef270ab1SKenneth D. Merry /**
491*ef270ab1SKenneth D. Merry * @brief Get pointer to buffer
492*ef270ab1SKenneth D. Merry *
493*ef270ab1SKenneth D. Merry * Wait for a buffer to become available, and return a pointer to the buffer.
494*ef270ab1SKenneth D. Merry *
495*ef270ab1SKenneth D. Merry * @param cbuf pointer to circular buffer
496*ef270ab1SKenneth D. Merry * @param timeout_usec timeout in microseconds
497*ef270ab1SKenneth D. Merry *
498*ef270ab1SKenneth D. Merry * @return pointer to buffer, or NULL if timeout
499*ef270ab1SKenneth D. Merry */
500*ef270ab1SKenneth D. Merry void*
ocs_cbuf_get(ocs_cbuf_t * cbuf,int32_t timeout_usec)501*ef270ab1SKenneth D. Merry ocs_cbuf_get(ocs_cbuf_t *cbuf, int32_t timeout_usec)
502*ef270ab1SKenneth D. Merry {
503*ef270ab1SKenneth D. Merry void *ret = NULL;
504*ef270ab1SKenneth D. Merry
505*ef270ab1SKenneth D. Merry if (likely(ocs_sem_p(&cbuf->cbuf_csem, timeout_usec) == 0)) {
506*ef270ab1SKenneth D. Merry ocs_lock(&cbuf->cbuf_clock);
507*ef270ab1SKenneth D. Merry ret = cbuf->array[cbuf->cidx];
508*ef270ab1SKenneth D. Merry if (unlikely(++cbuf->cidx >= cbuf->entry_count)) {
509*ef270ab1SKenneth D. Merry cbuf->cidx = 0;
510*ef270ab1SKenneth D. Merry }
511*ef270ab1SKenneth D. Merry ocs_unlock(&cbuf->cbuf_clock);
512*ef270ab1SKenneth D. Merry ocs_sem_v(&cbuf->cbuf_psem);
513*ef270ab1SKenneth D. Merry }
514*ef270ab1SKenneth D. Merry return ret;
515*ef270ab1SKenneth D. Merry }
516*ef270ab1SKenneth D. Merry
517*ef270ab1SKenneth D. Merry /**
518*ef270ab1SKenneth D. Merry * @brief write a buffer
519*ef270ab1SKenneth D. Merry *
520*ef270ab1SKenneth D. Merry * The buffer is written to the circular buffer.
521*ef270ab1SKenneth D. Merry *
522*ef270ab1SKenneth D. Merry * @param cbuf pointer to circular buffer
523*ef270ab1SKenneth D. Merry * @param elem pointer to entry
524*ef270ab1SKenneth D. Merry *
525*ef270ab1SKenneth D. Merry * @return returns 0 for success, a negative error code value for failure.
526*ef270ab1SKenneth D. Merry */
527*ef270ab1SKenneth D. Merry int32_t
ocs_cbuf_put(ocs_cbuf_t * cbuf,void * elem)528*ef270ab1SKenneth D. Merry ocs_cbuf_put(ocs_cbuf_t *cbuf, void *elem)
529*ef270ab1SKenneth D. Merry {
530*ef270ab1SKenneth D. Merry int32_t rc = 0;
531*ef270ab1SKenneth D. Merry
532*ef270ab1SKenneth D. Merry if (likely(ocs_sem_p(&cbuf->cbuf_psem, -1) == 0)) {
533*ef270ab1SKenneth D. Merry ocs_lock(&cbuf->cbuf_plock);
534*ef270ab1SKenneth D. Merry cbuf->array[cbuf->pidx] = elem;
535*ef270ab1SKenneth D. Merry if (unlikely(++cbuf->pidx >= cbuf->entry_count)) {
536*ef270ab1SKenneth D. Merry cbuf->pidx = 0;
537*ef270ab1SKenneth D. Merry }
538*ef270ab1SKenneth D. Merry ocs_unlock(&cbuf->cbuf_plock);
539*ef270ab1SKenneth D. Merry ocs_sem_v(&cbuf->cbuf_csem);
540*ef270ab1SKenneth D. Merry } else {
541*ef270ab1SKenneth D. Merry rc = -1;
542*ef270ab1SKenneth D. Merry }
543*ef270ab1SKenneth D. Merry return rc;
544*ef270ab1SKenneth D. Merry }
545*ef270ab1SKenneth D. Merry
546*ef270ab1SKenneth D. Merry /**
547*ef270ab1SKenneth D. Merry * @brief Prime a circular buffer data
548*ef270ab1SKenneth D. Merry *
549*ef270ab1SKenneth D. Merry * Post array buffers to a circular buffer
550*ef270ab1SKenneth D. Merry *
551*ef270ab1SKenneth D. Merry * @param cbuf pointer to circular buffer
552*ef270ab1SKenneth D. Merry * @param array pointer to buffer array
553*ef270ab1SKenneth D. Merry *
554*ef270ab1SKenneth D. Merry * @return returns 0 for success, a negative error code value for failure.
555*ef270ab1SKenneth D. Merry */
556*ef270ab1SKenneth D. Merry int32_t
ocs_cbuf_prime(ocs_cbuf_t * cbuf,ocs_array_t * array)557*ef270ab1SKenneth D. Merry ocs_cbuf_prime(ocs_cbuf_t *cbuf, ocs_array_t *array)
558*ef270ab1SKenneth D. Merry {
559*ef270ab1SKenneth D. Merry uint32_t i;
560*ef270ab1SKenneth D. Merry uint32_t count = MIN(ocs_array_get_count(array), cbuf->entry_count);
561*ef270ab1SKenneth D. Merry
562*ef270ab1SKenneth D. Merry for (i = 0; i < count; i++) {
563*ef270ab1SKenneth D. Merry ocs_cbuf_put(cbuf, ocs_array_get(array, i));
564*ef270ab1SKenneth D. Merry }
565*ef270ab1SKenneth D. Merry return 0;
566*ef270ab1SKenneth D. Merry }
567*ef270ab1SKenneth D. Merry
568*ef270ab1SKenneth D. Merry /**
569*ef270ab1SKenneth D. Merry * @brief Generate driver dump start of file information
570*ef270ab1SKenneth D. Merry *
571*ef270ab1SKenneth D. Merry * The start of file information is added to 'textbuf'
572*ef270ab1SKenneth D. Merry *
573*ef270ab1SKenneth D. Merry * @param textbuf pointer to driver dump text buffer
574*ef270ab1SKenneth D. Merry *
575*ef270ab1SKenneth D. Merry * @return none
576*ef270ab1SKenneth D. Merry */
577*ef270ab1SKenneth D. Merry
578*ef270ab1SKenneth D. Merry void
ocs_ddump_startfile(ocs_textbuf_t * textbuf)579*ef270ab1SKenneth D. Merry ocs_ddump_startfile(ocs_textbuf_t *textbuf)
580*ef270ab1SKenneth D. Merry {
581*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n");
582*ef270ab1SKenneth D. Merry }
583*ef270ab1SKenneth D. Merry
584*ef270ab1SKenneth D. Merry /**
585*ef270ab1SKenneth D. Merry * @brief Generate driver dump end of file information
586*ef270ab1SKenneth D. Merry *
587*ef270ab1SKenneth D. Merry * The end of file information is added to 'textbuf'
588*ef270ab1SKenneth D. Merry *
589*ef270ab1SKenneth D. Merry * @param textbuf pointer to driver dump text buffer
590*ef270ab1SKenneth D. Merry *
591*ef270ab1SKenneth D. Merry * @return none
592*ef270ab1SKenneth D. Merry */
593*ef270ab1SKenneth D. Merry
594*ef270ab1SKenneth D. Merry void
ocs_ddump_endfile(ocs_textbuf_t * textbuf)595*ef270ab1SKenneth D. Merry ocs_ddump_endfile(ocs_textbuf_t *textbuf)
596*ef270ab1SKenneth D. Merry {
597*ef270ab1SKenneth D. Merry }
598*ef270ab1SKenneth D. Merry
599*ef270ab1SKenneth D. Merry /**
600*ef270ab1SKenneth D. Merry * @brief Generate driver dump section start data
601*ef270ab1SKenneth D. Merry *
602*ef270ab1SKenneth D. Merry * The driver section start information is added to textbuf
603*ef270ab1SKenneth D. Merry *
604*ef270ab1SKenneth D. Merry * @param textbuf pointer to text buffer
605*ef270ab1SKenneth D. Merry * @param name name of section
606*ef270ab1SKenneth D. Merry * @param instance instance number of this section
607*ef270ab1SKenneth D. Merry *
608*ef270ab1SKenneth D. Merry * @return none
609*ef270ab1SKenneth D. Merry */
610*ef270ab1SKenneth D. Merry
611*ef270ab1SKenneth D. Merry void
ocs_ddump_section(ocs_textbuf_t * textbuf,const char * name,uint32_t instance)612*ef270ab1SKenneth D. Merry ocs_ddump_section(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
613*ef270ab1SKenneth D. Merry {
614*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "<%s type=\"section\" instance=\"%d\">\n", name, instance);
615*ef270ab1SKenneth D. Merry }
616*ef270ab1SKenneth D. Merry
617*ef270ab1SKenneth D. Merry /**
618*ef270ab1SKenneth D. Merry * @brief Generate driver dump section end data
619*ef270ab1SKenneth D. Merry *
620*ef270ab1SKenneth D. Merry * The driver section end information is added to textbuf
621*ef270ab1SKenneth D. Merry *
622*ef270ab1SKenneth D. Merry * @param textbuf pointer to text buffer
623*ef270ab1SKenneth D. Merry * @param name name of section
624*ef270ab1SKenneth D. Merry * @param instance instance number of this section
625*ef270ab1SKenneth D. Merry *
626*ef270ab1SKenneth D. Merry * @return none
627*ef270ab1SKenneth D. Merry */
628*ef270ab1SKenneth D. Merry
629*ef270ab1SKenneth D. Merry void
ocs_ddump_endsection(ocs_textbuf_t * textbuf,const char * name,uint32_t instance)630*ef270ab1SKenneth D. Merry ocs_ddump_endsection(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
631*ef270ab1SKenneth D. Merry {
632*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "</%s>\n", name);
633*ef270ab1SKenneth D. Merry }
634*ef270ab1SKenneth D. Merry
635*ef270ab1SKenneth D. Merry /**
636*ef270ab1SKenneth D. Merry * @brief Generate driver dump data for a given value
637*ef270ab1SKenneth D. Merry *
638*ef270ab1SKenneth D. Merry * A value is added to textbuf
639*ef270ab1SKenneth D. Merry *
640*ef270ab1SKenneth D. Merry * @param textbuf pointer to text buffer
641*ef270ab1SKenneth D. Merry * @param name name of variable
642*ef270ab1SKenneth D. Merry * @param fmt snprintf format specifier
643*ef270ab1SKenneth D. Merry *
644*ef270ab1SKenneth D. Merry * @return none
645*ef270ab1SKenneth D. Merry */
646*ef270ab1SKenneth D. Merry
647*ef270ab1SKenneth D. Merry void
ocs_ddump_value(ocs_textbuf_t * textbuf,const char * name,const char * fmt,...)648*ef270ab1SKenneth D. Merry ocs_ddump_value(ocs_textbuf_t *textbuf, const char *name, const char *fmt, ...)
649*ef270ab1SKenneth D. Merry {
650*ef270ab1SKenneth D. Merry va_list ap;
651*ef270ab1SKenneth D. Merry char valuebuf[64];
652*ef270ab1SKenneth D. Merry
653*ef270ab1SKenneth D. Merry va_start(ap, fmt);
654*ef270ab1SKenneth D. Merry vsnprintf(valuebuf, sizeof(valuebuf), fmt, ap);
655*ef270ab1SKenneth D. Merry va_end(ap);
656*ef270ab1SKenneth D. Merry
657*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "<%s>%s</%s>\n", name, valuebuf, name);
658*ef270ab1SKenneth D. Merry }
659*ef270ab1SKenneth D. Merry
660*ef270ab1SKenneth D. Merry /**
661*ef270ab1SKenneth D. Merry * @brief Generate driver dump data for an arbitrary buffer of DWORDS
662*ef270ab1SKenneth D. Merry *
663*ef270ab1SKenneth D. Merry * A status value is added to textbuf
664*ef270ab1SKenneth D. Merry *
665*ef270ab1SKenneth D. Merry * @param textbuf pointer to text buffer
666*ef270ab1SKenneth D. Merry * @param name name of status variable
667*ef270ab1SKenneth D. Merry * @param instance instance number of this section
668*ef270ab1SKenneth D. Merry * @param buffer buffer to print
669*ef270ab1SKenneth D. Merry * @param size size of buffer in bytes
670*ef270ab1SKenneth D. Merry *
671*ef270ab1SKenneth D. Merry * @return none
672*ef270ab1SKenneth D. Merry */
673*ef270ab1SKenneth D. Merry
674*ef270ab1SKenneth D. Merry void
ocs_ddump_buffer(ocs_textbuf_t * textbuf,const char * name,uint32_t instance,void * buffer,uint32_t size)675*ef270ab1SKenneth D. Merry ocs_ddump_buffer(ocs_textbuf_t *textbuf, const char *name, uint32_t instance, void *buffer, uint32_t size)
676*ef270ab1SKenneth D. Merry {
677*ef270ab1SKenneth D. Merry uint32_t *dword;
678*ef270ab1SKenneth D. Merry uint32_t i;
679*ef270ab1SKenneth D. Merry uint32_t count;
680*ef270ab1SKenneth D. Merry
681*ef270ab1SKenneth D. Merry count = size / sizeof(uint32_t);
682*ef270ab1SKenneth D. Merry
683*ef270ab1SKenneth D. Merry if (count == 0) {
684*ef270ab1SKenneth D. Merry return;
685*ef270ab1SKenneth D. Merry }
686*ef270ab1SKenneth D. Merry
687*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "<%s type=\"buffer\" instance=\"%d\">\n", name, instance);
688*ef270ab1SKenneth D. Merry
689*ef270ab1SKenneth D. Merry dword = buffer;
690*ef270ab1SKenneth D. Merry for (i = 0; i < count; i++) {
691*ef270ab1SKenneth D. Merry #define OCS_NEWLINE_MOD 8
692*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "%08x ", *dword++);
693*ef270ab1SKenneth D. Merry if ((i % OCS_NEWLINE_MOD) == (OCS_NEWLINE_MOD - 1)) {
694*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "\n");
695*ef270ab1SKenneth D. Merry }
696*ef270ab1SKenneth D. Merry }
697*ef270ab1SKenneth D. Merry
698*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "</%s>\n", name);
699*ef270ab1SKenneth D. Merry }
700*ef270ab1SKenneth D. Merry
701*ef270ab1SKenneth D. Merry /**
702*ef270ab1SKenneth D. Merry * @brief Generate driver dump for queue
703*ef270ab1SKenneth D. Merry *
704*ef270ab1SKenneth D. Merry * Add queue elements to text buffer
705*ef270ab1SKenneth D. Merry *
706*ef270ab1SKenneth D. Merry * @param textbuf pointer to driver dump text buffer
707*ef270ab1SKenneth D. Merry * @param q_addr address of start of queue
708*ef270ab1SKenneth D. Merry * @param size size of each queue entry
709*ef270ab1SKenneth D. Merry * @param length number of queue entries in the queue
710*ef270ab1SKenneth D. Merry * @param index current index of queue
711*ef270ab1SKenneth D. Merry * @param qentries number of most recent queue entries to dump
712*ef270ab1SKenneth D. Merry *
713*ef270ab1SKenneth D. Merry * @return none
714*ef270ab1SKenneth D. Merry */
715*ef270ab1SKenneth D. Merry
716*ef270ab1SKenneth D. Merry void
ocs_ddump_queue_entries(ocs_textbuf_t * textbuf,void * q_addr,uint32_t size,uint32_t length,int32_t index,uint32_t qentries)717*ef270ab1SKenneth D. Merry ocs_ddump_queue_entries(ocs_textbuf_t *textbuf, void *q_addr, uint32_t size,
718*ef270ab1SKenneth D. Merry uint32_t length, int32_t index, uint32_t qentries)
719*ef270ab1SKenneth D. Merry {
720*ef270ab1SKenneth D. Merry uint32_t i;
721*ef270ab1SKenneth D. Merry uint32_t j;
722*ef270ab1SKenneth D. Merry uint8_t *entry;
723*ef270ab1SKenneth D. Merry uint32_t *dword;
724*ef270ab1SKenneth D. Merry uint32_t entry_count = 0;
725*ef270ab1SKenneth D. Merry uint32_t entry_words = size / sizeof(uint32_t);
726*ef270ab1SKenneth D. Merry
727*ef270ab1SKenneth D. Merry if ((qentries == (uint32_t)-1) || (qentries > length)) {
728*ef270ab1SKenneth D. Merry /* if qentries is -1 or larger than queue size, dump entire queue */
729*ef270ab1SKenneth D. Merry entry_count = length;
730*ef270ab1SKenneth D. Merry index = 0;
731*ef270ab1SKenneth D. Merry } else {
732*ef270ab1SKenneth D. Merry entry_count = qentries;
733*ef270ab1SKenneth D. Merry
734*ef270ab1SKenneth D. Merry index -= (qentries - 1);
735*ef270ab1SKenneth D. Merry if (index < 0) {
736*ef270ab1SKenneth D. Merry index += length;
737*ef270ab1SKenneth D. Merry }
738*ef270ab1SKenneth D. Merry }
739*ef270ab1SKenneth D. Merry #define OCS_NEWLINE_MOD 8
740*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "<qentries>\n");
741*ef270ab1SKenneth D. Merry for (i = 0; i < entry_count; i++){
742*ef270ab1SKenneth D. Merry entry = q_addr;
743*ef270ab1SKenneth D. Merry entry += index * size;
744*ef270ab1SKenneth D. Merry dword = (uint32_t *)entry;
745*ef270ab1SKenneth D. Merry
746*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "[%04x] ", index);
747*ef270ab1SKenneth D. Merry for (j = 0; j < entry_words; j++) {
748*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "%08x ", *dword++);
749*ef270ab1SKenneth D. Merry if (((j+1) == entry_words) ||
750*ef270ab1SKenneth D. Merry ((j % OCS_NEWLINE_MOD) == (OCS_NEWLINE_MOD - 1))) {
751*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "\n");
752*ef270ab1SKenneth D. Merry if ((j+1) < entry_words) {
753*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, " ");
754*ef270ab1SKenneth D. Merry }
755*ef270ab1SKenneth D. Merry }
756*ef270ab1SKenneth D. Merry }
757*ef270ab1SKenneth D. Merry
758*ef270ab1SKenneth D. Merry index++;
759*ef270ab1SKenneth D. Merry if ((uint32_t)index >= length) {
760*ef270ab1SKenneth D. Merry index = 0;
761*ef270ab1SKenneth D. Merry }
762*ef270ab1SKenneth D. Merry }
763*ef270ab1SKenneth D. Merry ocs_textbuf_printf(textbuf, "</qentries>\n");
764*ef270ab1SKenneth D. Merry }
765*ef270ab1SKenneth D. Merry
766*ef270ab1SKenneth D. Merry #define OCS_DEBUG_ENABLE(x) (x ? ~0 : 0)
767*ef270ab1SKenneth D. Merry
768*ef270ab1SKenneth D. Merry #define OCS_DEBUG_MASK \
769*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(1) & OCS_DEBUG_ALWAYS) | \
770*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_MQ_DUMP) | \
771*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_CQ_DUMP) | \
772*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_WQ_DUMP) | \
773*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_EQ_DUMP) | \
774*ef270ab1SKenneth D. Merry (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_SPARAM_DUMP)
775*ef270ab1SKenneth D. Merry
776*ef270ab1SKenneth D. Merry static uint32_t ocs_debug_mask = OCS_DEBUG_MASK;
777*ef270ab1SKenneth D. Merry
778*ef270ab1SKenneth D. Merry static int
_isprint(int c)779*ef270ab1SKenneth D. Merry _isprint(int c) {
780*ef270ab1SKenneth D. Merry return ((c > 32) && (c < 127));
781*ef270ab1SKenneth D. Merry }
782*ef270ab1SKenneth D. Merry
783*ef270ab1SKenneth D. Merry /**
784*ef270ab1SKenneth D. Merry * @ingroup debug
785*ef270ab1SKenneth D. Merry * @brief enable debug options
786*ef270ab1SKenneth D. Merry *
787*ef270ab1SKenneth D. Merry * Enables debug options by or-ing in <b>mask</b> into the currently enabled
788*ef270ab1SKenneth D. Merry * debug mask.
789*ef270ab1SKenneth D. Merry *
790*ef270ab1SKenneth D. Merry * @param mask mask bits to enable
791*ef270ab1SKenneth D. Merry *
792*ef270ab1SKenneth D. Merry * @return none
793*ef270ab1SKenneth D. Merry */
794*ef270ab1SKenneth D. Merry
ocs_debug_enable(uint32_t mask)795*ef270ab1SKenneth D. Merry void ocs_debug_enable(uint32_t mask) {
796*ef270ab1SKenneth D. Merry ocs_debug_mask |= mask;
797*ef270ab1SKenneth D. Merry }
798*ef270ab1SKenneth D. Merry
799*ef270ab1SKenneth D. Merry /**
800*ef270ab1SKenneth D. Merry * @ingroup debug
801*ef270ab1SKenneth D. Merry * @brief disable debug options
802*ef270ab1SKenneth D. Merry *
803*ef270ab1SKenneth D. Merry * Disables debug options by clearing bits in <b>mask</b> into the currently enabled
804*ef270ab1SKenneth D. Merry * debug mask.
805*ef270ab1SKenneth D. Merry *
806*ef270ab1SKenneth D. Merry * @param mask mask bits to enable
807*ef270ab1SKenneth D. Merry *
808*ef270ab1SKenneth D. Merry * @return none
809*ef270ab1SKenneth D. Merry */
810*ef270ab1SKenneth D. Merry
ocs_debug_disable(uint32_t mask)811*ef270ab1SKenneth D. Merry void ocs_debug_disable(uint32_t mask) {
812*ef270ab1SKenneth D. Merry ocs_debug_mask &= ~mask;
813*ef270ab1SKenneth D. Merry }
814*ef270ab1SKenneth D. Merry
815*ef270ab1SKenneth D. Merry /**
816*ef270ab1SKenneth D. Merry * @ingroup debug
817*ef270ab1SKenneth D. Merry * @brief return true if debug bits are enabled
818*ef270ab1SKenneth D. Merry *
819*ef270ab1SKenneth D. Merry * Returns true if the request debug bits are set.
820*ef270ab1SKenneth D. Merry *
821*ef270ab1SKenneth D. Merry * @param mask debug bit mask
822*ef270ab1SKenneth D. Merry *
823*ef270ab1SKenneth D. Merry * @return true if corresponding bits are set
824*ef270ab1SKenneth D. Merry *
825*ef270ab1SKenneth D. Merry * @note Passing in a mask value of zero always returns true
826*ef270ab1SKenneth D. Merry */
827*ef270ab1SKenneth D. Merry
ocs_debug_is_enabled(uint32_t mask)828*ef270ab1SKenneth D. Merry int ocs_debug_is_enabled(uint32_t mask) {
829*ef270ab1SKenneth D. Merry return (ocs_debug_mask & mask) == mask;
830*ef270ab1SKenneth D. Merry }
831*ef270ab1SKenneth D. Merry
832*ef270ab1SKenneth D. Merry /**
833*ef270ab1SKenneth D. Merry * @ingroup debug
834*ef270ab1SKenneth D. Merry * @brief Dump 32 bit hex/ascii data
835*ef270ab1SKenneth D. Merry *
836*ef270ab1SKenneth D. Merry * Dumps using ocs_log a buffer of data as 32 bit hex and ascii
837*ef270ab1SKenneth D. Merry *
838*ef270ab1SKenneth D. Merry * @param mask debug enable bits
839*ef270ab1SKenneth D. Merry * @param os os handle
840*ef270ab1SKenneth D. Merry * @param label text label for the display (may be NULL)
841*ef270ab1SKenneth D. Merry * @param buf pointer to data buffer
842*ef270ab1SKenneth D. Merry * @param buf_length length of data buffer
843*ef270ab1SKenneth D. Merry *
844*ef270ab1SKenneth D. Merry * @return none
845*ef270ab1SKenneth D. Merry *
846*ef270ab1SKenneth D. Merry */
847*ef270ab1SKenneth D. Merry
848*ef270ab1SKenneth D. Merry void
ocs_dump32(uint32_t mask,ocs_os_handle_t os,const char * label,void * buf,uint32_t buf_length)849*ef270ab1SKenneth D. Merry ocs_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
850*ef270ab1SKenneth D. Merry {
851*ef270ab1SKenneth D. Merry uint32_t word_count = buf_length / sizeof(uint32_t);
852*ef270ab1SKenneth D. Merry uint32_t i;
853*ef270ab1SKenneth D. Merry uint32_t columns = 8;
854*ef270ab1SKenneth D. Merry uint32_t n;
855*ef270ab1SKenneth D. Merry uint32_t *wbuf;
856*ef270ab1SKenneth D. Merry char *cbuf;
857*ef270ab1SKenneth D. Merry uint32_t addr = 0;
858*ef270ab1SKenneth D. Merry char linebuf[200];
859*ef270ab1SKenneth D. Merry char *pbuf = linebuf;
860*ef270ab1SKenneth D. Merry
861*ef270ab1SKenneth D. Merry if (!ocs_debug_is_enabled(mask))
862*ef270ab1SKenneth D. Merry return;
863*ef270ab1SKenneth D. Merry
864*ef270ab1SKenneth D. Merry if (label)
865*ef270ab1SKenneth D. Merry ocs_log_debug(os, "%s\n", label);
866*ef270ab1SKenneth D. Merry
867*ef270ab1SKenneth D. Merry wbuf = buf;
868*ef270ab1SKenneth D. Merry while (word_count > 0) {
869*ef270ab1SKenneth D. Merry pbuf = linebuf;
870*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), "%08X: ", addr);
871*ef270ab1SKenneth D. Merry
872*ef270ab1SKenneth D. Merry n = word_count;
873*ef270ab1SKenneth D. Merry if (n > columns)
874*ef270ab1SKenneth D. Merry n = columns;
875*ef270ab1SKenneth D. Merry
876*ef270ab1SKenneth D. Merry for (i = 0; i < n; i ++)
877*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), "%08X ", wbuf[i]);
878*ef270ab1SKenneth D. Merry
879*ef270ab1SKenneth D. Merry for (; i < columns; i ++)
880*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), "%8s ", "");
881*ef270ab1SKenneth D. Merry
882*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), " ");
883*ef270ab1SKenneth D. Merry cbuf = (char*)wbuf;
884*ef270ab1SKenneth D. Merry for (i = 0; i < n*sizeof(uint32_t); i ++)
885*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), "%c", _isprint(cbuf[i]) ? cbuf[i] : '.');
886*ef270ab1SKenneth D. Merry pbuf += ocs_snprintf(pbuf, sizeof(linebuf) - (pbuf-linebuf), "\n");
887*ef270ab1SKenneth D. Merry
888*ef270ab1SKenneth D. Merry ocs_log_debug(os, "%s", linebuf);
889*ef270ab1SKenneth D. Merry
890*ef270ab1SKenneth D. Merry wbuf += n;
891*ef270ab1SKenneth D. Merry word_count -= n;
892*ef270ab1SKenneth D. Merry addr += n*sizeof(uint32_t);
893*ef270ab1SKenneth D. Merry }
894*ef270ab1SKenneth D. Merry }
895*ef270ab1SKenneth D. Merry
896*ef270ab1SKenneth D. Merry #if defined(OCS_DEBUG_QUEUE_HISTORY)
897*ef270ab1SKenneth D. Merry
898*ef270ab1SKenneth D. Merry /* each bit corresponds to word to capture */
899*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_WQE_WORD_MASK_DEFAULT (BIT(4) | BIT(6) | BIT(7) | BIT(9) | BIT(12))
900*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_TRECV_CONT_WQE_WORD_MASK (BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(9) | BIT(12))
901*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_IWRITE_WQE_WORD_MASK (BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(9))
902*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_IREAD_WQE_WORD_MASK (BIT(4) | BIT(6) | BIT(7) | BIT(9))
903*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_ABORT_WQE_WORD_MASK (BIT(3) | BIT(7) | BIT(8) | BIT(9))
904*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_WCQE_WORD_MASK (BIT(0) | BIT(3))
905*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_WCQE_WORD_MASK_ERR (BIT(0) | BIT(1) | BIT(2) | BIT(3))
906*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_CQXABT_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
907*ef270ab1SKenneth D. Merry
908*ef270ab1SKenneth D. Merry /* if set, will provide extra queue information in each entry */
909*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_ENABLE_Q_INFO 0
ocs_queue_history_q_info_enabled(void)910*ef270ab1SKenneth D. Merry uint8_t ocs_queue_history_q_info_enabled(void)
911*ef270ab1SKenneth D. Merry {
912*ef270ab1SKenneth D. Merry return OCS_Q_HIST_ENABLE_Q_INFO;
913*ef270ab1SKenneth D. Merry }
914*ef270ab1SKenneth D. Merry
915*ef270ab1SKenneth D. Merry /* if set, will provide timestamps in each entry */
916*ef270ab1SKenneth D. Merry #define OCS_Q_HIST_ENABLE_TIMESTAMPS 0
ocs_queue_history_timestamp_enabled(void)917*ef270ab1SKenneth D. Merry uint8_t ocs_queue_history_timestamp_enabled(void)
918*ef270ab1SKenneth D. Merry {
919*ef270ab1SKenneth D. Merry return OCS_Q_HIST_ENABLE_TIMESTAMPS;
920*ef270ab1SKenneth D. Merry }
921*ef270ab1SKenneth D. Merry
922*ef270ab1SKenneth D. Merry /* Add WQEs and masks to override default WQE mask */
923*ef270ab1SKenneth D. Merry ocs_q_hist_wqe_mask_t ocs_q_hist_wqe_masks[] = {
924*ef270ab1SKenneth D. Merry /* WQE command Word mask */
925*ef270ab1SKenneth D. Merry {SLI4_WQE_ABORT, OCS_Q_HIST_ABORT_WQE_WORD_MASK},
926*ef270ab1SKenneth D. Merry {SLI4_WQE_FCP_IREAD64, OCS_Q_HIST_IREAD_WQE_WORD_MASK},
927*ef270ab1SKenneth D. Merry {SLI4_WQE_FCP_IWRITE64, OCS_Q_HIST_IWRITE_WQE_WORD_MASK},
928*ef270ab1SKenneth D. Merry {SLI4_WQE_FCP_CONT_TRECEIVE64, OCS_Q_HIST_TRECV_CONT_WQE_WORD_MASK},
929*ef270ab1SKenneth D. Merry };
930*ef270ab1SKenneth D. Merry
931*ef270ab1SKenneth D. Merry /* CQE masks */
932*ef270ab1SKenneth D. Merry ocs_q_hist_cqe_mask_t ocs_q_hist_cqe_masks[] = {
933*ef270ab1SKenneth D. Merry /* CQE type Q_hist_type mask (success) mask (non-success) */
934*ef270ab1SKenneth D. Merry {SLI_QENTRY_WQ, OCS_Q_HIST_TYPE_CWQE, OCS_Q_HIST_WCQE_WORD_MASK, OCS_Q_HIST_WCQE_WORD_MASK_ERR},
935*ef270ab1SKenneth D. Merry {SLI_QENTRY_XABT, OCS_Q_HIST_TYPE_CXABT, OCS_Q_HIST_CQXABT_WORD_MASK, OCS_Q_HIST_WCQE_WORD_MASK},
936*ef270ab1SKenneth D. Merry };
937*ef270ab1SKenneth D. Merry
ocs_q_hist_get_wqe_mask(sli4_generic_wqe_t * wqe)938*ef270ab1SKenneth D. Merry static uint32_t ocs_q_hist_get_wqe_mask(sli4_generic_wqe_t *wqe)
939*ef270ab1SKenneth D. Merry {
940*ef270ab1SKenneth D. Merry uint32_t i;
941*ef270ab1SKenneth D. Merry for (i = 0; i < ARRAY_SIZE(ocs_q_hist_wqe_masks); i++) {
942*ef270ab1SKenneth D. Merry if (ocs_q_hist_wqe_masks[i].command == wqe->command) {
943*ef270ab1SKenneth D. Merry return ocs_q_hist_wqe_masks[i].mask;
944*ef270ab1SKenneth D. Merry }
945*ef270ab1SKenneth D. Merry }
946*ef270ab1SKenneth D. Merry /* return default WQE mask */
947*ef270ab1SKenneth D. Merry return OCS_Q_HIST_WQE_WORD_MASK_DEFAULT;
948*ef270ab1SKenneth D. Merry }
949*ef270ab1SKenneth D. Merry
950*ef270ab1SKenneth D. Merry /**
951*ef270ab1SKenneth D. Merry * @ingroup debug
952*ef270ab1SKenneth D. Merry * @brief Initialize resources for queue history
953*ef270ab1SKenneth D. Merry *
954*ef270ab1SKenneth D. Merry * @param os os handle
955*ef270ab1SKenneth D. Merry * @param q_hist Pointer to the queue history object.
956*ef270ab1SKenneth D. Merry *
957*ef270ab1SKenneth D. Merry * @return none
958*ef270ab1SKenneth D. Merry */
959*ef270ab1SKenneth D. Merry void
ocs_queue_history_init(ocs_t * ocs,ocs_hw_q_hist_t * q_hist)960*ef270ab1SKenneth D. Merry ocs_queue_history_init(ocs_t *ocs, ocs_hw_q_hist_t *q_hist)
961*ef270ab1SKenneth D. Merry {
962*ef270ab1SKenneth D. Merry q_hist->ocs = ocs;
963*ef270ab1SKenneth D. Merry if (q_hist->q_hist != NULL) {
964*ef270ab1SKenneth D. Merry /* Setup is already done */
965*ef270ab1SKenneth D. Merry ocs_log_debug(ocs, "q_hist not NULL, skipping init\n");
966*ef270ab1SKenneth D. Merry return;
967*ef270ab1SKenneth D. Merry }
968*ef270ab1SKenneth D. Merry
969*ef270ab1SKenneth D. Merry q_hist->q_hist = ocs_malloc(ocs, sizeof(*q_hist->q_hist)*OCS_Q_HIST_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
970*ef270ab1SKenneth D. Merry
971*ef270ab1SKenneth D. Merry if (q_hist->q_hist == NULL) {
972*ef270ab1SKenneth D. Merry ocs_log_err(ocs, "Could not allocate queue history buffer\n");
973*ef270ab1SKenneth D. Merry } else {
974*ef270ab1SKenneth D. Merry ocs_lock_init(ocs, &q_hist->q_hist_lock, "queue history lock[%d]", ocs_instance(ocs));
975*ef270ab1SKenneth D. Merry }
976*ef270ab1SKenneth D. Merry
977*ef270ab1SKenneth D. Merry q_hist->q_hist_index = 0;
978*ef270ab1SKenneth D. Merry }
979*ef270ab1SKenneth D. Merry
980*ef270ab1SKenneth D. Merry /**
981*ef270ab1SKenneth D. Merry * @ingroup debug
982*ef270ab1SKenneth D. Merry * @brief Free resources for queue history
983*ef270ab1SKenneth D. Merry *
984*ef270ab1SKenneth D. Merry * @param q_hist Pointer to the queue history object.
985*ef270ab1SKenneth D. Merry *
986*ef270ab1SKenneth D. Merry * @return none
987*ef270ab1SKenneth D. Merry */
988*ef270ab1SKenneth D. Merry void
ocs_queue_history_free(ocs_hw_q_hist_t * q_hist)989*ef270ab1SKenneth D. Merry ocs_queue_history_free(ocs_hw_q_hist_t *q_hist)
990*ef270ab1SKenneth D. Merry {
991*ef270ab1SKenneth D. Merry ocs_t *ocs = q_hist->ocs;
992*ef270ab1SKenneth D. Merry
993*ef270ab1SKenneth D. Merry if (q_hist->q_hist != NULL) {
994*ef270ab1SKenneth D. Merry ocs_free(ocs, q_hist->q_hist, sizeof(*q_hist->q_hist)*OCS_Q_HIST_SIZE);
995*ef270ab1SKenneth D. Merry ocs_lock_free(&q_hist->q_hist_lock);
996*ef270ab1SKenneth D. Merry q_hist->q_hist = NULL;
997*ef270ab1SKenneth D. Merry }
998*ef270ab1SKenneth D. Merry }
999*ef270ab1SKenneth D. Merry
1000*ef270ab1SKenneth D. Merry static void
ocs_queue_history_add_q_info(ocs_hw_q_hist_t * q_hist,uint32_t qid,uint32_t qindex)1001*ef270ab1SKenneth D. Merry ocs_queue_history_add_q_info(ocs_hw_q_hist_t *q_hist, uint32_t qid, uint32_t qindex)
1002*ef270ab1SKenneth D. Merry {
1003*ef270ab1SKenneth D. Merry if (ocs_queue_history_q_info_enabled()) {
1004*ef270ab1SKenneth D. Merry /* write qid, index */
1005*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = (qid << 16) | qindex;
1006*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1007*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1008*ef270ab1SKenneth D. Merry }
1009*ef270ab1SKenneth D. Merry }
1010*ef270ab1SKenneth D. Merry
1011*ef270ab1SKenneth D. Merry static void
ocs_queue_history_add_timestamp(ocs_hw_q_hist_t * q_hist)1012*ef270ab1SKenneth D. Merry ocs_queue_history_add_timestamp(ocs_hw_q_hist_t *q_hist)
1013*ef270ab1SKenneth D. Merry {
1014*ef270ab1SKenneth D. Merry if (ocs_queue_history_timestamp_enabled()) {
1015*ef270ab1SKenneth D. Merry /* write tsc */
1016*ef270ab1SKenneth D. Merry uint64_t tsc_value;
1017*ef270ab1SKenneth D. Merry tsc_value = get_cyclecount();
1018*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = ((tsc_value >> 32 ) & 0xFFFFFFFF);
1019*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1020*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1021*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = (tsc_value & 0xFFFFFFFF);
1022*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1023*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1024*ef270ab1SKenneth D. Merry }
1025*ef270ab1SKenneth D. Merry }
1026*ef270ab1SKenneth D. Merry
1027*ef270ab1SKenneth D. Merry /**
1028*ef270ab1SKenneth D. Merry * @ingroup debug
1029*ef270ab1SKenneth D. Merry * @brief Log work queue entry (WQE) into history array
1030*ef270ab1SKenneth D. Merry *
1031*ef270ab1SKenneth D. Merry * @param q_hist Pointer to the queue history object.
1032*ef270ab1SKenneth D. Merry * @param entryw Work queue entry in words
1033*ef270ab1SKenneth D. Merry * @param qid Queue ID
1034*ef270ab1SKenneth D. Merry * @param qindex Queue index
1035*ef270ab1SKenneth D. Merry *
1036*ef270ab1SKenneth D. Merry * @return none
1037*ef270ab1SKenneth D. Merry */
1038*ef270ab1SKenneth D. Merry void
ocs_queue_history_wq(ocs_hw_q_hist_t * q_hist,uint32_t * entryw,uint32_t qid,uint32_t qindex)1039*ef270ab1SKenneth D. Merry ocs_queue_history_wq(ocs_hw_q_hist_t *q_hist, uint32_t *entryw, uint32_t qid, uint32_t qindex)
1040*ef270ab1SKenneth D. Merry {
1041*ef270ab1SKenneth D. Merry int i;
1042*ef270ab1SKenneth D. Merry ocs_q_hist_ftr_t ftr;
1043*ef270ab1SKenneth D. Merry uint32_t wqe_word_mask = ocs_q_hist_get_wqe_mask((sli4_generic_wqe_t *)entryw);
1044*ef270ab1SKenneth D. Merry
1045*ef270ab1SKenneth D. Merry if (q_hist->q_hist == NULL) {
1046*ef270ab1SKenneth D. Merry /* Can't save anything */
1047*ef270ab1SKenneth D. Merry return;
1048*ef270ab1SKenneth D. Merry }
1049*ef270ab1SKenneth D. Merry
1050*ef270ab1SKenneth D. Merry ftr.word = 0;
1051*ef270ab1SKenneth D. Merry ftr.s.type = OCS_Q_HIST_TYPE_WQE;
1052*ef270ab1SKenneth D. Merry ocs_lock(&q_hist->q_hist_lock);
1053*ef270ab1SKenneth D. Merry /* Capture words in reverse order since we'll be interpretting them LIFO */
1054*ef270ab1SKenneth D. Merry for (i = ((sizeof(wqe_word_mask)*8) - 1); i >= 0; i--){
1055*ef270ab1SKenneth D. Merry if ((wqe_word_mask >> i) & 1) {
1056*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
1057*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1058*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1059*ef270ab1SKenneth D. Merry }
1060*ef270ab1SKenneth D. Merry }
1061*ef270ab1SKenneth D. Merry
1062*ef270ab1SKenneth D. Merry ocs_queue_history_add_q_info(q_hist, qid, qindex);
1063*ef270ab1SKenneth D. Merry ocs_queue_history_add_timestamp(q_hist);
1064*ef270ab1SKenneth D. Merry
1065*ef270ab1SKenneth D. Merry /* write footer */
1066*ef270ab1SKenneth D. Merry if (wqe_word_mask) {
1067*ef270ab1SKenneth D. Merry ftr.s.mask = wqe_word_mask;
1068*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
1069*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1070*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1071*ef270ab1SKenneth D. Merry }
1072*ef270ab1SKenneth D. Merry
1073*ef270ab1SKenneth D. Merry ocs_unlock(&q_hist->q_hist_lock);
1074*ef270ab1SKenneth D. Merry }
1075*ef270ab1SKenneth D. Merry
1076*ef270ab1SKenneth D. Merry /**
1077*ef270ab1SKenneth D. Merry * @ingroup debug
1078*ef270ab1SKenneth D. Merry * @brief Log misc words
1079*ef270ab1SKenneth D. Merry *
1080*ef270ab1SKenneth D. Merry * @param q_hist Pointer to the queue history object.
1081*ef270ab1SKenneth D. Merry * @param entryw array of words
1082*ef270ab1SKenneth D. Merry * @param num_words number of words in entryw
1083*ef270ab1SKenneth D. Merry *
1084*ef270ab1SKenneth D. Merry * @return none
1085*ef270ab1SKenneth D. Merry */
1086*ef270ab1SKenneth D. Merry void
ocs_queue_history_misc(ocs_hw_q_hist_t * q_hist,uint32_t * entryw,uint32_t num_words)1087*ef270ab1SKenneth D. Merry ocs_queue_history_misc(ocs_hw_q_hist_t *q_hist, uint32_t *entryw, uint32_t num_words)
1088*ef270ab1SKenneth D. Merry {
1089*ef270ab1SKenneth D. Merry int i;
1090*ef270ab1SKenneth D. Merry ocs_q_hist_ftr_t ftr;
1091*ef270ab1SKenneth D. Merry uint32_t mask = 0;
1092*ef270ab1SKenneth D. Merry
1093*ef270ab1SKenneth D. Merry if (q_hist->q_hist == NULL) {
1094*ef270ab1SKenneth D. Merry /* Can't save anything */
1095*ef270ab1SKenneth D. Merry return;
1096*ef270ab1SKenneth D. Merry }
1097*ef270ab1SKenneth D. Merry
1098*ef270ab1SKenneth D. Merry ftr.word = 0;
1099*ef270ab1SKenneth D. Merry ftr.s.type = OCS_Q_HIST_TYPE_MISC;
1100*ef270ab1SKenneth D. Merry ocs_lock(&q_hist->q_hist_lock);
1101*ef270ab1SKenneth D. Merry /* Capture words in reverse order since we'll be interpretting them LIFO */
1102*ef270ab1SKenneth D. Merry for (i = num_words-1; i >= 0; i--) {
1103*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
1104*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1105*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1106*ef270ab1SKenneth D. Merry mask |= BIT(i);
1107*ef270ab1SKenneth D. Merry }
1108*ef270ab1SKenneth D. Merry
1109*ef270ab1SKenneth D. Merry ocs_queue_history_add_timestamp(q_hist);
1110*ef270ab1SKenneth D. Merry
1111*ef270ab1SKenneth D. Merry /* write footer */
1112*ef270ab1SKenneth D. Merry if (num_words) {
1113*ef270ab1SKenneth D. Merry ftr.s.mask = mask;
1114*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
1115*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1116*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1117*ef270ab1SKenneth D. Merry }
1118*ef270ab1SKenneth D. Merry
1119*ef270ab1SKenneth D. Merry ocs_unlock(&q_hist->q_hist_lock);
1120*ef270ab1SKenneth D. Merry }
1121*ef270ab1SKenneth D. Merry
1122*ef270ab1SKenneth D. Merry /**
1123*ef270ab1SKenneth D. Merry * @ingroup debug
1124*ef270ab1SKenneth D. Merry * @brief Log work queue completion (CQE) entry into history
1125*ef270ab1SKenneth D. Merry * array
1126*ef270ab1SKenneth D. Merry *
1127*ef270ab1SKenneth D. Merry * @param q_hist Pointer to the queue history object.
1128*ef270ab1SKenneth D. Merry * @param ctype Type of completion entry
1129*ef270ab1SKenneth D. Merry * @param entryw Completion queue entry in words
1130*ef270ab1SKenneth D. Merry * @param status Completion queue status
1131*ef270ab1SKenneth D. Merry * @param qid Queue ID
1132*ef270ab1SKenneth D. Merry * @param qindex Queue index
1133*ef270ab1SKenneth D. Merry *
1134*ef270ab1SKenneth D. Merry * @return none
1135*ef270ab1SKenneth D. Merry */
1136*ef270ab1SKenneth D. Merry void
ocs_queue_history_cqe(ocs_hw_q_hist_t * q_hist,uint8_t ctype,uint32_t * entryw,uint8_t status,uint32_t qid,uint32_t qindex)1137*ef270ab1SKenneth D. Merry ocs_queue_history_cqe(ocs_hw_q_hist_t *q_hist, uint8_t ctype, uint32_t *entryw, uint8_t status, uint32_t qid, uint32_t qindex)
1138*ef270ab1SKenneth D. Merry {
1139*ef270ab1SKenneth D. Merry int i;
1140*ef270ab1SKenneth D. Merry unsigned j;
1141*ef270ab1SKenneth D. Merry uint32_t cqe_word_mask = 0;
1142*ef270ab1SKenneth D. Merry ocs_q_hist_ftr_t ftr;
1143*ef270ab1SKenneth D. Merry
1144*ef270ab1SKenneth D. Merry if (q_hist->q_hist == NULL) {
1145*ef270ab1SKenneth D. Merry /* Can't save anything */
1146*ef270ab1SKenneth D. Merry return;
1147*ef270ab1SKenneth D. Merry }
1148*ef270ab1SKenneth D. Merry
1149*ef270ab1SKenneth D. Merry ftr.word = 0;
1150*ef270ab1SKenneth D. Merry for (j = 0; j < ARRAY_SIZE(ocs_q_hist_cqe_masks); j++) {
1151*ef270ab1SKenneth D. Merry if (ocs_q_hist_cqe_masks[j].ctype == ctype) {
1152*ef270ab1SKenneth D. Merry ftr.s.type = ocs_q_hist_cqe_masks[j].type;
1153*ef270ab1SKenneth D. Merry if (status != 0) {
1154*ef270ab1SKenneth D. Merry cqe_word_mask = ocs_q_hist_cqe_masks[j].mask_err;
1155*ef270ab1SKenneth D. Merry } else {
1156*ef270ab1SKenneth D. Merry cqe_word_mask = ocs_q_hist_cqe_masks[j].mask;
1157*ef270ab1SKenneth D. Merry }
1158*ef270ab1SKenneth D. Merry }
1159*ef270ab1SKenneth D. Merry }
1160*ef270ab1SKenneth D. Merry ocs_lock(&q_hist->q_hist_lock);
1161*ef270ab1SKenneth D. Merry /* Capture words in reverse order since we'll be interpretting them LIFO */
1162*ef270ab1SKenneth D. Merry for (i = ((sizeof(cqe_word_mask)*8) - 1); i >= 0; i--){
1163*ef270ab1SKenneth D. Merry if ((cqe_word_mask >> i) & 1) {
1164*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
1165*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1166*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1167*ef270ab1SKenneth D. Merry }
1168*ef270ab1SKenneth D. Merry }
1169*ef270ab1SKenneth D. Merry ocs_queue_history_add_q_info(q_hist, qid, qindex);
1170*ef270ab1SKenneth D. Merry ocs_queue_history_add_timestamp(q_hist);
1171*ef270ab1SKenneth D. Merry
1172*ef270ab1SKenneth D. Merry /* write footer */
1173*ef270ab1SKenneth D. Merry if (cqe_word_mask) {
1174*ef270ab1SKenneth D. Merry ftr.s.mask = cqe_word_mask;
1175*ef270ab1SKenneth D. Merry q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
1176*ef270ab1SKenneth D. Merry q_hist->q_hist_index++;
1177*ef270ab1SKenneth D. Merry q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
1178*ef270ab1SKenneth D. Merry }
1179*ef270ab1SKenneth D. Merry
1180*ef270ab1SKenneth D. Merry ocs_unlock(&q_hist->q_hist_lock);
1181*ef270ab1SKenneth D. Merry }
1182*ef270ab1SKenneth D. Merry
1183*ef270ab1SKenneth D. Merry /**
1184*ef270ab1SKenneth D. Merry * @brief Get previous index
1185*ef270ab1SKenneth D. Merry *
1186*ef270ab1SKenneth D. Merry * @param index Index from which previous index is derived.
1187*ef270ab1SKenneth D. Merry */
1188*ef270ab1SKenneth D. Merry uint32_t
ocs_queue_history_prev_index(uint32_t index)1189*ef270ab1SKenneth D. Merry ocs_queue_history_prev_index(uint32_t index)
1190*ef270ab1SKenneth D. Merry {
1191*ef270ab1SKenneth D. Merry if (index == 0) {
1192*ef270ab1SKenneth D. Merry return OCS_Q_HIST_SIZE - 1;
1193*ef270ab1SKenneth D. Merry } else {
1194*ef270ab1SKenneth D. Merry return index - 1;
1195*ef270ab1SKenneth D. Merry }
1196*ef270ab1SKenneth D. Merry }
1197*ef270ab1SKenneth D. Merry
1198*ef270ab1SKenneth D. Merry #endif /* OCS_DEBUG_QUEUE_HISTORY */
1199*ef270ab1SKenneth D. Merry
1200*ef270ab1SKenneth D. Merry /**
1201*ef270ab1SKenneth D. Merry * @brief Display service parameters
1202*ef270ab1SKenneth D. Merry *
1203*ef270ab1SKenneth D. Merry * <description>
1204*ef270ab1SKenneth D. Merry *
1205*ef270ab1SKenneth D. Merry * @param prelabel leading display label
1206*ef270ab1SKenneth D. Merry * @param reqlabel display label
1207*ef270ab1SKenneth D. Merry * @param dest destination 0=ocs_log, 1=textbuf
1208*ef270ab1SKenneth D. Merry * @param textbuf text buffer destination (if dest==1)
1209*ef270ab1SKenneth D. Merry * @param sparams pointer to service parameter
1210*ef270ab1SKenneth D. Merry *
1211*ef270ab1SKenneth D. Merry * @return none
1212*ef270ab1SKenneth D. Merry */
1213*ef270ab1SKenneth D. Merry
1214*ef270ab1SKenneth D. Merry void
ocs_display_sparams(const char * prelabel,const char * reqlabel,int dest,void * textbuf,void * sparams)1215*ef270ab1SKenneth D. Merry ocs_display_sparams(const char *prelabel, const char *reqlabel, int dest, void *textbuf, void *sparams)
1216*ef270ab1SKenneth D. Merry {
1217*ef270ab1SKenneth D. Merry char label[64];
1218*ef270ab1SKenneth D. Merry
1219*ef270ab1SKenneth D. Merry if (sparams == NULL) {
1220*ef270ab1SKenneth D. Merry return;
1221*ef270ab1SKenneth D. Merry }
1222*ef270ab1SKenneth D. Merry
1223*ef270ab1SKenneth D. Merry switch(dest) {
1224*ef270ab1SKenneth D. Merry case 0:
1225*ef270ab1SKenneth D. Merry if (prelabel != NULL) {
1226*ef270ab1SKenneth D. Merry ocs_snprintf(label, sizeof(label), "[%s] sparam: %s", prelabel, reqlabel);
1227*ef270ab1SKenneth D. Merry } else {
1228*ef270ab1SKenneth D. Merry ocs_snprintf(label, sizeof(label), "sparam: %s", reqlabel);
1229*ef270ab1SKenneth D. Merry }
1230*ef270ab1SKenneth D. Merry
1231*ef270ab1SKenneth D. Merry ocs_dump32(OCS_DEBUG_ENABLE_SPARAM_DUMP, NULL, label, sparams, sizeof(fc_plogi_payload_t));
1232*ef270ab1SKenneth D. Merry break;
1233*ef270ab1SKenneth D. Merry case 1:
1234*ef270ab1SKenneth D. Merry ocs_ddump_buffer((ocs_textbuf_t*) textbuf, reqlabel, 0, sparams, sizeof(fc_plogi_payload_t));
1235*ef270ab1SKenneth D. Merry break;
1236*ef270ab1SKenneth D. Merry }
1237*ef270ab1SKenneth D. Merry }
1238*ef270ab1SKenneth D. Merry
1239*ef270ab1SKenneth D. Merry /**
1240*ef270ab1SKenneth D. Merry * @brief Calculate the T10 PI CRC guard value for a block.
1241*ef270ab1SKenneth D. Merry *
1242*ef270ab1SKenneth D. Merry * @param buffer Pointer to the data buffer.
1243*ef270ab1SKenneth D. Merry * @param size Number of bytes.
1244*ef270ab1SKenneth D. Merry * @param crc Previously-calculated CRC, or 0 for a new block.
1245*ef270ab1SKenneth D. Merry *
1246*ef270ab1SKenneth D. Merry * @return Returns the calculated CRC, which may be passed back in for partial blocks.
1247*ef270ab1SKenneth D. Merry *
1248*ef270ab1SKenneth D. Merry */
1249*ef270ab1SKenneth D. Merry
1250*ef270ab1SKenneth D. Merry uint16_t
ocs_scsi_dif_calc_crc(const uint8_t * buffer,uint32_t size,uint16_t crc)1251*ef270ab1SKenneth D. Merry ocs_scsi_dif_calc_crc(const uint8_t *buffer, uint32_t size, uint16_t crc)
1252*ef270ab1SKenneth D. Merry {
1253*ef270ab1SKenneth D. Merry return t10crc16(buffer, size, crc);
1254*ef270ab1SKenneth D. Merry }
1255*ef270ab1SKenneth D. Merry
1256*ef270ab1SKenneth D. Merry /**
1257*ef270ab1SKenneth D. Merry * @brief Calculate the IP-checksum guard value for a block.
1258*ef270ab1SKenneth D. Merry *
1259*ef270ab1SKenneth D. Merry * @param addrlen array of address length pairs
1260*ef270ab1SKenneth D. Merry * @param addrlen_count number of entries in the addrlen[] array
1261*ef270ab1SKenneth D. Merry *
1262*ef270ab1SKenneth D. Merry * Algorithm:
1263*ef270ab1SKenneth D. Merry * Sum all all the 16-byte words in the block
1264*ef270ab1SKenneth D. Merry * Add in the "carry", which is everything in excess of 16-bits
1265*ef270ab1SKenneth D. Merry * Flip all the bits
1266*ef270ab1SKenneth D. Merry *
1267*ef270ab1SKenneth D. Merry * @return Returns the calculated checksum
1268*ef270ab1SKenneth D. Merry */
1269*ef270ab1SKenneth D. Merry
1270*ef270ab1SKenneth D. Merry uint16_t
ocs_scsi_dif_calc_checksum(ocs_scsi_vaddr_len_t addrlen[],uint32_t addrlen_count)1271*ef270ab1SKenneth D. Merry ocs_scsi_dif_calc_checksum(ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count)
1272*ef270ab1SKenneth D. Merry {
1273*ef270ab1SKenneth D. Merry uint32_t i, j;
1274*ef270ab1SKenneth D. Merry uint16_t checksum;
1275*ef270ab1SKenneth D. Merry uint32_t intermediate; /* Use an intermediate to hold more than 16 bits during calculations */
1276*ef270ab1SKenneth D. Merry uint32_t count;
1277*ef270ab1SKenneth D. Merry uint16_t *buffer;
1278*ef270ab1SKenneth D. Merry
1279*ef270ab1SKenneth D. Merry intermediate = 0;
1280*ef270ab1SKenneth D. Merry for (j = 0; j < addrlen_count; j++) {
1281*ef270ab1SKenneth D. Merry buffer = addrlen[j].vaddr;
1282*ef270ab1SKenneth D. Merry count = addrlen[j].length / 2;
1283*ef270ab1SKenneth D. Merry for (i=0; i < count; i++) {
1284*ef270ab1SKenneth D. Merry intermediate += buffer[i];
1285*ef270ab1SKenneth D. Merry }
1286*ef270ab1SKenneth D. Merry }
1287*ef270ab1SKenneth D. Merry
1288*ef270ab1SKenneth D. Merry /* Carry is everything over 16 bits */
1289*ef270ab1SKenneth D. Merry intermediate += ((intermediate & 0xffff0000) >> 16);
1290*ef270ab1SKenneth D. Merry
1291*ef270ab1SKenneth D. Merry /* Flip all the bits */
1292*ef270ab1SKenneth D. Merry intermediate = ~intermediate;
1293*ef270ab1SKenneth D. Merry
1294*ef270ab1SKenneth D. Merry checksum = intermediate;
1295*ef270ab1SKenneth D. Merry
1296*ef270ab1SKenneth D. Merry return checksum;
1297*ef270ab1SKenneth D. Merry }
1298*ef270ab1SKenneth D. Merry
1299*ef270ab1SKenneth D. Merry /**
1300*ef270ab1SKenneth D. Merry * @brief Return blocksize given SCSI API DIF block size
1301*ef270ab1SKenneth D. Merry *
1302*ef270ab1SKenneth D. Merry * Given the DIF block size enumerated value, return the block size value. (e.g.
1303*ef270ab1SKenneth D. Merry * OCS_SCSI_DIF_BLK_SIZE_512 returns 512)
1304*ef270ab1SKenneth D. Merry *
1305*ef270ab1SKenneth D. Merry * @param dif_info Pointer to SCSI API DIF info block
1306*ef270ab1SKenneth D. Merry *
1307*ef270ab1SKenneth D. Merry * @return returns block size, or 0 if SCSI API DIF blocksize is invalid
1308*ef270ab1SKenneth D. Merry */
1309*ef270ab1SKenneth D. Merry
1310*ef270ab1SKenneth D. Merry uint32_t
ocs_scsi_dif_blocksize(ocs_scsi_dif_info_t * dif_info)1311*ef270ab1SKenneth D. Merry ocs_scsi_dif_blocksize(ocs_scsi_dif_info_t *dif_info)
1312*ef270ab1SKenneth D. Merry {
1313*ef270ab1SKenneth D. Merry uint32_t blocksize = 0;
1314*ef270ab1SKenneth D. Merry
1315*ef270ab1SKenneth D. Merry switch(dif_info->blk_size) {
1316*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_512: blocksize = 512; break;
1317*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_1024: blocksize = 1024; break;
1318*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_2048: blocksize = 2048; break;
1319*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_4096: blocksize = 4096; break;
1320*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_520: blocksize = 520; break;
1321*ef270ab1SKenneth D. Merry case OCS_SCSI_DIF_BK_SIZE_4104: blocksize = 4104; break;
1322*ef270ab1SKenneth D. Merry default:
1323*ef270ab1SKenneth D. Merry break;
1324*ef270ab1SKenneth D. Merry }
1325*ef270ab1SKenneth D. Merry
1326*ef270ab1SKenneth D. Merry return blocksize;
1327*ef270ab1SKenneth D. Merry }
1328*ef270ab1SKenneth D. Merry
1329*ef270ab1SKenneth D. Merry /**
1330*ef270ab1SKenneth D. Merry * @brief Set SCSI API DIF blocksize
1331*ef270ab1SKenneth D. Merry *
1332*ef270ab1SKenneth D. Merry * Given a blocksize value (512, 1024, etc.), set the SCSI API DIF blocksize
1333*ef270ab1SKenneth D. Merry * in the DIF info block
1334*ef270ab1SKenneth D. Merry *
1335*ef270ab1SKenneth D. Merry * @param dif_info Pointer to the SCSI API DIF info block
1336*ef270ab1SKenneth D. Merry * @param blocksize Block size
1337*ef270ab1SKenneth D. Merry *
1338*ef270ab1SKenneth D. Merry * @return returns 0 for success, a negative error code value for failure.
1339*ef270ab1SKenneth D. Merry */
1340*ef270ab1SKenneth D. Merry
1341*ef270ab1SKenneth D. Merry int32_t
ocs_scsi_dif_set_blocksize(ocs_scsi_dif_info_t * dif_info,uint32_t blocksize)1342*ef270ab1SKenneth D. Merry ocs_scsi_dif_set_blocksize(ocs_scsi_dif_info_t *dif_info, uint32_t blocksize)
1343*ef270ab1SKenneth D. Merry {
1344*ef270ab1SKenneth D. Merry int32_t rc = 0;
1345*ef270ab1SKenneth D. Merry
1346*ef270ab1SKenneth D. Merry switch(blocksize) {
1347*ef270ab1SKenneth D. Merry case 512: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_512; break;
1348*ef270ab1SKenneth D. Merry case 1024: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_1024; break;
1349*ef270ab1SKenneth D. Merry case 2048: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_2048; break;
1350*ef270ab1SKenneth D. Merry case 4096: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_4096; break;
1351*ef270ab1SKenneth D. Merry case 520: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_520; break;
1352*ef270ab1SKenneth D. Merry case 4104: dif_info->blk_size = OCS_SCSI_DIF_BK_SIZE_4104; break;
1353*ef270ab1SKenneth D. Merry default:
1354*ef270ab1SKenneth D. Merry rc = -1;
1355*ef270ab1SKenneth D. Merry break;
1356*ef270ab1SKenneth D. Merry }
1357*ef270ab1SKenneth D. Merry return rc;
1358*ef270ab1SKenneth D. Merry
1359*ef270ab1SKenneth D. Merry }
1360*ef270ab1SKenneth D. Merry
1361*ef270ab1SKenneth D. Merry /**
1362*ef270ab1SKenneth D. Merry * @brief Return memory block size given SCSI DIF API
1363*ef270ab1SKenneth D. Merry *
1364*ef270ab1SKenneth D. Merry * The blocksize in memory for the DIF transfer is returned, given the SCSI DIF info
1365*ef270ab1SKenneth D. Merry * block and the direction of transfer.
1366*ef270ab1SKenneth D. Merry *
1367*ef270ab1SKenneth D. Merry * @param dif_info Pointer to DIF info block
1368*ef270ab1SKenneth D. Merry * @param wiretomem Transfer direction, 1 is wire to memory, 0 is memory to wire
1369*ef270ab1SKenneth D. Merry *
1370*ef270ab1SKenneth D. Merry * @return Memory blocksize, or negative error value
1371*ef270ab1SKenneth D. Merry *
1372*ef270ab1SKenneth D. Merry * WARNING: the order of initialization of the adj[] arrays MUST match the declarations
1373*ef270ab1SKenneth D. Merry * of OCS_SCSI_DIF_OPER_*
1374*ef270ab1SKenneth D. Merry */
1375*ef270ab1SKenneth D. Merry
1376*ef270ab1SKenneth D. Merry int32_t
ocs_scsi_dif_mem_blocksize(ocs_scsi_dif_info_t * dif_info,int wiretomem)1377*ef270ab1SKenneth D. Merry ocs_scsi_dif_mem_blocksize(ocs_scsi_dif_info_t *dif_info, int wiretomem)
1378*ef270ab1SKenneth D. Merry {
1379*ef270ab1SKenneth D. Merry uint32_t blocksize;
1380*ef270ab1SKenneth D. Merry uint8_t wiretomem_adj[] = {
1381*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_DISABLED, */
1382*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC, */
1383*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF, */
1384*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1385*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1386*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC, */
1387*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1388*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1389*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1390*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW, */
1391*ef270ab1SKenneth D. Merry uint8_t memtowire_adj[] = {
1392*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_DISABLED, */
1393*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC, */
1394*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF, */
1395*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1396*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1397*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC, */
1398*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1399*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1400*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1401*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW, */
1402*ef270ab1SKenneth D. Merry
1403*ef270ab1SKenneth D. Merry blocksize = ocs_scsi_dif_blocksize(dif_info);
1404*ef270ab1SKenneth D. Merry if (blocksize == 0) {
1405*ef270ab1SKenneth D. Merry return -1;
1406*ef270ab1SKenneth D. Merry }
1407*ef270ab1SKenneth D. Merry
1408*ef270ab1SKenneth D. Merry if (wiretomem) {
1409*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(wiretomem_adj), 0);
1410*ef270ab1SKenneth D. Merry blocksize += wiretomem_adj[dif_info->dif_oper];
1411*ef270ab1SKenneth D. Merry } else { /* mem to wire */
1412*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(memtowire_adj), 0);
1413*ef270ab1SKenneth D. Merry blocksize += memtowire_adj[dif_info->dif_oper];
1414*ef270ab1SKenneth D. Merry }
1415*ef270ab1SKenneth D. Merry return blocksize;
1416*ef270ab1SKenneth D. Merry }
1417*ef270ab1SKenneth D. Merry
1418*ef270ab1SKenneth D. Merry /**
1419*ef270ab1SKenneth D. Merry * @brief Return wire block size given SCSI DIF API
1420*ef270ab1SKenneth D. Merry *
1421*ef270ab1SKenneth D. Merry * The blocksize on the wire for the DIF transfer is returned, given the SCSI DIF info
1422*ef270ab1SKenneth D. Merry * block and the direction of transfer.
1423*ef270ab1SKenneth D. Merry *
1424*ef270ab1SKenneth D. Merry * @param dif_info Pointer to DIF info block
1425*ef270ab1SKenneth D. Merry * @param wiretomem Transfer direction, 1 is wire to memory, 0 is memory to wire
1426*ef270ab1SKenneth D. Merry *
1427*ef270ab1SKenneth D. Merry * @return Wire blocksize or negative error value
1428*ef270ab1SKenneth D. Merry *
1429*ef270ab1SKenneth D. Merry * WARNING: the order of initialization of the adj[] arrays MUST match the declarations
1430*ef270ab1SKenneth D. Merry * of OCS_SCSI_DIF_OPER_*
1431*ef270ab1SKenneth D. Merry */
1432*ef270ab1SKenneth D. Merry
1433*ef270ab1SKenneth D. Merry int32_t
ocs_scsi_dif_wire_blocksize(ocs_scsi_dif_info_t * dif_info,int wiretomem)1434*ef270ab1SKenneth D. Merry ocs_scsi_dif_wire_blocksize(ocs_scsi_dif_info_t *dif_info, int wiretomem)
1435*ef270ab1SKenneth D. Merry {
1436*ef270ab1SKenneth D. Merry uint32_t blocksize;
1437*ef270ab1SKenneth D. Merry uint8_t wiretomem_adj[] = {
1438*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_DISABLED, */
1439*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC, */
1440*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF, */
1441*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1442*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1443*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC, */
1444*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1445*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1446*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1447*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW, */
1448*ef270ab1SKenneth D. Merry uint8_t memtowire_adj[] = {
1449*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_DISABLED, */
1450*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CRC, */
1451*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_NODIF, */
1452*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1453*ef270ab1SKenneth D. Merry 0, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1454*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CRC, */
1455*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1456*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1457*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_SCSI_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1458*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_SCSI_DIF_OPER_IN_RAW_OUT_RAW, */
1459*ef270ab1SKenneth D. Merry
1460*ef270ab1SKenneth D. Merry blocksize = ocs_scsi_dif_blocksize(dif_info);
1461*ef270ab1SKenneth D. Merry if (blocksize == 0) {
1462*ef270ab1SKenneth D. Merry return -1;
1463*ef270ab1SKenneth D. Merry }
1464*ef270ab1SKenneth D. Merry
1465*ef270ab1SKenneth D. Merry if (wiretomem) {
1466*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(wiretomem_adj), 0);
1467*ef270ab1SKenneth D. Merry blocksize += wiretomem_adj[dif_info->dif_oper];
1468*ef270ab1SKenneth D. Merry } else { /* mem to wire */
1469*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(memtowire_adj), 0);
1470*ef270ab1SKenneth D. Merry blocksize += memtowire_adj[dif_info->dif_oper];
1471*ef270ab1SKenneth D. Merry }
1472*ef270ab1SKenneth D. Merry
1473*ef270ab1SKenneth D. Merry return blocksize;
1474*ef270ab1SKenneth D. Merry }
1475*ef270ab1SKenneth D. Merry /**
1476*ef270ab1SKenneth D. Merry * @brief Return blocksize given HW API DIF block size
1477*ef270ab1SKenneth D. Merry *
1478*ef270ab1SKenneth D. Merry * Given the DIF block size enumerated value, return the block size value. (e.g.
1479*ef270ab1SKenneth D. Merry * OCS_SCSI_DIF_BLK_SIZE_512 returns 512)
1480*ef270ab1SKenneth D. Merry *
1481*ef270ab1SKenneth D. Merry * @param dif_info Pointer to HW API DIF info block
1482*ef270ab1SKenneth D. Merry *
1483*ef270ab1SKenneth D. Merry * @return returns block size, or 0 if HW API DIF blocksize is invalid
1484*ef270ab1SKenneth D. Merry */
1485*ef270ab1SKenneth D. Merry
1486*ef270ab1SKenneth D. Merry uint32_t
ocs_hw_dif_blocksize(ocs_hw_dif_info_t * dif_info)1487*ef270ab1SKenneth D. Merry ocs_hw_dif_blocksize(ocs_hw_dif_info_t *dif_info)
1488*ef270ab1SKenneth D. Merry {
1489*ef270ab1SKenneth D. Merry uint32_t blocksize = 0;
1490*ef270ab1SKenneth D. Merry
1491*ef270ab1SKenneth D. Merry switch(dif_info->blk_size) {
1492*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_512: blocksize = 512; break;
1493*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_1024: blocksize = 1024; break;
1494*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_2048: blocksize = 2048; break;
1495*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_4096: blocksize = 4096; break;
1496*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_520: blocksize = 520; break;
1497*ef270ab1SKenneth D. Merry case OCS_HW_DIF_BK_SIZE_4104: blocksize = 4104; break;
1498*ef270ab1SKenneth D. Merry default:
1499*ef270ab1SKenneth D. Merry break;
1500*ef270ab1SKenneth D. Merry }
1501*ef270ab1SKenneth D. Merry
1502*ef270ab1SKenneth D. Merry return blocksize;
1503*ef270ab1SKenneth D. Merry }
1504*ef270ab1SKenneth D. Merry
1505*ef270ab1SKenneth D. Merry /**
1506*ef270ab1SKenneth D. Merry * @brief Return memory block size given HW DIF API
1507*ef270ab1SKenneth D. Merry *
1508*ef270ab1SKenneth D. Merry * The blocksize in memory for the DIF transfer is returned, given the HW DIF info
1509*ef270ab1SKenneth D. Merry * block and the direction of transfer.
1510*ef270ab1SKenneth D. Merry *
1511*ef270ab1SKenneth D. Merry * @param dif_info Pointer to DIF info block
1512*ef270ab1SKenneth D. Merry * @param wiretomem Transfer direction, 1 is wire to memory, 0 is memory to wire
1513*ef270ab1SKenneth D. Merry *
1514*ef270ab1SKenneth D. Merry * @return Memory blocksize, or negative error value
1515*ef270ab1SKenneth D. Merry *
1516*ef270ab1SKenneth D. Merry * WARNING: the order of initialization of the adj[] arrays MUST match the declarations
1517*ef270ab1SKenneth D. Merry * of OCS_HW_DIF_OPER_*
1518*ef270ab1SKenneth D. Merry */
1519*ef270ab1SKenneth D. Merry
1520*ef270ab1SKenneth D. Merry int32_t
ocs_hw_dif_mem_blocksize(ocs_hw_dif_info_t * dif_info,int wiretomem)1521*ef270ab1SKenneth D. Merry ocs_hw_dif_mem_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem)
1522*ef270ab1SKenneth D. Merry {
1523*ef270ab1SKenneth D. Merry uint32_t blocksize;
1524*ef270ab1SKenneth D. Merry uint8_t wiretomem_adj[] = {
1525*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_DISABLED, */
1526*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CRC, */
1527*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_CRC_OUT_NODIF, */
1528*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1529*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1530*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CRC, */
1531*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1532*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1533*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1534*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_HW_DIF_OPER_IN_RAW_OUT_RAW, */
1535*ef270ab1SKenneth D. Merry uint8_t memtowire_adj[] = {
1536*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_DISABLED, */
1537*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CRC, */
1538*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_NODIF, */
1539*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1540*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1541*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CRC, */
1542*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1543*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1544*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1545*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_HW_DIF_OPER_IN_RAW_OUT_RAW, */
1546*ef270ab1SKenneth D. Merry
1547*ef270ab1SKenneth D. Merry blocksize = ocs_hw_dif_blocksize(dif_info);
1548*ef270ab1SKenneth D. Merry if (blocksize == 0) {
1549*ef270ab1SKenneth D. Merry return -1;
1550*ef270ab1SKenneth D. Merry }
1551*ef270ab1SKenneth D. Merry
1552*ef270ab1SKenneth D. Merry if (wiretomem) {
1553*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(wiretomem_adj), 0);
1554*ef270ab1SKenneth D. Merry blocksize += wiretomem_adj[dif_info->dif_oper];
1555*ef270ab1SKenneth D. Merry } else { /* mem to wire */
1556*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(memtowire_adj), 0);
1557*ef270ab1SKenneth D. Merry blocksize += memtowire_adj[dif_info->dif_oper];
1558*ef270ab1SKenneth D. Merry }
1559*ef270ab1SKenneth D. Merry return blocksize;
1560*ef270ab1SKenneth D. Merry }
1561*ef270ab1SKenneth D. Merry
1562*ef270ab1SKenneth D. Merry /**
1563*ef270ab1SKenneth D. Merry * @brief Return wire block size given HW DIF API
1564*ef270ab1SKenneth D. Merry *
1565*ef270ab1SKenneth D. Merry * The blocksize on the wire for the DIF transfer is returned, given the HW DIF info
1566*ef270ab1SKenneth D. Merry * block and the direction of transfer.
1567*ef270ab1SKenneth D. Merry *
1568*ef270ab1SKenneth D. Merry * @param dif_info Pointer to DIF info block
1569*ef270ab1SKenneth D. Merry * @param wiretomem Transfer direction, 1 is wire to memory, 0 is memory to wire
1570*ef270ab1SKenneth D. Merry *
1571*ef270ab1SKenneth D. Merry * @return Wire blocksize or negative error value
1572*ef270ab1SKenneth D. Merry *
1573*ef270ab1SKenneth D. Merry * WARNING: the order of initialization of the adj[] arrays MUST match the declarations
1574*ef270ab1SKenneth D. Merry * of OCS_HW_DIF_OPER_*
1575*ef270ab1SKenneth D. Merry */
1576*ef270ab1SKenneth D. Merry
1577*ef270ab1SKenneth D. Merry int32_t
ocs_hw_dif_wire_blocksize(ocs_hw_dif_info_t * dif_info,int wiretomem)1578*ef270ab1SKenneth D. Merry ocs_hw_dif_wire_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem)
1579*ef270ab1SKenneth D. Merry {
1580*ef270ab1SKenneth D. Merry uint32_t blocksize;
1581*ef270ab1SKenneth D. Merry uint8_t wiretomem_adj[] = {
1582*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_DISABLED, */
1583*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CRC, */
1584*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_NODIF, */
1585*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1586*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1587*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CRC, */
1588*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1589*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1590*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1591*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_HW_DIF_OPER_IN_RAW_OUT_RAW, */
1592*ef270ab1SKenneth D. Merry uint8_t memtowire_adj[] = {
1593*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_DISABLED, */
1594*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CRC, */
1595*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_CRC_OUT_NODIF, */
1596*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_NODIF_OUT_CHKSUM, */
1597*ef270ab1SKenneth D. Merry 0, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_NODIF, */
1598*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CRC, */
1599*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CHKSUM, */
1600*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CRC_OUT_CHKSUM, */
1601*ef270ab1SKenneth D. Merry DIF_SIZE, /* OCS_HW_DIF_OPER_IN_CHKSUM_OUT_CRC, */
1602*ef270ab1SKenneth D. Merry DIF_SIZE}; /* OCS_HW_DIF_OPER_IN_RAW_OUT_RAW, */
1603*ef270ab1SKenneth D. Merry
1604*ef270ab1SKenneth D. Merry blocksize = ocs_hw_dif_blocksize(dif_info);
1605*ef270ab1SKenneth D. Merry if (blocksize == 0) {
1606*ef270ab1SKenneth D. Merry return -1;
1607*ef270ab1SKenneth D. Merry }
1608*ef270ab1SKenneth D. Merry
1609*ef270ab1SKenneth D. Merry if (wiretomem) {
1610*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(wiretomem_adj), 0);
1611*ef270ab1SKenneth D. Merry blocksize += wiretomem_adj[dif_info->dif_oper];
1612*ef270ab1SKenneth D. Merry } else { /* mem to wire */
1613*ef270ab1SKenneth D. Merry ocs_assert(dif_info->dif_oper < ARRAY_SIZE(memtowire_adj), 0);
1614*ef270ab1SKenneth D. Merry blocksize += memtowire_adj[dif_info->dif_oper];
1615*ef270ab1SKenneth D. Merry }
1616*ef270ab1SKenneth D. Merry
1617*ef270ab1SKenneth D. Merry return blocksize;
1618*ef270ab1SKenneth D. Merry }
1619*ef270ab1SKenneth D. Merry
1620*ef270ab1SKenneth D. Merry static int32_t ocs_segment_remaining(ocs_textbuf_segment_t *segment);
1621*ef270ab1SKenneth D. Merry static ocs_textbuf_segment_t *ocs_textbuf_segment_alloc(ocs_textbuf_t *textbuf);
1622*ef270ab1SKenneth D. Merry static void ocs_textbuf_segment_free(ocs_t *ocs, ocs_textbuf_segment_t *segment);
1623*ef270ab1SKenneth D. Merry static ocs_textbuf_segment_t *ocs_textbuf_get_segment(ocs_textbuf_t *textbuf, uint32_t idx);
1624*ef270ab1SKenneth D. Merry
1625*ef270ab1SKenneth D. Merry uint8_t *
ocs_textbuf_get_buffer(ocs_textbuf_t * textbuf)1626*ef270ab1SKenneth D. Merry ocs_textbuf_get_buffer(ocs_textbuf_t *textbuf)
1627*ef270ab1SKenneth D. Merry {
1628*ef270ab1SKenneth D. Merry return ocs_textbuf_ext_get_buffer(textbuf, 0);
1629*ef270ab1SKenneth D. Merry }
1630*ef270ab1SKenneth D. Merry
1631*ef270ab1SKenneth D. Merry int32_t
ocs_textbuf_get_length(ocs_textbuf_t * textbuf)1632*ef270ab1SKenneth D. Merry ocs_textbuf_get_length(ocs_textbuf_t *textbuf)
1633*ef270ab1SKenneth D. Merry {
1634*ef270ab1SKenneth D. Merry return ocs_textbuf_ext_get_length(textbuf, 0);
1635*ef270ab1SKenneth D. Merry }
1636*ef270ab1SKenneth D. Merry
1637*ef270ab1SKenneth D. Merry int32_t
ocs_textbuf_get_written(ocs_textbuf_t * textbuf)1638*ef270ab1SKenneth D. Merry ocs_textbuf_get_written(ocs_textbuf_t *textbuf)
1639*ef270ab1SKenneth D. Merry {
1640*ef270ab1SKenneth D. Merry uint32_t idx;
1641*ef270ab1SKenneth D. Merry int32_t n;
1642*ef270ab1SKenneth D. Merry int32_t total = 0;
1643*ef270ab1SKenneth D. Merry
1644*ef270ab1SKenneth D. Merry for (idx = 0; (n = ocs_textbuf_ext_get_written(textbuf, idx)) >= 0; idx++) {
1645*ef270ab1SKenneth D. Merry total += n;
1646*ef270ab1SKenneth D. Merry }
1647*ef270ab1SKenneth D. Merry return total;
1648*ef270ab1SKenneth D. Merry }
1649*ef270ab1SKenneth D. Merry
ocs_textbuf_ext_get_buffer(ocs_textbuf_t * textbuf,uint32_t idx)1650*ef270ab1SKenneth D. Merry uint8_t *ocs_textbuf_ext_get_buffer(ocs_textbuf_t *textbuf, uint32_t idx)
1651*ef270ab1SKenneth D. Merry {
1652*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment = ocs_textbuf_get_segment(textbuf, idx);
1653*ef270ab1SKenneth D. Merry if (segment == NULL) {
1654*ef270ab1SKenneth D. Merry return NULL;
1655*ef270ab1SKenneth D. Merry }
1656*ef270ab1SKenneth D. Merry return segment->buffer;
1657*ef270ab1SKenneth D. Merry }
1658*ef270ab1SKenneth D. Merry
ocs_textbuf_ext_get_length(ocs_textbuf_t * textbuf,uint32_t idx)1659*ef270ab1SKenneth D. Merry int32_t ocs_textbuf_ext_get_length(ocs_textbuf_t *textbuf, uint32_t idx)
1660*ef270ab1SKenneth D. Merry {
1661*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment = ocs_textbuf_get_segment(textbuf, idx);
1662*ef270ab1SKenneth D. Merry if (segment == NULL) {
1663*ef270ab1SKenneth D. Merry return -1;
1664*ef270ab1SKenneth D. Merry }
1665*ef270ab1SKenneth D. Merry return segment->buffer_length;
1666*ef270ab1SKenneth D. Merry }
1667*ef270ab1SKenneth D. Merry
ocs_textbuf_ext_get_written(ocs_textbuf_t * textbuf,uint32_t idx)1668*ef270ab1SKenneth D. Merry int32_t ocs_textbuf_ext_get_written(ocs_textbuf_t *textbuf, uint32_t idx)
1669*ef270ab1SKenneth D. Merry {
1670*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment = ocs_textbuf_get_segment(textbuf, idx);
1671*ef270ab1SKenneth D. Merry if (segment == NULL) {
1672*ef270ab1SKenneth D. Merry return -1;
1673*ef270ab1SKenneth D. Merry }
1674*ef270ab1SKenneth D. Merry return segment->buffer_written;
1675*ef270ab1SKenneth D. Merry }
1676*ef270ab1SKenneth D. Merry
1677*ef270ab1SKenneth D. Merry uint32_t
ocs_textbuf_initialized(ocs_textbuf_t * textbuf)1678*ef270ab1SKenneth D. Merry ocs_textbuf_initialized(ocs_textbuf_t *textbuf)
1679*ef270ab1SKenneth D. Merry {
1680*ef270ab1SKenneth D. Merry return (textbuf->ocs != NULL);
1681*ef270ab1SKenneth D. Merry }
1682*ef270ab1SKenneth D. Merry
1683*ef270ab1SKenneth D. Merry int32_t
ocs_textbuf_alloc(ocs_t * ocs,ocs_textbuf_t * textbuf,uint32_t length)1684*ef270ab1SKenneth D. Merry ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length)
1685*ef270ab1SKenneth D. Merry {
1686*ef270ab1SKenneth D. Merry ocs_memset(textbuf, 0, sizeof(*textbuf));
1687*ef270ab1SKenneth D. Merry
1688*ef270ab1SKenneth D. Merry textbuf->ocs = ocs;
1689*ef270ab1SKenneth D. Merry ocs_list_init(&textbuf->segment_list, ocs_textbuf_segment_t, link);
1690*ef270ab1SKenneth D. Merry
1691*ef270ab1SKenneth D. Merry if (length > OCS_TEXTBUF_MAX_ALLOC_LEN) {
1692*ef270ab1SKenneth D. Merry textbuf->allocation_length = OCS_TEXTBUF_MAX_ALLOC_LEN;
1693*ef270ab1SKenneth D. Merry } else {
1694*ef270ab1SKenneth D. Merry textbuf->allocation_length = length;
1695*ef270ab1SKenneth D. Merry }
1696*ef270ab1SKenneth D. Merry
1697*ef270ab1SKenneth D. Merry /* mark as extendable */
1698*ef270ab1SKenneth D. Merry textbuf->extendable = TRUE;
1699*ef270ab1SKenneth D. Merry
1700*ef270ab1SKenneth D. Merry /* save maximum allocation length */
1701*ef270ab1SKenneth D. Merry textbuf->max_allocation_length = length;
1702*ef270ab1SKenneth D. Merry
1703*ef270ab1SKenneth D. Merry /* Add first segment */
1704*ef270ab1SKenneth D. Merry return (ocs_textbuf_segment_alloc(textbuf) == NULL) ? -1 : 0;
1705*ef270ab1SKenneth D. Merry }
1706*ef270ab1SKenneth D. Merry
1707*ef270ab1SKenneth D. Merry static ocs_textbuf_segment_t *
ocs_textbuf_segment_alloc(ocs_textbuf_t * textbuf)1708*ef270ab1SKenneth D. Merry ocs_textbuf_segment_alloc(ocs_textbuf_t *textbuf)
1709*ef270ab1SKenneth D. Merry {
1710*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment = NULL;
1711*ef270ab1SKenneth D. Merry
1712*ef270ab1SKenneth D. Merry if (textbuf->extendable) {
1713*ef270ab1SKenneth D. Merry segment = ocs_malloc(textbuf->ocs, sizeof(*segment), OCS_M_ZERO | OCS_M_NOWAIT);
1714*ef270ab1SKenneth D. Merry if (segment != NULL) {
1715*ef270ab1SKenneth D. Merry segment->buffer = ocs_malloc(textbuf->ocs, textbuf->allocation_length, OCS_M_ZERO | OCS_M_NOWAIT);
1716*ef270ab1SKenneth D. Merry if (segment->buffer != NULL) {
1717*ef270ab1SKenneth D. Merry segment->buffer_length = textbuf->allocation_length;
1718*ef270ab1SKenneth D. Merry segment->buffer_written = 0;
1719*ef270ab1SKenneth D. Merry ocs_list_add_tail(&textbuf->segment_list, segment);
1720*ef270ab1SKenneth D. Merry textbuf->total_allocation_length += textbuf->allocation_length;
1721*ef270ab1SKenneth D. Merry
1722*ef270ab1SKenneth D. Merry /* If we've allocated our limit, then mark as not extendable */
1723*ef270ab1SKenneth D. Merry if (textbuf->total_allocation_length >= textbuf->max_allocation_length) {
1724*ef270ab1SKenneth D. Merry textbuf->extendable = 0;
1725*ef270ab1SKenneth D. Merry }
1726*ef270ab1SKenneth D. Merry
1727*ef270ab1SKenneth D. Merry } else {
1728*ef270ab1SKenneth D. Merry ocs_textbuf_segment_free(textbuf->ocs, segment);
1729*ef270ab1SKenneth D. Merry segment = NULL;
1730*ef270ab1SKenneth D. Merry }
1731*ef270ab1SKenneth D. Merry }
1732*ef270ab1SKenneth D. Merry }
1733*ef270ab1SKenneth D. Merry return segment;
1734*ef270ab1SKenneth D. Merry }
1735*ef270ab1SKenneth D. Merry
1736*ef270ab1SKenneth D. Merry static void
ocs_textbuf_segment_free(ocs_t * ocs,ocs_textbuf_segment_t * segment)1737*ef270ab1SKenneth D. Merry ocs_textbuf_segment_free(ocs_t *ocs, ocs_textbuf_segment_t *segment)
1738*ef270ab1SKenneth D. Merry {
1739*ef270ab1SKenneth D. Merry if (segment) {
1740*ef270ab1SKenneth D. Merry if (segment->buffer && !segment->user_allocated) {
1741*ef270ab1SKenneth D. Merry ocs_free(ocs, segment->buffer, segment->buffer_length);
1742*ef270ab1SKenneth D. Merry }
1743*ef270ab1SKenneth D. Merry ocs_free(ocs, segment, sizeof(*segment));
1744*ef270ab1SKenneth D. Merry }
1745*ef270ab1SKenneth D. Merry }
1746*ef270ab1SKenneth D. Merry
1747*ef270ab1SKenneth D. Merry static ocs_textbuf_segment_t *
ocs_textbuf_get_segment(ocs_textbuf_t * textbuf,uint32_t idx)1748*ef270ab1SKenneth D. Merry ocs_textbuf_get_segment(ocs_textbuf_t *textbuf, uint32_t idx)
1749*ef270ab1SKenneth D. Merry {
1750*ef270ab1SKenneth D. Merry uint32_t i;
1751*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1752*ef270ab1SKenneth D. Merry
1753*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1754*ef270ab1SKenneth D. Merry i = 0;
1755*ef270ab1SKenneth D. Merry ocs_list_foreach(&textbuf->segment_list, segment) {
1756*ef270ab1SKenneth D. Merry if (i == idx) {
1757*ef270ab1SKenneth D. Merry return segment;
1758*ef270ab1SKenneth D. Merry }
1759*ef270ab1SKenneth D. Merry i++;
1760*ef270ab1SKenneth D. Merry }
1761*ef270ab1SKenneth D. Merry }
1762*ef270ab1SKenneth D. Merry return NULL;
1763*ef270ab1SKenneth D. Merry }
1764*ef270ab1SKenneth D. Merry
1765*ef270ab1SKenneth D. Merry int32_t
ocs_textbuf_init(ocs_t * ocs,ocs_textbuf_t * textbuf,void * buffer,uint32_t length)1766*ef270ab1SKenneth D. Merry ocs_textbuf_init(ocs_t *ocs, ocs_textbuf_t *textbuf, void *buffer, uint32_t length)
1767*ef270ab1SKenneth D. Merry {
1768*ef270ab1SKenneth D. Merry int32_t rc = -1;
1769*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1770*ef270ab1SKenneth D. Merry
1771*ef270ab1SKenneth D. Merry ocs_memset(textbuf, 0, sizeof(*textbuf));
1772*ef270ab1SKenneth D. Merry
1773*ef270ab1SKenneth D. Merry textbuf->ocs = ocs;
1774*ef270ab1SKenneth D. Merry ocs_list_init(&textbuf->segment_list, ocs_textbuf_segment_t, link);
1775*ef270ab1SKenneth D. Merry segment = ocs_malloc(ocs, sizeof(*segment), OCS_M_ZERO | OCS_M_NOWAIT);
1776*ef270ab1SKenneth D. Merry if (segment) {
1777*ef270ab1SKenneth D. Merry segment->buffer = buffer;
1778*ef270ab1SKenneth D. Merry segment->buffer_length = length;
1779*ef270ab1SKenneth D. Merry segment->buffer_written = 0;
1780*ef270ab1SKenneth D. Merry segment->user_allocated = 1;
1781*ef270ab1SKenneth D. Merry ocs_list_add_tail(&textbuf->segment_list, segment);
1782*ef270ab1SKenneth D. Merry rc = 0;
1783*ef270ab1SKenneth D. Merry }
1784*ef270ab1SKenneth D. Merry
1785*ef270ab1SKenneth D. Merry return rc;
1786*ef270ab1SKenneth D. Merry }
1787*ef270ab1SKenneth D. Merry
1788*ef270ab1SKenneth D. Merry void
ocs_textbuf_free(ocs_t * ocs,ocs_textbuf_t * textbuf)1789*ef270ab1SKenneth D. Merry ocs_textbuf_free(ocs_t *ocs, ocs_textbuf_t *textbuf)
1790*ef270ab1SKenneth D. Merry {
1791*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1792*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *n;
1793*ef270ab1SKenneth D. Merry
1794*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1795*ef270ab1SKenneth D. Merry ocs_list_foreach_safe(&textbuf->segment_list, segment, n) {
1796*ef270ab1SKenneth D. Merry ocs_list_remove(&textbuf->segment_list, segment);
1797*ef270ab1SKenneth D. Merry ocs_textbuf_segment_free(ocs, segment);
1798*ef270ab1SKenneth D. Merry }
1799*ef270ab1SKenneth D. Merry
1800*ef270ab1SKenneth D. Merry ocs_memset(textbuf, 0, sizeof(*textbuf));
1801*ef270ab1SKenneth D. Merry }
1802*ef270ab1SKenneth D. Merry }
1803*ef270ab1SKenneth D. Merry
1804*ef270ab1SKenneth D. Merry void
ocs_textbuf_printf(ocs_textbuf_t * textbuf,const char * fmt,...)1805*ef270ab1SKenneth D. Merry ocs_textbuf_printf(ocs_textbuf_t *textbuf, const char *fmt, ...)
1806*ef270ab1SKenneth D. Merry {
1807*ef270ab1SKenneth D. Merry va_list ap;
1808*ef270ab1SKenneth D. Merry
1809*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1810*ef270ab1SKenneth D. Merry va_start(ap, fmt);
1811*ef270ab1SKenneth D. Merry ocs_textbuf_vprintf(textbuf, fmt, ap);
1812*ef270ab1SKenneth D. Merry va_end(ap);
1813*ef270ab1SKenneth D. Merry }
1814*ef270ab1SKenneth D. Merry }
1815*ef270ab1SKenneth D. Merry
1816*ef270ab1SKenneth D. Merry void
ocs_textbuf_vprintf(ocs_textbuf_t * textbuf,const char * fmt,va_list ap)1817*ef270ab1SKenneth D. Merry ocs_textbuf_vprintf(ocs_textbuf_t *textbuf, const char *fmt, va_list ap)
1818*ef270ab1SKenneth D. Merry {
1819*ef270ab1SKenneth D. Merry int avail;
1820*ef270ab1SKenneth D. Merry int written;
1821*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1822*ef270ab1SKenneth D. Merry va_list save_ap;
1823*ef270ab1SKenneth D. Merry
1824*ef270ab1SKenneth D. Merry if (!ocs_textbuf_initialized(textbuf)) {
1825*ef270ab1SKenneth D. Merry return;
1826*ef270ab1SKenneth D. Merry }
1827*ef270ab1SKenneth D. Merry
1828*ef270ab1SKenneth D. Merry va_copy(save_ap, ap);
1829*ef270ab1SKenneth D. Merry
1830*ef270ab1SKenneth D. Merry /* fetch last segment */
1831*ef270ab1SKenneth D. Merry segment = ocs_list_get_tail(&textbuf->segment_list);
1832*ef270ab1SKenneth D. Merry
1833*ef270ab1SKenneth D. Merry avail = ocs_segment_remaining(segment);
1834*ef270ab1SKenneth D. Merry if (avail == 0) {
1835*ef270ab1SKenneth D. Merry if ((segment = ocs_textbuf_segment_alloc(textbuf)) == NULL) {
1836*ef270ab1SKenneth D. Merry goto out;
1837*ef270ab1SKenneth D. Merry }
1838*ef270ab1SKenneth D. Merry avail = ocs_segment_remaining(segment);
1839*ef270ab1SKenneth D. Merry }
1840*ef270ab1SKenneth D. Merry
1841*ef270ab1SKenneth D. Merry written = ocs_vsnprintf(segment->buffer + segment->buffer_written, avail, fmt, ap);
1842*ef270ab1SKenneth D. Merry
1843*ef270ab1SKenneth D. Merry /* See if data was truncated */
1844*ef270ab1SKenneth D. Merry if (written >= avail) {
1845*ef270ab1SKenneth D. Merry written = avail;
1846*ef270ab1SKenneth D. Merry
1847*ef270ab1SKenneth D. Merry if (textbuf->extendable) {
1848*ef270ab1SKenneth D. Merry /* revert the partially written data */
1849*ef270ab1SKenneth D. Merry *(segment->buffer + segment->buffer_written) = 0;
1850*ef270ab1SKenneth D. Merry
1851*ef270ab1SKenneth D. Merry /* Allocate a new segment */
1852*ef270ab1SKenneth D. Merry if ((segment = ocs_textbuf_segment_alloc(textbuf)) == NULL) {
1853*ef270ab1SKenneth D. Merry ocs_log_err(textbuf->ocs, "alloc segment failed\n");
1854*ef270ab1SKenneth D. Merry goto out;
1855*ef270ab1SKenneth D. Merry }
1856*ef270ab1SKenneth D. Merry avail = ocs_segment_remaining(segment);
1857*ef270ab1SKenneth D. Merry
1858*ef270ab1SKenneth D. Merry /* Retry the write */
1859*ef270ab1SKenneth D. Merry written = ocs_vsnprintf(segment->buffer + segment->buffer_written, avail, fmt, save_ap);
1860*ef270ab1SKenneth D. Merry }
1861*ef270ab1SKenneth D. Merry }
1862*ef270ab1SKenneth D. Merry segment->buffer_written += written;
1863*ef270ab1SKenneth D. Merry
1864*ef270ab1SKenneth D. Merry out:
1865*ef270ab1SKenneth D. Merry va_end(save_ap);
1866*ef270ab1SKenneth D. Merry }
1867*ef270ab1SKenneth D. Merry
1868*ef270ab1SKenneth D. Merry void
ocs_textbuf_putc(ocs_textbuf_t * textbuf,uint8_t c)1869*ef270ab1SKenneth D. Merry ocs_textbuf_putc(ocs_textbuf_t *textbuf, uint8_t c)
1870*ef270ab1SKenneth D. Merry {
1871*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1872*ef270ab1SKenneth D. Merry
1873*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1874*ef270ab1SKenneth D. Merry segment = ocs_list_get_tail(&textbuf->segment_list);
1875*ef270ab1SKenneth D. Merry
1876*ef270ab1SKenneth D. Merry if (ocs_segment_remaining(segment)) {
1877*ef270ab1SKenneth D. Merry *(segment->buffer + segment->buffer_written++) = c;
1878*ef270ab1SKenneth D. Merry }
1879*ef270ab1SKenneth D. Merry if (ocs_segment_remaining(segment) == 0) {
1880*ef270ab1SKenneth D. Merry ocs_textbuf_segment_alloc(textbuf);
1881*ef270ab1SKenneth D. Merry }
1882*ef270ab1SKenneth D. Merry }
1883*ef270ab1SKenneth D. Merry }
1884*ef270ab1SKenneth D. Merry
1885*ef270ab1SKenneth D. Merry void
ocs_textbuf_puts(ocs_textbuf_t * textbuf,char * s)1886*ef270ab1SKenneth D. Merry ocs_textbuf_puts(ocs_textbuf_t *textbuf, char *s)
1887*ef270ab1SKenneth D. Merry {
1888*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1889*ef270ab1SKenneth D. Merry while(*s) {
1890*ef270ab1SKenneth D. Merry ocs_textbuf_putc(textbuf, *s++);
1891*ef270ab1SKenneth D. Merry }
1892*ef270ab1SKenneth D. Merry }
1893*ef270ab1SKenneth D. Merry }
1894*ef270ab1SKenneth D. Merry
1895*ef270ab1SKenneth D. Merry void
ocs_textbuf_buffer(ocs_textbuf_t * textbuf,uint8_t * buffer,uint32_t buffer_length)1896*ef270ab1SKenneth D. Merry ocs_textbuf_buffer(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length)
1897*ef270ab1SKenneth D. Merry {
1898*ef270ab1SKenneth D. Merry char *s;
1899*ef270ab1SKenneth D. Merry
1900*ef270ab1SKenneth D. Merry if (!ocs_textbuf_initialized(textbuf)) {
1901*ef270ab1SKenneth D. Merry return;
1902*ef270ab1SKenneth D. Merry }
1903*ef270ab1SKenneth D. Merry
1904*ef270ab1SKenneth D. Merry s = (char*) buffer;
1905*ef270ab1SKenneth D. Merry while(*s) {
1906*ef270ab1SKenneth D. Merry /*
1907*ef270ab1SKenneth D. Merry * XML escapes
1908*ef270ab1SKenneth D. Merry *
1909*ef270ab1SKenneth D. Merry * " "
1910*ef270ab1SKenneth D. Merry * ' '
1911*ef270ab1SKenneth D. Merry * < <
1912*ef270ab1SKenneth D. Merry * > >
1913*ef270ab1SKenneth D. Merry * & &
1914*ef270ab1SKenneth D. Merry */
1915*ef270ab1SKenneth D. Merry
1916*ef270ab1SKenneth D. Merry switch(*s) {
1917*ef270ab1SKenneth D. Merry case '"': ocs_textbuf_puts(textbuf, """); break;
1918*ef270ab1SKenneth D. Merry case '\'': ocs_textbuf_puts(textbuf, "'"); break;
1919*ef270ab1SKenneth D. Merry case '<': ocs_textbuf_puts(textbuf, "<"); break;
1920*ef270ab1SKenneth D. Merry case '>': ocs_textbuf_puts(textbuf, ">"); break;
1921*ef270ab1SKenneth D. Merry case '&': ocs_textbuf_puts(textbuf, "&"); break;
1922*ef270ab1SKenneth D. Merry default: ocs_textbuf_putc(textbuf, *s); break;
1923*ef270ab1SKenneth D. Merry }
1924*ef270ab1SKenneth D. Merry s++;
1925*ef270ab1SKenneth D. Merry }
1926*ef270ab1SKenneth D. Merry
1927*ef270ab1SKenneth D. Merry }
1928*ef270ab1SKenneth D. Merry
1929*ef270ab1SKenneth D. Merry void
ocs_textbuf_copy(ocs_textbuf_t * textbuf,uint8_t * buffer,uint32_t buffer_length)1930*ef270ab1SKenneth D. Merry ocs_textbuf_copy(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length)
1931*ef270ab1SKenneth D. Merry {
1932*ef270ab1SKenneth D. Merry char *s;
1933*ef270ab1SKenneth D. Merry
1934*ef270ab1SKenneth D. Merry if (!ocs_textbuf_initialized(textbuf)) {
1935*ef270ab1SKenneth D. Merry return;
1936*ef270ab1SKenneth D. Merry }
1937*ef270ab1SKenneth D. Merry
1938*ef270ab1SKenneth D. Merry s = (char*) buffer;
1939*ef270ab1SKenneth D. Merry while(*s) {
1940*ef270ab1SKenneth D. Merry ocs_textbuf_putc(textbuf, *s++);
1941*ef270ab1SKenneth D. Merry }
1942*ef270ab1SKenneth D. Merry
1943*ef270ab1SKenneth D. Merry }
1944*ef270ab1SKenneth D. Merry
1945*ef270ab1SKenneth D. Merry int32_t
ocs_textbuf_remaining(ocs_textbuf_t * textbuf)1946*ef270ab1SKenneth D. Merry ocs_textbuf_remaining(ocs_textbuf_t *textbuf)
1947*ef270ab1SKenneth D. Merry {
1948*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1949*ef270ab1SKenneth D. Merry return ocs_segment_remaining(ocs_list_get_head(&textbuf->segment_list));
1950*ef270ab1SKenneth D. Merry } else {
1951*ef270ab1SKenneth D. Merry return 0;
1952*ef270ab1SKenneth D. Merry }
1953*ef270ab1SKenneth D. Merry }
1954*ef270ab1SKenneth D. Merry
1955*ef270ab1SKenneth D. Merry static int32_t
ocs_segment_remaining(ocs_textbuf_segment_t * segment)1956*ef270ab1SKenneth D. Merry ocs_segment_remaining(ocs_textbuf_segment_t *segment)
1957*ef270ab1SKenneth D. Merry {
1958*ef270ab1SKenneth D. Merry return segment->buffer_length - segment->buffer_written;
1959*ef270ab1SKenneth D. Merry }
1960*ef270ab1SKenneth D. Merry
1961*ef270ab1SKenneth D. Merry void
ocs_textbuf_reset(ocs_textbuf_t * textbuf)1962*ef270ab1SKenneth D. Merry ocs_textbuf_reset(ocs_textbuf_t *textbuf)
1963*ef270ab1SKenneth D. Merry {
1964*ef270ab1SKenneth D. Merry uint32_t i = 0;
1965*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *segment;
1966*ef270ab1SKenneth D. Merry ocs_textbuf_segment_t *n;
1967*ef270ab1SKenneth D. Merry
1968*ef270ab1SKenneth D. Merry if (ocs_textbuf_initialized(textbuf)) {
1969*ef270ab1SKenneth D. Merry /* zero written on the first segment, free the rest */
1970*ef270ab1SKenneth D. Merry ocs_list_foreach_safe(&textbuf->segment_list, segment, n) {
1971*ef270ab1SKenneth D. Merry if (i++ == 0) {
1972*ef270ab1SKenneth D. Merry segment->buffer_written = 0;
1973*ef270ab1SKenneth D. Merry } else {
1974*ef270ab1SKenneth D. Merry ocs_list_remove(&textbuf->segment_list, segment);
1975*ef270ab1SKenneth D. Merry ocs_textbuf_segment_free(textbuf->ocs, segment);
1976*ef270ab1SKenneth D. Merry }
1977*ef270ab1SKenneth D. Merry }
1978*ef270ab1SKenneth D. Merry }
1979*ef270ab1SKenneth D. Merry }
1980*ef270ab1SKenneth D. Merry
1981*ef270ab1SKenneth D. Merry /**
1982*ef270ab1SKenneth D. Merry * @brief Sparse Vector API.
1983*ef270ab1SKenneth D. Merry *
1984*ef270ab1SKenneth D. Merry * This is a trimmed down sparse vector implementation tuned to the problem of
1985*ef270ab1SKenneth D. Merry * 24-bit FC_IDs. In this case, the 24-bit index value is broken down in three
1986*ef270ab1SKenneth D. Merry * 8-bit values. These values are used to index up to three 256 element arrays.
1987*ef270ab1SKenneth D. Merry * Arrays are allocated, only when needed. @n @n
1988*ef270ab1SKenneth D. Merry * The lookup can complete in constant time (3 indexed array references). @n @n
1989*ef270ab1SKenneth D. Merry * A typical use case would be that the fabric/directory FC_IDs would cause two rows to be
1990*ef270ab1SKenneth D. Merry * allocated, and the fabric assigned remote nodes would cause two rows to be allocated, with
1991*ef270ab1SKenneth D. Merry * the root row always allocated. This gives five rows of 256 x sizeof(void*),
1992*ef270ab1SKenneth D. Merry * resulting in 10k.
1993*ef270ab1SKenneth D. Merry */
1994*ef270ab1SKenneth D. Merry
1995*ef270ab1SKenneth D. Merry /**
1996*ef270ab1SKenneth D. Merry * @ingroup spv
1997*ef270ab1SKenneth D. Merry * @brief Allocate a new sparse vector row.
1998*ef270ab1SKenneth D. Merry *
1999*ef270ab1SKenneth D. Merry * @param os OS handle
2000*ef270ab1SKenneth D. Merry * @param rowcount Count of rows.
2001*ef270ab1SKenneth D. Merry *
2002*ef270ab1SKenneth D. Merry * @par Description
2003*ef270ab1SKenneth D. Merry * A new sparse vector row is allocated.
2004*ef270ab1SKenneth D. Merry *
2005*ef270ab1SKenneth D. Merry * @param rowcount Number of elements in a row.
2006*ef270ab1SKenneth D. Merry *
2007*ef270ab1SKenneth D. Merry * @return Returns the pointer to a row.
2008*ef270ab1SKenneth D. Merry */
2009*ef270ab1SKenneth D. Merry static void
spv_new_row(ocs_os_handle_t os,uint32_t rowcount)2010*ef270ab1SKenneth D. Merry **spv_new_row(ocs_os_handle_t os, uint32_t rowcount)
2011*ef270ab1SKenneth D. Merry {
2012*ef270ab1SKenneth D. Merry return ocs_malloc(os, sizeof(void*) * rowcount, OCS_M_ZERO | OCS_M_NOWAIT);
2013*ef270ab1SKenneth D. Merry }
2014*ef270ab1SKenneth D. Merry
2015*ef270ab1SKenneth D. Merry /**
2016*ef270ab1SKenneth D. Merry * @ingroup spv
2017*ef270ab1SKenneth D. Merry * @brief Delete row recursively.
2018*ef270ab1SKenneth D. Merry *
2019*ef270ab1SKenneth D. Merry * @par Description
2020*ef270ab1SKenneth D. Merry * This function recursively deletes the rows in this sparse vector
2021*ef270ab1SKenneth D. Merry *
2022*ef270ab1SKenneth D. Merry * @param os OS handle
2023*ef270ab1SKenneth D. Merry * @param a Pointer to the row.
2024*ef270ab1SKenneth D. Merry * @param n Number of elements in the row.
2025*ef270ab1SKenneth D. Merry * @param depth Depth of deleting.
2026*ef270ab1SKenneth D. Merry *
2027*ef270ab1SKenneth D. Merry * @return None.
2028*ef270ab1SKenneth D. Merry */
2029*ef270ab1SKenneth D. Merry static void
_spv_del(ocs_os_handle_t os,void ** a,uint32_t n,uint32_t depth)2030*ef270ab1SKenneth D. Merry _spv_del(ocs_os_handle_t os, void **a, uint32_t n, uint32_t depth)
2031*ef270ab1SKenneth D. Merry {
2032*ef270ab1SKenneth D. Merry if (a) {
2033*ef270ab1SKenneth D. Merry if (depth) {
2034*ef270ab1SKenneth D. Merry uint32_t i;
2035*ef270ab1SKenneth D. Merry
2036*ef270ab1SKenneth D. Merry for (i = 0; i < n; i ++) {
2037*ef270ab1SKenneth D. Merry _spv_del(os, a[i], n, depth-1);
2038*ef270ab1SKenneth D. Merry }
2039*ef270ab1SKenneth D. Merry
2040*ef270ab1SKenneth D. Merry ocs_free(os, a, SPV_ROWLEN*sizeof(*a));
2041*ef270ab1SKenneth D. Merry }
2042*ef270ab1SKenneth D. Merry }
2043*ef270ab1SKenneth D. Merry }
2044*ef270ab1SKenneth D. Merry
2045*ef270ab1SKenneth D. Merry /**
2046*ef270ab1SKenneth D. Merry * @ingroup spv
2047*ef270ab1SKenneth D. Merry * @brief Delete a sparse vector.
2048*ef270ab1SKenneth D. Merry *
2049*ef270ab1SKenneth D. Merry * @par Description
2050*ef270ab1SKenneth D. Merry * The sparse vector is freed.
2051*ef270ab1SKenneth D. Merry *
2052*ef270ab1SKenneth D. Merry * @param spv Pointer to the sparse vector object.
2053*ef270ab1SKenneth D. Merry */
2054*ef270ab1SKenneth D. Merry void
spv_del(sparse_vector_t spv)2055*ef270ab1SKenneth D. Merry spv_del(sparse_vector_t spv)
2056*ef270ab1SKenneth D. Merry {
2057*ef270ab1SKenneth D. Merry if (spv) {
2058*ef270ab1SKenneth D. Merry _spv_del(spv->os, spv->array, SPV_ROWLEN, SPV_DIM);
2059*ef270ab1SKenneth D. Merry ocs_free(spv->os, spv, sizeof(*spv));
2060*ef270ab1SKenneth D. Merry }
2061*ef270ab1SKenneth D. Merry }
2062*ef270ab1SKenneth D. Merry
2063*ef270ab1SKenneth D. Merry /**
2064*ef270ab1SKenneth D. Merry * @ingroup spv
2065*ef270ab1SKenneth D. Merry * @brief Instantiate a new sparse vector object.
2066*ef270ab1SKenneth D. Merry *
2067*ef270ab1SKenneth D. Merry * @par Description
2068*ef270ab1SKenneth D. Merry * A new sparse vector is allocated.
2069*ef270ab1SKenneth D. Merry *
2070*ef270ab1SKenneth D. Merry * @param os OS handle
2071*ef270ab1SKenneth D. Merry *
2072*ef270ab1SKenneth D. Merry * @return Returns the pointer to the sparse vector, or NULL.
2073*ef270ab1SKenneth D. Merry */
2074*ef270ab1SKenneth D. Merry sparse_vector_t
spv_new(ocs_os_handle_t os)2075*ef270ab1SKenneth D. Merry spv_new(ocs_os_handle_t os)
2076*ef270ab1SKenneth D. Merry {
2077*ef270ab1SKenneth D. Merry sparse_vector_t spv;
2078*ef270ab1SKenneth D. Merry uint32_t i;
2079*ef270ab1SKenneth D. Merry
2080*ef270ab1SKenneth D. Merry spv = ocs_malloc(os, sizeof(*spv), OCS_M_ZERO | OCS_M_NOWAIT);
2081*ef270ab1SKenneth D. Merry if (!spv) {
2082*ef270ab1SKenneth D. Merry return NULL;
2083*ef270ab1SKenneth D. Merry }
2084*ef270ab1SKenneth D. Merry
2085*ef270ab1SKenneth D. Merry spv->os = os;
2086*ef270ab1SKenneth D. Merry spv->max_idx = 1;
2087*ef270ab1SKenneth D. Merry for (i = 0; i < SPV_DIM; i ++) {
2088*ef270ab1SKenneth D. Merry spv->max_idx *= SPV_ROWLEN;
2089*ef270ab1SKenneth D. Merry }
2090*ef270ab1SKenneth D. Merry
2091*ef270ab1SKenneth D. Merry return spv;
2092*ef270ab1SKenneth D. Merry }
2093*ef270ab1SKenneth D. Merry
2094*ef270ab1SKenneth D. Merry /**
2095*ef270ab1SKenneth D. Merry * @ingroup spv
2096*ef270ab1SKenneth D. Merry * @brief Return the address of a cell.
2097*ef270ab1SKenneth D. Merry *
2098*ef270ab1SKenneth D. Merry * @par Description
2099*ef270ab1SKenneth D. Merry * Returns the address of a cell, allocates sparse rows as needed if the
2100*ef270ab1SKenneth D. Merry * alloc_new_rows parameter is set.
2101*ef270ab1SKenneth D. Merry *
2102*ef270ab1SKenneth D. Merry * @param sv Pointer to the sparse vector.
2103*ef270ab1SKenneth D. Merry * @param idx Index of which to return the address.
2104*ef270ab1SKenneth D. Merry * @param alloc_new_rows If TRUE, then new rows may be allocated to set values,
2105*ef270ab1SKenneth D. Merry * Set to FALSE for retrieving values.
2106*ef270ab1SKenneth D. Merry *
2107*ef270ab1SKenneth D. Merry * @return Returns the pointer to the cell, or NULL.
2108*ef270ab1SKenneth D. Merry */
2109*ef270ab1SKenneth D. Merry static void
spv_new_cell(sparse_vector_t sv,uint32_t idx,uint8_t alloc_new_rows)2110*ef270ab1SKenneth D. Merry *spv_new_cell(sparse_vector_t sv, uint32_t idx, uint8_t alloc_new_rows)
2111*ef270ab1SKenneth D. Merry {
2112*ef270ab1SKenneth D. Merry uint32_t a = (idx >> 16) & 0xff;
2113*ef270ab1SKenneth D. Merry uint32_t b = (idx >> 8) & 0xff;
2114*ef270ab1SKenneth D. Merry uint32_t c = (idx >> 0) & 0xff;
2115*ef270ab1SKenneth D. Merry void **p;
2116*ef270ab1SKenneth D. Merry
2117*ef270ab1SKenneth D. Merry if (idx >= sv->max_idx) {
2118*ef270ab1SKenneth D. Merry return NULL;
2119*ef270ab1SKenneth D. Merry }
2120*ef270ab1SKenneth D. Merry
2121*ef270ab1SKenneth D. Merry if (sv->array == NULL) {
2122*ef270ab1SKenneth D. Merry sv->array = (alloc_new_rows ? spv_new_row(sv->os, SPV_ROWLEN) : NULL);
2123*ef270ab1SKenneth D. Merry if (sv->array == NULL) {
2124*ef270ab1SKenneth D. Merry return NULL;
2125*ef270ab1SKenneth D. Merry }
2126*ef270ab1SKenneth D. Merry }
2127*ef270ab1SKenneth D. Merry p = sv->array;
2128*ef270ab1SKenneth D. Merry if (p[a] == NULL) {
2129*ef270ab1SKenneth D. Merry p[a] = (alloc_new_rows ? spv_new_row(sv->os, SPV_ROWLEN) : NULL);
2130*ef270ab1SKenneth D. Merry if (p[a] == NULL) {
2131*ef270ab1SKenneth D. Merry return NULL;
2132*ef270ab1SKenneth D. Merry }
2133*ef270ab1SKenneth D. Merry }
2134*ef270ab1SKenneth D. Merry p = p[a];
2135*ef270ab1SKenneth D. Merry if (p[b] == NULL) {
2136*ef270ab1SKenneth D. Merry p[b] = (alloc_new_rows ? spv_new_row(sv->os, SPV_ROWLEN) : NULL);
2137*ef270ab1SKenneth D. Merry if (p[b] == NULL) {
2138*ef270ab1SKenneth D. Merry return NULL;
2139*ef270ab1SKenneth D. Merry }
2140*ef270ab1SKenneth D. Merry }
2141*ef270ab1SKenneth D. Merry p = p[b];
2142*ef270ab1SKenneth D. Merry
2143*ef270ab1SKenneth D. Merry return &p[c];
2144*ef270ab1SKenneth D. Merry }
2145*ef270ab1SKenneth D. Merry
2146*ef270ab1SKenneth D. Merry /**
2147*ef270ab1SKenneth D. Merry * @ingroup spv
2148*ef270ab1SKenneth D. Merry * @brief Set the sparse vector cell value.
2149*ef270ab1SKenneth D. Merry *
2150*ef270ab1SKenneth D. Merry * @par Description
2151*ef270ab1SKenneth D. Merry * Sets the sparse vector at @c idx to @c value.
2152*ef270ab1SKenneth D. Merry *
2153*ef270ab1SKenneth D. Merry * @param sv Pointer to the sparse vector.
2154*ef270ab1SKenneth D. Merry * @param idx Index of which to store.
2155*ef270ab1SKenneth D. Merry * @param value Value to store.
2156*ef270ab1SKenneth D. Merry *
2157*ef270ab1SKenneth D. Merry * @return None.
2158*ef270ab1SKenneth D. Merry */
2159*ef270ab1SKenneth D. Merry void
spv_set(sparse_vector_t sv,uint32_t idx,void * value)2160*ef270ab1SKenneth D. Merry spv_set(sparse_vector_t sv, uint32_t idx, void *value)
2161*ef270ab1SKenneth D. Merry {
2162*ef270ab1SKenneth D. Merry void **ref = spv_new_cell(sv, idx, TRUE);
2163*ef270ab1SKenneth D. Merry if (ref) {
2164*ef270ab1SKenneth D. Merry *ref = value;
2165*ef270ab1SKenneth D. Merry }
2166*ef270ab1SKenneth D. Merry }
2167*ef270ab1SKenneth D. Merry
2168*ef270ab1SKenneth D. Merry /**
2169*ef270ab1SKenneth D. Merry * @ingroup spv
2170*ef270ab1SKenneth D. Merry * @brief Return the sparse vector cell value.
2171*ef270ab1SKenneth D. Merry *
2172*ef270ab1SKenneth D. Merry * @par Description
2173*ef270ab1SKenneth D. Merry * Returns the value at @c idx.
2174*ef270ab1SKenneth D. Merry *
2175*ef270ab1SKenneth D. Merry * @param sv Pointer to the sparse vector.
2176*ef270ab1SKenneth D. Merry * @param idx Index of which to return the value.
2177*ef270ab1SKenneth D. Merry *
2178*ef270ab1SKenneth D. Merry * @return Returns the cell value, or NULL.
2179*ef270ab1SKenneth D. Merry */
2180*ef270ab1SKenneth D. Merry void
spv_get(sparse_vector_t sv,uint32_t idx)2181*ef270ab1SKenneth D. Merry *spv_get(sparse_vector_t sv, uint32_t idx)
2182*ef270ab1SKenneth D. Merry {
2183*ef270ab1SKenneth D. Merry void **ref = spv_new_cell(sv, idx, FALSE);
2184*ef270ab1SKenneth D. Merry if (ref) {
2185*ef270ab1SKenneth D. Merry return *ref;
2186*ef270ab1SKenneth D. Merry }
2187*ef270ab1SKenneth D. Merry return NULL;
2188*ef270ab1SKenneth D. Merry }
2189*ef270ab1SKenneth D. Merry
2190*ef270ab1SKenneth D. Merry /*****************************************************************/
2191*ef270ab1SKenneth D. Merry /* */
2192*ef270ab1SKenneth D. Merry /* CRC LOOKUP TABLE */
2193*ef270ab1SKenneth D. Merry /* ================ */
2194*ef270ab1SKenneth D. Merry /* The following CRC lookup table was generated automagically */
2195*ef270ab1SKenneth D. Merry /* by the Rocksoft^tm Model CRC Algorithm Table Generation */
2196*ef270ab1SKenneth D. Merry /* Program V1.0 using the following model parameters: */
2197*ef270ab1SKenneth D. Merry /* */
2198*ef270ab1SKenneth D. Merry /* Width : 2 bytes. */
2199*ef270ab1SKenneth D. Merry /* Poly : 0x8BB7 */
2200*ef270ab1SKenneth D. Merry /* Reverse : FALSE. */
2201*ef270ab1SKenneth D. Merry /* */
2202*ef270ab1SKenneth D. Merry /* For more information on the Rocksoft^tm Model CRC Algorithm, */
2203*ef270ab1SKenneth D. Merry /* see the document titled "A Painless Guide to CRC Error */
2204*ef270ab1SKenneth D. Merry /* Detection Algorithms" by Ross Williams */
2205*ef270ab1SKenneth D. Merry /* (ross@guest.adelaide.edu.au.). This document is likely to be */
2206*ef270ab1SKenneth D. Merry /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */
2207*ef270ab1SKenneth D. Merry /* */
2208*ef270ab1SKenneth D. Merry /*****************************************************************/
2209*ef270ab1SKenneth D. Merry /*
2210*ef270ab1SKenneth D. Merry * Emulex Inc, changes:
2211*ef270ab1SKenneth D. Merry * - minor syntax changes for successful compilation with contemporary
2212*ef270ab1SKenneth D. Merry * C compilers, and OCS SDK API
2213*ef270ab1SKenneth D. Merry * - crctable[] generated using Rocksoft public domain code
2214*ef270ab1SKenneth D. Merry *
2215*ef270ab1SKenneth D. Merry * Used in the Emulex SDK, the generated file crctable.out is cut and pasted into
2216*ef270ab1SKenneth D. Merry * applicable SDK sources.
2217*ef270ab1SKenneth D. Merry */
2218*ef270ab1SKenneth D. Merry
2219*ef270ab1SKenneth D. Merry static unsigned short crctable[256] =
2220*ef270ab1SKenneth D. Merry {
2221*ef270ab1SKenneth D. Merry 0x0000, 0x8BB7, 0x9CD9, 0x176E, 0xB205, 0x39B2, 0x2EDC, 0xA56B,
2222*ef270ab1SKenneth D. Merry 0xEFBD, 0x640A, 0x7364, 0xF8D3, 0x5DB8, 0xD60F, 0xC161, 0x4AD6,
2223*ef270ab1SKenneth D. Merry 0x54CD, 0xDF7A, 0xC814, 0x43A3, 0xE6C8, 0x6D7F, 0x7A11, 0xF1A6,
2224*ef270ab1SKenneth D. Merry 0xBB70, 0x30C7, 0x27A9, 0xAC1E, 0x0975, 0x82C2, 0x95AC, 0x1E1B,
2225*ef270ab1SKenneth D. Merry 0xA99A, 0x222D, 0x3543, 0xBEF4, 0x1B9F, 0x9028, 0x8746, 0x0CF1,
2226*ef270ab1SKenneth D. Merry 0x4627, 0xCD90, 0xDAFE, 0x5149, 0xF422, 0x7F95, 0x68FB, 0xE34C,
2227*ef270ab1SKenneth D. Merry 0xFD57, 0x76E0, 0x618E, 0xEA39, 0x4F52, 0xC4E5, 0xD38B, 0x583C,
2228*ef270ab1SKenneth D. Merry 0x12EA, 0x995D, 0x8E33, 0x0584, 0xA0EF, 0x2B58, 0x3C36, 0xB781,
2229*ef270ab1SKenneth D. Merry 0xD883, 0x5334, 0x445A, 0xCFED, 0x6A86, 0xE131, 0xF65F, 0x7DE8,
2230*ef270ab1SKenneth D. Merry 0x373E, 0xBC89, 0xABE7, 0x2050, 0x853B, 0x0E8C, 0x19E2, 0x9255,
2231*ef270ab1SKenneth D. Merry 0x8C4E, 0x07F9, 0x1097, 0x9B20, 0x3E4B, 0xB5FC, 0xA292, 0x2925,
2232*ef270ab1SKenneth D. Merry 0x63F3, 0xE844, 0xFF2A, 0x749D, 0xD1F6, 0x5A41, 0x4D2F, 0xC698,
2233*ef270ab1SKenneth D. Merry 0x7119, 0xFAAE, 0xEDC0, 0x6677, 0xC31C, 0x48AB, 0x5FC5, 0xD472,
2234*ef270ab1SKenneth D. Merry 0x9EA4, 0x1513, 0x027D, 0x89CA, 0x2CA1, 0xA716, 0xB078, 0x3BCF,
2235*ef270ab1SKenneth D. Merry 0x25D4, 0xAE63, 0xB90D, 0x32BA, 0x97D1, 0x1C66, 0x0B08, 0x80BF,
2236*ef270ab1SKenneth D. Merry 0xCA69, 0x41DE, 0x56B0, 0xDD07, 0x786C, 0xF3DB, 0xE4B5, 0x6F02,
2237*ef270ab1SKenneth D. Merry 0x3AB1, 0xB106, 0xA668, 0x2DDF, 0x88B4, 0x0303, 0x146D, 0x9FDA,
2238*ef270ab1SKenneth D. Merry 0xD50C, 0x5EBB, 0x49D5, 0xC262, 0x6709, 0xECBE, 0xFBD0, 0x7067,
2239*ef270ab1SKenneth D. Merry 0x6E7C, 0xE5CB, 0xF2A5, 0x7912, 0xDC79, 0x57CE, 0x40A0, 0xCB17,
2240*ef270ab1SKenneth D. Merry 0x81C1, 0x0A76, 0x1D18, 0x96AF, 0x33C4, 0xB873, 0xAF1D, 0x24AA,
2241*ef270ab1SKenneth D. Merry 0x932B, 0x189C, 0x0FF2, 0x8445, 0x212E, 0xAA99, 0xBDF7, 0x3640,
2242*ef270ab1SKenneth D. Merry 0x7C96, 0xF721, 0xE04F, 0x6BF8, 0xCE93, 0x4524, 0x524A, 0xD9FD,
2243*ef270ab1SKenneth D. Merry 0xC7E6, 0x4C51, 0x5B3F, 0xD088, 0x75E3, 0xFE54, 0xE93A, 0x628D,
2244*ef270ab1SKenneth D. Merry 0x285B, 0xA3EC, 0xB482, 0x3F35, 0x9A5E, 0x11E9, 0x0687, 0x8D30,
2245*ef270ab1SKenneth D. Merry 0xE232, 0x6985, 0x7EEB, 0xF55C, 0x5037, 0xDB80, 0xCCEE, 0x4759,
2246*ef270ab1SKenneth D. Merry 0x0D8F, 0x8638, 0x9156, 0x1AE1, 0xBF8A, 0x343D, 0x2353, 0xA8E4,
2247*ef270ab1SKenneth D. Merry 0xB6FF, 0x3D48, 0x2A26, 0xA191, 0x04FA, 0x8F4D, 0x9823, 0x1394,
2248*ef270ab1SKenneth D. Merry 0x5942, 0xD2F5, 0xC59B, 0x4E2C, 0xEB47, 0x60F0, 0x779E, 0xFC29,
2249*ef270ab1SKenneth D. Merry 0x4BA8, 0xC01F, 0xD771, 0x5CC6, 0xF9AD, 0x721A, 0x6574, 0xEEC3,
2250*ef270ab1SKenneth D. Merry 0xA415, 0x2FA2, 0x38CC, 0xB37B, 0x1610, 0x9DA7, 0x8AC9, 0x017E,
2251*ef270ab1SKenneth D. Merry 0x1F65, 0x94D2, 0x83BC, 0x080B, 0xAD60, 0x26D7, 0x31B9, 0xBA0E,
2252*ef270ab1SKenneth D. Merry 0xF0D8, 0x7B6F, 0x6C01, 0xE7B6, 0x42DD, 0xC96A, 0xDE04, 0x55B3
2253*ef270ab1SKenneth D. Merry };
2254*ef270ab1SKenneth D. Merry
2255*ef270ab1SKenneth D. Merry /*****************************************************************/
2256*ef270ab1SKenneth D. Merry /* End of CRC Lookup Table */
2257*ef270ab1SKenneth D. Merry /*****************************************************************/
2258*ef270ab1SKenneth D. Merry
2259*ef270ab1SKenneth D. Merry /**
2260*ef270ab1SKenneth D. Merry * @brief Calculate the T10 PI CRC guard value for a block.
2261*ef270ab1SKenneth D. Merry *
2262*ef270ab1SKenneth D. Merry * Code based on Rocksoft's public domain CRC code, refer to
2263*ef270ab1SKenneth D. Merry * http://www.ross.net/crc/download/crc_v3.txt. Minimally altered
2264*ef270ab1SKenneth D. Merry * to work with the ocs_dif API.
2265*ef270ab1SKenneth D. Merry *
2266*ef270ab1SKenneth D. Merry * @param blk_adr Pointer to the data buffer.
2267*ef270ab1SKenneth D. Merry * @param blk_len Number of bytes.
2268*ef270ab1SKenneth D. Merry * @param crc Previously-calculated CRC, or crcseed for a new block.
2269*ef270ab1SKenneth D. Merry *
2270*ef270ab1SKenneth D. Merry * @return Returns the calculated CRC, which may be passed back in for partial blocks.
2271*ef270ab1SKenneth D. Merry *
2272*ef270ab1SKenneth D. Merry */
2273*ef270ab1SKenneth D. Merry
2274*ef270ab1SKenneth D. Merry unsigned short
t10crc16(const unsigned char * blk_adr,unsigned long blk_len,unsigned short crc)2275*ef270ab1SKenneth D. Merry t10crc16(const unsigned char *blk_adr, unsigned long blk_len, unsigned short crc)
2276*ef270ab1SKenneth D. Merry {
2277*ef270ab1SKenneth D. Merry if (blk_len > 0) {
2278*ef270ab1SKenneth D. Merry while (blk_len--) {
2279*ef270ab1SKenneth D. Merry crc = crctable[((crc>>8) ^ *blk_adr++) & 0xFFL] ^ (crc << 8);
2280*ef270ab1SKenneth D. Merry }
2281*ef270ab1SKenneth D. Merry }
2282*ef270ab1SKenneth D. Merry return crc;
2283*ef270ab1SKenneth D. Merry }
2284*ef270ab1SKenneth D. Merry
2285*ef270ab1SKenneth D. Merry struct ocs_ramlog_s {
2286*ef270ab1SKenneth D. Merry uint32_t initialized;
2287*ef270ab1SKenneth D. Merry uint32_t textbuf_count;
2288*ef270ab1SKenneth D. Merry uint32_t textbuf_base;
2289*ef270ab1SKenneth D. Merry ocs_textbuf_t *textbufs;
2290*ef270ab1SKenneth D. Merry uint32_t cur_textbuf_idx;
2291*ef270ab1SKenneth D. Merry ocs_textbuf_t *cur_textbuf;
2292*ef270ab1SKenneth D. Merry ocs_lock_t lock;
2293*ef270ab1SKenneth D. Merry };
2294*ef270ab1SKenneth D. Merry
2295*ef270ab1SKenneth D. Merry static uint32_t ocs_ramlog_next_idx(ocs_ramlog_t *ramlog, uint32_t idx);
2296*ef270ab1SKenneth D. Merry
2297*ef270ab1SKenneth D. Merry /**
2298*ef270ab1SKenneth D. Merry * @brief Allocate a ramlog buffer.
2299*ef270ab1SKenneth D. Merry *
2300*ef270ab1SKenneth D. Merry * Initialize a RAM logging buffer with text buffers totalling buffer_len.
2301*ef270ab1SKenneth D. Merry *
2302*ef270ab1SKenneth D. Merry * @param ocs Pointer to driver structure.
2303*ef270ab1SKenneth D. Merry * @param buffer_len Total length of RAM log buffers.
2304*ef270ab1SKenneth D. Merry * @param buffer_count Number of text buffers to allocate (totalling buffer-len).
2305*ef270ab1SKenneth D. Merry *
2306*ef270ab1SKenneth D. Merry * @return Returns pointer to ocs_ramlog_t instance, or NULL.
2307*ef270ab1SKenneth D. Merry */
2308*ef270ab1SKenneth D. Merry ocs_ramlog_t *
ocs_ramlog_init(ocs_t * ocs,uint32_t buffer_len,uint32_t buffer_count)2309*ef270ab1SKenneth D. Merry ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count)
2310*ef270ab1SKenneth D. Merry {
2311*ef270ab1SKenneth D. Merry uint32_t i;
2312*ef270ab1SKenneth D. Merry uint32_t rc;
2313*ef270ab1SKenneth D. Merry ocs_ramlog_t *ramlog;
2314*ef270ab1SKenneth D. Merry
2315*ef270ab1SKenneth D. Merry ramlog = ocs_malloc(ocs, sizeof(*ramlog), OCS_M_ZERO | OCS_M_NOWAIT);
2316*ef270ab1SKenneth D. Merry if (ramlog == NULL) {
2317*ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_malloc ramlog failed\n");
2318*ef270ab1SKenneth D. Merry return NULL;
2319*ef270ab1SKenneth D. Merry }
2320*ef270ab1SKenneth D. Merry
2321*ef270ab1SKenneth D. Merry ramlog->textbuf_count = buffer_count;
2322*ef270ab1SKenneth D. Merry
2323*ef270ab1SKenneth D. Merry ramlog->textbufs = ocs_malloc(ocs, sizeof(*ramlog->textbufs)*buffer_count, OCS_M_ZERO | OCS_M_NOWAIT);
2324*ef270ab1SKenneth D. Merry if (ramlog->textbufs == NULL) {
2325*ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_malloc textbufs failed\n");
2326*ef270ab1SKenneth D. Merry ocs_ramlog_free(ocs, ramlog);
2327*ef270ab1SKenneth D. Merry return NULL;
2328*ef270ab1SKenneth D. Merry }
2329*ef270ab1SKenneth D. Merry
2330*ef270ab1SKenneth D. Merry for (i = 0; i < buffer_count; i ++) {
2331*ef270ab1SKenneth D. Merry rc = ocs_textbuf_alloc(ocs, &ramlog->textbufs[i], buffer_len);
2332*ef270ab1SKenneth D. Merry if (rc) {
2333*ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_textbuf_alloc failed\n");
2334*ef270ab1SKenneth D. Merry ocs_ramlog_free(ocs, ramlog);
2335*ef270ab1SKenneth D. Merry return NULL;
2336*ef270ab1SKenneth D. Merry }
2337*ef270ab1SKenneth D. Merry }
2338*ef270ab1SKenneth D. Merry
2339*ef270ab1SKenneth D. Merry ramlog->cur_textbuf_idx = 0;
2340*ef270ab1SKenneth D. Merry ramlog->textbuf_base = 1;
2341*ef270ab1SKenneth D. Merry ramlog->cur_textbuf = &ramlog->textbufs[0];
2342*ef270ab1SKenneth D. Merry ramlog->initialized = TRUE;
2343*ef270ab1SKenneth D. Merry ocs_lock_init(ocs, &ramlog->lock, "ramlog_lock[%d]", ocs_instance(ocs));
2344*ef270ab1SKenneth D. Merry return ramlog;
2345*ef270ab1SKenneth D. Merry }
2346*ef270ab1SKenneth D. Merry
2347*ef270ab1SKenneth D. Merry /**
2348*ef270ab1SKenneth D. Merry * @brief Free a ramlog buffer.
2349*ef270ab1SKenneth D. Merry *
2350*ef270ab1SKenneth D. Merry * A previously allocated RAM logging buffer is freed.
2351*ef270ab1SKenneth D. Merry *
2352*ef270ab1SKenneth D. Merry * @param ocs Pointer to driver structure.
2353*ef270ab1SKenneth D. Merry * @param ramlog Pointer to RAM logging buffer structure.
2354*ef270ab1SKenneth D. Merry *
2355*ef270ab1SKenneth D. Merry * @return None.
2356*ef270ab1SKenneth D. Merry */
2357*ef270ab1SKenneth D. Merry
2358*ef270ab1SKenneth D. Merry void
ocs_ramlog_free(ocs_t * ocs,ocs_ramlog_t * ramlog)2359*ef270ab1SKenneth D. Merry ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog)
2360*ef270ab1SKenneth D. Merry {
2361*ef270ab1SKenneth D. Merry uint32_t i;
2362*ef270ab1SKenneth D. Merry
2363*ef270ab1SKenneth D. Merry if (ramlog != NULL) {
2364*ef270ab1SKenneth D. Merry ocs_lock_free(&ramlog->lock);
2365*ef270ab1SKenneth D. Merry if (ramlog->textbufs) {
2366*ef270ab1SKenneth D. Merry for (i = 0; i < ramlog->textbuf_count; i ++) {
2367*ef270ab1SKenneth D. Merry ocs_textbuf_free(ocs, &ramlog->textbufs[i]);
2368*ef270ab1SKenneth D. Merry }
2369*ef270ab1SKenneth D. Merry
2370*ef270ab1SKenneth D. Merry ocs_free(ocs, ramlog->textbufs, ramlog->textbuf_count*sizeof(*ramlog->textbufs));
2371*ef270ab1SKenneth D. Merry ramlog->textbufs = NULL;
2372*ef270ab1SKenneth D. Merry }
2373*ef270ab1SKenneth D. Merry ocs_free(ocs, ramlog, sizeof(*ramlog));
2374*ef270ab1SKenneth D. Merry }
2375*ef270ab1SKenneth D. Merry }
2376*ef270ab1SKenneth D. Merry
2377*ef270ab1SKenneth D. Merry /**
2378*ef270ab1SKenneth D. Merry * @brief Clear a ramlog buffer.
2379*ef270ab1SKenneth D. Merry *
2380*ef270ab1SKenneth D. Merry * The text in the start of day and/or recent ramlog text buffers is cleared.
2381*ef270ab1SKenneth D. Merry *
2382*ef270ab1SKenneth D. Merry * @param ocs Pointer to driver structure.
2383*ef270ab1SKenneth D. Merry * @param ramlog Pointer to RAM logging buffer structure.
2384*ef270ab1SKenneth D. Merry * @param clear_start_of_day Clear the start of day (driver init) portion of the ramlog.
2385*ef270ab1SKenneth D. Merry * @param clear_recent Clear the recent messages portion of the ramlog.
2386*ef270ab1SKenneth D. Merry *
2387*ef270ab1SKenneth D. Merry * @return None.
2388*ef270ab1SKenneth D. Merry */
2389*ef270ab1SKenneth D. Merry
2390*ef270ab1SKenneth D. Merry void
ocs_ramlog_clear(ocs_t * ocs,ocs_ramlog_t * ramlog,int clear_start_of_day,int clear_recent)2391*ef270ab1SKenneth D. Merry ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent)
2392*ef270ab1SKenneth D. Merry {
2393*ef270ab1SKenneth D. Merry uint32_t i;
2394*ef270ab1SKenneth D. Merry
2395*ef270ab1SKenneth D. Merry if (clear_recent) {
2396*ef270ab1SKenneth D. Merry for (i = ramlog->textbuf_base; i < ramlog->textbuf_count; i ++) {
2397*ef270ab1SKenneth D. Merry ocs_textbuf_reset(&ramlog->textbufs[i]);
2398*ef270ab1SKenneth D. Merry }
2399*ef270ab1SKenneth D. Merry ramlog->cur_textbuf_idx = 1;
2400*ef270ab1SKenneth D. Merry }
2401*ef270ab1SKenneth D. Merry if (clear_start_of_day && ramlog->textbuf_base) {
2402*ef270ab1SKenneth D. Merry ocs_textbuf_reset(&ramlog->textbufs[0]);
2403*ef270ab1SKenneth D. Merry /* Set textbuf_base to 0, so that all buffers are available for
2404*ef270ab1SKenneth D. Merry * recent logs
2405*ef270ab1SKenneth D. Merry */
2406*ef270ab1SKenneth D. Merry ramlog->textbuf_base = 0;
2407*ef270ab1SKenneth D. Merry }
2408*ef270ab1SKenneth D. Merry }
2409*ef270ab1SKenneth D. Merry
2410*ef270ab1SKenneth D. Merry /**
2411*ef270ab1SKenneth D. Merry * @brief Append formatted printf data to a ramlog buffer.
2412*ef270ab1SKenneth D. Merry *
2413*ef270ab1SKenneth D. Merry * Formatted data is appended to a RAM logging buffer.
2414*ef270ab1SKenneth D. Merry *
2415*ef270ab1SKenneth D. Merry * @param os Pointer to driver structure.
2416*ef270ab1SKenneth D. Merry * @param fmt Pointer to printf style format specifier.
2417*ef270ab1SKenneth D. Merry *
2418*ef270ab1SKenneth D. Merry * @return Returns 0 on success, or a negative error code value on failure.
2419*ef270ab1SKenneth D. Merry */
2420*ef270ab1SKenneth D. Merry
2421*ef270ab1SKenneth D. Merry int32_t
ocs_ramlog_printf(void * os,const char * fmt,...)2422*ef270ab1SKenneth D. Merry ocs_ramlog_printf(void *os, const char *fmt, ...)
2423*ef270ab1SKenneth D. Merry {
2424*ef270ab1SKenneth D. Merry ocs_t *ocs = os;
2425*ef270ab1SKenneth D. Merry va_list ap;
2426*ef270ab1SKenneth D. Merry int32_t res;
2427*ef270ab1SKenneth D. Merry
2428*ef270ab1SKenneth D. Merry if (ocs == NULL || ocs->ramlog == NULL) {
2429*ef270ab1SKenneth D. Merry return -1;
2430*ef270ab1SKenneth D. Merry }
2431*ef270ab1SKenneth D. Merry
2432*ef270ab1SKenneth D. Merry va_start(ap, fmt);
2433*ef270ab1SKenneth D. Merry res = ocs_ramlog_vprintf(ocs->ramlog, fmt, ap);
2434*ef270ab1SKenneth D. Merry va_end(ap);
2435*ef270ab1SKenneth D. Merry
2436*ef270ab1SKenneth D. Merry return res;
2437*ef270ab1SKenneth D. Merry }
2438*ef270ab1SKenneth D. Merry
2439*ef270ab1SKenneth D. Merry /**
2440*ef270ab1SKenneth D. Merry * @brief Append formatted text to a ramlog using variable arguments.
2441*ef270ab1SKenneth D. Merry *
2442*ef270ab1SKenneth D. Merry * Formatted data is appended to the RAM logging buffer, using variable arguments.
2443*ef270ab1SKenneth D. Merry *
2444*ef270ab1SKenneth D. Merry * @param ramlog Pointer to RAM logging buffer.
2445*ef270ab1SKenneth D. Merry * @param fmt Pointer to printf style formatting string.
2446*ef270ab1SKenneth D. Merry * @param ap Variable argument pointer.
2447*ef270ab1SKenneth D. Merry *
2448*ef270ab1SKenneth D. Merry * @return Returns 0 on success, or a negative error code value on failure.
2449*ef270ab1SKenneth D. Merry */
2450*ef270ab1SKenneth D. Merry
2451*ef270ab1SKenneth D. Merry int32_t
ocs_ramlog_vprintf(ocs_ramlog_t * ramlog,const char * fmt,va_list ap)2452*ef270ab1SKenneth D. Merry ocs_ramlog_vprintf(ocs_ramlog_t *ramlog, const char *fmt, va_list ap)
2453*ef270ab1SKenneth D. Merry {
2454*ef270ab1SKenneth D. Merry if (ramlog == NULL || !ramlog->initialized) {
2455*ef270ab1SKenneth D. Merry return -1;
2456*ef270ab1SKenneth D. Merry }
2457*ef270ab1SKenneth D. Merry
2458*ef270ab1SKenneth D. Merry /* check the current text buffer, if it is almost full (less than 120 characaters), then
2459*ef270ab1SKenneth D. Merry * roll to the next one.
2460*ef270ab1SKenneth D. Merry */
2461*ef270ab1SKenneth D. Merry ocs_lock(&ramlog->lock);
2462*ef270ab1SKenneth D. Merry if (ocs_textbuf_remaining(ramlog->cur_textbuf) < 120) {
2463*ef270ab1SKenneth D. Merry ramlog->cur_textbuf_idx = ocs_ramlog_next_idx(ramlog, ramlog->cur_textbuf_idx);
2464*ef270ab1SKenneth D. Merry ramlog->cur_textbuf = &ramlog->textbufs[ramlog->cur_textbuf_idx];
2465*ef270ab1SKenneth D. Merry ocs_textbuf_reset(ramlog->cur_textbuf);
2466*ef270ab1SKenneth D. Merry }
2467*ef270ab1SKenneth D. Merry
2468*ef270ab1SKenneth D. Merry ocs_textbuf_vprintf(ramlog->cur_textbuf, fmt, ap);
2469*ef270ab1SKenneth D. Merry ocs_unlock(&ramlog->lock);
2470*ef270ab1SKenneth D. Merry
2471*ef270ab1SKenneth D. Merry return 0;
2472*ef270ab1SKenneth D. Merry }
2473*ef270ab1SKenneth D. Merry
2474*ef270ab1SKenneth D. Merry /**
2475*ef270ab1SKenneth D. Merry * @brief Return next ramlog buffer index.
2476*ef270ab1SKenneth D. Merry *
2477*ef270ab1SKenneth D. Merry * Given a RAM logging buffer index, return the next index.
2478*ef270ab1SKenneth D. Merry *
2479*ef270ab1SKenneth D. Merry * @param ramlog Pointer to RAM logging buffer.
2480*ef270ab1SKenneth D. Merry * @param idx Index value.
2481*ef270ab1SKenneth D. Merry *
2482*ef270ab1SKenneth D. Merry * @return Returns next index value.
2483*ef270ab1SKenneth D. Merry */
2484*ef270ab1SKenneth D. Merry
2485*ef270ab1SKenneth D. Merry static uint32_t
ocs_ramlog_next_idx(ocs_ramlog_t * ramlog,uint32_t idx)2486*ef270ab1SKenneth D. Merry ocs_ramlog_next_idx(ocs_ramlog_t *ramlog, uint32_t idx)
2487*ef270ab1SKenneth D. Merry {
2488*ef270ab1SKenneth D. Merry idx = idx + 1;
2489*ef270ab1SKenneth D. Merry
2490*ef270ab1SKenneth D. Merry if (idx >= ramlog->textbuf_count) {
2491*ef270ab1SKenneth D. Merry idx = ramlog->textbuf_base;
2492*ef270ab1SKenneth D. Merry }
2493*ef270ab1SKenneth D. Merry
2494*ef270ab1SKenneth D. Merry return idx;
2495*ef270ab1SKenneth D. Merry }
2496*ef270ab1SKenneth D. Merry
2497*ef270ab1SKenneth D. Merry /**
2498*ef270ab1SKenneth D. Merry * @brief Perform ramlog buffer driver dump.
2499*ef270ab1SKenneth D. Merry *
2500*ef270ab1SKenneth D. Merry * The RAM logging buffer is appended to the driver dump data.
2501*ef270ab1SKenneth D. Merry *
2502*ef270ab1SKenneth D. Merry * @param textbuf Pointer to the driver dump text buffer.
2503*ef270ab1SKenneth D. Merry * @param ramlog Pointer to the RAM logging buffer.
2504*ef270ab1SKenneth D. Merry *
2505*ef270ab1SKenneth D. Merry * @return Returns 0 on success, or a negative error code value on failure.
2506*ef270ab1SKenneth D. Merry */
2507*ef270ab1SKenneth D. Merry
2508*ef270ab1SKenneth D. Merry int32_t
ocs_ddump_ramlog(ocs_textbuf_t * textbuf,ocs_ramlog_t * ramlog)2509*ef270ab1SKenneth D. Merry ocs_ddump_ramlog(ocs_textbuf_t *textbuf, ocs_ramlog_t *ramlog)
2510*ef270ab1SKenneth D. Merry {
2511*ef270ab1SKenneth D. Merry uint32_t i;
2512*ef270ab1SKenneth D. Merry ocs_textbuf_t *rltextbuf;
2513*ef270ab1SKenneth D. Merry int idx;
2514*ef270ab1SKenneth D. Merry
2515*ef270ab1SKenneth D. Merry if ((ramlog == NULL) || (ramlog->textbufs == NULL)) {
2516*ef270ab1SKenneth D. Merry return -1;
2517*ef270ab1SKenneth D. Merry }
2518*ef270ab1SKenneth D. Merry
2519*ef270ab1SKenneth D. Merry ocs_ddump_section(textbuf, "driver-log", 0);
2520*ef270ab1SKenneth D. Merry
2521*ef270ab1SKenneth D. Merry /* Dump the start of day buffer */
2522*ef270ab1SKenneth D. Merry ocs_ddump_section(textbuf, "startofday", 0);
2523*ef270ab1SKenneth D. Merry /* If textbuf_base is 0, then all buffers are used for recent */
2524*ef270ab1SKenneth D. Merry if (ramlog->textbuf_base) {
2525*ef270ab1SKenneth D. Merry rltextbuf = &ramlog->textbufs[0];
2526*ef270ab1SKenneth D. Merry ocs_textbuf_buffer(textbuf, ocs_textbuf_get_buffer(rltextbuf), ocs_textbuf_get_written(rltextbuf));
2527*ef270ab1SKenneth D. Merry }
2528*ef270ab1SKenneth D. Merry ocs_ddump_endsection(textbuf, "startofday", 0);
2529*ef270ab1SKenneth D. Merry
2530*ef270ab1SKenneth D. Merry /* Dump the most recent buffers */
2531*ef270ab1SKenneth D. Merry ocs_ddump_section(textbuf, "recent", 0);
2532*ef270ab1SKenneth D. Merry
2533*ef270ab1SKenneth D. Merry /* start with the next textbuf */
2534*ef270ab1SKenneth D. Merry idx = ocs_ramlog_next_idx(ramlog, ramlog->textbuf_count);
2535*ef270ab1SKenneth D. Merry
2536*ef270ab1SKenneth D. Merry for (i = ramlog->textbuf_base; i < ramlog->textbuf_count; i ++) {
2537*ef270ab1SKenneth D. Merry rltextbuf = &ramlog->textbufs[idx];
2538*ef270ab1SKenneth D. Merry ocs_textbuf_buffer(textbuf, ocs_textbuf_get_buffer(rltextbuf), ocs_textbuf_get_written(rltextbuf));
2539*ef270ab1SKenneth D. Merry idx = ocs_ramlog_next_idx(ramlog, idx);
2540*ef270ab1SKenneth D. Merry }
2541*ef270ab1SKenneth D. Merry ocs_ddump_endsection(textbuf, "recent", 0);
2542*ef270ab1SKenneth D. Merry ocs_ddump_endsection(textbuf, "driver-log", 0);
2543*ef270ab1SKenneth D. Merry
2544*ef270ab1SKenneth D. Merry return 0;
2545*ef270ab1SKenneth D. Merry }
2546*ef270ab1SKenneth D. Merry
2547*ef270ab1SKenneth D. Merry struct ocs_pool_s {
2548*ef270ab1SKenneth D. Merry ocs_os_handle_t os;
2549*ef270ab1SKenneth D. Merry ocs_array_t *a;
2550*ef270ab1SKenneth D. Merry ocs_list_t freelist;
2551*ef270ab1SKenneth D. Merry uint32_t use_lock:1;
2552*ef270ab1SKenneth D. Merry ocs_lock_t lock;
2553*ef270ab1SKenneth D. Merry };
2554*ef270ab1SKenneth D. Merry
2555*ef270ab1SKenneth D. Merry typedef struct {
2556*ef270ab1SKenneth D. Merry ocs_list_link_t link;
2557*ef270ab1SKenneth D. Merry } pool_hdr_t;
2558*ef270ab1SKenneth D. Merry
2559*ef270ab1SKenneth D. Merry /**
2560*ef270ab1SKenneth D. Merry * @brief Allocate a memory pool.
2561*ef270ab1SKenneth D. Merry *
2562*ef270ab1SKenneth D. Merry * A memory pool of given size and item count is allocated.
2563*ef270ab1SKenneth D. Merry *
2564*ef270ab1SKenneth D. Merry * @param os OS handle.
2565*ef270ab1SKenneth D. Merry * @param size Size in bytes of item.
2566*ef270ab1SKenneth D. Merry * @param count Number of items in a memory pool.
2567*ef270ab1SKenneth D. Merry * @param use_lock TRUE to enable locking of pool.
2568*ef270ab1SKenneth D. Merry *
2569*ef270ab1SKenneth D. Merry * @return Returns pointer to allocated memory pool, or NULL.
2570*ef270ab1SKenneth D. Merry */
2571*ef270ab1SKenneth D. Merry ocs_pool_t *
ocs_pool_alloc(ocs_os_handle_t os,uint32_t size,uint32_t count,uint32_t use_lock)2572*ef270ab1SKenneth D. Merry ocs_pool_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count, uint32_t use_lock)
2573*ef270ab1SKenneth D. Merry {
2574*ef270ab1SKenneth D. Merry ocs_pool_t *pool;
2575*ef270ab1SKenneth D. Merry uint32_t i;
2576*ef270ab1SKenneth D. Merry
2577*ef270ab1SKenneth D. Merry pool = ocs_malloc(os, sizeof(*pool), OCS_M_ZERO | OCS_M_NOWAIT);
2578*ef270ab1SKenneth D. Merry if (pool == NULL) {
2579*ef270ab1SKenneth D. Merry return NULL;
2580*ef270ab1SKenneth D. Merry }
2581*ef270ab1SKenneth D. Merry
2582*ef270ab1SKenneth D. Merry pool->os = os;
2583*ef270ab1SKenneth D. Merry pool->use_lock = use_lock;
2584*ef270ab1SKenneth D. Merry
2585*ef270ab1SKenneth D. Merry /* Allocate an array where each array item is the size of a pool_hdr_t plus
2586*ef270ab1SKenneth D. Merry * the requested memory item size (size)
2587*ef270ab1SKenneth D. Merry */
2588*ef270ab1SKenneth D. Merry pool->a = ocs_array_alloc(os, size + sizeof(pool_hdr_t), count);
2589*ef270ab1SKenneth D. Merry if (pool->a == NULL) {
2590*ef270ab1SKenneth D. Merry ocs_pool_free(pool);
2591*ef270ab1SKenneth D. Merry return NULL;
2592*ef270ab1SKenneth D. Merry }
2593*ef270ab1SKenneth D. Merry
2594*ef270ab1SKenneth D. Merry ocs_list_init(&pool->freelist, pool_hdr_t, link);
2595*ef270ab1SKenneth D. Merry for (i = 0; i < count; i++) {
2596*ef270ab1SKenneth D. Merry ocs_list_add_tail(&pool->freelist, ocs_array_get(pool->a, i));
2597*ef270ab1SKenneth D. Merry }
2598*ef270ab1SKenneth D. Merry
2599*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2600*ef270ab1SKenneth D. Merry ocs_lock_init(os, &pool->lock, "ocs_pool:%p", pool);
2601*ef270ab1SKenneth D. Merry }
2602*ef270ab1SKenneth D. Merry
2603*ef270ab1SKenneth D. Merry return pool;
2604*ef270ab1SKenneth D. Merry }
2605*ef270ab1SKenneth D. Merry
2606*ef270ab1SKenneth D. Merry /**
2607*ef270ab1SKenneth D. Merry * @brief Reset a memory pool.
2608*ef270ab1SKenneth D. Merry *
2609*ef270ab1SKenneth D. Merry * Place all pool elements on the free list, and zero them.
2610*ef270ab1SKenneth D. Merry *
2611*ef270ab1SKenneth D. Merry * @param pool Pointer to the pool object.
2612*ef270ab1SKenneth D. Merry *
2613*ef270ab1SKenneth D. Merry * @return None.
2614*ef270ab1SKenneth D. Merry */
2615*ef270ab1SKenneth D. Merry void
ocs_pool_reset(ocs_pool_t * pool)2616*ef270ab1SKenneth D. Merry ocs_pool_reset(ocs_pool_t *pool)
2617*ef270ab1SKenneth D. Merry {
2618*ef270ab1SKenneth D. Merry uint32_t i;
2619*ef270ab1SKenneth D. Merry uint32_t count = ocs_array_get_count(pool->a);
2620*ef270ab1SKenneth D. Merry uint32_t size = ocs_array_get_size(pool->a);
2621*ef270ab1SKenneth D. Merry
2622*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2623*ef270ab1SKenneth D. Merry ocs_lock(&pool->lock);
2624*ef270ab1SKenneth D. Merry }
2625*ef270ab1SKenneth D. Merry
2626*ef270ab1SKenneth D. Merry /*
2627*ef270ab1SKenneth D. Merry * Remove all the entries from the free list, otherwise we will
2628*ef270ab1SKenneth D. Merry * encountered linked list asserts when they are re-added.
2629*ef270ab1SKenneth D. Merry */
2630*ef270ab1SKenneth D. Merry while (!ocs_list_empty(&pool->freelist)) {
2631*ef270ab1SKenneth D. Merry ocs_list_remove_head(&pool->freelist);
2632*ef270ab1SKenneth D. Merry }
2633*ef270ab1SKenneth D. Merry
2634*ef270ab1SKenneth D. Merry /* Reset the free list */
2635*ef270ab1SKenneth D. Merry ocs_list_init(&pool->freelist, pool_hdr_t, link);
2636*ef270ab1SKenneth D. Merry
2637*ef270ab1SKenneth D. Merry /* Return all elements to the free list and zero the elements */
2638*ef270ab1SKenneth D. Merry for (i = 0; i < count; i++) {
2639*ef270ab1SKenneth D. Merry ocs_memset(ocs_pool_get_instance(pool, i), 0, size - sizeof(pool_hdr_t));
2640*ef270ab1SKenneth D. Merry ocs_list_add_tail(&pool->freelist, ocs_array_get(pool->a, i));
2641*ef270ab1SKenneth D. Merry }
2642*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2643*ef270ab1SKenneth D. Merry ocs_unlock(&pool->lock);
2644*ef270ab1SKenneth D. Merry }
2645*ef270ab1SKenneth D. Merry
2646*ef270ab1SKenneth D. Merry }
2647*ef270ab1SKenneth D. Merry
2648*ef270ab1SKenneth D. Merry /**
2649*ef270ab1SKenneth D. Merry * @brief Free a previously allocated memory pool.
2650*ef270ab1SKenneth D. Merry *
2651*ef270ab1SKenneth D. Merry * The memory pool is freed.
2652*ef270ab1SKenneth D. Merry *
2653*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2654*ef270ab1SKenneth D. Merry *
2655*ef270ab1SKenneth D. Merry * @return None.
2656*ef270ab1SKenneth D. Merry */
2657*ef270ab1SKenneth D. Merry void
ocs_pool_free(ocs_pool_t * pool)2658*ef270ab1SKenneth D. Merry ocs_pool_free(ocs_pool_t *pool)
2659*ef270ab1SKenneth D. Merry {
2660*ef270ab1SKenneth D. Merry if (pool != NULL) {
2661*ef270ab1SKenneth D. Merry if (pool->a != NULL) {
2662*ef270ab1SKenneth D. Merry ocs_array_free(pool->a);
2663*ef270ab1SKenneth D. Merry }
2664*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2665*ef270ab1SKenneth D. Merry ocs_lock_free(&pool->lock);
2666*ef270ab1SKenneth D. Merry }
2667*ef270ab1SKenneth D. Merry ocs_free(pool->os, pool, sizeof(*pool));
2668*ef270ab1SKenneth D. Merry }
2669*ef270ab1SKenneth D. Merry }
2670*ef270ab1SKenneth D. Merry
2671*ef270ab1SKenneth D. Merry /**
2672*ef270ab1SKenneth D. Merry * @brief Allocate a memory pool item
2673*ef270ab1SKenneth D. Merry *
2674*ef270ab1SKenneth D. Merry * A memory pool item is taken from the free list and returned.
2675*ef270ab1SKenneth D. Merry *
2676*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2677*ef270ab1SKenneth D. Merry *
2678*ef270ab1SKenneth D. Merry * @return Pointer to allocated item, otherwise NULL if there are no unallocated
2679*ef270ab1SKenneth D. Merry * items.
2680*ef270ab1SKenneth D. Merry */
2681*ef270ab1SKenneth D. Merry void *
ocs_pool_get(ocs_pool_t * pool)2682*ef270ab1SKenneth D. Merry ocs_pool_get(ocs_pool_t *pool)
2683*ef270ab1SKenneth D. Merry {
2684*ef270ab1SKenneth D. Merry pool_hdr_t *h;
2685*ef270ab1SKenneth D. Merry void *item = NULL;
2686*ef270ab1SKenneth D. Merry
2687*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2688*ef270ab1SKenneth D. Merry ocs_lock(&pool->lock);
2689*ef270ab1SKenneth D. Merry }
2690*ef270ab1SKenneth D. Merry
2691*ef270ab1SKenneth D. Merry h = ocs_list_remove_head(&pool->freelist);
2692*ef270ab1SKenneth D. Merry
2693*ef270ab1SKenneth D. Merry if (h != NULL) {
2694*ef270ab1SKenneth D. Merry /* Return the array item address offset by the size of pool_hdr_t */
2695*ef270ab1SKenneth D. Merry item = &h[1];
2696*ef270ab1SKenneth D. Merry }
2697*ef270ab1SKenneth D. Merry
2698*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2699*ef270ab1SKenneth D. Merry ocs_unlock(&pool->lock);
2700*ef270ab1SKenneth D. Merry }
2701*ef270ab1SKenneth D. Merry return item;
2702*ef270ab1SKenneth D. Merry }
2703*ef270ab1SKenneth D. Merry
2704*ef270ab1SKenneth D. Merry /**
2705*ef270ab1SKenneth D. Merry * @brief free memory pool item
2706*ef270ab1SKenneth D. Merry *
2707*ef270ab1SKenneth D. Merry * A memory pool item is freed.
2708*ef270ab1SKenneth D. Merry *
2709*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2710*ef270ab1SKenneth D. Merry * @param item Pointer to item to free.
2711*ef270ab1SKenneth D. Merry *
2712*ef270ab1SKenneth D. Merry * @return None.
2713*ef270ab1SKenneth D. Merry */
2714*ef270ab1SKenneth D. Merry void
ocs_pool_put(ocs_pool_t * pool,void * item)2715*ef270ab1SKenneth D. Merry ocs_pool_put(ocs_pool_t *pool, void *item)
2716*ef270ab1SKenneth D. Merry {
2717*ef270ab1SKenneth D. Merry pool_hdr_t *h;
2718*ef270ab1SKenneth D. Merry
2719*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2720*ef270ab1SKenneth D. Merry ocs_lock(&pool->lock);
2721*ef270ab1SKenneth D. Merry }
2722*ef270ab1SKenneth D. Merry
2723*ef270ab1SKenneth D. Merry /* Fetch the address of the array item, which is the item address negatively offset
2724*ef270ab1SKenneth D. Merry * by size of pool_hdr_t (note the index of [-1]
2725*ef270ab1SKenneth D. Merry */
2726*ef270ab1SKenneth D. Merry h = &((pool_hdr_t*)item)[-1];
2727*ef270ab1SKenneth D. Merry
2728*ef270ab1SKenneth D. Merry ocs_list_add_tail(&pool->freelist, h);
2729*ef270ab1SKenneth D. Merry
2730*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2731*ef270ab1SKenneth D. Merry ocs_unlock(&pool->lock);
2732*ef270ab1SKenneth D. Merry }
2733*ef270ab1SKenneth D. Merry
2734*ef270ab1SKenneth D. Merry }
2735*ef270ab1SKenneth D. Merry
2736*ef270ab1SKenneth D. Merry /**
2737*ef270ab1SKenneth D. Merry * @brief Return memory pool item count.
2738*ef270ab1SKenneth D. Merry *
2739*ef270ab1SKenneth D. Merry * Returns the allocated number of items.
2740*ef270ab1SKenneth D. Merry *
2741*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2742*ef270ab1SKenneth D. Merry *
2743*ef270ab1SKenneth D. Merry * @return Returns count of allocated items.
2744*ef270ab1SKenneth D. Merry */
2745*ef270ab1SKenneth D. Merry uint32_t
ocs_pool_get_count(ocs_pool_t * pool)2746*ef270ab1SKenneth D. Merry ocs_pool_get_count(ocs_pool_t *pool)
2747*ef270ab1SKenneth D. Merry {
2748*ef270ab1SKenneth D. Merry uint32_t count;
2749*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2750*ef270ab1SKenneth D. Merry ocs_lock(&pool->lock);
2751*ef270ab1SKenneth D. Merry }
2752*ef270ab1SKenneth D. Merry count = ocs_array_get_count(pool->a);
2753*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2754*ef270ab1SKenneth D. Merry ocs_unlock(&pool->lock);
2755*ef270ab1SKenneth D. Merry }
2756*ef270ab1SKenneth D. Merry return count;
2757*ef270ab1SKenneth D. Merry }
2758*ef270ab1SKenneth D. Merry
2759*ef270ab1SKenneth D. Merry /**
2760*ef270ab1SKenneth D. Merry * @brief Return item given an index.
2761*ef270ab1SKenneth D. Merry *
2762*ef270ab1SKenneth D. Merry * A pointer to a memory pool item is returned given an index.
2763*ef270ab1SKenneth D. Merry *
2764*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2765*ef270ab1SKenneth D. Merry * @param idx Index.
2766*ef270ab1SKenneth D. Merry *
2767*ef270ab1SKenneth D. Merry * @return Returns pointer to item, or NULL if index is invalid.
2768*ef270ab1SKenneth D. Merry */
2769*ef270ab1SKenneth D. Merry void *
ocs_pool_get_instance(ocs_pool_t * pool,uint32_t idx)2770*ef270ab1SKenneth D. Merry ocs_pool_get_instance(ocs_pool_t *pool, uint32_t idx)
2771*ef270ab1SKenneth D. Merry {
2772*ef270ab1SKenneth D. Merry pool_hdr_t *h = ocs_array_get(pool->a, idx);
2773*ef270ab1SKenneth D. Merry
2774*ef270ab1SKenneth D. Merry if (h == NULL) {
2775*ef270ab1SKenneth D. Merry return NULL;
2776*ef270ab1SKenneth D. Merry }
2777*ef270ab1SKenneth D. Merry return &h[1];
2778*ef270ab1SKenneth D. Merry }
2779*ef270ab1SKenneth D. Merry
2780*ef270ab1SKenneth D. Merry /**
2781*ef270ab1SKenneth D. Merry * @brief Return count of free objects in a pool.
2782*ef270ab1SKenneth D. Merry *
2783*ef270ab1SKenneth D. Merry * The number of objects on a pool's free list.
2784*ef270ab1SKenneth D. Merry *
2785*ef270ab1SKenneth D. Merry * @param pool Pointer to memory pool.
2786*ef270ab1SKenneth D. Merry *
2787*ef270ab1SKenneth D. Merry * @return Returns count of objects on free list.
2788*ef270ab1SKenneth D. Merry */
2789*ef270ab1SKenneth D. Merry uint32_t
ocs_pool_get_freelist_count(ocs_pool_t * pool)2790*ef270ab1SKenneth D. Merry ocs_pool_get_freelist_count(ocs_pool_t *pool)
2791*ef270ab1SKenneth D. Merry {
2792*ef270ab1SKenneth D. Merry uint32_t count = 0;
2793*ef270ab1SKenneth D. Merry void *item;
2794*ef270ab1SKenneth D. Merry
2795*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2796*ef270ab1SKenneth D. Merry ocs_lock(&pool->lock);
2797*ef270ab1SKenneth D. Merry }
2798*ef270ab1SKenneth D. Merry
2799*ef270ab1SKenneth D. Merry ocs_list_foreach(&pool->freelist, item) {
2800*ef270ab1SKenneth D. Merry count++;
2801*ef270ab1SKenneth D. Merry }
2802*ef270ab1SKenneth D. Merry
2803*ef270ab1SKenneth D. Merry if (pool->use_lock) {
2804*ef270ab1SKenneth D. Merry ocs_unlock(&pool->lock);
2805*ef270ab1SKenneth D. Merry }
2806*ef270ab1SKenneth D. Merry return count;
2807*ef270ab1SKenneth D. Merry }
2808