diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/staging/vt6655/device_main.c | |
Diffstat (limited to 'drivers/staging/vt6655/device_main.c')
| -rw-r--r-- | drivers/staging/vt6655/device_main.c | 3405 |
1 files changed, 3405 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c new file mode 100644 index 00000000..d170b6f9 --- /dev/null +++ b/drivers/staging/vt6655/device_main.c @@ -0,0 +1,3405 @@ +/* + * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * File: device_main.c + * + * Purpose: driver entry for initial, open, close, tx and rx. + * + * Author: Lyndon Chen + * + * Date: Jan 8, 2003 + * + * Functions: + * + * vt6655_probe - module initial (insmod) driver entry + * vt6655_remove - module remove entry + * vt6655_init_info - device structure resource allocation function + * device_free_info - device structure resource free function + * device_get_pci_info - get allocated pci io/mem resource + * device_print_info - print out resource + * device_open - allocate dma/descripter resource & initial mac/bbp function + * device_xmit - asynchrous data tx function + * device_intr - interrupt handle function + * device_set_multi - set mac filter + * device_ioctl - ioctl entry + * device_close - shutdown mac/bbp & free dma/descripter resource + * device_rx_srv - rx service function + * device_receive_frame - rx data function + * device_alloc_rx_buf - rx buffer pre-allocated function + * device_alloc_frag_buf - rx fragement pre-allocated function + * device_free_tx_buf - free tx buffer function + * device_free_frag_buf- free de-fragement buffer + * device_dma0_tx_80211- tx 802.11 frame via dma0 + * device_dma0_xmit- tx PS bufferred frame via dma0 + * device_init_rd0_ring- initial rd dma0 ring + * device_init_rd1_ring- initial rd dma1 ring + * device_init_td0_ring- initial tx dma0 ring buffer + * device_init_td1_ring- initial tx dma1 ring buffer + * device_init_registers- initial MAC & BBP & RF internal registers. + * device_init_rings- initial tx/rx ring buffer + * device_init_defrag_cb- initial & allocate de-fragement buffer. + * device_free_rings- free all allocated ring buffer + * device_tx_srv- tx interrupt service function + * + * Revision History: + */ +#undef __NO_VERSION__ + +#include <linux/file.h> +#include "device.h" +#include "card.h" +#include "channel.h" +#include "baseband.h" +#include "mac.h" +#include "tether.h" +#include "wmgr.h" +#include "wctl.h" +#include "power.h" +#include "wcmd.h" +#include "iocmd.h" +#include "tcrc.h" +#include "rxtx.h" +#include "wroute.h" +#include "bssdb.h" +#include "hostap.h" +#include "wpactl.h" +#include "ioctl.h" +#include "iwctl.h" +#include "dpc.h" +#include "datarate.h" +#include "rf.h" +#include "iowpa.h" +#include <linux/delay.h> +#include <linux/kthread.h> +#include <linux/slab.h> + +/*--------------------- Static Definitions -------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel = MSG_LEVEL_INFO; + +// +// Define module options +// +MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); + +static int mlme_kill; +//static struct task_struct * mlme_task; + +#define DEVICE_PARAM(N, D) +/* + static const int N[MAX_UINTS]=OPTION_DEFAULT;\ + MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\ + MODULE_PARM_DESC(N, D); +*/ + +#define RX_DESC_MIN0 16 +#define RX_DESC_MAX0 128 +#define RX_DESC_DEF0 32 +DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0"); + +#define RX_DESC_MIN1 16 +#define RX_DESC_MAX1 128 +#define RX_DESC_DEF1 32 +DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1"); + +#define TX_DESC_MIN0 16 +#define TX_DESC_MAX0 128 +#define TX_DESC_DEF0 32 +DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0"); + +#define TX_DESC_MIN1 16 +#define TX_DESC_MAX1 128 +#define TX_DESC_DEF1 64 +DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1"); + +#define IP_ALIG_DEF 0 +/* IP_byte_align[] is used for IP header unsigned long byte aligned + 0: indicate the IP header won't be unsigned long byte aligned.(Default) . + 1: indicate the IP header will be unsigned long byte aligned. + In some environment, the IP header should be unsigned long byte aligned, + or the packet will be droped when we receive it. (eg: IPVS) +*/ +DEVICE_PARAM(IP_byte_align, "Enable IP header dword aligned"); + +#define INT_WORKS_DEF 20 +#define INT_WORKS_MIN 10 +#define INT_WORKS_MAX 64 + +DEVICE_PARAM(int_works, "Number of packets per interrupt services"); + +#define CHANNEL_MIN 1 +#define CHANNEL_MAX 14 +#define CHANNEL_DEF 6 + +DEVICE_PARAM(Channel, "Channel number"); + +/* PreambleType[] is the preamble length used for transmit. + 0: indicate allows long preamble type + 1: indicate allows short preamble type +*/ + +#define PREAMBLE_TYPE_DEF 1 + +DEVICE_PARAM(PreambleType, "Preamble Type"); + +#define RTS_THRESH_MIN 512 +#define RTS_THRESH_MAX 2347 +#define RTS_THRESH_DEF 2347 + +DEVICE_PARAM(RTSThreshold, "RTS threshold"); + +#define FRAG_THRESH_MIN 256 +#define FRAG_THRESH_MAX 2346 +#define FRAG_THRESH_DEF 2346 + +DEVICE_PARAM(FragThreshold, "Fragmentation threshold"); + +#define DATA_RATE_MIN 0 +#define DATA_RATE_MAX 13 +#define DATA_RATE_DEF 13 +/* datarate[] index + 0: indicate 1 Mbps 0x02 + 1: indicate 2 Mbps 0x04 + 2: indicate 5.5 Mbps 0x0B + 3: indicate 11 Mbps 0x16 + 4: indicate 6 Mbps 0x0c + 5: indicate 9 Mbps 0x12 + 6: indicate 12 Mbps 0x18 + 7: indicate 18 Mbps 0x24 + 8: indicate 24 Mbps 0x30 + 9: indicate 36 Mbps 0x48 + 10: indicate 48 Mbps 0x60 + 11: indicate 54 Mbps 0x6c + 12: indicate 72 Mbps 0x90 + 13: indicate auto rate +*/ + +DEVICE_PARAM(ConnectionRate, "Connection data rate"); + +#define OP_MODE_DEF 0 + +DEVICE_PARAM(OPMode, "Infrastruct, adhoc, AP mode "); + +/* OpMode[] is used for transmit. + 0: indicate infrastruct mode used + 1: indicate adhoc mode used + 2: indicate AP mode used +*/ + +/* PSMode[] + 0: indicate disable power saving mode + 1: indicate enable power saving mode +*/ + +#define PS_MODE_DEF 0 + +DEVICE_PARAM(PSMode, "Power saving mode"); + +#define SHORT_RETRY_MIN 0 +#define SHORT_RETRY_MAX 31 +#define SHORT_RETRY_DEF 8 + +DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); + +#define LONG_RETRY_MIN 0 +#define LONG_RETRY_MAX 15 +#define LONG_RETRY_DEF 4 + +DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); + +/* BasebandType[] baseband type selected + 0: indicate 802.11a type + 1: indicate 802.11b type + 2: indicate 802.11g type +*/ +#define BBP_TYPE_MIN 0 +#define BBP_TYPE_MAX 2 +#define BBP_TYPE_DEF 2 + +DEVICE_PARAM(BasebandType, "baseband type"); + +/* 80211hEnable[] + 0: indicate disable 802.11h + 1: indicate enable 802.11h +*/ + +#define X80211h_MODE_DEF 0 + +DEVICE_PARAM(b80211hEnable, "802.11h mode"); + +/* 80211hEnable[] + 0: indicate disable 802.11h + 1: indicate enable 802.11h +*/ + +#define DIVERSITY_ANT_DEF 0 + +DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode"); + +// +// Static vars definitions +// + +static int device_nics = 0; +static PSDevice pDevice_Infos = NULL; +static struct net_device *root_device_dev = NULL; + +static CHIP_INFO chip_info_table[] = { + { VT3253, "VIA Networking Solomon-A/B/G Wireless LAN Adapter ", + 256, 1, DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN }, + {0, NULL} +}; + +DEFINE_PCI_DEVICE_TABLE(vt6655_pci_id_table) = { + { PCI_VDEVICE(VIA, 0x3253), (kernel_ulong_t)chip_info_table}, + { 0, } +}; + +/*--------------------- Static Functions --------------------------*/ + +static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); +static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice, PCHIP_INFO); +static void device_free_info(PSDevice pDevice); +static bool device_get_pci_info(PSDevice, struct pci_dev *pcid); +static void device_print_info(PSDevice pDevice); +static struct net_device_stats *device_get_stats(struct net_device *dev); +static void device_init_diversity_timer(PSDevice pDevice); +static int device_open(struct net_device *dev); +static int device_xmit(struct sk_buff *skb, struct net_device *dev); +static irqreturn_t device_intr(int irq, void *dev_instance); +static void device_set_multi(struct net_device *dev); +static int device_close(struct net_device *dev); +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + +#ifdef CONFIG_PM +static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); +static int viawget_suspend(struct pci_dev *pcid, pm_message_t state); +static int viawget_resume(struct pci_dev *pcid); +struct notifier_block device_notifier = { + .notifier_call = device_notify_reboot, + .next = NULL, + .priority = 0, +}; +#endif + +static void device_init_rd0_ring(PSDevice pDevice); +static void device_init_rd1_ring(PSDevice pDevice); +static void device_init_defrag_cb(PSDevice pDevice); +static void device_init_td0_ring(PSDevice pDevice); +static void device_init_td1_ring(PSDevice pDevice); + +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev); +//2008-0714<Add>by Mike Liu +static bool device_release_WPADEV(PSDevice pDevice); + +static int ethtool_ioctl(struct net_device *dev, void *useraddr); +static int device_rx_srv(PSDevice pDevice, unsigned int uIdx); +static int device_tx_srv(PSDevice pDevice, unsigned int uIdx); +static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pDesc); +static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType); +static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc); +static void device_free_td0_ring(PSDevice pDevice); +static void device_free_td1_ring(PSDevice pDevice); +static void device_free_rd0_ring(PSDevice pDevice); +static void device_free_rd1_ring(PSDevice pDevice); +static void device_free_rings(PSDevice pDevice); +static void device_free_frag_buf(PSDevice pDevice); +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, unsigned char *source); + +/*--------------------- Export Variables --------------------------*/ + +/*--------------------- Export Functions --------------------------*/ + +static char *get_chip_name(int chip_id) +{ + int i; + for (i = 0; chip_info_table[i].name != NULL; i++) + if (chip_info_table[i].chip_id == chip_id) + break; + return chip_info_table[i].name; +} + +static void vt6655_remove(struct pci_dev *pcid) +{ + PSDevice pDevice = pci_get_drvdata(pcid); + + if (pDevice == NULL) + return; + device_free_info(pDevice); +} + +/* + static void + device_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) { + if (val==-1) + *opt=def; + else if (val<min || val>max) { + DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" , + devname,name, min,max); + *opt=def; + } else { + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n", + devname, name, val); + *opt=val; + } + } + + static void + device_set_bool_opt(unsigned int *opt, int val,bool def,u32 flag, char* name,char* devname) { + (*opt)&=(~flag); + if (val==-1) + *opt|=(def ? flag : 0); + else if (val<0 || val>1) { + DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE + "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name); + *opt|=(def ? flag : 0); + } else { + DBG_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: set parameter %s to %s\n", + devname,name , val ? "true" : "false"); + *opt|=(val ? flag : 0); + } + } +*/ +static void device_get_options(PSDevice pDevice, int index, char *devname) +{ + POPTIONS pOpts = &(pDevice->sOpts); + + pOpts->nRxDescs0 = RX_DESC_DEF0; + pOpts->nRxDescs1 = RX_DESC_DEF1; + pOpts->nTxDescs[0] = TX_DESC_DEF0; + pOpts->nTxDescs[1] = TX_DESC_DEF1; + pOpts->flags |= DEVICE_FLAGS_IP_ALIGN; + pOpts->int_works = INT_WORKS_DEF; + pOpts->rts_thresh = RTS_THRESH_DEF; + pOpts->frag_thresh = FRAG_THRESH_DEF; + pOpts->data_rate = DATA_RATE_DEF; + pOpts->channel_num = CHANNEL_DEF; + + pOpts->flags |= DEVICE_FLAGS_PREAMBLE_TYPE; + pOpts->flags |= DEVICE_FLAGS_OP_MODE; + //pOpts->flags|=DEVICE_FLAGS_PS_MODE; + pOpts->short_retry = SHORT_RETRY_DEF; + pOpts->long_retry = LONG_RETRY_DEF; + pOpts->bbp_type = BBP_TYPE_DEF; + pOpts->flags |= DEVICE_FLAGS_80211h_MODE; + pOpts->flags |= DEVICE_FLAGS_DiversityANT; +} + +static void +device_set_options(PSDevice pDevice) { + unsigned char abyBroadcastAddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + unsigned char abySNAP_RFC1042[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00}; + unsigned char abySNAP_Bridgetunnel[ETH_ALEN] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8}; + + memcpy(pDevice->abyBroadcastAddr, abyBroadcastAddr, ETH_ALEN); + memcpy(pDevice->abySNAP_RFC1042, abySNAP_RFC1042, ETH_ALEN); + memcpy(pDevice->abySNAP_Bridgetunnel, abySNAP_Bridgetunnel, ETH_ALEN); + + pDevice->uChannel = pDevice->sOpts.channel_num; + pDevice->wRTSThreshold = pDevice->sOpts.rts_thresh; + pDevice->wFragmentationThreshold = pDevice->sOpts.frag_thresh; + pDevice->byShortRetryLimit = pDevice->sOpts.short_retry; + pDevice->byLongRetryLimit = pDevice->sOpts.long_retry; + pDevice->wMaxTransmitMSDULifetime = DEFAULT_MSDU_LIFETIME; + pDevice->byShortPreamble = (pDevice->sOpts.flags & DEVICE_FLAGS_PREAMBLE_TYPE) ? 1 : 0; + pDevice->byOpMode = (pDevice->sOpts.flags & DEVICE_FLAGS_OP_MODE) ? 1 : 0; + pDevice->ePSMode = (pDevice->sOpts.flags & DEVICE_FLAGS_PS_MODE) ? 1 : 0; + pDevice->b11hEnable = (pDevice->sOpts.flags & DEVICE_FLAGS_80211h_MODE) ? 1 : 0; + pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0; + pDevice->uConnectionRate = pDevice->sOpts.data_rate; + if (pDevice->uConnectionRate < RATE_AUTO) pDevice->bFixRate = true; + pDevice->byBBType = pDevice->sOpts.bbp_type; + pDevice->byPacketType = pDevice->byBBType; + +//PLICE_DEBUG-> + pDevice->byAutoFBCtrl = AUTO_FB_0; + //pDevice->byAutoFBCtrl = AUTO_FB_1; +//PLICE_DEBUG<- + pDevice->bUpdateBBVGA = true; + pDevice->byFOETuning = 0; + pDevice->wCTSDuration = 0; + pDevice->byPreambleType = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uChannel= %d\n", (int)pDevice->uChannel); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byOpMode= %d\n", (int)pDevice->byOpMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ePSMode= %d\n", (int)pDevice->ePSMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " wRTSThreshold= %d\n", (int)pDevice->wRTSThreshold); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortRetryLimit= %d\n", (int)pDevice->byShortRetryLimit); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byLongRetryLimit= %d\n", (int)pDevice->byLongRetryLimit); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byPreambleType= %d\n", (int)pDevice->byPreambleType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byShortPreamble= %d\n", (int)pDevice->byShortPreamble); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " uConnectionRate= %d\n", (int)pDevice->uConnectionRate); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " byBBType= %d\n", (int)pDevice->byBBType); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->b11hEnable= %d\n", (int)pDevice->b11hEnable); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " pDevice->bDiversityRegCtlON= %d\n", (int)pDevice->bDiversityRegCtlON); +} + +static void s_vCompleteCurrentMeasure(PSDevice pDevice, unsigned char byResult) +{ + unsigned int ii; + unsigned long dwDuration = 0; + unsigned char byRPI0 = 0; + + for (ii = 1; ii < 8; ii++) { + pDevice->dwRPIs[ii] *= 255; + dwDuration |= *((unsigned short *)(pDevice->pCurrMeasureEID->sReq.abyDuration)); + dwDuration <<= 10; + pDevice->dwRPIs[ii] /= dwDuration; + pDevice->abyRPIs[ii] = (unsigned char)pDevice->dwRPIs[ii]; + byRPI0 += pDevice->abyRPIs[ii]; + } + pDevice->abyRPIs[0] = (0xFF - byRPI0); + + if (pDevice->uNumOfMeasureEIDs == 0) { + VNTWIFIbMeasureReport(pDevice->pMgmt, + true, + pDevice->pCurrMeasureEID, + byResult, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + } else { + VNTWIFIbMeasureReport(pDevice->pMgmt, + false, + pDevice->pCurrMeasureEID, + byResult, + pDevice->byBasicMap, + pDevice->byCCAFraction, + pDevice->abyRPIs + ); + CARDbStartMeasure(pDevice, pDevice->pCurrMeasureEID++, pDevice->uNumOfMeasureEIDs); + } +} + +// +// Initialisation of MAC & BBP registers +// + +static void device_init_registers(PSDevice pDevice, DEVICE_INIT_TYPE InitType) +{ + unsigned int ii; + unsigned char byValue; + unsigned char byValue1; + unsigned char byCCKPwrdBm = 0; + unsigned char byOFDMPwrdBm = 0; + int zonetype = 0; + PSMgmtObject pMgmt = &(pDevice->sMgmtObj); + MACbShutdown(pDevice->PortOffset); + BBvSoftwareReset(pDevice->PortOffset); + + if ((InitType == DEVICE_INIT_COLD) || + (InitType == DEVICE_INIT_DXPL)) { + // Do MACbSoftwareReset in MACvInitialize + MACbSoftwareReset(pDevice->PortOffset); + // force CCK + pDevice->bCCK = true; + pDevice->bAES = false; + pDevice->bProtectMode = false; //Only used in 11g type, sync with ERP IE + pDevice->bNonERPPresent = false; + pDevice->bBarkerPreambleMd = false; + pDevice->wCurrentRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_24M; + pDevice->byTopCCKBasicRate = RATE_1M; + + pDevice->byRevId = 0; //Target to IF pin while programming to RF chip. + + // init MAC + MACvInitialize(pDevice->PortOffset); + + // Get Local ID + VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &(pDevice->byLocalID)); + + spin_lock_irq(&pDevice->lock); + SROMvReadAllContents(pDevice->PortOffset, pDevice->abyEEPROM); + + spin_unlock_irq(&pDevice->lock); + + // Get Channel range + + pDevice->byMinChannel = 1; + pDevice->byMaxChannel = CB_MAX_CHANNEL; + + // Get Antena + byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA); + if (byValue & EEP_ANTINV) + pDevice->bTxRxAntInv = true; + else + pDevice->bTxRxAntInv = false; + + byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + if (byValue == 0) // if not set default is All + byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); + + pDevice->ulDiversityNValue = 100*260;//100*SROMbyReadEmbedded(pDevice->PortOffset, 0x51); + pDevice->ulDiversityMValue = 100*16;//SROMbyReadEmbedded(pDevice->PortOffset, 0x52); + pDevice->byTMax = 1;//SROMbyReadEmbedded(pDevice->PortOffset, 0x53); + pDevice->byTMax2 = 4;//SROMbyReadEmbedded(pDevice->PortOffset, 0x54); + pDevice->ulSQ3TH = 0;//(unsigned long) SROMbyReadEmbedded(pDevice->PortOffset, 0x55); + pDevice->byTMax3 = 64;//SROMbyReadEmbedded(pDevice->PortOffset, 0x56); + + if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { + pDevice->byAntennaCount = 2; + pDevice->byTxAntennaMode = ANT_B; + pDevice->dwTxAntennaSel = 1; + pDevice->dwRxAntennaSel = 1; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + // chester for antenna + byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA); + if ((byValue1 & 0x08) == 0) + pDevice->bDiversityEnable = false;//SROMbyReadEmbedded(pDevice->PortOffset, 0x50); + else + pDevice->bDiversityEnable = true; + } else { + pDevice->bDiversityEnable = false; + pDevice->byAntennaCount = 1; + pDevice->dwTxAntennaSel = 0; + pDevice->dwRxAntennaSel = 0; + if (byValue & EEP_ANTENNA_AUX) { + pDevice->byTxAntennaMode = ANT_A; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_B; + else + pDevice->byRxAntennaMode = ANT_A; + } else { + pDevice->byTxAntennaMode = ANT_B; + if (pDevice->bTxRxAntInv == true) + pDevice->byRxAntennaMode = ANT_A; + else + pDevice->byRxAntennaMode = ANT_B; + } + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n", + pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, (int)pDevice->ulDiversityMValue, pDevice->byTMax, pDevice->byTMax2); + +//#ifdef ZoneType_DefaultSetting +//2008-8-4 <add> by chester +//zonetype initial + pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + zonetype = Config_FileOperation(pDevice, false, NULL); + if (zonetype >= 0) { //read zonetype file ok! + if ((zonetype == 0) && + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x00)) { //for USA + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0B; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :USA\n"); + } else if ((zonetype == 1) && + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x01)) { //for Japan + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x01; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + } else if ((zonetype == 2) && + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] != 0x02)) { //for Europe + pDevice->abyEEPROM[EEP_OFS_ZONETYPE] = 0x02; + pDevice->abyEEPROM[EEP_OFS_MAXCHANNEL] = 0x0D; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Init Zone Type :Europe\n"); + } + + else { + if (zonetype != pDevice->abyEEPROM[EEP_OFS_ZONETYPE]) + printk("zonetype in file[%02x] mismatch with in EEPROM[%02x]\n", zonetype, pDevice->abyEEPROM[EEP_OFS_ZONETYPE]); + else + printk("Read Zonetype file success,use default zonetype setting[%02x]\n", zonetype); + } + } else + printk("Read Zonetype file fail,use default zonetype setting[%02x]\n", SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ZONETYPE)); + + // Get RFType + pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE); + + if ((pDevice->byRFType & RF_EMU) != 0) { + // force change RevID for VT3253 emu + pDevice->byRevId = 0x80; + } + + pDevice->byRFType &= RF_MASK; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRFType = %x\n", pDevice->byRFType); + + if (pDevice->bZoneRegExist == false) { + pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byZoneType = %x\n", pDevice->byZoneType); + + //Init RF module + RFbInit(pDevice); + + //Get Desire Power Value + pDevice->byCurPwr = 0xFF; + pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK); + pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG); + //byCCKPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_CCK_PWR_dBm); + + //byOFDMPwrdBm = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_OFDM_PWR_dBm); + + // Load power Table + + for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { + pDevice->abyCCKPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL)); + if (pDevice->abyCCKPwrTbl[ii + 1] == 0) { + pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr; + } + pDevice->abyOFDMPwrTbl[ii + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL)); + if (pDevice->abyOFDMPwrTbl[ii + 1] == 0) { + pDevice->abyOFDMPwrTbl[ii + 1] = pDevice->byOFDMPwrG; + } + pDevice->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm; + pDevice->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm; + } + //2008-8-4 <add> by chester + //recover 12,13 ,14channel for EUROPE by 11 channel + if (((pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Japan) || + (pDevice->abyEEPROM[EEP_OFS_ZONETYPE] == ZoneType_Europe)) && + (pDevice->byOriginalZonetype == ZoneType_USA)) { + for (ii = 11; ii < 14; ii++) { + pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; + pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; + + } + } + + // Load OFDM A Power Table + for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { //RobertYu:20041224, bug using CB_MAX_CHANNEL + pDevice->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL)); + pDevice->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = SROMbyReadEmbedded(pDevice->PortOffset, (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm)); + } + init_channel_table((void *)pDevice); + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN)); + MACvSelectPage0(pDevice->PortOffset); + } + + // use relative tx timeout and 802.11i D4 + MACvWordRegBitsOn(pDevice->PortOffset, MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); + + // set performance parameter by registry + MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit); + MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit); + + // reset TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); + // enable TSF counter + VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); + + // initialize BBP registers + BBbVT3253Init(pDevice); + + if (pDevice->bUpdateBBVGA) { + pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + pDevice->byBBVGANew = pDevice->byBBVGACurrent; + BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); + } + BBvSetRxAntennaMode(pDevice->PortOffset, pDevice->byRxAntennaMode); + BBvSetTxAntennaMode(pDevice->PortOffset, pDevice->byTxAntennaMode); + + pDevice->byCurrentCh = 0; + + //pDevice->NetworkType = Ndis802_11Automode; + // Set BB and packet type at the same time. + // Set Short Slot Time, xIFS, and RSPINF. + if (pDevice->uConnectionRate == RATE_AUTO) { + pDevice->wCurrentRate = RATE_54M; + } else { + pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate; + } + + // default G Mode + VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_11G); + VNTWIFIbConfigPhyMode(pDevice->pMgmt, PHY_TYPE_AUTO); + + pDevice->bRadioOff = false; + + pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RADIOCTL); + pDevice->bHWRadioOff = false; + + if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) { + // Get GPIO + MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); +//2008-4-14 <add> by chester for led issue +#ifdef FOR_LED_ON_NOTEBOOK + if (pDevice->byGPIO & GPIO0_DATA) { pDevice->bHWRadioOff = true; } + if (!(pDevice->byGPIO & GPIO0_DATA)) { pDevice->bHWRadioOff = false; } + + } + if ((pDevice->bRadioControlOff == true)) { + CARDbRadioPowerOff(pDevice); + } else CARDbRadioPowerOn(pDevice); +#else + if (((pDevice->byGPIO & GPIO0_DATA) && !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) || + (!(pDevice->byGPIO & GPIO0_DATA) && (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) { + pDevice->bHWRadioOff = true; + } + } + if ((pDevice->bHWRadioOff == true) || (pDevice->bRadioControlOff == true)) { + CARDbRadioPowerOff(pDevice); + } + +#endif +} +pMgmt->eScanType = WMAC_SCAN_PASSIVE; +// get Permanent network address +SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); +DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Network address = %pM\n", + pDevice->abyCurrentNetAddr); + +// reset Tx pointer +CARDvSafeResetRx(pDevice); +// reset Rx pointer +CARDvSafeResetTx(pDevice); + +if (pDevice->byLocalID <= REV_ID_VT3253_A1) { + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR); +} + +pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; + +// Turn On Rx DMA +MACvReceive0(pDevice->PortOffset); +MACvReceive1(pDevice->PortOffset); + +// start the adapter +MACvStart(pDevice->PortOffset); + +netif_stop_queue(pDevice->dev); +} + +static void device_init_diversity_timer(PSDevice pDevice) { + init_timer(&pDevice->TimerSQ3Tmax1); + pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice; + pDevice->TimerSQ3Tmax1.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax2); + pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice; + pDevice->TimerSQ3Tmax2.function = (TimerFunction)TimerSQ3CallBack; + pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); + + init_timer(&pDevice->TimerSQ3Tmax3); + pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice; + pDevice->TimerSQ3Tmax3.function = (TimerFunction)TimerState1CallBack; + pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); + + return; +} + +static bool device_release_WPADEV(PSDevice pDevice) +{ + viawget_wpa_header *wpahdr; + int ii = 0; + // wait_queue_head_t Set_wait; + //send device close to wpa_supplicnat layer + if (pDevice->bWPADEVUp == true) { + wpahdr = (viawget_wpa_header *)pDevice->skb->data; + wpahdr->type = VIAWGET_DEVICECLOSE_MSG; + wpahdr->resp_ie_len = 0; + wpahdr->req_ie_len = 0; + skb_put(pDevice->skb, sizeof(viawget_wpa_header)); + pDevice->skb->dev = pDevice->wpadev; + skb_reset_mac_header(pDevice->skb); + pDevice->skb->pkt_type = PACKET_HOST; + pDevice->skb->protocol = htons(ETH_P_802_2); + memset(pDevice->skb->cb, 0, sizeof(pDevice->skb->cb)); + netif_rx(pDevice->skb); + pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + + //wait release WPADEV + // init_waitqueue_head(&Set_wait); + // wait_event_timeout(Set_wait, ((pDevice->wpadev==NULL)&&(pDevice->skb == NULL)),5*HZ); //1s wait + while ((pDevice->bWPADEVUp == true)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 20); //wait 50ms + ii++; + if (ii > 20) + break; + } + } + return true; +} + +static const struct net_device_ops device_netdev_ops = { + .ndo_open = device_open, + .ndo_stop = device_close, + .ndo_do_ioctl = device_ioctl, + .ndo_get_stats = device_get_stats, + .ndo_start_xmit = device_xmit, + .ndo_set_rx_mode = device_set_multi, +}; + +static int +vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) +{ + static bool bFirst = true; + struct net_device *dev = NULL; + PCHIP_INFO pChip_info = (PCHIP_INFO)ent->driver_data; + PSDevice pDevice; + int rc; + if (device_nics++ >= MAX_UINTS) { + printk(KERN_NOTICE DEVICE_NAME ": already found %d NICs\n", device_nics); + return -ENODEV; + } + + dev = alloc_etherdev(sizeof(DEVICE_INFO)); + + pDevice = (PSDevice) netdev_priv(dev); + + if (dev == NULL) { + printk(KERN_ERR DEVICE_NAME ": allocate net device failed \n"); + return -ENOMEM; + } + + // Chain it all together + // SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pcid->dev); + + if (bFirst) { + printk(KERN_NOTICE "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); + printk(KERN_NOTICE "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); + bFirst = false; + } + + vt6655_init_info(pcid, &pDevice, pChip_info); + pDevice->dev = dev; + pDevice->next_module = root_device_dev; + root_device_dev = dev; + + if (pci_enable_device(pcid)) { + device_free_info(pDevice); + return -ENODEV; + } + dev->irq = pcid->irq; + +#ifdef DEBUG + printk("Before get pci_info memaddr is %x\n", pDevice->memaddr); +#endif + if (device_get_pci_info(pDevice, pcid) == false) { + printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device.\n"); + device_free_info(pDevice); + return -ENODEV; + } + +#if 1 + +#ifdef DEBUG + + //pci_read_config_byte(pcid, PCI_BASE_ADDRESS_0, &pDevice->byRevId); + printk("after get pci_info memaddr is %x, io addr is %x,io_size is %d\n", pDevice->memaddr, pDevice->ioaddr, pDevice->io_size); + { + int i; + u32 bar, len; + u32 address[] = { + PCI_BASE_ADDRESS_0, + PCI_BASE_ADDRESS_1, + PCI_BASE_ADDRESS_2, + PCI_BASE_ADDRESS_3, + PCI_BASE_ADDRESS_4, + PCI_BASE_ADDRESS_5, + 0}; + for (i = 0; address[i]; i++) { + //pci_write_config_dword(pcid,address[i], 0xFFFFFFFF); + pci_read_config_dword(pcid, address[i], &bar); + printk("bar %d is %x\n", i, bar); + if (!bar) { + printk("bar %d not implemented\n", i); + continue; + } + if (bar & PCI_BASE_ADDRESS_SPACE_IO) { + /* This is IO */ + + len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF); + len = len & ~(len - 1); + + printk("IO space: len in IO %x, BAR %d\n", len, i); + } else { + len = bar & 0xFFFFFFF0; + len = ~len + 1; + + printk("len in MEM %x, BAR %d\n", len, i); + } + } + } +#endif + +#endif + +#ifdef DEBUG + //return 0; +#endif + pDevice->PortOffset = (unsigned long)ioremap(pDevice->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pDevice->io_size); + //pDevice->PortOffset = (unsigned long)ioremap(pDevice->ioaddr & PCI_BASE_ADDRESS_IO_MASK, pDevice->io_size); + + if (pDevice->PortOffset == 0) { + printk(KERN_ERR DEVICE_NAME ": Failed to IO remapping ..\n"); + device_free_info(pDevice); + return -ENODEV; + } + + rc = pci_request_regions(pcid, DEVICE_NAME); + if (rc) { + printk(KERN_ERR DEVICE_NAME ": Failed to find PCI device\n"); + device_free_info(pDevice); + return -ENODEV; + } + + dev->base_addr = pDevice->ioaddr; +#ifdef PLICE_DEBUG + unsigned char value; + + VNSvInPortB(pDevice->PortOffset+0x4F, &value); + printk("Before write: value is %x\n", value); + //VNSvInPortB(pDevice->PortOffset+0x3F, 0x00); + VNSvOutPortB(pDevice->PortOffset, value); + VNSvInPortB(pDevice->PortOffset+0x4F, &value); + printk("After write: value is %x\n", value); +#endif + +#ifdef IO_MAP + pDevice->PortOffset = pDevice->ioaddr; +#endif + // do reset + if (!MACbSoftwareReset(pDevice->PortOffset)) { + printk(KERN_ERR DEVICE_NAME ": Failed to access MAC hardware..\n"); + device_free_info(pDevice); + return -ENODEV; + } + // initial to reload eeprom + MACvInitialize(pDevice->PortOffset); + MACvReadEtherAddress(pDevice->PortOffset, dev->dev_addr); + + device_get_options(pDevice, device_nics-1, dev->name); + device_set_options(pDevice); + //Mask out the options cannot be set to the chip + pDevice->sOpts.flags &= pChip_info->flags; + + //Enable the chip specified capabilities + pDevice->flags = pDevice->sOpts.flags | (pChip_info->flags & 0xFF000000UL); + pDevice->tx_80211 = device_dma0_tx_80211; + pDevice->sMgmtObj.pAdapter = (void *)pDevice; + pDevice->pMgmt = &(pDevice->sMgmtObj); + + dev->irq = pcid->irq; + dev->netdev_ops = &device_netdev_ops; + + dev->wireless_handlers = (struct iw_handler_def *)&iwctl_handler_def; + + rc = register_netdev(dev); + if (rc) { + printk(KERN_ERR DEVICE_NAME " Failed to register netdev\n"); + device_free_info(pDevice); + return -ENODEV; + } + device_print_info(pDevice); + pci_set_drvdata(pcid, pDevice); + return 0; +} + +static void device_print_info(PSDevice pDevice) +{ + struct net_device *dev = pDevice->dev; + + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n", dev->name, get_chip_name(pDevice->chip_id)); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr); +#ifdef IO_MAP + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx ", (unsigned long)pDevice->ioaddr); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq); +#else + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IO=0x%lx Mem=0x%lx ", + (unsigned long)pDevice->ioaddr, (unsigned long)pDevice->PortOffset); + DBG_PRT(MSG_LEVEL_INFO, KERN_INFO " IRQ=%d \n", pDevice->dev->irq); +#endif +} + +static void vt6655_init_info(struct pci_dev *pcid, PSDevice *ppDevice, + PCHIP_INFO pChip_info) { + PSDevice p; + + memset(*ppDevice, 0, sizeof(DEVICE_INFO)); + + if (pDevice_Infos == NULL) { + pDevice_Infos = *ppDevice; + } else { + for (p = pDevice_Infos; p->next != NULL; p = p->next) + do {} while (0); + p->next = *ppDevice; + (*ppDevice)->prev = p; + } + + (*ppDevice)->pcid = pcid; + (*ppDevice)->chip_id = pChip_info->chip_id; + (*ppDevice)->io_size = pChip_info->io_size; + (*ppDevice)->nTxQueues = pChip_info->nTxQueue; + (*ppDevice)->multicast_limit = 32; + + spin_lock_init(&((*ppDevice)->lock)); +} + +static bool device_get_pci_info(PSDevice pDevice, struct pci_dev *pcid) { + u16 pci_cmd; + u8 b; + unsigned int cis_addr; +#ifdef PLICE_DEBUG + unsigned char pci_config[256]; + unsigned char value = 0x00; + int ii, j; + u16 max_lat = 0x0000; + memset(pci_config, 0x00, 256); +#endif + + pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId); + pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pDevice->SubSystemID); + pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID); + pci_read_config_word(pcid, PCI_COMMAND, (u16 *)&(pci_cmd)); + + pci_set_master(pcid); + + pDevice->memaddr = pci_resource_start(pcid, 0); + pDevice->ioaddr = pci_resource_start(pcid, 1); + +#ifdef DEBUG +// pDevice->ioaddr = pci_resource_start(pcid, 0); +// pDevice->memaddr = pci_resource_start(pcid,1); +#endif + + cis_addr = pci_resource_start(pcid, 2); + + pDevice->pcid = pcid; + + pci_read_config_byte(pcid, PCI_COMMAND, &b); + pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER)); + +#ifdef PLICE_DEBUG + //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat); + //for (ii=0;ii<0xFF;ii++) + //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat); + //max_lat = 0x20; + //pci_write_config_word(pcid,PCI_MAX_LAT,max_lat); + //pci_read_config_word(pcid,PCI_MAX_LAT,&max_lat); + + for (ii = 0; ii < 0xFF; ii++) { + pci_read_config_byte(pcid, ii, &value); + pci_config[ii] = value; + } + for (ii = 0, j = 1; ii < 0x100; ii++, j++) { + if (j % 16 == 0) { + printk("%x:", pci_config[ii]); + printk("\n"); + } else { + printk("%x:", pci_config[ii]); + } + } +#endif + return true; +} + +static void device_free_info(PSDevice pDevice) { + PSDevice ptr; + struct net_device *dev = pDevice->dev; + + ASSERT(pDevice); +//2008-0714-01<Add>by chester + device_release_WPADEV(pDevice); + +//2008-07-21-01<Add>by MikeLiu +//unregister wpadev + if (wpa_set_wpadev(pDevice, 0) != 0) + printk("unregister wpadev fail?\n"); + + if (pDevice_Infos == NULL) + return; + + for (ptr = pDevice_Infos; ptr && (ptr != pDevice); ptr = ptr->next) + do {} while (0); + + if (ptr == pDevice) { + if (ptr == pDevice_Infos) + pDevice_Infos = ptr->next; + else + ptr->prev->next = ptr->next; + } else { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "info struct not found\n"); + return; + } +#ifdef HOSTAP + if (dev) + vt6655_hostap_set_hostapd(pDevice, 0, 0); +#endif + if (dev) + unregister_netdev(dev); + + if (pDevice->PortOffset) + iounmap((void *)pDevice->PortOffset); + + if (pDevice->pcid) + pci_release_regions(pDevice->pcid); + if (dev) + free_netdev(dev); + + if (pDevice->pcid) { + pci_set_drvdata(pDevice->pcid, NULL); + } +} + +static bool device_init_rings(PSDevice pDevice) { + void *vir_pool; + + /*allocate all RD/TD rings a single pool*/ + vir_pool = pci_alloc_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), + &pDevice->pool_dma); + + if (vir_pool == NULL) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s : allocate desc dma memory failed\n", pDevice->dev->name); + return false; + } + + memset(vir_pool, 0, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) + ); + + pDevice->aRD0Ring = vir_pool; + pDevice->aRD1Ring = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); + + pDevice->rd0_pool_dma = pDevice->pool_dma; + pDevice->rd1_pool_dma = pDevice->rd0_pool_dma + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); + + pDevice->tx0_bufs = pci_alloc_consistent(pDevice->pcid, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + &pDevice->tx_bufs_dma0); + + if (pDevice->tx0_bufs == NULL) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: allocate buf dma memory failed\n", pDevice->dev->name); + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), + vir_pool, pDevice->pool_dma + ); + return false; + } + + memset(pDevice->tx0_bufs, 0, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE + ); + + pDevice->td0_pool_dma = pDevice->rd1_pool_dma + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); + + pDevice->td1_pool_dma = pDevice->td0_pool_dma + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); + + // vir_pool: pvoid type + pDevice->apTD0Rings = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); + + pDevice->apTD1Rings = vir_pool + + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); + + pDevice->tx1_bufs = pDevice->tx0_bufs + + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; + + pDevice->tx_beacon_bufs = pDevice->tx1_bufs + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; + + pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs + + CB_BEACON_BUF_SIZE; + + pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 + + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; + + pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; + + return true; +} + +static void device_free_rings(PSDevice pDevice) { + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + + pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) + , + pDevice->aRD0Ring, pDevice->pool_dma + ); + + if (pDevice->tx0_bufs) + pci_free_consistent(pDevice->pcid, + pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + + pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + + CB_BEACON_BUF_SIZE + + CB_MAX_BUF_SIZE, + pDevice->tx0_bufs, pDevice->tx_bufs_dma0 + ); +} + +static void device_init_rd0_ring(PSDevice pDevice) { + int i; + dma_addr_t curr = pDevice->rd0_pool_dma; + PSRxDesc pDesc; + + /* Init the RD0 ring entries */ + for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) { + pDesc = &(pDevice->aRD0Ring[i]); + pDesc->pRDInfo = alloc_rd_info(); + ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n", + pDevice->dev->name); + } + pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]); + pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); + } + + if (i > 0) + pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma); + pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]); +} + +static void device_init_rd1_ring(PSDevice pDevice) { + int i; + dma_addr_t curr = pDevice->rd1_pool_dma; + PSRxDesc pDesc; + + /* Init the RD1 ring entries */ + for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) { + pDesc = &(pDevice->aRD1Ring[i]); + pDesc->pRDInfo = alloc_rd_info(); + ASSERT(pDesc->pRDInfo); + if (!device_alloc_rx_buf(pDevice, pDesc)) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc rx bufs\n", + pDevice->dev->name); + } + pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]); + pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); + } + + if (i > 0) + pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma); + pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]); +} + +static void device_init_defrag_cb(PSDevice pDevice) { + int i; + PSDeFragControlBlock pDeF; + + /* Init the fragment ctl entries */ + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + pDeF = &(pDevice->sRxDFCB[i]); + if (!device_alloc_frag_buf(pDevice, pDeF)) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not alloc frag bufs\n", + pDevice->dev->name); + } + } + pDevice->cbDFCB = CB_MAX_RX_FRAG; + pDevice->cbFreeDFCB = pDevice->cbDFCB; +} + +static void device_free_rd0_ring(PSDevice pDevice) { + int i; + + for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) { + PSRxDesc pDesc = &(pDevice->aRD0Ring[i]); + PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo; + + pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); + + dev_kfree_skb(pRDInfo->skb); + + kfree((void *)pDesc->pRDInfo); + } +} + +static void device_free_rd1_ring(PSDevice pDevice) { + int i; + + for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) { + PSRxDesc pDesc = &(pDevice->aRD1Ring[i]); + PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo; + + pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); + + dev_kfree_skb(pRDInfo->skb); + + kfree((void *)pDesc->pRDInfo); + } +} + +static void device_free_frag_buf(PSDevice pDevice) { + PSDeFragControlBlock pDeF; + int i; + + for (i = 0; i < CB_MAX_RX_FRAG; i++) { + pDeF = &(pDevice->sRxDFCB[i]); + + if (pDeF->skb) + dev_kfree_skb(pDeF->skb); + + } +} + +static void device_init_td0_ring(PSDevice pDevice) { + int i; + dma_addr_t curr; + PSTxDesc pDesc; + + curr = pDevice->td0_pool_dma; + for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) { + pDesc = &(pDevice->apTD0Rings[i]); + pDesc->pTDInfo = alloc_td_info(); + ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { + pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ; + pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ; + } + pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]); + pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); + } + + if (i > 0) + pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma); + pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]); +} + +static void device_init_td1_ring(PSDevice pDevice) { + int i; + dma_addr_t curr; + PSTxDesc pDesc; + + /* Init the TD ring entries */ + curr = pDevice->td1_pool_dma; + for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) { + pDesc = &(pDevice->apTD1Rings[i]); + pDesc->pTDInfo = alloc_td_info(); + ASSERT(pDesc->pTDInfo); + if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { + pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ; + pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ; + } + pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]); + pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); + pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); + } + + if (i > 0) + pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma); + pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]); +} + +static void device_free_td0_ring(PSDevice pDevice) { + int i; + for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) { + PSTxDesc pDesc = &(pDevice->apTD0Rings[i]); + PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; + + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) + pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, + pTDInfo->skb->len, PCI_DMA_TODEVICE); + + if (pTDInfo->skb) + dev_kfree_skb(pTDInfo->skb); + + kfree((void *)pDesc->pTDInfo); + } +} + +static void device_free_td1_ring(PSDevice pDevice) { + int i; + + for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) { + PSTxDesc pDesc = &(pDevice->apTD1Rings[i]); + PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; + + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) + pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, + pTDInfo->skb->len, PCI_DMA_TODEVICE); + + if (pTDInfo->skb) + dev_kfree_skb(pTDInfo->skb); + + kfree((void *)pDesc->pTDInfo); + } +} + +/*-----------------------------------------------------------------*/ + +static int device_rx_srv(PSDevice pDevice, unsigned int uIdx) { + PSRxDesc pRD; + int works = 0; + + for (pRD = pDevice->pCurrRD[uIdx]; + pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST; + pRD = pRD->next) { +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->pCurrRD = %x, works = %d\n", pRD, works); + if (works++ > 15) + break; + if (device_receive_frame(pDevice, pRD)) { + if (!device_alloc_rx_buf(pDevice, pRD)) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: can not allocate rx buf\n", pDevice->dev->name); + break; + } + } + pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; + pDevice->dev->last_rx = jiffies; + } + + pDevice->pCurrRD[uIdx] = pRD; + + return works; +} + +static bool device_alloc_rx_buf(PSDevice pDevice, PSRxDesc pRD) { + PDEVICE_RD_INFO pRDInfo = pRD->pRDInfo; + + pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pRDInfo->skb == NULL) + return false; + ASSERT(pRDInfo->skb); + pRDInfo->skb->dev = pDevice->dev; + pRDInfo->skb_dma = pci_map_single(pDevice->pcid, skb_tail_pointer(pRDInfo->skb), + pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); + *((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */ + + pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz); + pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; + pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz); + pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma); + + return true; +} + +bool device_alloc_frag_buf(PSDevice pDevice, PSDeFragControlBlock pDeF) { + pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); + if (pDeF->skb == NULL) + return false; + ASSERT(pDeF->skb); + pDeF->skb->dev = pDevice->dev; + + return true; +} + +static int device_tx_srv(PSDevice pDevice, unsigned int uIdx) { + PSTxDesc pTD; + bool bFull = false; + int works = 0; + unsigned char byTsr0; + unsigned char byTsr1; + unsigned int uFrameSize, uFIFOHeaderSize; + PSTxBufHead pTxBufHead; + struct net_device_stats *pStats = &pDevice->stats; + struct sk_buff *skb; + unsigned int uNodeIndex; + PSMgmtObject pMgmt = pDevice->pMgmt; + + for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) { + if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC) + break; + if (works++ > 15) + break; + + byTsr0 = pTD->m_td0TD0.byTSR0; + byTsr1 = pTD->m_td0TD0.byTSR1; + + //Only the status of first TD in the chain is correct + if (pTD->m_td1TD1.byTCR & TCR_STP) { + if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) { + uFIFOHeaderSize = pTD->pTDInfo->dwHeaderLength; + uFrameSize = pTD->pTDInfo->dwReqCount - uFIFOHeaderSize; + pTxBufHead = (PSTxBufHead) (pTD->pTDInfo->buf); + // Update the statistics based on the Transmit status + // now, we DONT check TSR0_CDH + + STAvUpdateTDStatCounter(&pDevice->scStatistic, + byTsr0, byTsr1, + (unsigned char *)(pTD->pTDInfo->buf + uFIFOHeaderSize), + uFrameSize, uIdx); + + BSSvUpdateNodeTxCounter(pDevice, + byTsr0, byTsr1, + (unsigned char *)(pTD->pTDInfo->buf), + uFIFOHeaderSize + ); + + if (!(byTsr1 & TSR1_TERR)) { + if (byTsr0 != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X].\n", + (int)uIdx, byTsr1, byTsr0); + } + if ((pTxBufHead->wFragCtl & FRAGCTL_ENDFRAG) != FRAGCTL_NONFRAG) { + pDevice->s802_11Counter.TransmittedFragmentCount++; + } + pStats->tx_packets++; + pStats->tx_bytes += pTD->pTDInfo->skb->len; + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] dropped & tsr1[%02X] tsr0[%02X].\n", + (int)uIdx, byTsr1, byTsr0); + pStats->tx_errors++; + pStats->tx_dropped++; + } + } + + if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { + if (pDevice->bEnableHostapd) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx call back netif.. \n"); + skb = pTD->pTDInfo->skb; + skb->dev = pDevice->apdev; + skb_reset_mac_header(skb); + skb->pkt_type = PACKET_OTHERHOST; + //skb->protocol = htons(ETH_P_802_2); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); + } + } + + if (byTsr1 & TSR1_TERR) { + if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", + (int)uIdx, byTsr1, byTsr0); + } + +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Tx[%d] fail has error. tsr1[%02X] tsr0[%02X].\n", +// (int)uIdx, byTsr1, byTsr0); + + if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) && + (pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)) { + unsigned short wAID; + unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + + skb = pTD->pTDInfo->skb; + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) { + if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); + pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; + // set tx map + wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + pTD->pTDInfo->byFlags &= ~(TD_FLAGS_NETIF_SKB); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "tx_srv:tx fail re-queue sta index= %d, QueCnt= %d\n" + , (int)uNodeIndex, pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt); + pStats->tx_errors--; + pStats->tx_dropped--; + } + } + } + } + device_free_tx_buf(pDevice, pTD); + pDevice->iTDUsed[uIdx]--; + } + } + + if (uIdx == TYPE_AC0DMA) { + // RESERV_AC0DMA reserved for relay + + if (AVAIL_TD(pDevice, uIdx) < RESERV_AC0DMA) { + bFull = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " AC0DMA is Full = %d\n", pDevice->iTDUsed[uIdx]); + } + if (netif_queue_stopped(pDevice->dev) && (bFull == false)) { + netif_wake_queue(pDevice->dev); + } + } + + pDevice->apTailTD[uIdx] = pTD; + + return works; +} + +static void device_error(PSDevice pDevice, unsigned short status) { + if (status & ISR_FETALERR) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR + "%s: Hardware fatal error.\n", + pDevice->dev->name); + netif_stop_queue(pDevice->dev); + del_timer(&pDevice->sTimerCommand); + del_timer(&(pDevice->pMgmt->sTimerSecondCallback)); + pDevice->bCmdRunning = false; + MACbShutdown(pDevice->PortOffset); + return; + } +} + +static void device_free_tx_buf(PSDevice pDevice, PSTxDesc pDesc) { + PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; + struct sk_buff *skb = pTDInfo->skb; + + // pre-allocated buf_dma can't be unmapped. + if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) { + pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len, + PCI_DMA_TODEVICE); + } + + if ((pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) + dev_kfree_skb_irq(skb); + + pTDInfo->skb_dma = 0; + pTDInfo->skb = 0; + pTDInfo->byFlags = 0; +} + +//PLICE_DEBUG -> +void InitRxManagementQueue(PSDevice pDevice) +{ + pDevice->rxManeQueue.packet_num = 0; + pDevice->rxManeQueue.head = pDevice->rxManeQueue.tail = 0; +} +//PLICE_DEBUG<- + +//PLICE_DEBUG -> +int MlmeThread( + void *Context) +{ + PSDevice pDevice = (PSDevice) Context; + PSRxMgmtPacket pRxMgmtPacket; + // int i; + //complete(&pDevice->notify); + + //i = 0; +#if 1 + while (1) { + //down(&pDevice->mlme_semaphore); + // pRxMgmtPacket = DeQueue(pDevice); +#if 1 + spin_lock_irq(&pDevice->lock); + while (pDevice->rxManeQueue.packet_num != 0) { + pRxMgmtPacket = DeQueue(pDevice); + //pDevice; + //DequeueManageObject(pDevice->FirstRecvMngList, pDevice->LastRecvMngList); + vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket); + } + spin_unlock_irq(&pDevice->lock); + if (mlme_kill == 0) + break; + //udelay(200); +#endif + schedule(); + if (mlme_kill == 0) + break; + } + +#endif + return 0; +} + +static int device_open(struct net_device *dev) { + PSDevice pDevice = (PSDevice)netdev_priv(dev); + int i; +#ifdef WPA_SM_Transtatus + extern SWPAResult wpa_Result; +#endif + + pDevice->rx_buf_sz = PKT_BUF_SZ; + if (!device_init_rings(pDevice)) { + return -ENOMEM; + } +//2008-5-13 <add> by chester + i = request_irq(pDevice->pcid->irq, &device_intr, IRQF_SHARED, dev->name, dev); + if (i) + return i; + +#ifdef WPA_SM_Transtatus + memset(wpa_Result.ifname, 0, sizeof(wpa_Result.ifname)); + wpa_Result.proto = 0; + wpa_Result.key_mgmt = 0; + wpa_Result.eap_type = 0; + wpa_Result.authenticated = false; + pDevice->fWPA_Authened = false; +#endif + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device init rd0 ring\n"); + device_init_rd0_ring(pDevice); + device_init_rd1_ring(pDevice); + device_init_defrag_cb(pDevice); + device_init_td0_ring(pDevice); + device_init_td1_ring(pDevice); +// VNTWIFIvSet11h(pDevice->pMgmt, pDevice->b11hEnable); + + if (pDevice->bDiversityRegCtlON) { + device_init_diversity_timer(pDevice); + } + vMgrObjectInit(pDevice); + vMgrTimerInit(pDevice); + +//PLICE_DEBUG-> +#ifdef TASK_LET + tasklet_init(&pDevice->RxMngWorkItem, (void *)MngWorkItem, (unsigned long)pDevice); +#endif +#ifdef THREAD + InitRxManagementQueue(pDevice); + mlme_kill = 0; + mlme_task = kthread_run(MlmeThread, (void *)pDevice, "MLME"); + if (IS_ERR(mlme_task)) { + printk("thread create fail\n"); + return -1; + } + + mlme_kill = 1; +#endif + + //wait_for_completion(&pDevice->notify); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call device_init_registers\n"); + device_init_registers(pDevice, DEVICE_INIT_COLD); + MACvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); + memcpy(pDevice->pMgmt->abyMACAddr, pDevice->abyCurrentNetAddr, ETH_ALEN); + device_set_multi(pDevice->dev); + + // Init for Key Management + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); + add_timer(&(pDevice->pMgmt->sTimerSecondCallback)); + +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + /* + pDevice->bwextstep0 = false; + pDevice->bwextstep1 = false; + pDevice->bwextstep2 = false; + pDevice->bwextstep3 = false; + */ + pDevice->bwextcount = 0; + pDevice->bWPASuppWextEnabled = false; +#endif + pDevice->byReAssocCount = 0; + pDevice->bWPADEVUp = false; + // Patch: if WEP key already set by iwconfig but device not yet open + if ((pDevice->bEncryptionEnable == true) && (pDevice->bTransmitKey == true)) { + KeybSetDefaultKey(&(pDevice->sKey), + (unsigned long)(pDevice->byKeyIndex | (1 << 31)), + pDevice->uKeyLength, + NULL, + pDevice->abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID + ); + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "call MACvIntEnable\n"); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + if (pDevice->pMgmt->eConfigMode == WMAC_CONFIG_AP) { + bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL); + } else { + bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); + } + pDevice->flags |= DEVICE_FLAGS_OPENED; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open success.. \n"); + return 0; +} + +static int device_close(struct net_device *dev) { + PSDevice pDevice = (PSDevice)netdev_priv(dev); + PSMgmtObject pMgmt = pDevice->pMgmt; + //PLICE_DEBUG-> +#ifdef THREAD + mlme_kill = 0; +#endif +//PLICE_DEBUG<- +//2007-1121-02<Add>by EinsnLiu + if (pDevice->bLinkPass) { + bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL); + mdelay(30); + } +#ifdef TxInSleep + del_timer(&pDevice->sTimerTxData); +#endif + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + if (pDevice->bDiversityRegCtlON) { + del_timer(&pDevice->TimerSQ3Tmax1); + del_timer(&pDevice->TimerSQ3Tmax2); + del_timer(&pDevice->TimerSQ3Tmax3); + } + +#ifdef TASK_LET + tasklet_kill(&pDevice->RxMngWorkItem); +#endif + netif_stop_queue(dev); + pDevice->bCmdRunning = false; + MACbShutdown(pDevice->PortOffset); + MACbSoftwareReset(pDevice->PortOffset); + CARDbRadioPowerOff(pDevice); + + pDevice->bLinkPass = false; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + device_free_td0_ring(pDevice); + device_free_td1_ring(pDevice); + device_free_rd0_ring(pDevice); + device_free_rd1_ring(pDevice); + device_free_frag_buf(pDevice); + device_free_rings(pDevice); + BSSvClearNodeDBTable(pDevice, 0); + free_irq(dev->irq, dev); + pDevice->flags &= (~DEVICE_FLAGS_OPENED); + //2008-0714-01<Add>by chester + device_release_WPADEV(pDevice); +//PLICE_DEBUG-> + //tasklet_kill(&pDevice->RxMngWorkItem); +//PLICE_DEBUG<- + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close.. \n"); + return 0; +} + +static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) { + PSDevice pDevice = netdev_priv(dev); + unsigned char *pbMPDU; + unsigned int cbMPDULen = 0; + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211\n"); + spin_lock_irq(&pDevice->lock); + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_tx_80211, td0 <=0\n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pDevice->bStopTx0Pkt == true) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + cbMPDULen = skb->len; + pbMPDU = skb->data; + + vDMA0_tx_80211(pDevice, skb, pbMPDU, cbMPDULen); + + spin_unlock_irq(&pDevice->lock); + + return 0; +} + +bool device_dma0_xmit(PSDevice pDevice, struct sk_buff *skb, unsigned int uNodeIndex) { + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxDesc pHeadTD, pLastTD; + unsigned int cbFrameBodySize; + unsigned int uMACfragNum; + unsigned char byPktType; + bool bNeedEncryption = false; + PSKeyItem pTransmitKey = NULL; + unsigned int cbHeaderSize; + unsigned int ii; + SKeyItem STempKey; +// unsigned char byKeyIndex = 0; + + if (pDevice->bStopTx0Pkt == true) { + dev_kfree_skb_irq(skb); + return false; + } + + if (AVAIL_TD(pDevice, TYPE_TXDMA0) <= 0) { + dev_kfree_skb_irq(skb); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, td0 <=0\n"); + return false; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->uAssocCount == 0) { + dev_kfree_skb_irq(skb); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_dma0_xmit, assocCount = 0\n"); + return false; + } + } + + pHeadTD = pDevice->apCurrTD[TYPE_TXDMA0]; + + pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); + + memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN); + cbFrameBodySize = skb->len - ETH_HLEN; + + // 802.1H + if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) { + cbFrameBodySize += 8; + } + uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader); + + if (uMACfragNum > AVAIL_TD(pDevice, TYPE_TXDMA0)) { + dev_kfree_skb_irq(skb); + return false; + } + byPktType = (unsigned char)pDevice->byPacketType; + + if (pDevice->bFixRate) { + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate; + } + } else { + if (pDevice->uConnectionRate >= RATE_54M) + pDevice->wCurrentRate = RATE_54M; + else + pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate; + } + } else { + pDevice->wCurrentRate = pDevice->pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate; + } + + //preamble type + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + } else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate); + + if (pDevice->wCurrentRate <= RATE_11M) { + byPktType = PK_TYPE_11B; + } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + byPktType = PK_TYPE_11A; + } else { + if (pDevice->bProtectMode == true) { + byPktType = PK_TYPE_11GB; + } else { + byPktType = PK_TYPE_11GA; + } + } + + if (pDevice->bEncryptionEnable == true) + bNeedEncryption = true; + + if (pDevice->bEnableHostWEP) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; + pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; + pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; + pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; + memcpy(pTransmitKey->abyKey, + &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], + pTransmitKey->uKeyLength + ); + } + vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption, + cbFrameBodySize, TYPE_TXDMA0, pHeadTD, + &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex, + &uMACfragNum, + &cbHeaderSize + ); + + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) { + // Disable PS + MACbPSWakeup(pDevice->PortOffset); + } + + pDevice->bPWBitOn = false; + + pLastTD = pHeadTD; + for (ii = 0; ii < uMACfragNum; ii++) { + // Poll Transmit the adapter + wmb(); + pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC; + wmb(); + if (ii == (uMACfragNum - 1)) + pLastTD = pHeadTD; + pHeadTD = pHeadTD->next; + } + + // Save the information needed by the tx interrupt handler + // to complete the Send request + pLastTD->pTDInfo->skb = skb; + pLastTD->pTDInfo->byFlags = 0; + pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB; + + pDevice->apCurrTD[TYPE_TXDMA0] = pHeadTD; + + MACvTransmit0(pDevice->PortOffset); + + return true; +} + +//TYPE_AC0DMA data tx +static int device_xmit(struct sk_buff *skb, struct net_device *dev) { + PSDevice pDevice = netdev_priv(dev); + + PSMgmtObject pMgmt = pDevice->pMgmt; + PSTxDesc pHeadTD, pLastTD; + unsigned int uNodeIndex = 0; + unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + unsigned short wAID; + unsigned int uMACfragNum = 1; + unsigned int cbFrameBodySize; + unsigned char byPktType; + unsigned int cbHeaderSize; + bool bNeedEncryption = false; + PSKeyItem pTransmitKey = NULL; + SKeyItem STempKey; + unsigned int ii; + bool bTKIP_UseGTK = false; + bool bNeedDeAuth = false; + unsigned char *pbyBSSID; + bool bNodeExist = false; + + spin_lock_irq(&pDevice->lock); + if (pDevice->bLinkPass == false) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pDevice->bStopDataPkt) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) { + if (pDevice->uAssocCount == 0) { + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + if (is_multicast_ether_addr((unsigned char *)(skb->data))) { + uNodeIndex = 0; + bNodeExist = true; + if (pMgmt->sNodeDBTable[0].bPSEnable) { + skb_queue_tail(&(pMgmt->sNodeDBTable[0].sTxPSQueue), skb); + pMgmt->sNodeDBTable[0].wEnQueueCnt++; + // set tx map + pMgmt->abyPSTxMap[0] |= byMask[0]; + spin_unlock_irq(&pDevice->lock); + return 0; + } + } else { + if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(skb->data), &uNodeIndex)) { + if (pMgmt->sNodeDBTable[uNodeIndex].bPSEnable) { + skb_queue_tail(&pMgmt->sNodeDBTable[uNodeIndex].sTxPSQueue, skb); + pMgmt->sNodeDBTable[uNodeIndex].wEnQueueCnt++; + // set tx map + wAID = pMgmt->sNodeDBTable[uNodeIndex].wAID; + pMgmt->abyPSTxMap[wAID >> 3] |= byMask[wAID & 7]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set:pMgmt->abyPSTxMap[%d]= %d\n", + (wAID >> 3), pMgmt->abyPSTxMap[wAID >> 3]); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble) { + pDevice->byPreambleType = pDevice->byShortPreamble; + + } else { + pDevice->byPreambleType = PREAMBLE_LONG; + } + bNodeExist = true; + + } + } + + if (bNodeExist == false) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Unknown STA not found in node DB \n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + } + + pHeadTD = pDevice->apCurrTD[TYPE_AC0DMA]; + + pHeadTD->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); + + memcpy(pDevice->sTxEthHeader.abyDstAddr, (unsigned char *)(skb->data), ETH_HLEN); + cbFrameBodySize = skb->len - ETH_HLEN; + // 802.1H + if (ntohs(pDevice->sTxEthHeader.wType) > ETH_DATA_LEN) { + cbFrameBodySize += 8; + } + + if (pDevice->bEncryptionEnable == true) { + bNeedEncryption = true; + // get Transmit key + do { + if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && + (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + pbyBSSID = pDevice->abyBSSID; + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == false) { + // get group key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == true) { + bTKIP_UseGTK = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n"); + break; + } + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get PTK.\n"); + break; + } + } else if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + pbyBSSID = pDevice->sTxEthHeader.abyDstAddr; //TO_DS = 0 and FROM_DS = 0 --> 802.11 MAC Address1 + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS Serach Key: \n"); + for (ii = 0; ii < 6; ii++) + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "%x \n", *(pbyBSSID+ii)); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "\n"); + + // get pairwise key + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, PAIRWISE_KEY, &pTransmitKey) == true) + break; + } + // get group key + pbyBSSID = pDevice->abyBroadcastAddr; + if (KeybGetTransmitKey(&(pDevice->sKey), pbyBSSID, GROUP_KEY, &pTransmitKey) == false) { + pTransmitKey = NULL; + if (pDevice->pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode); + } else + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "NOT IBSS and KEY is NULL. [%d]\n", pDevice->pMgmt->eCurrMode); + } else { + bTKIP_UseGTK = true; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "Get GTK.\n"); + } + } while (false); + } + + if (pDevice->bEnableHostWEP) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_DEBUG "acdma0: STA index %d\n", uNodeIndex); + if (pDevice->bEncryptionEnable == true) { + pTransmitKey = &STempKey; + pTransmitKey->byCipherSuite = pMgmt->sNodeDBTable[uNodeIndex].byCipherSuite; + pTransmitKey->dwKeyIndex = pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex; + pTransmitKey->uKeyLength = pMgmt->sNodeDBTable[uNodeIndex].uWepKeyLength; + pTransmitKey->dwTSC47_16 = pMgmt->sNodeDBTable[uNodeIndex].dwTSC47_16; + pTransmitKey->wTSC15_0 = pMgmt->sNodeDBTable[uNodeIndex].wTSC15_0; + memcpy(pTransmitKey->abyKey, + &pMgmt->sNodeDBTable[uNodeIndex].abyWepKey[0], + pTransmitKey->uKeyLength + ); + } + } + + uMACfragNum = cbGetFragCount(pDevice, pTransmitKey, cbFrameBodySize, &pDevice->sTxEthHeader); + + if (uMACfragNum > AVAIL_TD(pDevice, TYPE_AC0DMA)) { + DBG_PRT(MSG_LEVEL_ERR, KERN_DEBUG "uMACfragNum > AVAIL_TD(TYPE_AC0DMA) = %d\n", uMACfragNum); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + + if (pTransmitKey != NULL) { + if ((pTransmitKey->byCipherSuite == KEY_CTL_WEP) && + (pTransmitKey->uKeyLength == WLAN_WEP232_KEYLEN)) { + uMACfragNum = 1; //WEP256 doesn't support fragment + } + } + + byPktType = (unsigned char)pDevice->byPacketType; + + if (pDevice->bFixRate) { +#ifdef PLICE_DEBUG + printk("Fix Rate: PhyType is %d,ConnectionRate is %d\n", pDevice->eCurrentPHYType, pDevice->uConnectionRate); +#endif + + if (pDevice->eCurrentPHYType == PHY_TYPE_11B) { + if (pDevice->uConnectionRate >= RATE_11M) { + pDevice->wCurrentRate = RATE_11M; + } else { + pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate; + } + } else { + if ((pDevice->eCurrentPHYType == PHY_TYPE_11A) && + (pDevice->uConnectionRate <= RATE_6M)) { + pDevice->wCurrentRate = RATE_6M; + } else { + if (pDevice->uConnectionRate >= RATE_54M) + pDevice->wCurrentRate = RATE_54M; + else + pDevice->wCurrentRate = (unsigned short)pDevice->uConnectionRate; + + } + } + pDevice->byACKRate = (unsigned char) pDevice->wCurrentRate; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + //auto rate + if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { + if (pDevice->eCurrentPHYType != PHY_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } else { + VNTWIFIvGetTxRate(pDevice->pMgmt, + pDevice->sTxEthHeader.abyDstAddr, + &(pDevice->wCurrentRate), + &(pDevice->byACKRate), + &(pDevice->byTopCCKBasicRate), + &(pDevice->byTopOFDMBasicRate)); + + } + } + +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0: pDevice->wCurrentRate = %d \n", pDevice->wCurrentRate); + + if (pDevice->wCurrentRate <= RATE_11M) { + byPktType = PK_TYPE_11B; + } else if (pDevice->eCurrentPHYType == PHY_TYPE_11A) { + byPktType = PK_TYPE_11A; + } else { + if (pDevice->bProtectMode == true) { + byPktType = PK_TYPE_11GB; + } else { + byPktType = PK_TYPE_11GA; + } + } + +//#ifdef PLICE_DEBUG +// printk("FIX RATE:CurrentRate is %d"); +//#endif + + if (bNeedEncryption == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); + if ((pDevice->sTxEthHeader.wType) == TYPE_PKT_802_1x) { + bNeedEncryption = false; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); + if ((pDevice->pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pDevice->pMgmt->eCurrState == WMAC_STATE_ASSOC)) { + if (pTransmitKey == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Don't Find TX KEY\n"); + } else { + if (bTKIP_UseGTK == true) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "error: KEY is GTK!!~~\n"); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + bNeedEncryption = true; + } + } + } + + if (pDevice->byCntMeasure == 2) { + bNeedDeAuth = true; + pDevice->s802_11Counter.TKIPCounterMeasuresInvoked++; + } + + if (pDevice->bEnableHostWEP) { + if ((uNodeIndex != 0) && + (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + bNeedEncryption = true; + } + } + } else { + if (pTransmitKey == NULL) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return no tx key\n"); + dev_kfree_skb_irq(skb); + spin_unlock_irq(&pDevice->lock); + return 0; + } + } + } + + vGenerateFIFOHeader(pDevice, byPktType, pDevice->pbyTmpBuff, bNeedEncryption, + cbFrameBodySize, TYPE_AC0DMA, pHeadTD, + &pDevice->sTxEthHeader, (unsigned char *)skb->data, pTransmitKey, uNodeIndex, + &uMACfragNum, + &cbHeaderSize + ); + + if (MACbIsRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) { + // Disable PS + MACbPSWakeup(pDevice->PortOffset); + } + pDevice->bPWBitOn = false; + + pLastTD = pHeadTD; + for (ii = 0; ii < uMACfragNum; ii++) { + // Poll Transmit the adapter + wmb(); + pHeadTD->m_td0TD0.f1Owner = OWNED_BY_NIC; + wmb(); + if (ii == uMACfragNum - 1) + pLastTD = pHeadTD; + pHeadTD = pHeadTD->next; + } + + // Save the information needed by the tx interrupt handler + // to complete the Send request + pLastTD->pTDInfo->skb = skb; + pLastTD->pTDInfo->byFlags = 0; + pLastTD->pTDInfo->byFlags |= TD_FLAGS_NETIF_SKB; +#ifdef TxInSleep + pDevice->nTxDataTimeCout = 0; //2008-8-21 chester <add> for send null packet +#endif + if (AVAIL_TD(pDevice, TYPE_AC0DMA) <= 1) { + netif_stop_queue(dev); + } + + pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD; +//#ifdef PLICE_DEBUG + if (pDevice->bFixRate) { + printk("FixRate:Rate is %d,TxPower is %d\n", pDevice->wCurrentRate, pDevice->byCurPwr); + } else { + } +//#endif + + { + unsigned char Protocol_Version; //802.1x Authentication + unsigned char Packet_Type; //802.1x Authentication + unsigned char Descriptor_type; + unsigned short Key_info; + bool bTxeapol_key = false; + Protocol_Version = skb->data[ETH_HLEN]; + Packet_Type = skb->data[ETH_HLEN+1]; + Descriptor_type = skb->data[ETH_HLEN+1+1+2]; + Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); + if (pDevice->sTxEthHeader.wType == TYPE_PKT_802_1x) { + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { //802.1x OR eapol-key challenge frame transfer + bTxeapol_key = true; + if ((Descriptor_type == 254) || (Descriptor_type == 2)) { //WPA or RSN + if (!(Key_info & BIT3) && //group-key challenge + (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key + pDevice->fWPA_Authened = true; + if (Descriptor_type == 254) + printk("WPA "); + else + printk("WPA2 "); + printk("Authentication completed!!\n"); + } + } + } + } + } + + MACvTransmitAC0(pDevice->PortOffset); +// DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "acdma0:pDevice->apCurrTD= %p\n", pHeadTD); + + dev->trans_start = jiffies; + + spin_unlock_irq(&pDevice->lock); + return 0; +} + +static irqreturn_t device_intr(int irq, void *dev_instance) { + struct net_device *dev = dev_instance; + PSDevice pDevice = (PSDevice)netdev_priv(dev); + + int max_count = 0; + unsigned long dwMIBCounter = 0; + PSMgmtObject pMgmt = pDevice->pMgmt; + unsigned char byOrgPageSel = 0; + int handled = 0; + unsigned char byData = 0; + int ii = 0; + unsigned long flags; +// unsigned char byRSSI; + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + + if (pDevice->dwIsr == 0) + return IRQ_RETVAL(handled); + + if (pDevice->dwIsr == 0xffffffff) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dwIsr = 0xffff\n"); + return IRQ_RETVAL(handled); + } + /* + // 2008-05-21 <mark> by Richardtai, we can't read RSSI here, because no packet bound with RSSI + + if ((pDevice->dwIsr & ISR_RXDMA0) && + (pDevice->byLocalID != REV_ID_VT3253_B0) && + (pDevice->bBSSIDFilter == true)) { + // update RSSI + //BBbReadEmbedded(pDevice->PortOffset, 0x3E, &byRSSI); + //pDevice->uCurrRSSI = byRSSI; + } + */ + + handled = 1; + MACvIntDisable(pDevice->PortOffset); + + spin_lock_irqsave(&pDevice->lock, flags); + + //Make sure current page is 0 + VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); + if (byOrgPageSel == 1) { + MACvSelectPage0(pDevice->PortOffset); + } else + byOrgPageSel = 0; + + MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter); + // TBD.... + // Must do this after doing rx/tx, cause ISR bit is slow + // than RD/TD write back + // update ISR counter + STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter); + while (pDevice->dwIsr != 0) { + STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); + MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); + + if (pDevice->dwIsr & ISR_FETALERR) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " ISR_FETALERR \n"); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0); + VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); + device_error(pDevice, pDevice->dwIsr); + } + + if (pDevice->byLocalID > REV_ID_VT3253_B1) { + if (pDevice->dwIsr & ISR_MEASURESTART) { + // 802.11h measure start + pDevice->byOrgChannel = pDevice->byCurrentCh; + VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byOrgRCR)); + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, (RCR_RXALLTYPE | RCR_UNICAST | RCR_BROADCAST | RCR_MULTICAST | RCR_WPAERR)); + MACvSelectPage1(pDevice->PortOffset); + VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR0, &(pDevice->dwOrgMAR0)); + VNSvInPortD(pDevice->PortOffset + MAC_REG_MAR4, &(pDevice->dwOrgMAR4)); + MACvSelectPage0(pDevice->PortOffset); + //xxxx + // WCMDbFlushCommandQueue(pDevice->pMgmt, true); + if (set_channel(pDevice, pDevice->pCurrMeasureEID->sReq.byChannel) == true) { + pDevice->bMeasureInProgress = true; + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_READY); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byBasicMap = 0; + pDevice->byCCAFraction = 0; + for (ii = 0; ii < 8; ii++) { + pDevice->dwRPIs[ii] = 0; + } + } else { + // can not measure because set channel fail + // WCMDbResetCommandQueue(pDevice->pMgmt); + // clear measure control + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_INCAPABLE); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + } + } + if (pDevice->dwIsr & ISR_MEASUREEND) { + // 802.11h measure end + pDevice->bMeasureInProgress = false; + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byOrgRCR); + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, pDevice->dwOrgMAR0); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR4, pDevice->dwOrgMAR4); + VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRBBSTS, &byData); + pDevice->byBasicMap |= (byData >> 4); + VNSvInPortB(pDevice->PortOffset + MAC_REG_CCAFRACTION, &pDevice->byCCAFraction); + VNSvInPortB(pDevice->PortOffset + MAC_REG_MSRCTL, &byData); + // clear measure control + MACvRegBitsOff(pDevice->PortOffset, MAC_REG_MSRCTL, MSRCTL_EN); + MACvSelectPage0(pDevice->PortOffset); + set_channel(pDevice, pDevice->byOrgChannel); + // WCMDbResetCommandQueue(pDevice->pMgmt); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + if (byData & MSRCTL_FINISH) { + // measure success + s_vCompleteCurrentMeasure(pDevice, 0); + } else { + // can not measure because not ready before end of measure time + s_vCompleteCurrentMeasure(pDevice, MEASURE_MODE_LATE); + } + } + if (pDevice->dwIsr & ISR_QUIETSTART) { + do { + ; + } while (CARDbStartQuiet(pDevice) == false); + } + } + + if (pDevice->dwIsr & ISR_TBTT) { + if (pDevice->bEnableFirstQuiet == true) { + pDevice->byQuietStartCount--; + if (pDevice->byQuietStartCount == 0) { + pDevice->bEnableFirstQuiet = false; + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL, (MSRCTL_QUIETTXCHK | MSRCTL_QUIETEN)); + MACvSelectPage0(pDevice->PortOffset); + } + } + if ((pDevice->bChannelSwitch == true) && + (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)) { + pDevice->byChannelSwitchCount--; + if (pDevice->byChannelSwitchCount == 0) { + pDevice->bChannelSwitch = false; + set_channel(pDevice, pDevice->byNewChannel); + VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL); + + } + } + if (pDevice->eOPMode == OP_MODE_ADHOC) { + //pDevice->bBeaconSent = false; + } else { + if ((pDevice->bUpdateBBVGA) && (pDevice->bLinkPass == true) && (pDevice->uCurrRSSI != 0)) { + long ldBm; + + RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); + for (ii = 0; ii < BB_VGA_LEVEL; ii++) { + if (ldBm < pDevice->ldBmThreshold[ii]) { + pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; + break; + } + } + if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { + pDevice->uBBVGADiffCount++; + if (pDevice->uBBVGADiffCount == 1) { + // first VGA diff gain + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount); + } + if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", + (int)ldBm, pDevice->byBBVGANew, pDevice->byBBVGACurrent, (int)pDevice->uBBVGADiffCount); + BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); + } + } else { + pDevice->uBBVGADiffCount = 1; + } + } + } + + pDevice->bBeaconSent = false; + if (pDevice->bEnablePSMode) { + PSbIsNextTBTTWakeUp((void *)pDevice); + } + + if ((pDevice->eOPMode == OP_MODE_AP) || + (pDevice->eOPMode == OP_MODE_ADHOC)) { + MACvOneShotTimer1MicroSec(pDevice->PortOffset, + (pMgmt->wIBSSBeaconPeriod - MAKE_BEACON_RESERVED) << 10); + } + + if (pDevice->eOPMode == OP_MODE_ADHOC && pDevice->pMgmt->wCurrATIMWindow > 0) { + // todo adhoc PS mode + } + + } + + if (pDevice->dwIsr & ISR_BNTX) { + if (pDevice->eOPMode == OP_MODE_ADHOC) { + pDevice->bIsBeaconBufReadySet = false; + pDevice->cbBeaconBufReadySetCnt = 0; + } + + if (pDevice->eOPMode == OP_MODE_AP) { + if (pMgmt->byDTIMCount > 0) { + pMgmt->byDTIMCount--; + pMgmt->sNodeDBTable[0].bRxPSPoll = false; + } else { + if (pMgmt->byDTIMCount == 0) { + // check if mutltcast tx bufferring + pMgmt->byDTIMCount = pMgmt->byDTIMPeriod - 1; + pMgmt->sNodeDBTable[0].bRxPSPoll = true; + bScheduleCommand((void *)pDevice, WLAN_CMD_RX_PSPOLL, NULL); + } + } + } + pDevice->bBeaconSent = true; + + if (pDevice->bChannelSwitch == true) { + pDevice->byChannelSwitchCount--; + if (pDevice->byChannelSwitchCount == 0) { + pDevice->bChannelSwitch = false; + set_channel(pDevice, pDevice->byNewChannel); + VNTWIFIbChannelSwitch(pDevice->pMgmt, pDevice->byNewChannel); + MACvSelectPage1(pDevice->PortOffset); + MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MSRCTL+1, MSRCTL1_TXPAUSE); + MACvSelectPage0(pDevice->PortOffset); + //VNTWIFIbSendBeacon(pDevice->pMgmt); + CARDbStartTxPacket(pDevice, PKT_TYPE_802_11_ALL); + } + } + + } + + if (pDevice->dwIsr & ISR_RXDMA0) { + max_count += device_rx_srv(pDevice, TYPE_RXDMA0); + } + if (pDevice->dwIsr & ISR_RXDMA1) { + max_count += device_rx_srv(pDevice, TYPE_RXDMA1); + } + if (pDevice->dwIsr & ISR_TXDMA0) { + max_count += device_tx_srv(pDevice, TYPE_TXDMA0); + } + if (pDevice->dwIsr & ISR_AC0DMA) { + max_count += device_tx_srv(pDevice, TYPE_AC0DMA); + } + if (pDevice->dwIsr & ISR_SOFTTIMER) { + } + if (pDevice->dwIsr & ISR_SOFTTIMER1) { + if (pDevice->eOPMode == OP_MODE_AP) { + if (pDevice->bShortSlotTime) + pMgmt->wCurrCapInfo |= WLAN_SET_CAP_INFO_SHORTSLOTTIME(1); + else + pMgmt->wCurrCapInfo &= ~(WLAN_SET_CAP_INFO_SHORTSLOTTIME(1)); + } + bMgrPrepareBeaconToSend(pDevice, pMgmt); + pDevice->byCntMeasure = 0; + } + + MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); + + MACvReceive0(pDevice->PortOffset); + MACvReceive1(pDevice->PortOffset); + + if (max_count > pDevice->sOpts.int_works) + break; + } + + if (byOrgPageSel == 1) { + MACvSelectPage1(pDevice->PortOffset); + } + + spin_unlock_irqrestore(&pDevice->lock, flags); + + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + + return IRQ_RETVAL(handled); +} + +static unsigned const ethernet_polynomial = 0x04c11db7U; +static inline u32 ether_crc(int length, unsigned char *data) +{ + int crc = -1; + + while (--length >= 0) { + unsigned char current_octet = *data++; + int bit; + for (bit = 0; bit < 8; bit++, current_octet >>= 1) { + crc = (crc << 1) ^ + ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); + } + } + return crc; +} + +//2008-8-4 <add> by chester +static int Config_FileGetParameter(unsigned char *string, + unsigned char *dest, unsigned char *source) +{ + unsigned char buf1[100]; + int source_len = strlen(source); + + memset(buf1, 0, 100); + strcat(buf1, string); + strcat(buf1, "="); + source += strlen(buf1); + + memcpy(dest, source, source_len - strlen(buf1)); + return true; +} + +int Config_FileOperation(PSDevice pDevice,bool fwrite,unsigned char *Parameter) +{ + unsigned char *buffer = kmalloc(1024, GFP_KERNEL); + unsigned char tmpbuffer[20]; + struct file *file; + int result=0; + + if (!buffer) { + printk("allocate mem for file fail?\n"); + return -1; + } + file = filp_open(CONFIG_PATH, O_RDONLY, 0); + if (IS_ERR(file)) { + kfree(buffer); + printk("Config_FileOperation:open file fail?\n"); + return -1; + } + + if (kernel_read(file, 0, buffer, 1024) < 0) { + printk("read file error?\n"); + result = -1; + goto error1; + } + + if (Config_FileGetParameter("ZONETYPE",tmpbuffer,buffer)!=true) { + printk("get parameter error?\n"); + result = -1; + goto error1; + } + + if (memcmp(tmpbuffer,"USA",3)==0) { + result = ZoneType_USA; + } else if(memcmp(tmpbuffer,"JAPAN",5)==0) { + result = ZoneType_Japan; + } else if(memcmp(tmpbuffer,"EUROPE",5)==0) { + result = ZoneType_Europe; + } else { + result = -1; + printk("Unknown Zonetype[%s]?\n",tmpbuffer); + } + +error1: + kfree(buffer); + fput(file); + return result; +} + +static void device_set_multi(struct net_device *dev) { + PSDevice pDevice = (PSDevice)netdev_priv(dev); + + PSMgmtObject pMgmt = pDevice->pMgmt; + u32 mc_filter[2]; + struct netdev_hw_addr *ha; + + VNSvInPortB(pDevice->PortOffset + MAC_REG_RCR, &(pDevice->byRxMode)); + + if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ + DBG_PRT(MSG_LEVEL_ERR, KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name); + /* Unconditionally log net taps. */ + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST|RCR_UNICAST); + } else if ((netdev_mc_count(dev) > pDevice->multicast_limit) + || (dev->flags & IFF_ALLMULTI)) { + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, 0xffffffff); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, 0xffffffff); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } else { + memset(mc_filter, 0, sizeof(mc_filter)); + netdev_for_each_mc_addr(ha, dev) { + int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; + mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31)); + } + MACvSelectPage1(pDevice->PortOffset); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0, mc_filter[0]); + VNSvOutPortD(pDevice->PortOffset + MAC_REG_MAR0 + 4, mc_filter[1]); + MACvSelectPage0(pDevice->PortOffset); + pDevice->byRxMode &= ~(RCR_UNICAST); + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + } + + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + // If AP mode, don't enable RCR_UNICAST. Since hw only compare addr1 with local mac. + pDevice->byRxMode |= (RCR_MULTICAST|RCR_BROADCAST); + pDevice->byRxMode &= ~(RCR_UNICAST); + } + + VNSvOutPortB(pDevice->PortOffset + MAC_REG_RCR, pDevice->byRxMode); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pDevice->byRxMode = %x\n", pDevice->byRxMode); +} + +static struct net_device_stats *device_get_stats(struct net_device *dev) { + PSDevice pDevice = (PSDevice)netdev_priv(dev); + + return &pDevice->stats; +} + +static int device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { + PSDevice pDevice = (PSDevice)netdev_priv(dev); + + struct iwreq *wrq = (struct iwreq *)rq; + int rc = 0; + PSMgmtObject pMgmt = pDevice->pMgmt; + PSCmdRequest pReq; + + if (pMgmt == NULL) { + rc = -EFAULT; + return rc; + } + + switch (cmd) { + case SIOCGIWNAME: + rc = iwctl_giwname(dev, NULL, (char *)&(wrq->u.name), NULL); + break; + + case SIOCGIWNWID: //0x8b03 support + rc = -EOPNOTSUPP; + break; + + // Set frequency/channel + case SIOCSIWFREQ: + rc = iwctl_siwfreq(dev, NULL, &(wrq->u.freq), NULL); + break; + + // Get frequency/channel + case SIOCGIWFREQ: + rc = iwctl_giwfreq(dev, NULL, &(wrq->u.freq), NULL); + break; + + // Set desired network name (ESSID) + case SIOCSIWESSID: + + { + char essid[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) { + rc = -E2BIG; + break; + } + if (copy_from_user(essid, wrq->u.essid.pointer, + wrq->u.essid.length)) { + rc = -EFAULT; + break; + } + rc = iwctl_siwessid(dev, NULL, + &(wrq->u.essid), essid); + } + break; + + // Get current network name (ESSID) + case SIOCGIWESSID: + + { + char essid[IW_ESSID_MAX_SIZE+1]; + if (wrq->u.essid.pointer) + rc = iwctl_giwessid(dev, NULL, + &(wrq->u.essid), essid); + if (copy_to_user(wrq->u.essid.pointer, + essid, + wrq->u.essid.length)) + rc = -EFAULT; + } + break; + + case SIOCSIWAP: + + rc = iwctl_siwap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + // Get current Access Point (BSSID) + case SIOCGIWAP: + rc = iwctl_giwap(dev, NULL, &(wrq->u.ap_addr), NULL); + break; + + // Set desired station name + case SIOCSIWNICKN: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWNICKN \n"); + rc = -EOPNOTSUPP; + break; + + // Get current station name + case SIOCGIWNICKN: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWNICKN \n"); + rc = -EOPNOTSUPP; + break; + + // Set the desired bit-rate + case SIOCSIWRATE: + rc = iwctl_siwrate(dev, NULL, &(wrq->u.bitrate), NULL); + break; + + // Get the current bit-rate + case SIOCGIWRATE: + + rc = iwctl_giwrate(dev, NULL, &(wrq->u.bitrate), NULL); + break; + + // Set the desired RTS threshold + case SIOCSIWRTS: + + rc = iwctl_siwrts(dev, NULL, &(wrq->u.rts), NULL); + break; + + // Get the current RTS threshold + case SIOCGIWRTS: + + rc = iwctl_giwrts(dev, NULL, &(wrq->u.rts), NULL); + break; + + // Set the desired fragmentation threshold + case SIOCSIWFRAG: + + rc = iwctl_siwfrag(dev, NULL, &(wrq->u.frag), NULL); + break; + + // Get the current fragmentation threshold + case SIOCGIWFRAG: + + rc = iwctl_giwfrag(dev, NULL, &(wrq->u.frag), NULL); + break; + + // Set mode of operation + case SIOCSIWMODE: + rc = iwctl_siwmode(dev, NULL, &(wrq->u.mode), NULL); + break; + + // Get mode of operation + case SIOCGIWMODE: + rc = iwctl_giwmode(dev, NULL, &(wrq->u.mode), NULL); + break; + + // Set WEP keys and mode + case SIOCSIWENCODE: { + char abyKey[WLAN_WEP232_KEYLEN]; + + if (wrq->u.encoding.pointer) { + if (wrq->u.encoding.length > WLAN_WEP232_KEYLEN) { + rc = -E2BIG; + break; + } + memset(abyKey, 0, WLAN_WEP232_KEYLEN); + if (copy_from_user(abyKey, + wrq->u.encoding.pointer, + wrq->u.encoding.length)) { + rc = -EFAULT; + break; + } + } else if (wrq->u.encoding.length != 0) { + rc = -EINVAL; + break; + } + rc = iwctl_siwencode(dev, NULL, &(wrq->u.encoding), abyKey); + } + break; + + // Get the WEP keys and mode + case SIOCGIWENCODE: + + if (!capable(CAP_NET_ADMIN)) { + rc = -EPERM; + break; + } + { + char abyKey[WLAN_WEP232_KEYLEN]; + + rc = iwctl_giwencode(dev, NULL, &(wrq->u.encoding), abyKey); + if (rc != 0) break; + if (wrq->u.encoding.pointer) { + if (copy_to_user(wrq->u.encoding.pointer, + abyKey, + wrq->u.encoding.length)) + rc = -EFAULT; + } + } + break; + + // Get the current Tx-Power + case SIOCGIWTXPOW: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWTXPOW \n"); + rc = -EOPNOTSUPP; + break; + + case SIOCSIWTXPOW: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWTXPOW \n"); + rc = -EOPNOTSUPP; + break; + + case SIOCSIWRETRY: + + rc = iwctl_siwretry(dev, NULL, &(wrq->u.retry), NULL); + break; + + case SIOCGIWRETRY: + + rc = iwctl_giwretry(dev, NULL, &(wrq->u.retry), NULL); + break; + + // Get range of parameters + case SIOCGIWRANGE: + + { + struct iw_range range; + + rc = iwctl_giwrange(dev, NULL, &(wrq->u.data), (char *)&range); + if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range))) + rc = -EFAULT; + } + + break; + + case SIOCGIWPOWER: + + rc = iwctl_giwpower(dev, NULL, &(wrq->u.power), NULL); + break; + + case SIOCSIWPOWER: + + rc = iwctl_siwpower(dev, NULL, &(wrq->u.power), NULL); + break; + + case SIOCGIWSENS: + + rc = iwctl_giwsens(dev, NULL, &(wrq->u.sens), NULL); + break; + + case SIOCSIWSENS: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSENS \n"); + rc = -EOPNOTSUPP; + break; + + case SIOCGIWAPLIST: { + char buffer[IW_MAX_AP * (sizeof(struct sockaddr) + sizeof(struct iw_quality))]; + + if (wrq->u.data.pointer) { + rc = iwctl_giwaplist(dev, NULL, &(wrq->u.data), buffer); + if (rc == 0) { + if (copy_to_user(wrq->u.data.pointer, + buffer, + (wrq->u.data.length * (sizeof(struct sockaddr) + sizeof(struct iw_quality))) + )) + rc = -EFAULT; + } + } + } + break; + +#ifdef WIRELESS_SPY + // Set the spy list + case SIOCSIWSPY: + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWSPY \n"); + rc = -EOPNOTSUPP; + break; + + // Get the spy list + case SIOCGIWSPY: + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSPY \n"); + rc = -EOPNOTSUPP; + break; + +#endif // WIRELESS_SPY + + case SIOCGIWPRIV: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWPRIV \n"); + rc = -EOPNOTSUPP; +/* + if (wrq->u.data.pointer) { + wrq->u.data.length = sizeof(iwctl_private_args) / sizeof(iwctl_private_args[0]); + + if (copy_to_user(wrq->u.data.pointer, + (u_char *) iwctl_private_args, + sizeof(iwctl_private_args))) + rc = -EFAULT; + } +*/ + break; + +//2008-0409-07, <Add> by Einsn Liu +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + case SIOCSIWAUTH: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWAUTH \n"); + rc = iwctl_siwauth(dev, NULL, &(wrq->u.param), NULL); + break; + + case SIOCGIWAUTH: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWAUTH \n"); + rc = iwctl_giwauth(dev, NULL, &(wrq->u.param), NULL); + break; + + case SIOCSIWGENIE: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWGENIE \n"); + rc = iwctl_siwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + + case SIOCGIWGENIE: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWGENIE \n"); + rc = iwctl_giwgenie(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + + case SIOCSIWENCODEEXT: { + char extra[sizeof(struct iw_encode_ext)+MAX_KEY_LEN+1]; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWENCODEEXT \n"); + if (wrq->u.encoding.pointer) { + memset(extra, 0, sizeof(struct iw_encode_ext)+MAX_KEY_LEN + 1); + if (wrq->u.encoding.length > (sizeof(struct iw_encode_ext) + MAX_KEY_LEN)) { + rc = -E2BIG; + break; + } + if (copy_from_user(extra, wrq->u.encoding.pointer, wrq->u.encoding.length)) { + rc = -EFAULT; + break; + } + } else if (wrq->u.encoding.length != 0) { + rc = -EINVAL; + break; + } + rc = iwctl_siwencodeext(dev, NULL, &(wrq->u.encoding), extra); + } + break; + + case SIOCGIWENCODEEXT: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWENCODEEXT \n"); + rc = iwctl_giwencodeext(dev, NULL, &(wrq->u.encoding), NULL); + break; + + case SIOCSIWMLME: + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWMLME \n"); + rc = iwctl_siwmlme(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); + break; + +#endif // #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT +//End Add -- //2008-0409-07, <Add> by Einsn Liu + + case IOCTL_CMD_TEST: + + if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { + rc = -EFAULT; + break; + } else { + rc = 0; + } + pReq = (PSCmdRequest)rq; + pReq->wResult = MAGIC_CODE; + break; + + case IOCTL_CMD_SET: + +#ifdef SndEvt_ToAPI + if ((((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_EVT) && + !(pDevice->flags & DEVICE_FLAGS_OPENED)) +#else + if (!(pDevice->flags & DEVICE_FLAGS_OPENED) && + (((PSCmdRequest)rq)->wCmdCode != WLAN_CMD_SET_WPA)) +#endif + { + rc = -EFAULT; + break; + } else { + rc = 0; + } + + if (test_and_set_bit(0, (void *)&(pMgmt->uCmdBusy))) { + return -EBUSY; + } + rc = private_ioctl(pDevice, rq); + clear_bit(0, (void *)&(pMgmt->uCmdBusy)); + break; + + case IOCTL_CMD_HOSTAPD: + + rc = vt6655_hostap_ioctl(pDevice, &wrq->u.data); + break; + + case IOCTL_CMD_WPA: + + rc = wpa_ioctl(pDevice, &wrq->u.data); + break; + + case SIOCETHTOOL: + return ethtool_ioctl(dev, (void *)rq->ifr_data); + // All other calls are currently unsupported + + default: + rc = -EOPNOTSUPP; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Ioctl command not support..%x\n", cmd); + + } + + if (pDevice->bCommit) { + if (pMgmt->eConfigMode == WMAC_CONFIG_AP) { + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + bScheduleCommand((void *)pDevice, WLAN_CMD_RUN_AP, NULL); + spin_unlock_irq(&pDevice->lock); + } else { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Commit the settings\n"); + spin_lock_irq(&pDevice->lock); + pDevice->bLinkPass = false; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + netif_stop_queue(pDevice->dev); +#ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT + pMgmt->eScanType = WMAC_SCAN_ACTIVE; + if (pDevice->bWPASuppWextEnabled != true) +#endif + bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, pMgmt->abyDesireSSID); + bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + } + pDevice->bCommit = false; + } + + return rc; +} + +static int ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; + strncpy(info.driver, DEVICE_NAME, sizeof(info.driver)-1); + strncpy(info.version, DEVICE_VERSION, sizeof(info.version)-1); + if (copy_to_user(useraddr, &info, sizeof(info))) + return -EFAULT; + return 0; + } + + } + + return -EOPNOTSUPP; +} + +/*------------------------------------------------------------------*/ + +MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); + +static struct pci_driver device_driver = { + .name = DEVICE_NAME, + .id_table = vt6655_pci_id_table, + .probe = vt6655_probe, + .remove = vt6655_remove, +#ifdef CONFIG_PM + .suspend = viawget_suspend, + .resume = viawget_resume, +#endif +}; + +static int __init vt6655_init_module(void) +{ + int ret; + +// ret=pci_module_init(&device_driver); + //ret = pcie_port_service_register(&device_driver); + ret = pci_register_driver(&device_driver); +#ifdef CONFIG_PM + if (ret >= 0) + register_reboot_notifier(&device_notifier); +#endif + + return ret; +} + +static void __exit vt6655_cleanup_module(void) +{ +#ifdef CONFIG_PM + unregister_reboot_notifier(&device_notifier); +#endif + pci_unregister_driver(&device_driver); +} + +module_init(vt6655_init_module); +module_exit(vt6655_cleanup_module); + +#ifdef CONFIG_PM +static int +device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) +{ + struct pci_dev *pdev = NULL; + switch (event) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + for_each_pci_dev(pdev) { + if (pci_dev_driver(pdev) == &device_driver) { + if (pci_get_drvdata(pdev)) + viawget_suspend(pdev, PMSG_HIBERNATE); + } + } + } + return NOTIFY_DONE; +} + +static int +viawget_suspend(struct pci_dev *pcid, pm_message_t state) +{ + int power_status; // to silence the compiler + + PSDevice pDevice = pci_get_drvdata(pcid); + PSMgmtObject pMgmt = pDevice->pMgmt; + + netif_stop_queue(pDevice->dev); + spin_lock_irq(&pDevice->lock); + pci_save_state(pcid); + del_timer(&pDevice->sTimerCommand); + del_timer(&pMgmt->sTimerSecondCallback); + pDevice->cbFreeCmdQueue = CMD_Q_SIZE; + pDevice->uCmdDequeueIdx = 0; + pDevice->uCmdEnqueueIdx = 0; + pDevice->bCmdRunning = false; + MACbShutdown(pDevice->PortOffset); + MACvSaveContext(pDevice->PortOffset, pDevice->abyMacContext); + pDevice->bLinkPass = false; + memset(pMgmt->abyCurrBSSID, 0, 6); + pMgmt->eCurrState = WMAC_STATE_IDLE; + pci_disable_device(pcid); + power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state)); + spin_unlock_irq(&pDevice->lock); + return 0; +} + +static int +viawget_resume(struct pci_dev *pcid) +{ + PSDevice pDevice = pci_get_drvdata(pcid); + PSMgmtObject pMgmt = pDevice->pMgmt; + int power_status; // to silence the compiler + + power_status = pci_set_power_state(pcid, 0); + power_status = pci_enable_wake(pcid, 0, 0); + pci_restore_state(pcid); + if (netif_running(pDevice->dev)) { + spin_lock_irq(&pDevice->lock); + MACvRestoreContext(pDevice->PortOffset, pDevice->abyMacContext); + device_init_registers(pDevice, DEVICE_INIT_DXPL); + if (pMgmt->sNodeDBTable[0].bActive == true) { // Assoc with BSS + pMgmt->sNodeDBTable[0].bActive = false; + pDevice->bLinkPass = false; + if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) { + // In Adhoc, BSS state set back to started. + pMgmt->eCurrState = WMAC_STATE_STARTED; + } else { + pMgmt->eCurrMode = WMAC_MODE_STANDBY; + pMgmt->eCurrState = WMAC_STATE_IDLE; + } + } + init_timer(&pMgmt->sTimerSecondCallback); + init_timer(&pDevice->sTimerCommand); + MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); + BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass); + bScheduleCommand((void *)pDevice, WLAN_CMD_BSSID_SCAN, NULL); + bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL); + spin_unlock_irq(&pDevice->lock); + } + return 0; +} + +#endif |
