Commit | Line | Data |
---|---|---|
4bd43f50 LR |
1 | /* |
2 | * Copyright (c) 2007-2008 Atheros Communications Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | /* Module Name : wwrap.c */ | |
17 | /* Abstract */ | |
18 | /* This module contains wrapper functions. */ | |
19 | /* */ | |
20 | /* NOTES */ | |
21 | /* Platform dependent. */ | |
22 | /* */ | |
23 | ||
24 | /* Please include your header files here */ | |
25 | #include "oal_dt.h" | |
26 | #include "usbdrv.h" | |
27 | ||
28 | #include <linux/netlink.h> | |
29 | ||
30 | #if WIRELESS_EXT > 12 | |
31 | #include <net/iw_handler.h> | |
32 | #endif | |
33 | ||
34 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
35 | #define URB_ZERO_PACKET USB_ZERO_PACKET | |
36 | #endif | |
37 | ||
38 | extern void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo); | |
39 | extern void zfCoreRecv(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo); | |
40 | extern void zfIdlChkRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen); | |
41 | extern void zfIdlRsp(zdev_t* dev, u32_t *rsp, u16_t rspLen); | |
42 | ||
43 | ||
44 | ||
45 | //extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; | |
46 | extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; | |
47 | ||
48 | u32_t zfLnxUsbSubmitTxData(zdev_t* dev); | |
49 | u32_t zfLnxUsbIn(zdev_t* dev, urb_t *urb, zbuf_t *buf); | |
50 | u32_t zfLnxSubmitRegInUrb(zdev_t *dev); | |
51 | u32_t zfLnxUsbSubmitBulkUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction, | |
52 | void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context); | |
53 | u32_t zfLnxUsbSubmitIntUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction, | |
54 | void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context, | |
55 | u32_t interval); | |
56 | ||
57 | u16_t zfLnxGetFreeTxUrb(zdev_t *dev) | |
58 | { | |
59 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
60 | u16_t idx; | |
61 | unsigned long irqFlag; | |
62 | ||
63 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
64 | ||
65 | //idx = ((macp->TxUrbTail + 1) & (ZM_MAX_TX_URB_NUM - 1)); | |
66 | ||
67 | //if (idx != macp->TxUrbHead) | |
68 | if (macp->TxUrbCnt != 0) | |
69 | { | |
70 | idx = macp->TxUrbTail; | |
71 | macp->TxUrbTail = ((macp->TxUrbTail + 1) & (ZM_MAX_TX_URB_NUM - 1)); | |
72 | macp->TxUrbCnt--; | |
73 | } | |
74 | else | |
75 | { | |
76 | //printk(KERN_ERR "macp->TxUrbCnt: %d\n", macp->TxUrbCnt); | |
77 | idx = 0xffff; | |
78 | } | |
79 | ||
80 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
81 | return idx; | |
82 | } | |
83 | ||
84 | void zfLnxPutTxUrb(zdev_t *dev) | |
85 | { | |
86 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
87 | u16_t idx; | |
88 | unsigned long irqFlag; | |
89 | ||
90 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
91 | ||
92 | idx = ((macp->TxUrbHead + 1) & (ZM_MAX_TX_URB_NUM - 1)); | |
93 | ||
94 | //if (idx != macp->TxUrbTail) | |
95 | if (macp->TxUrbCnt < ZM_MAX_TX_URB_NUM) | |
96 | { | |
97 | macp->TxUrbHead = idx; | |
98 | macp->TxUrbCnt++; | |
99 | } | |
100 | else | |
101 | { | |
102 | printk("UsbTxUrbQ inconsistent: TxUrbHead: %d, TxUrbTail: %d\n", | |
103 | macp->TxUrbHead, macp->TxUrbTail); | |
104 | } | |
105 | ||
106 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
107 | } | |
108 | ||
109 | u16_t zfLnxCheckTxBufferCnt(zdev_t *dev) | |
110 | { | |
111 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
112 | u16_t TxBufCnt; | |
113 | unsigned long irqFlag; | |
114 | ||
115 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
116 | ||
117 | TxBufCnt = macp->TxBufCnt; | |
118 | ||
119 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
120 | return TxBufCnt; | |
121 | } | |
122 | ||
123 | UsbTxQ_t *zfLnxGetUsbTxBuffer(zdev_t *dev) | |
124 | { | |
125 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
126 | u16_t idx; | |
127 | UsbTxQ_t *TxQ; | |
128 | unsigned long irqFlag; | |
129 | ||
130 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
131 | ||
132 | idx = ((macp->TxBufHead+1) & (ZM_MAX_TX_BUF_NUM - 1)); | |
133 | ||
134 | //if (idx != macp->TxBufTail) | |
135 | if (macp->TxBufCnt > 0) | |
136 | { | |
137 | //printk("CWY - zfwGetUsbTxBuffer ,macp->TxBufCnt = %d\n", macp->TxBufCnt); | |
138 | TxQ = (UsbTxQ_t *)&(macp->UsbTxBufQ[macp->TxBufHead]); | |
139 | macp->TxBufHead = ((macp->TxBufHead+1) & (ZM_MAX_TX_BUF_NUM - 1)); | |
140 | macp->TxBufCnt--; | |
141 | } | |
142 | else | |
143 | { | |
144 | if (macp->TxBufHead != macp->TxBufTail) | |
145 | { | |
146 | printk(KERN_ERR "zfwGetUsbTxBuf UsbTxBufQ inconsistent: TxBufHead: %d, TxBufTail: %d\n", | |
147 | macp->TxBufHead, macp->TxBufTail); | |
148 | } | |
149 | ||
150 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
151 | return NULL; | |
152 | } | |
153 | ||
154 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
155 | return TxQ; | |
156 | } | |
157 | ||
158 | u16_t zfLnxPutUsbTxBuffer(zdev_t *dev, u8_t *hdr, u16_t hdrlen, | |
159 | u8_t *snap, u16_t snapLen, u8_t *tail, u16_t tailLen, | |
160 | zbuf_t *buf, u16_t offset) | |
161 | { | |
162 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
163 | u16_t idx; | |
164 | UsbTxQ_t *TxQ; | |
165 | unsigned long irqFlag; | |
166 | ||
167 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
168 | ||
169 | idx = ((macp->TxBufTail+1) & (ZM_MAX_TX_BUF_NUM - 1)); | |
170 | ||
171 | /* For Tx debug */ | |
172 | //zm_assert(macp->TxBufCnt >= 0); // deleted because of always true | |
173 | ||
174 | //if (idx != macp->TxBufHead) | |
175 | if (macp->TxBufCnt < ZM_MAX_TX_BUF_NUM) | |
176 | { | |
177 | //printk("CWY - zfwPutUsbTxBuffer ,macp->TxBufCnt = %d\n", macp->TxBufCnt); | |
178 | TxQ = (UsbTxQ_t *)&(macp->UsbTxBufQ[macp->TxBufTail]); | |
179 | memcpy(TxQ->hdr, hdr, hdrlen); | |
180 | TxQ->hdrlen = hdrlen; | |
181 | memcpy(TxQ->snap, snap, snapLen); | |
182 | TxQ->snapLen = snapLen; | |
183 | memcpy(TxQ->tail, tail, tailLen); | |
184 | TxQ->tailLen = tailLen; | |
185 | TxQ->buf = buf; | |
186 | TxQ->offset = offset; | |
187 | ||
188 | macp->TxBufTail = ((macp->TxBufTail+1) & (ZM_MAX_TX_BUF_NUM - 1)); | |
189 | macp->TxBufCnt++; | |
190 | } | |
191 | else | |
192 | { | |
193 | printk(KERN_ERR "zfLnxPutUsbTxBuffer UsbTxBufQ inconsistent: TxBufHead: %d, TxBufTail: %d, TxBufCnt: %d\n", | |
194 | macp->TxBufHead, macp->TxBufTail, macp->TxBufCnt); | |
195 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
196 | return 0xffff; | |
197 | } | |
198 | ||
199 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
200 | return 0; | |
201 | } | |
202 | ||
203 | zbuf_t *zfLnxGetUsbRxBuffer(zdev_t *dev) | |
204 | { | |
205 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
206 | //u16_t idx; | |
207 | zbuf_t *buf; | |
208 | unsigned long irqFlag; | |
209 | ||
210 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
211 | ||
212 | //idx = ((macp->RxBufHead+1) & (ZM_MAX_RX_URB_NUM - 1)); | |
213 | ||
214 | //if (idx != macp->RxBufTail) | |
215 | if (macp->RxBufCnt != 0) | |
216 | { | |
217 | buf = macp->UsbRxBufQ[macp->RxBufHead]; | |
218 | macp->RxBufHead = ((macp->RxBufHead+1) & (ZM_MAX_RX_URB_NUM - 1)); | |
219 | macp->RxBufCnt--; | |
220 | } | |
221 | else | |
222 | { | |
223 | printk("RxBufQ inconsistent: RxBufHead: %d, RxBufTail: %d\n", | |
224 | macp->RxBufHead, macp->RxBufTail); | |
225 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
226 | return NULL; | |
227 | } | |
228 | ||
229 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
230 | return buf; | |
231 | } | |
232 | ||
233 | u32_t zfLnxPutUsbRxBuffer(zdev_t *dev, zbuf_t *buf) | |
234 | { | |
235 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
236 | u16_t idx; | |
237 | unsigned long irqFlag; | |
238 | ||
239 | spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
240 | ||
241 | idx = ((macp->RxBufTail+1) & (ZM_MAX_RX_URB_NUM - 1)); | |
242 | ||
243 | //if (idx != macp->RxBufHead) | |
244 | if (macp->RxBufCnt != ZM_MAX_RX_URB_NUM) | |
245 | { | |
246 | macp->UsbRxBufQ[macp->RxBufTail] = buf; | |
247 | macp->RxBufTail = idx; | |
248 | macp->RxBufCnt++; | |
249 | } | |
250 | else | |
251 | { | |
252 | printk("RxBufQ inconsistent: RxBufHead: %d, RxBufTail: %d\n", | |
253 | macp->RxBufHead, macp->RxBufTail); | |
254 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
255 | return 0xffff; | |
256 | } | |
257 | ||
258 | spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag); | |
259 | return 0; | |
260 | } | |
261 | ||
262 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
263 | void zfLnxUsbDataOut_callback(urb_t *urb) | |
264 | #else | |
265 | void zfLnxUsbDataOut_callback(urb_t *urb, struct pt_regs *regs) | |
266 | #endif | |
267 | { | |
268 | zdev_t* dev = urb->context; | |
269 | //UsbTxQ_t *TxData; | |
270 | ||
271 | /* Give the urb back */ | |
272 | zfLnxPutTxUrb(dev); | |
273 | ||
274 | /* Check whether there is any pending buffer needed */ | |
275 | /* to be sent */ | |
276 | if (zfLnxCheckTxBufferCnt(dev) != 0) | |
277 | { | |
278 | //TxData = zfwGetUsbTxBuffer(dev); | |
279 | ||
280 | //if (TxData == NULL) | |
281 | //{ | |
282 | // printk("Get a NULL buffer from zfwGetUsbTxBuffer\n"); | |
283 | // return; | |
284 | //} | |
285 | //else | |
286 | //{ | |
287 | zfLnxUsbSubmitTxData(dev); | |
288 | //} | |
289 | } | |
290 | } | |
291 | ||
292 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
293 | void zfLnxUsbDataIn_callback(urb_t *urb) | |
294 | #else | |
295 | void zfLnxUsbDataIn_callback(urb_t *urb, struct pt_regs *regs) | |
296 | #endif | |
297 | { | |
298 | zdev_t* dev = urb->context; | |
299 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
300 | zbuf_t *buf; | |
301 | zbuf_t *new_buf; | |
302 | int status; | |
303 | ||
304 | #if ZM_USB_STREAM_MODE == 1 | |
305 | static int remain_len = 0, check_pad = 0, check_len = 0; | |
306 | int index = 0; | |
307 | int chk_idx; | |
308 | u16_t pkt_len; | |
309 | u16_t pkt_tag; | |
310 | u16_t ii; | |
311 | zbuf_t *rxBufPool[8]; | |
312 | u16_t rxBufPoolIndex = 0; | |
313 | #endif | |
314 | ||
315 | /* Check status for URB */ | |
316 | if (urb->status != 0){ | |
317 | printk("zfLnxUsbDataIn_callback() : status=0x%x\n", urb->status); | |
318 | if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET) | |
319 | && (urb->status != -ESHUTDOWN)) | |
320 | { | |
321 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
322 | if (urb->status == USB_ST_INTERNALERROR) | |
323 | status = -1; | |
324 | #else | |
325 | if (urb->status == -EPIPE){ | |
326 | //printk(KERN_ERR "nonzero read bulk status received: -EPIPE"); | |
327 | status = -1; | |
328 | } | |
329 | ||
330 | if (urb->status == -EPROTO){ | |
331 | //printk(KERN_ERR "nonzero read bulk status received: -EPROTO"); | |
332 | status = -1; | |
333 | } | |
334 | #endif | |
335 | } | |
336 | ||
337 | //printk(KERN_ERR "urb->status: 0x%08x\n", urb->status); | |
338 | ||
339 | /* Dequeue skb buffer */ | |
340 | buf = zfLnxGetUsbRxBuffer(dev); | |
341 | dev_kfree_skb_any(buf); | |
342 | #if 0 | |
343 | /* Enqueue skb buffer */ | |
344 | zfLnxPutUsbRxBuffer(dev, buf); | |
345 | ||
346 | /* Submit a Rx urb */ | |
347 | zfLnxUsbIn(dev, urb, buf); | |
348 | #endif | |
349 | return; | |
350 | } | |
351 | ||
352 | if (urb->actual_length == 0) | |
353 | { | |
354 | printk(KERN_ERR "Get an URB whose length is zero"); | |
355 | status = -1; | |
356 | } | |
357 | ||
358 | /* Dequeue skb buffer */ | |
359 | buf = zfLnxGetUsbRxBuffer(dev); | |
360 | ||
361 | //zfwBufSetSize(dev, buf, urb->actual_length); | |
362 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | |
363 | buf->tail = 0; | |
364 | buf->len = 0; | |
365 | #else | |
366 | buf->tail = buf->data; | |
367 | buf->len = 0; | |
368 | #endif | |
369 | ||
370 | if ((buf->tail + urb->actual_length) > buf->end) | |
371 | BUG(); | |
372 | ||
373 | skb_put(buf, urb->actual_length); | |
374 | ||
375 | #if ZM_USB_STREAM_MODE == 1 | |
376 | if (remain_len != 0) | |
377 | { | |
378 | zbuf_t *remain_buf = macp->reamin_buf; | |
379 | ||
380 | index = remain_len; | |
381 | remain_len -= check_pad; | |
382 | ||
383 | /* Copy data */ | |
384 | memcpy(&(remain_buf->data[check_len]), buf->data, remain_len); | |
385 | check_len += remain_len; | |
386 | remain_len = 0; | |
387 | ||
388 | rxBufPool[rxBufPoolIndex++] = remain_buf; | |
389 | } | |
390 | ||
391 | while(index < urb->actual_length) | |
392 | { | |
393 | pkt_len = buf->data[index] + (buf->data[index+1] << 8); | |
394 | pkt_tag = buf->data[index+2] + (buf->data[index+3] << 8); | |
395 | ||
396 | if (pkt_tag == 0x4e00) | |
397 | { | |
398 | int pad_len; | |
399 | ||
400 | //printk("Get a packet, index: %d, pkt_len: 0x%04x\n", index, pkt_len); | |
401 | #if 0 | |
402 | /* Dump data */ | |
403 | for (ii = index; ii < pkt_len+4;) | |
404 | { | |
405 | printk("%02x ", (buf->data[ii] & 0xff)); | |
406 | ||
407 | if ((++ii % 16) == 0) | |
408 | printk("\n"); | |
409 | } | |
410 | ||
411 | printk("\n"); | |
412 | #endif | |
413 | ||
414 | pad_len = 4 - (pkt_len & 0x3); | |
415 | ||
416 | if(pad_len == 4) | |
417 | pad_len = 0; | |
418 | ||
419 | chk_idx = index; | |
420 | index = index + 4 + pkt_len + pad_len; | |
421 | ||
422 | if (index > ZM_MAX_RX_BUFFER_SIZE) | |
423 | { | |
424 | remain_len = index - ZM_MAX_RX_BUFFER_SIZE; // - pad_len; | |
425 | check_len = ZM_MAX_RX_BUFFER_SIZE - chk_idx - 4; | |
426 | check_pad = pad_len; | |
427 | ||
428 | /* Allocate a skb buffer */ | |
429 | //new_buf = zfwBufAllocate(dev, ZM_MAX_RX_BUFFER_SIZE); | |
430 | new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE); | |
431 | ||
432 | /* Set skb buffer length */ | |
433 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | |
434 | new_buf->tail = 0; | |
435 | new_buf->len = 0; | |
436 | #else | |
437 | new_buf->tail = new_buf->data; | |
438 | new_buf->len = 0; | |
439 | #endif | |
440 | ||
441 | skb_put(new_buf, pkt_len); | |
442 | ||
443 | /* Copy the buffer */ | |
444 | memcpy(new_buf->data, &(buf->data[chk_idx+4]), check_len); | |
445 | ||
446 | /* Record the buffer pointer */ | |
447 | macp->reamin_buf = new_buf; | |
448 | } | |
449 | else | |
450 | { | |
451 | #ifdef ZM_DONT_COPY_RX_BUFFER | |
452 | if (rxBufPoolIndex == 0) | |
453 | { | |
454 | new_buf = skb_clone(buf, GFP_ATOMIC); | |
455 | ||
456 | new_buf->data = &(buf->data[chk_idx+4]); | |
457 | new_buf->len = pkt_len; | |
458 | } | |
459 | else | |
460 | { | |
461 | #endif | |
462 | /* Allocate a skb buffer */ | |
463 | new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE); | |
464 | ||
465 | /* Set skb buffer length */ | |
466 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | |
467 | new_buf->tail = 0; | |
468 | new_buf->len = 0; | |
469 | #else | |
470 | new_buf->tail = new_buf->data; | |
471 | new_buf->len = 0; | |
472 | #endif | |
473 | ||
474 | skb_put(new_buf, pkt_len); | |
475 | ||
476 | /* Copy the buffer */ | |
477 | memcpy(new_buf->data, &(buf->data[chk_idx+4]), pkt_len); | |
478 | ||
479 | #ifdef ZM_DONT_COPY_RX_BUFFER | |
480 | } | |
481 | #endif | |
482 | rxBufPool[rxBufPoolIndex++] = new_buf; | |
483 | } | |
484 | } | |
485 | else | |
486 | { | |
487 | printk(KERN_ERR "Can't find tag, pkt_len: 0x%04x, tag: 0x%04x\n", pkt_len, pkt_tag); | |
488 | ||
489 | /* Free buffer */ | |
490 | dev_kfree_skb_any(buf); | |
491 | ||
492 | /* Allocate a skb buffer */ | |
493 | new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE); | |
494 | ||
495 | /* Enqueue skb buffer */ | |
496 | zfLnxPutUsbRxBuffer(dev, new_buf); | |
497 | ||
498 | /* Submit a Rx urb */ | |
499 | zfLnxUsbIn(dev, urb, new_buf); | |
500 | ||
501 | return; | |
502 | } | |
503 | } | |
504 | ||
505 | /* Free buffer */ | |
506 | dev_kfree_skb_any(buf); | |
507 | #endif | |
508 | ||
509 | /* Allocate a skb buffer */ | |
510 | new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE); | |
511 | ||
512 | /* Enqueue skb buffer */ | |
513 | zfLnxPutUsbRxBuffer(dev, new_buf); | |
514 | ||
515 | /* Submit a Rx urb */ | |
516 | zfLnxUsbIn(dev, urb, new_buf); | |
517 | ||
518 | #if ZM_USB_STREAM_MODE == 1 | |
519 | for(ii = 0; ii < rxBufPoolIndex; ii++) | |
520 | { | |
521 | macp->usbCbFunctions.zfcbUsbRecv(dev, rxBufPool[ii]); | |
522 | } | |
523 | #else | |
524 | /* pass data to upper layer */ | |
525 | macp->usbCbFunctions.zfcbUsbRecv(dev, buf); | |
526 | #endif | |
527 | } | |
528 | ||
529 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
530 | void zfLnxUsbRegOut_callback(urb_t *urb) | |
531 | #else | |
532 | void zfLnxUsbRegOut_callback(urb_t *urb, struct pt_regs *regs) | |
533 | #endif | |
534 | { | |
535 | //dev_t* dev = urb->context; | |
536 | ||
537 | //printk(KERN_ERR "zfwUsbRegOut_callback\n"); | |
538 | } | |
539 | ||
540 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
541 | void zfLnxUsbRegIn_callback(urb_t *urb) | |
542 | #else | |
543 | void zfLnxUsbRegIn_callback(urb_t *urb, struct pt_regs *regs) | |
544 | #endif | |
545 | { | |
546 | zdev_t* dev = urb->context; | |
547 | u32_t rsp[64/4]; | |
548 | int status; | |
549 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
550 | ||
551 | /* Check status for URB */ | |
552 | if (urb->status != 0){ | |
553 | printk("zfLnxUsbRegIn_callback() : status=0x%x\n", urb->status); | |
554 | if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET) | |
555 | && (urb->status != -ESHUTDOWN)) | |
556 | { | |
557 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) | |
558 | if (urb->status == USB_ST_INTERNALERROR) | |
559 | status = -1; | |
560 | #else | |
561 | if (urb->status == -EPIPE){ | |
562 | //printk(KERN_ERR "nonzero read bulk status received: -EPIPE"); | |
563 | status = -1; | |
564 | } | |
565 | ||
566 | if (urb->status == -EPROTO){ | |
567 | //printk(KERN_ERR "nonzero read bulk status received: -EPROTO"); | |
568 | status = -1; | |
569 | } | |
570 | #endif | |
571 | } | |
572 | ||
573 | //printk(KERN_ERR "urb->status: 0x%08x\n", urb->status); | |
574 | return; | |
575 | } | |
576 | ||
577 | if (urb->actual_length == 0) | |
578 | { | |
579 | printk(KERN_ERR "Get an URB whose length is zero"); | |
580 | status = -1; | |
581 | } | |
582 | ||
583 | /* Copy data into respone buffer */ | |
584 | memcpy(rsp, macp->regUsbReadBuf, urb->actual_length); | |
585 | ||
586 | /* Notify to upper layer */ | |
587 | //zfIdlChkRsp(dev, rsp, (u16_t)urb->actual_length); | |
588 | //zfiUsbRegIn(dev, rsp, (u16_t)urb->actual_length); | |
589 | macp->usbCbFunctions.zfcbUsbRegIn(dev, rsp, (u16_t)urb->actual_length); | |
590 | ||
591 | /* Issue another USB IN URB */ | |
592 | zfLnxSubmitRegInUrb(dev); | |
593 | } | |
594 | ||
595 | u32_t zfLnxSubmitRegInUrb(zdev_t *dev) | |
596 | { | |
597 | u32_t ret; | |
598 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
599 | ||
600 | /* Submit a rx urb */ | |
601 | //ret = zfLnxUsbSubmitBulkUrb(macp->RegInUrb, macp->udev, | |
602 | // USB_REG_IN_PIPE, USB_DIR_IN, macp->regUsbReadBuf, | |
603 | // ZM_USB_REG_MAX_BUF_SIZE, zfLnxUsbRegIn_callback, dev); | |
604 | //CWYang(-) | |
605 | //if (ret != 0) | |
606 | // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret); | |
607 | ||
608 | ret = zfLnxUsbSubmitIntUrb(macp->RegInUrb, macp->udev, | |
609 | USB_REG_IN_PIPE, USB_DIR_IN, macp->regUsbReadBuf, | |
610 | ZM_USB_REG_MAX_BUF_SIZE, zfLnxUsbRegIn_callback, dev, 1); | |
611 | ||
612 | return ret; | |
613 | } | |
614 | ||
615 | u32_t zfLnxUsbSubmitTxData(zdev_t* dev) | |
616 | { | |
617 | u32_t i; | |
618 | u32_t ret; | |
619 | u16_t freeTxUrb; | |
620 | u8_t *puTxBuf = NULL; | |
621 | UsbTxQ_t *TxData; | |
622 | int len = 0; | |
623 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
624 | #if ZM_USB_TX_STREAM_MODE == 1 | |
625 | u8_t ii; | |
626 | u16_t offset = 0; | |
627 | u16_t usbTxAggCnt; | |
628 | u16_t *pUsbTxHdr; | |
629 | UsbTxQ_t *TxQPool[ZM_MAX_TX_AGGREGATE_NUM]; | |
630 | #endif | |
631 | ||
632 | /* First check whether there is a free URB */ | |
633 | freeTxUrb = zfLnxGetFreeTxUrb(dev); | |
634 | ||
635 | /* If there is no any free Tx Urb */ | |
636 | if (freeTxUrb == 0xffff) | |
637 | { | |
638 | //printk(KERN_ERR "Can't get free Tx Urb\n"); | |
639 | //printk("CWY - Can't get free Tx Urb\n"); | |
640 | return 0xffff; | |
641 | } | |
642 | ||
643 | #if ZM_USB_TX_STREAM_MODE == 1 | |
644 | usbTxAggCnt = zfLnxCheckTxBufferCnt(dev); | |
645 | ||
646 | if (usbTxAggCnt >= ZM_MAX_TX_AGGREGATE_NUM) | |
647 | { | |
648 | usbTxAggCnt = ZM_MAX_TX_AGGREGATE_NUM; | |
649 | } | |
650 | else | |
651 | { | |
652 | usbTxAggCnt = 1; | |
653 | } | |
654 | ||
655 | //printk("usbTxAggCnt: %d\n", usbTxAggCnt); | |
656 | #endif | |
657 | ||
658 | #if ZM_USB_TX_STREAM_MODE == 1 | |
659 | for(ii = 0; ii < usbTxAggCnt; ii++) | |
660 | { | |
661 | #endif | |
662 | /* Dequeue the packet from UsbTxBufQ */ | |
663 | TxData = zfLnxGetUsbTxBuffer(dev); | |
664 | if (TxData == NULL) | |
665 | { | |
666 | /* Give the urb back */ | |
667 | zfLnxPutTxUrb(dev); | |
668 | return 0xffff; | |
669 | } | |
670 | ||
671 | /* Point to the freeTxUrb buffer */ | |
672 | puTxBuf = macp->txUsbBuf[freeTxUrb]; | |
673 | ||
674 | #if ZM_USB_TX_STREAM_MODE == 1 | |
675 | puTxBuf += offset; | |
676 | pUsbTxHdr = (u16_t *)puTxBuf; | |
677 | ||
678 | /* Add the packet length and tag information */ | |
679 | *pUsbTxHdr++ = TxData->hdrlen + TxData->snapLen + | |
680 | (TxData->buf->len - TxData->offset) + TxData->tailLen; | |
681 | ||
682 | *pUsbTxHdr++ = 0x697e; | |
683 | ||
684 | puTxBuf += 4; | |
685 | #endif // #ifdef ZM_USB_TX_STREAM_MODE | |
686 | ||
687 | /* Copy WLAN header and packet buffer into USB buffer */ | |
688 | for(i = 0; i < TxData->hdrlen; i++) | |
689 | { | |
690 | *puTxBuf++ = TxData->hdr[i]; | |
691 | } | |
692 | ||
693 | /* Copy SNAP header */ | |
694 | for(i = 0; i < TxData->snapLen; i++) | |
695 | { | |
696 | *puTxBuf++ = TxData->snap[i]; | |
697 | } | |
698 | ||
699 | /* Copy packet buffer */ | |
700 | for(i = 0; i < TxData->buf->len - TxData->offset; i++) | |
701 | { | |
702 | //*puTxBuf++ = zmw_rx_buf_readb(dev, TxData->buf, i); | |
703 | *puTxBuf++ = *(u8_t*)((u8_t*)TxData->buf->data+i+TxData->offset); | |
704 | } | |
705 | ||
706 | /* Copy tail */ | |
707 | for(i = 0; i < TxData->tailLen; i++) | |
708 | { | |
709 | *puTxBuf++ = TxData->tail[i]; | |
710 | } | |
711 | ||
712 | len = TxData->hdrlen+TxData->snapLen+TxData->buf->len+TxData->tailLen-TxData->offset; | |
713 | ||
714 | #if 0 | |
715 | if (TxData->hdrlen != 0) | |
716 | { | |
717 | puTxBuf = macp->txUsbBuf[freeTxUrb]; | |
718 | for (i = 0; i < len; i++) | |
719 | { | |
720 | printk("%02x ", puTxBuf[i]); | |
721 | if (i % 16 == 15) | |
722 | printk("\n"); | |
723 | } | |
724 | printk("\n"); | |
725 | } | |
726 | #endif | |
727 | #if 0 | |
728 | /* For debug purpose */ | |
729 | if(TxData->hdr[9] & 0x40) | |
730 | { | |
731 | int i; | |
732 | u16_t ctrlLen = TxData->hdr[0] + (TxData->hdr[1] << 8); | |
733 | ||
734 | if (ctrlLen != len + 4) | |
735 | { | |
736 | /* Dump control setting */ | |
737 | for(i = 0; i < 8; i++) | |
738 | { | |
739 | printk(KERN_ERR "0x%02x ", TxData->hdr[i]); | |
740 | } | |
741 | printk(KERN_ERR "\n"); | |
742 | ||
743 | printk(KERN_ERR "ctrLen: %d, hdrLen: %d, snapLen: %d\n", ctrlLen, TxData->hdrlen, TxData->snapLen); | |
744 | printk(KERN_ERR "bufLen: %d, tailLen: %d, len: %d\n", TxData->buf->len, TxData->tailLen, len); | |
745 | } | |
746 | } | |
747 | #endif | |
748 | ||
749 | #if ZM_USB_TX_STREAM_MODE == 1 | |
750 | // Add the Length and Tag | |
751 | len += 4; | |
752 | ||
753 | //printk("%d packet, length: %d\n", ii+1, len); | |
754 | ||
755 | if (ii < (ZM_MAX_TX_AGGREGATE_NUM-1)) | |
756 | { | |
757 | /* Pad the buffer to firmware descriptor boundary */ | |
758 | offset += (((len-1) / 4) + 1) * 4; | |
759 | } | |
760 | ||
761 | if (ii == (ZM_MAX_TX_AGGREGATE_NUM-1)) | |
762 | { | |
763 | len += offset; | |
764 | } | |
765 | ||
766 | TxQPool[ii] = TxData; | |
767 | ||
768 | //DbgPrint("%d packet, offset: %d\n", ii+1, pUsbTxTransfer->offset); | |
769 | ||
770 | /* free packet */ | |
771 | //zfBufFree(dev, txData->buf); | |
772 | } | |
773 | #endif | |
774 | //printk("CWY - call zfwUsbSubmitBulkUrb(), len = 0x%d\n", len); | |
775 | /* Submit a tx urb */ | |
776 | ret = zfLnxUsbSubmitBulkUrb(macp->WlanTxDataUrb[freeTxUrb], macp->udev, | |
777 | USB_WLAN_TX_PIPE, USB_DIR_OUT, macp->txUsbBuf[freeTxUrb], | |
778 | len, zfLnxUsbDataOut_callback, dev); | |
779 | //CWYang(-) | |
780 | //if (ret != 0) | |
781 | // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret); | |
782 | ||
783 | /* free packet */ | |
784 | //dev_kfree_skb_any(TxData->buf); | |
785 | #if ZM_USB_TX_STREAM_MODE == 1 | |
786 | for(ii = 0; ii < usbTxAggCnt; ii++) | |
787 | macp->usbCbFunctions.zfcbUsbOutComplete(dev, TxQPool[ii]->buf, 1, TxQPool[ii]->hdr); | |
788 | #else | |
789 | macp->usbCbFunctions.zfcbUsbOutComplete(dev, TxData->buf, 1, TxData->hdr); | |
790 | #endif | |
791 | ||
792 | return ret; | |
793 | } | |
794 | ||
795 | ||
796 | ||
797 | u32_t zfLnxUsbIn(zdev_t* dev, urb_t *urb, zbuf_t *buf) | |
798 | { | |
799 | u32_t ret; | |
800 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
801 | ||
802 | /* Submit a rx urb */ | |
803 | ret = zfLnxUsbSubmitBulkUrb(urb, macp->udev, USB_WLAN_RX_PIPE, | |
804 | USB_DIR_IN, buf->data, ZM_MAX_RX_BUFFER_SIZE, | |
805 | zfLnxUsbDataIn_callback, dev); | |
806 | //CWYang(-) | |
807 | //if (ret != 0) | |
808 | // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret); | |
809 | ||
810 | return ret; | |
811 | } | |
812 | ||
813 | u32_t zfLnxUsbWriteReg(zdev_t* dev, u32_t* cmd, u16_t cmdLen) | |
814 | { | |
815 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
816 | u32_t ret; | |
817 | ||
818 | #ifdef ZM_CONFIG_BIG_ENDIAN | |
819 | int ii = 0; | |
820 | ||
821 | for(ii=0; ii<(cmdLen>>2); ii++) | |
822 | cmd[ii] = cpu_to_le32(cmd[ii]); | |
823 | #endif | |
824 | ||
825 | memcpy(macp->regUsbWriteBuf, cmd, cmdLen); | |
826 | ||
827 | /* Issue an USB Out transfer */ | |
828 | /* Submit a tx urb */ | |
829 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) | |
830 | ret = zfLnxUsbSubmitBulkUrb(macp->RegOutUrb, macp->udev, | |
831 | USB_REG_OUT_PIPE, USB_DIR_OUT, macp->regUsbWriteBuf, | |
832 | cmdLen, zfLnxUsbRegOut_callback, dev); | |
833 | #else | |
834 | ret = zfLnxUsbSubmitIntUrb(macp->RegOutUrb, macp->udev, | |
835 | USB_REG_OUT_PIPE, USB_DIR_OUT, macp->regUsbWriteBuf, | |
836 | cmdLen, zfLnxUsbRegOut_callback, dev, 1); | |
837 | #endif | |
838 | ||
839 | return ret; | |
840 | } | |
841 | ||
842 | ||
843 | u32_t zfLnxUsbOut(zdev_t* dev, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen, | |
844 | u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset) | |
845 | { | |
846 | u32_t ret; | |
847 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
848 | ||
849 | /* Check length of tail buffer */ | |
850 | //zm_assert((tailLen <= 16)); | |
851 | ||
852 | /* Enqueue the packet into UsbTxBufQ */ | |
853 | if (zfLnxPutUsbTxBuffer(dev, hdr, hdrlen, snap, snapLen, tail, tailLen, buf, offset) == 0xffff) | |
854 | { | |
855 | /* free packet */ | |
856 | //printk("CWY - zfwPutUsbTxBuffer Error, free packet\n"); | |
857 | //dev_kfree_skb_any(buf); | |
858 | macp->usbCbFunctions.zfcbUsbOutComplete(dev, buf, 0, hdr); | |
859 | return 0xffff; | |
860 | } | |
861 | ||
862 | //return 0; | |
863 | //printk("CWY - call zfwUsbSubmitTxData()\n"); | |
864 | ret = zfLnxUsbSubmitTxData(dev); | |
865 | return ret; | |
866 | } | |
867 | ||
868 | void zfLnxInitUsbTxQ(zdev_t* dev) | |
869 | { | |
870 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
871 | ||
872 | printk(KERN_ERR "zfwInitUsbTxQ\n"); | |
873 | ||
874 | /* Zero memory for UsbTxBufQ */ | |
875 | memset(macp->UsbTxBufQ, 0, sizeof(UsbTxQ_t) * ZM_MAX_TX_URB_NUM); | |
876 | ||
877 | macp->TxBufHead = 0; | |
878 | macp->TxBufTail = 0; | |
879 | macp->TxUrbHead = 0; | |
880 | macp->TxUrbTail = 0; | |
881 | macp->TxUrbCnt = ZM_MAX_TX_URB_NUM; | |
882 | } | |
883 | ||
884 | void zfLnxInitUsbRxQ(zdev_t* dev) | |
885 | { | |
886 | u16_t i; | |
887 | zbuf_t *buf; | |
888 | struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv; | |
889 | ||
890 | /* Zero memory for UsbRxBufQ */ | |
891 | memset(macp->UsbRxBufQ, 0, sizeof(zbuf_t *) * ZM_MAX_RX_URB_NUM); | |
892 | ||
893 | macp->RxBufHead = 0; | |
894 | ||
895 | for (i = 0; i < ZM_MAX_RX_URB_NUM; i++) | |
896 | { | |
897 | //buf = zfwBufAllocate(dev, ZM_MAX_RX_BUFFER_SIZE); | |
898 | buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE); | |
899 | macp->UsbRxBufQ[i] = buf; | |
900 | } | |
901 | ||
902 | //macp->RxBufTail = ZM_MAX_RX_URB_NUM - 1; | |
903 | macp->RxBufTail = 0; | |
904 | ||
905 | /* Submit all Rx urbs */ | |
906 | for (i = 0; i < ZM_MAX_RX_URB_NUM; i++) | |
907 | { | |
908 | zfLnxPutUsbRxBuffer(dev, macp->UsbRxBufQ[i]); | |
909 | zfLnxUsbIn(dev, macp->WlanRxDataUrb[i], macp->UsbRxBufQ[i]); | |
910 | } | |
911 | } | |
912 | ||
913 | ||
914 | ||
915 | u32_t zfLnxUsbSubmitBulkUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction, | |
916 | void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context) | |
917 | { | |
918 | u32_t ret; | |
919 | ||
920 | if(direction == USB_DIR_OUT) | |
921 | { | |
922 | usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, epnum), | |
923 | transfer_buffer, buffer_length, complete, context); | |
924 | ||
925 | urb->transfer_flags |= URB_ZERO_PACKET; | |
926 | } | |
927 | else | |
928 | { | |
929 | usb_fill_bulk_urb(urb, usb, usb_rcvbulkpipe(usb, epnum), | |
930 | transfer_buffer, buffer_length, complete, context); | |
931 | } | |
932 | ||
933 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) | |
934 | urb->transfer_flags |= URB_ASYNC_UNLINK; | |
935 | #endif | |
936 | ||
937 | if (epnum == 4) | |
938 | { | |
939 | if (urb->hcpriv) | |
940 | { | |
941 | //printk("CWY - urb->hcpriv set by unknown reason, reset it\n"); | |
942 | //urb->hcpriv = 0; | |
943 | } | |
944 | } | |
945 | ||
946 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | |
947 | ret = usb_submit_urb(urb, GFP_ATOMIC); | |
948 | #else | |
949 | ret = usb_submit_urb(urb); | |
950 | #endif | |
951 | if ((epnum == 4) & (ret != 0)) | |
952 | { | |
953 | //printk("CWY - ret = %x\n", ret); | |
954 | } | |
955 | return ret; | |
956 | } | |
957 | ||
958 | u32_t zfLnxUsbSubmitIntUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction, | |
959 | void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context, | |
960 | u32_t interval) | |
961 | { | |
962 | u32_t ret; | |
963 | ||
964 | if(direction == USB_DIR_OUT) | |
965 | { | |
966 | usb_fill_int_urb(urb, usb, usb_sndbulkpipe(usb, epnum), | |
967 | transfer_buffer, buffer_length, complete, context, interval); | |
968 | } | |
969 | else | |
970 | { | |
971 | usb_fill_int_urb(urb, usb, usb_rcvbulkpipe(usb, epnum), | |
972 | transfer_buffer, buffer_length, complete, context, interval); | |
973 | } | |
974 | ||
975 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) | |
976 | urb->transfer_flags |= URB_ASYNC_UNLINK; | |
977 | #endif | |
978 | ||
979 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) | |
980 | ret = usb_submit_urb(urb, GFP_ATOMIC); | |
981 | #else | |
982 | ret = usb_submit_urb(urb); | |
983 | #endif | |
984 | ||
985 | return ret; | |
986 | } | |
987 | ||
988 | #ifdef ZM_ENABLE_CENC | |
989 | int zfLnxCencSendMsg(struct sock *netlink_sk, u_int8_t *msg, int len) | |
990 | { | |
991 | #define COMMTYPE_GROUP 8 | |
992 | #define WAI_K_MSG 0x11 | |
993 | ||
994 | int ret = -1; | |
995 | int size; | |
996 | unsigned char *old_tail; | |
997 | struct sk_buff *skb; | |
998 | struct nlmsghdr *nlh; | |
999 | char *pos = NULL; | |
1000 | ||
1001 | size = NLMSG_SPACE(len); | |
1002 | skb = alloc_skb(size, GFP_ATOMIC); | |
1003 | ||
1004 | if(skb == NULL) | |
1005 | { | |
1006 | printk("dev_alloc_skb failure \n"); | |
1007 | goto out; | |
1008 | } | |
1009 | old_tail = skb->tail; | |
1010 | ||
1011 |