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 /*************************************************************************** 43ef270ab1SKenneth D. Merry * OS specific includes 44ef270ab1SKenneth D. Merry */ 455eaf9435SRam Kishore Vegesna #include "opt_stack.h" 465eaf9435SRam Kishore Vegesna 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 815eaf9435SRam Kishore Vegesna #include <sys/linker.h> /* for debug of memory allocations */ 825eaf9435SRam Kishore Vegesna 83ef270ab1SKenneth D. Merry /* OCS_OS_MAX_ISR_TIME_MSEC - maximum time driver code should spend in an interrupt 84ef270ab1SKenneth D. Merry * or kernel thread context without yielding 85ef270ab1SKenneth D. Merry */ 86ef270ab1SKenneth D. Merry #define OCS_OS_MAX_ISR_TIME_MSEC 1000 87ef270ab1SKenneth D. Merry 88ef270ab1SKenneth D. Merry /* BSD driver specific definitions */ 89ef270ab1SKenneth D. Merry 90ef270ab1SKenneth D. Merry #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 91ef270ab1SKenneth D. Merry 92ef270ab1SKenneth D. Merry #define OCS_MAX_LUN 512 93ef270ab1SKenneth D. Merry #define OCS_NUM_UNSOLICITED_FRAMES 1024 94ef270ab1SKenneth D. Merry 95ef270ab1SKenneth D. Merry #define OCS_MAX_DOMAINS 1 96ef270ab1SKenneth D. Merry #define OCS_MAX_REMOTE_NODES 2048 97ef270ab1SKenneth D. Merry #define OCS_MAX_TARGETS 1024 98ef270ab1SKenneth D. Merry #define OCS_MAX_INITIATORS 1024 99ef270ab1SKenneth D. Merry /** Reserve this number of IO for each intiator to return FULL/BUSY status */ 100ef270ab1SKenneth D. Merry #define OCS_RSVD_INI_IO 8 101ef270ab1SKenneth D. Merry 102ef270ab1SKenneth D. Merry #define OCS_MIN_DMA_ALIGNMENT 16 1037b56cb04SGordon Bergling #define OCS_MAX_DMA_ALLOC (64*1024) /* maximum DMA allocation that is expected to reliably succeed */ 104ef270ab1SKenneth D. Merry 105ef270ab1SKenneth D. Merry /* 106ef270ab1SKenneth D. Merry * Macros used to size the CQ hash table. We want to round up to the next 107ef270ab1SKenneth D. Merry * power of 2 for the hash. 108ef270ab1SKenneth D. Merry */ 109ef270ab1SKenneth D. Merry #define B2(x) ( (x) | ( (x) >> 1) ) 110ef270ab1SKenneth D. Merry #define B4(x) ( B2(x) | ( B2(x) >> 2) ) 111ef270ab1SKenneth D. Merry #define B8(x) ( B4(x) | ( B4(x) >> 4) ) 112ef270ab1SKenneth D. Merry #define B16(x) ( B8(x) | ( B8(x) >> 8) ) 113ef270ab1SKenneth D. Merry #define B32(x) (B16(x) | (B16(x) >>16) ) 114ef270ab1SKenneth D. Merry #define B32_NEXT_POWER_OF_2(x) (B32((x)-1) + 1) 115ef270ab1SKenneth D. Merry 116ef270ab1SKenneth D. Merry /* 117ef270ab1SKenneth D. Merry * likely/unlikely - branch prediction hint 118ef270ab1SKenneth D. Merry */ 119ef270ab1SKenneth D. Merry #define likely(x) __builtin_expect(!!(x), 1) 120ef270ab1SKenneth D. Merry #define unlikely(x) __builtin_expect(!!(x), 0) 121ef270ab1SKenneth D. Merry 122ef270ab1SKenneth D. Merry /*************************************************************************** 123ef270ab1SKenneth D. Merry * OS abstraction 124ef270ab1SKenneth D. Merry */ 125ef270ab1SKenneth D. Merry 126ef270ab1SKenneth D. Merry /** 127ef270ab1SKenneth D. Merry * @brief Min/Max macros 128ef270ab1SKenneth D. Merry * 129ef270ab1SKenneth D. Merry */ 130ef270ab1SKenneth D. Merry #define OCS_MAX(x, y) ((x) > (y) ? (x) : (y)) 131ef270ab1SKenneth D. Merry #define OCS_MIN(x, y) ((x) < (y) ? (x) : (y)) 132ef270ab1SKenneth D. Merry 133ef270ab1SKenneth D. Merry #define PRIX64 "lX" 134ef270ab1SKenneth D. Merry #define PRIx64 "lx" 135ef270ab1SKenneth D. Merry #define PRId64 "ld" 136ef270ab1SKenneth D. Merry #define PRIu64 "lu" 137ef270ab1SKenneth D. Merry 138ef270ab1SKenneth D. Merry /** 139ef270ab1SKenneth D. Merry * Enable optional features 140ef270ab1SKenneth D. Merry * - OCS_INCLUDE_DEBUG include low-level SLI debug support 141ef270ab1SKenneth D. Merry */ 142ef270ab1SKenneth D. Merry #define OCS_INCLUDE_DEBUG 143ef270ab1SKenneth D. Merry 144ef270ab1SKenneth D. Merry /** 145ef270ab1SKenneth D. Merry * @brief Set the Nth bit 146ef270ab1SKenneth D. Merry * 147ef270ab1SKenneth D. Merry * @todo move to a private file used internally? 148ef270ab1SKenneth D. Merry */ 149ef270ab1SKenneth D. Merry #ifndef BIT 150ef270ab1SKenneth D. Merry #define BIT(n) (1U << (n)) 151ef270ab1SKenneth D. Merry #endif 152ef270ab1SKenneth D. Merry 153ef270ab1SKenneth D. Merry /*************************************************************************** 154ef270ab1SKenneth D. Merry * Platform specific operations 155ef270ab1SKenneth D. Merry */ 156ef270ab1SKenneth D. Merry 1575eaf9435SRam Kishore Vegesna typedef struct ocs_softc ocs_t; 1585eaf9435SRam Kishore Vegesna 159ef270ab1SKenneth D. Merry /** 160ef270ab1SKenneth D. Merry * @ingroup os 161ef270ab1SKenneth D. Merry * @typedef ocs_os_handle_t 162ef270ab1SKenneth D. Merry * @brief OS specific handle or driver context 163ef270ab1SKenneth D. Merry * 164ef270ab1SKenneth D. Merry * This can be anything from a void * to some other OS specific type. The lower 165ef270ab1SKenneth D. Merry * layers make no assumption about its value and pass it back as the first 166ef270ab1SKenneth D. Merry * parameter to most OS functions. 167ef270ab1SKenneth D. Merry */ 168ef270ab1SKenneth D. Merry typedef ocs_t * ocs_os_handle_t; 169ef270ab1SKenneth D. Merry 170ef270ab1SKenneth D. Merry /** 171ef270ab1SKenneth D. Merry * @ingroup os 172ef270ab1SKenneth D. Merry * @brief return the lower 32-bits of a bus address 173ef270ab1SKenneth D. Merry * 174ef270ab1SKenneth D. Merry * @param addr Physical or bus address to convert 175ef270ab1SKenneth D. Merry * @return lower 32-bits of a bus address 176ef270ab1SKenneth D. Merry * 177ef270ab1SKenneth D. Merry * @note this may be a good cadidate for an inline or macro 178ef270ab1SKenneth D. Merry */ 179ef270ab1SKenneth D. Merry static inline uint32_t ocs_addr32_lo(uintptr_t addr) 180ef270ab1SKenneth D. Merry { 181ef270ab1SKenneth D. Merry #if defined(__LP64__) 182ef270ab1SKenneth D. Merry return (uint32_t)(addr & 0xffffffffUL); 183ef270ab1SKenneth D. Merry #else 184ef270ab1SKenneth D. Merry return addr; 185ef270ab1SKenneth D. Merry #endif 186ef270ab1SKenneth D. Merry } 187ef270ab1SKenneth D. Merry 188ef270ab1SKenneth D. Merry /** 189ef270ab1SKenneth D. Merry * @ingroup os 190ef270ab1SKenneth D. Merry * @brief return the upper 32-bits of a bus address 191ef270ab1SKenneth D. Merry * 192ef270ab1SKenneth D. Merry * @param addr Physical or bus address to convert 193ef270ab1SKenneth D. Merry * @return upper 32-bits of a bus address 194ef270ab1SKenneth D. Merry * 195ef270ab1SKenneth D. Merry * @note this may be a good cadidate for an inline or macro 196ef270ab1SKenneth D. Merry */ 197ef270ab1SKenneth D. Merry static inline uint32_t ocs_addr32_hi(uintptr_t addr) 198ef270ab1SKenneth D. Merry { 199ef270ab1SKenneth D. Merry #if defined(__LP64__) 200ef270ab1SKenneth D. Merry return (uint32_t)(addr >> 32); 201ef270ab1SKenneth D. Merry #else 202ef270ab1SKenneth D. Merry return 0; 203ef270ab1SKenneth D. Merry #endif 204ef270ab1SKenneth D. Merry } 205ef270ab1SKenneth D. Merry 206ef270ab1SKenneth D. Merry /** 207ef270ab1SKenneth D. Merry * @ingroup os 208ef270ab1SKenneth D. Merry * @brief return the log2(val) 209ef270ab1SKenneth D. Merry * 210ef270ab1SKenneth D. Merry * @param val number to use (assumed to be exact power of 2) 211ef270ab1SKenneth D. Merry * 212ef270ab1SKenneth D. Merry * @return log base 2 of val 213ef270ab1SKenneth D. Merry */ 214ef270ab1SKenneth D. Merry static inline uint32_t ocs_lg2(uint32_t val) 215ef270ab1SKenneth D. Merry { 216ef270ab1SKenneth D. Merry #if defined(__GNUC__) 217ef270ab1SKenneth D. Merry /* 218ef270ab1SKenneth D. Merry * clz = "count leading zero's" 219ef270ab1SKenneth D. Merry * 220ef270ab1SKenneth D. Merry * Assuming val is an exact power of 2, the most significant bit 221ef270ab1SKenneth D. Merry * will be the log base 2 of val 222ef270ab1SKenneth D. Merry */ 223ef270ab1SKenneth D. Merry return 31 - __builtin_clz(val); 224ef270ab1SKenneth D. Merry #else 225ef270ab1SKenneth D. Merry #error You need to provide a non-GCC version of this function 226ef270ab1SKenneth D. Merry #endif 227ef270ab1SKenneth D. Merry } 228ef270ab1SKenneth D. Merry 229ef270ab1SKenneth D. Merry /** 230ef270ab1SKenneth D. Merry * @ingroup os 231ef270ab1SKenneth D. Merry * @brief optimization barrier 232ef270ab1SKenneth D. Merry * 233ef270ab1SKenneth D. Merry * Optimization barrier. Prevents compiler re-ordering 234ef270ab1SKenneth D. Merry * instructions across barrier. 235ef270ab1SKenneth D. Merry * 236ef270ab1SKenneth D. Merry * @return none 237ef270ab1SKenneth D. Merry */ 238ef270ab1SKenneth D. Merry #define ocs_barrier() __asm __volatile("" : : : "memory"); 239ef270ab1SKenneth D. Merry 240ef270ab1SKenneth D. Merry /** 241ef270ab1SKenneth D. Merry * @ingroup os 242ef270ab1SKenneth D. Merry * @brief convert a big endian 32 bit value to the host's native format 243ef270ab1SKenneth D. Merry * 244ef270ab1SKenneth D. Merry * @param val 32 bit big endian value 245ef270ab1SKenneth D. Merry * 246ef270ab1SKenneth D. Merry * @return value converted to the host's native endianness 247ef270ab1SKenneth D. Merry */ 248ef270ab1SKenneth D. Merry #define ocs_be32toh(val) be32toh(val) 249ef270ab1SKenneth D. Merry 250ef270ab1SKenneth D. Merry /** 251ef270ab1SKenneth D. Merry * @ingroup os 252ef270ab1SKenneth D. Merry * @brief convert a 32 bit value from the host's native format to big endian 253ef270ab1SKenneth D. Merry * 254ef270ab1SKenneth D. Merry * @param val 32 bit native endian value 255ef270ab1SKenneth D. Merry * 256ef270ab1SKenneth D. Merry * @return value converted to big endian 257ef270ab1SKenneth D. Merry */ 258ef270ab1SKenneth D. Merry #define ocs_htobe32(val) htobe32(val) 259ef270ab1SKenneth D. Merry 260ef270ab1SKenneth D. Merry /** 261ef270ab1SKenneth D. Merry * @ingroup os 262ef270ab1SKenneth D. Merry * @brief convert a 16 bit value from the host's native format to big endian 263ef270ab1SKenneth D. Merry * 264ef270ab1SKenneth D. Merry * @param v 16 bit native endian value 265ef270ab1SKenneth D. Merry * 266ef270ab1SKenneth D. Merry * @return value converted to big endian 267ef270ab1SKenneth D. Merry */ 268ef270ab1SKenneth D. Merry #define ocs_htobe16(v) htobe16(v) 269ef270ab1SKenneth D. Merry #define ocs_be16toh(v) be16toh(v) 270ef270ab1SKenneth D. Merry 271ef270ab1SKenneth D. Merry #define ocs_htobe64(v) htobe64(v) 272ef270ab1SKenneth D. Merry #define ocs_be64toh(v) be64toh(v) 273ef270ab1SKenneth D. Merry 274ef270ab1SKenneth D. Merry /** 275ef270ab1SKenneth D. Merry * @ingroup os 276ef270ab1SKenneth D. Merry * @brief Delay execution by the given number of micro-seconds 277ef270ab1SKenneth D. Merry * 278ef270ab1SKenneth D. Merry * @param usec number of micro-seconds to "busy-wait" 279ef270ab1SKenneth D. Merry * 280ef270ab1SKenneth D. Merry * @note The value of usec may be greater than 1,000,000 281ef270ab1SKenneth D. Merry */ 282ef270ab1SKenneth D. Merry #define ocs_udelay(usec) DELAY(usec) 283ef270ab1SKenneth D. Merry 284ef270ab1SKenneth D. Merry /** 285ef270ab1SKenneth D. Merry * @ingroup os 286ef270ab1SKenneth D. Merry * @brief Delay execution by the given number of milli-seconds 287ef270ab1SKenneth D. Merry * 288ef270ab1SKenneth D. Merry * @param msec number of milli-seconds to "busy-wait" 289ef270ab1SKenneth D. Merry * 290ef270ab1SKenneth D. Merry * @note The value of usec may be greater than 1,000,000 291ef270ab1SKenneth D. Merry */ 292ef270ab1SKenneth D. Merry #define ocs_msleep(msec) ocs_udelay((msec)*1000) 293ef270ab1SKenneth D. Merry 294ef270ab1SKenneth D. Merry /** 295ef270ab1SKenneth D. Merry * @ingroup os 296ef270ab1SKenneth D. Merry * @brief Get time of day in msec 297ef270ab1SKenneth D. Merry * 298ef270ab1SKenneth D. Merry * @return time of day in msec 299ef270ab1SKenneth D. Merry */ 300ef270ab1SKenneth D. Merry static inline time_t 301ef270ab1SKenneth D. Merry ocs_msectime(void) 302ef270ab1SKenneth D. Merry { 303ef270ab1SKenneth D. Merry struct timeval tv; 304ef270ab1SKenneth D. Merry 305ef270ab1SKenneth D. Merry getmicrotime(&tv); 306ef270ab1SKenneth D. Merry return (tv.tv_sec*1000) + (tv.tv_usec / 1000); 307ef270ab1SKenneth D. Merry } 308ef270ab1SKenneth D. Merry 309ef270ab1SKenneth D. Merry /** 310ef270ab1SKenneth D. Merry * @ingroup os 311ef270ab1SKenneth D. Merry * @brief Copy length number of bytes from the source to destination address 312ef270ab1SKenneth D. Merry * 313ef270ab1SKenneth D. Merry * @param d pointer to the destination memory 314ef270ab1SKenneth D. Merry * @param s pointer to the source memory 315ef270ab1SKenneth D. Merry * @param l number of bytes to copy 316ef270ab1SKenneth D. Merry * 317ef270ab1SKenneth D. Merry * @return original value of dst pointer 318ef270ab1SKenneth D. Merry */ 319ef270ab1SKenneth D. Merry #define ocs_memcpy(d, s, l) memcpy(d, s, l) 320ef270ab1SKenneth D. Merry 321ef270ab1SKenneth D. Merry #define ocs_strlen(s) strlen(s) 322ef270ab1SKenneth D. Merry #define ocs_strcpy(d,s) strcpy(d, s) 323ef270ab1SKenneth D. Merry #define ocs_strncpy(d,s, n) strncpy(d, s, n) 324ef270ab1SKenneth D. Merry #define ocs_strcat(d, s) strcat(d, s) 325ef270ab1SKenneth D. Merry #define ocs_strtoul(s,ep,b) strtoul(s,ep,b) 326ef270ab1SKenneth D. Merry #define ocs_strtoull(s,ep,b) ((uint64_t)strtouq(s,ep,b)) 327ef270ab1SKenneth D. Merry #define ocs_atoi(s) strtol(s, 0, 0) 328ef270ab1SKenneth D. Merry #define ocs_strcmp(d,s) strcmp(d,s) 329ef270ab1SKenneth D. Merry #define ocs_strcasecmp(d,s) strcasecmp(d,s) 330ef270ab1SKenneth D. Merry #define ocs_strncmp(d,s,n) strncmp(d,s,n) 331ef270ab1SKenneth D. Merry #define ocs_strstr(h,n) strstr(h,n) 332ef270ab1SKenneth D. Merry #define ocs_strsep(h, n) strsep(h, n) 333ef270ab1SKenneth D. Merry #define ocs_strchr(s,c) strchr(s,c) 334ef270ab1SKenneth D. Merry #define ocs_copy_from_user(dst, src, n) copyin(src, dst, n) 335ef270ab1SKenneth D. Merry #define ocs_copy_to_user(dst, src, n) copyout(src, dst, n) 336ef270ab1SKenneth D. Merry #define ocs_snprintf(buf, n, fmt, ...) snprintf(buf, n, fmt, ##__VA_ARGS__) 337ef270ab1SKenneth D. Merry #define ocs_vsnprintf(buf, n, fmt, ap) vsnprintf((char*)buf, n, fmt, ap) 338ef270ab1SKenneth D. Merry #define ocs_sscanf(buf,fmt, ...) sscanf(buf, fmt, ##__VA_ARGS__) 339ef270ab1SKenneth D. Merry #define ocs_printf printf 340ef270ab1SKenneth D. Merry #define ocs_isspace(c) isspace(c) 341ef270ab1SKenneth D. Merry #define ocs_isdigit(c) isdigit(c) 342ef270ab1SKenneth D. Merry #define ocs_isxdigit(c) isxdigit(c) 343ef270ab1SKenneth D. Merry 344ef270ab1SKenneth D. Merry extern uint64_t ocs_get_tsc(void); 345ef270ab1SKenneth D. Merry extern void *ocs_ioctl_preprocess(ocs_os_handle_t os, void *arg, size_t size); 346ef270ab1SKenneth D. Merry extern int32_t ocs_ioctl_postprocess(ocs_os_handle_t os, void *arg, void *kern_ptr, size_t size); 347ef270ab1SKenneth D. Merry extern void ocs_ioctl_free(ocs_os_handle_t os, void *kern_ptr, size_t size); 348ef270ab1SKenneth D. Merry extern char *ocs_strdup(const char *s); 349ef270ab1SKenneth D. Merry 350ef270ab1SKenneth D. Merry /** 351ef270ab1SKenneth D. Merry * @ingroup os 352ef270ab1SKenneth D. Merry * @brief Set the value of each byte in memory 353ef270ab1SKenneth D. Merry * 354ef270ab1SKenneth D. Merry * @param b pointer to the memory 355ef270ab1SKenneth D. Merry * @param c value used to set memory 356ef270ab1SKenneth D. Merry * @param l number of bytes to set 357ef270ab1SKenneth D. Merry * 358ef270ab1SKenneth D. Merry * @return original value of mem pointer 359ef270ab1SKenneth D. Merry */ 360ef270ab1SKenneth D. Merry #define ocs_memset(b, c, l) memset(b, c, l) 361ef270ab1SKenneth D. Merry 362ef270ab1SKenneth D. Merry #define LOG_CRIT 0 363ef270ab1SKenneth D. Merry #define LOG_ERR 1 364ef270ab1SKenneth D. Merry #define LOG_WARN 2 365ef270ab1SKenneth D. Merry #define LOG_INFO 3 366ef270ab1SKenneth D. Merry #define LOG_TEST 4 367ef270ab1SKenneth D. Merry #define LOG_DEBUG 5 368ef270ab1SKenneth D. Merry 369ef270ab1SKenneth D. Merry extern int loglevel; 370ef270ab1SKenneth D. Merry 371ef270ab1SKenneth D. Merry extern void _ocs_log(ocs_t *ocs, const char *func, int line, const char *fmt, ...); 372ef270ab1SKenneth D. Merry 373ef270ab1SKenneth D. Merry #define ocs_log_crit(os, fmt, ...) ocs_log(os, LOG_CRIT, fmt, ##__VA_ARGS__); 374ef270ab1SKenneth D. Merry #define ocs_log_err(os, fmt, ...) ocs_log(os, LOG_ERR, fmt, ##__VA_ARGS__); 375ef270ab1SKenneth D. Merry #define ocs_log_warn(os, fmt, ...) ocs_log(os, LOG_WARN, fmt, ##__VA_ARGS__); 376ef270ab1SKenneth D. Merry #define ocs_log_info(os, fmt, ...) ocs_log(os, LOG_INFO, fmt, ##__VA_ARGS__); 377ef270ab1SKenneth D. Merry #define ocs_log_test(os, fmt, ...) ocs_log(os, LOG_TEST, fmt, ##__VA_ARGS__); 378ef270ab1SKenneth D. Merry #define ocs_log_debug(os, fmt, ...) ocs_log(os, LOG_DEBUG, fmt, ##__VA_ARGS__); 379ef270ab1SKenneth D. Merry 380ef270ab1SKenneth D. Merry #define ocs_log(os, level, fmt, ...) \ 381ef270ab1SKenneth D. Merry do { \ 382ef270ab1SKenneth D. Merry if (level <= loglevel) { \ 383ef270ab1SKenneth D. Merry _ocs_log(os, __func__, __LINE__, fmt, ##__VA_ARGS__); \ 384ef270ab1SKenneth D. Merry } \ 385ef270ab1SKenneth D. Merry } while (0) 386ef270ab1SKenneth D. Merry 387ef270ab1SKenneth D. Merry static inline uint32_t ocs_roundup(uint32_t x, uint32_t y) 388ef270ab1SKenneth D. Merry { 389ef270ab1SKenneth D. Merry return (((x + y - 1) / y) * y); 390ef270ab1SKenneth D. Merry } 391ef270ab1SKenneth D. Merry 392ef270ab1SKenneth D. Merry static inline uint32_t ocs_rounddown(uint32_t x, uint32_t y) 393ef270ab1SKenneth D. Merry { 394ef270ab1SKenneth D. Merry return ((x / y) * y); 395ef270ab1SKenneth D. Merry } 396ef270ab1SKenneth D. Merry 397ef270ab1SKenneth D. Merry /*************************************************************************** 398ef270ab1SKenneth D. Merry * Memory allocation interfaces 399ef270ab1SKenneth D. Merry */ 400ef270ab1SKenneth D. Merry 401ef270ab1SKenneth D. Merry #define OCS_M_ZERO M_ZERO 402ef270ab1SKenneth D. Merry #define OCS_M_NOWAIT M_NOWAIT 403ef270ab1SKenneth D. Merry 404ef270ab1SKenneth D. Merry /** 405ef270ab1SKenneth D. Merry * @ingroup os 406ef270ab1SKenneth D. Merry * @brief Allocate host memory 407ef270ab1SKenneth D. Merry * 408ef270ab1SKenneth D. Merry * @param os OS handle 409ef270ab1SKenneth D. Merry * @param size number of bytes to allocate 410ef270ab1SKenneth D. Merry * @param flags additional options 411ef270ab1SKenneth D. Merry * 412ef270ab1SKenneth D. Merry * Flags include 413ef270ab1SKenneth D. Merry * - OCS_M_ZERO zero memory after allocating 414ef270ab1SKenneth D. Merry * - OCS_M_NOWAIT do not block/sleep waiting for an allocation request 415ef270ab1SKenneth D. Merry * 416ef270ab1SKenneth D. Merry * @return pointer to allocated memory, NULL otherwise 417ef270ab1SKenneth D. Merry */ 418ef270ab1SKenneth D. Merry extern void *ocs_malloc(ocs_os_handle_t os, size_t size, int32_t flags); 419ef270ab1SKenneth D. Merry 420ef270ab1SKenneth D. Merry /** 421ef270ab1SKenneth D. Merry * @ingroup os 422ef270ab1SKenneth D. Merry * @brief Free host memory 423ef270ab1SKenneth D. Merry * 424ef270ab1SKenneth D. Merry * @param os OS handle 425ef270ab1SKenneth D. Merry * @param addr pointer to memory 426ef270ab1SKenneth D. Merry * @param size bytes to free 427ef270ab1SKenneth D. Merry */ 428ef270ab1SKenneth D. Merry extern void ocs_free(ocs_os_handle_t os, void *addr, size_t size); 429ef270ab1SKenneth D. Merry 430ef270ab1SKenneth D. Merry /** 431ef270ab1SKenneth D. Merry * @ingroup os 432ef270ab1SKenneth D. Merry * @brief generic DMA memory descriptor for driver allocations 433ef270ab1SKenneth D. Merry * 434ef270ab1SKenneth D. Merry * Memory regions ultimately used by the hardware are described using 435ef270ab1SKenneth D. Merry * this structure. All implementations must include the structure members 436ef270ab1SKenneth D. Merry * defined in the first section, and they may also add their own structure 437ef270ab1SKenneth D. Merry * members in the second section. 438ef270ab1SKenneth D. Merry * 439ef270ab1SKenneth D. Merry * Note that each region described by ocs_dma_s is assumed to be physically 440ef270ab1SKenneth D. Merry * contiguous. 441ef270ab1SKenneth D. Merry */ 442ef270ab1SKenneth D. Merry typedef struct ocs_dma_s { 443ef270ab1SKenneth D. Merry /* 444ef270ab1SKenneth D. Merry * OCS layer requires the following members 445ef270ab1SKenneth D. Merry */ 446ef270ab1SKenneth D. Merry void *virt; /**< virtual address of the memory used by the CPU */ 447ef270ab1SKenneth D. Merry void *alloc; /**< originally allocated virtual address used to restore virt if modified */ 448ef270ab1SKenneth D. Merry uintptr_t phys; /**< physical or bus address of the memory used by the hardware */ 449ef270ab1SKenneth D. Merry size_t size; /**< size in bytes of the memory */ 450ef270ab1SKenneth D. Merry /* 451ef270ab1SKenneth D. Merry * Implementation specific fields allowed here 452ef270ab1SKenneth D. Merry */ 453ef270ab1SKenneth D. Merry size_t len; /**< application specific length */ 454ef270ab1SKenneth D. Merry bus_dma_tag_t tag; 455ef270ab1SKenneth D. Merry bus_dmamap_t map; 456ef270ab1SKenneth D. Merry } ocs_dma_t; 457ef270ab1SKenneth D. Merry 458ef270ab1SKenneth D. Merry /** 459ef270ab1SKenneth D. Merry * @ingroup os 460ef270ab1SKenneth D. Merry * @brief Returns maximum supported DMA allocation size 461ef270ab1SKenneth D. Merry * 462ef270ab1SKenneth D. Merry * @param os OS specific handle or driver context 463ef270ab1SKenneth D. Merry * @param align alignment requirement for DMA allocation 464ef270ab1SKenneth D. Merry * 465ef270ab1SKenneth D. Merry * Return maximum supported DMA allocation size, given alignment 466ef270ab1SKenneth D. Merry * requirement. 467ef270ab1SKenneth D. Merry * 4687b56cb04SGordon Bergling * @return maximum supported DMA allocation size 469ef270ab1SKenneth D. Merry */ 470ef270ab1SKenneth D. Merry static inline uint32_t ocs_max_dma_alloc(ocs_os_handle_t os, size_t align) 471ef270ab1SKenneth D. Merry { 472ef270ab1SKenneth D. Merry return ~((uint32_t)0); /* no max */ 473ef270ab1SKenneth D. Merry } 474ef270ab1SKenneth D. Merry 475ef270ab1SKenneth D. Merry /** 476ef270ab1SKenneth D. Merry * @ingroup os 477ef270ab1SKenneth D. Merry * @brief Allocate a DMA capable block of memory 478ef270ab1SKenneth D. Merry * 479ef270ab1SKenneth D. Merry * @param os OS specific handle or driver context 480ef270ab1SKenneth D. Merry * @param dma DMA descriptor containing results of memory allocation 481ef270ab1SKenneth D. Merry * @param size Size in bytes of desired allocation 482ef270ab1SKenneth D. Merry * @param align Alignment in bytes of the requested allocation 483ef270ab1SKenneth D. Merry * 484ef270ab1SKenneth D. Merry * @return 0 on success, non-zero otherwise 485ef270ab1SKenneth D. Merry */ 486ef270ab1SKenneth D. Merry extern int32_t ocs_dma_alloc(ocs_os_handle_t, ocs_dma_t *, size_t, size_t); 487ef270ab1SKenneth D. Merry 488ef270ab1SKenneth D. Merry /** 489ef270ab1SKenneth D. Merry * @ingroup os 490ef270ab1SKenneth D. Merry * @brief Free a DMA capable block of memory 491ef270ab1SKenneth D. Merry * 492ef270ab1SKenneth D. Merry * @param os OS specific handle or driver context 493ef270ab1SKenneth D. Merry * @param dma DMA descriptor for memory to be freed 494ef270ab1SKenneth D. Merry * 495ef270ab1SKenneth D. Merry * @return 0 if memory is de-allocated, non-zero otherwise 496ef270ab1SKenneth D. Merry */ 497ef270ab1SKenneth D. Merry extern int32_t ocs_dma_free(ocs_os_handle_t, ocs_dma_t *); 498ef270ab1SKenneth D. Merry extern int32_t ocs_dma_copy_in(ocs_dma_t *dma, void *buffer, uint32_t buffer_length); 499ef270ab1SKenneth D. Merry extern int32_t ocs_dma_copy_out(ocs_dma_t *dma, void *buffer, uint32_t buffer_length); 500ef270ab1SKenneth D. Merry 501ef270ab1SKenneth D. Merry static inline int32_t ocs_dma_valid(ocs_dma_t *dma) 502ef270ab1SKenneth D. Merry { 503ef270ab1SKenneth D. Merry return (dma->size != 0); 504ef270ab1SKenneth D. Merry } 505ef270ab1SKenneth D. Merry 506ef270ab1SKenneth D. Merry /** 507ef270ab1SKenneth D. Merry * @ingroup os 508ef270ab1SKenneth D. Merry * @brief Synchronize the DMA buffer memory 509ef270ab1SKenneth D. Merry * 510ef270ab1SKenneth D. Merry * Ensures memory coherency between the CPU and device 511ef270ab1SKenneth D. Merry * 512ef270ab1SKenneth D. Merry * @param dma DMA descriptor of memory to synchronize 513ef270ab1SKenneth D. Merry * @param flags Describes direction of synchronization 514ef270ab1SKenneth D. Merry * - OCS_DMASYNC_PREREAD sync needed before hardware updates host memory 515ef270ab1SKenneth D. Merry * - OCS_DMASYNC_PREWRITE sync needed after CPU updates host memory but before hardware can access 516ef270ab1SKenneth D. Merry * - OCS_DMASYNC_POSTREAD sync needed after hardware updates host memory but before CPU can access 517ef270ab1SKenneth D. Merry * - OCS_DMASYNC_POSTWRITE sync needed after hardware updates host memory 518ef270ab1SKenneth D. Merry */ 519ef270ab1SKenneth D. Merry extern void ocs_dma_sync(ocs_dma_t *, uint32_t); 520ef270ab1SKenneth D. Merry 521ef270ab1SKenneth D. Merry #define OCS_DMASYNC_PREWRITE BUS_DMASYNC_PREWRITE 522ef270ab1SKenneth D. Merry #define OCS_DMASYNC_POSTREAD BUS_DMASYNC_POSTREAD 523ef270ab1SKenneth D. Merry 524ef270ab1SKenneth D. Merry /*************************************************************************** 525ef270ab1SKenneth D. Merry * Locking 526ef270ab1SKenneth D. Merry */ 527ef270ab1SKenneth D. Merry 528ef270ab1SKenneth D. Merry /** 529ef270ab1SKenneth D. Merry * @ingroup os 530ef270ab1SKenneth D. Merry * @typedef ocs_lock_t 531ef270ab1SKenneth D. Merry * @brief Define the type used implement locking 532ef270ab1SKenneth D. Merry */ 533ef270ab1SKenneth D. Merry #define MAX_LOCK_DESC_LEN 64 534ef270ab1SKenneth D. Merry typedef struct ocs_lock_s { 535ef270ab1SKenneth D. Merry struct mtx lock; 536ef270ab1SKenneth D. Merry char name[MAX_LOCK_DESC_LEN]; 537ef270ab1SKenneth D. Merry } ocs_lock_t; 538ef270ab1SKenneth D. Merry 539ef270ab1SKenneth D. Merry /** 540ef270ab1SKenneth D. Merry * @ingroup os 541ef270ab1SKenneth D. Merry * @brief Initialize a lock 542ef270ab1SKenneth D. Merry * 543ef270ab1SKenneth D. Merry * @param lock lock to initialize 544ef270ab1SKenneth D. Merry * @param name string identifier for the lock 545ef270ab1SKenneth D. Merry */ 546ef270ab1SKenneth D. Merry extern void ocs_lock_init(void *os, ocs_lock_t *lock, const char *name, ...); 547ef270ab1SKenneth D. Merry 548ef270ab1SKenneth D. Merry /** 549ef270ab1SKenneth D. Merry * @ingroup os 550ef270ab1SKenneth D. Merry * @brief Free a previously allocated lock 551ef270ab1SKenneth D. Merry * 552ef270ab1SKenneth D. Merry * @param lock lock to free 553ef270ab1SKenneth D. Merry */ 554ef270ab1SKenneth D. Merry static inline void 555ef270ab1SKenneth D. Merry ocs_lock_free(ocs_lock_t *lock) 556ef270ab1SKenneth D. Merry { 557ef270ab1SKenneth D. Merry 558ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 559ef270ab1SKenneth D. Merry mtx_assert(&(lock)->lock, MA_NOTOWNED); 560ef270ab1SKenneth D. Merry mtx_destroy(&(lock)->lock); 561ef270ab1SKenneth D. Merry } else { 562ef270ab1SKenneth D. Merry panic("XXX trying to free with un-initialized mtx!?!?\n"); 563ef270ab1SKenneth D. Merry } 564ef270ab1SKenneth D. Merry } 565ef270ab1SKenneth D. Merry 566ef270ab1SKenneth D. Merry /** 567ef270ab1SKenneth D. Merry * @ingroup os 568ef270ab1SKenneth D. Merry * @brief Acquire a lock 569ef270ab1SKenneth D. Merry * 570ef270ab1SKenneth D. Merry * @param lock lock to obtain 571ef270ab1SKenneth D. Merry */ 572ef270ab1SKenneth D. Merry static inline void 573ef270ab1SKenneth D. Merry ocs_lock(ocs_lock_t *lock) 574ef270ab1SKenneth D. Merry { 575ef270ab1SKenneth D. Merry 576ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 577ef270ab1SKenneth D. Merry mtx_assert(&(lock)->lock, MA_NOTOWNED); 578ef270ab1SKenneth D. Merry mtx_lock(&(lock)->lock); 579ef270ab1SKenneth D. Merry } else { 580ef270ab1SKenneth D. Merry panic("XXX trying to lock with un-initialized mtx!?!?\n"); 581ef270ab1SKenneth D. Merry } 582ef270ab1SKenneth D. Merry } 583ef270ab1SKenneth D. Merry 584ef270ab1SKenneth D. Merry /** 585ef270ab1SKenneth D. Merry * @ingroup os 586ef270ab1SKenneth D. Merry * @brief Release a lock 587ef270ab1SKenneth D. Merry * 588ef270ab1SKenneth D. Merry * @param lock lock to release 589ef270ab1SKenneth D. Merry */ 590ef270ab1SKenneth D. Merry static inline void 591ef270ab1SKenneth D. Merry ocs_unlock(ocs_lock_t *lock) 592ef270ab1SKenneth D. Merry { 593ef270ab1SKenneth D. Merry 594ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 595ef270ab1SKenneth D. Merry mtx_assert(&(lock)->lock, MA_OWNED | MA_NOTRECURSED); 596ef270ab1SKenneth D. Merry mtx_unlock(&(lock)->lock); 597ef270ab1SKenneth D. Merry } else { 598ef270ab1SKenneth D. Merry panic("XXX trying to unlock with un-initialized mtx!?!?\n"); 599ef270ab1SKenneth D. Merry } 600ef270ab1SKenneth D. Merry } 601ef270ab1SKenneth D. Merry 602ef270ab1SKenneth D. Merry /** 603ef270ab1SKenneth D. Merry * @ingroup os 604ef270ab1SKenneth D. Merry * @typedef ocs_lock_t 605ef270ab1SKenneth D. Merry * @brief Define the type used implement recursive locking 606ef270ab1SKenneth D. Merry */ 607ef270ab1SKenneth D. Merry typedef struct ocs_lock_s ocs_rlock_t; 608ef270ab1SKenneth D. Merry 609ef270ab1SKenneth D. Merry /** 610ef270ab1SKenneth D. Merry * @ingroup os 611ef270ab1SKenneth D. Merry * @brief Initialize a recursive lock 612ef270ab1SKenneth D. Merry * 613ef270ab1SKenneth D. Merry * @param ocs pointer to ocs structure 614ef270ab1SKenneth D. Merry * @param lock lock to initialize 615ef270ab1SKenneth D. Merry * @param name string identifier for the lock 616ef270ab1SKenneth D. Merry */ 617ef270ab1SKenneth D. Merry static inline void 618ef270ab1SKenneth D. Merry ocs_rlock_init(ocs_t *ocs, ocs_rlock_t *lock, const char *name) 619ef270ab1SKenneth D. Merry { 620ef270ab1SKenneth D. Merry ocs_strncpy(lock->name, name, MAX_LOCK_DESC_LEN); 621ef270ab1SKenneth D. Merry mtx_init(&(lock)->lock, lock->name, NULL, MTX_DEF | MTX_RECURSE | MTX_DUPOK); 622ef270ab1SKenneth D. Merry } 623ef270ab1SKenneth D. Merry 624ef270ab1SKenneth D. Merry /** 625ef270ab1SKenneth D. Merry * @ingroup os 626ef270ab1SKenneth D. Merry * @brief Free a previously allocated recursive lock 627ef270ab1SKenneth D. Merry * 628ef270ab1SKenneth D. Merry * @param lock lock to free 629ef270ab1SKenneth D. Merry */ 630ef270ab1SKenneth D. Merry static inline void 631ef270ab1SKenneth D. Merry ocs_rlock_free(ocs_rlock_t *lock) 632ef270ab1SKenneth D. Merry { 633ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 634ef270ab1SKenneth D. Merry mtx_destroy(&(lock)->lock); 635ef270ab1SKenneth D. Merry } else { 636ef270ab1SKenneth D. Merry panic("XXX trying to free with un-initialized mtx!?!?\n"); 637ef270ab1SKenneth D. Merry } 638ef270ab1SKenneth D. Merry } 639ef270ab1SKenneth D. Merry 640ef270ab1SKenneth D. Merry /** 641ef270ab1SKenneth D. Merry * @brief try to acquire a recursive lock 642ef270ab1SKenneth D. Merry * 643ef270ab1SKenneth D. Merry * Attempt to acquire a recursive lock, return TRUE if successful 644ef270ab1SKenneth D. Merry * 645ef270ab1SKenneth D. Merry * @param lock pointer to recursive lock 646ef270ab1SKenneth D. Merry * 647ef270ab1SKenneth D. Merry * @return TRUE if lock was acquired, FALSE if not 648ef270ab1SKenneth D. Merry */ 649ef270ab1SKenneth D. Merry static inline int32_t 650ef270ab1SKenneth D. Merry ocs_rlock_try(ocs_rlock_t *lock) 651ef270ab1SKenneth D. Merry { 652ef270ab1SKenneth D. Merry int rc = mtx_trylock(&(lock)->lock); 653ef270ab1SKenneth D. Merry 654ef270ab1SKenneth D. Merry return rc != 0; 655ef270ab1SKenneth D. Merry } 656ef270ab1SKenneth D. Merry 657ef270ab1SKenneth D. Merry /** 658ef270ab1SKenneth D. Merry * @ingroup os 659ef270ab1SKenneth D. Merry * @brief Acquire a recursive lock 660ef270ab1SKenneth D. Merry * 661ef270ab1SKenneth D. Merry * @param lock lock to obtain 662ef270ab1SKenneth D. Merry */ 663ef270ab1SKenneth D. Merry static inline void 664ef270ab1SKenneth D. Merry ocs_rlock_acquire(ocs_rlock_t *lock) 665ef270ab1SKenneth D. Merry { 666ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 667ef270ab1SKenneth D. Merry mtx_lock(&(lock)->lock); 668ef270ab1SKenneth D. Merry } else { 669ef270ab1SKenneth D. Merry panic("XXX trying to lock with un-initialized mtx!?!?\n"); 670ef270ab1SKenneth D. Merry } 671ef270ab1SKenneth D. Merry } 672ef270ab1SKenneth D. Merry 673ef270ab1SKenneth D. Merry /** 674ef270ab1SKenneth D. Merry * @ingroup os 675ef270ab1SKenneth D. Merry * @brief Release a recursive lock 676ef270ab1SKenneth D. Merry * 677ef270ab1SKenneth D. Merry * @param lock lock to release 678ef270ab1SKenneth D. Merry */ 679ef270ab1SKenneth D. Merry static inline void 680ef270ab1SKenneth D. Merry ocs_rlock_release(ocs_rlock_t *lock) 681ef270ab1SKenneth D. Merry { 682ef270ab1SKenneth D. Merry if (mtx_initialized(&(lock)->lock)) { 683ef270ab1SKenneth D. Merry mtx_assert(&(lock)->lock, MA_OWNED); 684ef270ab1SKenneth D. Merry mtx_unlock(&(lock)->lock); 685ef270ab1SKenneth D. Merry } else { 686ef270ab1SKenneth D. Merry panic("XXX trying to unlock with un-initialized mtx!?!?\n"); 687ef270ab1SKenneth D. Merry } 688ef270ab1SKenneth D. Merry } 689ef270ab1SKenneth D. Merry 690ef270ab1SKenneth D. Merry /** 691ef270ab1SKenneth D. Merry * @brief counting semaphore 692ef270ab1SKenneth D. Merry * 693ef270ab1SKenneth D. Merry * Declaration of the counting semaphore object 694ef270ab1SKenneth D. Merry * 695ef270ab1SKenneth D. Merry */ 696ef270ab1SKenneth D. Merry typedef struct { 697ef270ab1SKenneth D. Merry char name[32]; 698ef270ab1SKenneth D. Merry struct sema sem; /**< OS counting semaphore structure */ 699ef270ab1SKenneth D. Merry } ocs_sem_t; 700ef270ab1SKenneth D. Merry 701ef270ab1SKenneth D. Merry #define OCS_SEM_FOREVER (-1) 702ef270ab1SKenneth D. Merry #define OCS_SEM_TRY (0) 703ef270ab1SKenneth D. Merry 704ef270ab1SKenneth D. Merry /** 705ef270ab1SKenneth D. Merry * @brief Initialize a counting semaphore 706ef270ab1SKenneth D. Merry * 707ef270ab1SKenneth D. Merry * The semaphore is initiatlized to the value 708ef270ab1SKenneth D. Merry * 709ef270ab1SKenneth D. Merry * @param sem pointer to semaphore 710ef270ab1SKenneth D. Merry * @param val initial value 711ef270ab1SKenneth D. Merry * @param name label for the semaphore 712ef270ab1SKenneth D. Merry * 713ef270ab1SKenneth D. Merry * @return returns 0 for success, a negative error code value for failure. 714ef270ab1SKenneth D. Merry */ 715ef270ab1SKenneth D. Merry 716ef270ab1SKenneth D. Merry extern int ocs_sem_init(ocs_sem_t *sem, int val, const char *name, ...) __attribute__((format(printf, 3, 4))); 717ef270ab1SKenneth D. Merry 718ef270ab1SKenneth D. Merry /** 719ef270ab1SKenneth D. Merry * @brief execute a P (decrement) operation 720ef270ab1SKenneth D. Merry * 721ef270ab1SKenneth D. Merry * A P (decrement and block if negative) operation is performed on the semaphore. 722ef270ab1SKenneth D. Merry * 723ef270ab1SKenneth D. Merry * If timeout_usec is zero, the semaphore attempts one time and returns 0 if acquired. 724ef270ab1SKenneth D. Merry * If timeout_usec is greater than zero, then the call will block until the semaphore 725ef270ab1SKenneth D. Merry * is acquired, or a timeout occurred. If timeout_usec is less than zero, then 726ef270ab1SKenneth D. Merry * the call will block until the semaphore is acquired. 727ef270ab1SKenneth D. Merry * 728ef270ab1SKenneth D. Merry * @param sem pointer to semaphore 729ef270ab1SKenneth D. Merry * @param timeout_usec timeout in microseconds 730ef270ab1SKenneth D. Merry * 731ef270ab1SKenneth D. Merry * @return returns 0 for success, negative value if the semaphore was not acquired. 732ef270ab1SKenneth D. Merry */ 733ef270ab1SKenneth D. Merry 734ef270ab1SKenneth D. Merry static inline int 735ef270ab1SKenneth D. Merry ocs_sem_p(ocs_sem_t *sem, int timeout_usec) 736ef270ab1SKenneth D. Merry { 737ef270ab1SKenneth D. Merry int32_t rc = 0; 738ef270ab1SKenneth D. Merry 739ef270ab1SKenneth D. Merry if (timeout_usec == 0) { 740ef270ab1SKenneth D. Merry rc = sema_trywait(&sem->sem); 741ef270ab1SKenneth D. Merry if (rc == 0) { 742ef270ab1SKenneth D. Merry rc = -1; 743ef270ab1SKenneth D. Merry } 744ef270ab1SKenneth D. Merry } else if (timeout_usec > 0) { 745ef270ab1SKenneth D. Merry struct timeval tv; 746ef270ab1SKenneth D. Merry uint32_t ticks; 747ef270ab1SKenneth D. Merry 748ef270ab1SKenneth D. Merry tv.tv_sec = timeout_usec / 1000000; 749ef270ab1SKenneth D. Merry tv.tv_usec = timeout_usec % 1000000; 750ef270ab1SKenneth D. Merry ticks = tvtohz(&tv); 751ef270ab1SKenneth D. Merry if (ticks == 0) { 752ef270ab1SKenneth D. Merry ticks ++; 753ef270ab1SKenneth D. Merry } 754ef270ab1SKenneth D. Merry rc = sema_timedwait(&sem->sem, ticks); 755ef270ab1SKenneth D. Merry if (rc != 0) { 756ef270ab1SKenneth D. Merry rc = -1; 757ef270ab1SKenneth D. Merry } 758ef270ab1SKenneth D. Merry } else { 759ef270ab1SKenneth D. Merry sema_wait(&sem->sem); 760ef270ab1SKenneth D. Merry } 761ef270ab1SKenneth D. Merry if (rc) 762ef270ab1SKenneth D. Merry rc = -1; 763ef270ab1SKenneth D. Merry 764ef270ab1SKenneth D. Merry return rc; 765ef270ab1SKenneth D. Merry } 766ef270ab1SKenneth D. Merry 767ef270ab1SKenneth D. Merry /** 768ef270ab1SKenneth D. Merry * @brief perform a V (increment) operation on a counting semaphore 769ef270ab1SKenneth D. Merry * 770ef270ab1SKenneth D. Merry * The semaphore is incremented, unblocking one thread that is waiting on the 771ef270ab1SKenneth D. Merry * sempahore 772ef270ab1SKenneth D. Merry * 773ef270ab1SKenneth D. Merry * @param sem pointer to the semaphore 774ef270ab1SKenneth D. Merry * 775ef270ab1SKenneth D. Merry * @return none 776ef270ab1SKenneth D. Merry */ 777ef270ab1SKenneth D. Merry 778ef270ab1SKenneth D. Merry static inline void 779ef270ab1SKenneth D. Merry ocs_sem_v(ocs_sem_t *sem) 780ef270ab1SKenneth D. Merry { 781ef270ab1SKenneth D. Merry sema_post(&sem->sem); 782ef270ab1SKenneth D. Merry } 783ef270ab1SKenneth D. Merry 784ef270ab1SKenneth D. Merry /*************************************************************************** 785ef270ab1SKenneth D. Merry * Bitmap 786ef270ab1SKenneth D. Merry */ 787ef270ab1SKenneth D. Merry 788ef270ab1SKenneth D. Merry /** 789ef270ab1SKenneth D. Merry * @ingroup os 790ef270ab1SKenneth D. Merry * @typedef ocs_bitmap_t 791ef270ab1SKenneth D. Merry * @brief Define the type used implement bit-maps 792ef270ab1SKenneth D. Merry */ 793ef270ab1SKenneth D. Merry typedef bitstr_t ocs_bitmap_t; 794ef270ab1SKenneth D. Merry 795ef270ab1SKenneth D. Merry /** 796ef270ab1SKenneth D. Merry * @ingroup os 797ef270ab1SKenneth D. Merry * @brief Allocate a bitmap 798ef270ab1SKenneth D. Merry * 799ef270ab1SKenneth D. Merry * @param n_bits Minimum number of entries in the bit-map 800ef270ab1SKenneth D. Merry * 801ef270ab1SKenneth D. Merry * @return pointer to the bit-map or NULL on error 802ef270ab1SKenneth D. Merry */ 803ef270ab1SKenneth D. Merry extern ocs_bitmap_t *ocs_bitmap_alloc(uint32_t n_bits); 804ef270ab1SKenneth D. Merry 805ef270ab1SKenneth D. Merry /** 806ef270ab1SKenneth D. Merry * @ingroup os 807ef270ab1SKenneth D. Merry * @brief Free a bit-map 808ef270ab1SKenneth D. Merry * 809ef270ab1SKenneth D. Merry * @param bitmap Bit-map to free 810ef270ab1SKenneth D. Merry */ 811ef270ab1SKenneth D. Merry extern void ocs_bitmap_free(ocs_bitmap_t *bitmap); 812ef270ab1SKenneth D. Merry 813ef270ab1SKenneth D. Merry /** 814ef270ab1SKenneth D. Merry * @ingroup os 815ef270ab1SKenneth D. Merry * @brief Find next unset bit and set it 816ef270ab1SKenneth D. Merry * 817ef270ab1SKenneth D. Merry * @param bitmap bit map to search 818ef270ab1SKenneth D. Merry * @param n_bits number of bits in map 819ef270ab1SKenneth D. Merry * 820ef270ab1SKenneth D. Merry * @return bit position or -1 if map is full 821ef270ab1SKenneth D. Merry */ 822ef270ab1SKenneth D. Merry extern int32_t ocs_bitmap_find(ocs_bitmap_t *bitmap, uint32_t n_bits); 823ef270ab1SKenneth D. Merry 824ef270ab1SKenneth D. Merry /** 825ef270ab1SKenneth D. Merry * @ingroup os 826ef270ab1SKenneth D. Merry * @brief search for next (un)set bit 827ef270ab1SKenneth D. Merry * 828ef270ab1SKenneth D. Merry * @param bitmap bit map to search 829ef270ab1SKenneth D. Merry * @param set search for a set or unset bit 830ef270ab1SKenneth D. Merry * @param n_bits number of bits in map 831ef270ab1SKenneth D. Merry * 832ef270ab1SKenneth D. Merry * @return bit position or -1 833ef270ab1SKenneth D. Merry */ 834ef270ab1SKenneth D. Merry extern int32_t ocs_bitmap_search(ocs_bitmap_t *bitmap, uint8_t set, uint32_t n_bits); 835ef270ab1SKenneth D. Merry 836ef270ab1SKenneth D. Merry /** 837ef270ab1SKenneth D. Merry * @ingroup os 838ef270ab1SKenneth D. Merry * @brief clear the specified bit 839ef270ab1SKenneth D. Merry * 840ef270ab1SKenneth D. Merry * @param bitmap pointer to bit map 841ef270ab1SKenneth D. Merry * @param bit bit number to clear 842ef270ab1SKenneth D. Merry */ 843ef270ab1SKenneth D. Merry extern void ocs_bitmap_clear(ocs_bitmap_t *bitmap, uint32_t bit); 844ef270ab1SKenneth D. Merry 845ef270ab1SKenneth D. Merry extern int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len); 846ef270ab1SKenneth D. Merry 847ef270ab1SKenneth D. Merry /*************************************************************************** 848ef270ab1SKenneth D. Merry * Timer Routines 849ef270ab1SKenneth D. Merry * 850ef270ab1SKenneth D. Merry * Functions for setting, querying and canceling timers. 851ef270ab1SKenneth D. Merry */ 852ef270ab1SKenneth D. Merry typedef struct { 853ef270ab1SKenneth D. Merry struct callout callout; 854ef270ab1SKenneth D. Merry struct mtx lock; 855ef270ab1SKenneth D. Merry 856ef270ab1SKenneth D. Merry void (*func)(void *); 857ef270ab1SKenneth D. Merry void *data; 858ef270ab1SKenneth D. Merry } ocs_timer_t; 859ef270ab1SKenneth D. Merry 860ef270ab1SKenneth D. Merry /** 861ef270ab1SKenneth D. Merry * @ingroup os 862ef270ab1SKenneth D. Merry * @brief Initialize and set a timer 863ef270ab1SKenneth D. Merry * 864ef270ab1SKenneth D. Merry * @param os OS handle 865ef270ab1SKenneth D. Merry * @param timer pointer to the structure allocated for this timer 866ef270ab1SKenneth D. Merry * @param func the function to call when the timer expires 867ef270ab1SKenneth D. Merry * @param data Data to pass to the provided timer function when the timer 868ef270ab1SKenneth D. Merry * expires. 869ef270ab1SKenneth D. Merry * @param timeout_ms the timeout in milliseconds 870ef270ab1SKenneth D. Merry */ 871ef270ab1SKenneth D. Merry extern int32_t ocs_setup_timer(ocs_os_handle_t os, ocs_timer_t *timer, void(*func)(void *arg), 872ef270ab1SKenneth D. Merry void *data, uint32_t timeout_ms); 873ef270ab1SKenneth D. Merry 874ef270ab1SKenneth D. Merry /** 875ef270ab1SKenneth D. Merry * @ingroup os 876ef270ab1SKenneth D. Merry * @brief Modify a timer's expiration 877ef270ab1SKenneth D. Merry * 878ef270ab1SKenneth D. Merry * @param timer pointer to the structure allocated for this timer 879ef270ab1SKenneth D. Merry * @param timeout_ms the timeout in milliseconds 880ef270ab1SKenneth D. Merry */ 881ef270ab1SKenneth D. Merry extern int32_t ocs_mod_timer(ocs_timer_t *timer, uint32_t timeout_ms); 882ef270ab1SKenneth D. Merry 883ef270ab1SKenneth D. Merry /** 884ef270ab1SKenneth D. Merry * @ingroup os 885ef270ab1SKenneth D. Merry * @brief Queries to see if a timer is pending. 886ef270ab1SKenneth D. Merry * 887ef270ab1SKenneth D. Merry * @param timer pointer to the structure allocated for this timer 888ef270ab1SKenneth D. Merry * 889ef270ab1SKenneth D. Merry * @return non-zero if the timer is pending 890ef270ab1SKenneth D. Merry */ 891ef270ab1SKenneth D. Merry extern int32_t ocs_timer_pending(ocs_timer_t *timer); 892ef270ab1SKenneth D. Merry 893ef270ab1SKenneth D. Merry /** 894ef270ab1SKenneth D. Merry * @ingroup os 895ef270ab1SKenneth D. Merry * @brief Remove a pending timer 896ef270ab1SKenneth D. Merry * 897ef270ab1SKenneth D. Merry * @param timer pointer to the structure allocated for this timer 898ef270ab1SKenneth D. Merry * expires. 899ef270ab1SKenneth D. Merry */ 900ef270ab1SKenneth D. Merry extern int32_t ocs_del_timer(ocs_timer_t *timer); 901ef270ab1SKenneth D. Merry 902ef270ab1SKenneth D. Merry /*************************************************************************** 903ef270ab1SKenneth D. Merry * Atomics 904ef270ab1SKenneth D. Merry * 905ef270ab1SKenneth D. Merry */ 906ef270ab1SKenneth D. Merry 907ef270ab1SKenneth D. Merry typedef uint32_t ocs_atomic_t; 908ef270ab1SKenneth D. Merry 909ef270ab1SKenneth D. Merry /** 910ef270ab1SKenneth D. Merry * @ingroup os 911ef270ab1SKenneth D. Merry * @brief initialize an atomic 912ef270ab1SKenneth D. Merry * 913ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 914ef270ab1SKenneth D. Merry * @param v initial value 915ef270ab1SKenneth D. Merry * 916ef270ab1SKenneth D. Merry * @return none 917ef270ab1SKenneth D. Merry */ 918ef270ab1SKenneth D. Merry #define ocs_atomic_init(a, v) ocs_atomic_set(a, v) 919ef270ab1SKenneth D. Merry 920ef270ab1SKenneth D. Merry /** 921ef270ab1SKenneth D. Merry * @ingroup os 922ef270ab1SKenneth D. Merry * @brief adds an integer to an atomic value 923ef270ab1SKenneth D. Merry * 924ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 925ef270ab1SKenneth D. Merry * @param v value to increment 926ef270ab1SKenneth D. Merry * 927ef270ab1SKenneth D. Merry * @return the value of the atomic before incrementing. 928ef270ab1SKenneth D. Merry */ 929ef270ab1SKenneth D. Merry #define ocs_atomic_add_return(a, v) atomic_fetchadd_32(a, v) 930ef270ab1SKenneth D. Merry 931ef270ab1SKenneth D. Merry /** 932ef270ab1SKenneth D. Merry * @ingroup os 933ef270ab1SKenneth D. Merry * @brief subtracts an integer to an atomic value 934ef270ab1SKenneth D. Merry * 935ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 936ef270ab1SKenneth D. Merry * @param v value to increment 937ef270ab1SKenneth D. Merry * 938ef270ab1SKenneth D. Merry * @return the value of the atomic before subtracting. 939ef270ab1SKenneth D. Merry */ 940ef270ab1SKenneth D. Merry #define ocs_atomic_sub_return(a, v) atomic_fetchadd_32(a, (-(v))) 941ef270ab1SKenneth D. Merry 942ef270ab1SKenneth D. Merry /** 943ef270ab1SKenneth D. Merry * @ingroup os 944ef270ab1SKenneth D. Merry * @brief returns the current value of an atomic object 945ef270ab1SKenneth D. Merry * 946ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 947ef270ab1SKenneth D. Merry * 948ef270ab1SKenneth D. Merry * @return the value of the atomic. 949ef270ab1SKenneth D. Merry */ 950ef270ab1SKenneth D. Merry #define ocs_atomic_read(a) atomic_load_acq_32(a) 951ef270ab1SKenneth D. Merry 952ef270ab1SKenneth D. Merry /** 953ef270ab1SKenneth D. Merry * @ingroup os 954ef270ab1SKenneth D. Merry * @brief sets the current value of an atomic object 955ef270ab1SKenneth D. Merry * 956ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 957ef270ab1SKenneth D. Merry */ 958ef270ab1SKenneth D. Merry #define ocs_atomic_set(a, v) atomic_store_rel_32(a, v) 959ef270ab1SKenneth D. Merry 960ef270ab1SKenneth D. Merry /** 961ef270ab1SKenneth D. Merry * @ingroup os 962ef270ab1SKenneth D. Merry * @brief Sets atomic to 0, returns previous value 963ef270ab1SKenneth D. Merry * 964ef270ab1SKenneth D. Merry * @param a pointer to the atomic object 965ef270ab1SKenneth D. Merry * 966ef270ab1SKenneth D. Merry * @return the value of the atomic before the operation. 967ef270ab1SKenneth D. Merry */ 968ef270ab1SKenneth D. Merry #define ocs_atomic_read_and_clear atomic_readandclear_32(a) 969ef270ab1SKenneth D. Merry 970ef270ab1SKenneth D. Merry /** 971ef270ab1SKenneth D. Merry * @brief OCS thread structure 972ef270ab1SKenneth D. Merry * 973ef270ab1SKenneth D. Merry */ 974ef270ab1SKenneth D. Merry 975ef270ab1SKenneth D. Merry typedef struct ocs_thread_s ocs_thread_t; 976ef270ab1SKenneth D. Merry 977ef270ab1SKenneth D. Merry typedef int32_t (*ocs_thread_fctn)(ocs_thread_t *mythread); 978ef270ab1SKenneth D. Merry 979ef270ab1SKenneth D. Merry struct ocs_thread_s { 980ef270ab1SKenneth D. Merry struct thread *tcb; /*<< thread control block */ 981ef270ab1SKenneth D. Merry ocs_thread_fctn fctn; /*<< thread function */ 982ef270ab1SKenneth D. Merry char *name; /*<< name of thread */ 983ef270ab1SKenneth D. Merry void *arg; /*<< pointer to thread argument */ 984ef270ab1SKenneth D. Merry ocs_atomic_t terminate; /*<< terminate request */ 985ef270ab1SKenneth D. Merry int32_t retval; /*<< return value */ 986ef270ab1SKenneth D. Merry uint32_t cpu_affinity; /*<< cpu affinity */ 987ef270ab1SKenneth D. Merry }; 988ef270ab1SKenneth D. Merry #define OCS_THREAD_DEFAULT_STACK_SIZE_PAGES 8 989ef270ab1SKenneth D. Merry 990ef270ab1SKenneth D. Merry /** 991ef270ab1SKenneth D. Merry * @brief OCS thread start options 992ef270ab1SKenneth D. Merry * 993ef270ab1SKenneth D. Merry */ 994ef270ab1SKenneth D. Merry 995ef270ab1SKenneth D. Merry typedef enum { 996ef270ab1SKenneth D. Merry OCS_THREAD_RUN, /*<< run immediately */ 997ef270ab1SKenneth D. Merry OCS_THREAD_CREATE, /*<< create and wait for start request */ 998ef270ab1SKenneth D. Merry } ocs_thread_start_e; 999ef270ab1SKenneth D. Merry 1000ef270ab1SKenneth D. Merry extern int32_t ocs_thread_create(ocs_os_handle_t os, ocs_thread_t *thread, ocs_thread_fctn fctn, 1001ef270ab1SKenneth D. Merry const char *name, void *arg, ocs_thread_start_e start_option); 1002ef270ab1SKenneth D. Merry extern int32_t ocs_thread_start(ocs_thread_t *thread); 1003ef270ab1SKenneth D. Merry extern void *ocs_thread_get_arg(ocs_thread_t *mythread); 1004ef270ab1SKenneth D. Merry extern int32_t ocs_thread_terminate(ocs_thread_t *thread); 1005ef270ab1SKenneth D. Merry extern int32_t ocs_thread_terminate_requested(ocs_thread_t *thread); 1006ef270ab1SKenneth D. Merry extern int32_t ocs_thread_get_retval(ocs_thread_t *thread); 1007ef270ab1SKenneth D. Merry extern void ocs_thread_yield(ocs_thread_t *thread); 1008ef270ab1SKenneth D. Merry extern ocs_thread_t *ocs_thread_self(void); 1009ef270ab1SKenneth D. Merry extern int32_t ocs_thread_setcpu(ocs_thread_t *thread, uint32_t cpu); 1010ef270ab1SKenneth D. Merry extern int32_t ocs_thread_getcpu(void); 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) */ 10403bf42363SRam Kishore Vegesna #define PCI_PRODUCT_EMULEX_LANCER_G7 0xf400 /* LightPulse 32Gb x 4 FC (lancer-g7) */ 10413bf42363SRam Kishore Vegesna 1042ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE1600_VF 0xe208 1043ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE50102 0xe260 /* OneCore FCoE (lancer) */ 1044ef270ab1SKenneth D. Merry #define PCI_PRODUCT_EMULEX_OCE50102_VF 0xe268 1045ef270ab1SKenneth D. Merry 1046ef270ab1SKenneth D. Merry /** 1047ef270ab1SKenneth D. Merry * @ingroup os 1048ef270ab1SKenneth D. Merry * @brief Get the PCI bus, device, and function values 1049ef270ab1SKenneth D. Merry * 1050ef270ab1SKenneth D. Merry * @param ocs OS specific handle or driver context 1051ef270ab1SKenneth D. Merry * @param bus Pointer to location to store the bus number. 1052ef270ab1SKenneth D. Merry * @param dev Pointer to location to store the device number. 1053ef270ab1SKenneth D. Merry * @param func Pointer to location to store the function number. 1054ef270ab1SKenneth D. Merry * 1055ef270ab1SKenneth D. Merry */ 105629e2dbd4SRam Kishore Vegesna extern void 1057ef270ab1SKenneth D. Merry ocs_get_bus_dev_func(ocs_t *ocs, uint8_t* bus, uint8_t* dev, uint8_t* func); 1058ef270ab1SKenneth D. Merry 1059ef270ab1SKenneth D. Merry extern ocs_t *ocs_get_instance(uint32_t index); 1060ef270ab1SKenneth D. Merry extern uint32_t ocs_instance(void *os); 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