xref: /freebsd/sys/dev/ocs_fc/ocs_os.c (revision ef270ab1b656486947b3b4aaec9bc0a6b5d6af21)
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  * $FreeBSD$
32*ef270ab1SKenneth D. Merry  */
33*ef270ab1SKenneth D. Merry 
34*ef270ab1SKenneth D. Merry /**
35*ef270ab1SKenneth D. Merry  * @file
36*ef270ab1SKenneth D. Merry  * Implementation of common BSD OS abstraction functions
37*ef270ab1SKenneth D. Merry  */
38*ef270ab1SKenneth D. Merry 
39*ef270ab1SKenneth D. Merry #include "ocs.h"
40*ef270ab1SKenneth D. Merry #include <sys/sysctl.h>
41*ef270ab1SKenneth D. Merry #include <sys/malloc.h>
42*ef270ab1SKenneth D. Merry #include <sys/linker.h>		/* for debug of memory allocations */
43*ef270ab1SKenneth D. Merry 
44*ef270ab1SKenneth D. Merry static MALLOC_DEFINE(M_OCS, "OCS", "OneCore Storage data");
45*ef270ab1SKenneth D. Merry 
46*ef270ab1SKenneth D. Merry #include <dev/pci/pcireg.h>
47*ef270ab1SKenneth D. Merry #include <dev/pci/pcivar.h>
48*ef270ab1SKenneth D. Merry 
49*ef270ab1SKenneth D. Merry #include <machine/bus.h>
50*ef270ab1SKenneth D. Merry 
51*ef270ab1SKenneth D. Merry timeout_t	__ocs_callout;
52*ef270ab1SKenneth D. Merry 
53*ef270ab1SKenneth D. Merry uint32_t
54*ef270ab1SKenneth D. Merry ocs_config_read32(ocs_os_handle_t os, uint32_t reg)
55*ef270ab1SKenneth D. Merry {
56*ef270ab1SKenneth D. Merry 	return pci_read_config(os->dev, reg, 4);
57*ef270ab1SKenneth D. Merry }
58*ef270ab1SKenneth D. Merry 
59*ef270ab1SKenneth D. Merry uint16_t
60*ef270ab1SKenneth D. Merry ocs_config_read16(ocs_os_handle_t os, uint32_t reg)
61*ef270ab1SKenneth D. Merry {
62*ef270ab1SKenneth D. Merry 	return pci_read_config(os->dev, reg, 2);
63*ef270ab1SKenneth D. Merry }
64*ef270ab1SKenneth D. Merry 
65*ef270ab1SKenneth D. Merry uint8_t
66*ef270ab1SKenneth D. Merry ocs_config_read8(ocs_os_handle_t os, uint32_t reg)
67*ef270ab1SKenneth D. Merry {
68*ef270ab1SKenneth D. Merry 	return pci_read_config(os->dev, reg, 1);
69*ef270ab1SKenneth D. Merry }
70*ef270ab1SKenneth D. Merry 
71*ef270ab1SKenneth D. Merry void
72*ef270ab1SKenneth D. Merry ocs_config_write8(ocs_os_handle_t os, uint32_t reg, uint8_t val)
73*ef270ab1SKenneth D. Merry {
74*ef270ab1SKenneth D. Merry 	return pci_write_config(os->dev, reg, val, 1);
75*ef270ab1SKenneth D. Merry }
76*ef270ab1SKenneth D. Merry 
77*ef270ab1SKenneth D. Merry void
78*ef270ab1SKenneth D. Merry ocs_config_write16(ocs_os_handle_t os, uint32_t reg, uint16_t val)
79*ef270ab1SKenneth D. Merry {
80*ef270ab1SKenneth D. Merry 	return pci_write_config(os->dev, reg, val, 2);
81*ef270ab1SKenneth D. Merry }
82*ef270ab1SKenneth D. Merry 
83*ef270ab1SKenneth D. Merry void
84*ef270ab1SKenneth D. Merry ocs_config_write32(ocs_os_handle_t os, uint32_t reg, uint32_t val)
85*ef270ab1SKenneth D. Merry {
86*ef270ab1SKenneth D. Merry 	return pci_write_config(os->dev, reg, val, 4);
87*ef270ab1SKenneth D. Merry }
88*ef270ab1SKenneth D. Merry 
89*ef270ab1SKenneth D. Merry /**
90*ef270ab1SKenneth D. Merry  * @ingroup os
91*ef270ab1SKenneth D. Merry  * @brief Read a 32bit PCI register
92*ef270ab1SKenneth D. Merry  *
93*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
94*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
95*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
96*ef270ab1SKenneth D. Merry  *
97*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
98*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
99*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
100*ef270ab1SKenneth D. Merry  *
101*ef270ab1SKenneth D. Merry  * @return register value
102*ef270ab1SKenneth D. Merry  */
103*ef270ab1SKenneth D. Merry uint32_t
104*ef270ab1SKenneth D. Merry ocs_reg_read32(ocs_t *ocs, uint32_t rset, uint32_t off)
105*ef270ab1SKenneth D. Merry {
106*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
107*ef270ab1SKenneth D. Merry 
108*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
109*ef270ab1SKenneth D. Merry 
110*ef270ab1SKenneth D. Merry 	return bus_space_read_4(reg->btag, reg->bhandle, off);
111*ef270ab1SKenneth D. Merry }
112*ef270ab1SKenneth D. Merry 
113*ef270ab1SKenneth D. Merry /**
114*ef270ab1SKenneth D. Merry  * @ingroup os
115*ef270ab1SKenneth D. Merry  * @brief Read a 16bit PCI register
116*ef270ab1SKenneth D. Merry  *
117*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
118*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
119*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
120*ef270ab1SKenneth D. Merry  *
121*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
122*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
123*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
124*ef270ab1SKenneth D. Merry  *
125*ef270ab1SKenneth D. Merry  * @return register value
126*ef270ab1SKenneth D. Merry  */
127*ef270ab1SKenneth D. Merry uint16_t
128*ef270ab1SKenneth D. Merry ocs_reg_read16(ocs_t *ocs, uint32_t rset, uint32_t off)
129*ef270ab1SKenneth D. Merry {
130*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
131*ef270ab1SKenneth D. Merry 
132*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
133*ef270ab1SKenneth D. Merry 
134*ef270ab1SKenneth D. Merry 	return bus_space_read_2(reg->btag, reg->bhandle, off);
135*ef270ab1SKenneth D. Merry }
136*ef270ab1SKenneth D. Merry 
137*ef270ab1SKenneth D. Merry /**
138*ef270ab1SKenneth D. Merry  * @ingroup os
139*ef270ab1SKenneth D. Merry  * @brief Read a 8bit PCI register
140*ef270ab1SKenneth D. Merry  *
141*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
142*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
143*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
144*ef270ab1SKenneth D. Merry  *
145*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
146*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
147*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
148*ef270ab1SKenneth D. Merry  *
149*ef270ab1SKenneth D. Merry  * @return register value
150*ef270ab1SKenneth D. Merry  */
151*ef270ab1SKenneth D. Merry uint8_t
152*ef270ab1SKenneth D. Merry ocs_reg_read8(ocs_t *ocs, uint32_t rset, uint32_t off)
153*ef270ab1SKenneth D. Merry {
154*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
155*ef270ab1SKenneth D. Merry 
156*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
157*ef270ab1SKenneth D. Merry 
158*ef270ab1SKenneth D. Merry 	return bus_space_read_1(reg->btag, reg->bhandle, off);
159*ef270ab1SKenneth D. Merry }
160*ef270ab1SKenneth D. Merry 
161*ef270ab1SKenneth D. Merry /**
162*ef270ab1SKenneth D. Merry  * @ingroup os
163*ef270ab1SKenneth D. Merry  * @brief Write a 32bit PCI register
164*ef270ab1SKenneth D. Merry  *
165*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
166*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
167*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
168*ef270ab1SKenneth D. Merry  *
169*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
170*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
171*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
172*ef270ab1SKenneth D. Merry  * @param val Value to write
173*ef270ab1SKenneth D. Merry  *
174*ef270ab1SKenneth D. Merry  * @return none
175*ef270ab1SKenneth D. Merry  */
176*ef270ab1SKenneth D. Merry void
177*ef270ab1SKenneth D. Merry ocs_reg_write32(ocs_t *ocs, uint32_t rset, uint32_t off, uint32_t val)
178*ef270ab1SKenneth D. Merry {
179*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
180*ef270ab1SKenneth D. Merry 
181*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
182*ef270ab1SKenneth D. Merry 
183*ef270ab1SKenneth D. Merry 	return bus_space_write_4(reg->btag, reg->bhandle, off, val);
184*ef270ab1SKenneth D. Merry }
185*ef270ab1SKenneth D. Merry 
186*ef270ab1SKenneth D. Merry /**
187*ef270ab1SKenneth D. Merry  * @ingroup os
188*ef270ab1SKenneth D. Merry  * @brief Write a 16-bit PCI register
189*ef270ab1SKenneth D. Merry  *
190*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
191*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
192*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
193*ef270ab1SKenneth D. Merry  *
194*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
195*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
196*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
197*ef270ab1SKenneth D. Merry  * @param val Value to write
198*ef270ab1SKenneth D. Merry  *
199*ef270ab1SKenneth D. Merry  * @return none
200*ef270ab1SKenneth D. Merry  */
201*ef270ab1SKenneth D. Merry void
202*ef270ab1SKenneth D. Merry ocs_reg_write16(ocs_t *ocs, uint32_t rset, uint32_t off, uint16_t val)
203*ef270ab1SKenneth D. Merry {
204*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
205*ef270ab1SKenneth D. Merry 
206*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
207*ef270ab1SKenneth D. Merry 
208*ef270ab1SKenneth D. Merry 	return bus_space_write_2(reg->btag, reg->bhandle, off, val);
209*ef270ab1SKenneth D. Merry }
210*ef270ab1SKenneth D. Merry 
211*ef270ab1SKenneth D. Merry /**
212*ef270ab1SKenneth D. Merry  * @ingroup os
213*ef270ab1SKenneth D. Merry  * @brief Write a 8-bit PCI register
214*ef270ab1SKenneth D. Merry  *
215*ef270ab1SKenneth D. Merry  * The SLI documentation uses the term "register set" to describe one or more
216*ef270ab1SKenneth D. Merry  * PCI BARs which form a logical address. For example, a 64-bit address uses
217*ef270ab1SKenneth D. Merry  * two BARs, and thus constitute a register set.
218*ef270ab1SKenneth D. Merry  *
219*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver's context
220*ef270ab1SKenneth D. Merry  * @param rset Register Set to use
221*ef270ab1SKenneth D. Merry  * @param off Offset from the base address of the Register Set
222*ef270ab1SKenneth D. Merry  * @param val Value to write
223*ef270ab1SKenneth D. Merry  *
224*ef270ab1SKenneth D. Merry  * @return none
225*ef270ab1SKenneth D. Merry  */
226*ef270ab1SKenneth D. Merry void
227*ef270ab1SKenneth D. Merry ocs_reg_write8(ocs_t *ocs, uint32_t rset, uint32_t off, uint8_t val)
228*ef270ab1SKenneth D. Merry {
229*ef270ab1SKenneth D. Merry 	ocs_pci_reg_t		*reg = NULL;
230*ef270ab1SKenneth D. Merry 
231*ef270ab1SKenneth D. Merry 	reg = &ocs->reg[rset];
232*ef270ab1SKenneth D. Merry 
233*ef270ab1SKenneth D. Merry 	return bus_space_write_1(reg->btag, reg->bhandle, off, val);
234*ef270ab1SKenneth D. Merry }
235*ef270ab1SKenneth D. Merry 
236*ef270ab1SKenneth D. Merry /**
237*ef270ab1SKenneth D. Merry  * @ingroup os
238*ef270ab1SKenneth D. Merry  * @brief Allocate host memory
239*ef270ab1SKenneth D. Merry  *
240*ef270ab1SKenneth D. Merry  * @param os OS handle
241*ef270ab1SKenneth D. Merry  * @param size number of bytes to allocate
242*ef270ab1SKenneth D. Merry  * @param flags additional options
243*ef270ab1SKenneth D. Merry  *
244*ef270ab1SKenneth D. Merry  * @return pointer to allocated memory, NULL otherwise
245*ef270ab1SKenneth D. Merry  */
246*ef270ab1SKenneth D. Merry void *
247*ef270ab1SKenneth D. Merry ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags)
248*ef270ab1SKenneth D. Merry {
249*ef270ab1SKenneth D. Merry 	if ((flags & OCS_M_NOWAIT) == 0) {
250*ef270ab1SKenneth D. Merry 		flags |= M_WAITOK;
251*ef270ab1SKenneth D. Merry 	}
252*ef270ab1SKenneth D. Merry 
253*ef270ab1SKenneth D. Merry #ifndef OCS_DEBUG_MEMORY
254*ef270ab1SKenneth D. Merry 	return malloc(size, M_OCS, flags);
255*ef270ab1SKenneth D. Merry #else
256*ef270ab1SKenneth D. Merry 	char nameb[80];
257*ef270ab1SKenneth D. Merry 	long offset = 0;
258*ef270ab1SKenneth D. Merry 	void *addr = malloc(size, M_OCS, flags);
259*ef270ab1SKenneth D. Merry 
260*ef270ab1SKenneth D. Merry 	linker_ddb_search_symbol_name(__builtin_return_address(1), nameb, sizeof(nameb), &offset);
261*ef270ab1SKenneth D. Merry 	printf("A: %p %ld @ %s+%#lx\n", addr, size, nameb, offset);
262*ef270ab1SKenneth D. Merry 
263*ef270ab1SKenneth D. Merry 	return addr;
264*ef270ab1SKenneth D. Merry #endif
265*ef270ab1SKenneth D. Merry }
266*ef270ab1SKenneth D. Merry 
267*ef270ab1SKenneth D. Merry /**
268*ef270ab1SKenneth D. Merry  * @ingroup os
269*ef270ab1SKenneth D. Merry  * @brief Free host memory
270*ef270ab1SKenneth D. Merry  *
271*ef270ab1SKenneth D. Merry  * @param os OS handle
272*ef270ab1SKenneth D. Merry  * @param addr pointer to memory
273*ef270ab1SKenneth D. Merry  * @param size bytes to free
274*ef270ab1SKenneth D. Merry  *
275*ef270ab1SKenneth D. Merry  * @note size ignored in BSD
276*ef270ab1SKenneth D. Merry  */
277*ef270ab1SKenneth D. Merry void
278*ef270ab1SKenneth D. Merry ocs_free(ocs_os_handle_t os, void *addr, size_t size)
279*ef270ab1SKenneth D. Merry {
280*ef270ab1SKenneth D. Merry #ifndef OCS_DEBUG_MEMORY
281*ef270ab1SKenneth D. Merry 	free(addr, M_OCS);
282*ef270ab1SKenneth D. Merry #else
283*ef270ab1SKenneth D. Merry 	printf("F: %p %ld\n", addr, size);
284*ef270ab1SKenneth D. Merry 	free(addr, M_OCS);
285*ef270ab1SKenneth D. Merry #endif
286*ef270ab1SKenneth D. Merry }
287*ef270ab1SKenneth D. Merry 
288*ef270ab1SKenneth D. Merry /**
289*ef270ab1SKenneth D. Merry  * @brief Callback function provided to bus_dmamap_load
290*ef270ab1SKenneth D. Merry  *
291*ef270ab1SKenneth D. Merry  * Function loads the physical / bus address into the DMA descriptor. The caller
292*ef270ab1SKenneth D. Merry  * can detect a mapping failure if a descriptor's phys element is zero.
293*ef270ab1SKenneth D. Merry  *
294*ef270ab1SKenneth D. Merry  * @param arg Argument provided to bus_dmamap_load is a ocs_dma_t
295*ef270ab1SKenneth D. Merry  * @param seg Array of DMA segment(s), each describing segment's address and length
296*ef270ab1SKenneth D. Merry  * @param nseg Number of elements in array
297*ef270ab1SKenneth D. Merry  * @param error Indicates success (0) or failure of mapping
298*ef270ab1SKenneth D. Merry  */
299*ef270ab1SKenneth D. Merry static void
300*ef270ab1SKenneth D. Merry ocs_dma_load(void *arg, bus_dma_segment_t *seg, int nseg, int error)
301*ef270ab1SKenneth D. Merry {
302*ef270ab1SKenneth D. Merry 	ocs_dma_t	*dma = arg;
303*ef270ab1SKenneth D. Merry 
304*ef270ab1SKenneth D. Merry 	if (error) {
305*ef270ab1SKenneth D. Merry 		printf("%s: error=%d\n", __func__, error);
306*ef270ab1SKenneth D. Merry 		dma->phys = 0;
307*ef270ab1SKenneth D. Merry 	} else {
308*ef270ab1SKenneth D. Merry 		dma->phys = seg->ds_addr;
309*ef270ab1SKenneth D. Merry 	}
310*ef270ab1SKenneth D. Merry }
311*ef270ab1SKenneth D. Merry 
312*ef270ab1SKenneth D. Merry /**
313*ef270ab1SKenneth D. Merry  * @ingroup os
314*ef270ab1SKenneth D. Merry  * @brief Free a DMA capable block of memory
315*ef270ab1SKenneth D. Merry  *
316*ef270ab1SKenneth D. Merry  * @param os Device abstraction
317*ef270ab1SKenneth D. Merry  * @param dma DMA descriptor for memory to be freed
318*ef270ab1SKenneth D. Merry  *
319*ef270ab1SKenneth D. Merry  * @return 0 if memory is de-allocated, -1 otherwise
320*ef270ab1SKenneth D. Merry  */
321*ef270ab1SKenneth D. Merry int32_t
322*ef270ab1SKenneth D. Merry ocs_dma_free(ocs_os_handle_t os, ocs_dma_t *dma)
323*ef270ab1SKenneth D. Merry {
324*ef270ab1SKenneth D. Merry 	struct ocs_softc	*ocs = os;
325*ef270ab1SKenneth D. Merry 
326*ef270ab1SKenneth D. Merry 	if (!dma) {
327*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "%s: bad parameter(s) dma=%p\n", __func__, dma);
328*ef270ab1SKenneth D. Merry 		return -1;
329*ef270ab1SKenneth D. Merry 	}
330*ef270ab1SKenneth D. Merry 
331*ef270ab1SKenneth D. Merry 	if (dma->size == 0) {
332*ef270ab1SKenneth D. Merry 		return 0;
333*ef270ab1SKenneth D. Merry 	}
334*ef270ab1SKenneth D. Merry 
335*ef270ab1SKenneth D. Merry 	if (dma->map) {
336*ef270ab1SKenneth D. Merry 		bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_POSTREAD |
337*ef270ab1SKenneth D. Merry 				BUS_DMASYNC_POSTWRITE);
338*ef270ab1SKenneth D. Merry 		bus_dmamap_unload(dma->tag, dma->map);
339*ef270ab1SKenneth D. Merry 	}
340*ef270ab1SKenneth D. Merry 
341*ef270ab1SKenneth D. Merry 	if (dma->virt) {
342*ef270ab1SKenneth D. Merry 		bus_dmamem_free(dma->tag, dma->virt, dma->map);
343*ef270ab1SKenneth D. Merry 		bus_dmamap_destroy(dma->tag, dma->map);
344*ef270ab1SKenneth D. Merry 	}
345*ef270ab1SKenneth D. Merry 	bus_dma_tag_destroy(dma->tag);
346*ef270ab1SKenneth D. Merry 
347*ef270ab1SKenneth D. Merry 	bzero(dma, sizeof(ocs_dma_t));
348*ef270ab1SKenneth D. Merry 
349*ef270ab1SKenneth D. Merry 	return 0;
350*ef270ab1SKenneth D. Merry }
351*ef270ab1SKenneth D. Merry 
352*ef270ab1SKenneth D. Merry /**
353*ef270ab1SKenneth D. Merry  * @ingroup os
354*ef270ab1SKenneth D. Merry  * @brief Allocate a DMA capable block of memory
355*ef270ab1SKenneth D. Merry  *
356*ef270ab1SKenneth D. Merry  * @param os Device abstraction
357*ef270ab1SKenneth D. Merry  * @param dma DMA descriptor containing results of memory allocation
358*ef270ab1SKenneth D. Merry  * @param size Size in bytes of desired allocation
359*ef270ab1SKenneth D. Merry  * @param align Alignment in bytes
360*ef270ab1SKenneth D. Merry  *
361*ef270ab1SKenneth D. Merry  * @return 0 on success, ENOMEM otherwise
362*ef270ab1SKenneth D. Merry  */
363*ef270ab1SKenneth D. Merry int32_t
364*ef270ab1SKenneth D. Merry ocs_dma_alloc(ocs_os_handle_t os, ocs_dma_t *dma, size_t size, size_t align)
365*ef270ab1SKenneth D. Merry {
366*ef270ab1SKenneth D. Merry 	struct ocs_softc	*ocs = os;
367*ef270ab1SKenneth D. Merry 
368*ef270ab1SKenneth D. Merry 	if (!dma || !size) {
369*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "%s bad parameter(s) dma=%p size=%zd\n",
370*ef270ab1SKenneth D. Merry 				__func__, dma, size);
371*ef270ab1SKenneth D. Merry 		return ENOMEM;
372*ef270ab1SKenneth D. Merry 	}
373*ef270ab1SKenneth D. Merry 
374*ef270ab1SKenneth D. Merry 	bzero(dma, sizeof(ocs_dma_t));
375*ef270ab1SKenneth D. Merry 
376*ef270ab1SKenneth D. Merry 	/* create a "tag" that describes the desired memory allocation */
377*ef270ab1SKenneth D. Merry 	if (bus_dma_tag_create(ocs->dmat, align, 0, BUS_SPACE_MAXADDR,
378*ef270ab1SKenneth D. Merry 				BUS_SPACE_MAXADDR, NULL, NULL,
379*ef270ab1SKenneth D. Merry 				size, 1, size, 0, NULL, NULL, &dma->tag)) {
380*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "DMA tag allocation failed\n");
381*ef270ab1SKenneth D. Merry 		return ENOMEM;
382*ef270ab1SKenneth D. Merry 	}
383*ef270ab1SKenneth D. Merry 
384*ef270ab1SKenneth D. Merry 	dma->size = size;
385*ef270ab1SKenneth D. Merry 
386*ef270ab1SKenneth D. Merry 	/* allocate the memory */
387*ef270ab1SKenneth D. Merry 	if (bus_dmamem_alloc(dma->tag, &dma->virt, BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
388*ef270ab1SKenneth D. Merry 				&dma->map)) {
389*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "DMA memory allocation failed s=%zd a=%zd\n", size, align);
390*ef270ab1SKenneth D. Merry 		ocs_dma_free(ocs, dma);
391*ef270ab1SKenneth D. Merry 		return ENOMEM;
392*ef270ab1SKenneth D. Merry 	}
393*ef270ab1SKenneth D. Merry 
394*ef270ab1SKenneth D. Merry 	dma->alloc = dma->virt;
395*ef270ab1SKenneth D. Merry 
396*ef270ab1SKenneth D. Merry 	/* map virtual address to device visible address */
397*ef270ab1SKenneth D. Merry 	if (bus_dmamap_load(dma->tag, dma->map, dma->virt, dma->size, ocs_dma_load,
398*ef270ab1SKenneth D. Merry 				dma, 0)) {
399*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "DMA memory load failed\n");
400*ef270ab1SKenneth D. Merry 		ocs_dma_free(ocs, dma);
401*ef270ab1SKenneth D. Merry 		return ENOMEM;
402*ef270ab1SKenneth D. Merry 	}
403*ef270ab1SKenneth D. Merry 
404*ef270ab1SKenneth D. Merry 	/* if the DMA map load callback fails, it sets the physical address to zero */
405*ef270ab1SKenneth D. Merry 	if (0 == dma->phys) {
406*ef270ab1SKenneth D. Merry 		device_printf(ocs->dev, "ocs_dma_load failed\n");
407*ef270ab1SKenneth D. Merry 		ocs_dma_free(ocs, dma);
408*ef270ab1SKenneth D. Merry 		return ENOMEM;
409*ef270ab1SKenneth D. Merry 	}
410*ef270ab1SKenneth D. Merry 
411*ef270ab1SKenneth D. Merry 	return 0;
412*ef270ab1SKenneth D. Merry }
413*ef270ab1SKenneth D. Merry 
414*ef270ab1SKenneth D. Merry /**
415*ef270ab1SKenneth D. Merry  * @ingroup os
416*ef270ab1SKenneth D. Merry  * @brief Synchronize the DMA buffer memory
417*ef270ab1SKenneth D. Merry  *
418*ef270ab1SKenneth D. Merry  * Ensures memory coherency between the CPU and device
419*ef270ab1SKenneth D. Merry  *
420*ef270ab1SKenneth D. Merry  * @param dma DMA descriptor of memory to synchronize
421*ef270ab1SKenneth D. Merry  * @param flags Describes direction of synchronization
422*ef270ab1SKenneth D. Merry  *   See BUS_DMA(9) for details
423*ef270ab1SKenneth D. Merry  *   - BUS_DMASYNC_PREWRITE
424*ef270ab1SKenneth D. Merry  *   - BUS_DMASYNC_POSTREAD
425*ef270ab1SKenneth D. Merry  */
426*ef270ab1SKenneth D. Merry void
427*ef270ab1SKenneth D. Merry ocs_dma_sync(ocs_dma_t *dma, uint32_t flags)
428*ef270ab1SKenneth D. Merry {
429*ef270ab1SKenneth D. Merry 	bus_dmamap_sync(dma->tag, dma->map, flags);
430*ef270ab1SKenneth D. Merry }
431*ef270ab1SKenneth D. Merry 
432*ef270ab1SKenneth D. Merry int32_t
433*ef270ab1SKenneth D. Merry ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
434*ef270ab1SKenneth D. Merry {
435*ef270ab1SKenneth D. Merry 	if (!dma)
436*ef270ab1SKenneth D. Merry 		return -1;
437*ef270ab1SKenneth D. Merry 	if (!buffer)
438*ef270ab1SKenneth D. Merry 		return -1;
439*ef270ab1SKenneth D. Merry 	if (buffer_length == 0)
440*ef270ab1SKenneth D. Merry 		return 0;
441*ef270ab1SKenneth D. Merry 	if (buffer_length > dma->size)
442*ef270ab1SKenneth D. Merry 		buffer_length = dma->size;
443*ef270ab1SKenneth D. Merry 	ocs_memcpy(dma->virt, buffer, buffer_length);
444*ef270ab1SKenneth D. Merry 	dma->len = buffer_length;
445*ef270ab1SKenneth D. Merry 	return buffer_length;
446*ef270ab1SKenneth D. Merry }
447*ef270ab1SKenneth D. Merry 
448*ef270ab1SKenneth D. Merry int32_t
449*ef270ab1SKenneth D. Merry ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length)
450*ef270ab1SKenneth D. Merry {
451*ef270ab1SKenneth D. Merry 	if (!dma)
452*ef270ab1SKenneth D. Merry 		return -1;
453*ef270ab1SKenneth D. Merry 	if (!buffer)
454*ef270ab1SKenneth D. Merry 		return -1;
455*ef270ab1SKenneth D. Merry 	if (buffer_length == 0)
456*ef270ab1SKenneth D. Merry 		return 0;
457*ef270ab1SKenneth D. Merry 	if (buffer_length > dma->len)
458*ef270ab1SKenneth D. Merry 		buffer_length = dma->len;
459*ef270ab1SKenneth D. Merry 	ocs_memcpy(buffer, dma->virt, buffer_length);
460*ef270ab1SKenneth D. Merry 	return buffer_length;
461*ef270ab1SKenneth D. Merry }
462*ef270ab1SKenneth D. Merry 
463*ef270ab1SKenneth D. Merry /**
464*ef270ab1SKenneth D. Merry  * @ingroup os
465*ef270ab1SKenneth D. Merry  * @brief Initialize a lock
466*ef270ab1SKenneth D. Merry  *
467*ef270ab1SKenneth D. Merry  * @param lock lock to initialize
468*ef270ab1SKenneth D. Merry  * @param name string identifier for the lock
469*ef270ab1SKenneth D. Merry  */
470*ef270ab1SKenneth D. Merry void
471*ef270ab1SKenneth D. Merry ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...)
472*ef270ab1SKenneth D. Merry {
473*ef270ab1SKenneth D. Merry 	va_list ap;
474*ef270ab1SKenneth D. Merry 
475*ef270ab1SKenneth D. Merry 	va_start(ap, name);
476*ef270ab1SKenneth D. Merry 	ocs_vsnprintf(lock->name, MAX_LOCK_DESC_LEN, name, ap);
477*ef270ab1SKenneth D. Merry 	va_end(ap);
478*ef270ab1SKenneth D. Merry 
479*ef270ab1SKenneth D. Merry 	mtx_init(&lock->lock, lock->name, NULL, MTX_DEF);
480*ef270ab1SKenneth D. Merry }
481*ef270ab1SKenneth D. Merry 
482*ef270ab1SKenneth D. Merry /**
483*ef270ab1SKenneth D. Merry  * @brief Allocate a bit map
484*ef270ab1SKenneth D. Merry  *
485*ef270ab1SKenneth D. Merry  * For BSD, this is a simple character string
486*ef270ab1SKenneth D. Merry  *
487*ef270ab1SKenneth D. Merry  * @param n_bits number of bits in bit map
488*ef270ab1SKenneth D. Merry  *
489*ef270ab1SKenneth D. Merry  * @return pointer to the bit map, NULL on error
490*ef270ab1SKenneth D. Merry  */
491*ef270ab1SKenneth D. Merry ocs_bitmap_t *
492*ef270ab1SKenneth D. Merry ocs_bitmap_alloc(uint32_t n_bits)
493*ef270ab1SKenneth D. Merry {
494*ef270ab1SKenneth D. Merry 
495*ef270ab1SKenneth D. Merry 	return malloc(bitstr_size(n_bits), M_OCS, M_ZERO | M_NOWAIT);
496*ef270ab1SKenneth D. Merry }
497*ef270ab1SKenneth D. Merry 
498*ef270ab1SKenneth D. Merry /**
499*ef270ab1SKenneth D. Merry  * @brief Free a bit map
500*ef270ab1SKenneth D. Merry  *
501*ef270ab1SKenneth D. Merry  * @param bitmap pointer to previously allocated bit map
502*ef270ab1SKenneth D. Merry  */
503*ef270ab1SKenneth D. Merry void
504*ef270ab1SKenneth D. Merry ocs_bitmap_free(ocs_bitmap_t *bitmap)
505*ef270ab1SKenneth D. Merry {
506*ef270ab1SKenneth D. Merry 
507*ef270ab1SKenneth D. Merry 	free(bitmap, M_OCS);
508*ef270ab1SKenneth D. Merry }
509*ef270ab1SKenneth D. Merry 
510*ef270ab1SKenneth D. Merry /**
511*ef270ab1SKenneth D. Merry  * @brief find next unset bit and set it
512*ef270ab1SKenneth D. Merry  *
513*ef270ab1SKenneth D. Merry  * @param bitmap bit map to search
514*ef270ab1SKenneth D. Merry  * @param n_bits number of bits in map
515*ef270ab1SKenneth D. Merry  *
516*ef270ab1SKenneth D. Merry  * @return bit position or -1 if map is full
517*ef270ab1SKenneth D. Merry  */
518*ef270ab1SKenneth D. Merry int32_t
519*ef270ab1SKenneth D. Merry ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits)
520*ef270ab1SKenneth D. Merry {
521*ef270ab1SKenneth D. Merry 	int32_t		position = -1;
522*ef270ab1SKenneth D. Merry 
523*ef270ab1SKenneth D. Merry 	bit_ffc(bitmap, n_bits, &position);
524*ef270ab1SKenneth D. Merry 
525*ef270ab1SKenneth D. Merry 	if (-1 != position) {
526*ef270ab1SKenneth D. Merry 		bit_set(bitmap, position);
527*ef270ab1SKenneth D. Merry 	}
528*ef270ab1SKenneth D. Merry 
529*ef270ab1SKenneth D. Merry 	return position;
530*ef270ab1SKenneth D. Merry }
531*ef270ab1SKenneth D. Merry 
532*ef270ab1SKenneth D. Merry /**
533*ef270ab1SKenneth D. Merry  * @brief search for next (un)set bit
534*ef270ab1SKenneth D. Merry  *
535*ef270ab1SKenneth D. Merry  * @param bitmap bit map to search
536*ef270ab1SKenneth D. Merry  * @param set search for a set or unset bit
537*ef270ab1SKenneth D. Merry  * @param n_bits number of bits in map
538*ef270ab1SKenneth D. Merry  *
539*ef270ab1SKenneth D. Merry  * @return bit position or -1
540*ef270ab1SKenneth D. Merry  */
541*ef270ab1SKenneth D. Merry int32_t
542*ef270ab1SKenneth D. Merry ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits)
543*ef270ab1SKenneth D. Merry {
544*ef270ab1SKenneth D. Merry 	int32_t		position;
545*ef270ab1SKenneth D. Merry 
546*ef270ab1SKenneth D. Merry 	if (!bitmap) {
547*ef270ab1SKenneth D. Merry 		return -1;
548*ef270ab1SKenneth D. Merry 	}
549*ef270ab1SKenneth D. Merry 
550*ef270ab1SKenneth D. Merry 	if (set) {
551*ef270ab1SKenneth D. Merry 		bit_ffs(bitmap, n_bits, &position);
552*ef270ab1SKenneth D. Merry 	} else {
553*ef270ab1SKenneth D. Merry 		bit_ffc(bitmap, n_bits, &position);
554*ef270ab1SKenneth D. Merry 	}
555*ef270ab1SKenneth D. Merry 
556*ef270ab1SKenneth D. Merry 	return position;
557*ef270ab1SKenneth D. Merry }
558*ef270ab1SKenneth D. Merry 
559*ef270ab1SKenneth D. Merry /**
560*ef270ab1SKenneth D. Merry  * @brief clear the specified bit
561*ef270ab1SKenneth D. Merry  *
562*ef270ab1SKenneth D. Merry  * @param bitmap pointer to bit map
563*ef270ab1SKenneth D. Merry  * @param bit bit number to clear
564*ef270ab1SKenneth D. Merry  */
565*ef270ab1SKenneth D. Merry void
566*ef270ab1SKenneth D. Merry ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit)
567*ef270ab1SKenneth D. Merry {
568*ef270ab1SKenneth D. Merry 	bit_clear(bitmap, bit);
569*ef270ab1SKenneth D. Merry }
570*ef270ab1SKenneth D. Merry 
571*ef270ab1SKenneth D. Merry void _ocs_log(ocs_t *ocs, const char *func_name, int line, const char *fmt, ...)
572*ef270ab1SKenneth D. Merry {
573*ef270ab1SKenneth D. Merry 	va_list ap;
574*ef270ab1SKenneth D. Merry 	char buf[256];
575*ef270ab1SKenneth D. Merry 	char *p = buf;
576*ef270ab1SKenneth D. Merry 
577*ef270ab1SKenneth D. Merry 	va_start(ap, fmt);
578*ef270ab1SKenneth D. Merry 
579*ef270ab1SKenneth D. Merry 	/* TODO: Add Current PID info here. */
580*ef270ab1SKenneth D. Merry 
581*ef270ab1SKenneth D. Merry 	p += snprintf(p, sizeof(buf) - (p - buf), "%s: ", DRV_NAME);
582*ef270ab1SKenneth D. Merry 	p += snprintf(p, sizeof(buf) - (p - buf), "%s:", func_name);
583*ef270ab1SKenneth D. Merry 	p += snprintf(p, sizeof(buf) - (p - buf), "%i:", line);
584*ef270ab1SKenneth D. Merry 	p += snprintf(p, sizeof(buf) - (p - buf), "%s:", (ocs != NULL) ? device_get_nameunit(ocs->dev) : "");
585*ef270ab1SKenneth D. Merry 	p += vsnprintf(p, sizeof(buf) - (p - buf), fmt, ap);
586*ef270ab1SKenneth D. Merry 
587*ef270ab1SKenneth D. Merry 	va_end(ap);
588*ef270ab1SKenneth D. Merry 
589*ef270ab1SKenneth D. Merry 	printf("%s", buf);
590*ef270ab1SKenneth D. Merry }
591*ef270ab1SKenneth D. Merry 
592*ef270ab1SKenneth D. Merry /**
593*ef270ab1SKenneth D. Merry  * @brief Common thread call function
594*ef270ab1SKenneth D. Merry  *
595*ef270ab1SKenneth D. Merry  * This is the common function called whenever a thread instantiated by ocs_thread_create() is started.
596*ef270ab1SKenneth D. Merry  * It captures the return value from the actual thread function and stashes it in the thread object, to
597*ef270ab1SKenneth D. Merry  * be later retrieved by ocs_thread_get_retval(), and calls kthread_exit(), the proscribed method to terminate
598*ef270ab1SKenneth D. Merry  * a thread.
599*ef270ab1SKenneth D. Merry  *
600*ef270ab1SKenneth D. Merry  * @param arg a pointer to the thread object
601*ef270ab1SKenneth D. Merry  *
602*ef270ab1SKenneth D. Merry  * @return none
603*ef270ab1SKenneth D. Merry  */
604*ef270ab1SKenneth D. Merry 
605*ef270ab1SKenneth D. Merry static void
606*ef270ab1SKenneth D. Merry ocs_thread_call_fctn(void *arg)
607*ef270ab1SKenneth D. Merry {
608*ef270ab1SKenneth D. Merry 	ocs_thread_t *thread = arg;
609*ef270ab1SKenneth D. Merry 	thread->retval = (*thread->fctn)(thread->arg);
610*ef270ab1SKenneth D. Merry 	ocs_free(NULL, thread->name, ocs_strlen(thread->name+1));
611*ef270ab1SKenneth D. Merry 	kthread_exit();
612*ef270ab1SKenneth D. Merry }
613*ef270ab1SKenneth D. Merry 
614*ef270ab1SKenneth D. Merry /**
615*ef270ab1SKenneth D. Merry  * @brief Create a kernel thread
616*ef270ab1SKenneth D. Merry  *
617*ef270ab1SKenneth D. Merry  * Creates a kernel thread and optionally starts it.   If the thread is not immediately
618*ef270ab1SKenneth D. Merry  * started, ocs_thread_start() should be called at some later point.
619*ef270ab1SKenneth D. Merry  *
620*ef270ab1SKenneth D. Merry  * @param os OS handle
621*ef270ab1SKenneth D. Merry  * @param thread pointer to thread object
622*ef270ab1SKenneth D. Merry  * @param fctn function for thread to be begin executing
623*ef270ab1SKenneth D. Merry  * @param name text name to identify thread
624*ef270ab1SKenneth D. Merry  * @param arg application specific argument passed to thread function
625*ef270ab1SKenneth D. Merry  * @param start start option, OCS_THREAD_RUN will start the thread immediately,
626*ef270ab1SKenneth D. Merry  *			OCS_THREAD_CREATE will create but not start the thread
627*ef270ab1SKenneth D. Merry  *
628*ef270ab1SKenneth D. Merry  * @return returns 0 for success, a negative error code value for failure.
629*ef270ab1SKenneth D. Merry  */
630*ef270ab1SKenneth D. Merry 
631*ef270ab1SKenneth D. Merry int32_t
632*ef270ab1SKenneth D. Merry ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn, const char *name, void *arg, ocs_thread_start_e start)
633*ef270ab1SKenneth D. Merry {
634*ef270ab1SKenneth D. Merry 	int32_t rc = 0;
635*ef270ab1SKenneth D. Merry 
636*ef270ab1SKenneth D. Merry 	ocs_memset(thread, 0, sizeof(thread));
637*ef270ab1SKenneth D. Merry 
638*ef270ab1SKenneth D. Merry 	thread->fctn = fctn;
639*ef270ab1SKenneth D. Merry 	thread->name = ocs_strdup(name);
640*ef270ab1SKenneth D. Merry 	if (thread->name == NULL) {
641*ef270ab1SKenneth D. Merry 		thread->name = "unknown";
642*ef270ab1SKenneth D. Merry 	}
643*ef270ab1SKenneth D. Merry 	thread->arg = arg;
644*ef270ab1SKenneth D. Merry 
645*ef270ab1SKenneth D. Merry 	ocs_atomic_set(&thread->terminate, 0);
646*ef270ab1SKenneth D. Merry 
647*ef270ab1SKenneth D. Merry 	rc = kthread_add(ocs_thread_call_fctn, thread, NULL, &thread->tcb, (start == OCS_THREAD_CREATE) ? RFSTOPPED : 0,
648*ef270ab1SKenneth D. Merry 		OCS_THREAD_DEFAULT_STACK_SIZE_PAGES, "%s", name);
649*ef270ab1SKenneth D. Merry 
650*ef270ab1SKenneth D. Merry 	return rc;
651*ef270ab1SKenneth D. Merry }
652*ef270ab1SKenneth D. Merry 
653*ef270ab1SKenneth D. Merry /**
654*ef270ab1SKenneth D. Merry  * @brief Start a thread
655*ef270ab1SKenneth D. Merry  *
656*ef270ab1SKenneth D. Merry  * Starts a thread that was created with OCS_THREAD_CREATE rather than OCS_THREAD_RUN
657*ef270ab1SKenneth D. Merry  *
658*ef270ab1SKenneth D. Merry  * @param thread pointer to thread object
659*ef270ab1SKenneth D. Merry  *
660*ef270ab1SKenneth D. Merry  * @return returns 0 for success, a negative error code value for failure.
661*ef270ab1SKenneth D. Merry  */
662*ef270ab1SKenneth D. Merry 
663*ef270ab1SKenneth D. Merry int32_t ocs_thread_start(ocs_thread_t *thread)
664*ef270ab1SKenneth D. Merry {
665*ef270ab1SKenneth D. Merry 	sched_add(thread->tcb, SRQ_BORING);
666*ef270ab1SKenneth D. Merry 	return 0;
667*ef270ab1SKenneth D. Merry }
668*ef270ab1SKenneth D. Merry 
669*ef270ab1SKenneth D. Merry /**
670*ef270ab1SKenneth D. Merry  * @brief return thread argument
671*ef270ab1SKenneth D. Merry  *
672*ef270ab1SKenneth D. Merry  * Returns a pointer to the thread's application specific argument
673*ef270ab1SKenneth D. Merry  *
674*ef270ab1SKenneth D. Merry  * @param mythread pointer to the thread object
675*ef270ab1SKenneth D. Merry  *
676*ef270ab1SKenneth D. Merry  * @return pointer to application specific argument
677*ef270ab1SKenneth D. Merry  */
678*ef270ab1SKenneth D. Merry 
679*ef270ab1SKenneth D. Merry void *ocs_thread_get_arg(ocs_thread_t *mythread)
680*ef270ab1SKenneth D. Merry {
681*ef270ab1SKenneth D. Merry 	return mythread->arg;
682*ef270ab1SKenneth D. Merry }
683*ef270ab1SKenneth D. Merry 
684*ef270ab1SKenneth D. Merry /**
685*ef270ab1SKenneth D. Merry  * @brief Request thread stop
686*ef270ab1SKenneth D. Merry  *
687*ef270ab1SKenneth D. Merry  * A stop request is made to the thread.  This is a voluntary call, the thread needs
688*ef270ab1SKenneth D. Merry  * to periodically query its terminate request using ocs_thread_terminate_requested()
689*ef270ab1SKenneth D. Merry  *
690*ef270ab1SKenneth D. Merry  * @param thread pointer to thread object
691*ef270ab1SKenneth D. Merry  *
692*ef270ab1SKenneth D. Merry  * @return returns 0 for success, a negative error code value for failure.
693*ef270ab1SKenneth D. Merry  */
694*ef270ab1SKenneth D. Merry 
695*ef270ab1SKenneth D. Merry int32_t
696*ef270ab1SKenneth D. Merry ocs_thread_terminate(ocs_thread_t *thread)
697*ef270ab1SKenneth D. Merry {
698*ef270ab1SKenneth D. Merry 	ocs_atomic_set(&thread->terminate, 1);
699*ef270ab1SKenneth D. Merry 	return 0;
700*ef270ab1SKenneth D. Merry }
701*ef270ab1SKenneth D. Merry 
702*ef270ab1SKenneth D. Merry /**
703*ef270ab1SKenneth D. Merry  * @brief See if a terminate request has been made
704*ef270ab1SKenneth D. Merry  *
705*ef270ab1SKenneth D. Merry  * Check to see if a stop request has been made to the current thread.  This
706*ef270ab1SKenneth D. Merry  * function would be used by a thread to see if it should terminate.
707*ef270ab1SKenneth D. Merry  *
708*ef270ab1SKenneth D. Merry  * @return returns non-zero if a stop has been requested
709*ef270ab1SKenneth D. Merry  */
710*ef270ab1SKenneth D. Merry 
711*ef270ab1SKenneth D. Merry int32_t ocs_thread_terminate_requested(ocs_thread_t *thread)
712*ef270ab1SKenneth D. Merry {
713*ef270ab1SKenneth D. Merry 	return ocs_atomic_read(&thread->terminate);
714*ef270ab1SKenneth D. Merry }
715*ef270ab1SKenneth D. Merry 
716*ef270ab1SKenneth D. Merry /**
717*ef270ab1SKenneth D. Merry  * @brief Retrieve threads return value
718*ef270ab1SKenneth D. Merry  *
719*ef270ab1SKenneth D. Merry  * After a thread has terminated, it's return value may be retrieved with this function.
720*ef270ab1SKenneth D. Merry  *
721*ef270ab1SKenneth D. Merry  * @param thread pointer to thread object
722*ef270ab1SKenneth D. Merry  *
723*ef270ab1SKenneth D. Merry  * @return return value from thread function
724*ef270ab1SKenneth D. Merry  */
725*ef270ab1SKenneth D. Merry 
726*ef270ab1SKenneth D. Merry int32_t
727*ef270ab1SKenneth D. Merry ocs_thread_get_retval(ocs_thread_t *thread)
728*ef270ab1SKenneth D. Merry {
729*ef270ab1SKenneth D. Merry 	return thread->retval;
730*ef270ab1SKenneth D. Merry }
731*ef270ab1SKenneth D. Merry 
732*ef270ab1SKenneth D. Merry /**
733*ef270ab1SKenneth D. Merry  * @brief Request that the currently running thread yield
734*ef270ab1SKenneth D. Merry  *
735*ef270ab1SKenneth D. Merry  * The currently running thread yields to the scheduler
736*ef270ab1SKenneth D. Merry  *
737*ef270ab1SKenneth D. Merry  * @param thread pointer to thread (ignored)
738*ef270ab1SKenneth D. Merry  *
739*ef270ab1SKenneth D. Merry  * @return none
740*ef270ab1SKenneth D. Merry  */
741*ef270ab1SKenneth D. Merry 
742*ef270ab1SKenneth D. Merry void
743*ef270ab1SKenneth D. Merry ocs_thread_yield(ocs_thread_t *thread) {
744*ef270ab1SKenneth D. Merry 	pause("thread yield", 1);
745*ef270ab1SKenneth D. Merry }
746*ef270ab1SKenneth D. Merry 
747*ef270ab1SKenneth D. Merry ocs_thread_t *
748*ef270ab1SKenneth D. Merry ocs_thread_self(void)
749*ef270ab1SKenneth D. Merry {
750*ef270ab1SKenneth D. Merry 	ocs_printf(">>> %s not implemented\n", __func__);
751*ef270ab1SKenneth D. Merry 	ocs_abort();
752*ef270ab1SKenneth D. Merry }
753*ef270ab1SKenneth D. Merry 
754*ef270ab1SKenneth D. Merry int32_t
755*ef270ab1SKenneth D. Merry ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu)
756*ef270ab1SKenneth D. Merry {
757*ef270ab1SKenneth D. Merry 	ocs_printf(">>> %s not implemented\n", __func__);
758*ef270ab1SKenneth D. Merry 	return -1;
759*ef270ab1SKenneth D. Merry }
760*ef270ab1SKenneth D. Merry 
761*ef270ab1SKenneth D. Merry int32_t
762*ef270ab1SKenneth D. Merry ocs_thread_getcpu(void)
763*ef270ab1SKenneth D. Merry {
764*ef270ab1SKenneth D. Merry 	return curcpu;
765*ef270ab1SKenneth D. Merry }
766*ef270ab1SKenneth D. Merry 
767*ef270ab1SKenneth D. Merry int
768*ef270ab1SKenneth D. Merry ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...)
769*ef270ab1SKenneth D. Merry {
770*ef270ab1SKenneth D. Merry 	va_list ap;
771*ef270ab1SKenneth D. Merry 
772*ef270ab1SKenneth D. Merry 	va_start(ap, name);
773*ef270ab1SKenneth D. Merry 	ocs_vsnprintf(sem->name, sizeof(sem->name), name, ap);
774*ef270ab1SKenneth D. Merry 	va_end(ap);
775*ef270ab1SKenneth D. Merry 
776*ef270ab1SKenneth D. Merry 	sema_init(&sem->sem, val, sem->name);
777*ef270ab1SKenneth D. Merry 	return 0;
778*ef270ab1SKenneth D. Merry }
779*ef270ab1SKenneth D. Merry 
780*ef270ab1SKenneth D. Merry /**
781*ef270ab1SKenneth D. Merry  * @ingroup os
782*ef270ab1SKenneth D. Merry  * @brief  Copy user arguments in to kernel space for an ioctl
783*ef270ab1SKenneth D. Merry  * @par Description
784*ef270ab1SKenneth D. Merry  * This function is called at the beginning of an ioctl function
785*ef270ab1SKenneth D. Merry  * to copy the ioctl argument from user space to kernel space.
786*ef270ab1SKenneth D. Merry  *
787*ef270ab1SKenneth D. Merry  * BSD handles this for us - arg is already in kernel space,
788*ef270ab1SKenneth D. Merry  * so we just return it.
789*ef270ab1SKenneth D. Merry  *
790*ef270ab1SKenneth D. Merry  * @param os OS handle
791*ef270ab1SKenneth D. Merry  * @param arg The argument passed to the ioctl function
792*ef270ab1SKenneth D. Merry  * @param size The size of the structure pointed to by arg
793*ef270ab1SKenneth D. Merry  *
794*ef270ab1SKenneth D. Merry  * @return A pointer to a kernel space copy of the argument on
795*ef270ab1SKenneth D. Merry  *	success; NULL on failure
796*ef270ab1SKenneth D. Merry  */
797*ef270ab1SKenneth D. Merry void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size)
798*ef270ab1SKenneth D. Merry {
799*ef270ab1SKenneth D. Merry 	 return arg;
800*ef270ab1SKenneth D. Merry }
801*ef270ab1SKenneth D. Merry 
802*ef270ab1SKenneth D. Merry /**
803*ef270ab1SKenneth D. Merry  * @ingroup os
804*ef270ab1SKenneth D. Merry  * @brief  Copy results of an ioctl back to user space
805*ef270ab1SKenneth D. Merry  * @par Description
806*ef270ab1SKenneth D. Merry  * This function is called at the end of ioctl processing to
807*ef270ab1SKenneth D. Merry  * copy the argument back to user space.
808*ef270ab1SKenneth D. Merry  *
809*ef270ab1SKenneth D. Merry  * BSD handles this for us.
810*ef270ab1SKenneth D. Merry  *
811*ef270ab1SKenneth D. Merry  * @param os OS handle
812*ef270ab1SKenneth D. Merry  * @param arg The argument passed to the ioctl function
813*ef270ab1SKenneth D. Merry  * @param kern_ptr A pointer to the kernel space copy of the
814*ef270ab1SKenneth D. Merry  *		   argument
815*ef270ab1SKenneth D. Merry  * @param size The size of the structure pointed to by arg.
816*ef270ab1SKenneth D. Merry  *
817*ef270ab1SKenneth D. Merry  * @return Returns 0.
818*ef270ab1SKenneth D. Merry  */
819*ef270ab1SKenneth D. Merry int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size)
820*ef270ab1SKenneth D. Merry {
821*ef270ab1SKenneth D. Merry 	return 0;
822*ef270ab1SKenneth D. Merry }
823*ef270ab1SKenneth D. Merry 
824*ef270ab1SKenneth D. Merry /**
825*ef270ab1SKenneth D. Merry  * @ingroup os
826*ef270ab1SKenneth D. Merry  * @brief  Free memory allocated by ocs_ioctl_preprocess
827*ef270ab1SKenneth D. Merry  * @par Description
828*ef270ab1SKenneth D. Merry  * This function is called in the event of an error in ioctl
829*ef270ab1SKenneth D. Merry  * processing.  For operating environments where ocs_ioctlpreprocess
830*ef270ab1SKenneth D. Merry  * allocates memory, this call frees the memory without copying
831*ef270ab1SKenneth D. Merry  * results back to user space.
832*ef270ab1SKenneth D. Merry  *
833*ef270ab1SKenneth D. Merry  * For BSD, because no memory was allocated in ocs_ioctl_preprocess,
834*ef270ab1SKenneth D. Merry  * nothing needs to be done here.
835*ef270ab1SKenneth D. Merry  *
836*ef270ab1SKenneth D. Merry  * @param os OS handle
837*ef270ab1SKenneth D. Merry  * @param kern_ptr A pointer to the kernel space copy of the
838*ef270ab1SKenneth D. Merry  *		   argument
839*ef270ab1SKenneth D. Merry  * @param size The size of the structure pointed to by arg.
840*ef270ab1SKenneth D. Merry  *
841*ef270ab1SKenneth D. Merry  * @return Returns nothing.
842*ef270ab1SKenneth D. Merry  */
843*ef270ab1SKenneth D. Merry void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size)
844*ef270ab1SKenneth D. Merry {
845*ef270ab1SKenneth D. Merry 	return;
846*ef270ab1SKenneth D. Merry }
847*ef270ab1SKenneth D. Merry 
848*ef270ab1SKenneth D. Merry void ocs_intr_disable(ocs_os_handle_t os)
849*ef270ab1SKenneth D. Merry {
850*ef270ab1SKenneth D. Merry }
851*ef270ab1SKenneth D. Merry 
852*ef270ab1SKenneth D. Merry void ocs_intr_enable(ocs_os_handle_t os)
853*ef270ab1SKenneth D. Merry {
854*ef270ab1SKenneth D. Merry }
855*ef270ab1SKenneth D. Merry 
856*ef270ab1SKenneth D. Merry void ocs_print_stack(void)
857*ef270ab1SKenneth D. Merry {
858*ef270ab1SKenneth D. Merry 	struct stack st;
859*ef270ab1SKenneth D. Merry 
860*ef270ab1SKenneth D. Merry 	stack_zero(&st);
861*ef270ab1SKenneth D. Merry 	stack_save(&st);
862*ef270ab1SKenneth D. Merry 	stack_print(&st);
863*ef270ab1SKenneth D. Merry }
864*ef270ab1SKenneth D. Merry 
865*ef270ab1SKenneth D. Merry void ocs_abort(void)
866*ef270ab1SKenneth D. Merry {
867*ef270ab1SKenneth D. Merry 	panic(">>> abort/panic\n");
868*ef270ab1SKenneth D. Merry }
869*ef270ab1SKenneth D. Merry 
870*ef270ab1SKenneth D. Merry const char *
871*ef270ab1SKenneth D. Merry ocs_pci_model(uint16_t vendor, uint16_t device)
872*ef270ab1SKenneth D. Merry {
873*ef270ab1SKenneth D. Merry 	switch (device) {
874*ef270ab1SKenneth D. Merry 	case PCI_PRODUCT_EMULEX_OCE16002:	return "OCE16002";
875*ef270ab1SKenneth D. Merry 	case PCI_PRODUCT_EMULEX_OCE1600_VF:	return "OCE1600_VF";
876*ef270ab1SKenneth D. Merry 	case PCI_PRODUCT_EMULEX_OCE50102:	return "OCE50102";
877*ef270ab1SKenneth D. Merry 	case PCI_PRODUCT_EMULEX_OCE50102_VF:	return "OCE50102_VR";
878*ef270ab1SKenneth D. Merry 	default:
879*ef270ab1SKenneth D. Merry 		break;
880*ef270ab1SKenneth D. Merry 	}
881*ef270ab1SKenneth D. Merry 
882*ef270ab1SKenneth D. Merry 	return "unknown";
883*ef270ab1SKenneth D. Merry }
884*ef270ab1SKenneth D. Merry 
885*ef270ab1SKenneth D. Merry int32_t
886*ef270ab1SKenneth D. Merry ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func)
887*ef270ab1SKenneth D. Merry {
888*ef270ab1SKenneth D. Merry 	*bus = pci_get_bus(ocs->dev);
889*ef270ab1SKenneth D. Merry 	*dev = pci_get_slot(ocs->dev);
890*ef270ab1SKenneth D. Merry 	*func= pci_get_function(ocs->dev);
891*ef270ab1SKenneth D. Merry 	return 0;
892*ef270ab1SKenneth D. Merry }
893*ef270ab1SKenneth D. Merry 
894*ef270ab1SKenneth D. Merry /**
895*ef270ab1SKenneth D. Merry  * @brief return CPU information
896*ef270ab1SKenneth D. Merry  *
897*ef270ab1SKenneth D. Merry  * This function populates the ocs_cpuinfo_t buffer with CPU information
898*ef270ab1SKenneth D. Merry  *
899*ef270ab1SKenneth D. Merry  * @param cpuinfo pointer to ocs_cpuinfo_t buffer
900*ef270ab1SKenneth D. Merry  *
901*ef270ab1SKenneth D. Merry  * @return returns 0 for success, a negative error code value for failure.
902*ef270ab1SKenneth D. Merry  */
903*ef270ab1SKenneth D. Merry extern int mp_ncpus;
904*ef270ab1SKenneth D. Merry int32_t
905*ef270ab1SKenneth D. Merry ocs_get_cpuinfo(ocs_cpuinfo_t *cpuinfo)
906*ef270ab1SKenneth D. Merry {
907*ef270ab1SKenneth D. Merry 	cpuinfo->num_cpus = mp_ncpus;
908*ef270ab1SKenneth D. Merry 	return 0;
909*ef270ab1SKenneth D. Merry }
910*ef270ab1SKenneth D. Merry 
911*ef270ab1SKenneth D. Merry uint32_t
912*ef270ab1SKenneth D. Merry ocs_get_num_cpus(void)
913*ef270ab1SKenneth D. Merry {
914*ef270ab1SKenneth D. Merry 	static ocs_cpuinfo_t cpuinfo;
915*ef270ab1SKenneth D. Merry 
916*ef270ab1SKenneth D. Merry 	if (cpuinfo.num_cpus == 0) {
917*ef270ab1SKenneth D. Merry 		ocs_get_cpuinfo(&cpuinfo);
918*ef270ab1SKenneth D. Merry 	}
919*ef270ab1SKenneth D. Merry 	return cpuinfo.num_cpus;
920*ef270ab1SKenneth D. Merry }
921*ef270ab1SKenneth D. Merry 
922*ef270ab1SKenneth D. Merry 
923*ef270ab1SKenneth D. Merry void
924*ef270ab1SKenneth D. Merry __ocs_callout(void *t)
925*ef270ab1SKenneth D. Merry {
926*ef270ab1SKenneth D. Merry 	ocs_timer_t *timer = t;
927*ef270ab1SKenneth D. Merry 
928*ef270ab1SKenneth D. Merry 	if (callout_pending(&timer->callout)) {
929*ef270ab1SKenneth D. Merry 		/* Callout was reset */
930*ef270ab1SKenneth D. Merry 		return;
931*ef270ab1SKenneth D. Merry 	}
932*ef270ab1SKenneth D. Merry 
933*ef270ab1SKenneth D. Merry 	if (!callout_active(&timer->callout)) {
934*ef270ab1SKenneth D. Merry 		/* Callout was stopped */
935*ef270ab1SKenneth D. Merry 		return;
936*ef270ab1SKenneth D. Merry 	}
937*ef270ab1SKenneth D. Merry 
938*ef270ab1SKenneth D. Merry 	callout_deactivate(&timer->callout);
939*ef270ab1SKenneth D. Merry 
940*ef270ab1SKenneth D. Merry 	if (timer->func) {
941*ef270ab1SKenneth D. Merry 		timer->func(timer->data);
942*ef270ab1SKenneth D. Merry 	}
943*ef270ab1SKenneth D. Merry }
944*ef270ab1SKenneth D. Merry 
945*ef270ab1SKenneth D. Merry int32_t
946*ef270ab1SKenneth D. Merry ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg), void *data, uint32_t timeout_ms)
947*ef270ab1SKenneth D. Merry {
948*ef270ab1SKenneth D. Merry 	struct	timeval tv;
949*ef270ab1SKenneth D. Merry 	int	hz;
950*ef270ab1SKenneth D. Merry 
951*ef270ab1SKenneth D. Merry 	if (timer == NULL) {
952*ef270ab1SKenneth D. Merry 		ocs_log_err(NULL, "bad parameter\n");
953*ef270ab1SKenneth D. Merry 		return -1;
954*ef270ab1SKenneth D. Merry 	}
955*ef270ab1SKenneth D. Merry 
956*ef270ab1SKenneth D. Merry 	if (!mtx_initialized(&timer->lock)) {
957*ef270ab1SKenneth D. Merry 		mtx_init(&timer->lock, "ocs_timer", NULL, MTX_DEF);
958*ef270ab1SKenneth D. Merry 	}
959*ef270ab1SKenneth D. Merry 
960*ef270ab1SKenneth D. Merry 	callout_init_mtx(&timer->callout, &timer->lock, 0);
961*ef270ab1SKenneth D. Merry 
962*ef270ab1SKenneth D. Merry 	timer->func = func;
963*ef270ab1SKenneth D. Merry 	timer->data = data;
964*ef270ab1SKenneth D. Merry 
965*ef270ab1SKenneth D. Merry 	tv.tv_sec  = timeout_ms / 1000;
966*ef270ab1SKenneth D. Merry 	tv.tv_usec = (timeout_ms % 1000) * 1000;
967*ef270ab1SKenneth D. Merry 
968*ef270ab1SKenneth D. Merry 	hz = tvtohz(&tv);
969*ef270ab1SKenneth D. Merry 	if (hz < 0)
970*ef270ab1SKenneth D. Merry 		hz = INT32_MAX;
971*ef270ab1SKenneth D. Merry 	if (hz == 0)
972*ef270ab1SKenneth D. Merry 		hz = 1;
973*ef270ab1SKenneth D. Merry 
974*ef270ab1SKenneth D. Merry 	mtx_lock(&timer->lock);
975*ef270ab1SKenneth D. Merry 		callout_reset(&timer->callout, hz, __ocs_callout, timer);
976*ef270ab1SKenneth D. Merry 	mtx_unlock(&timer->lock);
977*ef270ab1SKenneth D. Merry 
978*ef270ab1SKenneth D. Merry 	return 0;
979*ef270ab1SKenneth D. Merry }
980*ef270ab1SKenneth D. Merry 
981*ef270ab1SKenneth D. Merry int32_t
982*ef270ab1SKenneth D. Merry ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms)
983*ef270ab1SKenneth D. Merry {
984*ef270ab1SKenneth D. Merry 	struct	timeval tv;
985*ef270ab1SKenneth D. Merry 	int	hz;
986*ef270ab1SKenneth D. Merry 
987*ef270ab1SKenneth D. Merry 	if (timer == NULL) {
988*ef270ab1SKenneth D. Merry 		ocs_log_err(NULL, "bad parameter\n");
989*ef270ab1SKenneth D. Merry 		return -1;
990*ef270ab1SKenneth D. Merry 	}
991*ef270ab1SKenneth D. Merry 
992*ef270ab1SKenneth D. Merry 	tv.tv_sec  = timeout_ms / 1000;
993*ef270ab1SKenneth D. Merry 	tv.tv_usec = (timeout_ms % 1000) * 1000;
994*ef270ab1SKenneth D. Merry 
995*ef270ab1SKenneth D. Merry 	hz = tvtohz(&tv);
996*ef270ab1SKenneth D. Merry 	if (hz < 0)
997*ef270ab1SKenneth D. Merry 		hz = INT32_MAX;
998*ef270ab1SKenneth D. Merry 	if (hz == 0)
999*ef270ab1SKenneth D. Merry 		hz = 1;
1000*ef270ab1SKenneth D. Merry 
1001*ef270ab1SKenneth D. Merry 	mtx_lock(&timer->lock);
1002*ef270ab1SKenneth D. Merry 		callout_reset(&timer->callout, hz, __ocs_callout, timer);
1003*ef270ab1SKenneth D. Merry 	mtx_unlock(&timer->lock);
1004*ef270ab1SKenneth D. Merry 
1005*ef270ab1SKenneth D. Merry 	return 0;
1006*ef270ab1SKenneth D. Merry }
1007*ef270ab1SKenneth D. Merry 
1008*ef270ab1SKenneth D. Merry int32_t
1009*ef270ab1SKenneth D. Merry ocs_timer_pending(ocs_timer_t *timer)
1010*ef270ab1SKenneth D. Merry {
1011*ef270ab1SKenneth D. Merry 	return callout_active(&timer->callout);
1012*ef270ab1SKenneth D. Merry }
1013*ef270ab1SKenneth D. Merry 
1014*ef270ab1SKenneth D. Merry int32_t
1015*ef270ab1SKenneth D. Merry ocs_del_timer(ocs_timer_t *timer)
1016*ef270ab1SKenneth D. Merry {
1017*ef270ab1SKenneth D. Merry 
1018*ef270ab1SKenneth D. Merry 	mtx_lock(&timer->lock);
1019*ef270ab1SKenneth D. Merry 		callout_stop(&timer->callout);
1020*ef270ab1SKenneth D. Merry 	mtx_unlock(&timer->lock);
1021*ef270ab1SKenneth D. Merry 
1022*ef270ab1SKenneth D. Merry 	return 0;
1023*ef270ab1SKenneth D. Merry }
1024*ef270ab1SKenneth D. Merry 
1025*ef270ab1SKenneth D. Merry char *
1026*ef270ab1SKenneth D. Merry ocs_strdup(const char *s)
1027*ef270ab1SKenneth D. Merry {
1028*ef270ab1SKenneth D. Merry 	uint32_t l = strlen(s);
1029*ef270ab1SKenneth D. Merry 	char *d;
1030*ef270ab1SKenneth D. Merry 
1031*ef270ab1SKenneth D. Merry 	d = ocs_malloc(NULL, l+1, OCS_M_NOWAIT);
1032*ef270ab1SKenneth D. Merry 	if (d != NULL) {
1033*ef270ab1SKenneth D. Merry 		ocs_strcpy(d, s);
1034*ef270ab1SKenneth D. Merry 	}
1035*ef270ab1SKenneth D. Merry 	return d;
1036*ef270ab1SKenneth D. Merry }
1037*ef270ab1SKenneth D. Merry 
1038*ef270ab1SKenneth D. Merry void
1039*ef270ab1SKenneth D. Merry _ocs_assert(const char *cond, const char *filename, int linenum)
1040*ef270ab1SKenneth D. Merry {
1041*ef270ab1SKenneth D. Merry 	const char *fn = strrchr(__FILE__, '/');
1042*ef270ab1SKenneth D. Merry 
1043*ef270ab1SKenneth D. Merry 	ocs_log_err(NULL, "%s(%d) assertion (%s) failed\n", (fn ? fn + 1 : filename), linenum, cond);
1044*ef270ab1SKenneth D. Merry 	ocs_print_stack();
1045*ef270ab1SKenneth D. Merry 	ocs_save_ddump_all(OCS_DDUMP_FLAGS_WQES|OCS_DDUMP_FLAGS_CQES|OCS_DDUMP_FLAGS_MQES, -1, TRUE);
1046*ef270ab1SKenneth D. Merry }
1047