blob: 605c6f3901010b9503f4a8e16054621cf3c294c8 [file] [log] [blame]
Forest Bond92b96792009-06-13 07:38:31 -04001/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * File: main_usb.c
20 *
21 * Purpose: driver entry for initial, open, close, tx and rx.
22 *
23 * Author: Lyndon Chen
24 *
25 * Date: Dec 8, 2005
26 *
27 * Functions:
28 *
Andres More26e5b652010-04-13 19:43:07 -030029 * vt6656_probe - module initial (insmod) driver entry
Forest Bond92b96792009-06-13 07:38:31 -040030 * device_remove1 - module remove entry
31 * device_open - allocate dma/descripter resource & initial mac/bbp function
Justin P. Mattocka0a1f612012-08-26 08:16:43 -070032 * device_xmit - asynchronous data tx function
Forest Bond92b96792009-06-13 07:38:31 -040033 * device_set_multi - set mac filter
34 * device_ioctl - ioctl entry
Justin P. Mattocka0a1f612012-08-26 08:16:43 -070035 * device_close - shutdown mac/bbp & free dma/descriptor resource
Forest Bond92b96792009-06-13 07:38:31 -040036 * device_alloc_frag_buf - rx fragement pre-allocated function
37 * device_free_tx_bufs - free tx buffer function
38 * device_dma0_tx_80211- tx 802.11 frame via dma0
Justin P. Mattocka0a1f612012-08-26 08:16:43 -070039 * device_dma0_xmit- tx PS buffered frame via dma0
Forest Bond92b96792009-06-13 07:38:31 -040040 * device_init_registers- initial MAC & BBP & RF internal registers.
41 * device_init_rings- initial tx/rx ring buffer
42 * device_init_defrag_cb- initial & allocate de-fragement buffer.
43 * device_tx_srv- tx interrupt service function
44 *
45 * Revision History:
46 */
47#undef __NO_VERSION__
48
Al Viro7c51d172013-04-06 18:00:07 -040049#include <linux/file.h>
Forest Bond92b96792009-06-13 07:38:31 -040050#include "device.h"
Forest Bond92b96792009-06-13 07:38:31 -040051#include "card.h"
Forest Bond92b96792009-06-13 07:38:31 -040052#include "baseband.h"
Forest Bond92b96792009-06-13 07:38:31 -040053#include "mac.h"
Forest Bond92b96792009-06-13 07:38:31 -040054#include "tether.h"
Forest Bond92b96792009-06-13 07:38:31 -040055#include "wmgr.h"
Forest Bond92b96792009-06-13 07:38:31 -040056#include "wctl.h"
Forest Bond92b96792009-06-13 07:38:31 -040057#include "power.h"
Forest Bond92b96792009-06-13 07:38:31 -040058#include "wcmd.h"
Forest Bond92b96792009-06-13 07:38:31 -040059#include "iocmd.h"
Forest Bond92b96792009-06-13 07:38:31 -040060#include "tcrc.h"
Forest Bond92b96792009-06-13 07:38:31 -040061#include "rxtx.h"
Forest Bond92b96792009-06-13 07:38:31 -040062#include "bssdb.h"
Forest Bond92b96792009-06-13 07:38:31 -040063#include "hostap.h"
Forest Bond92b96792009-06-13 07:38:31 -040064#include "wpactl.h"
Forest Bond92b96792009-06-13 07:38:31 -040065#include "iwctl.h"
Forest Bond92b96792009-06-13 07:38:31 -040066#include "dpc.h"
Forest Bond92b96792009-06-13 07:38:31 -040067#include "datarate.h"
Forest Bond92b96792009-06-13 07:38:31 -040068#include "rf.h"
Forest Bond92b96792009-06-13 07:38:31 -040069#include "firmware.h"
Forest Bond92b96792009-06-13 07:38:31 -040070#include "rndis.h"
Forest Bond92b96792009-06-13 07:38:31 -040071#include "control.h"
Forest Bond92b96792009-06-13 07:38:31 -040072#include "channel.h"
Forest Bond92b96792009-06-13 07:38:31 -040073#include "int.h"
Forest Bond92b96792009-06-13 07:38:31 -040074#include "iowpa.h"
Forest Bond92b96792009-06-13 07:38:31 -040075
Andres Moreec6e0f62013-01-31 18:23:07 -050076/* static int msglevel = MSG_LEVEL_DEBUG; */
Forest Bond92b96792009-06-13 07:38:31 -040077static int msglevel =MSG_LEVEL_INFO;
78
Andres Moreec6e0f62013-01-31 18:23:07 -050079/*
80 * define module options
81 */
Forest Bond92b96792009-06-13 07:38:31 -040082
Andres Moreec6e0f62013-01-31 18:23:07 -050083/* version information */
84#define DRIVER_AUTHOR \
85 "VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"
Forest Bond92b96792009-06-13 07:38:31 -040086MODULE_AUTHOR(DRIVER_AUTHOR);
87MODULE_LICENSE("GPL");
88MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM);
89
Forest Bond92b96792009-06-13 07:38:31 -040090#define DEVICE_PARAM(N,D) \
91 static int N[MAX_UINTS]=OPTION_DEFAULT;\
92 module_param_array(N, int, NULL, 0);\
93 MODULE_PARM_DESC(N, D);
94
Forest Bond92b96792009-06-13 07:38:31 -040095#define RX_DESC_DEF0 64
96DEVICE_PARAM(RxDescriptors0,"Number of receive usb desc buffer");
97
Forest Bond92b96792009-06-13 07:38:31 -040098#define TX_DESC_DEF0 64
99DEVICE_PARAM(TxDescriptors0,"Number of transmit usb desc buffer");
100
Forest Bond92b96792009-06-13 07:38:31 -0400101#define CHANNEL_DEF 6
Forest Bond92b96792009-06-13 07:38:31 -0400102DEVICE_PARAM(Channel, "Channel number");
103
Forest Bond92b96792009-06-13 07:38:31 -0400104/* PreambleType[] is the preamble length used for transmit.
105 0: indicate allows long preamble type
106 1: indicate allows short preamble type
107*/
108
109#define PREAMBLE_TYPE_DEF 1
110
111DEVICE_PARAM(PreambleType, "Preamble Type");
112
Forest Bond92b96792009-06-13 07:38:31 -0400113#define RTS_THRESH_DEF 2347
Forest Bond92b96792009-06-13 07:38:31 -0400114DEVICE_PARAM(RTSThreshold, "RTS threshold");
115
Forest Bond92b96792009-06-13 07:38:31 -0400116#define FRAG_THRESH_DEF 2346
Forest Bond92b96792009-06-13 07:38:31 -0400117DEVICE_PARAM(FragThreshold, "Fragmentation threshold");
118
Forest Bond92b96792009-06-13 07:38:31 -0400119#define DATA_RATE_DEF 13
120/* datarate[] index
121 0: indicate 1 Mbps 0x02
122 1: indicate 2 Mbps 0x04
123 2: indicate 5.5 Mbps 0x0B
124 3: indicate 11 Mbps 0x16
125 4: indicate 6 Mbps 0x0c
126 5: indicate 9 Mbps 0x12
127 6: indicate 12 Mbps 0x18
128 7: indicate 18 Mbps 0x24
129 8: indicate 24 Mbps 0x30
130 9: indicate 36 Mbps 0x48
131 10: indicate 48 Mbps 0x60
132 11: indicate 54 Mbps 0x6c
133 12: indicate 72 Mbps 0x90
134 13: indicate auto rate
135*/
136
137DEVICE_PARAM(ConnectionRate, "Connection data rate");
138
Forest Bond92b96792009-06-13 07:38:31 -0400139#define OP_MODE_DEF 0
Forest Bond92b96792009-06-13 07:38:31 -0400140DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode ");
141
142/* OpMode[] is used for transmit.
143 0: indicate infrastruct mode used
144 1: indicate adhoc mode used
145 2: indicate AP mode used
146*/
147
Forest Bond92b96792009-06-13 07:38:31 -0400148/* PSMode[]
149 0: indicate disable power saving mode
150 1: indicate enable power saving mode
151*/
152
153#define PS_MODE_DEF 0
Forest Bond92b96792009-06-13 07:38:31 -0400154DEVICE_PARAM(PSMode, "Power saving mode");
155
Forest Bond92b96792009-06-13 07:38:31 -0400156#define SHORT_RETRY_DEF 8
Forest Bond92b96792009-06-13 07:38:31 -0400157DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
158
Forest Bond92b96792009-06-13 07:38:31 -0400159#define LONG_RETRY_DEF 4
Forest Bond92b96792009-06-13 07:38:31 -0400160DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
161
Forest Bond92b96792009-06-13 07:38:31 -0400162/* BasebandType[] baseband type selected
163 0: indicate 802.11a type
164 1: indicate 802.11b type
165 2: indicate 802.11g type
166*/
Forest Bond92b96792009-06-13 07:38:31 -0400167
Marcos Paulo de Souza24b46f92012-07-02 23:59:30 -0300168#define BBP_TYPE_DEF 2
Forest Bond92b96792009-06-13 07:38:31 -0400169DEVICE_PARAM(BasebandType, "baseband type");
170
Forest Bond92b96792009-06-13 07:38:31 -0400171/* 80211hEnable[]
172 0: indicate disable 802.11h
173 1: indicate enable 802.11h
174*/
175
176#define X80211h_MODE_DEF 0
177
178DEVICE_PARAM(b80211hEnable, "802.11h mode");
179
Andres Moreec6e0f62013-01-31 18:23:07 -0500180/*
181 * Static vars definitions
182 */
Forest Bond92b96792009-06-13 07:38:31 -0400183
Greg Kroah-Hartman4d088872012-08-17 17:48:33 -0700184static struct usb_device_id vt6656_table[] = {
Forest Bond92b96792009-06-13 07:38:31 -0400185 {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)},
186 {}
187};
188
Andres Moreec6e0f62013-01-31 18:23:07 -0500189/* frequency list (map channels to frequencies) */
Forest Bond92b96792009-06-13 07:38:31 -0400190/*
191static const long frequency_list[] = {
192 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484,
193 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
194 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210, 5220, 5230, 5240,
195 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560, 5580, 5600, 5620, 5640, 5660, 5680,
196 5700, 5745, 5765, 5785, 5805, 5825
197 };
198
Forest Bond92b96792009-06-13 07:38:31 -0400199static const struct iw_handler_def iwctl_handler_def;
Forest Bond92b96792009-06-13 07:38:31 -0400200*/
201
Andres More26e5b652010-04-13 19:43:07 -0300202static int vt6656_probe(struct usb_interface *intf,
203 const struct usb_device_id *id);
204static void vt6656_disconnect(struct usb_interface *intf);
205
Forest Bond92b96792009-06-13 07:38:31 -0400206#ifdef CONFIG_PM /* Minimal support for suspend and resume */
Andres More26e5b652010-04-13 19:43:07 -0300207static int vt6656_suspend(struct usb_interface *intf, pm_message_t message);
208static int vt6656_resume(struct usb_interface *intf);
209#endif /* CONFIG_PM */
210
Forest Bond92b96792009-06-13 07:38:31 -0400211static struct net_device_stats *device_get_stats(struct net_device *dev);
212static int device_open(struct net_device *dev);
213static int device_xmit(struct sk_buff *skb, struct net_device *dev);
214static void device_set_multi(struct net_device *dev);
215static int device_close(struct net_device *dev);
216static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
217
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000218static int device_init_registers(struct vnt_private *pDevice,
219 DEVICE_INIT_TYPE InitType);
Andres Moredfdcc422013-02-12 20:36:28 -0500220static bool device_init_defrag_cb(struct vnt_private *pDevice);
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000221static void device_init_diversity_timer(struct vnt_private *pDevice);
Forest Bond92b96792009-06-13 07:38:31 -0400222static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev);
223
224static int ethtool_ioctl(struct net_device *dev, void *useraddr);
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000225static void device_free_tx_bufs(struct vnt_private *pDevice);
226static void device_free_rx_bufs(struct vnt_private *pDevice);
227static void device_free_int_bufs(struct vnt_private *pDevice);
228static void device_free_frag_bufs(struct vnt_private *pDevice);
Andres Moredfdcc422013-02-12 20:36:28 -0500229static bool device_alloc_bufs(struct vnt_private *pDevice);
Forest Bond92b96792009-06-13 07:38:31 -0400230
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000231static int Read_config_file(struct vnt_private *pDevice);
232static unsigned char *Config_FileOperation(struct vnt_private *pDevice);
Andres Morecc856e62010-05-17 21:34:01 -0300233static int Config_FileGetParameter(unsigned char *string,
234 unsigned char *dest,
235 unsigned char *source);
Forest Bond92b96792009-06-13 07:38:31 -0400236
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000237static void usb_device_reset(struct vnt_private *pDevice);
Forest Bond92b96792009-06-13 07:38:31 -0400238
Forest Bond92b96792009-06-13 07:38:31 -0400239static void
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000240device_set_options(struct vnt_private *pDevice) {
Forest Bond92b96792009-06-13 07:38:31 -0400241
Andres Moreb902fbf2013-02-25 20:32:51 -0500242 u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
243 u8 abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
Andres More9a0e7562010-04-13 21:54:48 -0300244 u8 abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8};
Forest Bond92b96792009-06-13 07:38:31 -0400245
Andres More9a0e7562010-04-13 21:54:48 -0300246 memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
247 memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
248 memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -0400249
250 pDevice->cbTD = TX_DESC_DEF0;
251 pDevice->cbRD = RX_DESC_DEF0;
252 pDevice->uChannel = CHANNEL_DEF;
253 pDevice->wRTSThreshold = RTS_THRESH_DEF;
254 pDevice->wFragmentationThreshold = FRAG_THRESH_DEF;
255 pDevice->byShortRetryLimit = SHORT_RETRY_DEF;
256 pDevice->byLongRetryLimit = LONG_RETRY_DEF;
257 pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME;
258 pDevice->byShortPreamble = PREAMBLE_TYPE_DEF;
259 pDevice->ePSMode = PS_MODE_DEF;
260 pDevice->b11hEnable = X80211h_MODE_DEF;
261 pDevice->eOPMode = OP_MODE_DEF;
262 pDevice->uConnectionRate = DATA_RATE_DEF;
Andres More4e9b5e22013-02-12 20:36:30 -0500263 if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true;
Forest Bond92b96792009-06-13 07:38:31 -0400264 pDevice->byBBType = BBP_TYPE_DEF;
265 pDevice->byPacketType = pDevice->byBBType;
266 pDevice->byAutoFBCtrl = AUTO_FB_0;
Andres More4e9b5e22013-02-12 20:36:30 -0500267 pDevice->bUpdateBBVGA = true;
Forest Bond92b96792009-06-13 07:38:31 -0400268 pDevice->byFOETuning = 0;
269 pDevice->byAutoPwrTunning = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400270 pDevice->byPreambleType = 0;
Andres Moree269fc22013-02-12 20:36:29 -0500271 pDevice->bExistSWNetAddr = false;
Andres More4e9b5e22013-02-12 20:36:30 -0500272 /* pDevice->bDiversityRegCtlON = true; */
Andres Moree269fc22013-02-12 20:36:29 -0500273 pDevice->bDiversityRegCtlON = false;
Forest Bond92b96792009-06-13 07:38:31 -0400274}
275
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000276static void device_init_diversity_timer(struct vnt_private *pDevice)
Andres More8611a292010-05-01 14:25:00 -0300277{
Forest Bond92b96792009-06-13 07:38:31 -0400278 init_timer(&pDevice->TimerSQ3Tmax1);
Andres Morecc856e62010-05-17 21:34:01 -0300279 pDevice->TimerSQ3Tmax1.data = (unsigned long)pDevice;
Forest Bond92b96792009-06-13 07:38:31 -0400280 pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack;
281 pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ);
282
283 init_timer(&pDevice->TimerSQ3Tmax2);
Andres Morecc856e62010-05-17 21:34:01 -0300284 pDevice->TimerSQ3Tmax2.data = (unsigned long)pDevice;
Forest Bond92b96792009-06-13 07:38:31 -0400285 pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack;
286 pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ);
287
288 init_timer(&pDevice->TimerSQ3Tmax3);
Andres Morecc856e62010-05-17 21:34:01 -0300289 pDevice->TimerSQ3Tmax3.data = (unsigned long)pDevice;
Forest Bond92b96792009-06-13 07:38:31 -0400290 pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerSQ3Tmax3CallBack;
291 pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ);
292
293 return;
294}
295
Andres Moreec6e0f62013-01-31 18:23:07 -0500296/*
297 * initialization of MAC & BBP registers
298 */
Forest Bond92b96792009-06-13 07:38:31 -0400299
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000300static int device_init_registers(struct vnt_private *pDevice,
301 DEVICE_INIT_TYPE InitType)
Forest Bond92b96792009-06-13 07:38:31 -0400302{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000303 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
304 u8 abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
305 u8 abySNAP_RFC1042[ETH_ALEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
306 u8 abySNAP_Bridgetunnel[ETH_ALEN]
307 = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
308 u8 byAntenna;
309 int ii;
310 CMD_CARD_INIT sInitCmd;
311 int ntStatus = STATUS_SUCCESS;
312 RSP_CARD_INIT sInitRsp;
313 u8 byTmp;
314 u8 byCalibTXIQ = 0, byCalibTXDC = 0, byCalibRXIQ = 0;
Forest Bond92b96792009-06-13 07:38:31 -0400315
316 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---->INIbInitAdapter. [%d][%d]\n", InitType, pDevice->byPacketType);
317 spin_lock_irq(&pDevice->lock);
Andres More9a0e7562010-04-13 21:54:48 -0300318 if (InitType == DEVICE_INIT_COLD) {
319 memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN);
320 memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN);
321 memcpy(pDevice->abySNAP_Bridgetunnel,
322 abySNAP_Bridgetunnel,
323 ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -0400324
325 if ( !FIRMWAREbCheckVersion(pDevice) ) {
Andres More4e9b5e22013-02-12 20:36:30 -0500326 if (FIRMWAREbDownload(pDevice) == true) {
Andres Moree269fc22013-02-12 20:36:29 -0500327 if (FIRMWAREbBrach2Sram(pDevice) == false) {
Forest Bond92b96792009-06-13 07:38:31 -0400328 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbBrach2Sram fail \n");
329 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500330 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400331 }
332 } else {
333
334 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" FIRMWAREbDownload fail \n");
335 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500336 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400337 }
338 }
339
340 if ( !BBbVT3184Init(pDevice) ) {
341 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" BBbVT3184Init fail \n");
342 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500343 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400344 }
345 }
346
Andres Moreb902fbf2013-02-25 20:32:51 -0500347 sInitCmd.byInitClass = (u8)InitType;
348 sInitCmd.bExistSWNetAddr = (u8) pDevice->bExistSWNetAddr;
Andres More33d33e422010-05-19 23:50:00 -0300349 for (ii = 0; ii < 6; ii++)
350 sInitCmd.bySWNetAddr[ii] = pDevice->abyCurrentNetAddr[ii];
Forest Bond92b96792009-06-13 07:38:31 -0400351 sInitCmd.byShortRetryLimit = pDevice->byShortRetryLimit;
352 sInitCmd.byLongRetryLimit = pDevice->byLongRetryLimit;
353
Andres Moreec6e0f62013-01-31 18:23:07 -0500354 /* issue card_init command to device */
Forest Bond92b96792009-06-13 07:38:31 -0400355 ntStatus = CONTROLnsRequestOut(pDevice,
356 MESSAGE_TYPE_CARDINIT,
357 0,
358 0,
359 sizeof(CMD_CARD_INIT),
Andres Moreb902fbf2013-02-25 20:32:51 -0500360 (u8 *) &(sInitCmd));
Forest Bond92b96792009-06-13 07:38:31 -0400361
362 if ( ntStatus != STATUS_SUCCESS ) {
363 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO" Issue Card init fail \n");
364 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500365 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400366 }
367 if (InitType == DEVICE_INIT_COLD) {
368
Andres Moreb902fbf2013-02-25 20:32:51 -0500369 ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp));
Forest Bond92b96792009-06-13 07:38:31 -0400370
371 if (ntStatus != STATUS_SUCCESS) {
372 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Cardinit request in status fail!\n");
373 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500374 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400375 }
376
Andres Moreec6e0f62013-01-31 18:23:07 -0500377 /* local ID for AES functions */
Forest Bond92b96792009-06-13 07:38:31 -0400378 ntStatus = CONTROLnsRequestIn(pDevice,
379 MESSAGE_TYPE_READ,
380 MAC_REG_LOCALID,
381 MESSAGE_REQUEST_MACREG,
382 1,
383 &pDevice->byLocalID);
384
385 if ( ntStatus != STATUS_SUCCESS ) {
386 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500387 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400388 }
389
Andres Moreec6e0f62013-01-31 18:23:07 -0500390 /* do MACbSoftwareReset in MACvInitialize */
391
392 /* force CCK */
Andres More4e9b5e22013-02-12 20:36:30 -0500393 pDevice->bCCK = true;
Andres Moree269fc22013-02-12 20:36:29 -0500394 pDevice->bProtectMode = false;
Andres Moreec6e0f62013-01-31 18:23:07 -0500395 /* only used in 11g type, sync with ERP IE */
Andres Moree269fc22013-02-12 20:36:29 -0500396 pDevice->bNonERPPresent = false;
397 pDevice->bBarkerPreambleMd = false;
Forest Bond92b96792009-06-13 07:38:31 -0400398 if ( pDevice->bFixRate ) {
Andres More3eaca0d2013-02-25 20:32:52 -0500399 pDevice->wCurrentRate = (u16) pDevice->uConnectionRate;
Forest Bond92b96792009-06-13 07:38:31 -0400400 } else {
401 if ( pDevice->byBBType == BB_TYPE_11B )
402 pDevice->wCurrentRate = RATE_11M;
403 else
404 pDevice->wCurrentRate = RATE_54M;
405 }
406
407 CHvInitChannelTable(pDevice);
408
409 pDevice->byTopOFDMBasicRate = RATE_24M;
410 pDevice->byTopCCKBasicRate = RATE_1M;
Andres Moreec6e0f62013-01-31 18:23:07 -0500411 pDevice->byRevId = 0;
412 /* target to IF pin while programming to RF chip */
Forest Bond92b96792009-06-13 07:38:31 -0400413 pDevice->byCurPwr = 0xFF;
414
415 pDevice->byCCKPwr = pDevice->abyEEPROM[EEP_OFS_PWR_CCK];
416 pDevice->byOFDMPwrG = pDevice->abyEEPROM[EEP_OFS_PWR_OFDMG];
Andres Moreec6e0f62013-01-31 18:23:07 -0500417 /* load power table */
418 for (ii = 0; ii < 14; ii++) {
Forest Bond92b96792009-06-13 07:38:31 -0400419 pDevice->abyCCKPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_CCK_PWR_TBL];
420 if (pDevice->abyCCKPwrTbl[ii] == 0)
421 pDevice->abyCCKPwrTbl[ii] = pDevice->byCCKPwr;
422 pDevice->abyOFDMPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDM_PWR_TBL];
423 if (pDevice->abyOFDMPwrTbl[ii] == 0)
424 pDevice->abyOFDMPwrTbl[ii] = pDevice->byOFDMPwrG;
425 }
426
Andres Moreec6e0f62013-01-31 18:23:07 -0500427 /*
428 * original zonetype is USA, but custom zonetype is Europe,
429 * then need to recover 12, 13, 14 channels with 11 channel
430 */
Forest Bond92b96792009-06-13 07:38:31 -0400431 if(((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) ||
432 (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe))&&
433 (pDevice->byOriginalZonetype == ZoneType_USA)) {
Andres More33d33e422010-05-19 23:50:00 -0300434 for (ii = 11; ii < 14; ii++) {
435 pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10];
436 pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10];
437 }
Forest Bond92b96792009-06-13 07:38:31 -0400438 }
439
Andres Moreec6e0f62013-01-31 18:23:07 -0500440 pDevice->byOFDMPwrA = 0x34; /* same as RFbMA2829SelectChannel */
441
442 /* load OFDM A power table */
443 for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
Forest Bond92b96792009-06-13 07:38:31 -0400444 pDevice->abyOFDMAPwrTbl[ii] = pDevice->abyEEPROM[ii + EEP_OFS_OFDMA_PWR_TBL];
445 if (pDevice->abyOFDMAPwrTbl[ii] == 0)
446 pDevice->abyOFDMAPwrTbl[ii] = pDevice->byOFDMPwrA;
447 }
Forest Bond92b96792009-06-13 07:38:31 -0400448
449 byAntenna = pDevice->abyEEPROM[EEP_OFS_ANTENNA];
450 if (byAntenna & EEP_ANTINV)
Andres More4e9b5e22013-02-12 20:36:30 -0500451 pDevice->bTxRxAntInv = true;
Forest Bond92b96792009-06-13 07:38:31 -0400452 else
Andres Moree269fc22013-02-12 20:36:29 -0500453 pDevice->bTxRxAntInv = false;
Forest Bond92b96792009-06-13 07:38:31 -0400454
455 byAntenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
456
Andres Moreec6e0f62013-01-31 18:23:07 -0500457 if (byAntenna == 0) /* if not set default is both */
Forest Bond92b96792009-06-13 07:38:31 -0400458 byAntenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
459
460 if (byAntenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
461 pDevice->byAntennaCount = 2;
462 pDevice->byTxAntennaMode = ANT_B;
463 pDevice->dwTxAntennaSel = 1;
464 pDevice->dwRxAntennaSel = 1;
Andres More4e9b5e22013-02-12 20:36:30 -0500465 if (pDevice->bTxRxAntInv == true)
Forest Bond92b96792009-06-13 07:38:31 -0400466 pDevice->byRxAntennaMode = ANT_A;
467 else
468 pDevice->byRxAntennaMode = ANT_B;
469
470 if (pDevice->bDiversityRegCtlON)
Andres More4e9b5e22013-02-12 20:36:30 -0500471 pDevice->bDiversityEnable = true;
Forest Bond92b96792009-06-13 07:38:31 -0400472 else
Andres Moree269fc22013-02-12 20:36:29 -0500473 pDevice->bDiversityEnable = false;
Forest Bond92b96792009-06-13 07:38:31 -0400474 } else {
Andres Moree269fc22013-02-12 20:36:29 -0500475 pDevice->bDiversityEnable = false;
Forest Bond92b96792009-06-13 07:38:31 -0400476 pDevice->byAntennaCount = 1;
477 pDevice->dwTxAntennaSel = 0;
478 pDevice->dwRxAntennaSel = 0;
479 if (byAntenna & EEP_ANTENNA_AUX) {
480 pDevice->byTxAntennaMode = ANT_A;
Andres More4e9b5e22013-02-12 20:36:30 -0500481 if (pDevice->bTxRxAntInv == true)
Forest Bond92b96792009-06-13 07:38:31 -0400482 pDevice->byRxAntennaMode = ANT_B;
483 else
484 pDevice->byRxAntennaMode = ANT_A;
485 } else {
486 pDevice->byTxAntennaMode = ANT_B;
Andres More4e9b5e22013-02-12 20:36:30 -0500487 if (pDevice->bTxRxAntInv == true)
Forest Bond92b96792009-06-13 07:38:31 -0400488 pDevice->byRxAntennaMode = ANT_A;
489 else
490 pDevice->byRxAntennaMode = ANT_B;
491 }
492 }
493 pDevice->ulDiversityNValue = 100*255;
494 pDevice->ulDiversityMValue = 100*16;
495 pDevice->byTMax = 1;
496 pDevice->byTMax2 = 4;
497 pDevice->ulSQ3TH = 0;
498 pDevice->byTMax3 = 64;
Forest Bond92b96792009-06-13 07:38:31 -0400499
Andres Moreec6e0f62013-01-31 18:23:07 -0500500 /* get Auto Fall Back type */
Forest Bond92b96792009-06-13 07:38:31 -0400501 pDevice->byAutoFBCtrl = AUTO_FB_0;
502
Andres Moreec6e0f62013-01-31 18:23:07 -0500503 /* set SCAN Time */
Forest Bond92b96792009-06-13 07:38:31 -0400504 pDevice->uScanTime = WLAN_SCAN_MINITIME;
505
Andres Moreec6e0f62013-01-31 18:23:07 -0500506 /* default Auto Mode */
507 /* pDevice->NetworkType = Ndis802_11Automode; */
Forest Bond92b96792009-06-13 07:38:31 -0400508 pDevice->eConfigPHYMode = PHY_TYPE_AUTO;
509 pDevice->byBBType = BB_TYPE_11G;
510
Andres Moreec6e0f62013-01-31 18:23:07 -0500511 /* initialize BBP registers */
Forest Bond92b96792009-06-13 07:38:31 -0400512 pDevice->ulTxPower = 25;
513
Andres Moreec6e0f62013-01-31 18:23:07 -0500514 /* get channel range */
Forest Bond92b96792009-06-13 07:38:31 -0400515 pDevice->byMinChannel = 1;
516 pDevice->byMaxChannel = CB_MAX_CHANNEL;
517
Andres Moreec6e0f62013-01-31 18:23:07 -0500518 /* get RFType */
Forest Bond92b96792009-06-13 07:38:31 -0400519 pDevice->byRFType = sInitRsp.byRFType;
520
521 if ((pDevice->byRFType & RF_EMU) != 0) {
Andres Moreec6e0f62013-01-31 18:23:07 -0500522 /* force change RevID for VT3253 emu */
523 pDevice->byRevId = 0x80;
Forest Bond92b96792009-06-13 07:38:31 -0400524 }
525
Andres Moreec6e0f62013-01-31 18:23:07 -0500526 /* load vt3266 calibration parameters in EEPROM */
Forest Bond92b96792009-06-13 07:38:31 -0400527 if (pDevice->byRFType == RF_VT3226D0) {
528 if((pDevice->abyEEPROM[EEP_OFS_MAJOR_VER] == 0x1) &&
529 (pDevice->abyEEPROM[EEP_OFS_MINOR_VER] >= 0x4)) {
530 byCalibTXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_IQ];
531 byCalibTXDC = pDevice->abyEEPROM[EEP_OFS_CALIB_TX_DC];
532 byCalibRXIQ = pDevice->abyEEPROM[EEP_OFS_CALIB_RX_IQ];
533 if( (byCalibTXIQ || byCalibTXDC || byCalibRXIQ) ) {
Andres Moreec6e0f62013-01-31 18:23:07 -0500534 /* CR255, enable TX/RX IQ and DC compensation mode */
535 ControlvWriteByte(pDevice,
536 MESSAGE_REQUEST_BBREG,
537 0xFF,
538 0x03);
539 /* CR251, TX I/Q Imbalance Calibration */
540 ControlvWriteByte(pDevice,
541 MESSAGE_REQUEST_BBREG,
542 0xFB,
543 byCalibTXIQ);
544 /* CR252, TX DC-Offset Calibration */
545 ControlvWriteByte(pDevice,
546 MESSAGE_REQUEST_BBREG,
547 0xFC,
548 byCalibTXDC);
549 /* CR253, RX I/Q Imbalance Calibration */
550 ControlvWriteByte(pDevice,
551 MESSAGE_REQUEST_BBREG,
552 0xFD,
553 byCalibRXIQ);
Forest Bond92b96792009-06-13 07:38:31 -0400554 } else {
Andres Moreec6e0f62013-01-31 18:23:07 -0500555 /* CR255, turn off BB Calibration compensation */
556 ControlvWriteByte(pDevice,
557 MESSAGE_REQUEST_BBREG,
558 0xFF,
559 0x0);
Forest Bond92b96792009-06-13 07:38:31 -0400560 }
561 }
562 }
563 pMgmt->eScanType = WMAC_SCAN_PASSIVE;
564 pMgmt->uCurrChannel = pDevice->uChannel;
565 pMgmt->uIBSSChannel = pDevice->uChannel;
566 CARDbSetMediaChannel(pDevice, pMgmt->uCurrChannel);
567
Andres Moreec6e0f62013-01-31 18:23:07 -0500568 /* get permanent network address */
Jim Lieb3e362592009-08-12 14:54:11 -0700569 memcpy(pDevice->abyPermanentNetAddr,&(sInitRsp.byNetAddr[0]),6);
Andres More9a0e7562010-04-13 21:54:48 -0300570 memcpy(pDevice->abyCurrentNetAddr,
571 pDevice->abyPermanentNetAddr,
572 ETH_ALEN);
Forest Bond92b96792009-06-13 07:38:31 -0400573
Andres Moreec6e0f62013-01-31 18:23:07 -0500574 /* if exist SW network address, use it */
Andy Shevchenkod6a32aa2011-07-26 10:35:31 +0300575 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
576 pDevice->abyCurrentNetAddr);
Forest Bond92b96792009-06-13 07:38:31 -0400577 }
578
Andres Moreec6e0f62013-01-31 18:23:07 -0500579 /*
580 * set BB and packet type at the same time
581 * set Short Slot Time, xIFS, and RSPINF
582 */
Forest Bond92b96792009-06-13 07:38:31 -0400583 if (pDevice->byBBType == BB_TYPE_11A) {
584 CARDbAddBasicRate(pDevice, RATE_6M);
Andres More4e9b5e22013-02-12 20:36:30 -0500585 pDevice->bShortSlotTime = true;
Forest Bond92b96792009-06-13 07:38:31 -0400586 } else {
587 CARDbAddBasicRate(pDevice, RATE_1M);
Andres Moree269fc22013-02-12 20:36:29 -0500588 pDevice->bShortSlotTime = false;
Forest Bond92b96792009-06-13 07:38:31 -0400589 }
590 BBvSetShortSlotTime(pDevice);
591 CARDvSetBSSMode(pDevice);
592
593 if (pDevice->bUpdateBBVGA) {
594 pDevice->byBBVGACurrent = pDevice->abyBBVGA[0];
595 pDevice->byBBVGANew = pDevice->byBBVGACurrent;
596 BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]);
597 }
598
599 pDevice->byRadioCtl = pDevice->abyEEPROM[EEP_OFS_RADIOCTL];
Andres Moree269fc22013-02-12 20:36:29 -0500600 pDevice->bHWRadioOff = false;
Forest Bond92b96792009-06-13 07:38:31 -0400601 if ( (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) != 0 ) {
602 ntStatus = CONTROLnsRequestIn(pDevice,
603 MESSAGE_TYPE_READ,
604 MAC_REG_GPIOCTL1,
605 MESSAGE_REQUEST_MACREG,
606 1,
607 &byTmp);
608
609 if ( ntStatus != STATUS_SUCCESS ) {
610 spin_unlock_irq(&pDevice->lock);
Andres Moree269fc22013-02-12 20:36:29 -0500611 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400612 }
613 if ( (byTmp & GPIO3_DATA) == 0 ) {
Andres More4e9b5e22013-02-12 20:36:30 -0500614 pDevice->bHWRadioOff = true;
Forest Bond92b96792009-06-13 07:38:31 -0400615 MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD);
616 } else {
617 MACvRegBitsOff(pDevice,MAC_REG_GPIOCTL1,GPIO3_INTMD);
Andres Moree269fc22013-02-12 20:36:29 -0500618 pDevice->bHWRadioOff = false;
Forest Bond92b96792009-06-13 07:38:31 -0400619 }
620
Andres Moreec6e0f62013-01-31 18:23:07 -0500621 }
Forest Bond92b96792009-06-13 07:38:31 -0400622
623 ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_TMLEN,0x38);
624 ControlvMaskByte(pDevice,MESSAGE_REQUEST_MACREG,MAC_REG_PAPEDELAY,LEDSTS_STS,LEDSTS_SLOW);
625 MACvRegBitsOn(pDevice,MAC_REG_GPIOCTL0,0x01);
626
Andres More4e9b5e22013-02-12 20:36:30 -0500627 if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) {
Forest Bond92b96792009-06-13 07:38:31 -0400628 CARDbRadioPowerOff(pDevice);
629 } else {
630 CARDbRadioPowerOn(pDevice);
631 }
632
633 spin_unlock_irq(&pDevice->lock);
634 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"<----INIbInitAdapter Exit\n");
Andres More4e9b5e22013-02-12 20:36:30 -0500635 return true;
Forest Bond92b96792009-06-13 07:38:31 -0400636}
637
Forest Bond92b96792009-06-13 07:38:31 -0400638#ifdef CONFIG_PM /* Minimal support for suspend and resume */
Andres More26e5b652010-04-13 19:43:07 -0300639
640static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
Forest Bond92b96792009-06-13 07:38:31 -0400641{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000642 struct vnt_private *device = usb_get_intfdata(intf);
Forest Bond92b96792009-06-13 07:38:31 -0400643
Andres Moree54d9eb2010-06-21 15:35:43 -0300644 if (!device || !device->dev)
645 return -ENODEV;
Forest Bond92b96792009-06-13 07:38:31 -0400646
Andres Moree54d9eb2010-06-21 15:35:43 -0300647 if (device->flags & DEVICE_FLAGS_OPENED)
648 device_close(device->dev);
649
Andres Moree54d9eb2010-06-21 15:35:43 -0300650 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400651}
652
Andres More26e5b652010-04-13 19:43:07 -0300653static int vt6656_resume(struct usb_interface *intf)
Forest Bond92b96792009-06-13 07:38:31 -0400654{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000655 struct vnt_private *device = usb_get_intfdata(intf);
Forest Bond92b96792009-06-13 07:38:31 -0400656
Andres Moree54d9eb2010-06-21 15:35:43 -0300657 if (!device || !device->dev)
658 return -ENODEV;
659
Andres Moree54d9eb2010-06-21 15:35:43 -0300660 if (!(device->flags & DEVICE_FLAGS_OPENED))
661 device_open(device->dev);
662
663 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400664}
Forest Bond92b96792009-06-13 07:38:31 -0400665
Andres More26e5b652010-04-13 19:43:07 -0300666#endif /* CONFIG_PM */
Forest Bonddd8db702009-06-13 07:38:54 -0400667
668static const struct net_device_ops device_netdev_ops = {
669 .ndo_open = device_open,
670 .ndo_stop = device_close,
671 .ndo_do_ioctl = device_ioctl,
672 .ndo_get_stats = device_get_stats,
673 .ndo_start_xmit = device_xmit,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000674 .ndo_set_rx_mode = device_set_multi,
Forest Bonddd8db702009-06-13 07:38:54 -0400675};
676
Bill Pemberton59cb2182012-11-19 13:21:55 -0500677static int
Andres More26e5b652010-04-13 19:43:07 -0300678vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
Forest Bond92b96792009-06-13 07:38:31 -0400679{
Andres More9a0e7562010-04-13 21:54:48 -0300680 u8 fake_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
Forest Bond92b96792009-06-13 07:38:31 -0400681 struct usb_device *udev = interface_to_usbdev(intf);
Andres More7a8b0052010-07-12 12:40:01 -0300682 int rc = 0;
683 struct net_device *netdev = NULL;
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000684 struct vnt_private *pDevice;
Forest Bond92b96792009-06-13 07:38:31 -0400685
Andres More7a8b0052010-07-12 12:40:01 -0300686 printk(KERN_NOTICE "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
687 printk(KERN_NOTICE "Copyright (c) 2004 VIA Networking Technologies, Inc.\n");
Forest Bond92b96792009-06-13 07:38:31 -0400688
Andres More7a8b0052010-07-12 12:40:01 -0300689 udev = usb_get_dev(udev);
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000690 netdev = alloc_etherdev(sizeof(struct vnt_private));
Andres More7a8b0052010-07-12 12:40:01 -0300691 if (!netdev) {
692 printk(KERN_ERR DEVICE_NAME ": allocate net device failed\n");
Dan Carpentere3a92cd2010-08-10 08:00:12 +0200693 rc = -ENOMEM;
Andres More7a8b0052010-07-12 12:40:01 -0300694 goto err_nomem;
695 }
Forest Bond92b96792009-06-13 07:38:31 -0400696
Andres More7a8b0052010-07-12 12:40:01 -0300697 pDevice = netdev_priv(netdev);
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000698 memset(pDevice, 0, sizeof(struct vnt_private));
Forest Bond92b96792009-06-13 07:38:31 -0400699
Andres More7a8b0052010-07-12 12:40:01 -0300700 pDevice->dev = netdev;
701 pDevice->usb = udev;
Forest Bond1e28efa2009-06-13 07:38:50 -0400702
Andres More7a8b0052010-07-12 12:40:01 -0300703 device_set_options(pDevice);
704 spin_lock_init(&pDevice->lock);
Malcolm Priestley94488a72013-09-27 16:48:14 +0100705 INIT_DELAYED_WORK(&pDevice->run_command_work, vRunCommand);
Malcolm Priestleybd9a6db2013-09-27 16:51:13 +0100706 INIT_DELAYED_WORK(&pDevice->second_callback_work, BSSvSecondCallBack);
Forest Bond1e28efa2009-06-13 07:38:50 -0400707
Andres More7a8b0052010-07-12 12:40:01 -0300708 pDevice->tx_80211 = device_dma0_tx_80211;
Malcolm Priestley14c5ef52013-01-17 23:19:37 +0000709 pDevice->vnt_mgmt.pAdapter = (void *) pDevice;
Forest Bond92b96792009-06-13 07:38:31 -0400710
Andres More7a8b0052010-07-12 12:40:01 -0300711 netdev->netdev_ops = &device_netdev_ops;
712 netdev->wireless_handlers =
713 (struct iw_handler_def *) &iwctl_handler_def;
Forest Bond92b96792009-06-13 07:38:31 -0400714
Andres More7a8b0052010-07-12 12:40:01 -0300715 usb_set_intfdata(intf, pDevice);
Forest Bond92b96792009-06-13 07:38:31 -0400716 SET_NETDEV_DEV(netdev, &intf->dev);
Andres More7a8b0052010-07-12 12:40:01 -0300717 memcpy(pDevice->dev->dev_addr, fake_mac, ETH_ALEN);
718 rc = register_netdev(netdev);
719 if (rc) {
720 printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n");
Dan Carpentere3a92cd2010-08-10 08:00:12 +0200721 goto err_netdev;
Andres More7a8b0052010-07-12 12:40:01 -0300722 }
Forest Bond92b96792009-06-13 07:38:31 -0400723
Andres More7a8b0052010-07-12 12:40:01 -0300724 usb_device_reset(pDevice);
Forest Bond92b96792009-06-13 07:38:31 -0400725
Forest Bond92b96792009-06-13 07:38:31 -0400726 return 0;
Forest Bond92b96792009-06-13 07:38:31 -0400727
Dan Carpentere3a92cd2010-08-10 08:00:12 +0200728err_netdev:
729 free_netdev(netdev);
Forest Bond92b96792009-06-13 07:38:31 -0400730err_nomem:
Andres More7a8b0052010-07-12 12:40:01 -0300731 usb_put_dev(udev);
Forest Bond92b96792009-06-13 07:38:31 -0400732
Dan Carpentere3a92cd2010-08-10 08:00:12 +0200733 return rc;
Forest Bond92b96792009-06-13 07:38:31 -0400734}
735
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000736static void device_free_tx_bufs(struct vnt_private *pDevice)
Andres More8611a292010-05-01 14:25:00 -0300737{
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +0100738 struct vnt_usb_send_context *pTxContext;
Forest Bond92b96792009-06-13 07:38:31 -0400739 int ii;
740
741 for (ii = 0; ii < pDevice->cbTD; ii++) {
742
743 pTxContext = pDevice->apTD[ii];
Andres Moreec6e0f62013-01-31 18:23:07 -0500744 /* deallocate URBs */
Forest Bond92b96792009-06-13 07:38:31 -0400745 if (pTxContext->pUrb) {
Jim Liebdad72fe2009-08-12 14:54:14 -0700746 usb_kill_urb(pTxContext->pUrb);
Forest Bond92b96792009-06-13 07:38:31 -0400747 usb_free_urb(pTxContext->pUrb);
748 }
Ilia Mirkin1d5c5362011-03-13 00:29:15 -0500749 kfree(pTxContext);
Forest Bond92b96792009-06-13 07:38:31 -0400750 }
751 return;
752}
753
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000754static void device_free_rx_bufs(struct vnt_private *pDevice)
Andres More8611a292010-05-01 14:25:00 -0300755{
Malcolm Priestley115cac22013-08-28 21:12:35 +0100756 struct vnt_rcb *pRCB;
757 int ii;
Forest Bond92b96792009-06-13 07:38:31 -0400758
759 for (ii = 0; ii < pDevice->cbRD; ii++) {
760
761 pRCB = pDevice->apRCB[ii];
Andres Moreec6e0f62013-01-31 18:23:07 -0500762 /* deallocate URBs */
Forest Bond92b96792009-06-13 07:38:31 -0400763 if (pRCB->pUrb) {
Jim Liebdad72fe2009-08-12 14:54:14 -0700764 usb_kill_urb(pRCB->pUrb);
Forest Bond92b96792009-06-13 07:38:31 -0400765 usb_free_urb(pRCB->pUrb);
766 }
Andres Moreec6e0f62013-01-31 18:23:07 -0500767 /* deallocate skb */
Forest Bond92b96792009-06-13 07:38:31 -0400768 if (pRCB->skb)
769 dev_kfree_skb(pRCB->skb);
770 }
Ilia Mirkin1d5c5362011-03-13 00:29:15 -0500771 kfree(pDevice->pRCBMem);
Forest Bond92b96792009-06-13 07:38:31 -0400772
773 return;
774}
775
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000776static void usb_device_reset(struct vnt_private *pDevice)
Forest Bond92b96792009-06-13 07:38:31 -0400777{
778 int status;
779 status = usb_reset_device(pDevice->usb);
780 if (status)
781 printk("usb_device_reset fail status=%d\n",status);
782 return ;
783}
Forest Bond92b96792009-06-13 07:38:31 -0400784
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000785static void device_free_int_bufs(struct vnt_private *pDevice)
Andres More8611a292010-05-01 14:25:00 -0300786{
Ilia Mirkin1d5c5362011-03-13 00:29:15 -0500787 kfree(pDevice->intBuf.pDataBuf);
Forest Bond92b96792009-06-13 07:38:31 -0400788 return;
789}
790
Andres Moredfdcc422013-02-12 20:36:28 -0500791static bool device_alloc_bufs(struct vnt_private *pDevice)
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000792{
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +0100793 struct vnt_usb_send_context *pTxContext;
Malcolm Priestley115cac22013-08-28 21:12:35 +0100794 struct vnt_rcb *pRCB;
795 int ii;
Forest Bond92b96792009-06-13 07:38:31 -0400796
Forest Bond92b96792009-06-13 07:38:31 -0400797 for (ii = 0; ii < pDevice->cbTD; ii++) {
798
Malcolm Priestleydcdf1d02013-08-27 12:41:50 +0100799 pTxContext = kmalloc(sizeof(struct vnt_usb_send_context), GFP_KERNEL);
Forest Bond92b96792009-06-13 07:38:31 -0400800 if (pTxContext == NULL) {
801 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : allocate tx usb context failed\n", pDevice->dev->name);
802 goto free_tx;
803 }
804 pDevice->apTD[ii] = pTxContext;
Andres More8611a292010-05-01 14:25:00 -0300805 pTxContext->pDevice = (void *) pDevice;
Andres Moreec6e0f62013-01-31 18:23:07 -0500806 /* allocate URBs */
Jim Liebdad72fe2009-08-12 14:54:14 -0700807 pTxContext->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
Forest Bond92b96792009-06-13 07:38:31 -0400808 if (pTxContext->pUrb == NULL) {
809 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "alloc tx urb failed\n");
810 goto free_tx;
811 }
Andres Moree269fc22013-02-12 20:36:29 -0500812 pTxContext->bBoolInUse = false;
Forest Bond92b96792009-06-13 07:38:31 -0400813 }
814
Andres Moreec6e0f62013-01-31 18:23:07 -0500815 /* allocate RCB mem */
Malcolm Priestley115cac22013-08-28 21:12:35 +0100816 pDevice->pRCBMem = kzalloc((sizeof(struct vnt_rcb) * pDevice->cbRD),
817 GFP_KERNEL);
Forest Bond92b96792009-06-13 07:38:31 -0400818 if (pDevice->pRCBMem == NULL) {
819 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s : alloc rx usb context failed\n", pDevice->dev->name);
820 goto free_tx;
821 }
822
Forest Bond92b96792009-06-13 07:38:31 -0400823 pDevice->FirstRecvFreeList = NULL;
824 pDevice->LastRecvFreeList = NULL;
825 pDevice->FirstRecvMngList = NULL;
826 pDevice->LastRecvMngList = NULL;
827 pDevice->NumRecvFreeList = 0;
Malcolm Priestley115cac22013-08-28 21:12:35 +0100828
829 pRCB = (struct vnt_rcb *)pDevice->pRCBMem;
Forest Bond92b96792009-06-13 07:38:31 -0400830
831 for (ii = 0; ii < pDevice->cbRD; ii++) {
832
833 pDevice->apRCB[ii] = pRCB;
Andres More8611a292010-05-01 14:25:00 -0300834 pRCB->pDevice = (void *) pDevice;
Andres Moreec6e0f62013-01-31 18:23:07 -0500835 /* allocate URBs */
Jim Liebdad72fe2009-08-12 14:54:14 -0700836 pRCB->pUrb = usb_alloc_urb(0, GFP_ATOMIC);
Forest Bond92b96792009-06-13 07:38:31 -0400837
838 if (pRCB->pUrb == NULL) {
839 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx urb\n");
840 goto free_rx_tx;
841 }
842 pRCB->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
843 if (pRCB->skb == NULL) {
844 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR" Failed to alloc rx skb\n");
845 goto free_rx_tx;
846 }
847 pRCB->skb->dev = pDevice->dev;
Andres Moree269fc22013-02-12 20:36:29 -0500848 pRCB->bBoolInUse = false;
Forest Bond92b96792009-06-13 07:38:31 -0400849 EnqueueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList, pRCB);
850 pDevice->NumRecvFreeList++;
851 pRCB++;
852 }
853
Jim Liebdad72fe2009-08-12 14:54:14 -0700854 pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC);
Forest Bond92b96792009-06-13 07:38:31 -0400855 if (pDevice->pControlURB == NULL) {
856 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n");
857 goto free_rx_tx;
858 }
859
Jim Liebdad72fe2009-08-12 14:54:14 -0700860 pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC);
Forest Bond92b96792009-06-13 07:38:31 -0400861 if (pDevice->pInterruptURB == NULL) {
862 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n");
Forest Bond92b96792009-06-13 07:38:31 -0400863 usb_free_urb(pDevice->pControlURB);
864 goto free_rx_tx;
865 }
866
867 pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
868 if (pDevice->intBuf.pDataBuf == NULL) {
869 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n");
Forest Bond92b96792009-06-13 07:38:31 -0400870 usb_free_urb(pDevice->pControlURB);
871 usb_free_urb(pDevice->pInterruptURB);
872 goto free_rx_tx;
873 }
874
Andres More4e9b5e22013-02-12 20:36:30 -0500875 return true;
Forest Bond92b96792009-06-13 07:38:31 -0400876
877free_rx_tx:
878 device_free_rx_bufs(pDevice);
879
880free_tx:
881 device_free_tx_bufs(pDevice);
882
Andres Moree269fc22013-02-12 20:36:29 -0500883 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400884}
885
Andres Moredfdcc422013-02-12 20:36:28 -0500886static bool device_init_defrag_cb(struct vnt_private *pDevice)
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000887{
888 int i;
889 PSDeFragControlBlock pDeF;
Forest Bond92b96792009-06-13 07:38:31 -0400890
891 /* Init the fragment ctl entries */
892 for (i = 0; i < CB_MAX_RX_FRAG; i++) {
893 pDeF = &(pDevice->sRxDFCB[i]);
894 if (!device_alloc_frag_buf(pDevice, pDeF)) {
895 DBG_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc frag bufs\n",
896 pDevice->dev->name);
897 goto free_frag;
Joe Perches9fc86022011-04-10 14:31:32 -0700898 }
Forest Bond92b96792009-06-13 07:38:31 -0400899 }
900 pDevice->cbDFCB = CB_MAX_RX_FRAG;
901 pDevice->cbFreeDFCB = pDevice->cbDFCB;
Andres More4e9b5e22013-02-12 20:36:30 -0500902 return true;
Forest Bond92b96792009-06-13 07:38:31 -0400903
904free_frag:
905 device_free_frag_bufs(pDevice);
Andres Moree269fc22013-02-12 20:36:29 -0500906 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400907}
908
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000909static void device_free_frag_bufs(struct vnt_private *pDevice)
910{
911 PSDeFragControlBlock pDeF;
912 int i;
Forest Bond92b96792009-06-13 07:38:31 -0400913
914 for (i = 0; i < CB_MAX_RX_FRAG; i++) {
915
916 pDeF = &(pDevice->sRxDFCB[i]);
917
918 if (pDeF->skb)
919 dev_kfree_skb(pDeF->skb);
920 }
921}
922
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000923int device_alloc_frag_buf(struct vnt_private *pDevice,
924 PSDeFragControlBlock pDeF)
925{
Forest Bond92b96792009-06-13 07:38:31 -0400926
927 pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
928 if (pDeF->skb == NULL)
Andres Moree269fc22013-02-12 20:36:29 -0500929 return false;
Forest Bond92b96792009-06-13 07:38:31 -0400930 pDeF->skb->dev = pDevice->dev;
931
Andres More4e9b5e22013-02-12 20:36:30 -0500932 return true;
Forest Bond92b96792009-06-13 07:38:31 -0400933}
934
Malcolm Priestleydd0a7742012-12-10 21:59:10 +0000935static int device_open(struct net_device *dev)
936{
937 struct vnt_private *pDevice = netdev_priv(dev);
Forest Bond92b96792009-06-13 07:38:31 -0400938
Andres Moree269fc22013-02-12 20:36:29 -0500939 pDevice->fWPA_Authened = false;
Forest Bond92b96792009-06-13 07:38:31 -0400940
941 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_open...\n");
942
Forest Bond92b96792009-06-13 07:38:31 -0400943 pDevice->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
944
Andres Moree269fc22013-02-12 20:36:29 -0500945 if (device_alloc_bufs(pDevice) == false) {
Forest Bond92b96792009-06-13 07:38:31 -0400946 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " device_alloc_bufs fail... \n");
947 return -ENOMEM;
948 }
949
Andres Moree269fc22013-02-12 20:36:29 -0500950 if (device_init_defrag_cb(pDevice)== false) {
Justin P. Mattocka0a1f612012-08-26 08:16:43 -0700951 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Initial defragment cb fail \n");
Forest Bond92b96792009-06-13 07:38:31 -0400952 goto free_rx_tx;
953 }
954
955 MP_CLEAR_FLAG(pDevice, fMP_DISCONNECTED);
956 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS);
957 MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES);
958 MP_SET_FLAG(pDevice, fMP_POST_READS);
959 MP_SET_FLAG(pDevice, fMP_POST_WRITES);
960
Andres Moreec6e0f62013-01-31 18:23:07 -0500961 /* read config file */
Forest Bond92b96792009-06-13 07:38:31 -0400962 Read_config_file(pDevice);
963
Andres Moree269fc22013-02-12 20:36:29 -0500964 if (device_init_registers(pDevice, DEVICE_INIT_COLD) == false) {
Forest Bond92b96792009-06-13 07:38:31 -0400965 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " init register fail\n");
966 goto free_all;
967 }
968
969 device_set_multi(pDevice->dev);
Forest Bond92b96792009-06-13 07:38:31 -0400970
Andres Moreec6e0f62013-01-31 18:23:07 -0500971 /* init for key management */
Forest Bond92b96792009-06-13 07:38:31 -0400972 KeyvInitTable(pDevice,&pDevice->sKey);
Malcolm Priestley14c5ef52013-01-17 23:19:37 +0000973 memcpy(pDevice->vnt_mgmt.abyMACAddr,
974 pDevice->abyCurrentNetAddr, ETH_ALEN);
Andres More9a0e7562010-04-13 21:54:48 -0300975 memcpy(pDevice->dev->dev_addr, pDevice->abyCurrentNetAddr, ETH_ALEN);
Andres Moree269fc22013-02-12 20:36:29 -0500976 pDevice->bStopTx0Pkt = false;
977 pDevice->bStopDataPkt = false;
978 pDevice->bRoaming = false;
979 pDevice->bIsRoaming = false;
980 pDevice->bEnableRoaming = false;
Forest Bond92b96792009-06-13 07:38:31 -0400981 if (pDevice->bDiversityRegCtlON) {
982 device_init_diversity_timer(pDevice);
983 }
984
985 vMgrObjectInit(pDevice);
986 tasklet_init(&pDevice->RxMngWorkItem, (void *)RXvMngWorkItem, (unsigned long)pDevice);
987 tasklet_init(&pDevice->ReadWorkItem, (void *)RXvWorkItem, (unsigned long)pDevice);
988 tasklet_init(&pDevice->EventWorkItem, (void *)INTvWorkItem, (unsigned long)pDevice);
Malcolm Priestleybd9a6db2013-09-27 16:51:13 +0100989
990 schedule_delayed_work(&pDevice->second_callback_work, HZ);
991
Andres Moreec6e0f62013-01-31 18:23:07 -0500992 pDevice->int_interval = 100; /* max 100 microframes */
Forest Bond92b96792009-06-13 07:38:31 -0400993 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
994
Andres More4e9b5e22013-02-12 20:36:30 -0500995 pDevice->bIsRxWorkItemQueued = true;
Andres Moree269fc22013-02-12 20:36:29 -0500996 pDevice->fKillEventPollingThread = false;
997 pDevice->bEventAvailable = false;
Forest Bond92b96792009-06-13 07:38:31 -0400998
Andres Moree269fc22013-02-12 20:36:29 -0500999 pDevice->bWPADEVUp = false;
1000 pDevice->bwextstep0 = false;
1001 pDevice->bwextstep1 = false;
1002 pDevice->bwextstep2 = false;
1003 pDevice->bwextstep3 = false;
1004 pDevice->bWPASuppWextEnabled = false;
Forest Bond92b96792009-06-13 07:38:31 -04001005 pDevice->byReAssocCount = 0;
1006
1007 RXvWorkItem(pDevice);
1008 INTvWorkItem(pDevice);
1009
Andres Moreec6e0f62013-01-31 18:23:07 -05001010 /* if WEP key already set by iwconfig but device not yet open */
Andres More4e9b5e22013-02-12 20:36:30 -05001011 if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) {
Forest Bond92b96792009-06-13 07:38:31 -04001012 spin_lock_irq(&pDevice->lock);
1013 KeybSetDefaultKey( pDevice,
1014 &(pDevice->sKey),
1015 pDevice->byKeyIndex | (1 << 31),
1016 pDevice->uKeyLength,
1017 NULL,
1018 pDevice->abyKey,
1019 KEY_CTL_WEP
1020 );
1021 spin_unlock_irq(&pDevice->lock);
1022 pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
1023 }
1024
Malcolm Priestley14c5ef52013-01-17 23:19:37 +00001025 if (pDevice->vnt_mgmt.eConfigMode == WMAC_CONFIG_AP)
Andres More0cbd8d92010-05-06 20:34:29 -03001026 bScheduleCommand((void *) pDevice, WLAN_CMD_RUN_AP, NULL);
Malcolm Priestley14c5ef52013-01-17 23:19:37 +00001027 else
1028 bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001029
Forest Bond92b96792009-06-13 07:38:31 -04001030 netif_stop_queue(pDevice->dev);
1031 pDevice->flags |= DEVICE_FLAGS_OPENED;
1032
Malcolm Priestley179f823d2012-11-24 14:47:11 +00001033 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success..\n");
1034 return 0;
Forest Bond92b96792009-06-13 07:38:31 -04001035
1036free_all:
1037 device_free_frag_bufs(pDevice);
1038free_rx_tx:
1039 device_free_rx_bufs(pDevice);
1040 device_free_tx_bufs(pDevice);
1041 device_free_int_bufs(pDevice);
Jim Liebdad72fe2009-08-12 14:54:14 -07001042 usb_kill_urb(pDevice->pControlURB);
1043 usb_kill_urb(pDevice->pInterruptURB);
Forest Bond92b96792009-06-13 07:38:31 -04001044 usb_free_urb(pDevice->pControlURB);
1045 usb_free_urb(pDevice->pInterruptURB);
1046
1047 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open fail.. \n");
1048 return -ENOMEM;
1049}
1050
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001051static int device_close(struct net_device *dev)
1052{
1053 struct vnt_private *pDevice = netdev_priv(dev);
1054 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
1055 int uu;
Forest Bond92b96792009-06-13 07:38:31 -04001056
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001057 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close1\n");
Forest Bond92b96792009-06-13 07:38:31 -04001058 if (pDevice == NULL)
1059 return -ENODEV;
1060
Forest Bond92b96792009-06-13 07:38:31 -04001061 if (pDevice->bLinkPass) {
Andres More0cbd8d92010-05-06 20:34:29 -03001062 bScheduleCommand((void *) pDevice, WLAN_CMD_DISASSOCIATE, NULL);
Forest Bond92b96792009-06-13 07:38:31 -04001063 mdelay(30);
1064 }
Forest Bond92b96792009-06-13 07:38:31 -04001065
Forest Bond92b96792009-06-13 07:38:31 -04001066 memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
Andres Moree269fc22013-02-12 20:36:29 -05001067 pMgmt->bShareKeyAlgorithm = false;
1068 pDevice->bEncryptionEnable = false;
Forest Bond92b96792009-06-13 07:38:31 -04001069 pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
Andres More33d33e422010-05-19 23:50:00 -03001070 spin_lock_irq(&pDevice->lock);
1071 for (uu = 0; uu < MAX_KEY_TABLE; uu++)
Forest Bond92b96792009-06-13 07:38:31 -04001072 MACvDisableKeyEntry(pDevice,uu);
Andres More33d33e422010-05-19 23:50:00 -03001073 spin_unlock_irq(&pDevice->lock);
Forest Bond92b96792009-06-13 07:38:31 -04001074
Andres Moree269fc22013-02-12 20:36:29 -05001075 if ((pDevice->flags & DEVICE_FLAGS_UNPLUG) == false) {
Forest Bond92b96792009-06-13 07:38:31 -04001076 MACbShutdown(pDevice);
1077 }
1078 netif_stop_queue(pDevice->dev);
1079 MP_SET_FLAG(pDevice, fMP_DISCONNECTED);
1080 MP_CLEAR_FLAG(pDevice, fMP_POST_WRITES);
1081 MP_CLEAR_FLAG(pDevice, fMP_POST_READS);
Andres More4e9b5e22013-02-12 20:36:30 -05001082 pDevice->fKillEventPollingThread = true;
Malcolm Priestley94488a72013-09-27 16:48:14 +01001083
1084 cancel_delayed_work_sync(&pDevice->run_command_work);
Malcolm Priestleybd9a6db2013-09-27 16:51:13 +01001085 cancel_delayed_work_sync(&pDevice->second_callback_work);
Forest Bond92b96792009-06-13 07:38:31 -04001086
Forest Bond92b96792009-06-13 07:38:31 -04001087 del_timer(&pDevice->sTimerTxData);
Forest Bond92b96792009-06-13 07:38:31 -04001088
1089 if (pDevice->bDiversityRegCtlON) {
1090 del_timer(&pDevice->TimerSQ3Tmax1);
1091 del_timer(&pDevice->TimerSQ3Tmax2);
1092 del_timer(&pDevice->TimerSQ3Tmax3);
1093 }
1094 tasklet_kill(&pDevice->RxMngWorkItem);
1095 tasklet_kill(&pDevice->ReadWorkItem);
1096 tasklet_kill(&pDevice->EventWorkItem);
1097
Andres Moree269fc22013-02-12 20:36:29 -05001098 pDevice->bRoaming = false;
1099 pDevice->bIsRoaming = false;
1100 pDevice->bEnableRoaming = false;
1101 pDevice->bCmdRunning = false;
1102 pDevice->bLinkPass = false;
Forest Bond92b96792009-06-13 07:38:31 -04001103 memset(pMgmt->abyCurrBSSID, 0, 6);
1104 pMgmt->eCurrState = WMAC_STATE_IDLE;
1105
Malcolm Priestleye3eb2702013-09-22 19:48:54 +01001106 pDevice->flags &= ~DEVICE_FLAGS_OPENED;
1107
Forest Bond92b96792009-06-13 07:38:31 -04001108 device_free_tx_bufs(pDevice);
1109 device_free_rx_bufs(pDevice);
1110 device_free_int_bufs(pDevice);
1111 device_free_frag_bufs(pDevice);
1112
Jim Liebdad72fe2009-08-12 14:54:14 -07001113 usb_kill_urb(pDevice->pControlURB);
1114 usb_kill_urb(pDevice->pInterruptURB);
Forest Bond92b96792009-06-13 07:38:31 -04001115 usb_free_urb(pDevice->pControlURB);
1116 usb_free_urb(pDevice->pInterruptURB);
1117
1118 BSSvClearNodeDBTable(pDevice, 0);
Forest Bond92b96792009-06-13 07:38:31 -04001119
1120 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n");
1121
1122 return 0;
1123}
1124
Bill Pemberton0d7fe142012-11-19 13:26:58 -05001125static void vt6656_disconnect(struct usb_interface *intf)
Forest Bond92b96792009-06-13 07:38:31 -04001126{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001127 struct vnt_private *device = usb_get_intfdata(intf);
Forest Bond92b96792009-06-13 07:38:31 -04001128
Andres More6cda24f2010-06-22 20:43:39 -03001129 if (!device)
1130 return;
Forest Bond92b96792009-06-13 07:38:31 -04001131
Forest Bond92b96792009-06-13 07:38:31 -04001132 usb_set_intfdata(intf, NULL);
Andres More6cda24f2010-06-22 20:43:39 -03001133 usb_put_dev(interface_to_usbdev(intf));
Forest Bond92b96792009-06-13 07:38:31 -04001134
Andres More6cda24f2010-06-22 20:43:39 -03001135 device->flags |= DEVICE_FLAGS_UNPLUG;
Forest Bond92b96792009-06-13 07:38:31 -04001136
Andres More6cda24f2010-06-22 20:43:39 -03001137 if (device->dev) {
1138 unregister_netdev(device->dev);
Andres More6cda24f2010-06-22 20:43:39 -03001139 free_netdev(device->dev);
1140 }
Malcolm Priestleyb3a6db92012-11-24 14:36:12 +00001141
Forest Bond92b96792009-06-13 07:38:31 -04001142}
1143
Andres Moree1669ed2010-07-12 13:10:27 -03001144static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev)
1145{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001146 struct vnt_private *pDevice = netdev_priv(dev);
Forest Bond92b96792009-06-13 07:38:31 -04001147
Andres Moree1669ed2010-07-12 13:10:27 -03001148 spin_lock_irq(&pDevice->lock);
Forest Bond92b96792009-06-13 07:38:31 -04001149
Andres Moree1669ed2010-07-12 13:10:27 -03001150 if (unlikely(pDevice->bStopTx0Pkt))
1151 dev_kfree_skb_irq(skb);
1152 else
1153 vDMA0_tx_80211(pDevice, skb);
Forest Bond92b96792009-06-13 07:38:31 -04001154
Andres Moree1669ed2010-07-12 13:10:27 -03001155 spin_unlock_irq(&pDevice->lock);
Forest Bond92b96792009-06-13 07:38:31 -04001156
Andres Moree1669ed2010-07-12 13:10:27 -03001157 return NETDEV_TX_OK;
Forest Bond92b96792009-06-13 07:38:31 -04001158}
1159
Andres More529e5b32010-07-12 19:28:25 -03001160static int device_xmit(struct sk_buff *skb, struct net_device *dev)
1161{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001162 struct vnt_private *pDevice = netdev_priv(dev);
Andres More529e5b32010-07-12 19:28:25 -03001163 struct net_device_stats *stats = &pDevice->stats;
Forest Bond92b96792009-06-13 07:38:31 -04001164
Andres More529e5b32010-07-12 19:28:25 -03001165 spin_lock_irq(&pDevice->lock);
Forest Bond92b96792009-06-13 07:38:31 -04001166
Andres More529e5b32010-07-12 19:28:25 -03001167 netif_stop_queue(dev);
Forest Bond92b96792009-06-13 07:38:31 -04001168
Andres More529e5b32010-07-12 19:28:25 -03001169 if (!pDevice->bLinkPass) {
1170 dev_kfree_skb_irq(skb);
1171 goto out;
1172 }
Forest Bond92b96792009-06-13 07:38:31 -04001173
Andres More529e5b32010-07-12 19:28:25 -03001174 if (pDevice->bStopDataPkt) {
1175 dev_kfree_skb_irq(skb);
1176 stats->tx_dropped++;
1177 goto out;
1178 }
Forest Bond92b96792009-06-13 07:38:31 -04001179
Andres More529e5b32010-07-12 19:28:25 -03001180 if (nsDMA_tx_packet(pDevice, TYPE_AC0DMA, skb)) {
1181 if (netif_queue_stopped(dev))
1182 netif_wake_queue(dev);
1183 }
Forest Bond92b96792009-06-13 07:38:31 -04001184
Andres More529e5b32010-07-12 19:28:25 -03001185out:
1186 spin_unlock_irq(&pDevice->lock);
Forest Bond92b96792009-06-13 07:38:31 -04001187
Andres More529e5b32010-07-12 19:28:25 -03001188 return NETDEV_TX_OK;
Forest Bond92b96792009-06-13 07:38:31 -04001189}
1190
Forest Bond92b96792009-06-13 07:38:31 -04001191static unsigned const ethernet_polynomial = 0x04c11db7U;
1192static inline u32 ether_crc(int length, unsigned char *data)
1193{
1194 int crc = -1;
1195
1196 while(--length >= 0) {
1197 unsigned char current_octet = *data++;
1198 int bit;
1199 for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
1200 crc = (crc << 1) ^
1201 ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
1202 }
1203 }
1204 return crc;
1205}
1206
Andres Moreec6e0f62013-01-31 18:23:07 -05001207/* find out the start position of str2 from str1 */
Andres Morecc856e62010-05-17 21:34:01 -03001208static unsigned char *kstrstr(const unsigned char *str1,
1209 const unsigned char *str2) {
1210 int str1_len = strlen(str1);
1211 int str2_len = strlen(str2);
Forest Bond92b96792009-06-13 07:38:31 -04001212
1213 while (str1_len >= str2_len) {
1214 str1_len--;
1215 if(memcmp(str1,str2,str2_len)==0)
Andres Morecc856e62010-05-17 21:34:01 -03001216 return (unsigned char *) str1;
Forest Bond92b96792009-06-13 07:38:31 -04001217 str1++;
1218 }
1219 return NULL;
1220}
1221
Andres Morecc856e62010-05-17 21:34:01 -03001222static int Config_FileGetParameter(unsigned char *string,
1223 unsigned char *dest,
1224 unsigned char *source)
Forest Bond92b96792009-06-13 07:38:31 -04001225{
Andres Morecc856e62010-05-17 21:34:01 -03001226 unsigned char buf1[100];
1227 unsigned char buf2[100];
1228 unsigned char *start_p = NULL, *end_p = NULL, *tmp_p = NULL;
Forest Bond92b96792009-06-13 07:38:31 -04001229 int ii;
1230
1231 memset(buf1,0,100);
1232 strcat(buf1, string);
1233 strcat(buf1, "=");
1234 source+=strlen(buf1);
1235
Andres Moreec6e0f62013-01-31 18:23:07 -05001236 /* find target string start point */
Joe Perchesbfbfeec2010-03-24 22:17:06 -07001237 start_p = kstrstr(source,buf1);
1238 if (start_p == NULL)
Andres Moree269fc22013-02-12 20:36:29 -05001239 return false;
Forest Bond92b96792009-06-13 07:38:31 -04001240
Andres Moreec6e0f62013-01-31 18:23:07 -05001241 /* check if current config line is marked by "#" */
Andres More33d33e422010-05-19 23:50:00 -03001242 for (ii = 1; ; ii++) {
1243 if (memcmp(start_p - ii, "\n", 1) == 0)
1244 break;
1245 if (memcmp(start_p - ii, "#", 1) == 0)
Andres Moree269fc22013-02-12 20:36:29 -05001246 return false;
Andres More33d33e422010-05-19 23:50:00 -03001247 }
Forest Bond92b96792009-06-13 07:38:31 -04001248
Andres Moreec6e0f62013-01-31 18:23:07 -05001249 /* find target string end point */
Joe Perchesbfbfeec2010-03-24 22:17:06 -07001250 end_p = kstrstr(start_p,"\n");
Andres Moreec6e0f62013-01-31 18:23:07 -05001251 if (end_p == NULL) { /* can't find "\n", but don't care */
1252 end_p = start_p + strlen(start_p); /* no include "\n" */
1253 }
Forest Bond92b96792009-06-13 07:38:31 -04001254
1255 memset(buf2,0,100);
Andres Moreec6e0f62013-01-31 18:23:07 -05001256 memcpy(buf2, start_p, end_p-start_p); /* get the target line */
Forest Bond92b96792009-06-13 07:38:31 -04001257 buf2[end_p-start_p]='\0';
1258
Andres Moreec6e0f62013-01-31 18:23:07 -05001259 /* find value */
Joe Perchesbfbfeec2010-03-24 22:17:06 -07001260 start_p = kstrstr(buf2,"=");
1261 if (start_p == NULL)
Andres Moree269fc22013-02-12 20:36:29 -05001262 return false;
Forest Bond92b96792009-06-13 07:38:31 -04001263 memset(buf1,0,100);
1264 strcpy(buf1,start_p+1);
1265
Andres Moreec6e0f62013-01-31 18:23:07 -05001266 /* except space */
Forest Bond92b96792009-06-13 07:38:31 -04001267 tmp_p = buf1;
1268 while(*tmp_p != 0x00) {
1269 if(*tmp_p==' ')
1270 tmp_p++;
1271 else
1272 break;
1273 }
1274
1275 memcpy(dest,tmp_p,strlen(tmp_p));
Andres More4e9b5e22013-02-12 20:36:30 -05001276 return true;
Forest Bond92b96792009-06-13 07:38:31 -04001277}
1278
Andres Moreec6e0f62013-01-31 18:23:07 -05001279/* if read fails, return NULL, or return data pointer */
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001280static unsigned char *Config_FileOperation(struct vnt_private *pDevice)
Andres Morecc856e62010-05-17 21:34:01 -03001281{
Al Viro7c51d172013-04-06 18:00:07 -04001282 unsigned char *buffer = kmalloc(1024, GFP_KERNEL);
1283 struct file *file;
Andres Moreec6e0f62013-01-31 18:23:07 -05001284
Al Viro7c51d172013-04-06 18:00:07 -04001285 if (!buffer) {
1286 printk("allocate mem for file fail?\n");
1287 return NULL;
1288 }
Forest Bond92b96792009-06-13 07:38:31 -04001289
Al Viro7c51d172013-04-06 18:00:07 -04001290 file = filp_open(CONFIG_PATH, O_RDONLY, 0);
1291 if (IS_ERR(file)) {
1292 kfree(buffer);
1293 printk("Config_FileOperation file Not exist\n");
1294 return NULL;
1295 }
Forest Bond92b96792009-06-13 07:38:31 -04001296
Al Viro7c51d172013-04-06 18:00:07 -04001297 if (kernel_read(file, 0, buffer, 1024) < 0) {
1298 printk("read file error?\n");
1299 kfree(buffer);
1300 buffer = NULL;
1301 }
Forest Bond92b96792009-06-13 07:38:31 -04001302
Al Viro7c51d172013-04-06 18:00:07 -04001303 fput(file);
1304 return buffer;
Forest Bond92b96792009-06-13 07:38:31 -04001305}
1306
Andres Moreec6e0f62013-01-31 18:23:07 -05001307/* return --->-1:fail; >=0:successful */
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001308static int Read_config_file(struct vnt_private *pDevice)
1309{
1310 int result = 0;
1311 unsigned char tmpbuffer[100];
1312 unsigned char *buffer = NULL;
Forest Bond92b96792009-06-13 07:38:31 -04001313
Andres Moreec6e0f62013-01-31 18:23:07 -05001314 /* init config setting */
Forest Bond92b96792009-06-13 07:38:31 -04001315 pDevice->config_file.ZoneType = -1;
1316 pDevice->config_file.eAuthenMode = -1;
1317 pDevice->config_file.eEncryptionStatus = -1;
1318
Joe Perchesbfbfeec2010-03-24 22:17:06 -07001319 buffer = Config_FileOperation(pDevice);
1320 if (buffer == NULL) {
Forest Bond92b96792009-06-13 07:38:31 -04001321 result =-1;
1322 return result;
1323 }
1324
Andres Moreec6e0f62013-01-31 18:23:07 -05001325/* get zonetype */
Forest Bond92b96792009-06-13 07:38:31 -04001326{
1327 memset(tmpbuffer,0,sizeof(tmpbuffer));
Andres More4e9b5e22013-02-12 20:36:30 -05001328 if(Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer) ==true) {
Forest Bond92b96792009-06-13 07:38:31 -04001329 if(memcmp(tmpbuffer,"USA",3)==0) {
1330 pDevice->config_file.ZoneType=ZoneType_USA;
1331 }
1332 else if(memcmp(tmpbuffer,"JAPAN",5)==0) {
1333 pDevice->config_file.ZoneType=ZoneType_Japan;
1334 }
1335 else if(memcmp(tmpbuffer,"EUROPE",6)==0) {
1336 pDevice->config_file.ZoneType=ZoneType_Europe;
1337 }
1338 else {
1339 printk("Unknown Zonetype[%s]?\n",tmpbuffer);
1340 }
1341 }
1342}
1343
Andres Moreec6e0f62013-01-31 18:23:07 -05001344/* get other parameter */
Forest Bond92b96792009-06-13 07:38:31 -04001345 {
1346 memset(tmpbuffer,0,sizeof(tmpbuffer));
Andres More4e9b5e22013-02-12 20:36:30 -05001347 if(Config_FileGetParameter("AUTHENMODE",tmpbuffer,buffer)==true) {
Forest Bond92b96792009-06-13 07:38:31 -04001348 pDevice->config_file.eAuthenMode = (int) simple_strtol(tmpbuffer, NULL, 10);
1349 }
1350
1351 memset(tmpbuffer,0,sizeof(tmpbuffer));
Andres More4e9b5e22013-02-12 20:36:30 -05001352 if(Config_FileGetParameter("ENCRYPTIONMODE",tmpbuffer,buffer)==true) {
Forest Bond92b96792009-06-13 07:38:31 -04001353 pDevice->config_file.eEncryptionStatus= (int) simple_strtol(tmpbuffer, NULL, 10);
1354 }
1355 }
Forest Bond92b96792009-06-13 07:38:31 -04001356
1357 kfree(buffer);
1358 return result;
1359}
1360
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001361static void device_set_multi(struct net_device *dev)
1362{
1363 struct vnt_private *pDevice = netdev_priv(dev);
1364 struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
1365 struct netdev_hw_addr *ha;
1366 u32 mc_filter[2];
1367 int ii;
1368 u8 pbyData[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1369 u8 byTmpMode = 0;
1370 int rc;
Forest Bond92b96792009-06-13 07:38:31 -04001371
Forest Bond92b96792009-06-13 07:38:31 -04001372 spin_lock_irq(&pDevice->lock);
1373 rc = CONTROLnsRequestIn(pDevice,
1374 MESSAGE_TYPE_READ,
1375 MAC_REG_RCR,
1376 MESSAGE_REQUEST_MACREG,
1377 1,
1378 &byTmpMode
1379 );
1380 if (rc == 0) pDevice->byRxMode = byTmpMode;
1381
1382 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode in= %x\n", pDevice->byRxMode);
1383
Andres Moreec6e0f62013-01-31 18:23:07 -05001384 if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
Forest Bond92b96792009-06-13 07:38:31 -04001385 DBG_PRT(MSG_LEVEL_ERR,KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
Andres Moreec6e0f62013-01-31 18:23:07 -05001386 /* unconditionally log net taps */
Forest Bond92b96792009-06-13 07:38:31 -04001387 pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST);
1388 }
Jiri Pirko4cd24ea2010-02-08 04:30:35 +00001389 else if ((netdev_mc_count(dev) > pDevice->multicast_limit) ||
1390 (dev->flags & IFF_ALLMULTI)) {
Forest Bond92b96792009-06-13 07:38:31 -04001391 CONTROLnsRequestOut(pDevice,
1392 MESSAGE_TYPE_WRITE,
1393 MAC_REG_MAR0,
1394 MESSAGE_REQUEST_MACREG,
1395 8,
1396 pbyData
1397 );
1398 pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
1399 }
1400 else {
1401 memset(mc_filter, 0, sizeof(mc_filter));
Jiri Pirko22bedad32010-04-01 21:22:57 +00001402 netdev_for_each_mc_addr(ha, dev) {
1403 int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
Forest Bond92b96792009-06-13 07:38:31 -04001404 mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
1405 }
1406 for (ii = 0; ii < 4; ii++) {
Andres Moreb902fbf2013-02-25 20:32:51 -05001407 MACvWriteMultiAddr(pDevice, ii, *((u8 *)&mc_filter[0] + ii));
1408 MACvWriteMultiAddr(pDevice, ii+ 4, *((u8 *)&mc_filter[1] + ii));
Forest Bond92b96792009-06-13 07:38:31 -04001409 }
1410 pDevice->byRxMode &= ~(RCR_UNICAST);
1411 pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
1412 }
1413
1414 if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
Andres Moreec6e0f62013-01-31 18:23:07 -05001415 /*
1416 * If AP mode, don't enable RCR_UNICAST since HW only compares
1417 * addr1 with local MAC
1418 */
Forest Bond92b96792009-06-13 07:38:31 -04001419 pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST);
1420 pDevice->byRxMode &= ~(RCR_UNICAST);
1421 }
1422 ControlvWriteByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, pDevice->byRxMode);
1423 DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode out= %x\n", pDevice->byRxMode);
1424 spin_unlock_irq(&pDevice->lock);
1425
1426}
1427
Malcolm Priestley7055a072012-11-24 14:44:29 +00001428static struct net_device_stats *device_get_stats(struct net_device *dev)
1429{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001430 struct vnt_private *pDevice = netdev_priv(dev);
Forest Bond92b96792009-06-13 07:38:31 -04001431
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001432 return &pDevice->stats;
Forest Bond92b96792009-06-13 07:38:31 -04001433}
1434
Malcolm Priestley7055a072012-11-24 14:44:29 +00001435static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1436{
Malcolm Priestleydd0a7742012-12-10 21:59:10 +00001437 struct vnt_private *pDevice = netdev_priv(dev);
Forest Bond92b96792009-06-13 07:38:31 -04001438 struct iwreq *wrq = (struct iwreq *) rq;
Malcolm Priestley848ce512012-11-13 21:04:36 +00001439 int rc = 0;
Forest Bond92b96792009-06-13 07:38:31 -04001440
Malcolm Priestley7055a072012-11-24 14:44:29 +00001441 switch (cmd) {
Forest Bond92b96792009-06-13 07:38:31 -04001442
Malcolm Priestley7055a072012-11-24 14:44:29 +00001443 case IOCTL_CMD_HOSTAPD:
Forest Bond92b96792009-06-13 07:38:31 -04001444
Malcolm Priestley7055a072012-11-24 14:44:29 +00001445 if (!(pDevice->flags & DEVICE_FLAGS_OPENED))
1446 rc = -EFAULT;
Forest Bond92b96792009-06-13 07:38:31 -04001447
Forest Bondc30d7972010-04-17 11:03:38 -04001448 rc = vt6656_hostap_ioctl(pDevice, &wrq->u.data);
Malcolm Priestley7055a072012-11-24 14:44:29 +00001449 break;
Forest Bond92b96792009-06-13 07:38:31 -04001450
Forest Bond92b96792009-06-13 07:38:31 -04001451 case SIOCETHTOOL:
Malcolm Priestley7055a072012-11-24 14:44:29 +00001452 return ethtool_ioctl(dev, (void *) rq->ifr_data);
Forest Bond92b96792009-06-13 07:38:31 -04001453
Malcolm Priestley7055a072012-11-24 14:44:29 +00001454 }
Forest Bond92b96792009-06-13 07:38:31 -04001455
Malcolm Priestley7055a072012-11-24 14:44:29 +00001456 return rc;
Forest Bond92b96792009-06-13 07:38:31 -04001457}
1458
Forest Bond92b96792009-06-13 07:38:31 -04001459static int ethtool_ioctl(struct net_device *dev, void *useraddr)
1460{
1461 u32 ethcmd;
1462
1463 if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
1464 return -EFAULT;
1465
1466 switch (ethcmd) {
1467 case ETHTOOL_GDRVINFO: {
1468 struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
1469 strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1);
1470 strncpy(info.version, DEVICE_VERSION, sizeof(info.version)-1);
1471 if (copy_to_user(useraddr, &info, sizeof(info)))
1472 return -EFAULT;
1473 return 0;
1474 }
1475
1476 }
1477
1478 return -EOPNOTSUPP;
1479}
1480
Andres More26e5b652010-04-13 19:43:07 -03001481MODULE_DEVICE_TABLE(usb, vt6656_table);
Forest Bond92b96792009-06-13 07:38:31 -04001482
Andres More26e5b652010-04-13 19:43:07 -03001483static struct usb_driver vt6656_driver = {
1484 .name = DEVICE_NAME,
1485 .probe = vt6656_probe,
1486 .disconnect = vt6656_disconnect,
1487 .id_table = vt6656_table,
Forest Bond92b96792009-06-13 07:38:31 -04001488#ifdef CONFIG_PM
Andres More26e5b652010-04-13 19:43:07 -03001489 .suspend = vt6656_suspend,
1490 .resume = vt6656_resume,
1491#endif /* CONFIG_PM */
Forest Bond92b96792009-06-13 07:38:31 -04001492};
1493
Greg Kroah-Hartmanbac2c122011-11-18 09:42:11 -08001494module_usb_driver(vt6656_driver);