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