convert brcm-2.4 to the new target structure
[openwrt/svn-archive/archive.git] / target / linux / brcm-2.4 / files / arch / mips / bcm947xx / bcmutils.c
1 /*
2 * Misc useful OS-independent routines.
3 *
4 * Copyright 2006, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $
12 */
13
14 #include <typedefs.h>
15 #include <bcmdefs.h>
16 #include <stdarg.h>
17 #include <bcmutils.h>
18 #include <osl.h>
19 #include <sbutils.h>
20 #include <bcmnvram.h>
21 #include <bcmendian.h>
22 #include <bcmdevs.h>
23
24 unsigned char bcm_ctype[] = {
25 _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */
26 _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
27 _BCM_C, /* 8-15 */
28 _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */
29 _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */
30 _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */
31 _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */
32 _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */
33 _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */
34 _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
35 _BCM_U|_BCM_X, _BCM_U, /* 64-71 */
36 _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */
37 _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */
38 _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */
39 _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
40 _BCM_L|_BCM_X, _BCM_L, /* 96-103 */
41 _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
42 _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
43 _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
44 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */
46 _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
47 _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */
48 _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
49 _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */
50 _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
51 _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */
52 _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
53 _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */
54 _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
55 _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */
56 _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
57 _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
58 };
59
60
61 ulong
62 bcm_strtoul(char *cp, char **endp, uint base)
63 {
64 ulong result, value;
65 bool minus;
66
67 minus = FALSE;
68
69 while (bcm_isspace(*cp))
70 cp++;
71
72 if (cp[0] == '+')
73 cp++;
74 else if (cp[0] == '-') {
75 minus = TRUE;
76 cp++;
77 }
78
79 if (base == 0) {
80 if (cp[0] == '0') {
81 if ((cp[1] == 'x') || (cp[1] == 'X')) {
82 base = 16;
83 cp = &cp[2];
84 } else {
85 base = 8;
86 cp = &cp[1];
87 }
88 } else
89 base = 10;
90 } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
91 cp = &cp[2];
92 }
93
94 result = 0;
95
96 while (bcm_isxdigit(*cp) &&
97 (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
98 result = result*base + value;
99 cp++;
100 }
101
102 if (minus)
103 result = (ulong)(result * -1);
104
105 if (endp)
106 *endp = (char *)cp;
107
108 return (result);
109 }
110
111 uchar
112 bcm_toupper(uchar c)
113 {
114 if (bcm_islower(c))
115 c -= 'a'-'A';
116 return (c);
117 }
118
119 char*
120 bcm_ether_ntoa(struct ether_addr *ea, char *buf)
121 {
122 sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
123 ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff,
124 ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff);
125 return (buf);
126 }
127
128
129 /*
130 * Search the name=value vars for a specific one and return its value.
131 * Returns NULL if not found.
132 */
133 char*
134 getvar(char *vars, char *name)
135 {
136 char *s;
137 int len;
138
139 len = strlen(name);
140
141 /* first look in vars[] */
142 for (s = vars; s && *s;) {
143 /* CSTYLED */
144 if ((memcmp(s, name, len) == 0) && (s[len] == '='))
145 return (&s[len+1]);
146
147 while (*s++)
148 ;
149 }
150
151 /* then query nvram */
152 return (nvram_get(name));
153 }
154
155 /*
156 * Search the vars for a specific one and return its value as
157 * an integer. Returns 0 if not found.
158 */
159 int
160 getintvar(char *vars, char *name)
161 {
162 char *val;
163
164 if ((val = getvar(vars, name)) == NULL)
165 return (0);
166
167 return (bcm_strtoul(val, NULL, 0));
168 }
169
170
171 /*******************************************************************************
172 * crc8
173 *
174 * Computes a crc8 over the input data using the polynomial:
175 *
176 * x^8 + x^7 +x^6 + x^4 + x^2 + 1
177 *
178 * The caller provides the initial value (either CRC8_INIT_VALUE
179 * or the previous returned value) to allow for processing of
180 * discontiguous blocks of data. When generating the CRC the
181 * caller is responsible for complementing the final return value
182 * and inserting it into the byte stream. When checking, a final
183 * return value of CRC8_GOOD_VALUE indicates a valid CRC.
184 *
185 * Reference: Dallas Semiconductor Application Note 27
186 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
187 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
188 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
189 *
190 * ****************************************************************************
191 */
192
193 static uint8 crc8_table[256] = {
194 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
195 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
196 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
197 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
198 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
199 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
200 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
201 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
202 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
203 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
204 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
205 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
206 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
207 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
208 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
209 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
210 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
211 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
212 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
213 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
214 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
215 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
216 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
217 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
218 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
219 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
220 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
221 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
222 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
223 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
224 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
225 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
226 };
227
228 #define CRC_INNER_LOOP(n, c, x) \
229 (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
230
231 uint8
232 hndcrc8(
233 uint8 *pdata, /* pointer to array of data to process */
234 uint nbytes, /* number of input data bytes to process */
235 uint8 crc /* either CRC8_INIT_VALUE or previous return value */
236 )
237 {
238 /* hard code the crc loop instead of using CRC_INNER_LOOP macro
239 * to avoid the undefined and unnecessary (uint8 >> 8) operation.
240 */
241 while (nbytes-- > 0)
242 crc = crc8_table[(crc ^ *pdata++) & 0xff];
243
244 return crc;
245 }
246
247