Branch data Line data Source code
1 : : /* =========================================================================
2 : : * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
3 : : * $Revision: #14 $
4 : : * $Date: 2010/11/04 $
5 : : * $Change: 1621695 $
6 : : *
7 : : * Synopsys Portability Library Software and documentation
8 : : * (hereinafter, "Software") is an Unsupported proprietary work of
9 : : * Synopsys, Inc. unless otherwise expressly agreed to in writing
10 : : * between Synopsys and you.
11 : : *
12 : : * The Software IS NOT an item of Licensed Software or Licensed Product
13 : : * under any End User Software License Agreement or Agreement for
14 : : * Licensed Product with Synopsys or any supplement thereto. You are
15 : : * permitted to use and redistribute this Software in source and binary
16 : : * forms, with or without modification, provided that redistributions
17 : : * of source code must retain this notice. You may not view, use,
18 : : * disclose, copy or distribute this file or any information contained
19 : : * herein except pursuant to this license grant from Synopsys. If you
20 : : * do not agree with this notice, including the disclaimer below, then
21 : : * you are not authorized to use the Software.
22 : : *
23 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
24 : : * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 : : * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
27 : : * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
31 : : * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33 : : * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34 : : * DAMAGE.
35 : : * ========================================================================= */
36 : : #ifndef _DWC_OS_H_
37 : : #define _DWC_OS_H_
38 : :
39 : : #ifdef __cplusplus
40 : : extern "C" {
41 : : #endif
42 : :
43 : : /** @file
44 : : *
45 : : * DWC portability library, low level os-wrapper functions
46 : : *
47 : : */
48 : :
49 : : /* These basic types need to be defined by some OS header file or custom header
50 : : * file for your specific target architecture.
51 : : *
52 : : * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t
53 : : *
54 : : * Any custom or alternate header file must be added and enabled here.
55 : : */
56 : :
57 : : #ifdef DWC_LINUX
58 : : # include <linux/types.h>
59 : : # ifdef CONFIG_DEBUG_MUTEXES
60 : : # include <linux/mutex.h>
61 : : # endif
62 : : # include <linux/spinlock.h>
63 : : # include <linux/errno.h>
64 : : # include <stdarg.h>
65 : : #endif
66 : :
67 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
68 : : # include <os_dep.h>
69 : : #endif
70 : :
71 : :
72 : : /** @name Primitive Types and Values */
73 : :
74 : : /** We define a boolean type for consistency. Can be either YES or NO */
75 : : typedef uint8_t dwc_bool_t;
76 : : #define YES 1
77 : : #define NO 0
78 : :
79 : : #ifdef DWC_LINUX
80 : :
81 : : /** @name Error Codes */
82 : : #define DWC_E_INVALID EINVAL
83 : : #define DWC_E_NO_MEMORY ENOMEM
84 : : #define DWC_E_NO_DEVICE ENODEV
85 : : #define DWC_E_NOT_SUPPORTED EOPNOTSUPP
86 : : #define DWC_E_TIMEOUT ETIMEDOUT
87 : : #define DWC_E_BUSY EBUSY
88 : : #define DWC_E_AGAIN EAGAIN
89 : : #define DWC_E_RESTART ERESTART
90 : : #define DWC_E_ABORT ECONNABORTED
91 : : #define DWC_E_SHUTDOWN ESHUTDOWN
92 : : #define DWC_E_NO_DATA ENODATA
93 : : #define DWC_E_DISCONNECT ECONNRESET
94 : : #define DWC_E_UNKNOWN EINVAL
95 : : #define DWC_E_NO_STREAM_RES ENOSR
96 : : #define DWC_E_COMMUNICATION ECOMM
97 : : #define DWC_E_OVERFLOW EOVERFLOW
98 : : #define DWC_E_PROTOCOL EPROTO
99 : : #define DWC_E_IN_PROGRESS EINPROGRESS
100 : : #define DWC_E_PIPE EPIPE
101 : : #define DWC_E_IO EIO
102 : : #define DWC_E_NO_SPACE ENOSPC
103 : :
104 : : #else
105 : :
106 : : /** @name Error Codes */
107 : : #define DWC_E_INVALID 1001
108 : : #define DWC_E_NO_MEMORY 1002
109 : : #define DWC_E_NO_DEVICE 1003
110 : : #define DWC_E_NOT_SUPPORTED 1004
111 : : #define DWC_E_TIMEOUT 1005
112 : : #define DWC_E_BUSY 1006
113 : : #define DWC_E_AGAIN 1007
114 : : #define DWC_E_RESTART 1008
115 : : #define DWC_E_ABORT 1009
116 : : #define DWC_E_SHUTDOWN 1010
117 : : #define DWC_E_NO_DATA 1011
118 : : #define DWC_E_DISCONNECT 2000
119 : : #define DWC_E_UNKNOWN 3000
120 : : #define DWC_E_NO_STREAM_RES 4001
121 : : #define DWC_E_COMMUNICATION 4002
122 : : #define DWC_E_OVERFLOW 4003
123 : : #define DWC_E_PROTOCOL 4004
124 : : #define DWC_E_IN_PROGRESS 4005
125 : : #define DWC_E_PIPE 4006
126 : : #define DWC_E_IO 4007
127 : : #define DWC_E_NO_SPACE 4008
128 : :
129 : : #endif
130 : :
131 : :
132 : : /** @name Tracing/Logging Functions
133 : : *
134 : : * These function provide the capability to add tracing, debugging, and error
135 : : * messages, as well exceptions as assertions. The WUDEV uses these
136 : : * extensively. These could be logged to the main console, the serial port, an
137 : : * internal buffer, etc. These functions could also be no-op if they are too
138 : : * expensive on your system. By default undefining the DEBUG macro already
139 : : * no-ops some of these functions. */
140 : :
141 : : /** Returns non-zero if in interrupt context. */
142 : : extern dwc_bool_t DWC_IN_IRQ(void);
143 : : #define dwc_in_irq DWC_IN_IRQ
144 : :
145 : : /** Returns "IRQ" if DWC_IN_IRQ is true. */
146 : : static inline char *dwc_irq(void) {
147 : 3 : return DWC_IN_IRQ() ? "IRQ" : "";
148 : : }
149 : :
150 : : /** Returns non-zero if in bottom-half context. */
151 : : extern dwc_bool_t DWC_IN_BH(void);
152 : : #define dwc_in_bh DWC_IN_BH
153 : :
154 : : /** Returns "BH" if DWC_IN_BH is true. */
155 : : static inline char *dwc_bh(void) {
156 : : return DWC_IN_BH() ? "BH" : "";
157 : : }
158 : :
159 : : /**
160 : : * A vprintf() clone. Just call vprintf if you've got it.
161 : : */
162 : : extern void DWC_VPRINTF(char *format, va_list args);
163 : : #define dwc_vprintf DWC_VPRINTF
164 : :
165 : : /**
166 : : * A vsnprintf() clone. Just call vprintf if you've got it.
167 : : */
168 : : extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args);
169 : : #define dwc_vsnprintf DWC_VSNPRINTF
170 : :
171 : : /**
172 : : * printf() clone. Just call printf if you've go it.
173 : : */
174 : : extern void DWC_PRINTF(char *format, ...)
175 : : /* This provides compiler level static checking of the parameters if you're
176 : : * using GCC. */
177 : : #ifdef __GNUC__
178 : : __attribute__ ((format(printf, 1, 2)));
179 : : #else
180 : : ;
181 : : #endif
182 : : #define dwc_printf DWC_PRINTF
183 : :
184 : : /**
185 : : * sprintf() clone. Just call sprintf if you've got it.
186 : : */
187 : : extern int DWC_SPRINTF(char *string, char *format, ...)
188 : : #ifdef __GNUC__
189 : : __attribute__ ((format(printf, 2, 3)));
190 : : #else
191 : : ;
192 : : #endif
193 : : #define dwc_sprintf DWC_SPRINTF
194 : :
195 : : /**
196 : : * snprintf() clone. Just call snprintf if you've got it.
197 : : */
198 : : extern int DWC_SNPRINTF(char *string, int size, char *format, ...)
199 : : #ifdef __GNUC__
200 : : __attribute__ ((format(printf, 3, 4)));
201 : : #else
202 : : ;
203 : : #endif
204 : : #define dwc_snprintf DWC_SNPRINTF
205 : :
206 : : /**
207 : : * Prints a WARNING message. On systems that don't differentiate between
208 : : * warnings and regular log messages, just print it. Indicates that something
209 : : * may be wrong with the driver. Works like printf().
210 : : *
211 : : * Use the DWC_WARN macro to call this function.
212 : : */
213 : : extern void __DWC_WARN(char *format, ...)
214 : : #ifdef __GNUC__
215 : : __attribute__ ((format(printf, 1, 2)));
216 : : #else
217 : : ;
218 : : #endif
219 : :
220 : : /**
221 : : * Prints an error message. On systems that don't differentiate between errors
222 : : * and regular log messages, just print it. Indicates that something went wrong
223 : : * with the driver. Works like printf().
224 : : *
225 : : * Use the DWC_ERROR macro to call this function.
226 : : */
227 : : extern void __DWC_ERROR(char *format, ...)
228 : : #ifdef __GNUC__
229 : : __attribute__ ((format(printf, 1, 2)));
230 : : #else
231 : : ;
232 : : #endif
233 : :
234 : : /**
235 : : * Prints an exception error message and takes some user-defined action such as
236 : : * print out a backtrace or trigger a breakpoint. Indicates that something went
237 : : * abnormally wrong with the driver such as programmer error, or other
238 : : * exceptional condition. It should not be ignored so even on systems without
239 : : * printing capability, some action should be taken to notify the developer of
240 : : * it. Works like printf().
241 : : */
242 : : extern void DWC_EXCEPTION(char *format, ...)
243 : : #ifdef __GNUC__
244 : : __attribute__ ((format(printf, 1, 2)));
245 : : #else
246 : : ;
247 : : #endif
248 : : #define dwc_exception DWC_EXCEPTION
249 : :
250 : : #ifndef DWC_OTG_DEBUG_LEV
251 : : #define DWC_OTG_DEBUG_LEV 0
252 : : #endif
253 : :
254 : : #ifdef DEBUG
255 : : /**
256 : : * Prints out a debug message. Used for logging/trace messages.
257 : : *
258 : : * Use the DWC_DEBUG macro to call this function
259 : : */
260 : : extern void __DWC_DEBUG(char *format, ...)
261 : : #ifdef __GNUC__
262 : : __attribute__ ((format(printf, 1, 2)));
263 : : #else
264 : : ;
265 : : #endif
266 : : #else
267 : : #define __DWC_DEBUG printk
268 : : #endif
269 : :
270 : : /**
271 : : * Prints out a Debug message.
272 : : */
273 : : #define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \
274 : : __func__, dwc_irq(), ## _args)
275 : : #define dwc_debug DWC_DEBUG
276 : : /**
277 : : * Prints out a Debug message if enabled at compile time.
278 : : */
279 : : #if DWC_OTG_DEBUG_LEV > 0
280 : : #define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args )
281 : : #else
282 : : #define DWC_DEBUGC(_format, _args...)
283 : : #endif
284 : : #define dwc_debugc DWC_DEBUGC
285 : : /**
286 : : * Prints out an informative message.
287 : : */
288 : : #define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \
289 : : dwc_irq(), ## _args)
290 : : #define dwc_info DWC_INFO
291 : : /**
292 : : * Prints out an informative message if enabled at compile time.
293 : : */
294 : : #if DWC_OTG_DEBUG_LEV > 1
295 : : #define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args )
296 : : #else
297 : : #define DWC_INFOC(_format, _args...)
298 : : #endif
299 : : #define dwc_infoc DWC_INFOC
300 : : /**
301 : : * Prints out a warning message.
302 : : */
303 : : #define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \
304 : : dwc_irq(), __func__, __LINE__, ## _args)
305 : : #define dwc_warn DWC_WARN
306 : : /**
307 : : * Prints out an error message.
308 : : */
309 : : #define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \
310 : : dwc_irq(), __func__, __LINE__, ## _args)
311 : : #define dwc_error DWC_ERROR
312 : :
313 : : #define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \
314 : : dwc_irq(), __func__, __LINE__, ## _args)
315 : : #define dwc_proto_error DWC_PROTO_ERROR
316 : :
317 : : #ifdef DEBUG
318 : : /** Prints out a exception error message if the _expr expression fails. Disabled
319 : : * if DEBUG is not enabled. */
320 : : #define DWC_ASSERT(_expr, _format, _args...) do { \
321 : : if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \
322 : : __FILE__, __LINE__, ## _args); } \
323 : : } while (0)
324 : : #else
325 : : #define DWC_ASSERT(_x...)
326 : : #endif
327 : : #define dwc_assert DWC_ASSERT
328 : :
329 : :
330 : : /** @name Byte Ordering
331 : : * The following functions are for conversions between processor's byte ordering
332 : : * and specific ordering you want.
333 : : */
334 : :
335 : : /** Converts 32 bit data in CPU byte ordering to little endian. */
336 : : extern uint32_t DWC_CPU_TO_LE32(uint32_t *p);
337 : : #define dwc_cpu_to_le32 DWC_CPU_TO_LE32
338 : :
339 : : /** Converts 32 bit data in CPU byte orderint to big endian. */
340 : : extern uint32_t DWC_CPU_TO_BE32(uint32_t *p);
341 : : #define dwc_cpu_to_be32 DWC_CPU_TO_BE32
342 : :
343 : : /** Converts 32 bit little endian data to CPU byte ordering. */
344 : : extern uint32_t DWC_LE32_TO_CPU(uint32_t *p);
345 : : #define dwc_le32_to_cpu DWC_LE32_TO_CPU
346 : :
347 : : /** Converts 32 bit big endian data to CPU byte ordering. */
348 : : extern uint32_t DWC_BE32_TO_CPU(uint32_t *p);
349 : : #define dwc_be32_to_cpu DWC_BE32_TO_CPU
350 : :
351 : : /** Converts 16 bit data in CPU byte ordering to little endian. */
352 : : extern uint16_t DWC_CPU_TO_LE16(uint16_t *p);
353 : : #define dwc_cpu_to_le16 DWC_CPU_TO_LE16
354 : :
355 : : /** Converts 16 bit data in CPU byte orderint to big endian. */
356 : : extern uint16_t DWC_CPU_TO_BE16(uint16_t *p);
357 : : #define dwc_cpu_to_be16 DWC_CPU_TO_BE16
358 : :
359 : : /** Converts 16 bit little endian data to CPU byte ordering. */
360 : : extern uint16_t DWC_LE16_TO_CPU(uint16_t *p);
361 : : #define dwc_le16_to_cpu DWC_LE16_TO_CPU
362 : :
363 : : /** Converts 16 bit bi endian data to CPU byte ordering. */
364 : : extern uint16_t DWC_BE16_TO_CPU(uint16_t *p);
365 : : #define dwc_be16_to_cpu DWC_BE16_TO_CPU
366 : :
367 : :
368 : : /** @name Register Read/Write
369 : : *
370 : : * The following six functions should be implemented to read/write registers of
371 : : * 32-bit and 64-bit sizes. All modules use this to read/write register values.
372 : : * The reg value is a pointer to the register calculated from the void *base
373 : : * variable passed into the driver when it is started. */
374 : :
375 : : #ifdef DWC_LINUX
376 : : /* Linux doesn't need any extra parameters for register read/write, so we
377 : : * just throw away the IO context parameter.
378 : : */
379 : : /** Reads the content of a 32-bit register. */
380 : : extern uint32_t DWC_READ_REG32(uint32_t volatile *reg);
381 : : #define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_)
382 : :
383 : : /** Reads the content of a 64-bit register. */
384 : : extern uint64_t DWC_READ_REG64(uint64_t volatile *reg);
385 : : #define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_)
386 : :
387 : : /** Writes to a 32-bit register. */
388 : : extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value);
389 : : #define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_)
390 : :
391 : : /** Writes to a 64-bit register. */
392 : : extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value);
393 : : #define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_)
394 : :
395 : : /**
396 : : * Modify bit values in a register. Using the
397 : : * algorithm: (reg_contents & ~clear_mask) | set_mask.
398 : : */
399 : : extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
400 : : #define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_)
401 : : extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
402 : : #define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_)
403 : :
404 : : #endif /* DWC_LINUX */
405 : :
406 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
407 : : typedef struct dwc_ioctx {
408 : : struct device *dev;
409 : : bus_space_tag_t iot;
410 : : bus_space_handle_t ioh;
411 : : } dwc_ioctx_t;
412 : :
413 : : /** BSD needs two extra parameters for register read/write, so we pass
414 : : * them in using the IO context parameter.
415 : : */
416 : : /** Reads the content of a 32-bit register. */
417 : : extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg);
418 : : #define dwc_read_reg32 DWC_READ_REG32
419 : :
420 : : /** Reads the content of a 64-bit register. */
421 : : extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg);
422 : : #define dwc_read_reg64 DWC_READ_REG64
423 : :
424 : : /** Writes to a 32-bit register. */
425 : : extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value);
426 : : #define dwc_write_reg32 DWC_WRITE_REG32
427 : :
428 : : /** Writes to a 64-bit register. */
429 : : extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value);
430 : : #define dwc_write_reg64 DWC_WRITE_REG64
431 : :
432 : : /**
433 : : * Modify bit values in a register. Using the
434 : : * algorithm: (reg_contents & ~clear_mask) | set_mask.
435 : : */
436 : : extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask);
437 : : #define dwc_modify_reg32 DWC_MODIFY_REG32
438 : : extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask);
439 : : #define dwc_modify_reg64 DWC_MODIFY_REG64
440 : :
441 : : #endif /* DWC_FREEBSD || DWC_NETBSD */
442 : :
443 : : /** @cond */
444 : :
445 : : /** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the
446 : : * register writes. */
447 : :
448 : : #ifdef DWC_LINUX
449 : :
450 : : # ifdef DWC_DEBUG_REGS
451 : :
452 : : #define dwc_define_read_write_reg_n(_reg,_container_type) \
453 : : static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
454 : : return DWC_READ_REG32(&container->regs->_reg[num]); \
455 : : } \
456 : : static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
457 : : DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
458 : : &(((uint32_t*)container->regs->_reg)[num]), data); \
459 : : DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
460 : : }
461 : :
462 : : #define dwc_define_read_write_reg(_reg,_container_type) \
463 : : static inline uint32_t dwc_read_##_reg(_container_type *container) { \
464 : : return DWC_READ_REG32(&container->regs->_reg); \
465 : : } \
466 : : static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
467 : : DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
468 : : DWC_WRITE_REG32(&container->regs->_reg, data); \
469 : : }
470 : :
471 : : # else /* DWC_DEBUG_REGS */
472 : :
473 : : #define dwc_define_read_write_reg_n(_reg,_container_type) \
474 : : static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \
475 : : return DWC_READ_REG32(&container->regs->_reg[num]); \
476 : : } \
477 : : static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \
478 : : DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \
479 : : }
480 : :
481 : : #define dwc_define_read_write_reg(_reg,_container_type) \
482 : : static inline uint32_t dwc_read_##_reg(_container_type *container) { \
483 : : return DWC_READ_REG32(&container->regs->_reg); \
484 : : } \
485 : : static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \
486 : : DWC_WRITE_REG32(&container->regs->_reg, data); \
487 : : }
488 : :
489 : : # endif /* DWC_DEBUG_REGS */
490 : :
491 : : #endif /* DWC_LINUX */
492 : :
493 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
494 : :
495 : : # ifdef DWC_DEBUG_REGS
496 : :
497 : : #define dwc_define_read_write_reg_n(_reg,_container_type) \
498 : : static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
499 : : return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
500 : : } \
501 : : static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
502 : : DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \
503 : : &(((uint32_t*)container->regs->_reg)[num]), data); \
504 : : DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
505 : : }
506 : :
507 : : #define dwc_define_read_write_reg(_reg,_container_type) \
508 : : static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
509 : : return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
510 : : } \
511 : : static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
512 : : DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \
513 : : DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
514 : : }
515 : :
516 : : # else /* DWC_DEBUG_REGS */
517 : :
518 : : #define dwc_define_read_write_reg_n(_reg,_container_type) \
519 : : static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \
520 : : return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \
521 : : } \
522 : : static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \
523 : : DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \
524 : : }
525 : :
526 : : #define dwc_define_read_write_reg(_reg,_container_type) \
527 : : static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \
528 : : return DWC_READ_REG32(io_ctx, &container->regs->_reg); \
529 : : } \
530 : : static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \
531 : : DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \
532 : : }
533 : :
534 : : # endif /* DWC_DEBUG_REGS */
535 : :
536 : : #endif /* DWC_FREEBSD || DWC_NETBSD */
537 : :
538 : : /** @endcond */
539 : :
540 : :
541 : : #ifdef DWC_CRYPTOLIB
542 : : /** @name Crypto Functions
543 : : *
544 : : * These are the low-level cryptographic functions used by the driver. */
545 : :
546 : : /** Perform AES CBC */
547 : : extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out);
548 : : #define dwc_aes_cbc DWC_AES_CBC
549 : :
550 : : /** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */
551 : : extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length);
552 : : #define dwc_random_bytes DWC_RANDOM_BYTES
553 : :
554 : : /** Perform the SHA-256 hash function */
555 : : extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out);
556 : : #define dwc_sha256 DWC_SHA256
557 : :
558 : : /** Calculated the HMAC-SHA256 */
559 : : extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out);
560 : : #define dwc_hmac_sha256 DWC_HMAC_SHA256
561 : :
562 : : #endif /* DWC_CRYPTOLIB */
563 : :
564 : :
565 : : /** @name Memory Allocation
566 : : *
567 : : * These function provide access to memory allocation. There are only 2 DMA
568 : : * functions and 3 Regular memory functions that need to be implemented. None
569 : : * of the memory debugging routines need to be implemented. The allocation
570 : : * routines all ZERO the contents of the memory.
571 : : *
572 : : * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering.
573 : : * This checks for memory leaks, keeping track of alloc/free pairs. It also
574 : : * keeps track of how much memory the driver is using at any given time. */
575 : :
576 : : #define DWC_PAGE_SIZE 4096
577 : : #define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff)
578 : : #define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0)
579 : :
580 : : #define DWC_INVALID_DMA_ADDR 0x0
581 : :
582 : : #ifdef DWC_LINUX
583 : : /** Type for a DMA address */
584 : : typedef dma_addr_t dwc_dma_t;
585 : : #endif
586 : :
587 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
588 : : typedef bus_addr_t dwc_dma_t;
589 : : #endif
590 : :
591 : : #ifdef DWC_FREEBSD
592 : : typedef struct dwc_dmactx {
593 : : struct device *dev;
594 : : bus_dma_tag_t dma_tag;
595 : : bus_dmamap_t dma_map;
596 : : bus_addr_t dma_paddr;
597 : : void *dma_vaddr;
598 : : } dwc_dmactx_t;
599 : : #endif
600 : :
601 : : #ifdef DWC_NETBSD
602 : : typedef struct dwc_dmactx {
603 : : struct device *dev;
604 : : bus_dma_tag_t dma_tag;
605 : : bus_dmamap_t dma_map;
606 : : bus_dma_segment_t segs[1];
607 : : int nsegs;
608 : : bus_addr_t dma_paddr;
609 : : void *dma_vaddr;
610 : : } dwc_dmactx_t;
611 : : #endif
612 : :
613 : : /* @todo these functions will be added in the future */
614 : : #if 0
615 : : /**
616 : : * Creates a DMA pool from which you can allocate DMA buffers. Buffers
617 : : * allocated from this pool will be guaranteed to meet the size, alignment, and
618 : : * boundary requirements specified.
619 : : *
620 : : * @param[in] size Specifies the size of the buffers that will be allocated from
621 : : * this pool.
622 : : * @param[in] align Specifies the byte alignment requirements of the buffers
623 : : * allocated from this pool. Must be a power of 2.
624 : : * @param[in] boundary Specifies the N-byte boundary that buffers allocated from
625 : : * this pool must not cross.
626 : : *
627 : : * @returns A pointer to an internal opaque structure which is not to be
628 : : * accessed outside of these library functions. Use this handle to specify
629 : : * which pools to allocate/free DMA buffers from and also to destroy the pool,
630 : : * when you are done with it.
631 : : */
632 : : extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary);
633 : :
634 : : /**
635 : : * Destroy a DMA pool. All buffers allocated from that pool must be freed first.
636 : : */
637 : : extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool);
638 : :
639 : : /**
640 : : * Allocate a buffer from the specified DMA pool and zeros its contents.
641 : : */
642 : : extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr);
643 : :
644 : : /**
645 : : * Free a previously allocated buffer from the DMA pool.
646 : : */
647 : : extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr);
648 : : #endif
649 : :
650 : : /** Allocates a DMA capable buffer and zeroes its contents. */
651 : : extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
652 : :
653 : : /** Allocates a DMA capable buffer and zeroes its contents in atomic contest */
654 : : extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr);
655 : :
656 : : /** Frees a previously allocated buffer. */
657 : : extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr);
658 : :
659 : : /** Allocates a block of memory and zeroes its contents. */
660 : : extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size);
661 : :
662 : : /** Allocates a block of memory and zeroes its contents, in an atomic manner
663 : : * which can be used inside interrupt context. The size should be sufficiently
664 : : * small, a few KB at most, such that failures are not likely to occur. Can just call
665 : : * __DWC_ALLOC if it is atomic. */
666 : : extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size);
667 : :
668 : : /** Frees a previously allocated buffer. */
669 : : extern void __DWC_FREE(void *mem_ctx, void *addr);
670 : :
671 : : #ifndef DWC_DEBUG_MEMORY
672 : :
673 : : #define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_)
674 : : #define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_)
675 : : #define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_)
676 : :
677 : : # ifdef DWC_LINUX
678 : : #define DWC_DMA_ALLOC(_dev, _size_, _dma_) __DWC_DMA_ALLOC(_dev, _size_, _dma_)
679 : : #define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) __DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_)
680 : : #define DWC_DMA_FREE(_dev, _size_,_virt_, _dma_) __DWC_DMA_FREE(_dev, _size_, _virt_, _dma_)
681 : : # endif
682 : :
683 : : # if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
684 : : #define DWC_DMA_ALLOC __DWC_DMA_ALLOC
685 : : #define DWC_DMA_FREE __DWC_DMA_FREE
686 : : # endif
687 : : extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line);
688 : :
689 : : #else /* DWC_DEBUG_MEMORY */
690 : :
691 : : extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line);
692 : : extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line);
693 : : extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line);
694 : : extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
695 : : char const *func, int line);
696 : : extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
697 : : char const *func, int line);
698 : : extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
699 : : dwc_dma_t dma_addr, char const *func, int line);
700 : :
701 : : extern int dwc_memory_debug_start(void *mem_ctx);
702 : : extern void dwc_memory_debug_stop(void);
703 : : extern void dwc_memory_debug_report(void);
704 : :
705 : : #define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__)
706 : : #define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \
707 : : __func__, __LINE__)
708 : : #define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__)
709 : :
710 : : # ifdef DWC_LINUX
711 : : #define DWC_DMA_ALLOC(_dev, _size_, _dma_) \
712 : : dwc_dma_alloc_debug(_dev, _size_, _dma_, __func__, __LINE__)
713 : : #define DWC_DMA_ALLOC_ATOMIC(_dev, _size_, _dma_) \
714 : : dwc_dma_alloc_atomic_debug(_dev, _size_, _dma_, __func__, __LINE__)
715 : : #define DWC_DMA_FREE(_dev, _size_, _virt_, _dma_) \
716 : : dwc_dma_free_debug(_dev, _size_, _virt_, _dma_, __func__, __LINE__)
717 : : # endif
718 : :
719 : : # if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
720 : : #define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \
721 : : _dma_, __func__, __LINE__)
722 : : #define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \
723 : : _virt_, _dma_, __func__, __LINE__)
724 : : # endif
725 : :
726 : : #endif /* DWC_DEBUG_MEMORY */
727 : :
728 : : #define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_)
729 : : #define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_)
730 : : #define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_)
731 : :
732 : : #ifdef DWC_LINUX
733 : : /* Linux doesn't need any extra parameters for DMA buffer allocation, so we
734 : : * just throw away the DMA context parameter.
735 : : */
736 : : #define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_)
737 : : #define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_)
738 : : #define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_)
739 : : #endif
740 : :
741 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
742 : : /** BSD needs several extra parameters for DMA buffer allocation, so we pass
743 : : * them in using the DMA context parameter.
744 : : */
745 : : #define dwc_dma_alloc DWC_DMA_ALLOC
746 : : #define dwc_dma_free DWC_DMA_FREE
747 : : #endif
748 : :
749 : :
750 : : /** @name Memory and String Processing */
751 : :
752 : : /** memset() clone */
753 : : extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size);
754 : : #define dwc_memset DWC_MEMSET
755 : :
756 : : /** memcpy() clone */
757 : : extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size);
758 : : #define dwc_memcpy DWC_MEMCPY
759 : :
760 : : /** memmove() clone */
761 : : extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size);
762 : : #define dwc_memmove DWC_MEMMOVE
763 : :
764 : : /** memcmp() clone */
765 : : extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size);
766 : : #define dwc_memcmp DWC_MEMCMP
767 : :
768 : : /** strcmp() clone */
769 : : extern int DWC_STRCMP(void *s1, void *s2);
770 : : #define dwc_strcmp DWC_STRCMP
771 : :
772 : : /** strncmp() clone */
773 : : extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size);
774 : : #define dwc_strncmp DWC_STRNCMP
775 : :
776 : : /** strlen() clone, for NULL terminated ASCII strings */
777 : : extern int DWC_STRLEN(char const *str);
778 : : #define dwc_strlen DWC_STRLEN
779 : :
780 : : /** strcpy() clone, for NULL terminated ASCII strings */
781 : : extern char *DWC_STRCPY(char *to, const char *from);
782 : : #define dwc_strcpy DWC_STRCPY
783 : :
784 : : /** strdup() clone. If you wish to use memory allocation debugging, this
785 : : * implementation of strdup should use the DWC_* memory routines instead of
786 : : * calling a predefined strdup. Otherwise the memory allocated by this routine
787 : : * will not be seen by the debugging routines. */
788 : : extern char *DWC_STRDUP(char const *str);
789 : : #define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_)
790 : :
791 : : /** NOT an atoi() clone. Read the description carefully. Returns an integer
792 : : * converted from the string str in base 10 unless the string begins with a "0x"
793 : : * in which case it is base 16. String must be a NULL terminated sequence of
794 : : * ASCII characters and may optionally begin with whitespace, a + or -, and a
795 : : * "0x" prefix if base 16. The remaining characters must be valid digits for
796 : : * the number and end with a NULL character. If any invalid characters are
797 : : * encountered or it returns with a negative error code and the results of the
798 : : * conversion are undefined. On sucess it returns 0. Overflow conditions are
799 : : * undefined. An example implementation using atoi() can be referenced from the
800 : : * Linux implementation. */
801 : : extern int DWC_ATOI(const char *str, int32_t *value);
802 : : #define dwc_atoi DWC_ATOI
803 : :
804 : : /** Same as above but for unsigned. */
805 : : extern int DWC_ATOUI(const char *str, uint32_t *value);
806 : : #define dwc_atoui DWC_ATOUI
807 : :
808 : : #ifdef DWC_UTFLIB
809 : : /** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */
810 : : extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len);
811 : : #define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE
812 : : #endif
813 : :
814 : :
815 : : /** @name Wait queues
816 : : *
817 : : * Wait queues provide a means of synchronizing between threads or processes. A
818 : : * process can block on a waitq if some condition is not true, waiting for it to
819 : : * become true. When the waitq is triggered all waiting process will get
820 : : * unblocked and the condition will be check again. Waitqs should be triggered
821 : : * every time a condition can potentially change.*/
822 : : struct dwc_waitq;
823 : :
824 : : /** Type for a waitq */
825 : : typedef struct dwc_waitq dwc_waitq_t;
826 : :
827 : : /** The type of waitq condition callback function. This is called every time
828 : : * condition is evaluated. */
829 : : typedef int (*dwc_waitq_condition_t)(void *data);
830 : :
831 : : /** Allocate a waitq */
832 : : extern dwc_waitq_t *DWC_WAITQ_ALLOC(void);
833 : : #define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC()
834 : :
835 : : /** Free a waitq */
836 : : extern void DWC_WAITQ_FREE(dwc_waitq_t *wq);
837 : : #define dwc_waitq_free DWC_WAITQ_FREE
838 : :
839 : : /** Check the condition and if it is false, block on the waitq. When unblocked, check the
840 : : * condition again. The function returns when the condition becomes true. The return value
841 : : * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */
842 : : extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data);
843 : : #define dwc_waitq_wait DWC_WAITQ_WAIT
844 : :
845 : : /** Check the condition and if it is false, block on the waitq. When unblocked,
846 : : * check the condition again. The function returns when the condition become
847 : : * true or the timeout has passed. The return value is 0 on condition true or
848 : : * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on
849 : : * error. */
850 : : extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond,
851 : : void *data, int32_t msecs);
852 : : #define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT
853 : :
854 : : /** Trigger a waitq, unblocking all processes. This should be called whenever a condition
855 : : * has potentially changed. */
856 : : extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq);
857 : : #define dwc_waitq_trigger DWC_WAITQ_TRIGGER
858 : :
859 : : /** Unblock all processes waiting on the waitq with an ABORTED result. */
860 : : extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq);
861 : : #define dwc_waitq_abort DWC_WAITQ_ABORT
862 : :
863 : :
864 : : /** @name Threads
865 : : *
866 : : * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP
867 : : * whenever it is woken up, and then return. The DWC_THREAD_STOP function
868 : : * returns the value from the thread.
869 : : */
870 : :
871 : : struct dwc_thread;
872 : :
873 : : /** Type for a thread */
874 : : typedef struct dwc_thread dwc_thread_t;
875 : :
876 : : /** The thread function */
877 : : typedef int (*dwc_thread_function_t)(void *data);
878 : :
879 : : /** Create a thread and start it running the thread_function. Returns a handle
880 : : * to the thread */
881 : : extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data);
882 : : #define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_)
883 : :
884 : : /** Stops a thread. Return the value returned by the thread. Or will return
885 : : * DWC_ABORT if the thread never started. */
886 : : extern int DWC_THREAD_STOP(dwc_thread_t *thread);
887 : : #define dwc_thread_stop DWC_THREAD_STOP
888 : :
889 : : /** Signifies to the thread that it must stop. */
890 : : #ifdef DWC_LINUX
891 : : /* Linux doesn't need any parameters for kthread_should_stop() */
892 : : extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void);
893 : : #define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP()
894 : :
895 : : /* No thread_exit function in Linux */
896 : : #define dwc_thread_exit(_thrd_)
897 : : #endif
898 : :
899 : : #if defined(DWC_FREEBSD) || defined(DWC_NETBSD)
900 : : /** BSD needs the thread pointer for kthread_suspend_check() */
901 : : extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread);
902 : : #define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP
903 : :
904 : : /** The thread must call this to exit. */
905 : : extern void DWC_THREAD_EXIT(dwc_thread_t *thread);
906 : : #define dwc_thread_exit DWC_THREAD_EXIT
907 : : #endif
908 : :
909 : :
910 : : /** @name Work queues
911 : : *
912 : : * Workqs are used to queue a callback function to be called at some later time,
913 : : * in another thread. */
914 : : struct dwc_workq;
915 : :
916 : : /** Type for a workq */
917 : : typedef struct dwc_workq dwc_workq_t;
918 : :
919 : : /** The type of the callback function to be called. */
920 : : typedef void (*dwc_work_callback_t)(void *data);
921 : :
922 : : /** Allocate a workq */
923 : : extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name);
924 : : #define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_)
925 : :
926 : : /** Free a workq. All work must be completed before being freed. */
927 : : extern void DWC_WORKQ_FREE(dwc_workq_t *workq);
928 : : #define dwc_workq_free DWC_WORKQ_FREE
929 : :
930 : : /** Schedule a callback on the workq, passing in data. The function will be
931 : : * scheduled at some later time. */
932 : : extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb,
933 : : void *data, char *format, ...)
934 : : #ifdef __GNUC__
935 : : __attribute__ ((format(printf, 4, 5)));
936 : : #else
937 : : ;
938 : : #endif
939 : : #define dwc_workq_schedule DWC_WORKQ_SCHEDULE
940 : :
941 : : /** Schedule a callback on the workq, that will be called until at least
942 : : * given number miliseconds have passed. */
943 : : extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb,
944 : : void *data, uint32_t time, char *format, ...)
945 : : #ifdef __GNUC__
946 : : __attribute__ ((format(printf, 5, 6)));
947 : : #else
948 : : ;
949 : : #endif
950 : : #define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED
951 : :
952 : : /** The number of processes in the workq */
953 : : extern int DWC_WORKQ_PENDING(dwc_workq_t *workq);
954 : : #define dwc_workq_pending DWC_WORKQ_PENDING
955 : :
956 : : /** Blocks until all the work in the workq is complete or timed out. Returns <
957 : : * 0 on timeout. */
958 : : extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout);
959 : : #define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE
960 : :
961 : :
962 : : /** @name Tasklets
963 : : *
964 : : */
965 : : struct dwc_tasklet;
966 : :
967 : : /** Type for a tasklet */
968 : : typedef struct dwc_tasklet dwc_tasklet_t;
969 : :
970 : : /** The type of the callback function to be called */
971 : : typedef void (*dwc_tasklet_callback_t)(void *data);
972 : :
973 : : /** Allocates a tasklet */
974 : : extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data);
975 : : #define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_)
976 : :
977 : : /** Frees a tasklet */
978 : : extern void DWC_TASK_FREE(dwc_tasklet_t *task);
979 : : #define dwc_task_free DWC_TASK_FREE
980 : :
981 : : /** Schedules a tasklet to run */
982 : : extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
983 : : #define dwc_task_schedule DWC_TASK_SCHEDULE
984 : :
985 : : extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
986 : : #define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
987 : :
988 : : /** @name Timer
989 : : *
990 : : * Callbacks must be small and atomic.
991 : : */
992 : : struct dwc_timer;
993 : :
994 : : /** Type for a timer */
995 : : typedef struct dwc_timer dwc_timer_t;
996 : :
997 : : /** The type of the callback function to be called */
998 : : typedef void (*dwc_timer_callback_t)(void *data);
999 : :
1000 : : /** Allocates a timer */
1001 : : extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data);
1002 : : #define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_)
1003 : :
1004 : : /** Frees a timer */
1005 : : extern void DWC_TIMER_FREE(dwc_timer_t *timer);
1006 : : #define dwc_timer_free DWC_TIMER_FREE
1007 : :
1008 : : /** Schedules the timer to run at time ms from now. And will repeat at every
1009 : : * repeat_interval msec therafter
1010 : : *
1011 : : * Modifies a timer that is still awaiting execution to a new expiration time.
1012 : : * The mod_time is added to the old time. */
1013 : : extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time);
1014 : : #define dwc_timer_schedule DWC_TIMER_SCHEDULE
1015 : :
1016 : : /** Disables the timer from execution. */
1017 : : extern void DWC_TIMER_CANCEL(dwc_timer_t *timer);
1018 : : #define dwc_timer_cancel DWC_TIMER_CANCEL
1019 : :
1020 : :
1021 : : /** @name Spinlocks
1022 : : *
1023 : : * These locks are used when the work between the lock/unlock is atomic and
1024 : : * short. Interrupts are also disabled during the lock/unlock and thus they are
1025 : : * suitable to lock between interrupt/non-interrupt context. They also lock
1026 : : * between processes if you have multiple CPUs or Preemption. If you don't have
1027 : : * multiple CPUS or Preemption, then the you can simply implement the
1028 : : * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because
1029 : : * the work between the lock/unlock is atomic, the process context will never
1030 : : * change, and so you never have to lock between processes. */
1031 : :
1032 : : struct dwc_spinlock;
1033 : :
1034 : : /** Type for a spinlock */
1035 : : typedef struct dwc_spinlock dwc_spinlock_t;
1036 : :
1037 : : /** Type for the 'flags' argument to spinlock funtions */
1038 : : typedef unsigned long dwc_irqflags_t;
1039 : :
1040 : : /** Returns an initialized lock variable. This function should allocate and
1041 : : * initialize the OS-specific data structure used for locking. This data
1042 : : * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should
1043 : : * be freed by the DWC_FREE_LOCK when it is no longer used.
1044 : : *
1045 : : * For Linux Spinlock Debugging make it macro because the debugging routines use
1046 : : * the symbol name to determine recursive locking. Using a wrapper function
1047 : : * makes it falsely think recursive locking occurs. */
1048 : : #if defined(DWC_LINUX) && defined(CONFIG_DEBUG_SPINLOCK)
1049 : : #define DWC_SPINLOCK_ALLOC_LINUX_DEBUG(lock) ({ \
1050 : : lock = DWC_ALLOC(sizeof(spinlock_t)); \
1051 : : if (lock) { \
1052 : : spin_lock_init((spinlock_t *)lock); \
1053 : : } \
1054 : : })
1055 : : #else
1056 : : extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void);
1057 : : #define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC()
1058 : : #endif
1059 : :
1060 : : /** Frees an initialized lock variable. */
1061 : : extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock);
1062 : : #define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_)
1063 : :
1064 : : /** Disables interrupts and blocks until it acquires the lock.
1065 : : *
1066 : : * @param lock Pointer to the spinlock.
1067 : : * @param flags Unsigned long for irq flags storage.
1068 : : */
1069 : : extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags);
1070 : : #define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE
1071 : :
1072 : : /** Re-enables the interrupt and releases the lock.
1073 : : *
1074 : : * @param lock Pointer to the spinlock.
1075 : : * @param flags Unsigned long for irq flags storage. Must be the same as was
1076 : : * passed into DWC_LOCK.
1077 : : */
1078 : : extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags);
1079 : : #define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE
1080 : :
1081 : : /** Blocks until it acquires the lock.
1082 : : *
1083 : : * @param lock Pointer to the spinlock.
1084 : : */
1085 : : extern void DWC_SPINLOCK(dwc_spinlock_t *lock);
1086 : : #define dwc_spinlock DWC_SPINLOCK
1087 : :
1088 : : /** Releases the lock.
1089 : : *
1090 : : * @param lock Pointer to the spinlock.
1091 : : */
1092 : : extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock);
1093 : : #define dwc_spinunlock DWC_SPINUNLOCK
1094 : :
1095 : :
1096 : : /** @name Mutexes
1097 : : *
1098 : : * Unlike spinlocks Mutexes lock only between processes and the work between the
1099 : : * lock/unlock CAN block, therefore it CANNOT be called from interrupt context.
1100 : : */
1101 : :
1102 : : struct dwc_mutex;
1103 : :
1104 : : /** Type for a mutex */
1105 : : typedef struct dwc_mutex dwc_mutex_t;
1106 : :
1107 : : /* For Linux Mutex Debugging make it inline because the debugging routines use
1108 : : * the symbol to determine recursive locking. This makes it falsely think
1109 : : * recursive locking occurs. */
1110 : : #if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
1111 : : #define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \
1112 : : __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \
1113 : : mutex_init((struct mutex *)__mutexp); \
1114 : : })
1115 : : #endif
1116 : :
1117 : : /** Allocate a mutex */
1118 : : extern dwc_mutex_t *DWC_MUTEX_ALLOC(void);
1119 : : #define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC()
1120 : :
1121 : : /* For memory leak debugging when using Linux Mutex Debugging */
1122 : : #if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)
1123 : : #define DWC_MUTEX_FREE(__mutexp) do { \
1124 : : mutex_destroy((struct mutex *)__mutexp); \
1125 : : DWC_FREE(__mutexp); \
1126 : : } while(0)
1127 : : #else
1128 : : /** Free a mutex */
1129 : : extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex);
1130 : : #define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_)
1131 : : #endif
1132 : :
1133 : : /** Lock a mutex */
1134 : : extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex);
1135 : : #define dwc_mutex_lock DWC_MUTEX_LOCK
1136 : :
1137 : : /** Non-blocking lock returns 1 on successful lock. */
1138 : : extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex);
1139 : : #define dwc_mutex_trylock DWC_MUTEX_TRYLOCK
1140 : :
1141 : : /** Unlock a mutex */
1142 : : extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex);
1143 : : #define dwc_mutex_unlock DWC_MUTEX_UNLOCK
1144 : :
1145 : :
1146 : : /** @name Time */
1147 : :
1148 : : /** Microsecond delay.
1149 : : *
1150 : : * @param usecs Microseconds to delay.
1151 : : */
1152 : : extern void DWC_UDELAY(uint32_t usecs);
1153 : : #define dwc_udelay DWC_UDELAY
1154 : :
1155 : : /** Millisecond delay.
1156 : : *
1157 : : * @param msecs Milliseconds to delay.
1158 : : */
1159 : : extern void DWC_MDELAY(uint32_t msecs);
1160 : : #define dwc_mdelay DWC_MDELAY
1161 : :
1162 : : /** Non-busy waiting.
1163 : : * Sleeps for specified number of milliseconds.
1164 : : *
1165 : : * @param msecs Milliseconds to sleep.
1166 : : */
1167 : : extern void DWC_MSLEEP(uint32_t msecs);
1168 : : #define dwc_msleep DWC_MSLEEP
1169 : :
1170 : : /**
1171 : : * Returns number of milliseconds since boot.
1172 : : */
1173 : : extern uint32_t DWC_TIME(void);
1174 : : #define dwc_time DWC_TIME
1175 : :
1176 : :
1177 : :
1178 : :
1179 : : /* @mainpage DWC Portability and Common Library
1180 : : *
1181 : : * This is the documentation for the DWC Portability and Common Library.
1182 : : *
1183 : : * @section intro Introduction
1184 : : *
1185 : : * The DWC Portability library consists of wrapper calls and data structures to
1186 : : * all low-level functions which are typically provided by the OS. The WUDEV
1187 : : * driver uses only these functions. In order to port the WUDEV driver, only
1188 : : * the functions in this library need to be re-implemented, with the same
1189 : : * behavior as documented here.
1190 : : *
1191 : : * The Common library consists of higher level functions, which rely only on
1192 : : * calling the functions from the DWC Portability library. These common
1193 : : * routines are shared across modules. Some of the common libraries need to be
1194 : : * used directly by the driver programmer when porting WUDEV. Such as the
1195 : : * parameter and notification libraries.
1196 : : *
1197 : : * @section low Portability Library OS Wrapper Functions
1198 : : *
1199 : : * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that
1200 : : * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of
1201 : : * these functions are included in the dwc_os.h file.
1202 : : *
1203 : : * There are many functions here covering a wide array of OS services. Please
1204 : : * see dwc_os.h for details, and implementation notes for each function.
1205 : : *
1206 : : * @section common Common Library Functions
1207 : : *
1208 : : * Any function starting with dwc and in all lowercase is a common library
1209 : : * routine. These functions have a portable implementation and do not need to
1210 : : * be reimplemented when porting. The common routines can be used by any
1211 : : * driver, and some must be used by the end user to control the drivers. For
1212 : : * example, you must use the Parameter common library in order to set the
1213 : : * parameters in the WUDEV module.
1214 : : *
1215 : : * The common libraries consist of the following:
1216 : : *
1217 : : * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h
1218 : : * - Parameters - Used internally and can be used by end-user. See dwc_params.h
1219 : : * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h
1220 : : * - Lists - Used internally and can be used by end-user. See dwc_list.h
1221 : : * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h
1222 : : * - Modpow - Used internally only. See dwc_modpow.h
1223 : : * - DH - Used internally only. See dwc_dh.h
1224 : : * - Crypto - Used internally only. See dwc_crypto.h
1225 : : *
1226 : : *
1227 : : * @section prereq Prerequistes For dwc_os.h
1228 : : * @subsection types Data Types
1229 : : *
1230 : : * The dwc_os.h file assumes that several low-level data types are pre defined for the
1231 : : * compilation environment. These data types are:
1232 : : *
1233 : : * - uint8_t - unsigned 8-bit data type
1234 : : * - int8_t - signed 8-bit data type
1235 : : * - uint16_t - unsigned 16-bit data type
1236 : : * - int16_t - signed 16-bit data type
1237 : : * - uint32_t - unsigned 32-bit data type
1238 : : * - int32_t - signed 32-bit data type
1239 : : * - uint64_t - unsigned 64-bit data type
1240 : : * - int64_t - signed 64-bit data type
1241 : : *
1242 : : * Ensure that these are defined before using dwc_os.h. The easiest way to do
1243 : : * that is to modify the top of the file to include the appropriate header.
1244 : : * This is already done for the Linux environment. If the DWC_LINUX macro is
1245 : : * defined, the correct header will be added. A standard header <stdint.h> is
1246 : : * also used for environments where standard C headers are available.
1247 : : *
1248 : : * @subsection stdarg Variable Arguments
1249 : : *
1250 : : * Variable arguments are provided by a standard C header <stdarg.h>. it is
1251 : : * available in Both the Linux and ANSI C enviornment. An equivalent must be
1252 : : * provided in your enviornment in order to use dwc_os.h with the debug and
1253 : : * tracing message functionality.
1254 : : *
1255 : : * @subsection thread Threading
1256 : : *
1257 : : * WUDEV Core must be run on an operating system that provides for multiple
1258 : : * threads/processes. Threading can be implemented in many ways, even in
1259 : : * embedded systems without an operating system. At the bare minimum, the
1260 : : * system should be able to start any number of processes at any time to handle
1261 : : * special work. It need not be a pre-emptive system. Process context can
1262 : : * change upon a call to a blocking function. The hardware interrupt context
1263 : : * that calls the module's ISR() function must be differentiable from process
1264 : : * context, even if your processes are impemented via a hardware interrupt.
1265 : : * Further locking mechanism between process must exist (or be implemented), and
1266 : : * process context must have a way to disable interrupts for a period of time to
1267 : : * lock them out. If all of this exists, the functions in dwc_os.h related to
1268 : : * threading should be able to be implemented with the defined behavior.
1269 : : *
1270 : : */
1271 : :
1272 : : #ifdef __cplusplus
1273 : : }
1274 : : #endif
1275 : :
1276 : : #endif /* _DWC_OS_H_ */
|