1/*-
2 * Copyright (c) 2017 Broadcom. All rights reserved.
3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 *    this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 *    this list of conditions and the following disclaimer in the documentation
13 *    and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $FreeBSD$
32 */
33
34/**
35 * @file
36 *
37 */
38
39#ifndef __OCS_UTILS_H
40#define __OCS_UTILS_H
41
42#include "ocs_list.h"
43typedef struct ocs_array_s ocs_array_t;
44
45extern void ocs_array_set_slablen(uint32_t len);
46extern ocs_array_t *ocs_array_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count);
47extern void ocs_array_free(ocs_array_t *array);
48extern void *ocs_array_get(ocs_array_t *array, uint32_t idx);
49extern uint32_t ocs_array_get_count(ocs_array_t *array);
50extern uint32_t ocs_array_get_size(ocs_array_t *array);
51
52/* Void pointer array and iterator */
53typedef struct ocs_varray_s ocs_varray_t;
54
55extern ocs_varray_t *ocs_varray_alloc(ocs_os_handle_t os, uint32_t entry_count);
56extern void ocs_varray_free(ocs_varray_t *ai);
57extern int32_t ocs_varray_add(ocs_varray_t *ai, void *entry);
58extern void ocs_varray_iter_reset(ocs_varray_t *ai);
59extern void *ocs_varray_iter_next(ocs_varray_t *ai);
60extern void *_ocs_varray_iter_next(ocs_varray_t *ai);
61extern void ocs_varray_lock(ocs_varray_t *ai);
62extern void ocs_varray_unlock(ocs_varray_t *ai);
63extern uint32_t ocs_varray_get_count(ocs_varray_t *ai);
64
65/***************************************************************************
66 * Circular buffer
67 *
68 */
69
70typedef struct ocs_cbuf_s ocs_cbuf_t;
71
72extern ocs_cbuf_t *ocs_cbuf_alloc(ocs_os_handle_t os, uint32_t entry_count);
73extern void ocs_cbuf_free(ocs_cbuf_t *cbuf);
74extern void *ocs_cbuf_get(ocs_cbuf_t *cbuf, int32_t timeout_usec);
75extern int32_t ocs_cbuf_put(ocs_cbuf_t *cbuf, void *elem);
76extern int32_t ocs_cbuf_prime(ocs_cbuf_t *cbuf, ocs_array_t *array);
77
78typedef struct {
79        void *vaddr;
80        uint32_t length;
81} ocs_scsi_vaddr_len_t;
82
83#define OCS_TEXTBUF_MAX_ALLOC_LEN	(256*1024)
84
85typedef struct {
86	ocs_list_link_t link;
87	uint8_t user_allocated:1;
88	uint8_t *buffer;
89	uint32_t buffer_length;
90	uint32_t buffer_written;
91} ocs_textbuf_segment_t;
92
93typedef struct {
94	ocs_t *ocs;
95	ocs_list_t segment_list;
96	uint8_t extendable:1;
97	uint32_t allocation_length;
98	uint32_t total_allocation_length;
99	uint32_t max_allocation_length;
100} ocs_textbuf_t;
101
102extern int32_t ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length);
103extern uint32_t ocs_textbuf_initialized(ocs_textbuf_t *textbuf);
104extern int32_t ocs_textbuf_init(ocs_t *ocs, ocs_textbuf_t *textbuf, void *buffer, uint32_t length);
105extern void ocs_textbuf_free(ocs_t *ocs, ocs_textbuf_t *textbuf);
106extern void ocs_textbuf_putc(ocs_textbuf_t *textbuf, uint8_t c);
107extern void ocs_textbuf_puts(ocs_textbuf_t *textbuf, char *s);
108__attribute__((format(printf,2,3)))
109extern void ocs_textbuf_printf(ocs_textbuf_t *textbuf, const char *fmt, ...);
110__attribute__((format(printf,2,0)))
111extern void ocs_textbuf_vprintf(ocs_textbuf_t *textbuf, const char *fmt, va_list ap);
112extern void ocs_textbuf_buffer(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length);
113extern void ocs_textbuf_copy(ocs_textbuf_t *textbuf, uint8_t *buffer, uint32_t buffer_length);
114extern int32_t ocs_textbuf_remaining(ocs_textbuf_t *textbuf);
115extern void ocs_textbuf_reset(ocs_textbuf_t *textbuf);
116extern uint8_t *ocs_textbuf_get_buffer(ocs_textbuf_t *textbuf);
117extern int32_t ocs_textbuf_get_length(ocs_textbuf_t *textbuf);
118extern int32_t ocs_textbuf_get_written(ocs_textbuf_t *textbuf);
119extern uint8_t *ocs_textbuf_ext_get_buffer(ocs_textbuf_t *textbuf, uint32_t idx);
120extern int32_t ocs_textbuf_ext_get_length(ocs_textbuf_t *textbuf, uint32_t idx);
121extern int32_t ocs_textbuf_ext_get_written(ocs_textbuf_t *textbuf, uint32_t idx);
122
123typedef struct ocs_pool_s ocs_pool_t;
124
125extern ocs_pool_t *ocs_pool_alloc(ocs_os_handle_t os, uint32_t size, uint32_t count, uint32_t use_lock);
126extern void ocs_pool_reset(ocs_pool_t *pool);
127extern void ocs_pool_free(ocs_pool_t *pool);
128extern void *ocs_pool_get(ocs_pool_t *pool);
129extern void ocs_pool_put(ocs_pool_t *pool, void *item);
130extern uint32_t ocs_pool_get_count(ocs_pool_t *pool);
131extern void *ocs_pool_get_instance(ocs_pool_t *pool, uint32_t idx);
132extern uint32_t ocs_pool_get_freelist_count(ocs_pool_t *pool);
133
134/* Uncomment this line to enable logging extended queue history
135 */
136//#define OCS_DEBUG_QUEUE_HISTORY
137
138/* Allocate maximum allowed (4M) */
139#if defined(OCS_DEBUG_QUEUE_HISTORY)
140#define OCS_Q_HIST_SIZE (1000000UL)		/* Size in words */
141#endif
142
143#define OCS_LOG_ENABLE_SM_TRACE(ocs)		(((ocs) != NULL) ? (((ocs)->logmask & (1U << 0)) != 0) : 0)
144#define OCS_LOG_ENABLE_ELS_TRACE(ocs)		(((ocs) != NULL) ? (((ocs)->logmask & (1U << 1)) != 0) : 0)
145#define OCS_LOG_ENABLE_SCSI_TRACE(ocs)		(((ocs) != NULL) ? (((ocs)->logmask & (1U << 2)) != 0) : 0)
146#define OCS_LOG_ENABLE_SCSI_TGT_TRACE(ocs)	(((ocs) != NULL) ? (((ocs)->logmask & (1U << 3)) != 0) : 0)
147#define OCS_LOG_ENABLE_DOMAIN_SM_TRACE(ocs)	(((ocs) != NULL) ? (((ocs)->logmask & (1U << 4)) != 0) : 0)
148#define OCS_LOG_ENABLE_Q_FULL_BUSY_MSG(ocs)	(((ocs) != NULL) ? (((ocs)->logmask & (1U << 5)) != 0) : 0)
149#define OCS_LOG_ENABLE_IO_ERRORS(ocs)		(((ocs) != NULL) ? (((ocs)->logmask & (1U << 6)) != 0) : 0)
150
151extern void ocs_dump32(uint32_t, ocs_os_handle_t, const char *, void *, uint32_t);
152extern void ocs_debug_enable(uint32_t mask);
153extern void ocs_debug_disable(uint32_t mask);
154extern int ocs_debug_is_enabled(uint32_t mask);
155extern void ocs_debug_attach(void *);
156extern void ocs_debug_detach(void *);
157
158#if defined(OCS_DEBUG_QUEUE_HISTORY)
159
160/**
161 * @brief Queue history footer
162 */
163typedef union ocs_q_hist_ftr_u {
164	uint32_t word;
165	struct {
166#define Q_HIST_TYPE_LEN 		3
167#define Q_HIST_MASK_LEN 		29
168		uint32_t mask:Q_HIST_MASK_LEN,
169			 type:Q_HIST_TYPE_LEN;
170	} s;
171} ocs_q_hist_ftr_t;
172
173/**
174 * @brief WQE command mask lookup
175 */
176typedef struct ocs_q_hist_wqe_mask_s {
177	uint8_t command;
178	uint32_t mask;
179} ocs_q_hist_wqe_mask_t;
180
181/**
182 * @brief CQE mask lookup
183 */
184typedef struct ocs_q_hist_cqe_mask_s {
185	uint8_t ctype;
186	uint32_t :Q_HIST_MASK_LEN,
187		 type:Q_HIST_TYPE_LEN;
188	uint32_t mask;
189	uint32_t mask_err;
190} ocs_q_hist_cqe_mask_t;
191
192/**
193 * @brief Queue history type
194 */
195typedef enum {
196	/* changes need to be made to ocs_queue_history_type_name() as well */
197	OCS_Q_HIST_TYPE_WQE = 0,
198	OCS_Q_HIST_TYPE_CWQE,
199	OCS_Q_HIST_TYPE_CXABT,
200	OCS_Q_HIST_TYPE_MISC,
201} ocs_q_hist_type_t;
202
203static __inline const char *
204ocs_queue_history_type_name(ocs_q_hist_type_t type)
205{
206	switch (type) {
207	case OCS_Q_HIST_TYPE_WQE: return "wqe"; break;
208	case OCS_Q_HIST_TYPE_CWQE: return "wcqe"; break;
209	case OCS_Q_HIST_TYPE_CXABT: return "xacqe"; break;
210	case OCS_Q_HIST_TYPE_MISC: return "misc"; break;
211	default: return "unknown"; break;
212	}
213}
214
215typedef struct {
216	ocs_t		*ocs;
217	uint32_t	*q_hist;
218	uint32_t	q_hist_index;
219	ocs_lock_t	q_hist_lock;
220} ocs_hw_q_hist_t;
221
222extern void ocs_queue_history_cqe(ocs_hw_q_hist_t*, uint8_t, uint32_t *, uint8_t, uint32_t, uint32_t);
223extern void ocs_queue_history_wq(ocs_hw_q_hist_t*, uint32_t *, uint32_t, uint32_t);
224extern void ocs_queue_history_misc(ocs_hw_q_hist_t*, uint32_t *, uint32_t);
225extern void ocs_queue_history_init(ocs_t *, ocs_hw_q_hist_t*);
226extern void ocs_queue_history_free(ocs_hw_q_hist_t*);
227extern uint32_t ocs_queue_history_prev_index(uint32_t);
228extern uint8_t ocs_queue_history_q_info_enabled(void);
229extern uint8_t ocs_queue_history_timestamp_enabled(void);
230#else
231#define ocs_queue_history_wq(...)
232#define ocs_queue_history_cqe(...)
233#define ocs_queue_history_misc(...)
234#define ocs_queue_history_init(...)
235#define ocs_queue_history_free(...)
236#endif
237
238#define OCS_DEBUG_ALWAYS		(1U << 0)
239#define OCS_DEBUG_ENABLE_MQ_DUMP	(1U << 1)
240#define OCS_DEBUG_ENABLE_CQ_DUMP	(1U << 2)
241#define OCS_DEBUG_ENABLE_WQ_DUMP	(1U << 3)
242#define OCS_DEBUG_ENABLE_EQ_DUMP	(1U << 4)
243#define OCS_DEBUG_ENABLE_SPARAM_DUMP	(1U << 5)
244
245extern void _ocs_assert(const char *cond, const char *filename, int linenum);
246
247#define ocs_assert(cond, ...) \
248	do { \
249		if (!(cond)) { \
250			_ocs_assert(#cond, __FILE__, __LINE__); \
251			return __VA_ARGS__; \
252		} \
253	} while (0)
254
255extern void ocs_dump_service_params(const char *label, void *sparms);
256extern void ocs_display_sparams(const char *prelabel, const char *reqlabel, int dest, void *textbuf, void *sparams);
257
258typedef struct {
259	uint16_t crc;
260	uint16_t app_tag;
261	uint32_t ref_tag;
262} ocs_dif_t;
263
264/* DIF guard calculations */
265extern uint16_t ocs_scsi_dif_calc_crc(const uint8_t *, uint32_t size, uint16_t crc);
266extern uint16_t ocs_scsi_dif_calc_checksum(ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count);
267
268/**
269 * @brief Power State change message types
270 *
271 */
272typedef enum {
273	OCS_PM_PREPARE = 1,
274	OCS_PM_SLEEP,
275	OCS_PM_HIBERNATE,
276	OCS_PM_RESUME,
277} ocs_pm_msg_e;
278
279/**
280 * @brief Power State values
281 *
282 */
283typedef enum {
284	OCS_PM_STATE_S0 = 0,
285	OCS_PM_STATE_S1,
286	OCS_PM_STATE_S2,
287	OCS_PM_STATE_S3,
288	OCS_PM_STATE_S4,
289} ocs_pm_state_e;
290
291typedef struct {
292	ocs_pm_state_e pm_state;		/*<< Current PM state */
293} ocs_pm_context_t;
294
295extern int32_t ocs_pm_request(ocs_t *ocs, ocs_pm_msg_e msg, int32_t (*callback)(ocs_t *ocs, int32_t status, void *arg),
296	void *arg);
297extern ocs_pm_state_e ocs_pm_get_state(ocs_t *ocs);
298extern const char *ocs_pm_get_state_string(ocs_t *ocs);
299
300#define SPV_ROWLEN	256
301#define SPV_DIM		3
302
303/*!
304* @defgroup spv Sparse Vector
305*/
306
307/**
308 * @brief Sparse vector structure.
309 */
310typedef struct sparse_vector_s {
311	ocs_os_handle_t os;
312	uint32_t max_idx;		/**< maximum index value */
313	void **array;			/**< pointer to 3D array */
314} *sparse_vector_t;
315
316extern void spv_del(sparse_vector_t spv);
317extern sparse_vector_t spv_new(ocs_os_handle_t os);
318extern void spv_set(sparse_vector_t sv, uint32_t idx, void *value);
319extern void *spv_get(sparse_vector_t sv, uint32_t idx);
320
321extern unsigned short t10crc16(const unsigned char *blk_adr, unsigned long blk_len, unsigned short crc);
322
323typedef struct ocs_ramlog_s ocs_ramlog_t;
324
325#define OCS_RAMLOG_DEFAULT_BUFFERS              5
326
327extern ocs_ramlog_t *ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count);
328extern void ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog);
329extern void ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent);
330__attribute__((format(printf,2,3)))
331extern int32_t ocs_ramlog_printf(void *os, const char *fmt, ...);
332__attribute__((format(printf,2,0)))
333extern int32_t ocs_ramlog_vprintf(ocs_ramlog_t *ramlog, const char *fmt, va_list ap);
334extern int32_t ocs_ddump_ramlog(ocs_textbuf_t *textbuf, ocs_ramlog_t *ramlog);
335
336#endif
337