OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / system / wlan / ti / sta_dk_4_0_4_32 / pform / linux / src / ioctl_list.c
1 /****************************************************************************
2 **+-----------------------------------------------------------------------+**
3 **|                                                                       |**
4 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved.      |**
5 **| All rights reserved.                                                  |**
6 **|                                                                       |**
7 **| Redistribution and use in source and binary forms, with or without    |**
8 **| modification, are permitted provided that the following conditions    |**
9 **| are met:                                                              |**
10 **|                                                                       |**
11 **|  * Redistributions of source code must retain the above copyright     |**
12 **|    notice, this list of conditions and the following disclaimer.      |**
13 **|  * Redistributions in binary form must reproduce the above copyright  |**
14 **|    notice, this list of conditions and the following disclaimer in    |**
15 **|    the documentation and/or other materials provided with the         |**
16 **|    distribution.                                                      |**
17 **|  * Neither the name Texas Instruments nor the names of its            |**
18 **|    contributors may be used to endorse or promote products derived    |**
19 **|    from this software without specific prior written permission.      |**
20 **|                                                                       |**
21 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |**
22 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |**
23 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
24 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |**
25 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
26 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |**
27 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
28 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
29 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |**
30 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
31 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |**
32 **|                                                                       |**
33 **+-----------------------------------------------------------------------+**
34 ****************************************************************************/
35
36
37 #include "arch_ti.h"
38
39 #include <asm/uaccess.h>        /* copy_to_user() */
40 #include <linux/netdevice.h>
41 #include <linux/ioctl.h>
42 #include <linux/completion.h>
43 #include <linux/vmalloc.h>
44
45 #include "esta_drv.h"
46 #include "tiwlan_profile.h"
47 #include "ioctl_init.h"
48 #include "ioctl_utils.h"
49 #include "tiioctl.h"
50 #include "ipc_k.h"
51
52
53 void print_priv_ioctl_params(struct net_device *dev, tiioctl_req_t *req, char *extra)
54 {
55         print_deb(" priv_ioctl_params(*dev:%p,*req:%p, *extra:%p)\n", dev, req, extra);
56         print_deb("   wrqu.point: user_data=%p, length=%ld, cmd=%ld\n", (void *) req->user_data_pointer,
57                   req->length, req->cmd );
58         print_deb("   wrqu dump: ");
59         print_memory_dump((char *) req, sizeof(*req) );
60         print_deb("\n");
61
62         if( extra )
63         {
64                 print_deb("   extra (%p) :", extra );
65                 print_memory_dump(extra, req->length );
66                 print_deb("\n");
67         }
68 }
69
70 /*sends complete to the user after to signal the completion of the asynchronous */
71 /*operation (need to set *pIoCompleteFlag = FALSE, at osCmd.c).*/
72
73 void os_IoctlComplete(PTIWLN_ADAPTER_T pAdapter, TI_STATUS ReturnStatus )
74 {
75         *pAdapter->pCompleteReply = (int)ReturnStatus;
76     complete(pAdapter->IoctlComp);
77 }
78
79
80 NTSTATUS DispatchCommand(PTIWLN_ADAPTER_T pAdapter,ULONG ioControlCode,PULONG outBufLen,
81                     ULONG inBufLen,PVOID ioBuffer,PUINT8 pIoCompleteFlag);
82
83 int ti1610_ioctl_priv_proc_tl(tiwlan_req_t *req_data)
84 {
85     struct net_device *dev = req_data->drv->netdev;
86     tiioctl_req_t *req = (tiioctl_req_t *) req_data->u.req.p1;
87     static unsigned int drv_started = 0;
88         static UINT8 IoCompleteFlag ;
89
90     ULONG *data = (ULONG *) req_data->u.req.p2;
91
92     int res = -EINVAL;
93
94     print_deb("priv_ioctl_proc(): cmd=%ld, data=%p (user_data=%lx), lenght=%ld\n",
95                 req->cmd, data, req->user_data_pointer, req->length);
96     if( !drv_started && (req->cmd != TIWLN_DRIVER_STATUS_SET)) { /* Dm: Fix */
97             return res;
98     }
99                                         
100     switch( req->cmd ) {
101         case TIWLN_DRIVER_STATUS_SET:
102             if(*data)
103                 res = tiwlan_start_drv( (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev) );
104             else
105                 res = tiwlan_stop_drv( (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev) );
106
107             if( res == OK )
108                     drv_started = !drv_started;
109             break;
110
111         case TIWLN_SEND_EAPOL_PACKET:
112             res = os_sendPacket(dev, data, req->length);
113             break;
114 #ifdef TI_DBG
115         case TIWLN_DRIVER_DEBUG_PRINT:
116                 res = util_hal_debug_print(dev, data);
117                 break;
118 #endif /* TI_DBG */
119         default:
120                 {
121             res = DispatchCommand(&req_data->drv->adapter, req->cmd, &req->length, req->length, data,&IoCompleteFlag );
122                         /* If we do not have to send complete to user back then set the Falg to FALSE 
123                         The Complete will be sent from another contect of command completion from FW */
124                         if(IoCompleteFlag == FALSE)
125                         {
126                            req_data->u.req.reply_expected = FALSE;
127                            /****** TO DO - This solution will have a problem in case of two async ioctrls (in case of two utility adapters). ******/
128                            /* Store the semaphore for later competion */
129                            (req_data->drv->adapter).IoctlComp = &(req_data->u.req.comp);
130                            /* Store the pointer of the result status for later competion */
131                            (req_data->drv->adapter).pCompleteReply = &(req_data->u.reply);
132                         }
133
134                 }
135     }
136     return res;
137 }
138
139 int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
140 {
141     tiioctl_req_t *req = (tiioctl_req_t *) &rq->ifr_ifru;
142     char *extra, *kbuf = NULL;
143     int res, aval_data_size = ((char *) req + sizeof(*req)) - (char *)&req->user_data_pointer;      /* = ~4 bytes */
144     /*int is_get_cmd = (req->cmd_type & IOCTL_GET);*/
145
146     print_deb("ti1610_do_ioctl(cmd=%lu(%s%s)) - user_data_pointer=0x%lx, len = %lu, aval_data_size=%d\n",
147                 req->cmd,
148                 (req->cmd_type & IOCTL_GET) ? "GET" : "", (req->cmd_type & IOCTL_SET) ? "SET" : "",
149                 req->user_data_pointer, req->length, aval_data_size );
150
151         /* driver is already initialized */
152         if ((req->cmd == TIWLN_SET_INIT_INFO) && (((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev))->adapter.CoreHalCtx))
153         {
154                 return 0;
155         }
156
157         if( req->length > aval_data_size )
158     {
159         if( req->user_data_pointer == 0 )
160             return -EFAULT;
161
162         print_deb("ti1610_do_ioctl() - alloc %ld bytes\n", req->length );
163                 kbuf = extra = os_memoryAlloc(NULL,req->length);
164 #ifdef TI_MEM_ALLOC_TRACE        
165         os_printf("MTT:%s:%d ::kmalloc(%lu, %x) : %lu\n", __FUNCTION__, __LINE__, req->length, GFP_KERNEL, req->length);
166 #endif/*I_MEM_ALLOC_TRACE*/
167
168         if( !extra )
169             return -ENOBUFS;
170         if( req->cmd_type & IOCTL_SET )
171         {
172             if( copy_from_user(extra, (void *) req->user_data_pointer, req->length) )
173                 return -EFAULT;
174         }
175         else {
176             os_memoryZero( NULL, extra, req->length );
177         }
178     } else
179             extra = (char *) &req->user_data_pointer;
180
181     /* Driver initialization must be performed in process context.
182        The rest is handled in the context of dedicated tasklet
183     */
184     if (req->cmd == TIWLN_SET_INIT_INFO)
185     {
186        tiwlan_dev_init_t *init_info = (tiwlan_dev_init_t *)extra;
187        print_deb("TIWLN_SET_INIT_INFO: el=%d il=%d, fl=%d\n",
188               init_info?init_info->eeprom_image_length:0,
189               init_info?init_info->init_file_length:0,
190               init_info?init_info->firmware_image_length:0 );
191        res = tiwlan_init_drv((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev), init_info);
192     }
193
194 #ifdef DRIVER_PROFILING
195     else if (req->cmd == TIWLAN_PROFILING_REPORT) 
196     {
197        res = tiwlan_profile_report((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
198     }
199     else if (req->cmd == TIWLAN_PROFILING_CPU_ESTIMATOR_CMD) {
200        /* get the command cpu estimator command parameter */
201        unsigned int command_param = *((unsigned int *)extra);
202        /* extract the command type which is the MSB byte of the command param*/
203        unsigned int command_type = 0xFF & (command_param >> 24);
204        /* extract the data of the command which are the 3 LSB bytes of the command param */
205        unsigned int command_data = 0xFFFFFF & command_param;
206        /* execute the command according to its type */
207        switch (command_type) 
208        {
209        case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_START:
210            res = tiwlan_profile_cpu_usage_estimator_start((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev),
211                                                           /* the data in this case is the estimator
212                                                           resolution in milliseconds */
213                                                           command_data * 1000);
214            break;
215        case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_STOP:
216            res = tiwlan_profile_cpu_usage_estimator_stop((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
217            break;
218        case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_RESET:
219            res =tiwlan_profile_cpu_usage_estimator_reset((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
220            break;
221        default:
222            res = 0;
223            printk("\n\n%s: cpu usage estimator unknow command: param = %x\n\n\n",
224                      __FUNCTION__, command_param);
225        }
226     }
227 #endif
228
229     else
230     {
231        res = tiwlan_send_wait_reply((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev), ti1610_ioctl_priv_proc_tl,
232                                     (unsigned long)req, (unsigned long)extra, 0, 0);
233     }
234
235     if( !res )
236     {
237             if( (req->cmd_type & IOCTL_GET) && kbuf /*req->length > aval_data_size*/ )
238             {
239                 print_deb("ti1610_do_ioctl(): ...copy from %p to %p %ld bytes\n\n", extra, (void *) req->user_data_pointer, req->length );
240                 print_memory_dump(extra, min(32,(int) req->length) );
241                 if( copy_to_user( (void *) req->user_data_pointer, extra, req->length ) )
242                     return -EFAULT;
243             }
244     }
245     print_deb("ti1610_do_ioctl() = %d (req = %p, user_data_pointer=0x%lx, extra=%p)\n\n", res, req, req->user_data_pointer, extra );
246
247     if( kbuf ){
248                 os_memoryFree(NULL,kbuf,sizeof(kbuf)); 
249 #ifdef TI_MEM_ALLOC_TRACE        
250         os_printf("MTT:%s:%d ::kfree(0x%p) : %d\n", __FUNCTION__, __LINE__, kbuf, -req->length);
251 #endif/*I_MEM_ALLOC_TRACE*/
252     }
253     return res;
254 }
255
256
257 int tiwlan_ioctl_init( struct net_device *dev )
258 {
259 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
260         dev->do_ioctl       = ti1610_do_ioctl;
261 #endif
262         return 0;
263 }