finally move buildroot-ng to trunk
[openwrt/staging/yousong.git] / package / broadcom-wl / src / kmod / linux_osl.c
1 /*
2 * Linux OS Independent Layer
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 *
12 * $Id: linux_osl.c,v 1.1.1.14 2006/04/08 06:13:39 honor Exp $
13 */
14
15 #define LINUX_OSL
16
17 #include <typedefs.h>
18 #include <bcmendian.h>
19 #include <linux/module.h>
20 #include <linuxver.h>
21 #include <bcmdefs.h>
22 #include <osl.h>
23 #include "linux_osl.h"
24 #include <bcmutils.h>
25 #include <linux/delay.h>
26 #ifdef mips
27 #include <asm/paccess.h>
28 #endif /* mips */
29 #include <pcicfg.h>
30
31 #define PCI_CFG_RETRY 10
32
33 #define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */
34 #define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
35
36 typedef struct bcm_mem_link {
37 struct bcm_mem_link *prev;
38 struct bcm_mem_link *next;
39 uint size;
40 int line;
41 char file[BCM_MEM_FILENAME_LEN];
42 } bcm_mem_link_t;
43
44 static int16 linuxbcmerrormap[] = \
45 { 0, /* 0 */
46 -EINVAL, /* BCME_ERROR */
47 -EINVAL, /* BCME_BADARG */
48 -EINVAL, /* BCME_BADOPTION */
49 -EINVAL, /* BCME_NOTUP */
50 -EINVAL, /* BCME_NOTDOWN */
51 -EINVAL, /* BCME_NOTAP */
52 -EINVAL, /* BCME_NOTSTA */
53 -EINVAL, /* BCME_BADKEYIDX */
54 -EINVAL, /* BCME_RADIOOFF */
55 -EINVAL, /* BCME_NOTBANDLOCKED */
56 -EINVAL, /* BCME_NOCLK */
57 -EINVAL, /* BCME_BADRATESET */
58 -EINVAL, /* BCME_BADBAND */
59 -E2BIG, /* BCME_BUFTOOSHORT */
60 -E2BIG, /* BCME_BUFTOOLONG */
61 -EBUSY, /* BCME_BUSY */
62 -EINVAL, /* BCME_NOTASSOCIATED */
63 -EINVAL, /* BCME_BADSSIDLEN */
64 -EINVAL, /* BCME_OUTOFRANGECHAN */
65 -EINVAL, /* BCME_BADCHAN */
66 -EFAULT, /* BCME_BADADDR */
67 -ENOMEM, /* BCME_NORESOURCE */
68 -EOPNOTSUPP, /* BCME_UNSUPPORTED */
69 -EMSGSIZE, /* BCME_BADLENGTH */
70 -EINVAL, /* BCME_NOTREADY */
71 -EPERM, /* BCME_NOTPERMITTED */
72 -ENOMEM, /* BCME_NOMEM */
73 -EINVAL, /* BCME_ASSOCIATED */
74 -ERANGE, /* BCME_RANGE */
75 -EINVAL, /* BCME_NOTFOUND */
76 -EINVAL, /* BCME_WME_NOT_ENABLED */
77 -EINVAL, /* BCME_TSPEC_NOTFOUND */
78 -EINVAL, /* BCME_ACM_NOTSUPPORTED */
79 -EINVAL, /* BCME_NOT_WME_ASSOCIATION */
80 -EIO, /* BCME_SDIO_ERROR */
81 -ENODEV /* BCME_DONGLE_DOWN */
82 };
83
84 /* translate bcmerrors into linux errors */
85 int
86 osl_error(int bcmerror)
87 {
88 int abs_bcmerror;
89 int array_size = ARRAYSIZE(linuxbcmerrormap);
90
91 abs_bcmerror = ABS(bcmerror);
92
93 if (bcmerror > 0)
94 abs_bcmerror = 0;
95
96 else if (abs_bcmerror >= array_size)
97 abs_bcmerror = BCME_ERROR;
98
99 return linuxbcmerrormap[abs_bcmerror];
100 }
101
102 osl_t *
103 osl_attach(void *pdev, bool pkttag)
104 {
105 osl_t *osh;
106
107 osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
108 ASSERT(osh);
109
110 bzero(osh, sizeof(osl_t));
111
112 /*
113 * check the cases where
114 * 1.Error code Added to bcmerror table, but forgot to add it to the OS
115 * dependent error code
116 * 2. Error code is added to the bcmerror table, but forgot to add the
117 * corresponding errorstring(dummy call to bcmerrorstr)
118 */
119 bcmerrorstr(0);
120 ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));
121
122 osh->magic = OS_HANDLE_MAGIC;
123 osh->malloced = 0;
124 osh->failed = 0;
125 osh->dbgmem_list = NULL;
126 osh->pdev = pdev;
127 osh->pub.pkttag = pkttag;
128
129 return osh;
130 }
131
132 void
133 osl_detach(osl_t *osh)
134 {
135 if (osh == NULL)
136 return;
137
138 ASSERT(osh->magic == OS_HANDLE_MAGIC);
139 kfree(osh);
140 }
141
142 /* Return a new packet. zero out pkttag */
143 void*
144 osl_pktget(osl_t *osh, uint len, bool send)
145 {
146 struct sk_buff *skb;
147
148 if ((skb = dev_alloc_skb(len))) {
149 skb_put(skb, len);
150 skb->priority = 0;
151
152 #ifdef BCMDBG_PKT
153 pktlist_add(&(osh->pktlist), (void *) skb);
154 #endif /* BCMDBG_PKT */
155
156 osh->pub.pktalloced++;
157 }
158
159 return ((void*) skb);
160 }
161
162 /* Free the driver packet. Free the tag if present */
163 void
164 osl_pktfree(osl_t *osh, void *p)
165 {
166 struct sk_buff *skb, *nskb;
167
168 skb = (struct sk_buff*) p;
169
170 /* perversion: we use skb->next to chain multi-skb packets */
171 while (skb) {
172 nskb = skb->next;
173 skb->next = NULL;
174
175 #ifdef BCMDBG_PKT
176 pktlist_remove(&(osh->pktlist), (void *) skb);
177 #endif /* BCMDBG_PKT */
178
179 if (skb->destructor) {
180 /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists
181 */
182 dev_kfree_skb_any(skb);
183 } else {
184 /* can free immediately (even in_irq()) if destructor does not exist */
185 dev_kfree_skb(skb);
186 }
187
188 osh->pub.pktalloced--;
189
190 skb = nskb;
191 }
192 }
193
194 void*
195 osl_malloc(osl_t *osh, uint size)
196 {
197 void *addr;
198
199 /* only ASSERT if osh is defined */
200 if (osh)
201 ASSERT(osh->magic == OS_HANDLE_MAGIC);
202
203 if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) {
204 if (osh)
205 osh->failed++;
206 return (NULL);
207 }
208 if (osh)
209 osh->malloced += size;
210
211 return (addr);
212 }
213
214 void
215 osl_mfree(osl_t *osh, void *addr, uint size)
216 {
217 if (osh) {
218 ASSERT(osh->magic == OS_HANDLE_MAGIC);
219 osh->malloced -= size;
220 }
221 kfree(addr);
222 }
223
224 uint
225 osl_malloced(osl_t *osh)
226 {
227 ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
228 return (osh->malloced);
229 }
230
231 uint osl_malloc_failed(osl_t *osh)
232 {
233 ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
234 return (osh->failed);
235 }
236
237 #undef osl_delay
238 void
239 osl_delay(uint usec)
240 {
241 OSL_DELAY(usec);
242 }
243
244 /* Clone a packet.
245 * The pkttag contents are NOT cloned.
246 */
247 void *
248 osl_pktdup(osl_t *osh, void *skb)
249 {
250 void * p;
251
252 if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL)
253 return NULL;
254
255 /* skb_clone copies skb->cb.. we don't want that */
256 if (osh->pub.pkttag)
257 bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ);
258
259 /* Increment the packet counter */
260 osh->pub.pktalloced++;
261 return (p);
262 }
263
264 uint
265 osl_pktalloced(osl_t *osh)
266 {
267 return (osh->pub.pktalloced);
268 }
269