OSDN Git Service

Add rtl8723bu driver version 4.4.5
[android-x86/external-kernel-drivers.git] / rtl8723bu / hal / hal_hci / hal_usb.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _HAL_USB_C_
21
22 #include <drv_types.h>
23 #include <hal_data.h>
24
25 int     usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
26 {
27         struct recv_priv        *precvpriv = &padapter->recvpriv;
28         int     i, res = _SUCCESS;
29         struct recv_buf *precvbuf;
30
31 #ifdef CONFIG_RECV_THREAD_MODE
32         _rtw_init_sema(&precvpriv->recv_sema, 0);//will be removed
33         _rtw_init_sema(&precvpriv->terminate_recvthread_sema, 0);//will be removed
34 #endif /* CONFIG_RECV_THREAD_MODE */
35
36 #ifdef PLATFORM_LINUX
37         tasklet_init(&precvpriv->recv_tasklet,
38                 (void(*)(unsigned long))usb_recv_tasklet,
39                 (unsigned long)padapter);
40 #endif /* PLATFORM_LINUX */
41
42 #ifdef PLATFORM_FREEBSD
43         #ifdef CONFIG_RX_INDICATE_QUEUE
44         TASK_INIT(&precvpriv->rx_indicate_tasklet, 0, rtw_rx_indicate_tasklet, padapter);
45         #endif /* CONFIG_RX_INDICATE_QUEUE */
46 #endif /* PLATFORM_FREEBSD */
47
48 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
49 #ifdef PLATFORM_LINUX
50         precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
51         if(precvpriv->int_in_urb == NULL){
52                 res = _FAIL;
53                 DBG_8192C("alloc_urb for interrupt in endpoint fail !!!!\n");
54                 goto exit;
55         }
56 #endif /* PLATFORM_LINUX */
57         precvpriv->int_in_buf = rtw_zmalloc(ini_in_buf_sz);
58         if(precvpriv->int_in_buf == NULL){
59                 res = _FAIL;
60                 DBG_8192C("alloc_mem for interrupt in endpoint fail !!!!\n");
61                 goto exit;
62         }
63 #endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
64
65         /* init recv_buf */
66         _rtw_init_queue(&precvpriv->free_recv_buf_queue);
67         _rtw_init_queue(&precvpriv->recv_buf_pending_queue);
68         #ifndef CONFIG_USE_USB_BUFFER_ALLOC_RX
69         /* this is used only when RX_IOBUF is sk_buff */
70         skb_queue_head_init(&precvpriv->free_recv_skb_queue);
71         #endif
72
73         DBG_871X("NR_RECVBUFF: %d\n", NR_RECVBUFF);
74         DBG_871X("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ);
75         precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF *sizeof(struct recv_buf) + 4);
76         if(precvpriv->pallocated_recv_buf==NULL){
77                 res= _FAIL;
78                 RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("alloc recv_buf fail!\n"));
79                 goto exit;
80         }
81
82         precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
83
84         precvbuf = (struct recv_buf*)precvpriv->precv_buf;
85
86         for(i=0; i < NR_RECVBUFF ; i++)
87         {
88                 _rtw_init_listhead(&precvbuf->list);
89
90                 _rtw_spinlock_init(&precvbuf->recvbuf_lock);
91
92                 precvbuf->alloc_sz = MAX_RECVBUF_SZ;
93
94                 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
95                 if(res==_FAIL)
96                         break;
97
98                 precvbuf->ref_cnt = 0;
99                 precvbuf->adapter =padapter;
100
101                 //rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue));
102
103                 precvbuf++;
104         }
105
106         precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
107
108 #if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
109
110         skb_queue_head_init(&precvpriv->rx_skb_queue);
111
112 #ifdef CONFIG_RX_INDICATE_QUEUE
113         memset(&precvpriv->rx_indicate_queue, 0, sizeof(struct ifqueue));
114         mtx_init(&precvpriv->rx_indicate_queue.ifq_mtx, "rx_indicate_queue", NULL, MTX_DEF);
115 #endif /* CONFIG_RX_INDICATE_QUEUE */
116
117 #ifdef CONFIG_PREALLOC_RECV_SKB
118         {
119                 int i;
120                 SIZE_PTR tmpaddr=0;
121                 SIZE_PTR alignment=0;
122                 struct sk_buff *pskb=NULL;
123
124                 DBG_871X("NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB);
125 #ifdef CONFIG_FIX_NR_BULKIN_BUFFER
126                 DBG_871X("Enable CONFIG_FIX_NR_BULKIN_BUFFER\n");
127 #endif
128
129                 for(i=0; i<NR_PREALLOC_RECV_SKB; i++)
130                 {
131 #ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
132                         pskb = rtw_alloc_skb_premem(MAX_RECVBUF_SZ);
133 #else
134                         pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
135 #endif //CONFIG_PREALLOC_RX_SKB_BUFFER
136
137                         if(pskb)
138                         {
139                                 #ifdef PLATFORM_FREEBSD
140                                 pskb->dev = padapter->pifp;
141                                 #else
142                                 pskb->dev = padapter->pnetdev;
143                                 #endif //PLATFORM_FREEBSD
144
145 #ifndef CONFIG_PREALLOC_RX_SKB_BUFFER
146                                 tmpaddr = (SIZE_PTR)pskb->data;
147                                 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
148                                 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
149 #endif
150                                 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
151                         }
152                 }
153         }
154 #endif /* CONFIG_PREALLOC_RECV_SKB */
155
156 #endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) */
157
158 exit:
159
160         return res;
161 }
162
163 void usb_free_recv_priv (_adapter *padapter, u16 ini_in_buf_sz)
164 {
165         int i;
166         struct recv_buf *precvbuf;
167         struct recv_priv        *precvpriv = &padapter->recvpriv;
168
169         precvbuf = (struct recv_buf *)precvpriv->precv_buf;
170
171         for(i=0; i < NR_RECVBUFF ; i++)
172         {
173                 rtw_os_recvbuf_resource_free(padapter, precvbuf);
174                 precvbuf++;
175         }
176
177         if(precvpriv->pallocated_recv_buf)
178                 rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF *sizeof(struct recv_buf) + 4);
179
180 #ifdef CONFIG_USB_INTERRUPT_IN_PIPE
181 #ifdef PLATFORM_LINUX
182         if(precvpriv->int_in_urb)
183         {
184                 usb_free_urb(precvpriv->int_in_urb);
185         }
186 #endif
187         if(precvpriv->int_in_buf)
188                 rtw_mfree(precvpriv->int_in_buf, ini_in_buf_sz);
189 #endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
190
191 #ifdef PLATFORM_LINUX
192
193         if (skb_queue_len(&precvpriv->rx_skb_queue)) {
194                 DBG_8192C(KERN_WARNING "rx_skb_queue not empty\n");
195         }
196
197         rtw_skb_queue_purge(&precvpriv->rx_skb_queue);
198
199         if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
200                 DBG_8192C(KERN_WARNING "free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
201         }
202
203 #if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
204         #if defined(CONFIG_PREALLOC_RECV_SKB) && defined(CONFIG_PREALLOC_RX_SKB_BUFFER)
205         {
206                 struct sk_buff *skb;
207
208                 while ((skb = skb_dequeue(&precvpriv->free_recv_skb_queue)) != NULL)
209                 {
210                         if (rtw_free_skb_premem(skb) != 0)
211                                 rtw_skb_free(skb);
212                 }
213         }
214         #else
215         rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
216         #endif /* defined(CONFIG_PREALLOC_RX_SKB_BUFFER) && defined(CONFIG_PREALLOC_RECV_SKB) */
217 #endif /* !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX) */
218
219 #endif /* PLATFORM_LINUX */
220
221 #ifdef PLATFORM_FREEBSD
222         struct sk_buff  *pskb;
223         while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue)))
224         {
225                 rtw_skb_free(pskb);
226         }
227
228         #if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
229         rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
230         #endif
231
232 #ifdef CONFIG_RX_INDICATE_QUEUE
233         struct mbuf *m;
234         for (;;) {
235                 IF_DEQUEUE(&precvpriv->rx_indicate_queue, m);
236                 if (m == NULL)
237                         break;
238                 m_freem(m);
239         }
240         mtx_destroy(&precvpriv->rx_indicate_queue.ifq_mtx);
241 #endif /* CONFIG_RX_INDICATE_QUEUE */
242
243 #endif /* PLATFORM_FREEBSD */
244 }
245
246 #ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
247 int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
248 {
249         u8 request;
250         u8 requesttype;
251         u16 wvalue;
252         u16 index;
253         int ret;
254
255         requesttype = VENDOR_WRITE;//write_out
256         request = REALTEK_USB_VENQT_CMD_REQ;
257         index = REALTEK_USB_VENQT_CMD_IDX;//n/a
258
259         wvalue = (u16)(addr&0x0000ffff);
260
261         ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
262
263         return ret;
264 }
265
266 int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
267 {
268         u8 data;
269         int ret;
270         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
271         struct usb_device *udev=pdvobjpriv->pusbdev;
272
273         _func_enter_;
274         data = val;
275         ret = usb_write_async(udev, addr, &data, 1);
276         _func_exit_;
277
278         return ret;
279 }
280
281 int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
282 {
283         u16 data;
284         int ret;
285         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
286         struct usb_device *udev=pdvobjpriv->pusbdev;
287
288         _func_enter_;
289         data = val;
290         ret = usb_write_async(udev, addr, &data, 2);
291         _func_exit_;
292
293         return ret;
294 }
295
296 int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
297 {
298         u32 data;
299         int ret;
300         struct dvobj_priv  *pdvobjpriv = (struct dvobj_priv  *)pintfhdl->pintf_dev;
301         struct usb_device *udev=pdvobjpriv->pusbdev;
302
303         _func_enter_;
304         data = val;
305         ret = usb_write_async(udev, addr, &data, 4);
306         _func_exit_;
307
308         return ret;
309 }
310 #endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
311
312 u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
313 {
314         u8 request;
315         u8 requesttype;
316         u16 wvalue;
317         u16 index;
318         u16 len;
319         u8 data=0;
320
321         _func_enter_;
322
323         request = 0x05;
324         requesttype = 0x01;//read_in
325         index = 0;//n/a
326
327         wvalue = (u16)(addr&0x0000ffff);
328         len = 1;
329         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
330                                         &data, len, requesttype);
331
332         _func_exit_;
333
334         return data;
335 }
336
337 u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
338 {
339         u8 request;
340         u8 requesttype;
341         u16 wvalue;
342         u16 index;
343         u16 len;
344         u16 data=0;
345
346         _func_enter_;
347
348         request = 0x05;
349         requesttype = 0x01;//read_in
350         index = 0;//n/a
351
352         wvalue = (u16)(addr&0x0000ffff);
353         len = 2;
354         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
355                                         &data, len, requesttype);
356
357         _func_exit_;
358
359         return data;
360
361 }
362
363 u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
364 {
365         u8 request;
366         u8 requesttype;
367         u16 wvalue;
368         u16 index;
369         u16 len;
370         u32 data=0;
371
372         _func_enter_;
373
374         request = 0x05;
375         requesttype = 0x01;//read_in
376         index = 0;//n/a
377
378         wvalue = (u16)(addr&0x0000ffff);
379         len = 4;
380         usbctrl_vendorreq(pintfhdl, request, wvalue, index,
381                                                 &data, len, requesttype);
382
383         _func_exit_;
384
385         return data;
386 }
387
388 int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
389 {
390         u8 request;
391         u8 requesttype;
392         u16 wvalue;
393         u16 index;
394         u16 len;
395         u8 data;
396         int ret;
397
398         _func_enter_;
399
400         request = 0x05;
401         requesttype = 0x00;//write_out
402         index = 0;//n/a
403
404         wvalue = (u16)(addr&0x0000ffff);
405         len = 1;
406
407         data = val;
408         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
409                                                 &data, len, requesttype);
410
411         _func_exit_;
412
413         return ret;
414 }
415
416 int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
417 {
418         u8 request;
419         u8 requesttype;
420         u16 wvalue;
421         u16 index;
422         u16 len;
423         u16 data;
424         int ret;
425
426         _func_enter_;
427
428         request = 0x05;
429         requesttype = 0x00;//write_out
430         index = 0;//n/a
431
432         wvalue = (u16)(addr&0x0000ffff);
433         len = 2;
434
435         data = val;
436         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
437                                                 &data, len, requesttype);
438
439         _func_exit_;
440
441         return ret;
442
443 }
444
445 int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
446 {
447         u8 request;
448         u8 requesttype;
449         u16 wvalue;
450         u16 index;
451         u16 len;
452         u32 data;
453         int ret;
454
455         _func_enter_;
456
457         request = 0x05;
458         requesttype = 0x00;//write_out
459         index = 0;//n/a
460
461         wvalue = (u16)(addr&0x0000ffff);
462         len = 4;
463         data =val;
464         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
465                                                 &data, len, requesttype);
466
467         _func_exit_;
468
469         return ret;
470
471 }
472
473 int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
474 {
475         u8 request;
476         u8 requesttype;
477         u16 wvalue;
478         u16 index;
479         u16 len;
480         u8 buf[VENDOR_CMD_MAX_DATA_LEN]={0};
481         int ret;
482
483         _func_enter_;
484
485         request = 0x05;
486         requesttype = 0x00;//write_out
487         index = 0;//n/a
488
489         wvalue = (u16)(addr&0x0000ffff);
490         len = length;
491          _rtw_memcpy(buf, pdata, len );
492         ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
493                                                 buf, len, requesttype);
494
495         _func_exit_;
496
497         return ret;
498
499 }