xref: /freebsd/sys/dev/ocs_fc/ocs_os.h (revision 95ee2897)
1ef270ab1SKenneth D. Merry /*-
2ef270ab1SKenneth D. Merry  * Copyright (c) 2017 Broadcom. All rights reserved.
3ef270ab1SKenneth D. Merry  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4ef270ab1SKenneth D. Merry  *
5ef270ab1SKenneth D. Merry  * Redistribution and use in source and binary forms, with or without
6ef270ab1SKenneth D. Merry  * modification, are permitted provided that the following conditions are met:
7ef270ab1SKenneth D. Merry  *
8ef270ab1SKenneth D. Merry  * 1. Redistributions of source code must retain the above copyright notice,
9ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer.
10ef270ab1SKenneth D. Merry  *
11ef270ab1SKenneth D. Merry  * 2. Redistributions in binary form must reproduce the above copyright notice,
12ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer in the documentation
13ef270ab1SKenneth D. Merry  *    and/or other materials provided with the distribution.
14ef270ab1SKenneth D. Merry  *
15ef270ab1SKenneth D. Merry  * 3. Neither the name of the copyright holder nor the names of its contributors
16ef270ab1SKenneth D. Merry  *    may be used to endorse or promote products derived from this software
17ef270ab1SKenneth D. Merry  *    without specific prior written permission.
18ef270ab1SKenneth D. Merry  *
19ef270ab1SKenneth D. Merry  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20ef270ab1SKenneth D. Merry  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21ef270ab1SKenneth D. Merry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22ef270ab1SKenneth D. Merry  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23ef270ab1SKenneth D. Merry  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ef270ab1SKenneth D. Merry  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ef270ab1SKenneth D. Merry  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ef270ab1SKenneth D. Merry  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ef270ab1SKenneth D. Merry  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ef270ab1SKenneth D. Merry  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ef270ab1SKenneth D. Merry  * POSSIBILITY OF SUCH DAMAGE.
30ef270ab1SKenneth D. Merry  */
31ef270ab1SKenneth D. Merry 
32ef270ab1SKenneth D. Merry /**
33ef270ab1SKenneth D. Merry  * @file
34ef270ab1SKenneth D. Merry  * bsd specific headers common to the driver
35ef270ab1SKenneth D. Merry  */
36ef270ab1SKenneth D. Merry 
37ef270ab1SKenneth D. Merry #ifndef _OCS_OS_H
38ef270ab1SKenneth D. Merry #define _OCS_OS_H
39ef270ab1SKenneth D. Merry 
40ef270ab1SKenneth D. Merry /***************************************************************************
41ef270ab1SKenneth D. Merry  * OS specific includes
42ef270ab1SKenneth D. Merry  */
435eaf9435SRam Kishore Vegesna #include "opt_stack.h"
445eaf9435SRam Kishore Vegesna 
45ef270ab1SKenneth D. Merry #include <sys/param.h>
46ef270ab1SKenneth D. Merry #include <sys/systm.h>
47ef270ab1SKenneth D. Merry #include <sys/malloc.h>
48ef270ab1SKenneth D. Merry #include <sys/kernel.h>
49ef270ab1SKenneth D. Merry #include <sys/module.h>
50ef270ab1SKenneth D. Merry #include <sys/bus.h>
51ef270ab1SKenneth D. Merry #include <sys/rman.h>
52ef270ab1SKenneth D. Merry #include <sys/endian.h>
53ef270ab1SKenneth D. Merry #include <sys/stddef.h>
54ef270ab1SKenneth D. Merry #include <sys/lock.h>
55ef270ab1SKenneth D. Merry #include <sys/mutex.h>
56ef270ab1SKenneth D. Merry #include <sys/taskqueue.h>
57ef270ab1SKenneth D. Merry #include <sys/bitstring.h>
58ef270ab1SKenneth D. Merry #include <sys/stack.h>
59ef270ab1SKenneth D. Merry 
60ef270ab1SKenneth D. Merry #include <machine/atomic.h>
61ef270ab1SKenneth D. Merry #include <machine/bus.h>
62ef270ab1SKenneth D. Merry #include <machine/stdarg.h>
63ef270ab1SKenneth D. Merry 
64ef270ab1SKenneth D. Merry #include <dev/pci/pcivar.h>
65ef270ab1SKenneth D. Merry 
66ef270ab1SKenneth D. Merry #include <sys/sema.h>
67ef270ab1SKenneth D. Merry #include <sys/time.h>
68ef270ab1SKenneth D. Merry 
69ef270ab1SKenneth D. Merry #include <sys/proc.h>
70ef270ab1SKenneth D. Merry #include <sys/kthread.h>
71ef270ab1SKenneth D. Merry #include <sys/unistd.h>
72ef270ab1SKenneth D. Merry #include <sys/sched.h>
73ef270ab1SKenneth D. Merry 
74ef270ab1SKenneth D. Merry #include <sys/conf.h>
75ef270ab1SKenneth D. Merry #include <sys/sysctl.h>
76ef270ab1SKenneth D. Merry #include <sys/ioccom.h>
77ef270ab1SKenneth D. Merry #include <sys/ctype.h>
78ef270ab1SKenneth D. Merry 
795eaf9435SRam Kishore Vegesna #include <sys/linker.h>		/* for debug of memory allocations */
805eaf9435SRam Kishore Vegesna 
81ef270ab1SKenneth D. Merry /* OCS_OS_MAX_ISR_TIME_MSEC -  maximum time driver code should spend in an interrupt
82ef270ab1SKenneth D. Merry  * or kernel thread context without yielding
83ef270ab1SKenneth D. Merry  */
84ef270ab1SKenneth D. Merry #define OCS_OS_MAX_ISR_TIME_MSEC	1000
85ef270ab1SKenneth D. Merry 
86ef270ab1SKenneth D. Merry /* BSD driver specific definitions */
87ef270ab1SKenneth D. Merry 
88ef270ab1SKenneth D. Merry #define ARRAY_SIZE(x)   (sizeof(x) / sizeof((x)[0]))
89ef270ab1SKenneth D. Merry 
90ef270ab1SKenneth D. Merry #define OCS_MAX_LUN			512
91ef270ab1SKenneth D. Merry #define OCS_NUM_UNSOLICITED_FRAMES	1024
92ef270ab1SKenneth D. Merry 
93ef270ab1SKenneth D. Merry #define OCS_MAX_DOMAINS			1
94ef270ab1SKenneth D. Merry #define OCS_MAX_REMOTE_NODES		2048
95ef270ab1SKenneth D. Merry #define OCS_MAX_TARGETS			1024
96ef270ab1SKenneth D. Merry #define OCS_MAX_INITIATORS		1024
97ef270ab1SKenneth D. Merry /** Reserve this number of IO for each intiator to return FULL/BUSY status */
98ef270ab1SKenneth D. Merry #define OCS_RSVD_INI_IO			8
99ef270ab1SKenneth D. Merry 
100ef270ab1SKenneth D. Merry #define OCS_MIN_DMA_ALIGNMENT		16
1017b56cb04SGordon Bergling #define OCS_MAX_DMA_ALLOC		(64*1024)	/* maximum DMA allocation that is expected to reliably succeed  */
102ef270ab1SKenneth D. Merry 
103ef270ab1SKenneth D. Merry /*
104ef270ab1SKenneth D. Merry  * Macros used to size the CQ hash table. We want to round up to the next
105ef270ab1SKenneth D. Merry  * power of 2 for the hash.
106ef270ab1SKenneth D. Merry  */
107ef270ab1SKenneth D. Merry #define B2(x)   (   (x) | (   (x) >> 1) )
108ef270ab1SKenneth D. Merry #define B4(x)   ( B2(x) | ( B2(x) >> 2) )
109ef270ab1SKenneth D. Merry #define B8(x)   ( B4(x) | ( B4(x) >> 4) )
110ef270ab1SKenneth D. Merry #define B16(x)  ( B8(x) | ( B8(x) >> 8) )
111ef270ab1SKenneth D. Merry #define B32(x)  (B16(x) | (B16(x) >>16) )
112ef270ab1SKenneth D. Merry #define B32_NEXT_POWER_OF_2(x)      (B32((x)-1) + 1)
113ef270ab1SKenneth D. Merry 
114ef270ab1SKenneth D. Merry /*
115ef270ab1SKenneth D. Merry  * likely/unlikely - branch prediction hint
116ef270ab1SKenneth D. Merry  */
117ef270ab1SKenneth D. Merry #define likely(x)               __builtin_expect(!!(x), 1)
118ef270ab1SKenneth D. Merry #define unlikely(x)             __builtin_expect(!!(x), 0)
119ef270ab1SKenneth D. Merry 
120ef270ab1SKenneth D. Merry /***************************************************************************
121ef270ab1SKenneth D. Merry  * OS abstraction
122ef270ab1SKenneth D. Merry  */
123ef270ab1SKenneth D. Merry 
124ef270ab1SKenneth D. Merry /**
125ef270ab1SKenneth D. Merry  * @brief Min/Max macros
126ef270ab1SKenneth D. Merry  *
127ef270ab1SKenneth D. Merry  */
128ef270ab1SKenneth D. Merry #define OCS_MAX(x, y)		((x) > (y) ? (x) : (y))
129ef270ab1SKenneth D. Merry #define OCS_MIN(x, y)		((x) < (y) ? (x) : (y))
130ef270ab1SKenneth D. Merry 
131ef270ab1SKenneth D. Merry #define PRIX64	"lX"
132ef270ab1SKenneth D. Merry #define PRIx64	"lx"
133ef270ab1SKenneth D. Merry #define PRId64	"ld"
134ef270ab1SKenneth D. Merry #define PRIu64	"lu"
135ef270ab1SKenneth D. Merry 
136ef270ab1SKenneth D. Merry /**
137ef270ab1SKenneth D. Merry  * Enable optional features
138ef270ab1SKenneth D. Merry  *  - OCS_INCLUDE_DEBUG include low-level SLI debug support
139ef270ab1SKenneth D. Merry  */
140ef270ab1SKenneth D. Merry #define OCS_INCLUDE_DEBUG
141ef270ab1SKenneth D. Merry 
142ef270ab1SKenneth D. Merry /**
143ef270ab1SKenneth D. Merry  * @brief Set the Nth bit
144ef270ab1SKenneth D. Merry  *
145ef270ab1SKenneth D. Merry  * @todo move to a private file used internally?
146ef270ab1SKenneth D. Merry  */
147ef270ab1SKenneth D. Merry #ifndef BIT
148ef270ab1SKenneth D. Merry #define BIT(n)		(1U << (n))
149ef270ab1SKenneth D. Merry #endif
150ef270ab1SKenneth D. Merry 
151ef270ab1SKenneth D. Merry /***************************************************************************
152ef270ab1SKenneth D. Merry  * Platform specific operations
153ef270ab1SKenneth D. Merry  */
154ef270ab1SKenneth D. Merry 
1555eaf9435SRam Kishore Vegesna typedef struct ocs_softc ocs_t;
1565eaf9435SRam Kishore Vegesna 
157ef270ab1SKenneth D. Merry /**
158ef270ab1SKenneth D. Merry  * @ingroup os
159ef270ab1SKenneth D. Merry  * @typedef ocs_os_handle_t
160ef270ab1SKenneth D. Merry  * @brief OS specific handle or driver context
161ef270ab1SKenneth D. Merry  *
162ef270ab1SKenneth D. Merry  * This can be anything from a void * to some other OS specific type. The lower
163ef270ab1SKenneth D. Merry  * layers make no assumption about its value and pass it back as the first
164ef270ab1SKenneth D. Merry  * parameter to most OS functions.
165ef270ab1SKenneth D. Merry  */
166ef270ab1SKenneth D. Merry typedef ocs_t * ocs_os_handle_t;
167ef270ab1SKenneth D. Merry 
168ef270ab1SKenneth D. Merry /**
169ef270ab1SKenneth D. Merry  * @ingroup os
170ef270ab1SKenneth D. Merry  * @brief return the lower 32-bits of a bus address
171ef270ab1SKenneth D. Merry  *
172ef270ab1SKenneth D. Merry  * @param addr Physical or bus address to convert
173ef270ab1SKenneth D. Merry  * @return lower 32-bits of a bus address
174ef270ab1SKenneth D. Merry  *
175ef270ab1SKenneth D. Merry  * @note this may be a good cadidate for an inline or macro
176ef270ab1SKenneth D. Merry  */
ocs_addr32_lo(uintptr_t addr)177ef270ab1SKenneth D. Merry static inline uint32_t ocs_addr32_lo(uintptr_t addr)
178ef270ab1SKenneth D. Merry {
179ef270ab1SKenneth D. Merry #if defined(__LP64__)
180ef270ab1SKenneth D. Merry 	return (uint32_t)(addr & 0xffffffffUL);
181ef270ab1SKenneth D. Merry #else
182ef270ab1SKenneth D. Merry 	return addr;
183ef270ab1SKenneth D. Merry #endif
184ef270ab1SKenneth D. Merry }
185ef270ab1SKenneth D. Merry 
186ef270ab1SKenneth D. Merry /**
187ef270ab1SKenneth D. Merry  * @ingroup os
188ef270ab1SKenneth D. Merry  * @brief return the upper 32-bits of a bus address
189ef270ab1SKenneth D. Merry  *
190ef270ab1SKenneth D. Merry  * @param addr Physical or bus address to convert
191ef270ab1SKenneth D. Merry  * @return upper 32-bits of a bus address
192ef270ab1SKenneth D. Merry  *
193ef270ab1SKenneth D. Merry  * @note this may be a good cadidate for an inline or macro
194ef270ab1SKenneth D. Merry  */
ocs_addr32_hi(uintptr_t addr)195ef270ab1SKenneth D. Merry static inline uint32_t ocs_addr32_hi(uintptr_t addr)
196ef270ab1SKenneth D. Merry {
197ef270ab1SKenneth D. Merry #if defined(__LP64__)
198ef270ab1SKenneth D. Merry 	return (uint32_t)(addr >> 32);
199ef270ab1SKenneth D. Merry #else
200ef270ab1SKenneth D. Merry 	return 0;
201ef270ab1SKenneth D. Merry #endif
202ef270ab1SKenneth D. Merry }
203ef270ab1SKenneth D. Merry 
204ef270ab1SKenneth D. Merry /**
205ef270ab1SKenneth D. Merry  * @ingroup os
206ef270ab1SKenneth D. Merry  * @brief return the log2(val)
207ef270ab1SKenneth D. Merry  *
208ef270ab1SKenneth D. Merry  * @param val number to use (assumed to be exact power of 2)
209ef270ab1SKenneth D. Merry  *
210ef270ab1SKenneth D. Merry  * @return log base 2 of val
211ef270ab1SKenneth D. Merry  */
ocs_lg2(uint32_t val)212ef270ab1SKenneth D. Merry static inline uint32_t ocs_lg2(uint32_t val)
213ef270ab1SKenneth D. Merry {
214ef270ab1SKenneth D. Merry #if defined(__GNUC__)
215ef270ab1SKenneth D. Merry 	/*
216ef270ab1SKenneth D. Merry 	 * clz = "count leading zero's"
217ef270ab1SKenneth D. Merry 	 *
218ef270ab1SKenneth D. Merry 	 * Assuming val is an exact power of 2, the most significant bit
219ef270ab1SKenneth D. Merry 	 * will be the log base 2 of val
220ef270ab1SKenneth D. Merry 	 */
221ef270ab1SKenneth D. Merry 	return 31 - __builtin_clz(val);
222ef270ab1SKenneth D. Merry #else
223ef270ab1SKenneth D. Merry #error You need to provide a non-GCC version of this function
224ef270ab1SKenneth D. Merry #endif
225ef270ab1SKenneth D. Merry }
226ef270ab1SKenneth D. Merry 
227ef270ab1SKenneth D. Merry /**
228ef270ab1SKenneth D. Merry  * @ingroup os
229ef270ab1SKenneth D. Merry  * @brief optimization barrier
230ef270ab1SKenneth D. Merry  *
231ef270ab1SKenneth D. Merry  * Optimization barrier. Prevents compiler re-ordering
232ef270ab1SKenneth D. Merry  * instructions across barrier.
233ef270ab1SKenneth D. Merry  *
234ef270ab1SKenneth D. Merry  * @return none
235ef270ab1SKenneth D. Merry  */
236ef270ab1SKenneth D. Merry #define ocs_barrier()	 __asm __volatile("" : : : "memory");
237ef270ab1SKenneth D. Merry 
238ef270ab1SKenneth D. Merry /**
239ef270ab1SKenneth D. Merry  * @ingroup os
240ef270ab1SKenneth D. Merry  * @brief convert a big endian 32 bit value to the host's native format
241ef270ab1SKenneth D. Merry  *
242ef270ab1SKenneth D. Merry  * @param val 32 bit big endian value
243ef270ab1SKenneth D. Merry  *
244ef270ab1SKenneth D. Merry  * @return value converted to the host's native endianness
245ef270ab1SKenneth D. Merry  */
246ef270ab1SKenneth D. Merry #define ocs_be32toh(val)	be32toh(val)
247ef270ab1SKenneth D. Merry 
248ef270ab1SKenneth D. Merry /**
249ef270ab1SKenneth D. Merry  * @ingroup os
250ef270ab1SKenneth D. Merry  * @brief convert a 32 bit value from the host's native format to big endian
251ef270ab1SKenneth D. Merry  *
252ef270ab1SKenneth D. Merry  * @param val 32 bit native endian value
253ef270ab1SKenneth D. Merry  *
254ef270ab1SKenneth D. Merry  * @return value converted to big endian
255ef270ab1SKenneth D. Merry  */
256ef270ab1SKenneth D. Merry #define ocs_htobe32(val)	htobe32(val)
257ef270ab1SKenneth D. Merry 
258ef270ab1SKenneth D. Merry /**
259ef270ab1SKenneth D. Merry  * @ingroup os
260ef270ab1SKenneth D. Merry  * @brief convert a 16 bit value from the host's native format to big endian
261ef270ab1SKenneth D. Merry  *
262ef270ab1SKenneth D. Merry  * @param v 16 bit native endian value
263ef270ab1SKenneth D. Merry  *
264ef270ab1SKenneth D. Merry  * @return value converted to big endian
265ef270ab1SKenneth D. Merry  */
266ef270ab1SKenneth D. Merry #define ocs_htobe16(v)	htobe16(v)
267ef270ab1SKenneth D. Merry #define ocs_be16toh(v)	be16toh(v)
268ef270ab1SKenneth D. Merry 
269ef270ab1SKenneth D. Merry #define ocs_htobe64(v)	htobe64(v)
270ef270ab1SKenneth D. Merry #define ocs_be64toh(v)	be64toh(v)
271ef270ab1SKenneth D. Merry 
272ef270ab1SKenneth D. Merry /**
273ef270ab1SKenneth D. Merry  * @ingroup os
274ef270ab1SKenneth D. Merry  * @brief Delay execution by the given number of micro-seconds
275ef270ab1SKenneth D. Merry  *
276ef270ab1SKenneth D. Merry  * @param usec number of micro-seconds to "busy-wait"
277ef270ab1SKenneth D. Merry  *
278ef270ab1SKenneth D. Merry  * @note The value of usec may be greater than 1,000,000
279ef270ab1SKenneth D. Merry  */
280ef270ab1SKenneth D. Merry #define ocs_udelay(usec) DELAY(usec)
281ef270ab1SKenneth D. Merry 
282ef270ab1SKenneth D. Merry /**
283ef270ab1SKenneth D. Merry  * @ingroup os
284ef270ab1SKenneth D. Merry  * @brief Delay execution by the given number of milli-seconds
285ef270ab1SKenneth D. Merry  *
286ef270ab1SKenneth D. Merry  * @param msec number of milli-seconds to "busy-wait"
287ef270ab1SKenneth D. Merry  *
288ef270ab1SKenneth D. Merry  * @note The value of usec may be greater than 1,000,000
289ef270ab1SKenneth D. Merry  */
290ef270ab1SKenneth D. Merry #define ocs_msleep(msec) ocs_udelay((msec)*1000)
291ef270ab1SKenneth D. Merry 
292ef270ab1SKenneth D. Merry /**
293ef270ab1SKenneth D. Merry  * @ingroup os
294ef270ab1SKenneth D. Merry  * @brief Get time of day in msec
295ef270ab1SKenneth D. Merry  *
296ef270ab1SKenneth D. Merry  * @return time of day in msec
297ef270ab1SKenneth D. Merry  */
298ef270ab1SKenneth D. Merry static inline time_t
ocs_msectime(void)299ef270ab1SKenneth D. Merry ocs_msectime(void)
300ef270ab1SKenneth D. Merry {
301ef270ab1SKenneth D. Merry 	struct timeval tv;
302ef270ab1SKenneth D. Merry 
303ef270ab1SKenneth D. Merry 	getmicrotime(&tv);
304ef270ab1SKenneth D. Merry 	return (tv.tv_sec*1000) + (tv.tv_usec / 1000);
305ef270ab1SKenneth D. Merry }
306ef270ab1SKenneth D. Merry 
307ef270ab1SKenneth D. Merry /**
308ef270ab1SKenneth D. Merry  * @ingroup os
309ef270ab1SKenneth D. Merry  * @brief Copy length number of bytes from the source to destination address
310ef270ab1SKenneth D. Merry  *
311ef270ab1SKenneth D. Merry  * @param d pointer to the destination memory
312ef270ab1SKenneth D. Merry  * @param s pointer to the source memory
313ef270ab1SKenneth D. Merry  * @param l number of bytes to copy
314ef270ab1SKenneth D. Merry  *
315ef270ab1SKenneth D. Merry  * @return original value of dst pointer
316ef270ab1SKenneth D. Merry  */
317ef270ab1SKenneth D. Merry #define ocs_memcpy(d, s, l)		memcpy(d, s, l)
318ef270ab1SKenneth D. Merry 
319ef270ab1SKenneth D. Merry #define ocs_strlen(s)			strlen(s)
320ef270ab1SKenneth D. Merry #define ocs_strcpy(d,s)			strcpy(d, s)
321ef270ab1SKenneth D. Merry #define ocs_strncpy(d,s, n)		strncpy(d, s, n)
322ef270ab1SKenneth D. Merry #define ocs_strcat(d, s)		strcat(d, s)
323ef270ab1SKenneth D. Merry #define ocs_strtoul(s,ep,b)		strtoul(s,ep,b)
324ef270ab1SKenneth D. Merry #define ocs_strtoull(s,ep,b)		((uint64_t)strtouq(s,ep,b))
325ef270ab1SKenneth D. Merry #define ocs_atoi(s)			strtol(s, 0, 0)
326ef270ab1SKenneth D. Merry #define ocs_strcmp(d,s)			strcmp(d,s)
327ef270ab1SKenneth D. Merry #define ocs_strcasecmp(d,s)		strcasecmp(d,s)
328ef270ab1SKenneth D. Merry #define ocs_strncmp(d,s,n)		strncmp(d,s,n)
329ef270ab1SKenneth D. Merry #define ocs_strstr(h,n)			strstr(h,n)
330ef270ab1SKenneth D. Merry #define ocs_strsep(h, n)		strsep(h, n)
331ef270ab1SKenneth D. Merry #define ocs_strchr(s,c)			strchr(s,c)
332ef270ab1SKenneth D. Merry #define ocs_copy_from_user(dst, src, n)	copyin(src, dst, n)
333ef270ab1SKenneth D. Merry #define ocs_copy_to_user(dst, src, n)	copyout(src, dst, n)
334ef270ab1SKenneth D. Merry #define ocs_snprintf(buf, n, fmt, ...)	snprintf(buf, n, fmt, ##__VA_ARGS__)
335ef270ab1SKenneth D. Merry #define ocs_vsnprintf(buf, n, fmt, ap)	vsnprintf((char*)buf, n, fmt, ap)
336ef270ab1SKenneth D. Merry #define ocs_sscanf(buf,fmt, ...)	sscanf(buf, fmt, ##__VA_ARGS__)
337ef270ab1SKenneth D. Merry #define ocs_printf			printf
338ef270ab1SKenneth D. Merry #define ocs_isspace(c)			isspace(c)
339ef270ab1SKenneth D. Merry #define ocs_isdigit(c)			isdigit(c)
340ef270ab1SKenneth D. Merry #define ocs_isxdigit(c)			isxdigit(c)
341ef270ab1SKenneth D. Merry 
342ef270ab1SKenneth D. Merry extern uint64_t ocs_get_tsc(void);
343ef270ab1SKenneth D. Merry extern void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size);
344ef270ab1SKenneth D. Merry extern int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size);
345ef270ab1SKenneth D. Merry extern void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size);
346ef270ab1SKenneth D. Merry extern char *ocs_strdup(const char *s);
347ef270ab1SKenneth D. Merry 
348ef270ab1SKenneth D. Merry /**
349ef270ab1SKenneth D. Merry  * @ingroup os
350ef270ab1SKenneth D. Merry  * @brief Set the value of each byte in memory
351ef270ab1SKenneth D. Merry  *
352ef270ab1SKenneth D. Merry  * @param b pointer to the memory
353ef270ab1SKenneth D. Merry  * @param c value used to set memory
354ef270ab1SKenneth D. Merry  * @param l number of bytes to set
355ef270ab1SKenneth D. Merry  *
356ef270ab1SKenneth D. Merry  * @return original value of mem pointer
357ef270ab1SKenneth D. Merry  */
358ef270ab1SKenneth D. Merry #define ocs_memset(b, c, l) memset(b, c, l)
359ef270ab1SKenneth D. Merry 
360ef270ab1SKenneth D. Merry #define LOG_CRIT	0
361ef270ab1SKenneth D. Merry #define LOG_ERR		1
362ef270ab1SKenneth D. Merry #define LOG_WARN	2
363ef270ab1SKenneth D. Merry #define LOG_INFO	3
364ef270ab1SKenneth D. Merry #define LOG_TEST	4
365ef270ab1SKenneth D. Merry #define LOG_DEBUG	5
366ef270ab1SKenneth D. Merry 
367ef270ab1SKenneth D. Merry extern int loglevel;
368ef270ab1SKenneth D. Merry 
369ef270ab1SKenneth D. Merry extern void _ocs_log(ocs_t *ocs, const char *func, int line, const char *fmt, ...);
370ef270ab1SKenneth D. Merry 
371ef270ab1SKenneth D. Merry #define ocs_log_crit(os, fmt, ...)	ocs_log(os, LOG_CRIT, fmt, ##__VA_ARGS__);
372ef270ab1SKenneth D. Merry #define ocs_log_err(os, fmt, ...)	ocs_log(os, LOG_ERR, fmt, ##__VA_ARGS__);
373ef270ab1SKenneth D. Merry #define ocs_log_warn(os, fmt, ...)	ocs_log(os, LOG_WARN, fmt, ##__VA_ARGS__);
374ef270ab1SKenneth D. Merry #define ocs_log_info(os, fmt, ...)	ocs_log(os, LOG_INFO, fmt, ##__VA_ARGS__);
375ef270ab1SKenneth D. Merry #define ocs_log_test(os, fmt, ...)	ocs_log(os, LOG_TEST, fmt, ##__VA_ARGS__);
376ef270ab1SKenneth D. Merry #define ocs_log_debug(os, fmt, ...)	ocs_log(os, LOG_DEBUG, fmt, ##__VA_ARGS__);
377ef270ab1SKenneth D. Merry 
378ef270ab1SKenneth D. Merry #define ocs_log(os, level, fmt, ...)                    \
379ef270ab1SKenneth D. Merry 	do {                                            \
380ef270ab1SKenneth D. Merry 		if (level <= loglevel) {                \
381ef270ab1SKenneth D. Merry 			_ocs_log(os, __func__, __LINE__, fmt, ##__VA_ARGS__);   \
382ef270ab1SKenneth D. Merry 		}                                       \
383ef270ab1SKenneth D. Merry 	} while (0)
384ef270ab1SKenneth D. Merry 
ocs_roundup(uint32_t x,uint32_t y)385ef270ab1SKenneth D. Merry static inline uint32_t ocs_roundup(uint32_t x, uint32_t y)
386ef270ab1SKenneth D. Merry {
387ef270ab1SKenneth D. Merry 	return (((x + y - 1) / y) * y);
388ef270ab1SKenneth D. Merry }
389ef270ab1SKenneth D. Merry 
ocs_rounddown(uint32_t x,uint32_t y)390ef270ab1SKenneth D. Merry static inline uint32_t ocs_rounddown(uint32_t x, uint32_t y)
391ef270ab1SKenneth D. Merry {
392ef270ab1SKenneth D. Merry 	return ((x / y) * y);
393ef270ab1SKenneth D. Merry }
394ef270ab1SKenneth D. Merry 
395ef270ab1SKenneth D. Merry /***************************************************************************
396ef270ab1SKenneth D. Merry  * Memory allocation interfaces
397ef270ab1SKenneth D. Merry  */
398ef270ab1SKenneth D. Merry 
399ef270ab1SKenneth D. Merry #define OCS_M_ZERO	M_ZERO
400ef270ab1SKenneth D. Merry #define OCS_M_NOWAIT	M_NOWAIT
401ef270ab1SKenneth D. Merry 
402ef270ab1SKenneth D. Merry /**
403ef270ab1SKenneth D. Merry  * @ingroup os
404ef270ab1SKenneth D. Merry  * @brief Allocate host memory
405ef270ab1SKenneth D. Merry  *
406ef270ab1SKenneth D. Merry  * @param os OS handle
407ef270ab1SKenneth D. Merry  * @param size number of bytes to allocate
408ef270ab1SKenneth D. Merry  * @param flags additional options
409ef270ab1SKenneth D. Merry  *
410ef270ab1SKenneth D. Merry  * Flags include
411ef270ab1SKenneth D. Merry  *  - OCS_M_ZERO zero memory after allocating
412ef270ab1SKenneth D. Merry  *  - OCS_M_NOWAIT do not block/sleep waiting for an allocation request
413ef270ab1SKenneth D. Merry  *
414ef270ab1SKenneth D. Merry  * @return pointer to allocated memory, NULL otherwise
415ef270ab1SKenneth D. Merry  */
416ef270ab1SKenneth D. Merry extern void *ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags);
417ef270ab1SKenneth D. Merry 
418ef270ab1SKenneth D. Merry /**
419ef270ab1SKenneth D. Merry  * @ingroup os
420ef270ab1SKenneth D. Merry  * @brief Free host memory
421ef270ab1SKenneth D. Merry  *
422ef270ab1SKenneth D. Merry  * @param os OS handle
423ef270ab1SKenneth D. Merry  * @param addr pointer to memory
424ef270ab1SKenneth D. Merry  * @param size bytes to free
425ef270ab1SKenneth D. Merry  */
426ef270ab1SKenneth D. Merry extern void ocs_free(ocs_os_handle_t os, void *addr, size_t size);
427ef270ab1SKenneth D. Merry 
428ef270ab1SKenneth D. Merry /**
429ef270ab1SKenneth D. Merry  * @ingroup os
430ef270ab1SKenneth D. Merry  * @brief generic DMA memory descriptor for driver allocations
431ef270ab1SKenneth D. Merry  *
432ef270ab1SKenneth D. Merry  * Memory regions ultimately used by the hardware are described using
433ef270ab1SKenneth D. Merry  * this structure. All implementations must include the structure members
434ef270ab1SKenneth D. Merry  * defined in the first section, and they may also add their own structure
435ef270ab1SKenneth D. Merry  * members in the second section.
436ef270ab1SKenneth D. Merry  *
437ef270ab1SKenneth D. Merry  * Note that each region described by ocs_dma_s is assumed to be physically
438ef270ab1SKenneth D. Merry  * contiguous.
439ef270ab1SKenneth D. Merry  */
440ef270ab1SKenneth D. Merry typedef struct ocs_dma_s {
441ef270ab1SKenneth D. Merry 	/*
442ef270ab1SKenneth D. Merry 	 * OCS layer requires the following members
443ef270ab1SKenneth D. Merry 	 */
444ef270ab1SKenneth D. Merry 	void		*virt;	/**< virtual address of the memory used by the CPU */
445ef270ab1SKenneth D. Merry 	void		*alloc;	/**< originally allocated virtual address used to restore virt if modified */
446ef270ab1SKenneth D. Merry 	uintptr_t	phys;	/**< physical or bus address of the memory used by the hardware */
447ef270ab1SKenneth D. Merry 	size_t		size;	/**< size in bytes of the memory */
448ef270ab1SKenneth D. Merry 	/*
449ef270ab1SKenneth D. Merry 	 * Implementation specific fields allowed here
450ef270ab1SKenneth D. Merry 	 */
451ef270ab1SKenneth D. Merry 	size_t		len;	/**< application specific length */
452ef270ab1SKenneth D. Merry 	bus_dma_tag_t	tag;
453ef270ab1SKenneth D. Merry 	bus_dmamap_t	map;
454ef270ab1SKenneth D. Merry } ocs_dma_t;
455ef270ab1SKenneth D. Merry 
456ef270ab1SKenneth D. Merry /**
457ef270ab1SKenneth D. Merry  * @ingroup os
458ef270ab1SKenneth D. Merry  * @brief Returns maximum supported DMA allocation size
459ef270ab1SKenneth D. Merry  *
460ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
461ef270ab1SKenneth D. Merry  * @param align alignment requirement for DMA allocation
462ef270ab1SKenneth D. Merry  *
463ef270ab1SKenneth D. Merry  * Return maximum supported DMA allocation size, given alignment
464ef270ab1SKenneth D. Merry  * requirement.
465ef270ab1SKenneth D. Merry  *
4667b56cb04SGordon Bergling  * @return maximum supported DMA allocation size
467ef270ab1SKenneth D. Merry  */
ocs_max_dma_alloc(ocs_os_handle_t os,size_t align)468ef270ab1SKenneth D. Merry static inline uint32_t ocs_max_dma_alloc(ocs_os_handle_t os, size_t align)
469ef270ab1SKenneth D. Merry {
470ef270ab1SKenneth D. Merry 	return ~((uint32_t)0); /* no max */
471ef270ab1SKenneth D. Merry }
472ef270ab1SKenneth D. Merry 
473ef270ab1SKenneth D. Merry /**
474ef270ab1SKenneth D. Merry  * @ingroup os
475ef270ab1SKenneth D. Merry  * @brief Allocate a DMA capable block of memory
476ef270ab1SKenneth D. Merry  *
477ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
478ef270ab1SKenneth D. Merry  * @param dma DMA descriptor containing results of memory allocation
479ef270ab1SKenneth D. Merry  * @param size Size in bytes of desired allocation
480ef270ab1SKenneth D. Merry  * @param align Alignment in bytes of the requested allocation
481ef270ab1SKenneth D. Merry  *
482ef270ab1SKenneth D. Merry  * @return 0 on success, non-zero otherwise
483ef270ab1SKenneth D. Merry  */
484ef270ab1SKenneth D. Merry extern int32_t ocs_dma_alloc(ocs_os_handle_t, ocs_dma_t *, size_t, size_t);
485ef270ab1SKenneth D. Merry 
486ef270ab1SKenneth D. Merry /**
487ef270ab1SKenneth D. Merry  * @ingroup os
488ef270ab1SKenneth D. Merry  * @brief Free a DMA capable block of memory
489ef270ab1SKenneth D. Merry  *
490ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
491ef270ab1SKenneth D. Merry  * @param dma DMA descriptor for memory to be freed
492ef270ab1SKenneth D. Merry  *
493ef270ab1SKenneth D. Merry  * @return 0 if memory is de-allocated, non-zero otherwise
494ef270ab1SKenneth D. Merry  */
495ef270ab1SKenneth D. Merry extern int32_t ocs_dma_free(ocs_os_handle_t, ocs_dma_t *);
496ef270ab1SKenneth D. Merry extern int32_t ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length);
497ef270ab1SKenneth D. Merry extern int32_t ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length);
498ef270ab1SKenneth D. Merry 
ocs_dma_valid(ocs_dma_t * dma)499ef270ab1SKenneth D. Merry static inline int32_t ocs_dma_valid(ocs_dma_t *dma)
500ef270ab1SKenneth D. Merry {
501ef270ab1SKenneth D. Merry 	return (dma->size != 0);
502ef270ab1SKenneth D. Merry }
503ef270ab1SKenneth D. Merry 
504ef270ab1SKenneth D. Merry /**
505ef270ab1SKenneth D. Merry  * @ingroup os
506ef270ab1SKenneth D. Merry  * @brief Synchronize the DMA buffer memory
507ef270ab1SKenneth D. Merry  *
508ef270ab1SKenneth D. Merry  * Ensures memory coherency between the CPU and device
509ef270ab1SKenneth D. Merry  *
510ef270ab1SKenneth D. Merry  * @param dma DMA descriptor of memory to synchronize
511ef270ab1SKenneth D. Merry  * @param flags Describes direction of synchronization
512ef270ab1SKenneth D. Merry  *   - OCS_DMASYNC_PREREAD sync needed before hardware updates host memory
513ef270ab1SKenneth D. Merry  *   - OCS_DMASYNC_PREWRITE sync needed after CPU updates host memory but before hardware can access
514ef270ab1SKenneth D. Merry  *   - OCS_DMASYNC_POSTREAD sync needed after hardware updates host memory but before CPU can access
515ef270ab1SKenneth D. Merry  *   - OCS_DMASYNC_POSTWRITE sync needed after hardware updates host memory
516ef270ab1SKenneth D. Merry  */
517ef270ab1SKenneth D. Merry extern void ocs_dma_sync(ocs_dma_t *, uint32_t);
518ef270ab1SKenneth D. Merry 
519ef270ab1SKenneth D. Merry #define OCS_DMASYNC_PREWRITE BUS_DMASYNC_PREWRITE
520ef270ab1SKenneth D. Merry #define OCS_DMASYNC_POSTREAD BUS_DMASYNC_POSTREAD
521ef270ab1SKenneth D. Merry 
522ef270ab1SKenneth D. Merry /***************************************************************************
523ef270ab1SKenneth D. Merry  * Locking
524ef270ab1SKenneth D. Merry  */
525ef270ab1SKenneth D. Merry 
526ef270ab1SKenneth D. Merry /**
527ef270ab1SKenneth D. Merry  * @ingroup os
528ef270ab1SKenneth D. Merry  * @typedef ocs_lock_t
529ef270ab1SKenneth D. Merry  * @brief Define the type used implement locking
530ef270ab1SKenneth D. Merry  */
531ef270ab1SKenneth D. Merry #define MAX_LOCK_DESC_LEN	64
532ef270ab1SKenneth D. Merry typedef struct ocs_lock_s {
533ef270ab1SKenneth D. Merry 	struct	mtx lock;
534ef270ab1SKenneth D. Merry 	char	name[MAX_LOCK_DESC_LEN];
535ef270ab1SKenneth D. Merry } ocs_lock_t;
536ef270ab1SKenneth D. Merry 
537ef270ab1SKenneth D. Merry /**
538ef270ab1SKenneth D. Merry  * @ingroup os
539ef270ab1SKenneth D. Merry  * @brief Initialize a lock
540ef270ab1SKenneth D. Merry  *
541ef270ab1SKenneth D. Merry  * @param lock lock to initialize
542ef270ab1SKenneth D. Merry  * @param name string identifier for the lock
543ef270ab1SKenneth D. Merry  */
544ef270ab1SKenneth D. Merry extern void ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...);
545ef270ab1SKenneth D. Merry 
546ef270ab1SKenneth D. Merry /**
547ef270ab1SKenneth D. Merry  * @ingroup os
548ef270ab1SKenneth D. Merry  * @brief Free a previously allocated lock
549ef270ab1SKenneth D. Merry  *
550ef270ab1SKenneth D. Merry  * @param lock lock to free
551ef270ab1SKenneth D. Merry  */
552ef270ab1SKenneth D. Merry static inline void
ocs_lock_free(ocs_lock_t * lock)553ef270ab1SKenneth D. Merry ocs_lock_free(ocs_lock_t *lock)
554ef270ab1SKenneth D. Merry {
555ef270ab1SKenneth D. Merry 
556ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
557ef270ab1SKenneth D. Merry 		mtx_assert(&(lock)->lock, MA_NOTOWNED);
558ef270ab1SKenneth D. Merry 		mtx_destroy(&(lock)->lock);
559ef270ab1SKenneth D. Merry 	} else {
560ef270ab1SKenneth D. Merry 		panic("XXX trying to free with un-initialized mtx!?!?\n");
561ef270ab1SKenneth D. Merry 	}
562ef270ab1SKenneth D. Merry }
563ef270ab1SKenneth D. Merry 
564ef270ab1SKenneth D. Merry /**
565ef270ab1SKenneth D. Merry  * @ingroup os
566ef270ab1SKenneth D. Merry  * @brief Acquire a lock
567ef270ab1SKenneth D. Merry  *
568ef270ab1SKenneth D. Merry  * @param lock lock to obtain
569ef270ab1SKenneth D. Merry  */
570ef270ab1SKenneth D. Merry static inline void
ocs_lock(ocs_lock_t * lock)571ef270ab1SKenneth D. Merry ocs_lock(ocs_lock_t *lock)
572ef270ab1SKenneth D. Merry {
573ef270ab1SKenneth D. Merry 
574ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
575ef270ab1SKenneth D. Merry 		mtx_assert(&(lock)->lock, MA_NOTOWNED);
576ef270ab1SKenneth D. Merry 		mtx_lock(&(lock)->lock);
577ef270ab1SKenneth D. Merry 	} else {
578ef270ab1SKenneth D. Merry 		panic("XXX trying to lock with un-initialized mtx!?!?\n");
579ef270ab1SKenneth D. Merry 	}
580ef270ab1SKenneth D. Merry }
581ef270ab1SKenneth D. Merry 
582ef270ab1SKenneth D. Merry /**
583ef270ab1SKenneth D. Merry  * @ingroup os
584ef270ab1SKenneth D. Merry  * @brief Release a lock
585ef270ab1SKenneth D. Merry  *
586ef270ab1SKenneth D. Merry  * @param lock lock to release
587ef270ab1SKenneth D. Merry  */
588ef270ab1SKenneth D. Merry static inline void
ocs_unlock(ocs_lock_t * lock)589ef270ab1SKenneth D. Merry ocs_unlock(ocs_lock_t *lock)
590ef270ab1SKenneth D. Merry {
591ef270ab1SKenneth D. Merry 
592ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
593ef270ab1SKenneth D. Merry 		mtx_assert(&(lock)->lock, MA_OWNED | MA_NOTRECURSED);
594ef270ab1SKenneth D. Merry 		mtx_unlock(&(lock)->lock);
595ef270ab1SKenneth D. Merry 	} else {
596ef270ab1SKenneth D. Merry 		panic("XXX trying to unlock with un-initialized mtx!?!?\n");
597ef270ab1SKenneth D. Merry 	}
598ef270ab1SKenneth D. Merry }
599ef270ab1SKenneth D. Merry 
600ef270ab1SKenneth D. Merry /**
601ef270ab1SKenneth D. Merry  * @ingroup os
602ef270ab1SKenneth D. Merry  * @typedef ocs_lock_t
603ef270ab1SKenneth D. Merry  * @brief Define the type used implement recursive locking
604ef270ab1SKenneth D. Merry  */
605ef270ab1SKenneth D. Merry typedef struct ocs_lock_s ocs_rlock_t;
606ef270ab1SKenneth D. Merry 
607ef270ab1SKenneth D. Merry /**
608ef270ab1SKenneth D. Merry  * @ingroup os
609ef270ab1SKenneth D. Merry  * @brief Initialize a recursive lock
610ef270ab1SKenneth D. Merry  *
611ef270ab1SKenneth D. Merry  * @param ocs pointer to ocs structure
612ef270ab1SKenneth D. Merry  * @param lock lock to initialize
613ef270ab1SKenneth D. Merry  * @param name string identifier for the lock
614ef270ab1SKenneth D. Merry  */
615ef270ab1SKenneth D. Merry static inline void
ocs_rlock_init(ocs_t * ocs,ocs_rlock_t * lock,const char * name)616ef270ab1SKenneth D. Merry ocs_rlock_init(ocs_t *ocs, ocs_rlock_t *lock, const char *name)
617ef270ab1SKenneth D. Merry {
618ef270ab1SKenneth D. Merry 	ocs_strncpy(lock->name, name, MAX_LOCK_DESC_LEN);
619ef270ab1SKenneth D. Merry 	mtx_init(&(lock)->lock, lock->name, NULL, MTX_DEF | MTX_RECURSE | MTX_DUPOK);
620ef270ab1SKenneth D. Merry }
621ef270ab1SKenneth D. Merry 
622ef270ab1SKenneth D. Merry /**
623ef270ab1SKenneth D. Merry  * @ingroup os
624ef270ab1SKenneth D. Merry  * @brief Free a previously allocated recursive lock
625ef270ab1SKenneth D. Merry  *
626ef270ab1SKenneth D. Merry  * @param lock lock to free
627ef270ab1SKenneth D. Merry  */
628ef270ab1SKenneth D. Merry static inline void
ocs_rlock_free(ocs_rlock_t * lock)629ef270ab1SKenneth D. Merry ocs_rlock_free(ocs_rlock_t *lock)
630ef270ab1SKenneth D. Merry {
631ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
632ef270ab1SKenneth D. Merry 		mtx_destroy(&(lock)->lock);
633ef270ab1SKenneth D. Merry 	} else {
634ef270ab1SKenneth D. Merry 		panic("XXX trying to free with un-initialized mtx!?!?\n");
635ef270ab1SKenneth D. Merry 	}
636ef270ab1SKenneth D. Merry }
637ef270ab1SKenneth D. Merry 
638ef270ab1SKenneth D. Merry /**
639ef270ab1SKenneth D. Merry  * @brief try to acquire a recursive lock
640ef270ab1SKenneth D. Merry  *
641ef270ab1SKenneth D. Merry  * Attempt to acquire a recursive lock, return TRUE if successful
642ef270ab1SKenneth D. Merry  *
643ef270ab1SKenneth D. Merry  * @param lock pointer to recursive lock
644ef270ab1SKenneth D. Merry  *
645ef270ab1SKenneth D. Merry  * @return TRUE if lock was acquired, FALSE if not
646ef270ab1SKenneth D. Merry  */
647ef270ab1SKenneth D. Merry static inline int32_t
ocs_rlock_try(ocs_rlock_t * lock)648ef270ab1SKenneth D. Merry ocs_rlock_try(ocs_rlock_t *lock)
649ef270ab1SKenneth D. Merry {
650ef270ab1SKenneth D. Merry 	int rc = mtx_trylock(&(lock)->lock);
651ef270ab1SKenneth D. Merry 
652ef270ab1SKenneth D. Merry 	return rc != 0;
653ef270ab1SKenneth D. Merry }
654ef270ab1SKenneth D. Merry 
655ef270ab1SKenneth D. Merry /**
656ef270ab1SKenneth D. Merry  * @ingroup os
657ef270ab1SKenneth D. Merry  * @brief Acquire a recursive lock
658ef270ab1SKenneth D. Merry  *
659ef270ab1SKenneth D. Merry  * @param lock lock to obtain
660ef270ab1SKenneth D. Merry  */
661ef270ab1SKenneth D. Merry static inline void
ocs_rlock_acquire(ocs_rlock_t * lock)662ef270ab1SKenneth D. Merry ocs_rlock_acquire(ocs_rlock_t *lock)
663ef270ab1SKenneth D. Merry {
664ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
665ef270ab1SKenneth D. Merry 		mtx_lock(&(lock)->lock);
666ef270ab1SKenneth D. Merry 	} else {
667ef270ab1SKenneth D. Merry 		panic("XXX trying to lock with un-initialized mtx!?!?\n");
668ef270ab1SKenneth D. Merry 	}
669ef270ab1SKenneth D. Merry }
670ef270ab1SKenneth D. Merry 
671ef270ab1SKenneth D. Merry /**
672ef270ab1SKenneth D. Merry  * @ingroup os
673ef270ab1SKenneth D. Merry  * @brief Release a recursive lock
674ef270ab1SKenneth D. Merry  *
675ef270ab1SKenneth D. Merry  * @param lock lock to release
676ef270ab1SKenneth D. Merry  */
677ef270ab1SKenneth D. Merry static inline void
ocs_rlock_release(ocs_rlock_t * lock)678ef270ab1SKenneth D. Merry ocs_rlock_release(ocs_rlock_t *lock)
679ef270ab1SKenneth D. Merry {
680ef270ab1SKenneth D. Merry 	if (mtx_initialized(&(lock)->lock)) {
681ef270ab1SKenneth D. Merry 		mtx_assert(&(lock)->lock, MA_OWNED);
682ef270ab1SKenneth D. Merry 		mtx_unlock(&(lock)->lock);
683ef270ab1SKenneth D. Merry 	} else {
684ef270ab1SKenneth D. Merry 		panic("XXX trying to unlock with un-initialized mtx!?!?\n");
685ef270ab1SKenneth D. Merry 	}
686ef270ab1SKenneth D. Merry }
687ef270ab1SKenneth D. Merry 
688ef270ab1SKenneth D. Merry /**
689ef270ab1SKenneth D. Merry  * @brief counting semaphore
690ef270ab1SKenneth D. Merry  *
691ef270ab1SKenneth D. Merry  * Declaration of the counting semaphore object
692ef270ab1SKenneth D. Merry  *
693ef270ab1SKenneth D. Merry  */
694ef270ab1SKenneth D. Merry typedef struct {
695ef270ab1SKenneth D. Merry 	char name[32];
696ef270ab1SKenneth D. Merry 	struct sema sem;		/**< OS counting semaphore structure */
697ef270ab1SKenneth D. Merry } ocs_sem_t;
698ef270ab1SKenneth D. Merry 
699ef270ab1SKenneth D. Merry #define OCS_SEM_FOREVER		(-1)
700ef270ab1SKenneth D. Merry #define OCS_SEM_TRY		(0)
701ef270ab1SKenneth D. Merry 
702ef270ab1SKenneth D. Merry /**
703ef270ab1SKenneth D. Merry  * @brief Initialize a counting semaphore
704ef270ab1SKenneth D. Merry  *
705ef270ab1SKenneth D. Merry  * The semaphore is initiatlized to the value
706ef270ab1SKenneth D. Merry  *
707ef270ab1SKenneth D. Merry  * @param sem pointer to semaphore
708ef270ab1SKenneth D. Merry  * @param val initial value
709ef270ab1SKenneth D. Merry  * @param name label for the semaphore
710ef270ab1SKenneth D. Merry  *
711ef270ab1SKenneth D. Merry  * @return returns 0 for success, a negative error code value for failure.
712ef270ab1SKenneth D. Merry  */
713ef270ab1SKenneth D. Merry 
714ef270ab1SKenneth D. Merry extern int ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...) __attribute__((format(printf, 3, 4)));
715ef270ab1SKenneth D. Merry 
716ef270ab1SKenneth D. Merry /**
717ef270ab1SKenneth D. Merry  * @brief execute a P (decrement) operation
718ef270ab1SKenneth D. Merry  *
719ef270ab1SKenneth D. Merry  * A P (decrement and block if negative) operation is performed on the semaphore.
720ef270ab1SKenneth D. Merry  *
721ef270ab1SKenneth D. Merry  * If timeout_usec is zero, the semaphore attempts one time and returns 0 if acquired.
722ef270ab1SKenneth D. Merry  * If timeout_usec is greater than zero, then the call will block until the semaphore
723ef270ab1SKenneth D. Merry  * is acquired, or a timeout occurred.  If timeout_usec is less than zero, then
724ef270ab1SKenneth D. Merry  * the call will block until the semaphore is acquired.
725ef270ab1SKenneth D. Merry  *
726ef270ab1SKenneth D. Merry  * @param sem pointer to semaphore
727ef270ab1SKenneth D. Merry  * @param timeout_usec timeout in microseconds
728ef270ab1SKenneth D. Merry  *
729ef270ab1SKenneth D. Merry  * @return returns 0 for success, negative value if the semaphore was not acquired.
730ef270ab1SKenneth D. Merry  */
731ef270ab1SKenneth D. Merry 
732ef270ab1SKenneth D. Merry static inline int
ocs_sem_p(ocs_sem_t * sem,int timeout_usec)733ef270ab1SKenneth D. Merry ocs_sem_p(ocs_sem_t *sem, int timeout_usec)
734ef270ab1SKenneth D. Merry {
735ef270ab1SKenneth D. Merry 	int32_t rc = 0;
736ef270ab1SKenneth D. Merry 
737ef270ab1SKenneth D. Merry 	if (timeout_usec == 0) {
738ef270ab1SKenneth D. Merry 		rc = sema_trywait(&sem->sem);
739ef270ab1SKenneth D. Merry 		if (rc == 0) {
740ef270ab1SKenneth D. Merry 			rc = -1;
741ef270ab1SKenneth D. Merry 		}
742ef270ab1SKenneth D. Merry 	} else if (timeout_usec > 0) {
743ef270ab1SKenneth D. Merry 		struct timeval tv;
744ef270ab1SKenneth D. Merry 		uint32_t ticks;
745ef270ab1SKenneth D. Merry 
746ef270ab1SKenneth D. Merry 		tv.tv_sec = timeout_usec / 1000000;
747ef270ab1SKenneth D. Merry 		tv.tv_usec = timeout_usec % 1000000;
748ef270ab1SKenneth D. Merry 		ticks = tvtohz(&tv);
749ef270ab1SKenneth D. Merry 		if (ticks == 0) {
750ef270ab1SKenneth D. Merry 			ticks ++;
751ef270ab1SKenneth D. Merry 		}
752ef270ab1SKenneth D. Merry 		rc = sema_timedwait(&sem->sem, ticks);
753ef270ab1SKenneth D. Merry 		if (rc != 0) {
754ef270ab1SKenneth D. Merry 			rc = -1;
755ef270ab1SKenneth D. Merry 		}
756ef270ab1SKenneth D. Merry 	} else {
757ef270ab1SKenneth D. Merry 		sema_wait(&sem->sem);
758ef270ab1SKenneth D. Merry 	}
759ef270ab1SKenneth D. Merry 	if (rc)
760ef270ab1SKenneth D. Merry 		rc = -1;
761ef270ab1SKenneth D. Merry 
762ef270ab1SKenneth D. Merry 	return rc;
763ef270ab1SKenneth D. Merry }
764ef270ab1SKenneth D. Merry 
765ef270ab1SKenneth D. Merry /**
766ef270ab1SKenneth D. Merry  * @brief perform a V (increment) operation on a counting semaphore
767ef270ab1SKenneth D. Merry  *
768ef270ab1SKenneth D. Merry  * The semaphore is incremented, unblocking one thread that is waiting on the
769ef270ab1SKenneth D. Merry  * sempahore
770ef270ab1SKenneth D. Merry  *
771ef270ab1SKenneth D. Merry  * @param sem pointer to the semaphore
772ef270ab1SKenneth D. Merry  *
773ef270ab1SKenneth D. Merry  * @return none
774ef270ab1SKenneth D. Merry  */
775ef270ab1SKenneth D. Merry 
776ef270ab1SKenneth D. Merry static inline void
ocs_sem_v(ocs_sem_t * sem)777ef270ab1SKenneth D. Merry ocs_sem_v(ocs_sem_t *sem)
778ef270ab1SKenneth D. Merry {
779ef270ab1SKenneth D. Merry 	sema_post(&sem->sem);
780ef270ab1SKenneth D. Merry }
781ef270ab1SKenneth D. Merry 
782ef270ab1SKenneth D. Merry /***************************************************************************
783ef270ab1SKenneth D. Merry  * Bitmap
784ef270ab1SKenneth D. Merry  */
785ef270ab1SKenneth D. Merry 
786ef270ab1SKenneth D. Merry /**
787ef270ab1SKenneth D. Merry  * @ingroup os
788ef270ab1SKenneth D. Merry  * @typedef ocs_bitmap_t
789ef270ab1SKenneth D. Merry  * @brief Define the type used implement bit-maps
790ef270ab1SKenneth D. Merry  */
791ef270ab1SKenneth D. Merry typedef bitstr_t ocs_bitmap_t;
792ef270ab1SKenneth D. Merry 
793ef270ab1SKenneth D. Merry /**
794ef270ab1SKenneth D. Merry  * @ingroup os
795ef270ab1SKenneth D. Merry  * @brief Allocate a bitmap
796ef270ab1SKenneth D. Merry  *
797ef270ab1SKenneth D. Merry  * @param n_bits Minimum number of entries in the bit-map
798ef270ab1SKenneth D. Merry  *
799ef270ab1SKenneth D. Merry  * @return pointer to the bit-map or NULL on error
800ef270ab1SKenneth D. Merry  */
801ef270ab1SKenneth D. Merry extern ocs_bitmap_t *ocs_bitmap_alloc(uint32_t n_bits);
802ef270ab1SKenneth D. Merry 
803ef270ab1SKenneth D. Merry /**
804ef270ab1SKenneth D. Merry  * @ingroup os
805ef270ab1SKenneth D. Merry  * @brief Free a bit-map
806ef270ab1SKenneth D. Merry  *
807ef270ab1SKenneth D. Merry  * @param bitmap Bit-map to free
808ef270ab1SKenneth D. Merry  */
809ef270ab1SKenneth D. Merry extern void ocs_bitmap_free(ocs_bitmap_t *bitmap);
810ef270ab1SKenneth D. Merry 
811ef270ab1SKenneth D. Merry /**
812ef270ab1SKenneth D. Merry  * @ingroup os
813ef270ab1SKenneth D. Merry  * @brief Find next unset bit and set it
814ef270ab1SKenneth D. Merry  *
815ef270ab1SKenneth D. Merry  * @param bitmap bit map to search
816ef270ab1SKenneth D. Merry  * @param n_bits number of bits in map
817ef270ab1SKenneth D. Merry  *
818ef270ab1SKenneth D. Merry  * @return bit position or -1 if map is full
819ef270ab1SKenneth D. Merry  */
820ef270ab1SKenneth D. Merry extern int32_t ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits);
821ef270ab1SKenneth D. Merry 
822ef270ab1SKenneth D. Merry /**
823ef270ab1SKenneth D. Merry  * @ingroup os
824ef270ab1SKenneth D. Merry  * @brief search for next (un)set bit
825ef270ab1SKenneth D. Merry  *
826ef270ab1SKenneth D. Merry  * @param bitmap bit map to search
827ef270ab1SKenneth D. Merry  * @param set search for a set or unset bit
828ef270ab1SKenneth D. Merry  * @param n_bits number of bits in map
829ef270ab1SKenneth D. Merry  *
830ef270ab1SKenneth D. Merry  * @return bit position or -1
831ef270ab1SKenneth D. Merry  */
832ef270ab1SKenneth D. Merry extern int32_t ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits);
833ef270ab1SKenneth D. Merry 
834ef270ab1SKenneth D. Merry /**
835ef270ab1SKenneth D. Merry  * @ingroup os
836ef270ab1SKenneth D. Merry  * @brief clear the specified bit
837ef270ab1SKenneth D. Merry  *
838ef270ab1SKenneth D. Merry  * @param bitmap pointer to bit map
839ef270ab1SKenneth D. Merry  * @param bit bit number to clear
840ef270ab1SKenneth D. Merry  */
841ef270ab1SKenneth D. Merry extern void ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit);
842ef270ab1SKenneth D. Merry 
843ef270ab1SKenneth D. Merry extern int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len);
844ef270ab1SKenneth D. Merry 
845ef270ab1SKenneth D. Merry /***************************************************************************
846ef270ab1SKenneth D. Merry  * Timer Routines
847ef270ab1SKenneth D. Merry  *
848ef270ab1SKenneth D. Merry  * Functions for setting, querying and canceling timers.
849ef270ab1SKenneth D. Merry  */
850ef270ab1SKenneth D. Merry typedef struct {
851ef270ab1SKenneth D. Merry 	struct callout	callout;
852ef270ab1SKenneth D. Merry 	struct mtx	lock;
853ef270ab1SKenneth D. Merry 
854ef270ab1SKenneth D. Merry 	void	(*func)(void *);
855ef270ab1SKenneth D. Merry 	void	*data;
856ef270ab1SKenneth D. Merry } ocs_timer_t;
857ef270ab1SKenneth D. Merry 
858ef270ab1SKenneth D. Merry /**
859ef270ab1SKenneth D. Merry  * @ingroup os
860ef270ab1SKenneth D. Merry  * @brief Initialize and set a timer
861ef270ab1SKenneth D. Merry  *
862ef270ab1SKenneth D. Merry  * @param os OS handle
863ef270ab1SKenneth D. Merry  * @param timer    pointer to the structure allocated for this timer
864ef270ab1SKenneth D. Merry  * @param func     the function to call when the timer expires
865ef270ab1SKenneth D. Merry  * @param data     Data to pass to the provided timer function when the timer
866ef270ab1SKenneth D. Merry  *                 expires.
867ef270ab1SKenneth D. Merry  * @param timeout_ms the timeout in milliseconds
868ef270ab1SKenneth D. Merry  */
869ef270ab1SKenneth D. Merry extern int32_t ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg),
870ef270ab1SKenneth D. Merry 			       void *data, uint32_t timeout_ms);
871ef270ab1SKenneth D. Merry 
872ef270ab1SKenneth D. Merry /**
873ef270ab1SKenneth D. Merry  * @ingroup os
874ef270ab1SKenneth D. Merry  * @brief Modify a timer's expiration
875ef270ab1SKenneth D. Merry  *
876ef270ab1SKenneth D. Merry  * @param timer    pointer to the structure allocated for this timer
877ef270ab1SKenneth D. Merry  * @param timeout_ms the timeout in milliseconds
878ef270ab1SKenneth D. Merry  */
879ef270ab1SKenneth D. Merry extern int32_t ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms);
880ef270ab1SKenneth D. Merry 
881ef270ab1SKenneth D. Merry /**
882ef270ab1SKenneth D. Merry  * @ingroup os
883ef270ab1SKenneth D. Merry  * @brief Queries to see if a timer is pending.
884ef270ab1SKenneth D. Merry  *
885ef270ab1SKenneth D. Merry  * @param timer    pointer to the structure allocated for this timer
886ef270ab1SKenneth D. Merry  *
887ef270ab1SKenneth D. Merry  * @return non-zero if the timer is pending
888ef270ab1SKenneth D. Merry  */
889ef270ab1SKenneth D. Merry extern int32_t ocs_timer_pending(ocs_timer_t *timer);
890ef270ab1SKenneth D. Merry 
891ef270ab1SKenneth D. Merry /**
892ef270ab1SKenneth D. Merry  * @ingroup os
893ef270ab1SKenneth D. Merry  * @brief Remove a pending timer
894ef270ab1SKenneth D. Merry  *
895ef270ab1SKenneth D. Merry  * @param timer    pointer to the structure allocated for this timer
896ef270ab1SKenneth D. Merry  *                 expires.
897ef270ab1SKenneth D. Merry  */
898ef270ab1SKenneth D. Merry extern int32_t ocs_del_timer(ocs_timer_t *timer);
899ef270ab1SKenneth D. Merry 
900ef270ab1SKenneth D. Merry /***************************************************************************
901ef270ab1SKenneth D. Merry  * Atomics
902ef270ab1SKenneth D. Merry  *
903ef270ab1SKenneth D. Merry  */
904ef270ab1SKenneth D. Merry 
905ef270ab1SKenneth D. Merry typedef uint32_t ocs_atomic_t;
906ef270ab1SKenneth D. Merry 
907ef270ab1SKenneth D. Merry /**
908ef270ab1SKenneth D. Merry  * @ingroup os
909ef270ab1SKenneth D. Merry  * @brief initialize an atomic
910ef270ab1SKenneth D. Merry  *
911ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
912ef270ab1SKenneth D. Merry  * @param v    initial value
913ef270ab1SKenneth D. Merry  *
914ef270ab1SKenneth D. Merry  * @return none
915ef270ab1SKenneth D. Merry  */
916ef270ab1SKenneth D. Merry #define ocs_atomic_init(a, v)	ocs_atomic_set(a, v)
917ef270ab1SKenneth D. Merry 
918ef270ab1SKenneth D. Merry /**
919ef270ab1SKenneth D. Merry  * @ingroup os
920ef270ab1SKenneth D. Merry  * @brief adds an integer to an atomic value
921ef270ab1SKenneth D. Merry  *
922ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
923ef270ab1SKenneth D. Merry  * @param v    value to increment
924ef270ab1SKenneth D. Merry  *
925ef270ab1SKenneth D. Merry  * @return the value of the atomic before incrementing.
926ef270ab1SKenneth D. Merry  */
927ef270ab1SKenneth D. Merry #define ocs_atomic_add_return(a, v)	atomic_fetchadd_32(a, v)
928ef270ab1SKenneth D. Merry 
929ef270ab1SKenneth D. Merry /**
930ef270ab1SKenneth D. Merry  * @ingroup os
931ef270ab1SKenneth D. Merry  * @brief subtracts an integer to an atomic value
932ef270ab1SKenneth D. Merry  *
933ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
934ef270ab1SKenneth D. Merry  * @param v    value to increment
935ef270ab1SKenneth D. Merry  *
936ef270ab1SKenneth D. Merry  * @return the value of the atomic before subtracting.
937ef270ab1SKenneth D. Merry  */
938ef270ab1SKenneth D. Merry #define ocs_atomic_sub_return(a, v)     atomic_fetchadd_32(a, (-(v)))
939ef270ab1SKenneth D. Merry 
940ef270ab1SKenneth D. Merry /**
941ef270ab1SKenneth D. Merry  * @ingroup os
942ef270ab1SKenneth D. Merry  * @brief returns the current value of an atomic object
943ef270ab1SKenneth D. Merry  *
944ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
945ef270ab1SKenneth D. Merry  *
946ef270ab1SKenneth D. Merry  * @return the value of the atomic.
947ef270ab1SKenneth D. Merry  */
948ef270ab1SKenneth D. Merry #define ocs_atomic_read(a)		atomic_load_acq_32(a)
949ef270ab1SKenneth D. Merry 
950ef270ab1SKenneth D. Merry /**
951ef270ab1SKenneth D. Merry  * @ingroup os
952ef270ab1SKenneth D. Merry  * @brief sets the current value of an atomic object
953ef270ab1SKenneth D. Merry  *
954ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
955ef270ab1SKenneth D. Merry  */
956ef270ab1SKenneth D. Merry #define ocs_atomic_set(a, v)		atomic_store_rel_32(a, v)
957ef270ab1SKenneth D. Merry 
958ef270ab1SKenneth D. Merry /**
959ef270ab1SKenneth D. Merry  * @ingroup os
960ef270ab1SKenneth D. Merry  * @brief Sets atomic to 0, returns previous value
961ef270ab1SKenneth D. Merry  *
962ef270ab1SKenneth D. Merry  * @param a    pointer to the atomic object
963ef270ab1SKenneth D. Merry  *
964ef270ab1SKenneth D. Merry  * @return the value of the atomic before the operation.
965ef270ab1SKenneth D. Merry  */
966ef270ab1SKenneth D. Merry #define ocs_atomic_read_and_clear	atomic_readandclear_32(a)
967ef270ab1SKenneth D. Merry 
968ef270ab1SKenneth D. Merry /**
969ef270ab1SKenneth D. Merry  * @brief OCS thread structure
970ef270ab1SKenneth D. Merry  *
971ef270ab1SKenneth D. Merry  */
972ef270ab1SKenneth D. Merry 
973ef270ab1SKenneth D. Merry typedef struct ocs_thread_s ocs_thread_t;
974ef270ab1SKenneth D. Merry 
975ef270ab1SKenneth D. Merry typedef int32_t (*ocs_thread_fctn)(ocs_thread_t *mythread);
976ef270ab1SKenneth D. Merry 
977ef270ab1SKenneth D. Merry struct ocs_thread_s  {
978ef270ab1SKenneth D. Merry 	struct thread *tcb;			/*<< thread control block */
979ef270ab1SKenneth D. Merry 	ocs_thread_fctn fctn;			/*<< thread function */
980ef270ab1SKenneth D. Merry 	char *name;				/*<< name of thread */
981ef270ab1SKenneth D. Merry 	void *arg;				/*<< pointer to thread argument */
982ef270ab1SKenneth D. Merry 	ocs_atomic_t terminate;			/*<< terminate request */
983ef270ab1SKenneth D. Merry 	int32_t retval;				/*<< return value */
984ef270ab1SKenneth D. Merry 	uint32_t cpu_affinity;			/*<< cpu affinity */
985ef270ab1SKenneth D. Merry };
986ef270ab1SKenneth D. Merry #define OCS_THREAD_DEFAULT_STACK_SIZE_PAGES	8
987ef270ab1SKenneth D. Merry 
988ef270ab1SKenneth D. Merry /**
989ef270ab1SKenneth D. Merry  * @brief OCS thread start options
990ef270ab1SKenneth D. Merry  *
991ef270ab1SKenneth D. Merry  */
992ef270ab1SKenneth D. Merry 
993ef270ab1SKenneth D. Merry typedef enum {
994ef270ab1SKenneth D. Merry 	OCS_THREAD_RUN,				/*<< run immediately */
995ef270ab1SKenneth D. Merry 	OCS_THREAD_CREATE,			/*<< create and wait for start request */
996ef270ab1SKenneth D. Merry } ocs_thread_start_e;
997ef270ab1SKenneth D. Merry 
998ef270ab1SKenneth D. Merry extern int32_t ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn,
999ef270ab1SKenneth D. Merry 				 const char *name, void *arg, ocs_thread_start_e start_option);
1000ef270ab1SKenneth D. Merry extern int32_t ocs_thread_start(ocs_thread_t *thread);
1001ef270ab1SKenneth D. Merry extern void *ocs_thread_get_arg(ocs_thread_t *mythread);
1002ef270ab1SKenneth D. Merry extern int32_t ocs_thread_terminate(ocs_thread_t *thread);
1003ef270ab1SKenneth D. Merry extern int32_t ocs_thread_terminate_requested(ocs_thread_t *thread);
1004ef270ab1SKenneth D. Merry extern int32_t ocs_thread_get_retval(ocs_thread_t *thread);
1005ef270ab1SKenneth D. Merry extern void ocs_thread_yield(ocs_thread_t *thread);
1006ef270ab1SKenneth D. Merry extern ocs_thread_t *ocs_thread_self(void);
1007ef270ab1SKenneth D. Merry extern int32_t ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu);
1008ef270ab1SKenneth D. Merry extern int32_t ocs_thread_getcpu(void);
1009ef270ab1SKenneth D. Merry 
1010ef270ab1SKenneth D. Merry /***************************************************************************
1011ef270ab1SKenneth D. Merry  * PCI
1012ef270ab1SKenneth D. Merry  *
1013ef270ab1SKenneth D. Merry  * Several functions below refer to a "register set". This is one or
1014ef270ab1SKenneth D. Merry  * more PCI BARs that constitute a PCI address. For example, if a MMIO
1015ef270ab1SKenneth D. Merry  * region is described using both BAR[0] and BAR[1], the combination of
1016ef270ab1SKenneth D. Merry  * BARs defines register set 0.
1017ef270ab1SKenneth D. Merry  */
1018ef270ab1SKenneth D. Merry 
1019ef270ab1SKenneth D. Merry /**
1020ef270ab1SKenneth D. Merry  * @brief tracks mapped PCI memory regions
1021ef270ab1SKenneth D. Merry  */
1022ef270ab1SKenneth D. Merry typedef struct ocs_pci_reg_s {
1023ef270ab1SKenneth D. Merry 	uint32_t		rid;
1024ef270ab1SKenneth D. Merry 	struct resource		*res;
1025ef270ab1SKenneth D. Merry 	bus_space_tag_t		btag;
1026ef270ab1SKenneth D. Merry 	bus_space_handle_t	bhandle;
1027ef270ab1SKenneth D. Merry } ocs_pci_reg_t;
1028ef270ab1SKenneth D. Merry 
1029ef270ab1SKenneth D. Merry #define PCI_MAX_BAR				6
1030ef270ab1SKenneth D. Merry #define PCI_64BIT_BAR0				0
1031ef270ab1SKenneth D. Merry 
1032ef270ab1SKenneth D. Merry #define PCI_VENDOR_EMULEX			0x10df	/* Emulex */
1033ef270ab1SKenneth D. Merry 
1034ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE16001		0xe200	/* OneCore 16Gb FC (lancer) */
1035ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE16002		0xe200	/* OneCore 16Gb FC (lancer) */
1036ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_LPE31004		0xe300  /* LightPulse 16Gb x 4 FC (lancer-g6) */
1037ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_LPE32002		0xe300  /* LightPulse 32Gb x 2 FC (lancer-g6) */
10383bf42363SRam Kishore Vegesna #define PCI_PRODUCT_EMULEX_LANCER_G7		0xf400	/* LightPulse 32Gb x 4 FC (lancer-g7) */
10393bf42363SRam Kishore Vegesna 
1040ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE1600_VF		0xe208
1041ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE50102		0xe260	/* OneCore FCoE (lancer) */
1042ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE50102_VF		0xe268
1043ef270ab1SKenneth D. Merry 
1044ef270ab1SKenneth D. Merry /**
1045ef270ab1SKenneth D. Merry  * @ingroup os
1046ef270ab1SKenneth D. Merry  * @brief Get the PCI bus, device, and function values
1047ef270ab1SKenneth D. Merry  *
1048ef270ab1SKenneth D. Merry  * @param ocs OS specific handle or driver context
1049ef270ab1SKenneth D. Merry  * @param bus Pointer to location to store the bus number.
1050ef270ab1SKenneth D. Merry  * @param dev Pointer to location to store the device number.
1051ef270ab1SKenneth D. Merry  * @param func Pointer to location to store the function number.
1052ef270ab1SKenneth D. Merry  *
1053ef270ab1SKenneth D. Merry  */
105429e2dbd4SRam Kishore Vegesna extern void
1055ef270ab1SKenneth D. Merry ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func);
1056ef270ab1SKenneth D. Merry 
1057ef270ab1SKenneth D. Merry extern ocs_t *ocs_get_instance(uint32_t index);
1058ef270ab1SKenneth D. Merry extern uint32_t ocs_instance(void *os);
1059ef270ab1SKenneth D. Merry 
1060ef270ab1SKenneth D. Merry /**
1061ef270ab1SKenneth D. Merry  * @ingroup os
1062ef270ab1SKenneth D. Merry  * @brief Read a 32 bit value from the specified configuration register
1063ef270ab1SKenneth D. Merry  *
1064ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1065ef270ab1SKenneth D. Merry  * @param reg register offset
1066ef270ab1SKenneth D. Merry  *
1067ef270ab1SKenneth D. Merry  * @return The 32 bit value
1068ef270ab1SKenneth D. Merry  */
1069ef270ab1SKenneth D. Merry extern uint32_t ocs_config_read32(ocs_os_handle_t os, uint32_t reg);
1070ef270ab1SKenneth D. Merry 
1071ef270ab1SKenneth D. Merry /**
1072ef270ab1SKenneth D. Merry  * @ingroup os
1073ef270ab1SKenneth D. Merry  * @brief Read a 16 bit value from the specified configuration
1074ef270ab1SKenneth D. Merry  *        register
1075ef270ab1SKenneth D. Merry  *
1076ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1077ef270ab1SKenneth D. Merry  * @param reg register offset
1078ef270ab1SKenneth D. Merry  *
1079ef270ab1SKenneth D. Merry  * @return The 16 bit value
1080ef270ab1SKenneth D. Merry  */
1081ef270ab1SKenneth D. Merry extern uint16_t ocs_config_read16(ocs_os_handle_t os, uint32_t reg);
1082ef270ab1SKenneth D. Merry 
1083ef270ab1SKenneth D. Merry /**
1084ef270ab1SKenneth D. Merry  * @ingroup os
1085ef270ab1SKenneth D. Merry  * @brief Read a 8 bit value from the specified configuration
1086ef270ab1SKenneth D. Merry  *        register
1087ef270ab1SKenneth D. Merry  *
1088ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1089ef270ab1SKenneth D. Merry  * @param reg register offset
1090ef270ab1SKenneth D. Merry  *
1091ef270ab1SKenneth D. Merry  * @return The 8 bit value
1092ef270ab1SKenneth D. Merry  */
1093ef270ab1SKenneth D. Merry extern uint8_t ocs_config_read8(ocs_os_handle_t os, uint32_t reg);
1094ef270ab1SKenneth D. Merry 
1095ef270ab1SKenneth D. Merry /**
1096ef270ab1SKenneth D. Merry  * @ingroup os
1097ef270ab1SKenneth D. Merry  * @brief Write a 8 bit value to the specified configuration
1098ef270ab1SKenneth D. Merry  *        register
1099ef270ab1SKenneth D. Merry  *
1100ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1101ef270ab1SKenneth D. Merry  * @param reg register offset
1102ef270ab1SKenneth D. Merry  * @param val value to write
1103ef270ab1SKenneth D. Merry  *
1104ef270ab1SKenneth D. Merry  * @return None
1105ef270ab1SKenneth D. Merry  */
1106ef270ab1SKenneth D. Merry extern void ocs_config_write8(ocs_os_handle_t os, uint32_t reg, uint8_t val);
1107ef270ab1SKenneth D. Merry 
1108ef270ab1SKenneth D. Merry /**
1109ef270ab1SKenneth D. Merry  * @ingroup os
1110ef270ab1SKenneth D. Merry  * @brief Write a 16 bit value to the specified configuration
1111ef270ab1SKenneth D. Merry  *        register
1112ef270ab1SKenneth D. Merry  *
1113ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1114ef270ab1SKenneth D. Merry  * @param reg register offset
1115ef270ab1SKenneth D. Merry  * @param val value to write
1116ef270ab1SKenneth D. Merry  *
1117ef270ab1SKenneth D. Merry  * @return None
1118ef270ab1SKenneth D. Merry  */
1119ef270ab1SKenneth D. Merry extern void ocs_config_write16(ocs_os_handle_t os, uint32_t reg, uint16_t val);
1120ef270ab1SKenneth D. Merry 
1121ef270ab1SKenneth D. Merry /**
1122ef270ab1SKenneth D. Merry  * @ingroup os
1123ef270ab1SKenneth D. Merry  * @brief Write a 32 bit value to the specified configuration
1124ef270ab1SKenneth D. Merry  *        register
1125ef270ab1SKenneth D. Merry  *
1126ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1127ef270ab1SKenneth D. Merry  * @param reg register offset
1128ef270ab1SKenneth D. Merry  * @param val value to write
1129ef270ab1SKenneth D. Merry  *
1130ef270ab1SKenneth D. Merry  * @return None
1131ef270ab1SKenneth D. Merry  */
1132ef270ab1SKenneth D. Merry extern void ocs_config_write32(ocs_os_handle_t os, uint32_t reg, uint32_t val);
1133ef270ab1SKenneth D. Merry 
1134ef270ab1SKenneth D. Merry /**
1135ef270ab1SKenneth D. Merry  * @ingroup os
1136ef270ab1SKenneth D. Merry  * @brief Read a PCI register
1137ef270ab1SKenneth D. Merry  *
1138ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1139ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1140ef270ab1SKenneth D. Merry  * @param off  Register offset
1141ef270ab1SKenneth D. Merry  *
1142ef270ab1SKenneth D. Merry  * @return 32 bit conents of the register
1143ef270ab1SKenneth D. Merry  */
1144ef270ab1SKenneth D. Merry extern uint32_t ocs_reg_read32(ocs_os_handle_t os, uint32_t rset, uint32_t off);
1145ef270ab1SKenneth D. Merry 
1146ef270ab1SKenneth D. Merry /**
1147ef270ab1SKenneth D. Merry  * @ingroup os
1148ef270ab1SKenneth D. Merry  * @brief Read a PCI register
1149ef270ab1SKenneth D. Merry  *
1150ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1151ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1152ef270ab1SKenneth D. Merry  * @param off  Register offset
1153ef270ab1SKenneth D. Merry  *
1154ef270ab1SKenneth D. Merry  * @return 16 bit conents of the register
1155ef270ab1SKenneth D. Merry  */
1156ef270ab1SKenneth D. Merry extern uint16_t ocs_reg_read16(ocs_os_handle_t os, uint32_t rset, uint32_t off);
1157ef270ab1SKenneth D. Merry 
1158ef270ab1SKenneth D. Merry /**
1159ef270ab1SKenneth D. Merry  * @ingroup os
1160ef270ab1SKenneth D. Merry  * @brief Read a PCI register
1161ef270ab1SKenneth D. Merry  *
1162ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1163ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1164ef270ab1SKenneth D. Merry  * @param off  Register offset
1165ef270ab1SKenneth D. Merry  *
1166ef270ab1SKenneth D. Merry  * @return 8 bit conents of the register
1167ef270ab1SKenneth D. Merry  */
1168ef270ab1SKenneth D. Merry extern uint8_t ocs_reg_read8(ocs_os_handle_t os, uint32_t rset, uint32_t off);
1169ef270ab1SKenneth D. Merry 
1170ef270ab1SKenneth D. Merry /**
1171ef270ab1SKenneth D. Merry  * @ingroup os
1172ef270ab1SKenneth D. Merry  * @brief Write a PCI register
1173ef270ab1SKenneth D. Merry  *
1174ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1175ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1176ef270ab1SKenneth D. Merry  * @param off  Register offset
1177ef270ab1SKenneth D. Merry  * @param val  32-bit value to write
1178ef270ab1SKenneth D. Merry  */
1179ef270ab1SKenneth D. Merry extern void ocs_reg_write32(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint32_t val);
1180ef270ab1SKenneth D. Merry 
1181ef270ab1SKenneth D. Merry /**
1182ef270ab1SKenneth D. Merry  * @ingroup os
1183ef270ab1SKenneth D. Merry  * @brief Write a PCI register
1184ef270ab1SKenneth D. Merry  *
1185ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1186ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1187ef270ab1SKenneth D. Merry  * @param off  Register offset
1188ef270ab1SKenneth D. Merry  * @param val  16-bit value to write
1189ef270ab1SKenneth D. Merry  */
1190ef270ab1SKenneth D. Merry extern void ocs_reg_write16(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint16_t val);
1191ef270ab1SKenneth D. Merry 
1192ef270ab1SKenneth D. Merry /**
1193ef270ab1SKenneth D. Merry  * @ingroup os
1194ef270ab1SKenneth D. Merry  * @brief Write a PCI register
1195ef270ab1SKenneth D. Merry  *
1196ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1197ef270ab1SKenneth D. Merry  * @param rset Which "register set" to use
1198ef270ab1SKenneth D. Merry  * @param off  Register offset
1199ef270ab1SKenneth D. Merry  * @param val  8-bit value to write
1200ef270ab1SKenneth D. Merry  */
1201ef270ab1SKenneth D. Merry extern void ocs_reg_write8(ocs_os_handle_t os, uint32_t rset, uint32_t off, uint8_t val);
1202ef270ab1SKenneth D. Merry 
1203ef270ab1SKenneth D. Merry /**
1204ef270ab1SKenneth D. Merry  * @ingroup os
1205ef270ab1SKenneth D. Merry  * @brief Disable interrupts
1206ef270ab1SKenneth D. Merry  *
1207ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1208ef270ab1SKenneth D. Merry  */
1209ef270ab1SKenneth D. Merry extern void ocs_intr_disable(ocs_os_handle_t os);
1210ef270ab1SKenneth D. Merry 
1211ef270ab1SKenneth D. Merry /**
1212ef270ab1SKenneth D. Merry  * @ingroup os
1213ef270ab1SKenneth D. Merry  * @brief Enable interrupts
1214ef270ab1SKenneth D. Merry  *
1215ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1216ef270ab1SKenneth D. Merry  */
1217ef270ab1SKenneth D. Merry extern void ocs_intr_enable(ocs_os_handle_t os);
1218ef270ab1SKenneth D. Merry 
1219ef270ab1SKenneth D. Merry /**
1220ef270ab1SKenneth D. Merry  * @ingroup os
1221ef270ab1SKenneth D. Merry  * @brief Return model string
1222ef270ab1SKenneth D. Merry  *
1223ef270ab1SKenneth D. Merry  * @param os OS specific handle or driver context
1224ef270ab1SKenneth D. Merry  */
1225ef270ab1SKenneth D. Merry extern const char *ocs_pci_model(uint16_t vendor, uint16_t device);
1226ef270ab1SKenneth D. Merry 
1227ef270ab1SKenneth D. Merry extern void ocs_print_stack(void);
1228ef270ab1SKenneth D. Merry 
1229ef270ab1SKenneth D. Merry extern void ocs_abort(void) __attribute__((noreturn));
1230ef270ab1SKenneth D. Merry 
1231ef270ab1SKenneth D. Merry /***************************************************************************
1232ef270ab1SKenneth D. Merry  * Reference counting
1233ef270ab1SKenneth D. Merry  *
1234ef270ab1SKenneth D. Merry  */
1235ef270ab1SKenneth D. Merry 
1236ef270ab1SKenneth D. Merry /**
1237ef270ab1SKenneth D. Merry  * @ingroup os
1238ef270ab1SKenneth D. Merry  * @brief reference counter object
1239ef270ab1SKenneth D. Merry  */
1240ef270ab1SKenneth D. Merry typedef void (*ocs_ref_release_t)(void *arg);
1241ef270ab1SKenneth D. Merry typedef struct ocs_ref_s {
1242ef270ab1SKenneth D. Merry 	ocs_ref_release_t release; /* release function to call */
1243ef270ab1SKenneth D. Merry 	void *arg;
1244ef270ab1SKenneth D. Merry 	uint32_t count;		/* ref count; no need to be atomic if we have a lock */
1245ef270ab1SKenneth D. Merry } ocs_ref_t;
1246ef270ab1SKenneth D. Merry 
1247ef270ab1SKenneth D. Merry /**
1248ef270ab1SKenneth D. Merry  * @ingroup os
1249ef270ab1SKenneth D. Merry  * @brief initialize given reference object
1250ef270ab1SKenneth D. Merry  *
1251ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1252ef270ab1SKenneth D. Merry  * @param release Function to be called when count is 0.
1253ef270ab1SKenneth D. Merry  * @param arg Argument to be passed to release function.
1254ef270ab1SKenneth D. Merry  */
1255ef270ab1SKenneth D. Merry static inline void
ocs_ref_init(ocs_ref_t * ref,ocs_ref_release_t release,void * arg)1256ef270ab1SKenneth D. Merry ocs_ref_init(ocs_ref_t *ref, ocs_ref_release_t release, void *arg)
1257ef270ab1SKenneth D. Merry {
1258ef270ab1SKenneth D. Merry 	ref->release = release;
1259ef270ab1SKenneth D. Merry 	ref->arg = arg;
1260ef270ab1SKenneth D. Merry 	ocs_atomic_init(&ref->count, 1);
1261ef270ab1SKenneth D. Merry }
1262ef270ab1SKenneth D. Merry 
1263ef270ab1SKenneth D. Merry /**
1264ef270ab1SKenneth D. Merry  * @ingroup os
1265ef270ab1SKenneth D. Merry  * @brief Return reference count value
1266ef270ab1SKenneth D. Merry  *
1267ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1268ef270ab1SKenneth D. Merry  *
1269ef270ab1SKenneth D. Merry  * @return Count value of given reference object
1270ef270ab1SKenneth D. Merry  */
1271ef270ab1SKenneth D. Merry static inline uint32_t
ocs_ref_read_count(ocs_ref_t * ref)1272ef270ab1SKenneth D. Merry ocs_ref_read_count(ocs_ref_t *ref)
1273ef270ab1SKenneth D. Merry {
1274ef270ab1SKenneth D. Merry 	return ocs_atomic_read(&ref->count);
1275ef270ab1SKenneth D. Merry }
1276ef270ab1SKenneth D. Merry 
1277ef270ab1SKenneth D. Merry /**
1278ef270ab1SKenneth D. Merry  * @ingroup os
1279ef270ab1SKenneth D. Merry  * @brief Set count on given reference object to a value.
1280ef270ab1SKenneth D. Merry  *
1281ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1282ef270ab1SKenneth D. Merry  * @param i Set count to this value
1283ef270ab1SKenneth D. Merry  */
1284ef270ab1SKenneth D. Merry static inline void
ocs_ref_set(ocs_ref_t * ref,int i)1285ef270ab1SKenneth D. Merry ocs_ref_set(ocs_ref_t *ref, int i)
1286ef270ab1SKenneth D. Merry {
1287ef270ab1SKenneth D. Merry 	ocs_atomic_set(&ref->count, i);
1288ef270ab1SKenneth D. Merry }
1289ef270ab1SKenneth D. Merry 
1290ef270ab1SKenneth D. Merry /**
1291ef270ab1SKenneth D. Merry  * @ingroup os
1292ef270ab1SKenneth D. Merry  * @brief Take a reference on given object.
1293ef270ab1SKenneth D. Merry  *
1294ef270ab1SKenneth D. Merry  * @par Description
1295ef270ab1SKenneth D. Merry  * This function takes a reference on an object.
1296ef270ab1SKenneth D. Merry  *
1297ef270ab1SKenneth D. Merry  * Note: this function should only be used if the caller can
1298ef270ab1SKenneth D. Merry  * guarantee that the reference count is >= 1 and will stay >= 1
1299ef270ab1SKenneth D. Merry  * for the duration of this call (i.e. won't go to zero). If it
1300ef270ab1SKenneth D. Merry  * can't (the refcount may go to zero during this call),
1301ef270ab1SKenneth D. Merry  * ocs_ref_get_unless_zero() should be used instead.
1302ef270ab1SKenneth D. Merry  *
1303ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1304ef270ab1SKenneth D. Merry  *
1305ef270ab1SKenneth D. Merry  */
1306ef270ab1SKenneth D. Merry static inline void
ocs_ref_get(ocs_ref_t * ref)1307ef270ab1SKenneth D. Merry ocs_ref_get(ocs_ref_t *ref)
1308ef270ab1SKenneth D. Merry {
1309ef270ab1SKenneth D. Merry 	ocs_atomic_add_return(&ref->count, 1);
1310ef270ab1SKenneth D. Merry }
1311ef270ab1SKenneth D. Merry 
1312ef270ab1SKenneth D. Merry /**
1313ef270ab1SKenneth D. Merry  * @ingroup os
1314ef270ab1SKenneth D. Merry  * @brief Take a reference on given object if count is not zero.
1315ef270ab1SKenneth D. Merry  *
1316ef270ab1SKenneth D. Merry  * @par Description
1317ef270ab1SKenneth D. Merry  * This function takes a reference on an object if and only if
1318ef270ab1SKenneth D. Merry  * the given reference object is "active" or valid.
1319ef270ab1SKenneth D. Merry  *
1320ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1321ef270ab1SKenneth D. Merry  *
1322ef270ab1SKenneth D. Merry  * @return non-zero if "get" succeeded; Return zero if ref count
1323ef270ab1SKenneth D. Merry  * is zero.
1324ef270ab1SKenneth D. Merry  */
1325ef270ab1SKenneth D. Merry static inline uint32_t
ocs_ref_get_unless_zero(ocs_ref_t * ref)1326ef270ab1SKenneth D. Merry ocs_ref_get_unless_zero(ocs_ref_t *ref)
1327ef270ab1SKenneth D. Merry {
1328ef270ab1SKenneth D. Merry 	uint32_t rc = 0;
1329ef270ab1SKenneth D. Merry 	rc = ocs_atomic_read(&ref->count);
1330ef270ab1SKenneth D. Merry 		if (rc != 0) {
1331ef270ab1SKenneth D. Merry 			ocs_atomic_add_return(&ref->count, 1);
1332ef270ab1SKenneth D. Merry 		}
1333ef270ab1SKenneth D. Merry 	return rc;
1334ef270ab1SKenneth D. Merry }
1335ef270ab1SKenneth D. Merry 
1336ef270ab1SKenneth D. Merry /**
1337ef270ab1SKenneth D. Merry  * @ingroup os
1338ef270ab1SKenneth D. Merry  * @brief Decrement reference on given object
1339ef270ab1SKenneth D. Merry  *
1340ef270ab1SKenneth D. Merry  * @par Description
1341ef270ab1SKenneth D. Merry  * This function decrements the reference count on the given
1342ef270ab1SKenneth D. Merry  * reference object. If the reference count becomes zero, the
1343ef270ab1SKenneth D. Merry  * "release" function (set during "init" time) is called.
1344ef270ab1SKenneth D. Merry  *
1345ef270ab1SKenneth D. Merry  * @param ref Pointer to reference object
1346ef270ab1SKenneth D. Merry  *
1347ef270ab1SKenneth D. Merry  * @return non-zero if release function was called; zero
1348ef270ab1SKenneth D. Merry  * otherwise.
1349ef270ab1SKenneth D. Merry  */
1350ef270ab1SKenneth D. Merry static inline uint32_t
ocs_ref_put(ocs_ref_t * ref)1351ef270ab1SKenneth D. Merry ocs_ref_put(ocs_ref_t *ref)
1352ef270ab1SKenneth D. Merry {
1353ef270ab1SKenneth D. Merry 	uint32_t rc = 0;
1354ef270ab1SKenneth D. Merry 	if (ocs_atomic_sub_return(&ref->count, 1) == 1) {
1355ef270ab1SKenneth D. Merry 		ref->release(ref->arg);
1356ef270ab1SKenneth D. Merry 		rc = 1;
1357ef270ab1SKenneth D. Merry 	}
1358ef270ab1SKenneth D. Merry 	return rc;
1359ef270ab1SKenneth D. Merry }
1360ef270ab1SKenneth D. Merry 
1361ef270ab1SKenneth D. Merry /**
1362ef270ab1SKenneth D. Merry  * @ingroup os
1363ef270ab1SKenneth D. Merry  * @brief Get the OS system ticks
1364ef270ab1SKenneth D. Merry  *
1365ef270ab1SKenneth D. Merry  * @return number of ticks that have occurred since the system
1366ef270ab1SKenneth D. Merry  * booted.
1367ef270ab1SKenneth D. Merry  */
1368ef270ab1SKenneth D. Merry static inline uint64_t
ocs_get_os_ticks(void)1369ef270ab1SKenneth D. Merry ocs_get_os_ticks(void)
1370ef270ab1SKenneth D. Merry {
1371ef270ab1SKenneth D. Merry 	return ticks;
1372ef270ab1SKenneth D. Merry }
1373ef270ab1SKenneth D. Merry 
1374ef270ab1SKenneth D. Merry /**
1375ef270ab1SKenneth D. Merry  * @ingroup os
1376ef270ab1SKenneth D. Merry  * @brief Get the OS system tick frequency
1377ef270ab1SKenneth D. Merry  *
1378ef270ab1SKenneth D. Merry  * @return frequency of system ticks.
1379ef270ab1SKenneth D. Merry  */
1380ef270ab1SKenneth D. Merry static inline uint32_t
ocs_get_os_tick_freq(void)1381ef270ab1SKenneth D. Merry ocs_get_os_tick_freq(void)
1382ef270ab1SKenneth D. Merry {
1383ef270ab1SKenneth D. Merry 	return hz;
1384ef270ab1SKenneth D. Merry }
1385ef270ab1SKenneth D. Merry 
1386ef270ab1SKenneth D. Merry /*****************************************************************************
1387ef270ab1SKenneth D. Merry  *
1388ef270ab1SKenneth D. Merry  * CPU topology API
1389ef270ab1SKenneth D. Merry  */
1390ef270ab1SKenneth D. Merry 
1391ef270ab1SKenneth D. Merry typedef struct {
1392ef270ab1SKenneth D. Merry 	uint32_t num_cpus;	/* Number of CPU cores */
1393ef270ab1SKenneth D. Merry 	uint8_t hyper;		/* TRUE if threaded CPUs */
1394ef270ab1SKenneth D. Merry } ocs_cpuinfo_t;
1395ef270ab1SKenneth D. Merry 
1396ef270ab1SKenneth D. Merry extern int32_t ocs_get_cpuinfo(ocs_cpuinfo_t *cpuinfo);
1397ef270ab1SKenneth D. Merry extern uint32_t ocs_get_num_cpus(void);
1398ef270ab1SKenneth D. Merry 
1399ef270ab1SKenneth D. Merry #include "ocs_list.h"
1400ef270ab1SKenneth D. Merry #include "ocs_utils.h"
1401ef270ab1SKenneth D. Merry #include "ocs_mgmt.h"
1402ef270ab1SKenneth D. Merry #include "ocs_common.h"
1403ef270ab1SKenneth D. Merry 
1404ef270ab1SKenneth D. Merry #endif /* !_OCS_OS_H */
1405