/*************************************************************** ** ** Broadcom Corp. Confidential ** Copyright 1998-2000 Broadcom Corp. All Rights Reserved. ** ** THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED ** SOFTWARE LICENSE AGREEMENT BETWEEN THE USER AND BROADCOM. ** YOU HAVE NO RIGHT TO USE OR EXPLOIT THIS MATERIAL EXCEPT ** SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. ** ** File: ministd.c ** Description: subset of standard c functions. ****************************************************************/ #include "ministd.h" #include "serial.h" #include "bcmmemmgr.h" #include "bchp_hif_cpu_intr1.h" #include "bchp_irq0.h" #include "bkni_print.h" #if SUPPORT_DST_PLATFORM bcm_heap_t *g_p_sdram_heap = NULL; #else static bcm_heap_t *g_p_sdram_heap = NULL; #endif static bcm_heap_t g_sdram_heap; extern unsigned int _end; #ifdef ACB612 /* some ACB612 boards have 256 MB DDR */ #ifdef CONFIG_AOV_SDRAM_1G #define SDRAM_SIZE (128 * 1024 * 1024) #else #define SDRAM_SIZE (256 * 1024 * 1024) #endif #else #define SDRAM_SIZE (256 * 1024 * 1024) #endif #define do_div64_32(res, high, low, base) ({ \ unsigned long __quot, __mod; \ unsigned long __cf, __tmp, __tmp2, __i; \ \ __asm__(".set push\n\t" \ ".set noat\n\t" \ ".set noreorder\n\t" \ "move %2, $0\n\t" \ "move %3, $0\n\t" \ "b 1f\n\t" \ " li %4, 0x21\n" \ "0:\n\t" \ "sll $1, %0, 0x1\n\t" \ "srl %3, %0, 0x1f\n\t" \ "or %0, $1, %5\n\t" \ "sll %1, %1, 0x1\n\t" \ "sll %2, %2, 0x1\n" \ "1:\n\t" \ "bnez %3, 2f\n\t" \ "sltu %5, %0, %z6\n\t" \ "bnez %5, 3f\n\t" \ "2:\n\t" \ " addiu %4,%4,-1\n\t" \ "subu %0, %0, %z6\n\t" \ "addiu %2, %2, 1\n" \ "3:\n\t" \ "bnez %4, 0b\n\t" \ " srl %5, %1, 0x1f\n\t" \ ".set pop" \ : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ "=&r" (__i), "=&r" (__tmp2) \ : "Jr" (base), "0" (high), "1" (low)); \ \ (res) = __quot; \ __mod; }) #if 1 /*defined(SDE_MIPS) || defined(__NEWLIB__) */ #define do_div(n,base) ({ \ int __res; \ __res = ((unsigned long) (n)) % (unsigned) (base); \ (n) = ((unsigned long) (n)) / (unsigned) (base); \ __res; }) #else #define do_div(n, base) ({ \ unsigned long long __quot; \ unsigned long __upper, __low, __high, __mod; \ \ __quot = (n); \ __high = __quot >> 32; \ __low = __quot; \ __upper = __high; \ \ if (__high) \ __asm__("divu $0,%z2,%z3" \ : "=h" (__upper), "=l" (__high) \ : "Jr" (__high), "Jr" (base)); \ \ __mod = do_div64_32(__low, __upper, __low, base); \ \ __quot = __high; \ __quot = __quot << 32 | __low; \ (n) = __quot; \ __mod; }) #endif static unsigned b_div64_32(unsigned *res, unsigned high, unsigned low, unsigned base) { unsigned res_; unsigned rem; rem = do_div64_32(res_, high, low, base); *res = res_; return rem; } /* __udivdi3 calls are generated by gcc due long long division done in the bvdc_window_priv.c PI files * to avoid problems linking this function is supplied here */ #if 1 unsigned long long __udivdi3(unsigned long long n, unsigned long long d) { long mod; if (d & ~0xffffffff) { printf("Need true 64-bit/64-bit division\n"); __asm__("sdbbp"); } mod = do_div(n, (uint32_t)d); return n; } #endif #ifndef __NEWLIB__ #ifndef va_arg #ifndef _VALIST #define _VALIST typedef char *va_list; #endif /* _VALIST */ /* * Storage alignment properties */ #define _AUPBND (sizeof (int) - 1) #define _ADNBND (sizeof (int) - 1) /* * Variable argument list macro definitions */ #define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) #define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) #define va_end(ap) (void) 0 #define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) #endif /* va_arg */ /**************************************************************** * put_c() ****************************************************************/ static inline void put_c(char ch) { #ifdef CONFIG_ENABLE_UART serial_putc(CONSOLE_UART, ch); #endif #ifdef CONFIG_ENABLE_FAST_UART SW_EMU_FAST_UART_OUT(ch); #endif } /**************************************************************** * put_str() ****************************************************************/ static void put_str(char *s) { char ch; while ('\0'!=(ch=*s++)) { if (ch=='\n') { put_c('\r'); } put_c(ch); } } /**************************************************************** * Other C-Libs that might be provided by OS. ****************************************************************/ #ifndef TAB #define TAB_CH 0x09 #endif #ifndef SPACE #define SPACE_CH 0x20 #endif #ifndef SkipWhiteSpace #define SkipWhiteSpace(z) while (*z == TAB_CH || *z == SPACE_CH) z++; #endif #ifndef toupper #define toupper(x) (x&0xDF) #endif #ifndef isnum #define isnum(x) (x >= '0' && x <= '9') ? 1 : 0 #endif #ifndef ishexnum #define ishexnum(x) ((x >= '0' && x <= '9') || ((x & 0xDF) >= 'A' && (x & 0xDF) <= 'F')) ? 1 : 0 #endif int sscanf (char* buf, char* fmt, unsigned int * val) { int valid; unsigned int result, base; char * pbuf; if (!buf || !fmt || !val) return 0; SkipWhiteSpace(fmt); SkipWhiteSpace(buf); pbuf = buf; if (*fmt != '%') return 0; fmt++; if (*fmt == 'x' || *fmt == 'X') base = 16; else if (*fmt == 'd' || *fmt == 'D') base = 10; else return 0; for (valid=0,result=0,pbuf=buf; ishexnum(*pbuf); pbuf++) { result *= base; if (isnum (*pbuf)) result += (unsigned long) (*pbuf - 0x30); else if (base == 16) result += (unsigned long) (toupper(*pbuf) - 0x37); else return 0; valid=1; } if (valid) *val = result; return valid; } #if 0 /**************************************************************** * memset() ****************************************************************/ void *memset(void *dest,int c,size_t count) { uint8_t *d = dest; for(;count>0;count--) { *d++ = c; } return dest; } #endif #if 0 /* using fast assembly version */ /**************************************************************** * memcpy() ****************************************************************/ void *memcpy(void *dest,const void *src,size_t count) { char *d,*s; int cnt; s = (char*)src; d = (char*)dest; cnt = count; while(cnt--) *d++ = *s++; return dest; } #endif int memcmp(const void *s1,const void *s2, size_t count) { const uint8_t *b1= s1; const uint8_t *b2= s2; for(;count>0;count--) { int diff = *b1-*b2; if (diff) { return diff; } ++b1;++b2; } return 0; } size_t strlen (const char * str) { const char *s = str; for(;*s;++s) { } return s-str; } char* strcpy ( char * dst,const char * src) { char *d1=dst; while('\0' != (*d1=*src) ) { d1++;src++; } return dst; } char *strncpy(char *dest, const char *src, size_t n) { char *d1=dest; while('\0' != (*d1=*src) ) { d1++;src++; if (d1 >= (dest + n)) { break; } } return dest; } int strcmp(const char *s1_, const char *s2_) { const uint8_t *s1 = s1_; const uint8_t *s2 = s2_; for(;;) { int ch1 = *s1++; int diff = ch1 - *s2++; if (diff || /* strings are different */ ch1 == 0 /* end of string reached */ ) { return diff; /* return difference */ } } } int strncmp(const char *s1, const char *s2, int n) { if (n == 0) return (0); do { if (*s1 != *s2++) return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); if (*s1++ == 0) break; } while (--n != 0); return (0); } #define _U 0x01 /* upper */ #define _L 0x02 /* lower */ #define _D 0x04 /* digit */ #define _C 0x08 /* cntrl */ #define _P 0x10 /* punct */ #define _S 0x20 /* white space (space/lf/tab) */ #define _X 0x40 /* hex digit */ #define _SP 0x80 /* hard space (0x20) */ const unsigned char _ctype[] = { _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ #define __ismask(x) (_ctype[(int)(unsigned char)(x)]) #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) #define iscntrl(c) ((__ismask(c)&(_C)) != 0) #define isdigit(c) ((__ismask(c)&(_D)) != 0) #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) #define islower(c) ((__ismask(c)&(_L)) != 0) #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) #define ispunct(c) ((__ismask(c)&(_P)) != 0) #define isspace(c) ((__ismask(c)&(_S)) != 0) #define isupper(c) ((__ismask(c)&(_U)) != 0) #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) #define isascii(c) (((unsigned char)(c))<=0x7f) #define toascii(c) (((unsigned char)(c))&0x7f) static inline unsigned char __tolower(unsigned char c) { if (isupper(c)) c -= 'A'-'a'; return c; } static inline unsigned char __toupper(unsigned char c) { if (islower(c)) c -= 'a'-'A'; return c; } #define tolower(c) __tolower(c) #ifdef toupper #undef toupper #endif #define toupper(c) __toupper(c) int strcasecmp(const char *s1_, const char *s2_) { const uint8_t *s1 = s1_; const uint8_t *s2 = s2_; for(;;) { int ch1 = tolower(*s1++); int diff = ch1 - tolower(*s2++); if (diff || /* strings are different */ ch1 == 0 /* end of string reached */ ) { return diff; /* return difference */ } } } char *getenv(const char *name) { return NULL; } int atoi(const char **s) { int i=0; while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #if 0 /** * simple_strtoul - convert a string to an unsigned long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ static unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) { unsigned long result = 0,value; if (!base) { base = 10; if (*cp == '0') { base = 8; cp++; if ((*cp == 'x') && isxdigit(cp[1])) { cp++; base = 16; } } } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { result = result*base + value; cp++; } if (endp) *endp = (char *)cp; return result; } /** * simple_strtol - convert a string to a signed long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ static long simple_strtol(const char *cp,char **endp,unsigned int base) { if(*cp=='-') return -simple_strtoul(cp+1,endp,base); return simple_strtoul(cp,endp,base); } /** * simple_strtoull - convert a string to an unsigned long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ static unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base) { unsigned long long result = 0,value; if (!base) { base = 10; if (*cp == '0') { base = 8; cp++; if ((*cp == 'x') && isxdigit(cp[1])) { cp++; base = 16; } } } while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) ? toupper(*cp) : *cp)-'A'+10) < base) { result = result*base + value; cp++; } if (endp) *endp = (char *)cp; return result; } /** * simple_strtoll - convert a string to a signed long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ static long long simple_strtoll(const char *cp,char **endp,unsigned int base) { if(*cp=='-') return -simple_strtoull(cp+1,endp,base); return simple_strtoull(cp,endp,base); } #endif static int skip_atoi(const char **s) { int i=0; while (isdigit(**s)) i = i*10 + *((*s)++) - '0'; return i; } #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ #define PLUS 4 /* show plus */ #define SPACE 8 /* space if plus */ #define LEFT 16 /* left justified */ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ /* * No traps on overflows for any of these... */ const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; int i; digits = (type & LARGE) ? large_digits : small_digits; if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) return 0; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { if (num < 0) { sign = '-'; num = -num; size--; } else if (type & PLUS) { sign = '+'; size--; } else if (type & SPACE) { sign = ' '; size--; } } if (type & SPECIAL) { if (base == 16) size -= 2; else if (base == 8) size--; } i = 0; if (num == 0) tmp[i++]='0'; else while (num != 0) tmp[i++] = digits[do_div(num,base)]; if (i > precision) precision = i; size -= precision; if (!(type&(ZEROPAD+LEFT))) { while(size-->0) { if (buf <= end) *buf = ' '; ++buf; } } if (sign) { if (buf <= end) *buf = sign; ++buf; } if (type & SPECIAL) { if (base==8) { if (buf <= end) *buf = '0'; ++buf; } else if (base==16) { if (buf <= end) *buf = '0'; ++buf; if (buf <= end) *buf = digits[33]; ++buf; } } if (!(type & LEFT)) { while (size-- > 0) { if (buf <= end) *buf = c; ++buf; } } while (i < precision--) { if (buf <= end) *buf = '0'; ++buf; } while (i-- > 0) { if (buf <= end) *buf = tmp[i]; ++buf; } while (size-- > 0) { if (buf <= end) *buf = ' '; ++buf; } return buf; } /** * vsnprintf - Format a string and place it in a buffer * @buf: The buffer to place the result into * @size: The size of the buffer, including the trailing null space * @fmt: The format string to use * @args: Arguments for the format string * * Call this function if you are already dealing with a va_list. * You probably want snprintf instead. */ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) { int len; unsigned long long num; int i, base; char *str, *end, c; const char *s; int flags; /* flags to number() */ int field_width; /* width of output field */ int precision; /* min. # of digits for integers; max number of chars for from string */ int qualifier; /* 'h', 'l', or 'L' for integer fields */ /* 'z' support added 23/7/1999 S.H. */ /* 'z' changed to 'Z' --davidm 1/25/99 */ str = buf; end = buf + size - 1; if (end < buf - 1) { end = ((void *) -1); size = end - buf + 1; } for (; *fmt ; ++fmt) { if (*fmt != '%') { if (str <= end) *str = *fmt; ++str; continue; } /* process flags */ flags = 0; repeat: ++fmt; /* this also skips first '%' */ switch (*fmt) { case '-': flags |= LEFT; goto repeat; case '+': flags |= PLUS; goto repeat; case ' ': flags |= SPACE; goto repeat; case '#': flags |= SPECIAL; goto repeat; case '0': flags |= ZEROPAD; goto repeat; } /* get field width */ field_width = -1; if (isdigit(*fmt)) field_width = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ field_width = va_arg(args, int); if (field_width < 0) { field_width = -field_width; flags |= LEFT; } } /* get the precision */ precision = -1; if (*fmt == '.') { ++fmt; if (isdigit(*fmt)) precision = skip_atoi(&fmt); else if (*fmt == '*') { ++fmt; /* it's the next argument */ precision = va_arg(args, int); } if (precision < 0) precision = 0; } /* get the conversion qualifier */ qualifier = -1; if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { qualifier = *fmt; ++fmt; if (qualifier == 'l' && *fmt == 'l') { qualifier = 'L'; ++fmt; } } /* default base */ base = 10; switch (*fmt) { case 'c': if (!(flags & LEFT)) { while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } } c = (unsigned char) va_arg(args, int); if (str <= end) *str = c; ++str; while (--field_width > 0) { if (str <= end) *str = ' '; ++str; } continue; case 's': s = va_arg(args, char *); if (!s) s = ""; len = strnlen(s, precision); len = strnlen(s, precision); if (!(flags & LEFT)) { while (len < field_width--) { if (str <= end) *str = ' '; ++str; } } for (i = 0; i < len; ++i) { if (str <= end) *str = *s; ++str; ++s; } while (len < field_width--) { if (str <= end) *str = ' '; ++str; } continue; case 'p': if (field_width == -1) { field_width = 2*sizeof(void *); flags |= ZEROPAD; } str = number(str, end, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); continue; case 'n': /* FIXME: * What does C99 say about the overflow case here? */ if (qualifier == 'l') { long * ip = va_arg(args, long *); *ip = (str - buf); } else if (qualifier == 'Z') { size_t * ip = va_arg(args, size_t *); *ip = (str - buf); } else { int * ip = va_arg(args, int *); *ip = (str - buf); } continue; case '%': if (str <= end) *str = '%'; ++str; continue; /* integer number formats - set up the flags and "break" */ case 'o': base = 8; break; case 'X': flags |= LARGE; case 'x': base = 16; break; case 'd': case 'i': flags |= SIGN; case 'u': break; default: if (str <= end) *str = '%'; ++str; if (*fmt) { if (str <= end) *str = *fmt; ++str; } else { --fmt; } continue; } if (qualifier == 'L') num = va_arg(args, long long); else if (qualifier == 'l') { num = va_arg(args, unsigned long); if (flags & SIGN) num = (signed long) num; } else if (qualifier == 'Z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { num = (unsigned short) va_arg(args, int); if (flags & SIGN) num = (signed short) num; } else { num = va_arg(args, unsigned int); if (flags & SIGN) num = (signed int) num; } str = number(str, end, num, base, field_width, precision, flags); } if (str <= end) *str = '\0'; else if (size > 0) /* don't write out a null byte if the buf size is zero */ *end = '\0'; /* the trailing null byte doesn't count towards the total * ++str; */ return str-buf; } int snprintf(char *str, size_t size, const char *format, ...) { va_list arg; int rv; va_start(arg, format); rv = vsnprintf(str, size, format, arg); va_end(arg); return rv; } #if 0 /* unused */ int strcmpn ( const char * first,const char * last,int count) { if (!count) return(0); while (--count && *first && *first == *last) { first++; last++; } return( *(unsigned char *)first - *(unsigned char *)last ); } /* unused */ int strcmpi(const char *dest,const char *src) { char dc,sc; while (*src && *dest) { dc = __toupper(*dest); sc = __toupper(*src); if (dc < sc) return -1; if (dc > sc) return 1; dest++; src++; } if (*dest && !*src) return 1; if (!*dest && *src) return -1; return 0; } #endif size_t strnlen(const char * s, size_t count) { const char *sc; for (sc = s; count-- && *sc != '\0'; ++sc) /* nothing */; return sc - s; } int perror(const char *str) { printf(str); printf("\n"); return 0; } /****************************************************************************** * INPUTS: none. * OUTPUTS: tv - structure containing the current seconds and microseconds. * RETURNS: non-zero on failure. * FUNCTION: Return the current seconds and microseconds. ******************************************************************************/ void gettimeofday(b_timeval *tv) { b_clock clock; long long usec_ticks; /* get running clock */ bos_getclock(&clock); if(clock.clock_freq>0) { usec_ticks = b_div64_32(&tv->tv_sec, clock.clock_hi, clock.clock_low, clock.clock_freq); usec_ticks *= (1000000/64); /* scale usec ticks */ b_div64_32(&tv->tv_usec, usec_ticks>>32, usec_ticks, (clock.clock_freq/64)); } else { tv->tv_usec = 0; tv->tv_sec = 0; } return; } #if !SUPPORT_DST_PLATFORM /* in dst platform, we need this function in DHL_OS_GetChar impl. so, make it public. */ static inline #endif int console_getch(void) { volatile UartChannel *uart; #if (BCHP_CHIP!=7550) && ( (BCHP_CHIP!=7552)) unsigned int event; if(s_console) { uart = s_console->uart; uart->rxstat |= RXINTEN; event = (unsigned int)bos_pend_event(s_console->rx.rx_queue,CONSOLE_TIMEOUT); } else { uart = CONSOLE_UART; } #else uart = CONSOLE_UART; #endif return serial_getc(uart, false); /* don't block */ } static int vprintf_poll(const char *format, va_list ap) { static char stdout_buf[128]; /* keep it small */ int rv; rv = vsnprintf(stdout_buf, sizeof(stdout_buf), format, ap); if (rv>0) { put_str(stdout_buf); } return rv; } int printf(const char *format, ...) { int rv = 0; va_list arg; va_start(arg, format); #if 1 rv = BKNI_Print_Vprintf(format, arg); #else #if (BCHP_CHIP!=7550) && (BCHP_CHIP!=7552) if (s_console) { rv = vprintf_console(s_console, format, arg); } else { rv = vprintf_poll(format, arg); } #else rv = vprintf_poll(format, arg); #endif #endif va_end(arg); return rv; } int vprintf(const char *format, va_list arg) { int rv = 0; rv = vprintf_poll(format, arg); return rv; } int getchar(void) { #ifdef CONFIG_GP int ch = -1; int last_ch = -1; #else char ch = 0; char last_ch = 0; #endif do { #ifdef CONFIG_GP if (ch != -1) #else if (ch != 0) #endif { last_ch = ch; printf("%c", ch); } ch = console_getch(); }while ((ch != '\n') && (ch != '\r')); return last_ch; } char *gets(char *s) { #ifdef CONFIG_GP int ch; #else char ch; #endif char *orig_s = s; do { ch = console_getch(); #ifdef CONFIG_GP if (ch != -1) #else if (ch != 0) #endif { /* Don't print backspace if we have reached beginning of string input */ if (ch == '\b') { if (s > orig_s) { printf("\b \b", ch); s--; } continue; } printf("%c", ch); if ((ch != '\n') && (ch != '\r')) { *s++ = ch; } }else{ bos_sleep(20); /* let other task run */ } } while ((ch != '\n') && (ch != '\r')); *s = 0; return orig_s; } char *ngets(char *s,int max_len) { #ifdef CONFIG_GP int ch; #else char ch; #endif char *orig_s = s; do { ch = console_getch(); #ifdef CONFIG_GP if (ch != -1) #else if (ch != 0) #endif { /* Don't print backspace if we have reached beginning of string input */ if (ch == '\b') { if (s > orig_s) { printf("\b \b", ch); s--; } continue; } printf("%c", ch); if ((ch != '\n') && (ch != '\r')) { *s++ = ch; } }else{ bos_sleep(20); /* let other task run */ } if ((unsigned int)s >= (unsigned int)(&orig_s[max_len + 1])) { break; } } while ((ch != '\n') && (ch != '\r')); *s = 0; return orig_s; } int fprintf(int* f, const char *format, ...) { int rv = 0; va_list arg; va_start(arg, format); #if (BCHP_CHIP!=7550) && (BCHP_CHIP!=7552) if (s_console) { rv = vprintf_console(s_console, format, arg); } else { rv = vprintf_poll(format, arg); } #else rv = vprintf_poll(format, arg); #endif va_end(arg); return rv; } #ifdef CONFIG_GP void GP_putchar(char ch) { put_c(ch); } int GP_getchar(void) { int v = console_getch(); while (v==-1) { bos_sleep(20); v = console_getch(); } return v; } #endif static unsigned int rand_table_idx = 0; static const unsigned short rand_table[] = { 840,394,783,798,911,197,335,768,277,553, 477,628,364,513,952,916,635,717,141,606, 16,242,137,804,156,400,129,108,998,218, 512,839,612,296,637,524,493,972,292,771, 526,769,400,891,283,352,807,919,69,949, 525,86,192,663,890,348,64,20,457,63, 238,970,902,850,266,539,375,760,512,667, 531,39,437,931,930,720,284,738,639,354, 687,165,440,880,829,330,228,893,350,686, 956,588,657,858,439,923,398,814,684,910, 482,215,950,920,147,881,641,431,619,281, 786,307,447,226,187,276,556,416,169,906, 103,126,495,760,984,935,684,383,749,368, 294,232,584,244,152,732,125,793,164,745, 74,950,52,521,176,240,797,732,656,967, 639,759,93,134,520,78,69,204,461,819, 573,755,51,157,999,204,889,125,997,54, 870,72,4,923,593,180,163,391,913,819, 359,552,579,452,687,99,530,757,304,992, 576,877,747,628,35,747,833,925,873,831, 979,743,903,983,666,497,163,830,888,76, 649,248,629,229,700,316,328,231,74,633, 223,651,510,971,280,546,719,113,471,592, 944,450,336,847,434,3,344,598,833,233, 675,482,481,304,712,182,621,40,413,695, 673,637,347,184,609,627,730,328,740,202, 920,684,653,257,532,87,260,877,686,93, 111,361,576,593,666,288,775,288,329,189, 984,3,827,331,188,436,958,918,764,699, 121,685,383,774,943,916,861,203,793,548, 297,904,909,873,498,576,162,273,864,492, 463,848,495,291,180,684,727,139,603,492, 838,724,178,221,498,121,138,360,324,931, 908,622,836,818,496,334,394,658,608,258, 151,72,107,647,363,288,331,91,427,934, 583,265,658,761,487,157,883,625,517,207, 557,426,829,394,244,326,729,638,984,338, 897,136,410,5,783,774,293,114,865,721, 49,449,986,707,210,473,865,93,99,382, 301,657,809,131,51,53,457,780,692,442, 119,589,578,529,595,361,304,888,476,169, 609,525,618,596,233,829,70,98,923,169, 481,225,826,290,357,878,344,814,659,36, 257,778,625,836,308,221,198,612,109,674, 782,719,200,401,315,434,230,385,532,154, 555,14,380,382,305,737,260,649,552,919, 685,809,697,311,645,6,532,843,618,642, 518,400,362,718,801,677,152,32,63,685, 187,618,700,567,1,5,305,261,655,857, 181,341,667,879,653,313,885,186,157,503, 828,675,904,191,394,706,868,547,738,932, 233,926,551,933,494,552,939,799,814,594, 657,995,935,324,874,589,637,759,775,794, 262,604,470,166,795,865,873,664,412,611, 596,645,538,148,579,32,700,518,832,515, 112,489,510,48,814,384,637,452,143,413, 247,406,17,717,573,812,582,446,477,995, 58,74,640,597,222,219,630,923,737,462, 438,850,952,948,899,767,333,536,219,477, 949,466,884,967,183,458,780,766,904,257, 761,963,331,402,560,554,622,191,477,360, 653,916,210,606,865,109,373,199,646,592, 676,596,58,560,563,242,18,343,9,923, 601,770,887,933,173,447,487,795,639,965, 155,292,882,366,899,747,475,272,946,122, 865,623,718,924,184,282,167,202,626,176, 126,227,946,13,160,119,461,648,915,100, 614,70,393,496,436,293,244,912,566,190, 34,431,813,753,356,997,35,523,200,661, 699,327,889,646,341,50,766,803,698,681, 904,312,752,297,809,189,591,53,101,157, 244,136,589,58,889,945,56,925,469,256, 587,168,584,476,815,926,526,582,729,225, 264,633,538,16,931,347,205,522,400,307, 679,645,443,269,703,332,214,759,258,683, 16,845,852,600,321,667,526,848,250,256, 73,514,889,611,531,821,958,736,343,359, 43,23,5,487,292,708,820,507,467,78, 190,483,923,43,84,244,711,611,92,961, 867,166,475,757,777,6,578,736,743,922, 96,787,946,101,274,239,809,95,746,277, 173,937,760,96,981,845,341,692,456,434, 654,323,600,129,81,377,136,659,114,880, 582,210,668,528,312,943,768,122,38,514, 399,211,452,160,308,433,5,649,126,461, 84,780,785,684,910,867,62,47,527,177, 927,109,387,596,638,700,539,406,822,577, 921,221,789,374,381,97,807,387,747,934, 849,831,714,635,516,624,502,578,671,29, 755,599,139,143,195,777,844,735,184,666, 312,105,888,102,479,270,199,287,657,947, 221,506,778,936,142,294,561,644,873,232, 673,629,832,812,773,28,590,617,763,774, 284,76,880,172,178,359,443,378,647,100, 325,869,607,104,805,749,398,366,394,272, 599,68,901,432,881,674,460,471,292,224, 246,576,301,126,749,480,485,192,858,133, 293,184,2,900,288,808,650,687,175,44, 959,775,112,861,207,994,536,667,465,828, 892,711,405,193,837,154,673,323,347,532, }; unsigned int rand(void) { unsigned int reg ; reg = rand_table[rand_table_idx++]; if (rand_table_idx == RAND_MAX) { rand_table_idx = 0; } return reg; } void srand(unsigned int seed) { rand_table_idx = seed % RAND_MAX; if (rand_table_idx == RAND_MAX) { rand_table_idx = 0; } } #endif /* __NEWLIB__ */ /* Summary: Calculate the UTC time offset from Jan 6th 1980. NOTE: This function only works for times after Jan 6th, 1980 */ #ifndef LINUX /* Jan 6, 1980 => Sunday */ #define START_DAY 0 #define START_YEAR 1980 #else /* Jan 1, 1970 => Thursday */ #define START_DAY 3 #endif /* Days/month for non-leap year */ const unsigned char s_days_per_mon[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; #define IS_LEAP_YEAR(y) ( !((y + START_YEAR) % 4) && ( ((y + START_YEAR) % 100) || !((y + START_YEAR) % 400) ) ) void utctime(unsigned int secs,b_tm *p_tm) { unsigned int yday,mon,t_val; unsigned char *p_dpm = (unsigned char*)s_days_per_mon; memset(p_tm,0,sizeof(b_tm)); /* seconds */ p_tm->tm_sec = secs % 60; t_val = secs / 60; /* minutes */ /* minutes */ p_tm->tm_min = t_val % 60; t_val /= 60; /* hours */ /* hours */ p_tm->tm_hour = t_val % 24; t_val /= 24; /* day of week */ p_tm->tm_wday = t_val % 7; p_tm->tm_wday = (t_val - START_DAY) % 7; /* offset value to start of the year */ #ifndef LINUX t_val += 5; #endif /* year */ p_tm->tm_yday = t_val; p_tm->tm_year = 0; /* day of current year */ while ((IS_LEAP_YEAR(p_tm->tm_year) && (p_tm->tm_yday > 365)) || (!IS_LEAP_YEAR(p_tm->tm_year) && (p_tm->tm_yday > 364))) { if (IS_LEAP_YEAR(p_tm->tm_year)) p_tm->tm_yday -= 366; else p_tm->tm_yday -= 365; p_tm->tm_year++; } if (IS_LEAP_YEAR(p_tm->tm_year)) p_dpm += 12; yday = p_tm->tm_yday + 1; mon = 0; while(yday > p_dpm[mon]) { yday -= p_dpm[mon]; mon++; } /* month */ p_tm->tm_mon = mon; /* day of month */ p_tm->tm_mday = yday; } /****************************************************************************** * INPUTS: size - number of bytes to allocate * alignbits - alignment in number of lsb bits. * file,line for debugging purposes * OUTPUTS: None. * RETURNS: the buffer allocated * FUNCTION: allocate memory from primary heap ******************************************************************************/ #ifdef BCM_DEBUG void *malloc_align_dbg(size_t size,char alignbits, char* file, int line) #else void *malloc_align(size_t size,char alignbits) #endif { char* p_ref; if (!g_p_sdram_heap) { unsigned int offset = (unsigned int)&_end; offset &= 0x0FFFFFFF; /*RLQ, don't printout here as BKNI_Print_Init is not complete yet as first one is called BKNI_CreateEvent */ //printf("%15s SDRAM_SIZE = %d\n\n",strrchr(__FILE__,'/')? strrchr(__FILE__,'/')+1 : __FILE__,SDRAM_SIZE/(1024 * 1024)); heap_init(&g_sdram_heap, (unsigned long *)&_end, SDRAM_SIZE - offset); g_p_sdram_heap = &g_sdram_heap; } /* Make sure size is a multiple of 4 bytes */ /* This insures that we never attempt to access one of the 32- */ /* bit signature values on anything other than a 4-byte aligned */ /* address. */ size = (size+3)&(~3); #ifdef BCM_DEBUG p_ref = mem_tagalloc(g_p_sdram_heap,size,alignbits,file,line); #else p_ref = mem_tagalloc(g_p_sdram_heap,size,alignbits, NULL, 0); #endif return p_ref; } /****************************************************************************** * INPUTS: size - number of bytes to allocate * file,line for debugging purposes * OUTPUTS: None. * RETURNS: the buffer allocated * FUNCTION: allocate memory from primary heap ******************************************************************************/ #include "bkni.h" #include "bkni_multi.h" static void malloc_lock(int bLock) { static BKNI_MutexHandle bMutex = NULL; static int nCount = 0; if (bLock) nCount++; if(nCount == 1000 && bMutex == NULL) { BKNI_CreateMutex(&bMutex); } if (bLock) { BKNI_AcquireMutex(bMutex); } else { BKNI_ReleaseMutex(bMutex); } } #ifdef BCM_DEBUG void *malloc_dbg(size_t size, char* file, int line) #else void *malloc(size_t size) #endif { malloc_lock(1); #ifdef BCM_DEBUG void *p = malloc_align_dbg(size,DEFAULT_ALIGN_BITS,file,line); #else void *p = malloc_align(size,DEFAULT_ALIGN_BITS); #endif malloc_lock(0); return p; } /****************************************************************************** * INPUTS: ptr - memory block to free * file, line - file and line where allocation is freed * OUTPUTS: None. * RETURNS: none. * FUNCTION: Free memory from primary heap ******************************************************************************/ #ifdef BCM_DEBUG void free_dbg(void *ptr, char* file, int line) #else void free(void *ptr) #endif { malloc_lock(1); #ifdef BCM_DEBUG mem_tagfree(g_p_sdram_heap,ptr,file,line); #else mem_tagfree(g_p_sdram_heap,ptr, NULL, 0); #endif malloc_lock(0); } #ifdef BCM_DEBUG /* libstdc++ seems to generate unavoidable calls to malloc,free and realloc */ #undef malloc #undef free void *malloc(size_t size) { return malloc_dbg(size,__FILE__,__LINE__); } void free(void *ptr) { free_dbg(ptr,__FILE__,__LINE__); } void *realloc(void *ptr,size_t size) { void *nptr; if (!ptr) return malloc(size); nptr = malloc(size); if (!nptr) return NULL; memcpy(nptr,ptr,size); free(ptr); return nptr; } #endif /****************************************************************************** * INPUTS: none * OUTPUTS: None. * RETURNS: none. * FUNCTION: Report memory heap info ******************************************************************************/ void m_report(void) { #ifdef BCM_DEBUG mem_reportbrief(g_p_sdram_heap); #else printf("Largest unused block = %d bytes\n",mem_available(g_p_sdram_heap)); #endif } void console_init(volatile void *uart) { /* setup FIFO control register */ CONSOLE_UART->sdw_iir_fcr = 7; /* reset XMIT and RCVR FIFO */ } void console_flush(void) { #ifdef CONFIG_GP while ((serial_getc(CONSOLE_UART, false) != -1)); #else while (serial_getc(CONSOLE_UART, false)); #endif } void console_shutdown(void) { #if (BCHP_CHIP==7550) /* disable interrupts if any */ CONSOLE_UART->sdw_dlh_ier = 0; #endif console_flush(); #if (BCHP_CHIP==7550) /* setup FIFO control register */ /* TODO to set FIFO buffer triggers */ CONSOLE_UART->sdw_iir_fcr = 0x6; CONSOLE_UART->sdw_iir_fcr = FIFOE; /* assume that other UART paramters, baud rate, stop bit, parity are set correctly */ #endif } #if SUPPORT_DST_PLATFORM char *strchr(const char *str, int c) { char *pstr = (char *)str; char temp; if(c == 0) { while(*pstr++); return pstr - 1; } while((temp = *pstr++)) { if(temp == c) { return pstr - 1; } } return 0; } int sprintf(char *str, const char *format, ...) { va_list arg; int rv; size_t size = 4096; // actually, sprintf do not limit size. use numbers big enough. va_start(arg, format); rv = vsnprintf(str, size, format, arg); va_end(arg); return rv; } char *strcat(char *dest, const char *src) { return strcpy(dest + strlen(dest), src); } char *strstr(const char *s, const char *s2) { char c, *p; int len; if (!s2 || !*s2) return (char *)s; // check this is correct. c = *s2; p = (char *)s; len = strlen(s2); while (*p) { if (*p == c) { // ok, fist char is matched. lets check full string. if (!strncmp(p, s2, len)) return p; } p++; } return NULL; // needle not found. } void *memmove(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); } /////BKTEMP typedef struct mem_io_t { char *name; bool open; uint8_t *data; unsigned int *size; unsigned int cnt; }mem_io_t; static mem_io_t g_files[] = { { "",false,0,0,0}, }; size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { mem_io_t *file = (mem_io_t*)stream; BDBG_ASSERT(file); size = size * nmemb; if (file->cnt + size > *(file->size)) { printf("Requesting more bytes than available (cnt = %d, size = %d,total = %d)\n", file->cnt,size,*(file->size)); size = *(file->size) - file->cnt; } memcpy(ptr,&(file->data[file->cnt]),size); file->cnt += size; return size; } size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { mem_io_t *file = (mem_io_t*)stream; BDBG_ASSERT(file); size = size * nmemb; if (file->cnt + size > *(file->size)) { printf("Attempt to write more bytes than available (cnt = %d, size = %d,total = %d)\n", file->cnt,size,*(file->size)); size = *(file->size) - file->cnt; } memcpy(&(file->data[file->cnt]),ptr,size); file->cnt += size; return size; } FILE *fopen(const char *path, const char *mode) { int idx = 0; while(g_files[idx].data != NULL) { if ((strcmp(path,g_files[idx].name) == 0) && !g_files[idx].open) { g_files[idx].open = true; g_files[idx].cnt = 0; return &(g_files[idx]); } idx++; } return NULL; } int fclose(FILE *stream) { mem_io_t *file = (mem_io_t*)stream; BDBG_ASSERT(file); file->open = false; return 0; } int fseek(FILE *stream, long offset, int whence) { mem_io_t *file = (mem_io_t*)stream; switch(whence) { default: case SEEK_SET: file->cnt = offset; break; case SEEK_CUR: file->cnt += offset; break; case SEEK_END: file->size += offset; break; } return file->cnt; } long ftell(FILE *stream) { mem_io_t *file = (mem_io_t*)stream; return (long) file->cnt; } int fflush(FILE *stream) { return 0; } #endif