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