Home | History | Annotate | Download | only in src
      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 }
    264