1 /****************************************************************************
2 **+-----------------------------------------------------------------------+**
4 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
5 **| All rights reserved. |**
7 **| Redistribution and use in source and binary forms, with or without |**
8 **| modification, are permitted provided that the following conditions |**
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 |**
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. |**
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. |**
33 **+-----------------------------------------------------------------------+**
34 ****************************************************************************/
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>
46 #include "tiwlan_profile.h"
47 #include "ioctl_init.h"
48 #include "ioctl_utils.h"
53 void print_priv_ioctl_params(struct net_device *dev, tiioctl_req_t *req, char *extra)
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) );
64 print_deb(" extra (%p) :", extra );
65 print_memory_dump(extra, req->length );
70 /*sends complete to the user after to signal the completion of the asynchronous */
71 /*operation (need to set *pIoCompleteFlag = FALSE, at osCmd.c).*/
73 void os_IoctlComplete(PTIWLN_ADAPTER_T pAdapter, TI_STATUS ReturnStatus )
75 *pAdapter->pCompleteReply = (int)ReturnStatus;
76 complete(pAdapter->IoctlComp);
80 NTSTATUS DispatchCommand(PTIWLN_ADAPTER_T pAdapter,ULONG ioControlCode,PULONG outBufLen,
81 ULONG inBufLen,PVOID ioBuffer,PUINT8 pIoCompleteFlag);
83 int ti1610_ioctl_priv_proc_tl(tiwlan_req_t *req_data)
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 ;
90 ULONG *data = (ULONG *) req_data->u.req.p2;
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 */
101 case TIWLN_DRIVER_STATUS_SET:
103 res = tiwlan_start_drv( (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev) );
105 res = tiwlan_stop_drv( (tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev) );
108 drv_started = !drv_started;
111 case TIWLN_SEND_EAPOL_PACKET:
112 res = os_sendPacket(dev, data, req->length);
115 case TIWLN_DRIVER_DEBUG_PRINT:
116 res = util_hal_debug_print(dev, data);
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)
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);
139 int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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);*/
146 print_deb("ti1610_do_ioctl(cmd=%lu(%s%s)) - user_data_pointer=0x%lx, len = %lu, aval_data_size=%d\n",
148 (req->cmd_type & IOCTL_GET) ? "GET" : "", (req->cmd_type & IOCTL_SET) ? "SET" : "",
149 req->user_data_pointer, req->length, aval_data_size );
151 /* driver is already initialized */
152 if ((req->cmd == TIWLN_SET_INIT_INFO) && (((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev))->adapter.CoreHalCtx))
157 if( req->length > aval_data_size )
159 if( req->user_data_pointer == 0 )
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*/
170 if( req->cmd_type & IOCTL_SET )
172 if( copy_from_user(extra, (void *) req->user_data_pointer, req->length) )
176 os_memoryZero( NULL, extra, req->length );
179 extra = (char *) &req->user_data_pointer;
181 /* Driver initialization must be performed in process context.
182 The rest is handled in the context of dedicated tasklet
184 if (req->cmd == TIWLN_SET_INIT_INFO)
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);
194 #ifdef DRIVER_PROFILING
195 else if (req->cmd == TIWLAN_PROFILING_REPORT)
197 res = tiwlan_profile_report((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
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)
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);
215 case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_STOP:
216 res = tiwlan_profile_cpu_usage_estimator_stop((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
218 case TIWLAN_PROFILING_CPU_ESTIMATOR_CMD_RESET:
219 res =tiwlan_profile_cpu_usage_estimator_reset((tiwlan_net_dev_t *)NETDEV_GET_PRIVATE(dev));
223 printk("\n\n%s: cpu usage estimator unknow command: param = %x\n\n\n",
224 __FUNCTION__, command_param);
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);
237 if( (req->cmd_type & IOCTL_GET) && kbuf /*req->length > aval_data_size*/ )
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 ) )
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 );
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*/
257 int tiwlan_ioctl_init( struct net_device *dev )
259 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 31))
260 dev->do_ioctl = ti1610_do_ioctl;