diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/Makefile 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/Makefile --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/Makefile 2006-05-24 14:48:14.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/Makefile 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,12 @@ -# # File : app/Makefile # # (c) Copyright © 2003-2006, Marvell International Ltd. -# All Rights Reserved # # This software file (the "File") is distributed by Marvell International # Ltd. under the terms of the GNU General Public License Version 2, June 1991 # (the "License"). You may use, redistribute and/or modify this File in # accordance with the terms and conditions of the License, a copy of which -# is available along with the File in the license.txt file or by writing to +# is available along with the File in the gpl.txt file or by writing to # the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. # @@ -47,12 +47,9 @@ # All rule compiles list of TARGETS using builtin program target from src rule all : $(TARGETS) -# Install rule; INSTALLPATH calculated above from passed INSTALLDIR variable -$(INSTALLPATH)/% : ./% - @cp -f $< $@ - -# Map build and install invocation to the install rule for each TARGET file -build install: $(addprefix $(INSTALLPATH)/, $(TARGETS)) +# Update any needed TARGETS and then copy to the install path +build install: $(TARGETS) + @cp -f $< $(INSTALLPATH) clean: @rm -f $(TARGETS) diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/wlanconfig.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/wlanconfig.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/wlanconfig.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/wlanconfig.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,16 +1,13 @@ /** @file wlanconfig.c * @brief Program to configure addition paramters into the wlan driver * - * Usage: wlanconfig [...] - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -33,6 +30,9 @@ 04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 05/03/06: Add auto_tx hostcmd + 05/15/06: Support EMBEDDED_TCPIP with Linux 2.6.9 + 08/28/06: Add LED_CTRL hostcmd ********************************************************/ #include @@ -49,14 +49,9 @@ #include #include #include +#include -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; -typedef unsigned long long u64; -typedef char s8; -typedef short s16; -typedef long s32; +#define WLANCONFIG_VER "2.03" /* wlanconfig Version number */ #ifdef BYTE_SWAP #define cpu_to_le16(x) __swab16(x) @@ -81,9 +76,11 @@ #undef BIG_ENDIAN #endif -#include "wlan_defs.h" #include "wlan_types.h" +#include "wlan_defs.h" +#include "wlan_wmm.h" #include "wlan_11d.h" + #include "host.h" #include "hostcmd.h" #include "wlan_scan.h" @@ -94,7 +91,8 @@ #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif /* MIN */ -enum COMMANDS { +enum COMMANDS +{ CMD_HOSTCMD, CMD_RDMAC, CMD_WRMAC, @@ -107,19 +105,42 @@ CMD_CMD52W, CMD_CMD53R, CMD_CMD53W, - CMD_CFREGR, - CMD_CFREGW, - CMD_GETRATE, + CMD_BG_SCAN_CONFIG, + CMD_ADDTS, + CMD_DELTS, + CMD_QCONFIG, + CMD_QSTATS, + CMD_WMM_QSTATUS, + CMD_TX_PKT_STATS, + CMD_CAL_DATA_EXT, CMD_SLEEPPARAMS, CMD_BCA_TS, CMD_EXTSCAN, CMD_SCAN_LIST, + CMD_SET_GEN_IE, CMD_GET_SCAN_RSP, CMD_SET_USER_SCAN, + CMD_SET_MRVL_TLV, + CMD_GET_ASSOC_RSP, + CMD_GET_TSF, + CMD_HS_TEST, + CMD_GET_CFP_TABLE, + CMD_ARPFILTER, }; #define IW_MAX_PRIV_DEF 128 +#define MAX_MSG_SIZE 1024 + +enum HS_STATE +{ + HS_STATE_DEACTIVATED, + HS_STATE_ACTIVATED, + HS_STATE_GPIO_INT, +}; + +static int hs_state = HS_STATE_DEACTIVATED; + /******************************************************** Local Variables ********************************************************/ @@ -136,27 +157,50 @@ "sdcmd52w", "sdcmd53r", "sdcmd53w", - "rdcfreg", - "wrcfreg", - "getrate", + "bgscanconfig", + "addts", + "delts", + "qconfig", + "qstats", + "qstatus", + "txpktstats", + "caldataext", "sleepparams", "bca-ts", "extscan", "getscanlist", + "setgenie", "getscantable", "setuserscan", + "setmrvltlv", + "getassocrsp", + "gettsf", + "hstest", + "getcfptable", + "arpfilter", }; static s8 *usage[] = { - "Usage: wlanconfig [...]", + "Usage: ", + " wlanconfig -v (version)", + " wlanconfig [...]", "where", " ethX : wireless network interface", " cmd : hostcmd, rdmac, wrmac, rdbbp, wrbbp, rdrf, wrrf", " : sdcmd52r, sdcmd52w, sdcmd53r", - " : caldataext, rdcfreg, wrcfreg, rdeeprom", - " : sleepparams, bca-ts", - " : setadhocch, getadhocch", + " : caldataext", + " : rdeeprom, sleepparams", + " : bca-ts", + " : bgscanconfig", + " : qstatus", + " : addts, delts, qconfig, qstats", + " : txpktstats", + " : setgenie", " : getscantable, setuserscan", + " : setmrvltlv, getassocrsp", + " : hstest", + " : getcfptable", + " : arpfilter", " [...] : additional parameters for read registers are", " : ", " : additional parameters for write registers are", @@ -165,6 +209,8 @@ " : ", " : addition parameters for caldataext", " : ", + " : additonal parameter for arpfilter", + " : ", }; static s32 sockfd; @@ -174,7 +220,36 @@ #define MRV_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) +static u16 TLVChanSize; +static u16 TLVSsidSize; +static u16 TLVProbeSize; +static u16 TLVSnrSize; +static u16 TLVBcProbeSize; +static u16 TLVNumSsidProbeSize; +static u16 TLVStartBGScanLaterSize; +static u16 ActualPos = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG); + +char rate_bitmap[16][16] = + { "1", "2", "5.5", "11", "reserved", "6", "9", "12", "18", "24", "36", +"48", "54", "reserved", "reserved", "reserved" }; +char fw_state[9][32] = { "Disconnected", + "Scanning", + "Connected-Awake", + "Connected-Sleep", + "Deep Sleep", + "Connected-Single", + "Disconnected-Link Loss", + "Disconnected-Disassociated", + "Exception" +}; +char led_state[3][16] = { "Steady OFF", + "Steady ON", + "Blinking" +}; +char led_duty_factor[5][8] = { "1/2", "1/4", "1/8", "1/16", "1/32" }; +char led_blink_period[6][8] = + { "37ms", "74ms", "149ms", "298ms", "596ms", "1192ms" }; static s8 * wlan_config_get_line(s8 *s, s32 size, FILE *stream, int *line); @@ -182,7 +257,6 @@ Global Variables ********************************************************/ - /******************************************************** Local Functions ********************************************************/ @@ -192,7 +266,8 @@ * @param chr char to convert * @return hex integer or 0 */ -static int hexval(s32 chr) +static int +hexval(s32 chr) { if (chr >= '0' && chr <= '9') return chr - '0'; @@ -213,19 +288,22 @@ * @param delim delim char * @return hex integer */ -static void hexdump(s8 *prompt, void *p, s32 len, s8 delim) +static void +hexdump(s8 * prompt, void *p, s32 len, s8 delim) { s32 i; u8 *s = p; if (prompt) { - printf("%s: ", prompt); + printf("%s: len=%d\n", prompt, (int) len); } for (i = 0; i < len; i++) { if (i != len - 1) printf("%02x%c", *s++, delim); else printf("%02x\n", *s); + if ((i + 1) % 16 == 0) + printf("\n"); } } @@ -235,7 +313,8 @@ * @param chr char * @return hex integer */ -static u8 hexc2bin(s8 chr) +static u8 +hexc2bin(s8 chr) { if (chr >= '0' && chr <= '9') chr -= '0'; @@ -253,7 +332,8 @@ * @param s A pointer string buffer * @return hex integer */ -static u32 a2hex(s8 *s) +static u32 +a2hex(s8 * s) { u32 val = 0; while (*s && isxdigit(*s)) { @@ -263,21 +343,23 @@ return val; } - /* * @brief convert String to integer * * @param value A pointer to string * @return integer */ -static u32 a2hex_or_atoi(s8 *value) +static u32 +a2hex_or_atoi(s8 * value) { - if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) + if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) { return a2hex(value + 2); - else + } else if (isdigit(*value)) { return atoi(value); + } else { + return *value; + } } - /** * @brief convert string to integer @@ -286,7 +368,8 @@ * @param chr A pointer to return integer * @return A pointer to next data field */ -s8 *convert2hex(s8 *ptr, u8 *chr) +s8 * +convert2hex(s8 * ptr, u8 * chr) { u8 val; @@ -305,7 +388,8 @@ * @param ifname A pointer to net name * @return WLAN_STATUS_SUCCESS--success, otherwise --fail */ -static int get_private_info(const s8 *ifname) +static int +get_private_info(const s8 * ifname) { /* This function sends the SIOCGIWPRIV command which is * handled by the kernel. and gets the total number of @@ -349,10 +433,9 @@ * @param subioctl_val A pointer to return sub-ioctl number * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int marvell_get_subioctl_no(s32 i, - s32 priv_cnt, - int *ioctl_val, - int *subioctl_val) +static int +marvell_get_subioctl_no(s32 i, + s32 priv_cnt, int *ioctl_val, int *subioctl_val) { s32 j; @@ -395,10 +478,9 @@ * @param subioctl_val A pointer to return sub-ioctl number * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int marvell_get_ioctl_no(const s8 *ifname, - const s8 *priv_cmd, - int *ioctl_val, - int *subioctl_val) +static int +marvell_get_ioctl_no(const s8 * ifname, + const s8 * priv_cmd, int *ioctl_val, int *subioctl_val) { s32 i; s32 priv_cnt; @@ -406,7 +488,7 @@ priv_cnt = get_private_info(ifname); /* Are there any private ioctls? */ - if (priv_cnt <= 0) { + if (priv_cnt <= 0 || priv_cnt > IW_MAX_PRIV_DEF) { /* Could skip this message ? */ printf("%-8.8s no private ioctls.\n", ifname); } else { @@ -424,20 +506,19 @@ /** * @brief Retrieve the ioctl and sub-ioctl numbers for the given ioctl string * - * @param ifname Private IOCTL string name + * @param ioctl_name Private IOCTL string name * @param ioctl_val A pointer to return ioctl number * @param subioctl_val A pointer to return sub-ioctl number * * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int get_priv_ioctl(char* ioctl_name, int* ioctl_val, int* subioctl_val) +static int +get_priv_ioctl(char *ioctl_name, int *ioctl_val, int *subioctl_val) { int retval; retval = marvell_get_ioctl_no(dev_name, - ioctl_name, - ioctl_val, - subioctl_val); + ioctl_name, ioctl_val, subioctl_val); #if 0 /* Debug print discovered IOCTL values */ @@ -447,13 +528,13 @@ return retval; } - /** * @brief get range * * @return WLAN_STATUS_SUCCESS--success, otherwise --fail */ -static int get_range(void) +static int +get_range(void) { struct iw_range *range; struct iwreq iwr; @@ -480,50 +561,11 @@ return WLAN_STATUS_FAILURE; } we_version_compiled = range->we_version_compiled; - printf("Driver build with Wireless Extension %d\n",range->we_version_compiled); + printf("Driver build with Wireless Extension %d\n", + range->we_version_compiled); free(range); return WLAN_STATUS_SUCCESS; } -#define WLAN_MAX_RATES 14 -#define GIGA 1e9 -#define MEGA 1e6 -#define KILO 1e3 - -/** - * @brief print bit rate - * - * @param rate rate to be print - * @param current if current is TRUE, data rate not need convert - * @param fixed not used - * @return WLAN_STATUS_SUCCESS - */ -static int print_bitrate(double rate, s32 current, s32 fixed) -{ - s8 scale = 'k', buf[128]; - s32 divisor = KILO; - - if (!current) - rate *= 500000; - - if (rate >= GIGA) { - scale = 'G'; - divisor = GIGA; - } else if (rate >= MEGA) { - scale = 'M'; - divisor = MEGA; - } - - snprintf(buf, sizeof(buf), "%g %cb/s", rate/divisor, scale); - - if (current) { - printf("\t Current Bit Rate%c%s\n\n", - (fixed) ? '=' : ':', buf); - } else { - printf("\t %s\n", buf); - } - - return WLAN_STATUS_SUCCESS; -} /* * @brief get hostcmd data @@ -534,13 +576,13 @@ * @param size A pointer to the return size of hostcmd buffer * @return WLAN_STATUS_SUCCESS */ -static int wlan_get_hostcmd_data(FILE *fp, int *ln, u8 *buf, u16 *size) +static int +wlan_get_hostcmd_data(FILE * fp, int *ln, u8 * buf, u16 * size) { s32 errors = 0, i; s8 line[256], *pos, *pos1, *pos2, *pos3; u16 len; - while ((pos = wlan_config_get_line(line, sizeof(line), fp, ln))) { (*ln)++; if (strcmp(pos, "}") == 0) { @@ -583,8 +625,7 @@ memset(buf, 0, len); memmove(buf, pos2, MIN(strlen(pos2),len)); buf += len; - } - else if (*pos2 == '\'') { + } else if (*pos2 == '\'') { pos2++; if ((pos3=strchr(pos2, '\'')) == NULL) { printf("Line %d: invalid quotation '%s'\n", *ln, pos); @@ -597,19 +638,26 @@ *pos3 = '\0'; *buf++ = (u8)a2hex_or_atoi(pos2); pos2 = pos3 + 1; - } - else + } else *buf++ = 0; } - } - else if (*pos2 == '{') { + } else if (*pos2 == '{') { u16 *tlvlen = (u16 *)buf; wlan_get_hostcmd_data(fp, ln, buf+len, tlvlen); *size += *tlvlen; buf += len + *tlvlen; - } - else { + } else { u32 value = a2hex_or_atoi(pos2); + switch (len) { + case 2: + value = wlan_cpu_to_le16(value); + break; + case 4: + value = wlan_cpu_to_le32(value); + break; + default: + break; + } while (len--) { *buf++ = (u8)(value & 0xff); value >>= 8; @@ -621,34 +669,48 @@ /** * @brief Process host_cmd - * @param hostcmd A pointer to HostCmd_DS_GEN data structure + * @param argc number of arguments + * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_host_cmd(int argc, char *argv[]) +static int +process_host_cmd(int argc, char *argv[]) { s8 line[256], cmdname[256], *pos; u8 *buf; FILE *fp; HostCmd_DS_GEN *hostcmd; - struct ifreq userdata; + struct iwreq iwr; int ln = 0; int cmdname_found = 0, cmdcode_found = 0; int ret = WLAN_STATUS_SUCCESS; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("hostcmd", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } if (argc < 5) { printf("Error: invalid no of arguments\n"); - printf("Syntax: ./wlanconfig eth1 hostcmd \n"); + printf + ("Syntax: ./wlanconfig eth1 hostcmd \n"); exit(1); } if ((fp = fopen(argv[3], "r")) == NULL) { - fprintf(stderr, "Cannot open file %s\n", argv[4]); + fprintf(stderr, "Cannot open file %s\n", argv[3]); exit(1); } buf = (u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + printf("Error: allocate memory for hostcmd failed\n"); + return -ENOMEM; + } + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); - hostcmd = (PHostCmd_DS_GEN)buf; + hostcmd = (HostCmd_DS_GEN *) buf; hostcmd->Command = 0xffff; @@ -664,12 +726,15 @@ cmdcode_found = 1; hostcmd->Command = a2hex_or_atoi(pos+strlen(cmdname)); hostcmd->Size = S_DS_GEN; - wlan_get_hostcmd_data(fp, &ln, buf+hostcmd->Size, &hostcmd->Size); + wlan_get_hostcmd_data(fp, &ln, buf + hostcmd->Size, + &hostcmd->Size); break; } } if (!cmdcode_found) { - fprintf(stderr, "wlanconfig: CmdCode not found in file '%s'\n", argv[3]); + fprintf(stderr, + "wlanconfig: CmdCode not found in file '%s'\n", + argv[3]); } break; } @@ -678,7 +743,8 @@ fclose(fp); if (!cmdname_found) - fprintf(stderr, "wlanconfig: cmdname '%s' not found in file '%s'\n", argv[4],argv[3]); + fprintf(stderr, "wlanconfig: cmdname '%s' not found in file '%s'\n", + argv[4], argv[3]); if (!cmdname_found || !cmdcode_found) { ret = -1; @@ -690,70 +756,144 @@ hostcmd->SeqNum = 0; hostcmd->Result = 0; - strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); - userdata.ifr_data = (u8 *)hostcmd; + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (u8 *) hostcmd; + iwr.u.data.length = hostcmd->Size; - if (ioctl(sockfd, WLANHOSTCMD, &userdata)) { - fprintf(stderr, "wlanconfig: WLANHOSTCMD is not supported by %s\n", dev_name); + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, "wlanconfig: WLANHOSTCMD is not supported by %s\n", + dev_name); ret = -1; goto _exit_; } if (!hostcmd->Result) { switch (hostcmd->Command) { + case HostCmd_RET_MEM_ACCESS: + { + HostCmd_DS_MEM_ACCESS *ma = + (HostCmd_DS_MEM_ACCESS *) (buf + S_DS_GEN); + if (ma->Action == HostCmd_ACT_GET) { + printf("Address: %#08lx Value=%#08lx\n", ma->Addr, + ma->Value); + } + break; + } + case HostCmd_RET_802_11_POWER_ADAPT_CFG_EXT: + { + HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT *pace = + (HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT *) (buf + + S_DS_GEN); + int i, j; + printf("EnablePA=%#04x\n", pace->EnablePA); + for (i = 0; + i < + pace->PowerAdaptGroup.Header.Len / sizeof(PA_Group_t); + i++) { + printf("PA Group #%d: level=%ddbm, Rate Bitmap=%#04x (", + i, + pace->PowerAdaptGroup.PA_Group[i].PowerAdaptLevel, + pace->PowerAdaptGroup.PA_Group[i].RateBitmap); + for (j = + 8 * + sizeof(pace->PowerAdaptGroup.PA_Group[i]. + RateBitmap) - 1; j >= 0; j--) { + if ((j == 4) || (j >= 13)) // reserved + continue; + if (pace->PowerAdaptGroup.PA_Group[i]. + RateBitmap & (1 << j)) + printf("%s ", rate_bitmap[j]); + } + printf("Mbps)\n"); + } + break; + } case HostCmd_RET_802_11_SUBSCRIBE_EVENT: { - HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = (HostCmd_DS_802_11_SUBSCRIBE_EVENT *)(buf + S_DS_GEN); + HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = + (HostCmd_DS_802_11_SUBSCRIBE_EVENT *) (buf + S_DS_GEN); if (se->Action == HostCmd_ACT_GET) { - int len = S_DS_GEN + sizeof(HostCmd_DS_802_11_SUBSCRIBE_EVENT); + int len = + S_DS_GEN + sizeof(HostCmd_DS_802_11_SUBSCRIBE_EVENT); printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n"); while (len < hostcmd->Size) { - MrvlIEtypesHeader_t *header = (MrvlIEtypesHeader_t *)(buf + len); + MrvlIEtypesHeader_t *header = + (MrvlIEtypesHeader_t *) (buf + len); switch (header->Type) { case TLV_TYPE_RSSI_LOW: { - MrvlIEtypes_RssiParamSet_t *LowRssi = (MrvlIEtypes_RssiParamSet_t *)(buf + len); - printf("Low RSSI\t%d\t%d\t%s\n",LowRssi->RSSIValue,LowRssi->RSSIFreq,(se->Events & 0x0001)?"yes":"no"); - len += sizeof(MrvlIEtypes_RssiParamSet_t); + MrvlIEtypes_RssiThreshold_t *LowRssi = + (MrvlIEtypes_RssiThreshold_t *) (buf + + len); + printf("Low RSSI\t%d\t%d\t%s\n", + LowRssi->RSSIValue, LowRssi->RSSIFreq, + (se->Events & 0x0001) ? "yes" : "no"); + len += sizeof(MrvlIEtypes_RssiThreshold_t); break; } case TLV_TYPE_SNR_LOW: { - MrvlIEtypes_SnrThreshold_t *LowSnr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); - printf("Low SNR\t\t%d\t%d\t%s\n",LowSnr->SNRValue,LowSnr->SNRFreq,(se->Events & 0x0002)?"yes":"no"); + MrvlIEtypes_SnrThreshold_t *LowSnr = + (MrvlIEtypes_SnrThreshold_t *) (buf + + len); + printf("Low SNR\t\t%d\t%d\t%s\n", + LowSnr->SNRValue, LowSnr->SNRFreq, + (se->Events & 0x0002) ? "yes" : "no"); len += sizeof(MrvlIEtypes_SnrThreshold_t); break; } case TLV_TYPE_FAILCOUNT: { - MrvlIEtypes_FailureCount_t *FailureCount = (MrvlIEtypes_FailureCount_t *)(buf + len); - printf("Failure Count\t%d\t%d\t%s\n",FailureCount->FailValue,FailureCount->FailFreq,(se->Events & 0x0004)?"yes":"no"); + MrvlIEtypes_FailureCount_t *FailureCount = + (MrvlIEtypes_FailureCount_t *) (buf + + len); + printf("Failure Count\t%d\t%d\t%s\n", + FailureCount->FailValue, + FailureCount->FailFreq, + (se->Events & 0x0004) ? "yes" : "no"); len += sizeof(MrvlIEtypes_FailureCount_t); break; } case TLV_TYPE_BCNMISS: { - MrvlIEtypes_BeaconsMissed_t *BcnMissed = (MrvlIEtypes_BeaconsMissed_t *)(buf + len); - printf("Beacon Missed\t%d\tN/A\t%s\n",BcnMissed->BeaconMissed,(se->Events & 0x0008)?"yes":"no"); + MrvlIEtypes_BeaconsMissed_t *BcnMissed = + (MrvlIEtypes_BeaconsMissed_t *) (buf + + len); + printf("Beacon Missed\t%d\tN/A\t%s\n", + BcnMissed->BeaconMissed, + (se->Events & 0x0008) ? "yes" : "no"); len += sizeof(MrvlIEtypes_BeaconsMissed_t); break; } case TLV_TYPE_RSSI_HIGH: { - MrvlIEtypes_RssiParamSet_t *HighRssi = (MrvlIEtypes_RssiParamSet_t *)(buf + len); - printf("High RSSI\t%d\t%d\t%s\n",HighRssi->RSSIValue,HighRssi->RSSIFreq,(se->Events & 0x0010)?"yes":"no"); - len += sizeof(MrvlIEtypes_RssiParamSet_t); + MrvlIEtypes_RssiThreshold_t *HighRssi = + (MrvlIEtypes_RssiThreshold_t *) (buf + + len); + printf("High RSSI\t%d\t%d\t%s\n", + HighRssi->RSSIValue, + HighRssi->RSSIFreq, + (se->Events & 0x0010) ? "yes" : "no"); + len += sizeof(MrvlIEtypes_RssiThreshold_t); break; } case TLV_TYPE_SNR_HIGH: { - MrvlIEtypes_SnrThreshold_t *HighSnr = (MrvlIEtypes_SnrThreshold_t *)(buf + len); - printf("High SNR\t%d\t%d\t%s\n",HighSnr->SNRValue,HighSnr->SNRFreq,(se->Events & 0x0020)?"yes":"no"); + MrvlIEtypes_SnrThreshold_t *HighSnr = + (MrvlIEtypes_SnrThreshold_t *) (buf + + len); + printf("High SNR\t%d\t%d\t%s\n", + HighSnr->SNRValue, HighSnr->SNRFreq, + (se->Events & 0x0020) ? "yes" : "no"); len += sizeof(MrvlIEtypes_SnrThreshold_t); break; } default: - printf("unknown subscribed event TLV Type=%#x, Len=%d\n", header->Type, header->Len); + printf + ("unknown subscribed event TLV Type=%#x, Len=%d\n", + header->Type, header->Len); len += sizeof(MrvlIEtypesHeader_t) + header->Len; break; } @@ -761,63 +901,127 @@ } break; } - default: - printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n",hostcmd->Command,hostcmd->Result); - break; + case HostCmd_RET_802_11_AUTO_TX: + { + HostCmd_DS_802_11_AUTO_TX *at = + (HostCmd_DS_802_11_AUTO_TX *) (buf + S_DS_GEN); + if (at->Action == HostCmd_ACT_GET) { + if (S_DS_GEN + sizeof(at->Action) == hostcmd->Size) { + printf("auto_tx not configured\n"); + } else { + MrvlIEtypesHeader_t *header = &at->AutoTx.Header; + if ((S_DS_GEN + sizeof(at->Action) + + sizeof(MrvlIEtypesHeader_t) + header->Len == + hostcmd->Size) && + (header->Type == TLV_TYPE_AUTO_TX)) { + AutoTx_MacFrame_t *atmf = + &at->AutoTx.AutoTx_MacFrame; + + printf("Interval: %d second(s)\n", + atmf->Interval); + printf("Priority: %#x\n", atmf->Priority); + + printf("Frame Length: %d\n", atmf->FrameLen); + printf + ("Dest Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + atmf->DestMacAddr[0], atmf->DestMacAddr[1], + atmf->DestMacAddr[2], atmf->DestMacAddr[3], + atmf->DestMacAddr[4], atmf->DestMacAddr[5]); + printf + ("Src Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + atmf->SrcMacAddr[0], atmf->SrcMacAddr[1], + atmf->SrcMacAddr[2], atmf->SrcMacAddr[3], + atmf->SrcMacAddr[4], atmf->SrcMacAddr[5]); + + hexdump("Frame Payload", atmf->Payload, + atmf->FrameLen - ETH_ALEN * 2, ' '); + } else { + printf("incorrect auto_tx command response\n"); } } - else { - printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",hostcmd->Command,hostcmd->Result); } - -_exit_: - if (buf) - free(buf); - - return WLAN_STATUS_SUCCESS; + break; } - -/** - * @brief Get Rate - * - * @return WLAN_STATUS_SUCCESS--success, otherwise --fail - */ -static int process_get_rate(void) + case HostCmd_RET_802_11_LED_CONTROL: { - u32 bitrate[WLAN_MAX_RATES]; - struct iwreq iwr; - s32 i = 0; - int ioctl_val, subioctl_val; + HostCmd_DS_802_11_LED_CTRL *led = + (HostCmd_DS_802_11_LED_CTRL *) (buf + S_DS_GEN); - if (get_priv_ioctl("getrate", - &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { - return -EOPNOTSUPP; - } + if (led->Action == HostCmd_ACT_GET) { + MrvlIEtypesHeader_t *header = &led->LedGpio.Header; - memset(&iwr, 0, sizeof(iwr)); - strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) bitrate; - iwr.u.data.length = sizeof(bitrate); - iwr.u.data.flags = subioctl_val; + printf("LedNums=%d\n", led->LedNums); + if ((S_DS_GEN + sizeof(led->Action) + sizeof(led->LedNums) + == hostcmd->Size) || !led->LedNums || + (led->LedNums > MAX_LEDS) + || (led->LedNums != header->Len / sizeof(LedGpio_t))) { + printf("LED CTRL not configured\n"); + } else { + if (header->Type == TLV_TYPE_LED_GPIO) { + int i; - if (ioctl(sockfd, ioctl_val, &iwr) < 0) { - perror("wlanconfig"); - return WLAN_STATUS_FAILURE; + for (i = 0; i < led->LedNums; i++) { + LedGpio_t *ledgpio = &led->LedGpio.LedGpio[i]; + + if (ledgpio->GpioNum > 0 && + ledgpio->GpioNum < LED_DISABLED) + printf + ("LED #%d is mapped to GPIO pin #%d\n", + ledgpio->LedNum, ledgpio->GpioNum); + else + printf("LED #%d is disabled\n", + ledgpio->LedNum); } + } else if (header->Type == MRVL_TERMINATE_TLV_ID) + break; + else + printf("incorrect LED_GPIO TLV type\n"); - printf("%-8.16s %d available bit-rates :\n", - dev_name, iwr.u.data.length); + char *pos = + (char *) (&led->LedGpio.LedGpio[0]) + header->Len; + char *end = (char *) (buf + hostcmd->Size); + printf + ("\nLED#\tLEDState\tDutyFactor\tBlinkPeriod\tFirmwareState\n"); + while (end - pos >= sizeof(MrvlIEtypes_LedBehavior_t)) { + MrvlIEtypes_LedBehavior_t *ledb = + (MrvlIEtypes_LedBehavior_t *) pos; - for (i = 0; i < iwr.u.data.length; i++) { - print_bitrate(bitrate[i], 0, 0); - } + if (ledb->Header.Type == TLV_TYPE_LEDBEHAVIOR) { + printf("%d\t%s\t%s\t\t%s\t\t%s\n", + ledb->LedNum, + led_state[ledb->LedState], + (ledb->LedState == LED_BLINKING) ? + led_duty_factor[ledb-> + LedArgs >> 4] : "N/A", + (ledb->LedState == + LED_BLINKING) ? + led_blink_period[ledb-> + LedArgs & 0x0f] : + "N/A", fw_state[ledb->FirmwareState]); + } else if (header->Type == MRVL_TERMINATE_TLV_ID) + break; + else + printf("incorrect LEDBEHAVIOR TLV type\n"); - if (ioctl(sockfd, SIOCGIWRATE, &iwr)) { - perror("wlanconfig"); - return WLAN_STATUS_FAILURE; + pos += sizeof(MrvlIEtypes_LedBehavior_t); + } + } + } + break; + } + default: + printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n", + hostcmd->Command, hostcmd->Result); + break; + } + } else { + printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n", + hostcmd->Command, hostcmd->Result); } - print_bitrate(iwr.u.bitrate.value, 1, iwr.u.bitrate.fixed); + _exit_: + if (buf) + free(buf); return WLAN_STATUS_SUCCESS; } @@ -827,7 +1031,8 @@ * @param s A pointer to the string * @return 0--HexString, -1--not HexString */ -static int ishexstring(s8 *s) +static int +ishexstring(s8 * s) { int ret = -1; s32 tmp; @@ -849,7 +1054,8 @@ * @param buf A pointer to the string * @return Integer */ -static int atoval(s8 *buf) +static int +atoval(s8 * buf) { if (!strncasecmp(buf, "0x", 2)) return a2hex(buf+2); @@ -859,13 +1065,13 @@ return atoi(buf); } - /** * @brief Display sleep params * @param sp A pointer to wlan_ioctl_sleep_params_config structure * @return NA */ -void display_sleep_params(wlan_ioctl_sleep_params_config *sp) +void +display_sleep_params(wlan_ioctl_sleep_params_config * sp) { printf("Sleep Params for %s:\n", sp->Action ? "set" : "get"); printf("----------------------------------------\n"); @@ -883,7 +1089,8 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_sleep_params(int argc, char *argv[]) +static int +process_sleep_params(int argc, char *argv[]) { struct iwreq iwr; int ret; @@ -958,7 +1165,8 @@ * @param sp A point to wlan_ioctl_bca_timeshare_config structure * @return NA */ -static void display_bca_ts_params(wlan_ioctl_bca_timeshare_config *bca_ts) +static void +display_bca_ts_params(wlan_ioctl_bca_timeshare_config * bca_ts) { printf("BCA Time Share Params for %s:\n", bca_ts->Action?"set" : "get"); printf("----------------------------------------\n"); @@ -973,7 +1181,8 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_bca_ts(int argc, char *argv[]) +static int +process_bca_ts(int argc, char *argv[]) { int ret, i; struct iwreq iwr; @@ -1058,9 +1267,273 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief Provision the driver with a IEEE IE for use in the next join cmd + * + * Test function used to check the ioctl and driver funcionality + * + * @return WLAN_STATUS_SUCCESS or ioctl error code + */ +#if (WIRELESS_EXT >= 18) +static int +process_setgenie(void) +{ + struct iwreq iwr; + + u8 testIE[] = { 0xdd, 0x09, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 + }; + + memset(&iwr, 0x00, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) testIE; + iwr.u.data.length = sizeof(testIE); + + if (ioctl(sockfd, SIOCSIWGENIE, &iwr) < 0) { + perror("wlanconfig: setgenie ioctl"); + return -EFAULT; + } + + return WLAN_STATUS_SUCCESS; +} +#else +static int +process_setgenie(void) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + + u8 testIE[] = { 0xdd, 0x09, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 + }; + + if (get_priv_ioctl("setgenie", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) testIE; + iwr.u.data.length = sizeof(testIE); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: setgenie ioctl"); + return -EFAULT; + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +/** + * @brief Helper function for process_getscantable_idx + * + */ +static void +dump_scan_elems(const u8 * pBuf, uint buf_len) +{ + uint idx; + uint marker = 2 + pBuf[1]; + + for (idx = 0; idx < buf_len; idx++) { + if (idx % 0x10 == 0) { + printf("\n%04x: ", idx); + } + + if (idx == marker) { + printf("|"); + marker = idx + pBuf[idx + 1] + 2; + } else { + printf(" "); + } + + printf("%02x ", pBuf[idx]); + } + + printf("\n"); +} + +/** + * @brief Helper function for process_getscantable_idx + * + */ +static int +scantable_elem_next(IEEEtypes_Generic_t ** pp_ie_out, int *p_buf_left) +{ + IEEEtypes_Generic_t *pIeGen; + u8 *p_next; + + if (*p_buf_left < 2) { + return -1; + } + + pIeGen = *pp_ie_out; + + p_next = (u8 *) pIeGen + (pIeGen->IeeeHdr.Len + sizeof(pIeGen->IeeeHdr)); + *p_buf_left -= (p_next - (u8 *) pIeGen); + + *pp_ie_out = (IEEEtypes_Generic_t *) p_next; + + if (*p_buf_left <= 0) { + return -1; + } + + return 0; +} + +/** + * @brief Helper function for process_getscantable_idx + * + */ +static int +scantable_find_elem(u8 * ie_buf, + unsigned int ie_buf_len, + IEEEtypes_ElementId_e ie_type, + IEEEtypes_Generic_t ** ppIeOut) +{ + int found; + unsigned int ie_buf_left; + + ie_buf_left = ie_buf_len; + + found = FALSE; + + *ppIeOut = (IEEEtypes_Generic_t *) ie_buf; + + do { + found = ((*ppIeOut)->IeeeHdr.ElementId == ie_type); + + } while (!found && + (scantable_elem_next(ppIeOut, (int *) &ie_buf_left) == 0)); + + if (!found) { + *ppIeOut = NULL; + } + + return (found ? 0 : -1); +} + +/** + * @brief Helper function for process_getscantable_idx + * + */ +static int +scantable_get_ssid_from_ie(u8 * ie_buf, + unsigned int ie_buf_len, + u8 * pSsid, unsigned int ssid_buf_max) +{ + int retval; + IEEEtypes_Generic_t *pIeGen; + + retval = scantable_find_elem(ie_buf, ie_buf_len, SSID, &pIeGen); + + memcpy(pSsid, pIeGen->Data, MIN(pIeGen->IeeeHdr.Len, ssid_buf_max)); + + return retval; +} + +/** + * @brief Provision the driver with a IEEE IE for use in the next join cmd + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_getscantable_idx(int tableIdx) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + u8 *pCurrent; + int bssInfoLen; + char ssid[33]; + u16 tmp_cap; + u8 tsf[8]; + u16 beaconInterval; + u8 scanRspBuffer[500]; /* Stack buffer can be as large as ioctl allows */ + IEEEtypes_CapInfo_t capInfo; + wlan_ioctl_get_scan_table_info *pRspInfo; + wlan_ioctl_get_scan_table_entry *pRspEntry; + + memset(ssid, 0x00, sizeof(ssid)); + + pRspInfo = (wlan_ioctl_get_scan_table_info *) scanRspBuffer; + + pRspInfo->scanNumber = tableIdx; + + if (get_priv_ioctl("getscantable", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + /* + * Set up and execute the ioctl call + */ + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) pRspInfo; + iwr.u.data.length = sizeof(scanRspBuffer); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: getscantable ioctl"); + return -EFAULT; + } + + pRspEntry + = + (wlan_ioctl_get_scan_table_entry *) pRspInfo->scan_table_entry_buffer; + + if (pRspInfo->scanNumber == 0) { + printf("wlanconfig: getscantable ioctl - index out of range\n"); + return -EINVAL; + } + + pCurrent = pRspInfo->scan_table_entry_buffer; + pCurrent += (sizeof(pRspEntry->fixedFieldLength) + + pRspEntry->fixedFieldLength); + + bssInfoLen = pRspEntry->bssInfoLength; + pCurrent += sizeof(pRspEntry->bssInfoLength); + + /* time stamp is 8 byte long */ + memcpy(tsf, pCurrent, sizeof(tsf)); + pCurrent += sizeof(tsf); + bssInfoLen -= sizeof(tsf); + /* beacon interval is 2 byte long */ + memcpy(&beaconInterval, pCurrent, sizeof(beaconInterval)); + pCurrent += sizeof(beaconInterval); + bssInfoLen -= sizeof(beaconInterval); + + /* capability information is 2 byte long */ + memcpy(&capInfo, pCurrent, sizeof(capInfo)); + pCurrent += sizeof(capInfo); + bssInfoLen -= sizeof(capInfo); + scantable_get_ssid_from_ie(pCurrent, + bssInfoLen, (u8 *) ssid, sizeof(ssid)); + printf("\n*** [%s], %02x:%02x:%02x:%02x:%02x:%2x\n", + ssid, + pRspEntry->fixedFields.bssid[0], pRspEntry->fixedFields.bssid[1], + pRspEntry->fixedFields.bssid[2], pRspEntry->fixedFields.bssid[3], + pRspEntry->fixedFields.bssid[4], pRspEntry->fixedFields.bssid[5]); + memcpy(&tmp_cap, &capInfo, sizeof(tmp_cap)); + printf("Channel = %d, SS = %d, CapInfo = 0x%04x, BcnIntvl = %d\n", + pRspEntry->fixedFields.channel, + 255 - pRspEntry->fixedFields.rssi, tmp_cap, beaconInterval); + + printf("TSF Values: AP(0x%02x%02x%02x%02x%02x%02x%02x%02x), ", + tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]); + + printf("Network(0x%016llx)\n", pRspEntry->fixedFields.networkTSF); + printf("\n"); + printf("Element Data (%d bytes)\n", bssInfoLen); + printf("------------"); + dump_scan_elems(pCurrent, bssInfoLen); + printf("\n"); + + return 0; +} /** * @brief Retrieve and display the contents of the driver scan table. @@ -1076,14 +1549,15 @@ * * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_getscantable(int argc, char *argv[]) +static int +process_getscantable(int argc, char *argv[]) { int ioctl_val, subioctl_val; struct iwreq iwr; u8 scanRspBuffer[500]; /* Stack buffer can be as large as ioctl allows */ - uint scanStart; - uint idx; + unsigned int scanStart; + unsigned int idx; u8* pCurrent; u8* pNext; @@ -1091,13 +1565,27 @@ u8* pElementLen; int bssInfoLen; int ssidIdx; - u16 tmpCap; u8* pByte; + char ssid[33]; + int ssidLen = 0; - IEEEtypes_CapInfo_t capInfo; + IEEEtypes_CapInfo_t capInfo = { 0 }; u8 tsf[8]; u16 beaconInterval; + IEEEtypes_VendorSpecific_t *pWpaIe; + const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + + IEEEtypes_WmmParameter_t *pWmmIe; + const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + char wmmCap; + char wscCap; + char dot11kCap; + char dot11rCap; + char privCap; + + int displayedInfo; + wlan_ioctl_get_scan_table_info* pRspInfo; wlan_ioctl_get_scan_table_entry* pRspEntry; @@ -1108,7 +1596,18 @@ return -EOPNOTSUPP; } - scanStart = 0; + if (argc > 3 && (strcmp(argv[3], "tsf") != 0) + && (strcmp(argv[3], "help") != 0)) { + + idx = strtol(argv[3], NULL, 10); + + if (idx >= 0) { + return process_getscantable_idx(idx); + } + } + + displayedInfo = FALSE; + scanStart = 1; printf("---------------------------------------"); printf("---------------------------------------\n"); @@ -1148,7 +1647,7 @@ printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |", scanStart + idx, pRspEntry->fixedFields.channel, - pRspEntry->fixedFields.rssi, + 255 - pRspEntry->fixedFields.rssi, pRspEntry->fixedFields.bssid[0], pRspEntry->fixedFields.bssid[1], pRspEntry->fixedFields.bssid[2], @@ -1156,6 +1655,8 @@ pRspEntry->fixedFields.bssid[4], pRspEntry->fixedFields.bssid[5]); + displayedInfo = TRUE; + #if 0 printf("fixed = %u, bssInfo = %u\n", (unsigned int)pRspEntry->fixedFieldLength, @@ -1183,19 +1684,17 @@ /* capability information is 2 byte long */ memcpy(&capInfo, pCurrent, sizeof(capInfo)); - memcpy(&tmpCap, pCurrent, sizeof(tmpCap)); pCurrent += sizeof(capInfo); bssInfoLen -= sizeof(capInfo); + } - printf(" %04x-", tmpCap); + wmmCap = ' '; /* M (WMM), C (WMM-Call Admission Control) */ + wscCap = ' '; /* "S" */ + dot11kCap = ' '; /* "K" */ + dot11rCap = ' '; /* "R" */ - printf("%c%c%c | ", - capInfo.Ibss ? 'A' : 'I', - capInfo.Privacy ? 'P' : ' ', - capInfo.SpectrumMgmt ? 'S' : ' '); - } else { - printf(" | "); - } + /* "P" for Privacy (WEP) since "W" is WPA, and "2" is RSN/WPA2 */ + privCap = capInfo.Privacy ? 'P' : ' '; while (bssInfoLen >= 2) { pElementId = (IEEEtypes_ElementId_e*)pCurrent; @@ -1207,16 +1706,43 @@ case SSID: if (*pElementLen && *pElementLen <= MRVDRV_MAX_SSID_LENGTH) { - for (ssidIdx = 0; ssidIdx < *pElementLen; ssidIdx++) { - if (isprint(*(pCurrent + ssidIdx))) { - printf("%c", *(pCurrent + ssidIdx)); + memcpy(ssid, pCurrent, *pElementLen); + ssidLen = *pElementLen; + } + break; + + case WPA_IE: + pWpaIe = (IEEEtypes_VendorSpecific_t *) pElementId; + if ((memcmp + (pWpaIe->VendHdr.Oui, wpa_oui, + sizeof(pWpaIe->VendHdr.Oui)) == 0) + && (pWpaIe->VendHdr.OuiType == wpa_oui[3])) { + /* WPA IE found, 'W' for WPA */ + privCap = 'W'; } else { - printf("\\%02x", *(pCurrent + ssidIdx)); + pWmmIe = (IEEEtypes_WmmParameter_t *) pElementId; + if ((memcmp(pWmmIe->VendHdr.Oui, + wmm_oui, + sizeof(pWmmIe->VendHdr.Oui)) == 0) + && (pWmmIe->VendHdr.OuiType == wmm_oui[3])) { + /* Check the subtype: 1 == parameter, 0 == info */ + if ((pWmmIe->VendHdr.OuiSubtype == 1) + && pWmmIe->AcParams[WMM_AC_VO].AciAifsn.Acm) { + /* Call admission on VO; 'C' for CAC */ + wmmCap = 'C'; + } else { + /* No CAC; 'M' for uh, WMM */ + wmmCap = 'M'; } } } break; + case RSN_IE: + /* RSN IE found; '2' for WPA2 (RSN) */ + privCap = '2'; + break; + default: #if 0 printf("% d(%d), bil=%d\n", @@ -1229,9 +1755,28 @@ bssInfoLen -= (2 + *pElementLen); } + /* "A" for Adhoc + * "I" for Infrastructure, + * "D" for DFS (Spectrum Mgmt) + */ + printf(" %c%c%c%c%c%c%c | ", capInfo.Ibss ? 'A' : 'I', privCap, /* P (WEP), W (WPA), 2 (WPA2) */ + capInfo.SpectrumMgmt ? 'D' : ' ', wmmCap, /* M (WMM), C (WMM-Call Admission Control) */ + dot11kCap, /* K */ + dot11rCap, /* R */ + wscCap); /* S */ + + /* Print out the ssid or the hex values if non-printable */ + for (ssidIdx = 0; ssidIdx < ssidLen; ssidIdx++) { + if (isprint(ssid[ssidIdx])) { + printf("%c", ssid[ssidIdx]); + } else { + printf("\\%02x", ssid[ssidIdx]); + } + } + printf("\n"); - if (argc > 3) { + if (argc > 3 && strcmp(argv[3], "tsf") == 0) { /* TSF is a u64, some formatted printing libs have * trouble printing long longs, so cast and dump as bytes */ @@ -1244,9 +1789,26 @@ scanStart += pRspInfo->scanNumber; - } while (pRspInfo->scanNumber); + if (displayedInfo == TRUE) { + if (argc > 3 && strcmp(argv[3], "help") == 0) { + printf("\n\n" + "Capability Legend (Not all may be supported)\n" + "-----------------\n" + " I [ Infrastructure ]\n" + " A [ Ad-hoc ]\n" + " W [ WPA IE ]\n" + " 2 [ WPA2/RSN IE ]\n" + " M [ WMM IE ]\n" + " C [ Call Admission Control - WMM IE, VO ACM set ]\n" + " D [ Spectrum Management - DFS (11h) ]\n" + " K [ 11k ]\n" " R [ 11r ]\n" " S [ WSC ]\n" "\n\n"); + } + } else { + printf("< No Scan Results >\n"); + } + return WLAN_STATUS_SUCCESS; } @@ -1277,7 +1839,8 @@ * * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_setuserscan(int argc, char *argv[]) +static int +process_setuserscan(int argc, char *argv[]) { wlan_ioctl_user_scan_cfg scanReq; int ioctl_val, subioctl_val; @@ -1292,12 +1855,14 @@ char chanScratch[10]; char* pScratch; int tmpIdx; - unsigned int mac[MRVDRV_ETH_ADDR_LEN]; int scanTime; + int numSsid; + unsigned int mac[MRVDRV_ETH_ADDR_LEN]; memset(&scanReq, 0x00, sizeof(scanReq)); chanCmdIdx = 0; scanTime = 0; + numSsid = 0; if (get_priv_ioctl("setuserscan", &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { @@ -1335,8 +1900,7 @@ scanReq.chanList[chanCmdIdx].chanNumber = atoi(pChanTok); } else { - switch (toupper(*pChanTok)) - { + switch (toupper(*pChanTok)) { case 'A': scanReq.chanList[chanCmdIdx].radioType = 1; break; @@ -1377,8 +1941,43 @@ /* * "ssid" token string handler */ - strncpy(scanReq.specificSSID, argv[argIdx] + strlen("ssid="), - sizeof(scanReq.specificSSID)); + if (numSsid < MRVDRV_MAX_SSID_LIST_LENGTH) { + strncpy(scanReq.ssidList[numSsid].ssid, + argv[argIdx] + strlen("ssid="), + sizeof(scanReq.ssidList[numSsid].ssid)); + + scanReq.ssidList[numSsid].maxLen = 0; + + numSsid++; + } + } else if (strncmp(argv[argIdx], "wc=", strlen("wc=")) == 0) { + + if (numSsid < MRVDRV_MAX_SSID_LIST_LENGTH) { + /* + * "wc" token string handler + */ + pScratch = rindex(argv[argIdx], ','); + + if (pScratch) { + *pScratch = 0; + pScratch++; + + if (isdigit(*pScratch)) { + scanReq.ssidList[numSsid].maxLen = atoi(pScratch); + } else { + scanReq.ssidList[numSsid].maxLen = *pScratch; + } + } else { + /* Standard wildcard matching */ + scanReq.ssidList[numSsid].maxLen = 0xFF; + } + + strncpy(scanReq.ssidList[numSsid].ssid, + argv[argIdx] + strlen("wc="), + sizeof(scanReq.ssidList[numSsid].ssid)); + + numSsid++; + } } else if (strncmp(argv[argIdx], "probes=", strlen("probes=")) == 0) { /* * "probes" token string handler @@ -1389,8 +1988,7 @@ * "type" token string handler */ scanReq.bssType = atoi(argv[argIdx] + strlen("type=")); - switch (scanReq.bssType) - { + switch (scanReq.bssType) { case WLAN_SCAN_BSS_TYPE_BSS: case WLAN_SCAN_BSS_TYPE_IBSS: break; @@ -1425,7 +2023,113 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief Provision the driver with a Marvell TLV for use in the next join cmd + * + * Test function used to check the ioctl and driver funcionality + * + * @return WLAN_STATUS_SUCCESS or ioctl error code + */ +static int +process_setmrvltlv(void) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + u8 testTlv[] = { 0x0A, 0x01, 0x0C, 0x00, + 0xdd, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + + if (get_priv_ioctl("setmrvltlv", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) testTlv; + iwr.u.data.length = sizeof(testTlv); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: setmrvltlv ioctl"); + return -EFAULT; + } + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Retrieve the association response from the driver + * + * Retrieve the buffered (re)association management frame from the driver. + * The response is identical to the one received from the AP and conforms + * to the IEEE specification. + * + * @return WLAN_STATUS_SUCCESS or ioctl error code + */ +static int +process_getassocrsp(void) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + u8 assocRspBuffer[500]; /* Stack buffer can be as large as ioctl allows */ + IEEEtypes_AssocRsp_t *pAssocRsp; + + pAssocRsp = (IEEEtypes_AssocRsp_t *) assocRspBuffer; + + if (get_priv_ioctl("getassocrsp", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) assocRspBuffer; + iwr.u.data.length = sizeof(assocRspBuffer); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: getassocrsp ioctl"); + return -EFAULT; + } + + if (iwr.u.data.length) { + printf("getassocrsp: Status[%d], Cap[0x%04x]: ", + pAssocRsp->StatusCode, *(u16 *) & pAssocRsp->Capability); + hexdump(NULL, assocRspBuffer, iwr.u.data.length, ' '); + } else { + printf("getassocrsp: \n"); + } + + return WLAN_STATUS_SUCCESS; +} + +static int +process_gettsf(void) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + u8 tsf[8]; + + if (get_priv_ioctl("gettsf", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) tsf; + iwr.u.data.length = sizeof(u64); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("gettsf ioctl"); + return -1; + } + + printf("TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n", + tsf[7], tsf[6], tsf[5], tsf[4], tsf[3], tsf[2], tsf[1], tsf[0]); + + return WLAN_STATUS_SUCCESS; +} /** * @brief scan network with specific ssid @@ -1433,7 +2137,8 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_extscan(int argc, char *argv[]) +static int +process_extscan(int argc, char *argv[]) { struct iwreq iwr; WCON_SSID Ssid; @@ -1455,7 +2160,12 @@ memset(&Ssid, 0, sizeof(Ssid)); memset(&iwr, 0, sizeof(iwr)); + if (strlen(argv[3]) <= IW_ESSID_MAX_SIZE) { Ssid.ssid_len = strlen(argv[3]); + } else { + printf("Invalid SSID:Exceeds more than 32 charecters\n"); + exit(1); + } memcpy(Ssid.ssid, argv[3], Ssid.ssid_len); strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); @@ -1479,7 +2189,8 @@ * @param idx AP index * @return NA */ -static void parse_custom_info(WCON_HANDLE *pHandle, struct iw_point *data, s32 idx) +static void +parse_custom_info(WCON_HANDLE * pHandle, struct iw_point *data, s32 idx) { s32 i = 0; s8 *custom_cmd[] = { "wpa_ie", "rsn_ie", NULL }; @@ -1494,8 +2205,7 @@ } while (custom_cmd[i]) { - if (!strncmp(data->pointer, custom_cmd[i], - strlen(custom_cmd[i]))) { + if (!strncmp(data->pointer, custom_cmd[i], strlen(custom_cmd[i]))) { pHandle->ScanList[idx].WpaAP = WCON_WPA_ENABLED; break; } @@ -1516,15 +2226,19 @@ * @param length length of scan result buffer * @return NA */ -static void parse_scan_info(WCON_HANDLE *pHandle, u8 buffer[], s32 length) +static void +parse_scan_info(WCON_HANDLE * pHandle, u8 buffer[], s32 length) { s32 len = 0; - s32 ap_index = -1; + u32 ap_index = 0; + int new_index = FALSE; s8 *mode[3] = {"auto", "ad-hoc", "infra"}; struct iw_event iwe; struct iw_point iwp; memset(pHandle->ScanList, 0, sizeof(pHandle->ScanList)); + memset((u8 *) & iwe, 0, sizeof(struct iw_event)); + memset((u8 *) & iwp, 0, sizeof(struct iw_point)); pHandle->ApNum = 0; while (len + IW_EV_LCP_LEN < length) { @@ -1532,37 +2246,37 @@ if ((iwe.cmd == SIOCGIWESSID)||(iwe.cmd ==SIOCGIWENCODE)|| (iwe.cmd ==IWEVCUSTOM)){ if(we_version_compiled > 18) - memcpy((s8 *)&iwp, buffer + len + IW_EV_LCP_LEN - MRV_EV_POINT_OFF, + memcpy((s8 *) & iwp, + buffer + len + IW_EV_LCP_LEN - MRV_EV_POINT_OFF, sizeof(struct iw_point)); else - memcpy((s8 *)&iwp, buffer + len + IW_EV_LCP_LEN,sizeof(struct iw_point)); + memcpy((s8 *) & iwp, buffer + len + IW_EV_LCP_LEN, + sizeof(struct iw_point)); iwp.pointer = buffer + len + IW_EV_POINT_LEN; } switch (iwe.cmd) { case SIOCGIWAP: + if (new_index && ap_index < IW_MAX_AP - 1) ap_index++; memcpy(pHandle->ScanList[ap_index].Bssid, iwe.u.ap_addr.sa_data, ETH_ALEN); printf("\nBSSID:\t %02X:%02X:%02X:%02X:%02X:%02X\n", HWA_ARG(pHandle->ScanList[ap_index].Bssid)); + new_index = TRUE; break; case SIOCGIWESSID: if ((iwp.pointer) && (iwp.length)) { memcpy(pHandle->ScanList[ap_index].Ssid.ssid, - (s8 *)iwp.pointer, - iwp.length); - pHandle->ScanList[ap_index].Ssid.ssid_len = - iwp.length; + (s8 *) iwp.pointer, iwp.length); + pHandle->ScanList[ap_index].Ssid.ssid_len = iwp.length; } - printf("SSID:\t %s\n", - pHandle->ScanList[ap_index].Ssid.ssid); + printf("SSID:\t %s\n", pHandle->ScanList[ap_index].Ssid.ssid); break; case SIOCGIWENCODE: if (!(iwp.flags & IW_ENCODE_DISABLED)) { - pHandle->ScanList[ap_index].Privacy = - WCON_ENC_ENABLED; + pHandle->ScanList[ap_index].Privacy = WCON_ENC_ENABLED; } printf("Privacy: %s\n", pHandle->ScanList[ap_index].Privacy ? @@ -1583,14 +2297,13 @@ case IWEVQUAL: pHandle->ScanList[ap_index].Rssi = iwe.u.qual.level; - printf("Quality: %d\n", - pHandle->ScanList[ap_index].Rssi); + printf("Quality: %d\n", pHandle->ScanList[ap_index].Rssi); break; } len += iwe.len; } - + if (new_index) pHandle->ApNum = ap_index + 1; printf("\nNo of AP's = %d\n", pHandle->ApNum); @@ -1603,30 +2316,61 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_scan_results(int argc, char *argv[]) +static int +process_scanlist(int argc, char *argv[]) { - u8 buffer[IW_SCAN_MAX_DATA]; + u8 *buffer = NULL; + u8 *newbuf = NULL; + int buflen = IW_SCAN_MAX_DATA; struct iwreq iwr; WCON_HANDLE mhandle, *pHandle = &mhandle; memset(pHandle, 0, sizeof(WCON_HANDLE)); memset(&iwr, 0, sizeof(struct iwreq)); + realloc: + /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ + newbuf = realloc(buffer, buflen); + if (newbuf == NULL) { + if (buffer) + free(buffer); + fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); + return (-1); + } + buffer = newbuf; iwr.u.data.pointer = buffer; - iwr.u.data.length = sizeof(buffer); + iwr.u.data.length = buflen; strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); if ((ioctl(sockfd, SIOCGIWSCAN, &iwr)) < 0) { + if ((errno == E2BIG)) { + /* Some driver may return very large scan results, either + * because there are many cells, or because they have many + * large elements in cells (like IWEVCUSTOM). Most will + * only need the regular sized buffer. We now use a dynamic + * allocation of the buffer to satisfy everybody. Of course, + * as we don't know in advance the size of the array, we try + * various increasing sizes. */ + + /* Check if the driver gave us any hints. */ + if (iwr.u.data.length > buflen) + buflen = iwr.u.data.length; + else + buflen *= 2; + + /* Try again */ + goto realloc; + } printf("Get Scan Results Failed\n"); + free(buffer); return -1; } parse_scan_info(pHandle, buffer, iwr.u.data.length); - + free(buffer); return WLAN_STATUS_SUCCESS; } - /** * @brief Process read eeprom * @@ -1634,11 +2378,18 @@ * @param strnob A pointer to NOB string * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_read_eeprom(s8 *stroffset, s8 *strnob) +static int +process_read_eeprom(s8 * stroffset, s8 * strnob) { s8 buffer[MAX_EEPROM_DATA]; struct ifreq userdata; wlan_ioctl_regrdwr *reg = (wlan_ioctl_regrdwr *)buffer; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("regrdwr", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } memset(buffer, 0, sizeof(buffer)); reg->WhichReg = REG_EEPROM; @@ -1654,7 +2405,7 @@ else reg->NOB = atoi(strnob); - if (reg->NOB > MAX_EEPROM_DATA) { + if ((reg->NOB + sizeof(wlan_ioctl_regrdwr)) > MAX_EEPROM_DATA) { fprintf(stderr, "Number of bytes exceeds MAX EEPROM Read size\n"); return WLAN_STATUS_FAILURE; } @@ -1662,7 +2413,7 @@ strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = buffer; - if (ioctl(sockfd, WLANREGRDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: EEPROM read not possible " @@ -1670,7 +2421,7 @@ return WLAN_STATUS_FAILURE; } - hexdump("RD EEPROM", ®->Value, reg->NOB, ' '); + hexdump("RD EEPROM", ®->Value, MIN(reg->NOB, MAX_EEPROM_DATA), ' '); return WLAN_STATUS_SUCCESS; } @@ -1680,7 +2431,8 @@ * * @return NA */ -static void display_usage(void) +static void +display_usage(void) { s32 i; @@ -1696,7 +2448,8 @@ * @param cmd A pointer to command buffer * @return index of command or WLAN_STATUS_FAILURE */ -static int findcommand(s32 maxcmds, s8 *cmds[], s8 *cmd) +static int +findcommand(s32 maxcmds, s8 * cmds[], s8 * cmd) { s32 i; @@ -1715,11 +2468,18 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_sdcmd52r(int argc, char *argv[]) +static int +process_sdcmd52r(int argc, char *argv[]) { struct ifreq userdata; u8 buf[6]; u32 tmp; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("sdcmd52rw", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } buf[0] = 0; //CMD52 read if (argc == 5) { @@ -1737,7 +2497,7 @@ strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = buf; - if (ioctl(sockfd, WLANCMD52RDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: CMD52 R/W not supported by " @@ -1755,11 +2515,18 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_sdcmd52w(int argc, char *argv[]) +static int +process_sdcmd52w(int argc, char *argv[]) { struct ifreq userdata; u8 buf[7]; u32 tmp; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("sdcmd52rw", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } buf[0] = 1; //CMD52 write if (argc == 6) { @@ -1778,7 +2545,7 @@ strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = buf; - if (ioctl(sockfd, WLANCMD52RDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: CMD52 R/W not supported by " @@ -1797,19 +2564,25 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_sdcmd53r(void) +static int +process_sdcmd53r(void) { struct ifreq userdata; s8 buf[CMD53BUFLEN]; int i; + int ioctl_val, subioctl_val; + if (get_priv_ioctl("sdcmd53rw", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = buf; for(i=0; i < NELEMENTS(buf); i++) buf[i] = i & 0xff; - if (ioctl(sockfd, WLANCMD53RDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: CMD53 R/W not supported by " @@ -1825,7 +2598,696 @@ return WLAN_STATUS_SUCCESS; } +/* + * @brief Get the current status of the WMM Queues + * + * Command: wlanconfig eth1 qstatus + * + * Retrieve the following information for each AC if wmm is enabled: + * - WMM IE ACM Required + * - Firmware Flow Required + * - Firmware Flow Established + * - Firmware Queue Enabled + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_wmm_qstatus(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_status_t qstatus; + wlan_wmm_ac_e acVal; + + if (get_priv_ioctl("qstatus", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + memset(&qstatus, 0x00, sizeof(qstatus)); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & qstatus; + iwr.u.data.length = (sizeof(qstatus)); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: qstatus ioctl"); + return -EFAULT; + } + + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + switch (acVal) { + case WMM_AC_BK: + printf("BK: "); + break; + case WMM_AC_BE: + printf("BE: "); + break; + case WMM_AC_VI: + printf("VI: "); + break; + case WMM_AC_VO: + printf("VO: "); + break; + default: + printf("??: "); + } + + printf("ACM[%c], FlowReq[%c], FlowCreated[%c], Enabled[%c]\n", + (qstatus.acStatus[acVal].wmmAcm ? 'X' : ' '), + (qstatus.acStatus[acVal].flowRequired ? 'X' : ' '), + (qstatus.acStatus[acVal].flowCreated ? 'X' : ' '), + (qstatus.acStatus[acVal].disabled ? ' ' : 'X')); + } + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief read current command + * @param ptr A pointer to data + * @param curCmd A pointer to the buf which will hold current command + * @return NULL or the pointer to the left command buf + */ +static s8 * +readCurCmd(s8 * ptr, s8 * curCmd) +{ + s32 i = 0; +#define MAX_CMD_SIZE 64 + + while (*ptr != ']' && i < (MAX_CMD_SIZE - 1)) + curCmd[i++] = *(++ptr); + + if (*ptr != ']') + return NULL; + + curCmd[i - 1] = '\0'; + + return ++ptr; +} + +/** + * @brief parse command and hex data + * @param fp A pointer to FILE stream + * @param dst A pointer to the dest buf + * @param cmd A pointer to command buf for search + * @return length of hex data or WLAN_STATUS_FAILURE + */ +static int +fparse_for_cmd_and_hex(FILE * fp, u8 * dst, u8 * cmd) +{ + s8 *ptr; + u8 *dptr; + s8 buf[256], curCmd[64]; + s32 isCurCmd = 0; + + dptr = dst; + while (fgets(buf, sizeof(buf), fp)) { + ptr = buf; + + while (*ptr) { + // skip leading spaces + while (*ptr && isspace(*ptr)) + ptr++; + + // skip blank lines and lines beginning with '#' + if (*ptr == '\0' || *ptr == '#') + break; + + if (*ptr == '[' && *(ptr + 1) != '/') { + if (!(ptr = readCurCmd(ptr, curCmd))) + return WLAN_STATUS_FAILURE; + + if (strcasecmp(curCmd, (char *) cmd)) /* Not equal */ + isCurCmd = 0; + else + isCurCmd = 1; + } + + /* Ignore the rest if it is not correct cmd */ + if (!isCurCmd) + break; + + if (*ptr == '[' && *(ptr + 1) == '/') + return (dptr - dst); + + if (isxdigit(*ptr)) { + ptr = convert2hex(ptr, dptr++); + } else { + /* Invalid character on data line */ + ptr++; + } + + } + } + + return WLAN_STATUS_FAILURE; +} + +/** + * @brief Send an ADDTS command to the associated AP + * + * Process a given conf file for a specific TSPEC data block. Send the + * TSPEC along with any other IEs to the driver/firmware for transmission + * in an ADDTS request to the associated AP. + * + * Return the execution status of the command as well as the ADDTS response + * from the AP if any. + * + * wlanconfig ethX addts + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_addts(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + unsigned int ieBytes; + wlan_ioctl_wmm_addts_req_t addtsReq; + + FILE *fp; + char filename[48]; + char config_id[20]; + + memset(&addtsReq, 0x00, sizeof(addtsReq)); + memset(filename, 0x00, sizeof(filename)); + + if (get_priv_ioctl("addts", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 6) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + ieBytes = 0; + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + perror("fopen"); + fprintf(stderr, "Cannot open file %s\n", argv[3]); + exit(1); + } + + sprintf(config_id, "tspec%d", atoi(argv[4])); + + ieBytes = + fparse_for_cmd_and_hex(fp, addtsReq.tspecData, (u8 *) config_id); + + if (ieBytes > 0) { + printf("Found %d bytes in the %s section of conf file %s\n", + ieBytes, config_id, filename); + } else { + fprintf(stderr, "section %s not found in %s\n", config_id, filename); + exit(1); + } + + addtsReq.timeout_ms = atoi(argv[5]); + + printf("Cmd Input:\n"); + hexdump(config_id, addtsReq.tspecData, ieBytes, ' '); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & addtsReq; + iwr.u.data.length = (sizeof(addtsReq.timeout_ms) + + sizeof(addtsReq.commandResult) + + sizeof(addtsReq.ieeeStatusCode) + + ieBytes); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: addts ioctl"); + return -EFAULT; + } + + ieBytes = iwr.u.data.length - (sizeof(addtsReq.timeout_ms) + + sizeof(addtsReq.commandResult) + + sizeof(addtsReq.ieeeStatusCode)); + printf("Cmd Output:\n"); + printf("ADDTS Command Result = %d\n", addtsReq.commandResult); + printf("ADDTS IEEE Status = %d\n", addtsReq.ieeeStatusCode); + hexdump(config_id, addtsReq.tspecData, ieBytes, ' '); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Send a DELTS command to the associated AP + * + * Process a given conf file for a specific TSPEC data block. Send the + * TSPEC along with any other IEs to the driver/firmware for transmission + * in a DELTS request to the associated AP. + * + * Return the execution status of the command. There is no response to a + * DELTS from the AP. + * + * wlanconfig ethX delts + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_delts(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + unsigned int ieBytes; + wlan_ioctl_wmm_delts_req_t deltsReq; + + FILE *fp; + char filename[48]; + char config_id[20]; + + memset(&deltsReq, 0x00, sizeof(deltsReq)); + memset(filename, 0x00, sizeof(filename)); + + if (get_priv_ioctl("delts", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 5) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + ieBytes = 0; + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + perror("fopen"); + fprintf(stderr, "Cannot open file %s\n", argv[3]); + exit(1); + } + + sprintf(config_id, "tspec%d", atoi(argv[4])); + + ieBytes = + fparse_for_cmd_and_hex(fp, deltsReq.tspecData, (u8 *) config_id); + + if (ieBytes > 0) { + printf("Found %d bytes in the %s section of conf file %s\n", + ieBytes, config_id, filename); + } else { + fprintf(stderr, "section %s not found in %s\n", config_id, filename); + exit(1); + } + + deltsReq.ieeeReasonCode = 0x20; /* 32, unspecified QOS reason */ + + printf("Cmd Input:\n"); + hexdump(config_id, deltsReq.tspecData, ieBytes, ' '); + + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.flags = subioctl_val; + iwr.u.data.pointer = (caddr_t) & deltsReq; + iwr.u.data.length = (sizeof(deltsReq.commandResult) + + sizeof(deltsReq.ieeeReasonCode) + + ieBytes); + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("wlanconfig: delts ioctl"); + return -EFAULT; + } + + printf("Cmd Output:\n"); + printf("DELTS Command Result = %d\n", deltsReq.commandResult); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Send a WMM AC Queue configuration command to get/set/default params + * + * Configure or get the parameters of a WMM AC queue. The command takes + * an optional Queue Id as a last parameter. Without the queue id, all + * queues will be acted upon. + * + * wlanconfig ethX qconfig set msdu [Queue Id: 0-3] + * wlanconfig ethX qconfig get [Queue Id: 0-3] + * wlanconfig ethX qconfig def [Queue Id: 0-3] + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_qconfig(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_config_t queue_config_cmd; + wlan_wmm_ac_e ac_idx; + wlan_wmm_ac_e ac_idx_start; + wlan_wmm_ac_e ac_idx_stop; + + const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" }; + + if (argc < 4) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + if (get_priv_ioctl("qconfig", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + memset(&queue_config_cmd, 0x00, sizeof(queue_config_cmd)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) & queue_config_cmd; + iwr.u.data.length = sizeof(queue_config_cmd); + iwr.u.data.flags = subioctl_val; + + if (strcmp(argv[3], "get") == 0) { + /* 3 4 5 */ + /* qconfig get [qid] */ + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_GET; + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf("qconfig %s(%d): MSDU Lifetime GET = 0x%04x (%d)\n", + ac_str_tbl[ac_idx], + ac_idx, + queue_config_cmd.msduLifetimeExpiry, + queue_config_cmd.msduLifetimeExpiry); + } + } + } else if (strcmp(argv[3], "set") == 0) { + if (strcmp(argv[4], "msdu") == 0) { + /* 3 4 5 6 7 */ + /* qconfig set msdu [qid] */ + if (argc == 6) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 7) { + ac_idx_start = atoi(argv[6]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_SET; + queue_config_cmd.msduLifetimeExpiry = atoi(argv[5]); + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf + ("qconfig %s(%d): MSDU Lifetime SET = 0x%04x (%d)\n", + ac_str_tbl[ac_idx], ac_idx, + queue_config_cmd.msduLifetimeExpiry, + queue_config_cmd.msduLifetimeExpiry); + } + } + } else { + /* Only MSDU Lifetime provisioning accepted for now */ + fprintf(stderr, "Invalid set parameter: s/b [msdu]\n"); + return -EINVAL; + } + } else if (strncmp(argv[3], "def", strlen("def")) == 0) { + /* 3 4 5 */ + /* qconfig def [qid] */ + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_config_cmd.action = WMM_QUEUE_CONFIG_ACTION_DEFAULT; + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_config_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qconfig ioctl"); + } else { + printf + ("qconfig %s(%d): MSDU Lifetime DEFAULT = 0x%04x (%d)\n", + ac_str_tbl[ac_idx], ac_idx, + queue_config_cmd.msduLifetimeExpiry, + queue_config_cmd.msduLifetimeExpiry); + } + } + } else { + fprintf(stderr, "Invalid qconfig command; s/b [set, get, default]\n"); + return -EINVAL; + } + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Turn on/off or retrieve and clear the queue statistics for an AC + * + * Turn the queue statistics collection on/off for a given AC or retrieve the + * current accumulated stats and clear them from the firmware. The command + * takes an optional Queue Id as a last parameter. Without the queue id, + * all queues will be acted upon. + * + * wlanconfig ethX qstats on [Queue Id: 0-3] + * wlanconfig ethX qstats off [Queue Id: 0-3] + * wlanconfig ethX qstats get [Queue Id: 0-3] + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_qstats(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + wlan_ioctl_wmm_queue_stats_t queue_stats_cmd; + wlan_wmm_ac_e ac_idx; + wlan_wmm_ac_e ac_idx_start; + wlan_wmm_ac_e ac_idx_stop; + + const char *ac_str_tbl[] = { "BK", "BE", "VI", "VO" }; + if (argc < 3) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + if (get_priv_ioctl("qstats", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + printf("\n"); + + memset(&queue_stats_cmd, 0x00, sizeof(queue_stats_cmd)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) & queue_stats_cmd; + iwr.u.data.length = sizeof(queue_stats_cmd); + iwr.u.data.flags = subioctl_val; + + if ((argc > 3) && strcmp(argv[3], "on") == 0) { + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_stats_cmd.action = WMM_STATS_ACTION_START; + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_stats_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf("qstats %s(%d) turned on\n", + ac_str_tbl[ac_idx], ac_idx); + } + } + } else if ((argc > 3) && strcmp(argv[3], "off") == 0) { + if (argc == 4) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + queue_stats_cmd.action = WMM_STATS_ACTION_STOP; + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_stats_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf("qstats %s(%d) turned off\n", + ac_str_tbl[ac_idx], ac_idx); + } + } + } + /* If the user types: "wlanconfig eth1 qstats" without get argument. + The wlanconfig application invokes "get" option for all the queues */ + else if (((argc > 3) || (argc == 3)) && + ((argc == 3) ? 1 : (strcmp(argv[3], "get") == 0))) { + printf("AC Count Loss TxDly QDly" + " <=5 <=10 <=20 <=30 <=40 <=50 >50\n"); + printf("----------------------------------" + "---------------------------------------------\n"); + if ((argc == 4) || (argc == 3)) { + ac_idx_start = WMM_AC_BK; + ac_idx_stop = WMM_AC_VO; + } else if (argc == 5) { + ac_idx_start = atoi(argv[4]); + ac_idx_stop = ac_idx_start; + } else { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + queue_stats_cmd.action = WMM_STATS_ACTION_GET_CLR; + + for (ac_idx = ac_idx_start; ac_idx <= ac_idx_stop; ac_idx++) { + queue_stats_cmd.accessCategory = ac_idx; + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("qstats ioctl"); + } else { + printf("%s %5u %5u %6u %6u" + " %5u %5u %5u %5u %5u %5u %5u\n", + ac_str_tbl[ac_idx], + queue_stats_cmd.pktCount, + queue_stats_cmd.pktLoss, + (unsigned int) queue_stats_cmd.avgTxDelay, + (unsigned int) queue_stats_cmd.avgQueueDelay, + queue_stats_cmd.delayHistogram[0], + queue_stats_cmd.delayHistogram[1], + queue_stats_cmd.delayHistogram[2], + queue_stats_cmd.delayHistogram[3], + queue_stats_cmd.delayHistogram[4], + queue_stats_cmd.delayHistogram[5], + queue_stats_cmd.delayHistogram[6]); + } + } + } else { + fprintf(stderr, "Invalid qstats command;\n"); + return -EINVAL; + } + printf("\n"); + + return 0; +} + +/** + * @brief Retrieve and clear the TX Packet statistics + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_txpktstats(int argc, char *argv[]) +{ + int ioctl_val, subioctl_val; + struct iwreq iwr; + HostCmd_DS_TX_PKT_STATS tx_pkt_stats; + u32 totInit, totSuccess, totAttempts, totFailRetry, totFailExpiry; + int idx; + + totInit = totSuccess = totAttempts = totFailRetry = totFailExpiry = 0; + + const char *rateIdStr[] = { "1", "2", "5.5", "11", "--", + "6", "9", "12", "18", "24", "36", "48", "54", "--" + }; + + if (argc != 3) { + fprintf(stderr, "Invalid number of parameters!\n"); + return -EINVAL; + } + + if (get_priv_ioctl("txpktstats", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + printf("\n"); + + memset(&tx_pkt_stats, 0x00, sizeof(tx_pkt_stats)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) & tx_pkt_stats; + iwr.u.data.length = sizeof(tx_pkt_stats); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr) < 0) { + perror("txpktstats ioctl"); + return 0; + } + + printf(" Rate InitialTx SuccessTx Attempts" + " FailRetry FailExpiry\n"); + printf("--------------------------------------------" + "---------------------------\n"); + + for (idx = 0; idx < NELEMENTS(tx_pkt_stats.StatEntry); idx++) { + printf(" %5s %10u %10u %10u %10u %10u\n", + rateIdStr[idx], + (unsigned int) tx_pkt_stats.StatEntry[idx].PktInitCnt, + (unsigned int) tx_pkt_stats.StatEntry[idx].PktSuccessCnt, + (unsigned int) tx_pkt_stats.StatEntry[idx].TxAttempts, + (unsigned int) tx_pkt_stats.StatEntry[idx].RetryFailure, + (unsigned int) tx_pkt_stats.StatEntry[idx].ExpiryFailure); + + totInit += tx_pkt_stats.StatEntry[idx].PktInitCnt; + totSuccess += tx_pkt_stats.StatEntry[idx].PktSuccessCnt; + totAttempts += tx_pkt_stats.StatEntry[idx].TxAttempts; + totFailRetry += tx_pkt_stats.StatEntry[idx].RetryFailure; + totFailExpiry += tx_pkt_stats.StatEntry[idx].ExpiryFailure; + } + + printf("--------------------------------------------" + "---------------------------\n"); + printf(" %10u %10u %10u %10u %10u\n", + (unsigned int) totInit, + (unsigned int) totSuccess, + (unsigned int) totAttempts, + (unsigned int) totFailRetry, (unsigned int) totFailExpiry); + + printf("\n"); + + return 0; +} /* * @brief Get one line from the File @@ -1836,7 +3298,8 @@ * @param line A pointer to return current line number * @return returns string or NULL */ -static s8 * wlan_config_get_line(s8 *s, s32 size, FILE *stream, int *line) +static s8 * +wlan_config_get_line(s8 * s, s32 size, FILE * stream, int *line) { s8 *pos, *end, *sstart; @@ -1875,7 +3338,759 @@ return NULL; } +/* + * @brief convert hex char to integer + * + * @param c char + * @return integer or WLAN_STATUS_FAILURE + */ +static int +hex2num(s8 c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return WLAN_STATUS_FAILURE; +} + +/* + * @brief convert hex char to integer + * + * @param c char + * @return integer or WLAN_STATUS_FAILURE + */ +static int +hex2byte(const s8 * hex) +{ + s32 a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +/* + * @brief convert hex char to integer + * + * @param hex A pointer to hex string + * @param buf buffer to storege the data + * @param len + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +hexstr2bin(const s8 * hex, u8 * buf, size_t len) +{ + s32 i, a; + const s8 *ipos = hex; + s8 *opos = (s8 *) buf; + + for (i = 0; i < len; i++) { + a = hex2byte(ipos); + if (a < 0) + return WLAN_STATUS_FAILURE; + *opos++ = a; + ipos += 2; + } + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse string + * + * @param value A pointer to string + * @param buf buffer to storege the data + * @param str buffer to hold return string + * @param len use to return the length of parsed string + * @param maxlen use to return the max length of ssid + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_config_parse_string(const s8 * value, s8 * str, size_t * len, + size_t * maxlen) +{ + s8 *p; + p = strchr(value, ','); + if (p) { + *maxlen = (u16) a2hex_or_atoi(p + 1); + *p = '\0'; + } + + if (*value == '"') { + s8 *pos; + value++; + pos = strchr(value, '"'); + + if (pos == NULL || pos[1] != '\0') { + value--; + return WLAN_STATUS_FAILURE; + } + *pos = '\0'; + *len = strlen(value); + strcpy(str, value); + return WLAN_STATUS_SUCCESS; + } else { + s32 hlen = strlen(value); + + if (hlen % 1) + return WLAN_STATUS_FAILURE; + *len = hlen / 2; + if (str == NULL) + return WLAN_STATUS_FAILURE; + if (hexstr2bin(value, (u8 *) str, *len)) { + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + } +} + +/* + * @brief parse bgscan action + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to Action buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_action(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->Action = (u16) a2hex_or_atoi(value); + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan enable parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to Enable buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_enable(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->Enable = (u8) a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan BssType + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to BssType buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_bsstype(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->BssType = (u8) a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan channels per scan parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to channels per scan buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_channelsperscan(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->ChannelsPerScan = (u8) a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan scan interval parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to scan interval buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_scaninterval(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->ScanInterval = (u32) a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan store condition parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to store condition buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_storecondition(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->StoreCondition = a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan report conditions parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to report conditionsn buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_reportconditions(u8 * CmdBuf, s32 line, s8 * value) +{ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config = + (HostCmd_DS_802_11_BG_SCAN_CONFIG *) CmdBuf; + + bgscan_config->ReportConditions = a2hex_or_atoi(value); + + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan ssid parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to ssid buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +bgscan_parse_ssid(u8 * CmdBuf, s32 line, s8 * value) +{ + static int ssidCnt; + + s8 *buf = NULL; + size_t len = 0; + size_t maxlen = 0; + + MrvlIEtypes_WildCardSsIdParamSet_t *WildcardSsIdParamSet = NULL; + WildcardSsIdParamSet = (MrvlIEtypes_WildCardSsIdParamSet_t *) (CmdBuf + + + ActualPos); + if (value != NULL) { + buf = (s8 *) malloc(strlen(value)); + if (buf == NULL) + return WLAN_STATUS_FAILURE; + } else { + printf("Invalid SSID\n"); + return WLAN_STATUS_FAILURE; + } + memset(buf, 0, strlen(value)); + + if (ssidCnt >= MRVDRV_MAX_SSID_LIST_LENGTH) { + printf("Too many SSIDs\n"); + free(buf); + return WLAN_STATUS_FAILURE; + } + + if (wlan_config_parse_string(value, buf, &len, &maxlen)) { + printf("Invalid SSID\n"); + free(buf); + return WLAN_STATUS_FAILURE; + } + ssidCnt++; + if (!strlen(buf)) { + printf("The %dth SSID is NULL.\n", ssidCnt); + free(buf); + return WLAN_STATUS_FAILURE; + } + //It will be treated as specific scan in firmware only if MaxSsidLength=0 + WildcardSsIdParamSet->Header.Type = cpu_to_le16(TLV_TYPE_WILDCARDSSID); + WildcardSsIdParamSet->Header.Len = + strlen(buf) + sizeof(WildcardSsIdParamSet->MaxSsidLength); + WildcardSsIdParamSet->MaxSsidLength = maxlen; + TLVSsidSize += + WildcardSsIdParamSet->Header.Len + sizeof(MrvlIEtypesHeader_t); + ActualPos += + WildcardSsIdParamSet->Header.Len + sizeof(MrvlIEtypesHeader_t); + WildcardSsIdParamSet->Header.Len = + cpu_to_le16(WildcardSsIdParamSet->Header.Len); + memcpy(WildcardSsIdParamSet->SsId, buf, strlen(buf)); + + free(buf); + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan probes parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to probes buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_probes(u8 * CmdBuf, s32 line, s8 * value) +{ + MrvlIEtypes_NumProbes_t *Probes = NULL; + +#define PROBES_PAYLOAD_SIZE 2 + + Probes = (MrvlIEtypes_NumProbes_t *) (CmdBuf + ActualPos); + + Probes->Header.Type = TLV_TYPE_NUMPROBES; + Probes->Header.Len = PROBES_PAYLOAD_SIZE; + + Probes->NumProbes = (u16) a2hex_or_atoi(value); + + if (Probes->NumProbes) { + TLVProbeSize += sizeof(MrvlIEtypesHeader_t) + Probes->Header.Len; + } else { + TLVProbeSize = 0; + } + + ActualPos += TLVProbeSize; + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan channel list parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to channel list buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +bgscan_parse_channellist(u8 * CmdBuf, s32 line, s8 * value) +{ + MrvlIEtypes_ChanListParamSet_t *chan; + char *buf, *grp0, *grp1; + s32 len, idx; + + chan = (MrvlIEtypes_ChanListParamSet_t *) (CmdBuf + ActualPos); + + len = strlen(value) + 1; + buf = malloc(len); + + if (buf == NULL) { + return WLAN_STATUS_FAILURE; + } + + memset(buf, 0, len); + strcpy(buf, value); + + chan->Header.Type = cpu_to_le16(TLV_TYPE_CHANLIST); + grp1 = buf; + idx = 0; + while ((grp1 != NULL) && (*grp1 != 0)) { + + grp0 = strsep(&grp1, "\";"); + + if ((grp0 != NULL) && (*grp0 != 0)) { + char *ps8Resultstr = NULL; + + ps8Resultstr = strtok(grp0, ","); + if (ps8Resultstr == NULL) { + goto failure; + } + chan->ChanScanParam[idx].RadioType = atoi(ps8Resultstr); + ps8Resultstr = strtok(NULL, ","); + if (ps8Resultstr == NULL) { + goto failure; + } + chan->ChanScanParam[idx].ChanNumber = atoi(ps8Resultstr); + + ps8Resultstr = strtok(NULL, ","); + if (ps8Resultstr == NULL) { + goto failure; + } + chan->ChanScanParam[idx].ChanScanMode.PassiveScan + = atoi(ps8Resultstr); + + chan->ChanScanParam[idx].ChanScanMode.DisableChanFilt = 1; + + ps8Resultstr = strtok(NULL, ","); + if (ps8Resultstr == NULL) { + goto failure; + } + chan->ChanScanParam[idx].MinScanTime = atoi(ps8Resultstr); + + ps8Resultstr = strtok(NULL, ","); + if (ps8Resultstr == NULL) { + goto failure; + } + chan->ChanScanParam[idx].MaxScanTime = atoi(ps8Resultstr); + idx++; + } + } + + chan->Header.Len = (idx * sizeof(ChanScanParamSet_t)); + TLVChanSize += (chan->Header.Len + sizeof(MrvlIEtypesHeader_t)); + chan->Header.Len = cpu_to_le16(chan->Header.Len); + ActualPos += TLVChanSize; + + free(buf); + return WLAN_STATUS_SUCCESS; + failure: + free(buf); + printf("Invalid string:Check the bg_scan config file\n"); + return WLAN_STATUS_FAILURE; +} + +/* + * @brief parse bgscan snr threshold parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to bgscan snr threshold buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_snrthreshold(u8 * CmdBuf, s32 line, s8 * value) +{ + MrvlIEtypes_SnrThreshold_t *SnrThreshold = NULL; + u32 tmp; + + SnrThreshold = (MrvlIEtypes_SnrThreshold_t *) (CmdBuf + ActualPos); + + SnrThreshold->Header.Type = TLV_TYPE_SNR_LOW; + SnrThreshold->Header.Len = (sizeof(MrvlIEtypes_SnrThreshold_t) + - sizeof(SnrThreshold->Header)); + + tmp = (u16) a2hex_or_atoi(value); + SnrThreshold->SNRValue = tmp & 0xff; + SnrThreshold->SNRFreq = (tmp >> 8) & 0xff; + + TLVSnrSize += sizeof(MrvlIEtypes_SnrThreshold_t); + ActualPos += sizeof(MrvlIEtypes_SnrThreshold_t); + return WLAN_STATUS_SUCCESS; +} + +/* + * @brief parse bgscan start later parameter + * + * @param CmdBuf A pointer to command buffer + * @param line line number + * @param value A pointer to bgscan start later buffer + * @return WLAN_STATUS_SUCCESS + */ +static int +bgscan_parse_startlater(u8 * CmdBuf, s32 line, s8 * value) +{ + MrvlIEtypes_StartBGScanLater_t *StartBGScanLater = NULL; + + StartBGScanLater = + (MrvlIEtypes_StartBGScanLater_t *) (CmdBuf + ActualPos); + + StartBGScanLater->Header.Type = TLV_TYPE_STARTBGSCANLATER; + StartBGScanLater->Header.Len = PROBES_PAYLOAD_SIZE; + + StartBGScanLater->StartLater = (u16) a2hex_or_atoi(value); + + TLVStartBGScanLaterSize + = sizeof(MrvlIEtypesHeader_t) + StartBGScanLater->Header.Len; + ActualPos += TLVStartBGScanLaterSize; + return WLAN_STATUS_SUCCESS; +} + +static struct bgscan_fields +{ + s8 *name; + int (*parser) (u8 * CmdBuf, s32 line, s8 * value); +} bgscan_fields[] = { + { + "Action", bgscan_parse_action}, { + "Enable", bgscan_parse_enable}, { + "BssType", bgscan_parse_bsstype}, { + "ChannelsPerScan", bgscan_parse_channelsperscan}, { + "ScanInterval", bgscan_parse_scaninterval}, { + "ReportConditions", bgscan_parse_reportconditions}, { + "SSID", bgscan_parse_ssid}, { + "Probes", bgscan_parse_probes}, { + "ChannelList", bgscan_parse_channellist}, { + "SnrThreshold", bgscan_parse_snrthreshold}, { + "StoreCondition", bgscan_parse_storecondition}, { +"StartLater", bgscan_parse_startlater},}; + +/* + * @brief get bgscan data + * + * @param fp A pointer to file stream + * @param line A pointer to line number + * @param bgscan_config A pointer to HostCmd_DS_802_11_BG_SCAN_CONFIG structure + * @return WLAN_STATUS_SUCCESS + */ +static int +wlan_get_bgscan_data(FILE * fp, int *line, + HostCmd_DS_802_11_BG_SCAN_CONFIG * bgscan_config) +{ + s32 errors = 0, i, end = 0; + s8 buf[256], *pos, *pos2; + + while ((pos = wlan_config_get_line(buf, sizeof(buf), fp, line))) { + if (strcmp(pos, "}") == 0) { + end = 1; + break; + } + + pos2 = strchr(pos, '='); + if (pos2 == NULL) { + printf("Line %d: Invalid bgscan line '%s'.", *line, pos); + errors++; + continue; + } + + *pos2++ = '\0'; + if (*pos2 == '"') { + if (strchr(pos2 + 1, '"') == NULL) { + printf("Line %d: invalid quotation '%s'.", *line, pos2); + errors++; + continue; + } + } + + for (i = 0; i < NELEMENTS(bgscan_fields); i++) { + if (strncmp(pos, bgscan_fields[i].name, + strlen(bgscan_fields[i].name)) == 0) { + if (bgscan_fields[i].parser((u8 *) bgscan_config, + *line, pos2)) { + printf("Line %d: failed to parse %s" + "'%s'.", *line, pos, pos2); + errors++; + } + break; + } + } + if (i == NELEMENTS(bgscan_fields)) { + printf("Line %d: unknown bgscan field '%s'.\n", *line, pos); + errors++; + } + } + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Process bgscan config + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_bg_scan_config(int argc, char *argv[]) +{ + u8 scanCfg[256], *pos, *buf = NULL; + s8 filename[48] = ""; + FILE *fp; + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgscan_config; + struct ifreq userdata; + int line = 0; + s32 CmdNum = BG_SCAN_CONFIG; + s32 Action; + u16 Size; + int ioctl_val, subioctl_val; + if (get_priv_ioctl("setgetconf", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./wlanconfig eth1 bgscanconfig \n"); + exit(1); + } + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", filename); + exit(1); + } + + buf = (u8 *) malloc(MAX_SETGET_CONF_SIZE); + if (buf == NULL) { + printf("Error: allocate memory for bgscan fail\n"); + fclose(fp); + return -ENOMEM; + } + memset(buf, 0, MAX_SETGET_CONF_SIZE); + + bgscan_config = (HostCmd_DS_802_11_BG_SCAN_CONFIG *) + (buf + sizeof(s32) + sizeof(u16)); + + while ((pos = + (u8 *) wlan_config_get_line((s8 *) scanCfg, sizeof(scanCfg), fp, + &line))) { + if (strcmp((char *) pos, "bgscan={") == 0) { + wlan_get_bgscan_data(fp, &line, bgscan_config); + } + } + + fclose(fp); + + Action = bgscan_config->Action; + + Size = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + + TLVStartBGScanLaterSize + + TLVSsidSize + TLVProbeSize + TLVChanSize + TLVSnrSize + + TLVBcProbeSize + TLVNumSsidProbeSize; + + memcpy(buf, &CmdNum, sizeof(s32)); + memcpy(buf + sizeof(s32), &Size, sizeof(u16)); + + strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); + userdata.ifr_data = buf; + + if (ioctl(sockfd, ioctl_val, &userdata)) { + fprintf(stderr, "wlanconfig: BG_SCAN is not supported by %s\n", + dev_name); + return -1; + } + + if (Action == HostCmd_ACT_GEN_GET) { + Size = *(u16 *) buf; + hexdump("BGSCAN Configuration setup", &buf[SKIP_TYPE_SIZE], Size, + ' '); + } + + free(buf); + + return WLAN_STATUS_SUCCESS; + +} + +/** + * @brief parse hex data + * @param fp A pointer to FILE stream + * @param dst A pointer to receive hex data + * @return length of hex data + */ +static int +fparse_for_hex(FILE * fp, u8 * dst) +{ + s8 *ptr; + u8 *dptr; + s8 buf[256]; + + dptr = dst; + while (fgets(buf, sizeof(buf), fp)) { + ptr = buf; + + while (*ptr) { + // skip leading spaces + while (*ptr && isspace(*ptr)) + ptr++; + + // skip blank lines and lines beginning with '#' + if (*ptr == '\0' || *ptr == '#') + break; + + if (isxdigit(*ptr)) { + ptr = convert2hex(ptr, dptr++); + } else { + /* Invalid character on data line */ + ptr++; + } + } + } + + return (dptr - dst); +} + +/** + * @brief Process calibration data + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +int +process_cal_data_ext(int argc, char *argv[]) +{ + s32 count; + u8 *buf = NULL; + FILE *fp; + s8 filename[48] = ""; + HostCmd_DS_802_11_CAL_DATA_EXT *pcal_data; + struct ifreq userdata; + s32 CmdNum = CAL_DATA_EXT_CONFIG; + int ioctl_val, subioctl_val; + u16 action; + + if (get_priv_ioctl("setgetconf", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc != 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./wlanconfig eth1 caldataext \n"); + exit(1); + } + + strncpy(filename, argv[3], MIN(sizeof(filename) - 1, strlen(argv[3]))); + if ((fp = fopen(filename, "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[1]); + exit(1); + } + + buf = malloc(MAX_SETGET_CONF_SIZE); + if (buf == NULL) { + printf("Error: allocate memory for caldata fail\n"); + fclose(fp); + return WLAN_STATUS_FAILURE; + } + memset(buf, 0, MAX_SETGET_CONF_SIZE); + pcal_data = (HostCmd_DS_802_11_CAL_DATA_EXT *) (buf + sizeof(s32)); + + count = fparse_for_hex(fp, (u8 *) pcal_data); + fclose(fp); + + action = pcal_data->Action; + memcpy(buf, &CmdNum, sizeof(s32)); + strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); + userdata.ifr_data = buf; + + if (ioctl(sockfd, ioctl_val, &userdata)) { + fprintf(stderr, "wlanconfig: CAL DATA not supported by %s\n", + dev_name); + free(buf); + return WLAN_STATUS_FAILURE; + } + + if (action == HostCmd_ACT_GET) { + printf("Cal Data revision: %04x\n", pcal_data->Revision); + hexdump("Cal Data", pcal_data->CalData, pcal_data->CalDataLen, ' '); + } + + free(buf); + return WLAN_STATUS_SUCCESS; +} /** * @brief read register @@ -1883,12 +4098,19 @@ * @param stroffset A pointer to register index string * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int process_read_register(s32 cmd, s8 *stroffset) +static int +process_read_register(s32 cmd, s8 * stroffset) { struct ifreq userdata; wlan_ioctl_regrdwr reg; s8 *whichreg; + int ioctl_val, subioctl_val; + if (get_priv_ioctl("regrdwr", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + memset(®, 0, sizeof(reg)); switch (cmd) { case CMD_RDMAC: /* @@ -1912,8 +4134,7 @@ whichreg = "RF"; break; default: - fprintf(stderr, - "Invalid Register set specified.\n"); + fprintf(stderr, "Invalid Register set specified.\n"); return -1; } @@ -1927,7 +4148,7 @@ strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = (s8 *) ® - if (ioctl(sockfd, WLANREGRDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: Register Reading not supported by" @@ -1935,8 +4156,7 @@ return WLAN_STATUS_FAILURE; } - printf("%s[0x%04lx] = 0x%08lx\n", - whichreg, reg.Offset, reg.Value); + printf("%s[0x%04lx] = 0x%08lx\n", whichreg, reg.Offset, reg.Value); return WLAN_STATUS_SUCCESS; } @@ -1948,11 +4168,18 @@ * @param strvalue A pointer to the register value * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int process_write_register(s32 cmd, s8 *stroffset, s8 *strvalue) +static int +process_write_register(s32 cmd, s8 * stroffset, s8 * strvalue) { struct ifreq userdata; wlan_ioctl_regrdwr reg; s8 *whichreg; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("regrdwr", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } switch (cmd) { case CMD_WRMAC: @@ -1977,8 +4204,7 @@ whichreg = "RF"; break; default: - fprintf(stderr, - "Invalid register set specified.\n"); + fprintf(stderr, "Invalid register set specified.\n"); return -1; } @@ -2000,7 +4226,7 @@ strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); userdata.ifr_data = (s8 *) ® - if (ioctl(sockfd, WLANREGRDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &userdata)) { perror("wlanconfig"); fprintf(stderr, "wlanconfig: Register Writing not supported " @@ -2008,83 +4234,374 @@ return WLAN_STATUS_FAILURE; } - printf("%s[0x%04lx] = 0x%08lx\n", - whichreg, reg.Offset, reg.Value); + printf("%s[0x%04lx] = 0x%08lx\n", whichreg, reg.Offset, reg.Value); return WLAN_STATUS_SUCCESS; } /** - * @brief read CF register - * - * @param stroffset A pointer to register index string - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + * @brief iwpriv command hostsleepcfg + * @param cond condition + * @param gpio GPIO number + * @param gap Gap + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -static int process_read_cfreg(s8 *stroffset) +static int +do_hostsleepcfg(u32 cond, u8 gpio, u8 gap) { - struct ifreq userdata; - wlan_ioctl_cfregrdwr reg; + struct iwreq iwr; + u8 buf[32]; + int maxlen = sizeof(buf) - 1; + int ioctl_val, subioctl_val; - reg.Action = 0; //Read register + if (get_priv_ioctl("hostsleepcfg", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return WLAN_STATUS_FAILURE; + } - if (!strncasecmp(stroffset, "0x", 2)) - reg.Offset = a2hex((stroffset + 2)); - else - reg.Offset = atoi(stroffset); + snprintf((char *) buf, maxlen, "0%lx 0%x 0%x", cond, gpio, gap); + buf[maxlen] = 0; - strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); - userdata.ifr_data = (s8 *) ® + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (u8 *) buf; + iwr.u.data.length = strlen((char *) buf); - if (ioctl(sockfd, WLANREGCFRDWR, &userdata)) { + if (ioctl(sockfd, ioctl_val, &iwr)) { perror("wlanconfig"); fprintf(stderr, - "wlanconfig: Register reading not supported " - "by interface %s\n", dev_name); + "wlanconfig: hostsleepcfg not supported by " + "interface %s\n", dev_name); return WLAN_STATUS_FAILURE; } - printf("CFREG[0x%04X] = 0x%04X\n", - reg.Offset, reg.Value); - return WLAN_STATUS_SUCCESS; +} +/** + * @brief decode wireless custom event + * + * @param h A pointer to structure nlmsghdr + * @param left number of message for decoding + * @param queue_id message queue ID + * @return number of message leftover + */ +static int +decode_iwevcustom(struct nlmsghdr *h, int left) +{ + int len, plen, attrlen, nlmsg_len, rta_len; + struct ifinfomsg *ifi; + struct rtattr *attr; + + while (left >= sizeof(*h)) { + len = h->nlmsg_len; + plen = len - sizeof(*h); + if (len > left || plen < 0) { + printf("malformed netlink message: len=%d left=%d plen=%d", + len, left, plen); + break; + } + if (h->nlmsg_type != RTM_NEWLINK) { + break; + } + if (plen < sizeof(*ifi)) { + printf("[plen=%d] < [sizeof(strcut ifinfomsg)=%d]\n", + h->nlmsg_type, sizeof(*ifi)); + break; + } + + ifi = NLMSG_DATA(h); + nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); + attrlen = h->nlmsg_len - nlmsg_len; + if (attrlen < 0) { + printf("h->nlmsg_len=%d nlmsg_len=%d attrlen=%d\n", + h->nlmsg_len, nlmsg_len, attrlen); + break; + } + + attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + while (RTA_OK(attr, attrlen)) { + if (attr->rta_type == IFLA_WIRELESS) { + struct iw_event *iwe; + char *pos = ((char *) attr) + rta_len; + char *end = pos + (attr->rta_len - rta_len); + char *custom; + u16 dlen; + + while (pos + IW_EV_LCP_LEN <= end) { + iwe = (struct iw_event *) pos; + if ((iwe->len <= IW_EV_LCP_LEN) + || (iwe->cmd != IWEVCUSTOM)) + break; + + custom = pos + IW_EV_POINT_LEN; + if (IW_EV_POINT_LEN == + IW_EV_LCP_LEN + sizeof(struct iw_point)) { + dlen = iwe->u.data.length; + } else { /* WIRELESS_EXT >= 19 */ + dlen = *((u16 *) (pos + IW_EV_LCP_LEN)); + } + if (custom + dlen > end) { + printf("corrupt custom wireless event: '%s'\n", + custom); + break; + } + + if (strlen(CUS_EVT_HS_ACTIVATED) == strlen(custom) + && !strncmp(CUS_EVT_HS_ACTIVATED, custom, + strlen(CUS_EVT_HS_ACTIVATED))) { + hs_state = HS_STATE_ACTIVATED; + printf("Host Sleep Activated\n"); + } else if (strlen(CUS_EVT_HS_DEACTIVATED) == + strlen(custom) + && !strncmp(CUS_EVT_HS_DEACTIVATED, custom, + strlen(CUS_EVT_HS_DEACTIVATED))) { + hs_state = HS_STATE_DEACTIVATED; + printf("Host Sleep Deactivated\n"); + } else if (strlen(CUS_EVT_HS_GPIO_INT) == strlen(custom) + && !strncmp(CUS_EVT_HS_GPIO_INT, custom, + strlen(CUS_EVT_HS_GPIO_INT))) { + if (hs_state != HS_STATE_GPIO_INT) { + hs_state = HS_STATE_GPIO_INT; + if (do_hostsleepcfg(HOST_SLEEP_CFG_CANCEL, 0, 0) + != WLAN_STATUS_SUCCESS) { + printf("do_hostsleepcfg(cancel) failed\n"); + } + } + } + pos += iwe->len; + } + } + attr = RTA_NEXT(attr, attrlen); + } + + len = NLMSG_ALIGN(len); + left -= len; + h = (struct nlmsghdr *) ((char *) h + len); + } + + return left; } /** - * @brief write CF register + * @brief NETLINK message receiver * - * @param stroffset A pointer to register index string - * @param strvalue A pointer to the register value * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int process_write_cfreg(s8 *stroffset, s8 *strvalue) +static int +netlink_msg_receiver(void) { - struct ifreq userdata; - wlan_ioctl_cfregrdwr reg; + struct sockaddr_nl local; + int sock_nl = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - reg.Action = 1; //Write register + if (sock_nl < 0) { + fprintf(stderr, + "wlanconfig hstest: socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)" + "returned %d\n", sock_nl); + return WLAN_STATUS_FAILURE; + } - if (!strncasecmp(stroffset, "0x", 2)) - reg.Offset = a2hex((stroffset + 2)); - else - reg.Offset = atoi(stroffset); + memset(&local, 0, sizeof(local)); + local.nl_family = AF_NETLINK; + local.nl_groups = RTMGRP_LINK; + if (bind(sock_nl, (struct sockaddr *) &local, sizeof(local)) < 0) { + fprintf(stderr, "wlanconfig hstest: bind(%d) failed\n", sock_nl); + close(sock_nl); + return WLAN_STATUS_FAILURE; + } - if (!strncasecmp(strvalue, "0x", 2)) - reg.Value = a2hex((strvalue + 2)); - else - reg.Value = atoi(strvalue); + while (1) { + fd_set rfds; + int retval; + struct sockaddr_nl from; + socklen_t fromlen = sizeof(from); + char msg[MAX_MSG_SIZE]; + int left; - strncpy(userdata.ifr_name, dev_name, IFNAMSIZ); - userdata.ifr_data = (s8 *) ® + FD_ZERO(&rfds); + FD_SET(sock_nl, &rfds); + retval = select(sock_nl + 1, &rfds, NULL, NULL, NULL); + if ((retval < 0 && errno != EINTR) || !FD_ISSET(sock_nl, &rfds)) { + fprintf(stderr, "wlanconfig hstest: select() failed, errno=%d\n", + errno); + close(sock_nl); + return WLAN_STATUS_FAILURE; + } - if (ioctl(sockfd, WLANREGCFRDWR, &userdata)) { - perror("wlanconfig"); + left = recvfrom(sock_nl, msg, sizeof(msg), MSG_DONTWAIT, + (struct sockaddr *) &from, &fromlen); + if (left < 0) { fprintf(stderr, - "wlanconfig: Register writing not supported " - "by interface %s\n", dev_name); + "wlanconfig hstest: recvfrom() failed, errno=%d\n", + errno); + close(sock_nl); + return WLAN_STATUS_FAILURE; + } + + left = decode_iwevcustom((struct nlmsghdr *) msg, left); + } + close(sock_nl); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief test Host Sleep + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +process_hs_test(void) +{ + netlink_msg_receiver(); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get the CFP table based on the region code + * + * @param argc number of arguments + * @param argv A pointer to arguments array + * + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_getcfptable(int argc, char *argv[]) +{ + pwlan_ioctl_cfp_table cfptable; + int ioctl_val, subioctl_val; + struct iwreq iwr; + int region = 0; + int i; + + if (get_priv_ioctl("getcfptable", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc > 4) { + printf("Error: invalid number of arguments\n"); + printf("Syntax: ./wlanconfig ethX getcfptable [regioncode]"); + return -EINVAL; + } + + if (argc == 4) { + if ((region = atoval(argv[3])) < 0) + return -EINVAL; + } + + cfptable = (pwlan_ioctl_cfp_table) malloc(sizeof(wlan_ioctl_cfp_table)); + if (cfptable == NULL) { + printf("Error: allocate memory for CFP table failed\n"); + return -ENOMEM; + } + memset(cfptable, 0, sizeof(wlan_ioctl_cfp_table)); + + cfptable->region = region; + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) cfptable; + iwr.u.data.length = sizeof(wlan_ioctl_cfp_table); + iwr.u.data.flags = subioctl_val; + + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, "wlanconfig: get CFP table failed\n"); + free(cfptable); return WLAN_STATUS_FAILURE; } + printf("-------------------------------\n"); + printf(" # | ch | freq | max_tx_power\n"); + printf("-------------------------------\n"); + + for (i = 0; i < cfptable->cfp_no; i++) { + printf(" %02u | %03d | %04ld | %02d\n", + i + 1, + cfptable->cfp[i].Channel, + cfptable->cfp[i].Freq, cfptable->cfp[i].MaxTxPower); + } + + free(cfptable); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Process arpfilter + * @param argc number of arguments + * @param argv A pointer to arguments array + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +process_arpfilter(int argc, char *argv[]) +{ + s8 line[256], *pos; + u8 *buf; + FILE *fp; + struct iwreq iwr; + int ln = 0; + int arpfilter_found = 0; + u16 length = 0; + int ret = WLAN_STATUS_SUCCESS; + int ioctl_val, subioctl_val; + + if (get_priv_ioctl("arpfilter", + &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) { + return -EOPNOTSUPP; + } + + if (argc < 4) { + printf("Error: invalid no of arguments\n"); + printf("Syntax: ./wlanconfig eth1 arpfilter \n"); + exit(1); + } + + if ((fp = fopen(argv[3], "r")) == NULL) { + fprintf(stderr, "Cannot open file %s\n", argv[3]); + exit(1); + } + + buf = (u8 *) malloc(MRVDRV_SIZE_OF_CMD_BUFFER); + if (buf == NULL) { + printf("Error: allocate memory for arpfilter failed\n"); + return -ENOMEM; + } + memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER); + + arpfilter_found = 0; + while ((pos = wlan_config_get_line(line, sizeof(line), fp, &ln))) { + if (strcmp(pos, "arpfilter={") == 0) { + arpfilter_found = 1; + wlan_get_hostcmd_data(fp, &ln, buf + length, &length); + break; + } + } + + fclose(fp); + + if (!arpfilter_found) { + fprintf(stderr, "wlanconfig: 'arpfilter' not found in file '%s'\n", + argv[3]); + ret = -1; + goto _exit_; + } + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, dev_name, IFNAMSIZ); + iwr.u.data.pointer = buf; + iwr.u.data.length = length; + + iwr.u.data.flags = 0; + if (ioctl(sockfd, ioctl_val, &iwr)) { + fprintf(stderr, "wlanconfig: WLANARPFILTER failed\n"); + ret = -1; + goto _exit_; + } + + _exit_: + if (buf) + free(buf); + return WLAN_STATUS_SUCCESS; } @@ -2097,10 +4614,15 @@ * @param argv A pointer to arguments array * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -int main(int argc, char *argv[]) +int +main(int argc, char *argv[]) { s32 cmd; + if ((argc == 2) && (strcmp(argv[1], "-v") == 0)) { + fprintf(stdout, "Marvell wlanconfig version %s\n", WLANCONFIG_VER); + exit(0); + } if (argc < 3) { fprintf(stderr, "Invalid number of parameters!\n"); display_usage(); @@ -2146,8 +4668,7 @@ display_usage(); exit(1); } - if (process_write_register(cmd, argv[3], - argv[4])) { + if (process_write_register(cmd, argv[3], argv[4])) { fprintf(stderr, "Write command failed!\n"); exit(1); } @@ -2161,34 +4682,40 @@ case CMD_CMD53R: process_sdcmd53r(); break; - case CMD_CFREGR: - printf("process read cfreg\n"); - if (argc < 4) { - fprintf(stderr, "Register offset required!\n"); - display_usage(); + case CMD_BG_SCAN_CONFIG: + process_bg_scan_config(argc, argv); + break; + case CMD_WMM_QSTATUS: + process_wmm_qstatus(argc, argv); + break; + case CMD_TX_PKT_STATS: + process_txpktstats(argc, argv); + break; + case CMD_ADDTS: + if (process_addts(argc, argv)) { exit(1); } - if (process_read_cfreg(argv[3])) { - fprintf(stderr, "Read CF register failed\n"); - display_usage(); + break; + case CMD_DELTS: + if (process_delts(argc, argv)) { exit(1); } break; - case CMD_CFREGW: - printf("process write cfreg\n"); - if (argc < 5) { - fprintf(stderr, "Register offset required!\n"); - display_usage(); + case CMD_QCONFIG: + if (process_qconfig(argc, argv)) { exit(1); } - if (process_write_cfreg(argv[3], argv[4])) { - fprintf(stderr, "Read CF register failed\n"); - display_usage(); + break; + case CMD_QSTATS: + if (process_qstats(argc, argv)) { exit(1); } break; + case CMD_CAL_DATA_EXT: + process_cal_data_ext(argc, argv); + break; case CMD_RDEEPROM: - printf("proces read eeprom\n"); + printf("process read eeprom\n"); if(argc < 5) { fprintf(stderr, "Register offset, number of bytes required\n"); @@ -2202,13 +4729,6 @@ exit(1); } break; - case CMD_GETRATE: - if (process_get_rate()) { - fprintf(stderr, "Get Rate Failed\n"); - display_usage(); - exit(1); - } - break; case CMD_SLEEPPARAMS: if (process_sleep_params(argc, argv)) { fprintf(stderr, "Sleep Params Failed\n"); @@ -2231,12 +4751,17 @@ } break; case CMD_SCAN_LIST: - if (process_scan_results(argc, argv)) { + if (process_scanlist(argc, argv)) { fprintf(stderr, "getscanlist Failed\n"); display_usage(); exit(1); } break; + case CMD_SET_GEN_IE: + if (process_setgenie()) { + exit(1); + } + break; case CMD_GET_SCAN_RSP: if (process_getscantable(argc, argv)) { exit(1); @@ -2249,6 +4774,35 @@ } break; + case CMD_SET_MRVL_TLV: + if (process_setmrvltlv()) { + exit(1); + } + break; + + case CMD_GET_ASSOC_RSP: + if (process_getassocrsp()) { + exit(1); + } + break; + case CMD_HS_TEST: + if (process_hs_test()) { + exit(1); + } + break; + case CMD_GET_TSF: + if (process_gettsf()) { + exit(1); + } + break; + case CMD_GET_CFP_TABLE: + if (process_getcfptable(argc, argv)) { + exit(1); + } + break; + case CMD_ARPFILTER: + process_arpfilter(argc, argv); + break; default: fprintf(stderr, "Invalid command specified!\n"); display_usage(); diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/wlanconfig.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/wlanconfig.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/app/wlanconfig/wlanconfig.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/app/wlanconfig/wlanconfig.h 2007-11-06 12:26:40.000000000 -0500 @@ -3,13 +3,12 @@ * @brief This file contains definitions for application * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -44,7 +43,8 @@ #define WCON_WMM_ENABLED 1 /** struct of SSID network name */ -typedef struct _WCON_SSID { +typedef struct _WCON_SSID +{ /** SSID name length */ u32 ssid_len; /** SSID name string */ @@ -54,7 +54,8 @@ typedef u8 WCON_BSSID[ETH_ALEN]; /** struct of SSID network information */ -typedef struct _WCON_NET_INFO { +typedef struct _WCON_NET_INFO +{ /** SSID network name struct */ WCON_SSID Ssid; /** hardware address of the SSID network */ @@ -72,11 +73,11 @@ } WCON_NET_INFO; /** struct of SSID list from scan */ -typedef struct _WCON_HANDLE { +typedef struct _WCON_HANDLE +{ /** list of scan result */ WCON_NET_INFO ScanList[IW_MAX_AP]; int ApNum; } WCON_HANDLE; #endif /* _WLANCONFIG_H_ */ - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/arpfilter.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/arpfilter.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/arpfilter.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/arpfilter.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,40 @@ +# File : arpfilter.conf +# +# (c) Copyright © 2003-2007, Marvell International Ltd. +# +# This software file (the "File") is distributed by Marvell International +# Ltd. under the terms of the GNU General Public License Version 2, June 1991 +# (the "License"). You may use, redistribute and/or modify this File in +# accordance with the terms and conditions of the License, a copy of which +# is available along with the File in the gpl.txt file or by writing to +# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. +# +# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE +# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE +# ARE EXPRESSLY DISCLAIMED. The License provides additional details about +# this warranty disclaimer. +# + +######################### Host Sleep ARP/IP filtering command ################## +# add arp filter +# must not exceed 20 bytes +arpfilter={ + TlvType:2=0x0115 + TlvLength:2={ + AddrType:2=3 # multicast + EthType:2=0x0008 # IPv4: 0x0800 + Ipv4Addr:4=0xffffffff # not used + AddrType:2=1 # broadcast + EthType:2=0x0608 # ARP: 0x0806 + Ipv4Addr:4=0x5800a8c0 # 192.168.0.88 + } +} + +# remove arp filter +#arpfilter={ +# TlvType:2=0x0115 +# TlvLength:2={ +# } +#} +######################### Host Sleep ARP/IP filtering command ################## diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/bg_scan.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/bg_scan.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/bg_scan.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/bg_scan.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,101 @@ +# File : bg_scan_config.conf +# +# (c) Copyright © 2003-2006, Marvell International Ltd. +# +# This software file (the "File") is distributed by Marvell International +# Ltd. under the terms of the GNU General Public License Version 2, June 1991 +# (the "License"). You may use, redistribute and/or modify this File in +# accordance with the terms and conditions of the License, a copy of which +# is available along with the File in the gpl.txt file or by writing to +# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. +# +# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE +# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE +# ARE EXPRESSLY DISCLAIMED. The License provides additional details about +# this warranty disclaimer. +# + +bgscan={ + Action=1 # 1 - set configuration 0 - get previous configuration + + BssType=3 # 1 - Infrastructure + # 2 - IBSS + # 3 - Any + + ChannelsPerScan=14 # Number of Channel to scan at one scan; maximum 14 + + ScanInterval=1000 # Interval between consecutive scan (in milliseconds) + + StoreCondition=1 # 1 - SSID match (bit 0) + # 2 - SSID match AND SNR above SNR threshold (bit 1) + + ReportConditions=1 # 1 - SSID match (bit 0) + # 2 - SSID match AND SNR above SNR threshold (bit 1) + + +# SSID entries: +# +# 1. SSID="" - to denote NULL SSID, which is considered +# as SSID with length 0. +# 2. SSID="AP_NAME" - to mention a specific SSID to match. +# 3. SSID="AP_NAME",maxlen - wildcard AP_NAME will be use to base match +# the SSID, and SSID's max length is max length +# 4. SSID="AP_NAME%",% - wildcard AP_NAME% will be use to match +# the SSID with the % being a single char wildcard +# 5. SSID="AP?NAME*",255 - wildcard AP*NAME will be use to match the SSID. + +# SSID Examples: +# +# SSID="AP_NAME" # match AP_NAME exactly, generate SSID specific probes +# SSID="AP_NAME",0 # match AP_NAME exactly, generate SSID specific probes +# SSID="AP*NAME" # match AP*NAME exactly, generate SSID specific probes +# SSID="AP_NAME",7 # match "AP_NAME" exactly, do not generate SSID + # specific probe requests +# SSID="AP_NAME*",8 # match "AP_NAME*" exactly, do not generate SSID + # specific probe requests +# SSID="AP_NAME",4 # match "AP_N" exactly, do not generate SSID + # specific probe requests +# SSID="AP_NAME",9 # match "AP_NAME" as a base and SSID's max length is 9 +# SSID="AP*NAME",* # match "AP*NAME" where '*' is a single char +# SSID="AP?NAME",? # match "AP?NAME" where '?' is a single char +# SSID="AP?NAME*,255 # match "AP?NAME*" with unix pattern matching + +# For each entry requiring a SSID specific probe request, "Numprobes" of +# SSID specific probe requests will be transmitted per channel. +# +# If any SSID in the list has a non-zero modifier (wildcard match char, +# unix pattern match, maxlen), "Numprobes" of broadcast probe requests +# will be transmitted once per channel and the results matched against +# all entries. + + SSID="MarvellAP" + + Probes=2 # Number Probe requests to be sent for broadcast and + # for each SSID specific scan required. + # + # Set to 0 to use global scan probes setting + # + + + # ChannelList contains the channels to scan + # The ChannelList should be specified in the form of + # + # RadioType, ChanNumber, ScanType, MinScanTime, ScanTime; + # + # RadioType - 0 [B/G Band], 1 [A Band] + # ScanType - 0 [Active], 1 [Passive] + # + # The next channel description should be separated by semicolon operator + + ChannelList="0,10,0,10,100;0,6,1,10,100" + + + SnrThreshold=40 # SNR threshold to match, when StoreCondition + # or ReportConditions been set to 2 + + StartLater=0 # 0 - BGScan start immediately + # 1 - BGScan will start later after "Scan Interval" + +} + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_v5.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_v5.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_v5.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_v5.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,7 @@ +01 00 # 01 00: SET, 00 00: GET +05 00 40 00 +#from CF8385 EEPROM 0x80 +43 46 2d 32 35 70 00 ab 05 02 00 09 06 00 06 00 +06 00 06 00 06 00 06 00 06 00 06 00 06 00 06 00 +06 00 06 00 06 00 04 00 8f ce 18 5d 10 00 00 00 +10 40 00 80 12 11 08 00 01 00 01 01 04 78 05 f6 diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_v7.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_v7.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_v7.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_v7.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,19 @@ +01 00 # 01 00: SET, 00 00: GET +07 00 00 01 +#from CF8385H EEPROM 0x80, set v7 +07 24 44 98 01 01 00 00 00 03 e2 3b 00 00 10 03 +20 00 20 01 88 20 03 10 01 01 02 02 10 01 00 00 +00 00 03 4f 0c 8f ce 18 08 00 00 00 08 00 00 00 +08 00 00 00 08 00 00 00 07 00 00 00 07 00 00 00 +06 00 00 00 05 00 00 00 04 00 00 00 04 00 00 00 +03 00 00 00 03 00 00 00 02 00 00 00 02 00 00 00 +dd 22 40 06 00 00 03 11 04 95 00 00 fb 08 00 00 +fa 08 00 00 f9 08 00 00 f8 08 00 00 f8 08 00 00 +f7 08 00 00 f6 08 00 00 f6 08 00 00 f8 08 00 00 +f8 08 00 00 f8 08 00 00 f9 08 00 00 f9 08 00 00 +f9 08 00 00 f9 08 00 00 fa 08 00 00 f9 08 00 00 +f9 08 00 00 f9 08 00 00 fc 0c 00 00 fc 0c 00 00 +fc 0c 00 00 fc 0c 00 00 fd 0c 00 00 03 09 00 00 +02 09 00 00 01 09 00 00 fd 09 00 00 fc 09 00 00 +fa 09 00 00 f9 09 00 00 04 09 00 00 04 09 00 00 +04 09 00 00 04 09 00 00 00 22 40 06 0d 2b 1d d1 diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_vA.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_vA.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/cal_data_ext_set_vA.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/cal_data_ext_set_vA.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,31 @@ +01 00 # 01 00: SET, 00 00: GET +0a 00 b0 01 +#from GSPI8385 EEPROM Rev A +00 00 00 00 01 01 01 01 0a 00 00 a0 00 00 00 40 +04 71 ed 00 00 fe 00 00 ff f9 00 00 00 00 00 00 +14 0f 14 0f 8f ce 18 14 8f ce 18 14 10 00 00 00 +10 1f 00 00 10 11 10 00 01 00 01 01 04 48 00 1f +01 98 00 50 00 00 00 90 00 fe 00 00 ff f9 00 00 +00 00 00 00 0e 0b 0e 0b 8f ce 18 0e 8f ce 18 0e +00 fe 00 00 ff f9 00 00 00 00 00 00 0a 06 0a 06 +8f ca 0a 0a 8f ce 18 0a 00 fe 00 00 ff f9 00 00 +00 00 00 00 05 00 05 00 86 ca 10 05 86 ca 18 05 +02 b1 00 1c 00 00 00 ac 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 03 94 00 1c +00 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 04 6f 00 20 00 00 00 e8 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 05 71 00 10 00 00 00 f8 +00 ff ff ff 00 00 00 00 07 74 00 5c 00 00 01 54 +00 0c 0a 54 01 0f 0d 5c 02 12 10 64 03 14 12 68 +04 17 15 70 05 1a 18 78 06 1f 1d 6c 07 27 25 74 +08 2f 2d 7c 09 37 35 84 0a 3f 3d 8c 0b 26 24 61 +0c 2b 29 69 0d 31 2f 71 0e 36 34 79 0f 39 37 81 +10 3c 3a 89 11 3f 3d 91 12 ff ff fd 13 ff ff fd +14 ff ff fd 08 43 00 5c ff ff ff ff 00 0a 08 70 +01 0d 0b 78 02 10 0e 80 03 12 10 88 04 15 13 90 +05 18 16 98 06 1c 1a 68 07 22 20 70 08 29 27 78 +09 2f 2d 80 0a 36 34 88 0b ff ff fd 0c ff ff fd +0d ff ff fd 0e ff ff fd 0f ff ff fd 10 ff ff fd +11 ff ff fd 12 ff ff fd 13 ff ff fd 14 ff ff fd + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/hostcmd.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/hostcmd.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/hostcmd.conf 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/hostcmd.conf 2007-11-06 12:26:40.000000000 -0500 @@ -1,13 +1,12 @@ # File : hostcmd.conf # # (c) Copyright © 2003-2006, Marvell International Ltd. -# All Rights Reserved # # This software file (the "File") is distributed by Marvell International # Ltd. under the terms of the GNU General Public License Version 2, June 1991 # (the "License"). You may use, redistribute and/or modify this File in # accordance with the terms and conditions of the License, a copy of which -# is available along with the File in the license.txt file or by writing to +# is available along with the File in the gpl.txt file or by writing to # the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. # @@ -17,6 +16,70 @@ # this warranty disclaimer. # +######################### Power Adaptation Config Ext command ################## +pa_cfg_ext_get={ + CmdCode=0x007e # do NOT change this line + + # The following table shows the bitmap of the rates: + # (bit 0 is the least significant bit) + # Bit Data rate + # 0 1 Mbps + # 1 2 Mbps + # 2 5.5 Mbps + # 3 11 Mbps + # 4 Reserved + # 5 6 Mbps + # 6 9 Mbps + # 7 12 Mbps + # 8 18 Mbps + # 9 24 Mbps + # 10 36 Mbps + # 11 48 Mbps + # 12 54 Mbps + # 13-15 Reserved + + Action:2=0 # 0 - GET + EnablePA:2=0 + TlvType:2=0x0114 + TlvLength:2={ + } +} + +pa_cfg_ext_set={ + CmdCode=0x007e # do NOT change this line + + Action:2=1 # 1 - SET + EnablePA:2=1 # 1 - enable power adaptation + TlvType:2=0x0114 + TlvLength:2={ + # Up to 5 power level groups are supported + # Power Level Rate Bitmap (Mbps) + + # 13 dbm 0x1800 (54, 48) + PowerAdaptGroup1.PowerLevel:2=13 + PowerAdaptGroup1.RateBitmap:2=0x1800 + PowerAdaptGroup1.Reserved:4=0 + + # 15 dbm 0x07e0 (36, 24, 18, 12, 9, 6) + PowerAdaptGroup2.PowerLevel:2=15 + PowerAdaptGroup2.RateBitmap:2=0x07e0 + PowerAdaptGroup2.Reserved:4=0 + + # 18 dbm 0x000f (11, 5.5, 2, 1) + PowerAdaptGroup3.PowerLevel:2=18 + PowerAdaptGroup3.RateBitmap:2=0x000f + PowerAdaptGroup3.Reserved:4=0 + +# PowerAdaptGroup4.PowerLevel:2=0 +# PowerAdaptGroup4.RateBitmap:2=0 +# PowerAdaptGroup4.Reserved:4=0 + +# PowerAdaptGroup5.PowerLevel:2=0 +# PowerAdaptGroup5.RateBitmap:2=0 +# PowerAdaptGroup5.Reserved:4=0 + } +} +######################### Power Adaptation Config Ext command ################## ######################### Subscribe Events command ################## subevent_get={ @@ -37,7 +100,7 @@ LowRssiTlvType:2=0x0104 LowRssiTlvLength:2={ - Threshold:1=40 + Threshold:1=70 ReportingFreq:1=0 } @@ -61,7 +124,7 @@ HighRssiTlvType:2=0x0116 HighRssiTlvLength:2={ - Threshold:1=70 + Threshold:1=40 ReportingFreq:1=0 } @@ -73,3 +136,327 @@ } ######################### Subscribe Events command ################## +######################### Host Sleep ARP/IP filtering command ################## +arp_filter={ + CmdCode=0x0043 # do NOT change this line + + Condition:4=0x09 # bit0 - broadcast; bit1 - unicast; bit2 - MAC event; bit3 - multicast + # 0xffffffff - cancel host_sleep_cfg + Gpio:1=0xff # 0xff - GPIO wakeup not required + # 0-7: GPIO 0-7 + Gap:1=0x80 # 128 ms + TlvType:2=0x0115 + TlvLength:2={ + AddrType:2=3 # multicast + EthType:2=0x0008 # IPv4: 0x0800 + Ipv4Addr:4=0xffffffff # not used + AddrType:2=1 # broadcast + EthType:2=0x0608 # ARP: 0x0806 + Ipv4Addr:4=0x5800a8c0 # 192.168.0.88 + } +} +######################### Host Sleep ARP/IP filtering command ################## + +######################### Auto-TX command ################## +auto_tx_get={ + CmdCode=0x0082 # do NOT change this line + + Action:2=0 # GET +} + +auto_tx_unreg={ + CmdCode=0x0082 # do NOT change this line + + Action:2=1 # SET +} + +NatKeepAlive={ + CmdCode=0x0082 # do NOT change this line + + Action:2=1 # SET + + AutoTxTlvType:2=0x0118 + AutoTxTlvLength:2={ # 58 = 6 + 52 (FrameLen) + Interval:2=2 # 1 - 3600 seconds + Priority:1=7 # Priority, ignored if non-WMM + Reserved:1=0 + FrameLength:2={ # 52 = 6 (DA) + 6 (SA) + 2 + 38 (Length) + DestMacAddr:6='0x00,0x40,0xf4,0xbf,0x24,0xee' + SrcMacAddr:6='0x00,0x00,0x00,0x00,0x00,0x00' + Length:2='0x00,38' # 38 = 8 (SNAP hdr) + 29 (IP) + 1 (padding) + DSAP:1=0xaa # SNAP header + SSAP:1=0xaa + Ctrl:1=0x03 + SNAP_OUI:3='0x00,0x00,0x00' + SNAP_PID:2='0x08,0x00' # IP Packet + IPv4:1=0x45 + IP_TOS:1=0x00 + IP_LEN:2='0x00,29' # IP hdr 20 + payload 9 = 29 + IP_ID:2=0xefbe + IP_Flag_FragOffset:2=0x0000 + IP_TTL:1=128 + IP_Prot:1=17 # UDP protocol + IPhdr_cksum:2=0xc5f9 # may need re-calculation if changed + IPsrcAddr:4='192,168,0,201' # 192.168.0.201 + IPdstAddr:4='192,168,0,1' # 192.168.0.1 + UDPsrcPort:2='0x11,0x94' # 4500 + UDPdstPort:2='0x11,0x94' # 4500 + UDPlength:2='0x00,9' # UDP hdr 8 + payload 1 = 9 + UDPcksum:2=0x985b # may need re-calculation if changed + UDPpayload:1=0xff + padding:1=0 # MAC Padding for 32bit alignment, set to 0 + } + } +} +######################### Auto-TX command ################## + +######################### MEM_ACCESS ################## +mr_c00153e4={ + CmdCode=0x0086 # do NOT change this line + + Action:2=0 # GET + Reserved:2=0 + Address:4=0xc00153e4 + Value:4=0 +} + +mw_c00153e4_0={ + CmdCode=0x0086 # do NOT change this line + + Action:2=1 # SET + Reserved:2=0 + Address:4=0xc00153e4 + Value:4=0 +} + +mw_c00153e4_aabbccdd={ + CmdCode=0x0086 # do NOT change this line + + Action:2=1 # SET + Reserved:2=0 + Address:4=0xc00153e4 + Value:4=0xaabbccdd +} +######################### MEM_ACCESS ################## + +######################### LED Ctrl command ################## +ledctrl_get={ + CmdCode=0x004e # do NOT change this line + + Action:2=0 # GET + LedNums:2=0 +} + +ledctrl_set={ + CmdCode=0x004e # do NOT change this line + + Action:2=1 # SET + LedNums:2=0 + + LedGpioTlvType:2=0x0108 + LedGpioTlvLength:2={ + LedNum:1=1 + GpioNum:1=1 + LedNum:1=2 + GpioNum:1=16 # disabled + LedNum:1=3 + GpioNum:1=16 # disabled + } + + # LED #1 Behaviors + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=0 # Disconnected + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=1 # Scanning + LedNum:1=1 # LED #1 + Led1State:1=2 # Blinking + Led1Args:1=0x04 # Arg2=0 (1/2 Duty Factor), Arg1=4 (298ms Blink Period) + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=2 # Connected-Awake + LedNum:1=1 # LED #1 + Led1State:1=1 # Steady ON + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=3 # Connected-Sleep + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=4 # Deep Sleep + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=5 # Connected-Single + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=6 # Disconnected-Link Loss + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=7 # Disconnected-Disassociated + LedNum:1=1 # LED #1 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=8 # Exception + LedNum:1=1 # LED #1 + Led1State:1=2 # Blinking + Led1Args:1=0x05 # Arg2=0 (1/2 Duty Factor), Arg1=5 (1192ms Blink Period) + } + + # LED #2 Behaviors + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=0 # Disconnected + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=1 # Scanning + LedNum:1=2 # LED #2 + Led1State:1=2 # Blinking + Led1Args:1=0x04 # Arg2=0 (1/2 Duty Factor), Arg1=4 (298ms Blink Period) + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=2 # Connected-Awake + LedNum:1=2 # LED #2 + Led1State:1=1 # Steady ON + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=3 # Connected-Sleep + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=4 # Deep Sleep + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=5 # Connected-Single + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=6 # Disconnected-Link Loss + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=7 # Disconnected-Disassociated + LedNum:1=2 # LED #2 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=8 # Exception + LedNum:1=2 # LED #2 + Led1State:1=2 # Blinking + Led1Args:1=0x05 # Arg2=0 (1/2 Duty Factor), Arg1=5 (1192ms Blink Period) + } + + # LED #3 Behaviors + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=0 # Disconnected + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=1 # Scanning + LedNum:1=3 # LED #3 + Led1State:1=2 # Blinking + Led1Args:1=0x04 # Arg2=0 (1/2 Duty Factor), Arg1=4 (298ms Blink Period) + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=2 # Connected-Awake + LedNum:1=3 # LED #3 + Led1State:1=1 # Steady ON + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=3 # Connected-Sleep + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=4 # Deep Sleep + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=5 # Connected-Single + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=6 # Disconnected-Link Loss + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=7 # Disconnected-Disassociated + LedNum:1=3 # LED #3 + Led1State:1=0 # Steady OFF + Led1Args:1=0 # N/A + } + LedBehaviorTlvType:2=0x0109 + LedBehaviorTlvLength:2={ + FirmwareState:1=8 # Exception + LedNum:1=3 # LED #3 + Led1State:1=2 # Blinking + Led1Args:1=0x05 # Arg2=0 (1/2 Duty Factor), Arg1=5 (1192ms Blink Period) + } + +} +######################### LED Ctrl command ################## diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/tspecs.conf 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/tspecs.conf --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/config/tspecs.conf 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/config/tspecs.conf 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,99 @@ +# TSPEC contents for TID=0, UserPriority = 6 +[tspec0] +# Element ID +dd +# Length +3d +# OUI +00 50 f2 +# OUI Type +02 +# OUI SubType +02 +# Version +01 +# TSInfo +e0 34 00 +# Nominal MSDU Size +d0 80 +# Maximum MSDU Size +d0 00 +# Min Service Interval +20 4e 00 00 +# Max Service Interval +20 4e 00 00 +# Inactivity Interval +80 96 98 00 +# Suspension Interval +ff ff ff ff +# Service Start Time +00 00 00 00 +# Minimum Data Rate +00 45 01 00 +# Mean Data Rate +00 45 01 00 +# Peak Data Rate +00 45 01 00 +# Max Burst Size +00 00 00 00 +# Delay Bound +00 00 00 00 +# Min PHY Rate +00 1b b7 00 +# Surplus Bandwidth Allowance +04 20 +# Medium Time +00 00 +# Extra Data Bytes +[/tspec0] + + +# TSPEC contents for TID=1, UserPriority = 4 +[tspec1] +# Element ID +dd +# Length +3d +# OUI +00 50 f2 +# OUI Type +02 +# OUI SubType +02 +# Version +01 +# TSInfo +e3 20 00 +# Nominal MSDU Size +96 00 +# Maximum MSDU Size +dc 05 +# Min Service Interval +00 00 00 00 +# Max Service Interval +00 00 00 00 +# Inactivity Interval +00 00 00 00 +# Suspension Interval +ff ff ff ff +# Service Start Time +00 00 00 00 +# Minimum Data Rate +a0 00 00 00 +# Mean Data Rate +a0 00 00 00 +# Peak Data Rate +a0 00 00 00 +# Max Burst Size +00 00 00 00 +# Delay Bound +00 00 00 00 +# Min PHY Rate +80 8d 5b 00 +# Surplus Bandwidth Allowance +00 20 +# Medium Time +00 00 +# Extra Data Bytes +[/tspec1] + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_sdio/if_sdio.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_sdio/if_sdio.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_sdio/if_sdio.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_sdio/if_sdio.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,1371 @@ +/** @file if_sdio.c + * @brief This file contains SDIO IF (interface) module + * related functions. + * + * (c) Copyright © 2003-2007, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************** +Change log: + 10/14/05: add Doxygen format comments + 01/05/06: add kernel 2.6.x support + 01/23/06: add fw downlaod + 06/06/06: add macro SD_BLOCK_SIZE_FW_DL for firmware download + add macro ALLOC_BUF_SIZE for cmd resp/Rx data skb buffer allocation +****************************************************/ + +#include "if_sdio.h" + +#include + +/* define SD block size for firmware download */ +#define SD_BLOCK_SIZE_FW_DL 32 + +/* define SD block size for data Tx/Rx */ +#define SD_BLOCK_SIZE 32 + +#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \ + MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \ + + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE) + +/* Max retry number of CMD53 write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +#define GPIO_PORT_TO_HIGH() sd_set_gpo(priv, 1) +#define GPIO_PORT_TO_LOW() sd_set_gpo(priv, 0) + +/******************************************************** + Local Variables +********************************************************/ + +static wlan_private *pwlanpriv; +static wlan_private *(*wlan_add_callback) (void *dev_id); +static int (*wlan_remove_callback) (void *dev_id); + +/******************************************************** + Global Variables +********************************************************/ + +#define SDIO_CLK_RATE_6MHZ 6 /* MHz */ +#define SDIO_CLK_RATE_12MHZ 12 /* MHz */ +#define SDIO_CLK_RATE_25MHZ 25 /* MHz */ +#define SDIO_CLK_RATE_DEFAULT 0 +int clkrate = SDIO_CLK_RATE_DEFAULT; +module_param(clkrate, int, 0); + +mmc_notifier_rec_t if_sdio_notifier; +isr_notifier_fn_t isr_function; + +int request_gpio_irq_callback(void (*callback) (void *), void *arg); +int release_gpio_irq_callback(void (*callback) (void *), void *arg); + +#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin" +#define DEFAULT_FW_NAME "mrvl/sd8686.bin" + +extern u8 *helper_name; +extern u8 *fw_name; + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief This function adds the card + * + * @param card A pointer to the card + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +sbi_add_card(void *card) +{ + if (!wlan_add_callback) + return WLAN_STATUS_FAILURE; + + pwlanpriv = wlan_add_callback(card); + + if (pwlanpriv) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/** + * @brief This function removes the card + * + * @param card A pointer to the card + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +sbi_remove_card(void *card) +{ + if (!wlan_remove_callback) + return WLAN_STATUS_FAILURE; + + pwlanpriv = NULL; + return wlan_remove_callback(card); +} + +/** + * @brief This function reads scratch registers + * + * @param priv A pointer to wlan_private structure + * @param dat A pointer to keep returned data + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +mv_sdio_read_scratch(wlan_private * priv, u16 * dat) +{ + int ret = WLAN_STATUS_SUCCESS; + u8 scr0; + u8 scr1; + ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, CARD_OCR_0_REG, &scr0); + if (ret < 0) + return WLAN_STATUS_FAILURE; + + ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, CARD_OCR_1_REG, &scr1); + PRINTM(INFO, "CARD_OCR_0_REG = 0x%x, CARD_OCR_1_REG = 0x%x\n", scr0, + scr1); + if (ret < 0) + return WLAN_STATUS_FAILURE; + + *dat = (((u16) scr1) << 8) | scr0; + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function polls the card status register. + * + * @param priv A pointer to wlan_private structure + * @param bits the bit mask + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +mv_sdio_poll_card_status(wlan_private * priv, u8 bits) +{ + int tries; + int rval; + u8 cs; + + for (tries = 0; tries < MAX_POLL_TRIES * 1000; tries++) { + rval = sdio_read_ioreg(priv->wlan_dev.card, FN1, + CARD_STATUS_REG, &cs); + if (rval == 0 && (cs & bits) == bits) { + return WLAN_STATUS_SUCCESS; + } + + udelay(1); + } + + PRINTM(WARN, "mv_sdio_poll_card_status: FAILED!:%d\n", rval); + return WLAN_STATUS_FAILURE; +} + +/** + * @brief This function programs the firmware image. + * + * @param priv A pointer to wlan_private structure + * @param firmware A pointer to the buffer of firmware image + * @param firmwarelen the length of firmware image + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +sbi_prog_firmware_image(wlan_private * priv, + const u8 * firmware, int firmwarelen) +{ + int ret = WLAN_STATUS_SUCCESS; + u16 firmwarestat; + u8 *fwbuf = priv->adapter->TmpTxBuf; + int fwblknow; + u32 tx_len; +#ifdef FW_DOWNLOAD_SPEED + u32 tv1, tv2; +#endif + + ENTER(); + + /* Check if the firmware is already downloaded */ + if ((ret = mv_sdio_read_scratch(priv, &firmwarestat)) < 0) { + PRINTM(INFO, "read scratch returned <0\n"); + goto done; + } + + if (firmwarestat == FIRMWARE_READY) { + PRINTM(INFO, "FW already downloaded!\n"); + ret = WLAN_STATUS_SUCCESS; + goto done; + } + + PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n", + firmwarelen, SD_BLOCK_SIZE_FW_DL); + +#ifdef FW_DOWNLOAD_SPEED + tv1 = get_utimeofday(); +#endif + /* Perform firmware data transfer */ + tx_len = + (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE_FW_DL) - SDIO_HEADER_LEN; + for (fwblknow = 0; fwblknow < firmwarelen; fwblknow += tx_len) { + + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); + if (ret < 0) { + PRINTM(FATAL, "FW download died @ %d\n", fwblknow); + goto done; + } + + /* Set blocksize to transfer - checking for last block */ + if (firmwarelen - fwblknow < tx_len) + tx_len = firmwarelen - fwblknow; + + fwbuf[0] = ((tx_len & 0x000000ff) >> 0); /* Little-endian */ + fwbuf[1] = ((tx_len & 0x0000ff00) >> 8); + fwbuf[2] = ((tx_len & 0x00ff0000) >> 16); + fwbuf[3] = ((tx_len & 0xff000000) >> 24); + + /* Copy payload to buffer */ + memcpy(&fwbuf[SDIO_HEADER_LEN], &firmware[fwblknow], tx_len); + + PRINTM(INFO, "."); + + /* Send data */ + ret = sdio_write_iomem(priv->wlan_dev.card, FN1, + priv->wlan_dev.ioport, BLOCK_MODE, + FIXED_ADDRESS, FIRMWARE_TRANSFER_NBLOCK, + SD_BLOCK_SIZE_FW_DL, fwbuf); + + if (ret < 0) { + PRINTM(FATAL, "IO error: transferring block @ %d\n", fwblknow); + goto done; + } + } + +#ifdef FW_DOWNLOAD_SPEED + tv2 = get_utimeofday(); + PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000, + (tv1 % 1000000) / 1000, tv1 % 1000); + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); + tv2 -= tv1; + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); +#endif + mdelay(1); + + /* Write last EOF data */ + PRINTM(INFO, "\nTransferring EOF block\n"); + memset(fwbuf, 0x0, SD_BLOCK_SIZE_FW_DL); + ret = sdio_write_iomem(priv->wlan_dev.card, FN1, + priv->wlan_dev.ioport, BLOCK_MODE, + FIXED_ADDRESS, 1, SD_BLOCK_SIZE_FW_DL, fwbuf); + + if (ret < 0) { + PRINTM(FATAL, "IO error in writing EOF FW block\n"); + goto done; + } + + ret = WLAN_STATUS_SUCCESS; + + done: + return ret; +} + +/** + * @brief This function downloads firmware image to the card. + * + * @param priv A pointer to wlan_private structure + * @param firmware A pointer to firmware image buffer + * @param firmwarelen the length of firmware image + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +sbi_download_wlan_fw_image(wlan_private * priv, + const u8 * firmware, int firmwarelen) +{ + u8 base0; + u8 base1; + int ret = WLAN_STATUS_SUCCESS; + int offset; + u8 *fwbuf = priv->adapter->TmpTxBuf; + int timeout = 5000; + u16 len; + int txlen = 0; + int tx_blocks = 0; + int i = 0; +#ifdef FW_DOWNLOAD_SPEED + u32 tv1, tv2; +#endif + + ENTER(); + + PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen); + +#ifdef FW_DOWNLOAD_SPEED + tv1 = get_utimeofday(); +#endif + + /* Wait initially for the first non-zero value */ + do { + if ((ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, + HOST_F1_RD_BASE_0, &base0)) < 0) { + PRINTM(WARN, "Dev BASE0 register read failed:" + " base0=0x%04X(%d)\n", base0, base0); + ret = WLAN_STATUS_FAILURE; + goto done; + } + if ((ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, + HOST_F1_RD_BASE_1, &base1)) < 0) { + PRINTM(WARN, "Dev BASE1 register read failed:" + " base1=0x%04X(%d)\n", base1, base1); + ret = WLAN_STATUS_FAILURE; + goto done; + } + len = (((u16) base1) << 8) | base0; + mdelay(1); + } while (!len && --timeout); + + if (!timeout) { + PRINTM(MSG, "Helper downloading finished.\n"); + PRINTM(MSG, "Timeout for FW downloading!\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); + if (ret < 0) { + PRINTM(FATAL, "FW download died, helper not ready\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + + len &= ~B_BIT_0; + + /* Perform firmware data transfer */ + for (offset = 0; offset < firmwarelen; offset += txlen) { + txlen = len; + + /* Set blocksize to transfer - checking for last block */ + if (firmwarelen - offset < txlen) { + txlen = firmwarelen - offset; + } + /* PRINTM(INFO, "fw: offset=%d, txlen = 0x%04X(%d)\n", + offset,txlen,txlen); */ + PRINTM(INFO, "."); + + tx_blocks = (txlen + SD_BLOCK_SIZE_FW_DL - 1) / SD_BLOCK_SIZE_FW_DL; + + /* Copy payload to buffer */ + memcpy(fwbuf, &firmware[offset], txlen); + + /* Send data */ + ret = sdio_write_iomem(priv->wlan_dev.card, FN1, + priv->wlan_dev.ioport, BLOCK_MODE, + FIXED_ADDRESS, tx_blocks, SD_BLOCK_SIZE_FW_DL, + fwbuf); + + if (ret < 0) { + PRINTM(ERROR, "FW download, write iomem (%d) failed: %d\n", i, + ret); + if (sdio_write_ioreg + (priv->wlan_dev.card, FN1, CONFIGURATION_REG, 0x04) < 0) { + PRINTM(ERROR, "write ioreg failed (FN1 CFG)\n"); + } + } + + /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */ + ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY); + if (ret < 0) { + PRINTM(FATAL, "FW download with helper died @ %d\n", offset); + goto done; + } + + if ((ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, + HOST_F1_RD_BASE_0, &base0)) < 0) { + PRINTM(WARN, "Dev BASE0 register read failed:" + " base0=0x%04X(%d)\n", base0, base0); + ret = WLAN_STATUS_FAILURE; + goto done; + } + if ((ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, + HOST_F1_RD_BASE_1, &base1)) < 0) { + PRINTM(WARN, "Dev BASE1 register read failed:" + " base1=0x%04X(%d)\n", base1, base1); + ret = WLAN_STATUS_FAILURE; + goto done; + } + len = (((u16) base1) << 8) | base0; + + if (!len) { + break; + } + + if (len & B_BIT_0) { + i++; + if (i > MAX_WRITE_IOMEM_RETRY) { + PRINTM(FATAL, "FW download failure, over max retry count\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + PRINTM(ERROR, "CRC error indicated by the helper:" + " len = 0x%04X, txlen = %d\n", len, txlen); + len &= ~B_BIT_0; + /* Setting this to 0 to resend from same offset */ + txlen = 0; + } else + i = 0; + } + PRINTM(INFO, "\nFW download over, size %d bytes\n", firmwarelen); + + ret = WLAN_STATUS_SUCCESS; + done: +#ifdef FW_DOWNLOAD_SPEED + tv2 = get_utimeofday(); + PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000, + (tv1 % 1000000) / 1000, tv1 % 1000); + PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); + tv2 -= tv1; + PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, + (tv2 % 1000000) / 1000, tv2 % 1000); +#endif + LEAVE(); + return ret; +} + +/** + * @brief This function reads data from the card. + * + * @param priv A pointer to wlan_private structure + * @param type A pointer to keep type as data or command + * @param nb A pointer to keep the data/cmd length retured in buffer + * @param payload A pointer to the data/cmd buffer + * @param nb the length of data/cmd buffer + * @param npayload the length of data/cmd buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +mv_sdio_card_to_host(wlan_private * priv, + u32 * type, int *nb, u8 * payload, int npayload) +{ + int ret = WLAN_STATUS_SUCCESS; + u16 buf_len = 0; + int buf_block_len; + int blksz; + u32 *pevent; + + if (!payload) { + PRINTM(WARN, "payload NULL pointer received!\n"); + ret = WLAN_STATUS_FAILURE; + goto exit; + } + + /* Read the length of data to be transferred */ + ret = mv_sdio_read_scratch(priv, &buf_len); + if (ret < 0) { + PRINTM(ERROR, "card_to_host, read scratch reg failed\n"); + ret = WLAN_STATUS_FAILURE; + goto exit; + } + + if (buf_len <= SDIO_HEADER_LEN || buf_len > npayload) { + PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len); + ret = WLAN_STATUS_FAILURE; + goto exit; + } + + /* Allocate buffer */ + blksz = SD_BLOCK_SIZE; + buf_block_len = (buf_len + blksz - 1) / blksz; + + ret = sdio_read_iomem(priv->wlan_dev.card, FN1, priv->wlan_dev.ioport, + BLOCK_MODE, FIXED_ADDRESS, buf_block_len, + blksz, payload); + + if (ret < 0) { + PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret); + ret = WLAN_STATUS_FAILURE; + goto exit; + } + *nb = buf_len; + + DBG_HEXDUMP(IF_D, "SDIO Blk Rd", payload, blksz * buf_block_len); + + *type = (payload[2] | (payload[3] << 8)); + if (*type == MVSD_EVENT) { + pevent = (u32 *) & payload[4]; + priv->adapter->EventCause = MVSD_EVENT | (((u16) (*pevent)) << 3); + } + + exit: + return ret; +} + +/** + * @brief This function enables the host interrupts mask + * + * @param priv A pointer to wlan_private structure + * @param mask the interrupt mask + * @return WLAN_STATUS_SUCCESS + */ +static int +enable_host_int_mask(wlan_private * priv, u8 mask) +{ + int ret = WLAN_STATUS_SUCCESS; + mmc_card_t card = (mmc_card_t) priv->wlan_dev.card; + + /* Simply write the mask to the register */ + ret = sdio_write_ioreg(card, FN1, HOST_INT_MASK_REG, mask); + + if (ret < 0) { + PRINTM(WARN, "ret = %d\n", ret); + ret = WLAN_STATUS_FAILURE; + } + + priv->adapter->HisRegCpy = 1; + + return ret; +} + +/** @brief This function disables the host interrupts mask. + * + * @param priv A pointer to wlan_private structure + * @param mask the interrupt mask + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +disable_host_int_mask(wlan_private * priv, u8 mask) +{ + int ret = WLAN_STATUS_SUCCESS; + u8 host_int_mask; + + /* Read back the host_int_mask register */ + ret = sdio_read_ioreg(priv->wlan_dev.card, FN1, HOST_INT_MASK_REG, + &host_int_mask); + if (ret < 0) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + + /* Update with the mask and write back to the register */ + host_int_mask &= ~mask; + ret = sdio_write_ioreg(priv->wlan_dev.card, FN1, HOST_INT_MASK_REG, + host_int_mask); + if (ret < 0) { + PRINTM(WARN, "Unable to diable the host interrupt!\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + + done: + return ret; +} + +/******************************************************** + Global Functions +********************************************************/ + +int start_bus_clock(mmc_controller_t); +int stop_bus_clock_2(mmc_controller_t); + +void +gpio_irq_callback(void *arg) +{ + wlan_private *priv = (wlan_private *) arg; + + PRINTM(INFO, "gpio_irq_callback() called\n"); + if (wlan_host_sleep_gpio_int_event(priv)) + PRINTM(FATAL, "gpio_irq_handler(): sending event failed\n"); +} + +/** + * @brief This function handles the interrupt. + * + * @param irq The irq of device. + * @param dev_id A pointer to net_device structure + * @param fp A pointer to pt_regs structure + * @return n/a + */ +static IRQ_RET_TYPE +sbi_interrupt(int irq, void *dev_id, struct pt_regs *fp) +{ + struct net_device *dev = dev_id; + wlan_private *priv; + + ENTER(); + + priv = dev->priv; + + wlan_interrupt(dev); + + IRQ_RET; +} + +/** + * @brief This function registers the IF module in bus driver. + * + * @param add wlan driver's call back funtion for add card. + * @param remove wlan driver's call back funtion for remove card. + * @param arg not been used + * @return An int pointer that keeps returned value + */ +int * +sbi_register(wlan_notifier_fn_add add, wlan_notifier_fn_remove remove, + void *arg) +{ + int *sdio_ret; + + ENTER(); + + wlan_add_callback = add; + wlan_remove_callback = remove; + + if_sdio_notifier.add = (mmc_notifier_fn_t) sbi_add_card; + if_sdio_notifier.remove = (mmc_notifier_fn_t) sbi_remove_card; + isr_function = sbi_interrupt; + sdio_ret = sdio_register(MMC_REG_TYPE_USER, &if_sdio_notifier, 0); + + LEAVE(); + + return sdio_ret; +} + +/** + * @brief This function de-registers the IF module in bus driver. + * + * @return n/a + */ +void +sbi_unregister(void) +{ + sdio_unregister(MMC_REG_TYPE_USER, &if_sdio_notifier); +} + +/** + * @brief This function reads the IO register. + * + * @param priv A pointer to wlan_private structure + * @param func funcion number + * @param reg register to be read + * @param dat A pointer to variable that keeps returned value + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_read_ioreg(wlan_private * priv, u8 func, u32 reg, u8 * dat) +{ + return sdio_read_ioreg(priv->wlan_dev.card, func, reg, dat); +} + +/** + * @brief This function writes the IO register. + * + * @param priv A pointer to wlan_private structure + * @param func funcion number + * @param reg register to be written + * @param dat the value to be written + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_write_ioreg(wlan_private * priv, u8 func, u32 reg, u8 dat) +{ + return sdio_write_ioreg(priv->wlan_dev.card, func, reg, dat); +} + +/** + * @brief This function checks the interrupt status and handle it accordingly. + * + * @param priv A pointer to wlan_private structure + * @param ireg A pointer to variable that keeps returned value + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_get_int_status(wlan_private * priv, u8 * ireg) +{ + int ret = WLAN_STATUS_SUCCESS; + u8 sdio_ireg = 0; + u8 *cmdBuf; + wlan_dev_t *wlan_dev = &priv->wlan_dev; + struct sk_buff *skb; + mmc_card_t card = (mmc_card_t) wlan_dev->card; + + *ireg = 0; + if ((ret = sdio_read_ioreg(card, FN1, HOST_INTSTATUS_REG, &sdio_ireg))) { + PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + + if (sdio_ireg != 0) { + /* + * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS + * Clear the interrupt status register and re-enable the interrupt + */ + PRINTM(INFO, "sdio_ireg = 0x%x\n", sdio_ireg); + if ((ret = sdio_write_ioreg(card, FN1, HOST_INTSTATUS_REG, + ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS | + UP_LD_HOST_INT_STATUS))) < + 0) { + PRINTM(WARN, + "sdio_write_ioreg: clear int status register failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + } + + sdio_unmask(); + + if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */ + *ireg |= HIS_TxDnLdRdy; + if (!priv->wlan_dev.dnld_sent) { /* tx_done already received */ + PRINTM(INFO, "warning: tx_done already received:" + " dnld_sent=0x%x int status=0x%x\n", + priv->wlan_dev.dnld_sent, sdio_ireg); + } else { + wmm_process_fw_iface_tx_xfer_end(priv); + priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + } + } + + if (sdio_ireg & UP_LD_HOST_INT_STATUS) { + + /* + * DMA read data is by block alignment,so we need alloc extra block + * to avoid wrong memory access. + */ + if (!(skb = dev_alloc_skb(ALLOC_BUF_SIZE))) { + PRINTM(WARN, "No free skb\n"); + priv->stats.rx_dropped++; + ret = WLAN_STATUS_FAILURE; + goto done; + } + + /* + * Transfer data from card + * skb->tail is passed as we are calling skb_put after we + * are reading the data + */ + if (mv_sdio_card_to_host(priv, &wlan_dev->upld_typ, + (int *) &wlan_dev->upld_len, skb->tail, + ALLOC_BUF_SIZE) < 0) { + u8 cr = 0; + + PRINTM(ERROR, "Card to host failed: int status=0x%x\n", + sdio_ireg); + if (sdio_read_ioreg(wlan_dev->card, FN1, CONFIGURATION_REG, &cr) < + 0) + PRINTM(ERROR, "read ioreg failed (FN1 CFG)\n"); + + PRINTM(INFO, "Config Reg val = %d\n", cr); + if (sdio_write_ioreg(wlan_dev->card, FN1, + CONFIGURATION_REG, (cr | 0x04)) < 0) + PRINTM(ERROR, "write ioreg failed (FN1 CFG)\n"); + + PRINTM(INFO, "write success\n"); + if (sdio_read_ioreg(wlan_dev->card, FN1, + CONFIGURATION_REG, &cr) < 0) + PRINTM(ERROR, "read ioreg failed (FN1 CFG)\n"); + + PRINTM(INFO, "Config reg val =%x\n", cr); + ret = WLAN_STATUS_FAILURE; + kfree_skb(skb); + goto done; + } + + switch (wlan_dev->upld_typ) { + case MVSD_DAT: + PRINTM(DATA, "Data <= FW\n"); + *ireg |= HIS_RxUpLdRdy; + skb_put(skb, priv->wlan_dev.upld_len); + skb_pull(skb, SDIO_HEADER_LEN); + list_add_tail((struct list_head *) skb, + (struct list_head *) &priv->adapter->RxSkbQ); + /* skb will be freed by kernel later */ + break; + + case MVSD_CMD: + *ireg |= HIS_CmdUpLdRdy; + + /* take care of CurCmd = NULL case */ + if (!priv->adapter->CurCmd) { + cmdBuf = priv->wlan_dev.upld_buf; + } else { + cmdBuf = priv->adapter->CurCmd->BufVirtualAddr; + } + + priv->wlan_dev.upld_len -= SDIO_HEADER_LEN; + memcpy(cmdBuf, skb->data + SDIO_HEADER_LEN, + MIN(MRVDRV_SIZE_OF_CMD_BUFFER, priv->wlan_dev.upld_len)); + kfree_skb(skb); + break; + + case MVSD_EVENT: + *ireg |= HIS_CardEvent; + /* event cause has been saved to priv->adapter->EventCause */ + kfree_skb(skb); + break; + + default: + PRINTM(ERROR, "SDIO unknown upld type = 0x%x\n", + wlan_dev->upld_typ); + kfree_skb(skb); + break; + } + } + + ret = WLAN_STATUS_SUCCESS; + done: + return ret; +} + +/** + * @brief This function is a dummy function. + * + * @return WLAN_STATUS_SUCCESS + */ +int +sbi_card_to_host(wlan_private * priv, u32 type, + u32 * nb, u8 * payload, u16 npayload) +{ + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function is a dummy function. + * + * @return WLAN_STATUS_SUCCESS + */ +int +sbi_read_event_cause(wlan_private * priv) +{ + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function disables the host interrupts. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_disable_host_int(wlan_private * priv) +{ + return disable_host_int_mask(priv, HIM_DISABLE); +} + +/** + * @brief This function enables the host interrupts. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS + */ +int +sbi_enable_host_int(wlan_private * priv) +{ + sdio_enable_SDIO_INT(); + return enable_host_int_mask(priv, HIM_ENABLE); +} + +/** + * @brief This function de-registers the device. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS + */ +int +sbi_unregister_dev(wlan_private * priv) +{ + ENTER(); + + if (priv->wlan_dev.card != NULL) { + /* Release the SDIO IRQ */ + sdio_free_irq(priv->wlan_dev.card, priv->wlan_dev.netdev); + if (release_gpio_irq_callback + ((void (*)(void *)) gpio_irq_callback, (void *) priv)) + PRINTM(FATAL, "Failed to release GPIO IRQ callback\n"); + PRINTM(WARN, "Making the sdio dev card as NULL\n"); + } + + GPIO_PORT_TO_LOW(); + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function registers the device. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_register_dev(wlan_private * priv) +{ + int ret = WLAN_STATUS_SUCCESS; + u8 reg; + mmc_card_t card = (mmc_card_t) priv->wlan_dev.card; + + ENTER(); + + GPIO_PORT_TO_HIGH(); + + priv->hotplug_device = card->dev; + if (helper_name == NULL) { + helper_name = DEFAULT_HELPER_NAME; + } + if (fw_name == NULL) { + fw_name = DEFAULT_FW_NAME; + } + + /* Initialize the private structure */ + strncpy(priv->wlan_dev.name, "sdio0", sizeof(priv->wlan_dev.name)); + priv->wlan_dev.ioport = 0; + priv->wlan_dev.upld_rcv = 0; + priv->wlan_dev.upld_typ = 0; + priv->wlan_dev.upld_len = 0; + + /* Read the IO port */ + ret = sdio_read_ioreg(card, FN1, IO_PORT_0_REG, ®); + if (ret < 0) + goto failed; + else + priv->wlan_dev.ioport |= reg; + + ret = sdio_read_ioreg(card, FN1, IO_PORT_1_REG, ®); + if (ret < 0) + goto failed; + else + priv->wlan_dev.ioport |= (reg << 8); + + ret = sdio_read_ioreg(card, FN1, IO_PORT_2_REG, ®); + if (ret < 0) + goto failed; + else + priv->wlan_dev.ioport |= (reg << 16); + + PRINTM(INFO, "SDIO FUNC1 IO port: 0x%x\n", priv->wlan_dev.ioport); + + /* Disable host interrupt first. */ + if ((ret = disable_host_int_mask(priv, 0xff)) < 0) { + PRINTM(WARN, "Warning: unable to disable host interrupt!\n"); + } + + /* Request the SDIO IRQ */ + PRINTM(INFO, "Before request_irq Address is if==>%p\n", isr_function); + ret = sdio_request_irq(priv->wlan_dev.card, + (handler_fn_t) isr_function, 0, + "sdio_irq", priv->wlan_dev.netdev); + + if (ret < 0) { + PRINTM(FATAL, "Failed to request IRQ on SDIO bus (%d)\n", ret); + goto failed; + } + + PRINTM(INFO, "IrqLine: %d\n", card->ctrlr->tmpl->irq_line); + priv->wlan_dev.netdev->irq = card->ctrlr->tmpl->irq_line; + priv->adapter->irq = priv->wlan_dev.netdev->irq; + priv->adapter->chip_rev = card->chiprev; + if (request_gpio_irq_callback + ((void (*)(void *)) gpio_irq_callback, (void *) priv)) + PRINTM(FATAL, "Failed to request GPIO IRQ callback\n"); + + return WLAN_STATUS_SUCCESS; + + failed: + priv->wlan_dev.card = NULL; + + return WLAN_STATUS_FAILURE; +} + +/** + * @brief This function sends data to the card. + * + * @param priv A pointer to wlan_private structure + * @param type data or command + * @param payload A pointer to the data/cmd buffer + * @param nb the length of data/cmd + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb) +{ + int ret = WLAN_STATUS_SUCCESS; + int buf_block_len; + int blksz; + int i = 0; + + ENTER(); + + priv->adapter->HisRegCpy = 0; + + /* Allocate buffer and copy payload */ + blksz = SD_BLOCK_SIZE; + buf_block_len = (nb + SDIO_HEADER_LEN + blksz - 1) / blksz; + + /* This is SDIO specific header + * length: byte[1][0], + * type: byte[3][2] (MVSD_DAT = 0, MVSD_CMD = 1, MVSD_EVENT = 3) + */ + priv->adapter->TmpTxBuf[0] = (nb + SDIO_HEADER_LEN) & 0xff; + priv->adapter->TmpTxBuf[1] = ((nb + SDIO_HEADER_LEN) >> 8) & 0xff; + priv->adapter->TmpTxBuf[2] = type; + priv->adapter->TmpTxBuf[3] = 0x0; + + if (payload != NULL && + (nb > 0 && + nb <= (sizeof(priv->adapter->TmpTxBuf) - SDIO_HEADER_LEN))) { + if (type == MVMS_CMD) + memcpy(&priv->adapter->TmpTxBuf[SDIO_HEADER_LEN], payload, nb); + } else { + PRINTM(WARN, "sbi_host_to_card(): Error: payload=%p, nb=%d\n", + payload, nb); + } + + do { + /* Transfer data to card */ + ret = + sdio_write_iomem(priv->wlan_dev.card, FN1, priv->wlan_dev.ioport, + BLOCK_MODE, FIXED_ADDRESS, buf_block_len, blksz, + priv->adapter->TmpTxBuf); + if (ret < 0) { + i++; + PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i, + ret); + if (sdio_write_ioreg + (priv->wlan_dev.card, FN1, CONFIGURATION_REG, 0x04) < 0) { + PRINTM(ERROR, "write ioreg failed (FN1 CFG)\n"); + } + ret = WLAN_STATUS_FAILURE; + if (i > MAX_WRITE_IOMEM_RETRY) + goto exit; + } else { + DBG_HEXDUMP(IF_D, "SDIO Blk Wr", priv->adapter->TmpTxBuf, + blksz * buf_block_len); + } + } while (ret == WLAN_STATUS_FAILURE); + + if (type == MVSD_DAT) + priv->wlan_dev.dnld_sent = DNLD_DATA_SENT; + else + priv->wlan_dev.dnld_sent = DNLD_CMD_SENT; + + exit: + LEAVE(); + return ret; +} + +/** + * @brief This function reads CIS informaion. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_get_cis_info(wlan_private * priv) +{ + mmc_card_t card = (mmc_card_t) priv->wlan_dev.card; + wlan_adapter *Adapter = priv->adapter; + u8 tupledata[255]; + int i; + u32 ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + /* Read the Tuple Data */ + for (i = 0; i < sizeof(tupledata); i++) { + ret = sdio_read_ioreg(card, FN0, card->info.cisptr[FN0] + i, + &tupledata[i]); + if (ret) { + PRINTM(WARN, "get_cis_info error:%d\n", ret); + return WLAN_STATUS_FAILURE; + } + } + + /* Copy the CIS Table to Adapter */ + memset(Adapter->CisInfoBuf, 0x0, sizeof(Adapter->CisInfoBuf)); + memcpy(Adapter->CisInfoBuf, tupledata, sizeof(tupledata)); + Adapter->CisInfoLen = sizeof(tupledata); + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function probes the card. + * + * @param card_p A pointer to the card + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_probe_card(void *card_p) +{ + mmc_card_t card = (mmc_card_t) card_p; + int ret = WLAN_STATUS_SUCCESS; + u8 bic; + + ENTER(); + + if (!card) { + ret = -ENODEV; //WLAN_STATUS_FAILURE; + goto done; + } + + /* Check for MANFID */ + ret = sdio_get_vendor_id(card); + +#define MARVELL_VENDOR_ID 0x02df + if (ret == MARVELL_VENDOR_ID) { + PRINTM(INFO, "Marvell SDIO card detected!\n"); + } else { + PRINTM(MSG, "Ignoring a non-Marvell SDIO card...\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + + /* read Revision Register to get the hw revision number */ + if (sdio_read_ioreg(card, FN1, CARD_REVISION_REG, &card->chiprev) < 0) { + PRINTM(FATAL, "cannot read CARD_REVISION_REG\n"); + } else { + PRINTM(INFO, "revsion=0x%x\n", card->chiprev); + switch (card->chiprev) { + default: + card->async_int_mode = TRUE; + + /* enable async interrupt mode */ + ret = sdio_read_ioreg(card, FN0, BUS_INTERFACE_CONTROL_REG, &bic); + if (ret < 0) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + bic |= ASYNC_INT_MODE; + ret = sdio_write_ioreg(card, FN0, BUS_INTERFACE_CONTROL_REG, bic); + if (ret < 0) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + break; + } + } + + ret = WLAN_STATUS_SUCCESS; + done: + + LEAVE(); + return ret; +} + +/** + * @brief This function calls sbi_download_wlan_fw_image to download + * firmware image to the card. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_prog_firmware_w_helper(wlan_private * priv) +{ + if (priv->firmware) { + return sbi_download_wlan_fw_image(priv, + priv->firmware->data, + priv->firmware->size); + } else { + PRINTM(MSG, "No hotplug firmware image\n"); + return WLAN_STATUS_FAILURE; + } +} + +/** + * @brief This function programs helper image. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_prog_helper(wlan_private * priv) +{ + if (priv->fw_helper) { + return sbi_prog_firmware_image(priv, + priv->fw_helper->data, + priv->fw_helper->size); + } else { + PRINTM(MSG, "No hotplug helper image\n"); + return WLAN_STATUS_FAILURE; + } +} + +/** + * @brief This function checks if the firmware is ready to accept + * command or not. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_verify_fw_download(wlan_private * priv) +{ + int ret = WLAN_STATUS_SUCCESS; + u16 firmwarestat; + int tries; + + /* Wait for firmware initialization event */ + for (tries = 0; tries < MAX_FIRMWARE_POLL_TRIES; tries++) { + if ((ret = mv_sdio_read_scratch(priv, &firmwarestat)) < 0) + continue; + + if (firmwarestat == FIRMWARE_READY) { + ret = WLAN_STATUS_SUCCESS; + break; + } else { + mdelay(10); + ret = WLAN_STATUS_FAILURE; + } + } + + if (ret < 0) { + PRINTM(MSG, "Timeout waiting for FW to become active\n"); + goto done; + } + + ret = WLAN_STATUS_SUCCESS; + done: + return ret; +} + +int +sd_set_clock(wlan_private * priv, u32 slotFreq) +{ + sdio_SetClockSpeed(((mmc_card_t) (priv->wlan_dev.card))->ctrlr, slotFreq); + return WLAN_STATUS_SUCCESS; +} + + /*--- mmoser 12/19/2006 ---*/ +int +sd_stop_clock(wlan_private * priv) +{ + sdio_SetClock(((mmc_card_t) (priv->wlan_dev.card))->ctrlr, 0); + return WLAN_STATUS_SUCCESS; +} + +int +sd_start_clock(wlan_private * priv) +{ + sdio_SetClock(((mmc_card_t) (priv->wlan_dev.card))->ctrlr, 1); + return WLAN_STATUS_SUCCESS; +} + +int +sd_set_bus_width(wlan_private * priv, u8 width) +{ + sdio_SetBusWidth(((mmc_card_t) (priv->wlan_dev.card))->ctrlr, width); + return WLAN_STATUS_SUCCESS; +} + +int +sd_set_gpo(wlan_private * priv, u8 on) +{ + sdio_SetGPO(((mmc_card_t) (priv->wlan_dev.card))->ctrlr, on); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function set bus clock on/off + * + * @param priv A pointer to wlan_private structure + * @param option TRUE--on , FALSE--off + * @return WLAN_STATUS_SUCCESS + */ +int +sbi_set_bus_clock(wlan_private * priv, u8 option) +{ + + if (option == TRUE) + sd_start_clock(priv); + else + sd_stop_clock(priv); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function makes firmware exiting from deep sleep. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_exit_deep_sleep(wlan_private * priv) +{ + int ret = WLAN_STATUS_SUCCESS; + + sbi_set_bus_clock(priv, TRUE); + + if (priv->adapter->fwWakeupMethod == WAKEUP_FW_THRU_GPIO) { + GPIO_PORT_TO_LOW(); + } else + ret = sdio_write_ioreg(priv->wlan_dev.card, FN1, CONFIGURATION_REG, + HOST_POWER_UP); + + return ret; +} + +/** + * @brief This function resets the setting of deep sleep. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_reset_deepsleep_wakeup(wlan_private * priv) +{ + + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (priv->adapter->fwWakeupMethod == WAKEUP_FW_THRU_GPIO) { + GPIO_PORT_TO_HIGH(); + } else + ret = + sdio_write_ioreg(priv->wlan_dev.card, FN1, CONFIGURATION_REG, 0); + + LEAVE(); + + return ret; +} + +#ifdef ENABLE_PM +/** + * @brief This function suspends the device. + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sbi_suspend(wlan_private * priv) +{ + return sdio_suspend(priv->wlan_dev.card); +} + +/** + * @brief This function resumes the device from sleep + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE +*/ +int +sbi_resume(wlan_private * priv) +{ + return sdio_resume(priv->wlan_dev.card); +} +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_sdio/if_sdio.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_sdio/if_sdio.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_sdio/if_sdio.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_sdio/if_sdio.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,112 @@ +/** @file if_sdio.h + * @brief This file contains SDIO IF (interface) module + * related macros, enum, and structure. + * + * (c) Copyright © 2003-2006, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************** +Change log: + 10/12/05: add Doxygen format comments +****************************************************/ + +#ifndef _IF_SDIO_H_ +#define _IF_SDIO_H_ + +#include +#include + +#define SD_BUS_WIDTH_1 0x00 +#define SD_BUS_WIDTH_4 0x02 +#define SD_BUS_WIDTH_MASK 0x03 +#define ASYNC_INT_MODE 0x20 + +/* Host Control Registers */ +#define IO_PORT_0_REG 0x00 +#define IO_PORT_1_REG 0x01 +#define IO_PORT_2_REG 0x02 +#define CONFIGURATION_REG 0x03 +#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) +#define HOST_POWER_UP (0x1U << 1) +#define HOST_POWER_DOWN (0x1U << 0) +#define HOST_INT_MASK_REG 0x04 +#define UP_LD_HOST_INT_MASK (0x1U) +#define DN_LD_HOST_INT_MASK (0x2U) +#define HOST_INTSTATUS_REG 0x05 +#define UP_LD_HOST_INT_STATUS (0x1U) +#define DN_LD_HOST_INT_STATUS (0x2U) +#define HOST_INT_RSR_REG 0x06 +#define UP_LD_HOST_INT_RSR (0x1U) +#define HOST_INT_STATUS_REG 0x07 +#define UP_LD_CRC_ERR (0x1U << 2) +#define UP_LD_RESTART (0x1U << 1) +#define DN_LD_RESTART (0x1U << 0) + +/* Card Control Registers */ +#define SQ_READ_BASE_ADDRESS_A0_REG 0x10 +#define SQ_READ_BASE_ADDRESS_A1_REG 0x11 +#define SQ_READ_BASE_ADDRESS_A2_REG 0x12 +#define SQ_READ_BASE_ADDRESS_A3_REG 0x13 +#define SQ_READ_BASE_ADDRESS_B0_REG 0x14 +#define SQ_READ_BASE_ADDRESS_B1_REG 0x15 +#define SQ_READ_BASE_ADDRESS_B2_REG 0x16 +#define SQ_READ_BASE_ADDRESS_B3_REG 0x17 +#define CARD_STATUS_REG 0x20 +#define CARD_IO_READY (0x1U << 3) +#define CIS_CARD_RDY (0x1U << 2) +#define UP_LD_CARD_RDY (0x1U << 1) +#define DN_LD_CARD_RDY (0x1U << 0) +#define HOST_INTERRUPT_MASK_REG 0x24 +#define HOST_POWER_INT_MASK (0x1U << 3) +#define ABORT_CARD_INT_MASK (0x1U << 2) +#define UP_LD_CARD_INT_MASK (0x1U << 1) +#define DN_LD_CARD_INT_MASK (0x1U << 0) +#define CARD_INTERRUPT_STATUS_REG 0x28 +#define POWER_UP_INT (0x1U << 4) +#define POWER_DOWN_INT (0x1U << 3) +#define CARD_INTERRUPT_RSR_REG 0x2c +#define POWER_UP_RSR (0x1U << 4) +#define POWER_DOWN_RSR (0x1U << 3) +#define DEBUG_0_REG 0x30 +#define SD_TESTBUS0 (0x1U) +#define DEBUG_1_REG 0x31 +#define SD_TESTBUS1 (0x1U) +#define DEBUG_2_REG 0x32 +#define SD_TESTBUS2 (0x1U) +#define DEBUG_3_REG 0x33 +#define SD_TESTBUS3 (0x1U) +#define CARD_OCR_0_REG 0x34 +#define CARD_OCR_1_REG 0x35 +#define CARD_OCR_3_REG 0x36 +#define CARD_CONFIG_REG 0x38 +#define CARD_REVISION_REG 0x3c +#define CMD53_FINISH_GBUS (0x1U << 1) +#define SD_NEG_EDGE (0x1U << 0) + +/* Special registers in function 0 of the SDxx card */ +#define SCRATCH_0_REG 0x80fe +#define SCRATCH_1_REG 0x80ff +#define HOST_F1_RD_BASE_0 0x0010 +#define HOST_F1_RD_BASE_1 0x0011 +#define HOST_F1_CARD_RDY 0x0020 + +/******************************************************** + Global Functions +********************************************************/ + +extern int sdio_get_vendor_id(mmc_card_t card); + +#endif /* _IF_SDIO_H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_usb/if_usb.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_usb/if_usb.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_usb/if_usb.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_usb/if_usb.c 1969-12-31 19:00:00.000000000 -0500 @@ -1,1051 +0,0 @@ -/** @file if_usb.c - * @brief This file contains functions used in USB interface module. - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - * - */ -/******************************************************** -Change log: - 09/29/05: Add Doxygen format comments - 02/01/06: Correct the usage of compile flag HELPER_IMAGE - 02/13/06: Add a FW ready flag for interoperability issue - 02/22/06: Add support for new VID/PID - 03/02/06: Add receive exception handling, fix some memory leak issues - 03/03/06: Add FW download failure handling - 03/10/06: Fix the rmmod/insmod issue - 04/07/06: Add Linux kernel 2.6 support - 04/21/06: Add hotplug firmware loading - -********************************************************/ - -#include "if_usb.h" - -#include - -/******************************************************** - Local Variables -********************************************************/ -#define MARVELL_USB_DEVICE(vid, pid, name) \ - USB_DEVICE(vid, pid), \ - .driver_info = (u32)name - -/* Context definition for Interrupt simulation */ -#define TX_SUCCESS 1 -#define RX_SUCCESS 2 -#define TX_FAILURE -1 - -#define MESSAGE_HEADER_LEN 4 - -static wlan_private *pwlanpriv; -static struct usb_card_rec usb_cardp; -const char usbdriver_name[] = "usb8xxx"; -static u8 usb_int_cause = 0; -BOOLEAN usb_fw_ready = TRUE; - -/** struct This structure contains the device signature */ -struct usb_device_id if_usb_table[] = { - - /* Enter the device signature inside */ - {MARVELL_USB_DEVICE(USB8388_VID_1, USB8388_PID_1, "Marvell WLAN USB Adapter")}, - {MARVELL_USB_DEVICE(USB8388_VID_2, USB8388_PID_2, "Marvell WLAN USB Adapter")}, - - /* Terminating entry */ - {} , -}; - -int if_prog_firmware(wlan_private *priv); -static int if_usb_submit_rx_urb(wlan_private *priv); - -static void if_usb_receive(struct urb *urb, struct pt_regs *regs); -static int if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id); -static void if_usb_disconnect(struct usb_interface *intf); -static int if_usb_suspend(struct usb_interface *intf, pm_message_t message); -static int if_usb_resume(struct usb_interface *intf); - -/** if_usb_driver */ -static struct usb_driver if_usb_driver = { - /* driver name */ - .name = usbdriver_name, - - /* probe function name */ - .probe = if_usb_probe, - - /* disconnect function name */ - .disconnect = if_usb_disconnect, - - /* device signature table */ - .id_table = if_usb_table, - - .suspend = if_usb_suspend, - - .resume = if_usb_resume, -}; - -MODULE_DEVICE_TABLE(usb, if_usb_table); - -/******************************************************** - Global Variables -********************************************************/ - - -/******************************************************** - Local Functions -********************************************************/ -/** - * @brief Interrupt handler - * @param priv pointer to wlan_private - * @param flag flag - * @param context context parameter - * @return N/A - */ -static void if_usb_interrupt(wlan_private *priv, u8 flags, int context) -{ - wlan_interrupt(priv->wlan_dev.netdev); -} - -/** - * @brief call back function to handle the status of the URB - * @param urb pointer to urb structure - * @return N/A - */ -static void if_usb_write_bulk_callback(struct urb *urb, struct pt_regs *regs) -{ - wlan_private *priv = (wlan_private *)(urb->context); - struct usb_card_rec *cardp = priv->wlan_dev.card; - - ENTER(); - - cardp->tx_urb_pending = FALSE; - - /* handle the transmission complete validations */ - - if (urb->status != 0) { - /* print the failure status number for debug */ - PRINTM(FATAL, "URB in failure status\n"); - if (!cardp->IsFWDnld) { - if_usb_interrupt(priv, 0, TX_FAILURE); - } else { - goto tx_exit; - } - } else { - PRINTM(INFO, "URB status is successfull\n"); - PRINTM(INFO, "Actual length transmitted %d\n", urb->actual_length); - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; - } - - if (!cardp->IsFWDnld) { - usb_int_cause |= HIS_TxDnLdRdy; - if (priv->adapter->PSState != PS_STATE_SLEEP) - if_usb_interrupt(priv, HIS_TxDnLdRdy, TX_SUCCESS); - } - -tx_exit: - LEAVE(); - return; -} - -/** - * @brief free tx/rx urb, skb and rx buffer - * @param cardp pointer usb_card_rec - * @return N/A - */ -static void if_usb_free(struct usb_card_rec *cardp) -{ - ENTER(); - - /* Unlink tx & rx urb */ - if (cardp->tx_urb) - usb_kill_urb(cardp->tx_urb); - if (cardp->rx_urb) - usb_kill_urb(cardp->rx_urb); - - os_sched_timeout(10); - - /* Free tx & rx urb */ - if (cardp->tx_urb) { - if (!cardp->tx_urb_pending) { - usb_free_urb(cardp->tx_urb); - cardp->tx_urb = NULL; - } - else { - PRINTM(FATAL, "Tx urb pending, can not free tx urb\n"); - } - } - - if (cardp->rx_urb) { - if (!cardp->rx_urb_pending) { - usb_free_urb(cardp->rx_urb); - cardp->rx_urb = NULL; - } - else { - PRINTM(FATAL, "Rx urb pending, can not free rx urb\n"); - } - } - - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - - if (cardp->bulk_out_buffer) { - kfree(cardp->bulk_out_buffer); - cardp->bulk_out_buffer = NULL; - } - - LEAVE(); - return ; -} - -/** - * @brief sets the configuration values - * @param udev pointer to usb_device - * @param ifnum interface number - * @param id pointer to usb_device_id - * @return address of gloabl variable usb_cardp - */ -static int if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i; - - ENTER(); - - udev = interface_to_usbdev(intf); - - /* Check probe is for our device */ - for (i=0; if_usb_table[i].idVendor; i++) - { - if (udev->descriptor.idVendor == if_usb_table[i].idVendor && - udev->descriptor.idProduct == if_usb_table[i].idProduct) - { - PRINTM(INFO, "VID/PID = %X/%X, matched\n", udev->descriptor.idVendor, udev->descriptor.idProduct); - break; - } - } - - if ( if_usb_table[i].idVendor ) { - - usb_cardp.udev = udev; - iface_desc = intf->cur_altsetting; - - PRINTM(INFO, "bcdUSB = 0x%X bDeviceClass = 0x%X" - " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", - udev->descriptor.bcdUSB, - udev->descriptor.bDeviceClass, - udev->descriptor.bDeviceSubClass, - udev->descriptor.bDeviceProtocol); - - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if ((endpoint->bEndpointAddress & BULK_ENDPOINT_PRESENT) && - ((endpoint->bmAttributes & BULK_ENDPOINT_MASK) == BULK_ENDPOINT_FOUND)) { - /* we found a bulk in endpoint */ - PRINTM(INFO, "Bulk in size is %d\n", - endpoint->wMaxPacketSize); - if (!(usb_cardp.rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { - PRINTM(INFO, "Rx URB allocation failed\n"); - goto error; - } - usb_cardp.rx_urb_pending = FALSE; - usb_cardp.rx_urb_recall = FALSE; - - usb_cardp.bulk_in_size = - endpoint->wMaxPacketSize; - usb_cardp.bulk_in_endpointAddr = - (endpoint->bEndpointAddress & ENDPOINT_NUMBER_MASK); - PRINTM(INFO, "in_endpoint = %d\n", - endpoint->bEndpointAddress); - } - - if (((endpoint->bEndpointAddress & BULK_ENDPOINT_PRESENT) == BULK_OUT_PRESENT) && - ((endpoint->bmAttributes & BULK_ENDPOINT_MASK) == BULK_ENDPOINT_FOUND)) { - /* We found bulk out endpoint */ - if (!(usb_cardp.tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { - PRINTM(INFO, "Tx URB allocation failed\n"); - goto error; - } - usb_cardp.tx_urb_pending = FALSE; - - usb_cardp.bulk_out_size = - endpoint->wMaxPacketSize; - PRINTM(INFO, "Bulk out size is %d\n", - endpoint->wMaxPacketSize); - usb_cardp.bulk_out_endpointAddr = - endpoint->bEndpointAddress; - PRINTM(INFO, "out_endpoint = %d\n", - endpoint->bEndpointAddress); - usb_cardp.bulk_out_buffer = - kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, - GFP_DMA); - - if (!usb_cardp.bulk_out_buffer) { - PRINTM(INFO, "Could not allocate buffer\n"); - goto error; - } - } - } - - /* At this point wlan_add_card() will be called */ - if (!(pwlanpriv = usb_cardp.add(&usb_cardp))) { - goto error; - } - - usb_get_dev(udev); - usb_set_intfdata(intf, &usb_cardp); - LEAVE(); - - /* - * return card structure, which can be got back in the - * diconnect function as the ptr - * argument. - */ - return 0; - } else { - PRINTM(INFO, "Discard the Probe request\n"); - PRINTM(INFO, "VID = 0x%X PID = 0x%X\n", udev->descriptor.idVendor, - udev->descriptor.idProduct); - } -error: - if_usb_free(&usb_cardp); - - LEAVE(); - return (-ENOMEM); -} - -/** - * @brief free resource and cleanup - * @param udev pointer to usb_device - * @param ptr pointer to usb_cardp - * @return N/A - */ -static void if_usb_disconnect(struct usb_interface *intf) -{ - struct usb_card_rec *cardp = usb_get_intfdata(intf); - wlan_private *priv = (wlan_private*)cardp->priv; - wlan_adapter *Adapter = priv->adapter; - - ENTER(); - - /* - * Update Surprie removed to TRUE - * Free all the URB's allocated - */ - if (!Adapter->SurpriseRemoved) { - Adapter->SurpriseRemoved = TRUE; - } - - /* Unlink and free urb */ - if_usb_free(cardp); - - /* card is removed and we can call wlan_remove_card */ - PRINTM(INFO, "call remove card\n"); - cardp->remove(cardp); - - usb_set_intfdata(intf,NULL); - usb_put_dev(interface_to_usbdev(intf)); - - LEAVE(); - return ; -} - -/** - * @brief This function transfer the data to the device. - * @param priv pointer to wlan_private - * @param payload pointer to payload data - * @param nb data length - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb) -{ - /* pointer to card structure */ - struct usb_card_rec *cardp = priv->wlan_dev.card; - int ret = WLAN_STATUS_FAILURE; - - ENTER(); - - /* check if device is removed */ - if (priv->adapter->SurpriseRemoved) { - PRINTM(INFO, "Device removed\n"); - goto tx_ret; - } - - /* use USB API macro FILL_BULK_URB or API function - * usb_fill_bulk_urb() used to set the - * configuration information to send the bulk URB - */ - usb_fill_bulk_urb( cardp->tx_urb, cardp->udev, - usb_sndbulkpipe(cardp->udev, - cardp->bulk_out_endpointAddr), - payload, nb, if_usb_write_bulk_callback, priv); - - cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET; - - if ((ret=usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) { - /* transfer failed */ - PRINTM(INFO, "usb_submit_urb Failed\n"); - - ret = WLAN_STATUS_FAILURE; - } else { - cardp->tx_urb_pending = TRUE; - PRINTM(INFO, "usb_submit_urb Success\n"); - ret = WLAN_STATUS_SUCCESS; - } - -tx_ret: - LEAVE(); - return ret; -} - -/** - * @brief This function submit the rx data to OS - * @param priv pointer to wlan_private structure - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int if_usb_submit_rx_urb(wlan_private *priv) -{ - struct usb_card_rec *cardp = priv->wlan_dev.card; - int ret = WLAN_STATUS_FAILURE; - - ENTER(); - - if(!(cardp->skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { - PRINTM(FATAL, "No free skb\n"); - goto rx_ret; - } - - /* Fill the receive configuration URB and initialise the Rx call back */ - usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, - usb_rcvbulkpipe(cardp->udev, cardp->bulk_in_endpointAddr), - cardp->skb->tail + IPFIELD_ALIGN_OFFSET, - MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, - if_usb_receive, priv); - - cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - - PRINTM(INFO, "Pointer for rx_urb %p\n", cardp->rx_urb); - if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { - /* handle failure conditions */ - PRINTM(INFO, "Submit Rx URB failed\n"); - ret = WLAN_STATUS_FAILURE; - } - else { - cardp->rx_urb_pending = TRUE; - PRINTM(INFO, "Submit Rx URB Success\n"); - ret = WLAN_STATUS_SUCCESS; - } - -rx_ret: - LEAVE(); - return ret; -} - -/** - * @brief This function reads of the packet into the upload buff, - * wake up the main thread and initialise the Rx callack. - * - * @param urb pointer to struct urb - * @return N/A - */ -static void if_usb_receive(struct urb *urb, struct pt_regs *regs) -{ - wlan_private *priv = (wlan_private *)urb->context; - struct usb_card_rec *cardp = - (struct usb_card_rec *)priv->wlan_dev.card; - - int RecvLength = urb->actual_length; - u8 *RecvBuff = NULL; - u32 RecvType; - u8 *cmdBuf; - - FWSyncHeader SyncFWHeader; - -#define MRVDRV_MIN_PKT_LEN 30 - - ENTER(); - - cardp->rx_urb_pending = FALSE; - - if (RecvLength) { - if (urb->status) { - PRINTM(INFO, "URB Status is failed\n"); - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - goto setup_for_next; - } - - RecvBuff = cardp->skb->data + IPFIELD_ALIGN_OFFSET; - memcpy(&RecvType, RecvBuff, sizeof(u32)); - PRINTM(INFO, "Recv length = 0x%x\n", RecvLength); - PRINTM(INFO, "Receive type = 0x%X\n", RecvType); - RecvType = wlan_le32_to_cpu(RecvType); - PRINTM(INFO, "Receive type after = 0x%X\n", RecvType); - } else if (urb->status) { - if (!cardp->rx_urb_recall) { - PRINTM(INFO, "Card Is Removed\n"); - priv->adapter->SurpriseRemoved = TRUE; - // Wake up main thread to handle card removal. - if_usb_interrupt(priv, 0, 0); - } - goto rx_exit; - } - - if (cardp->IsFWDnld) { - - memcpy(&SyncFWHeader, RecvBuff, sizeof(FWSyncHeader)); - - - if (!SyncFWHeader.Cmd) { - PRINTM(INFO, "FW received Blk with correct CRC\n"); - PRINTM(INFO, "FW received Blk SeqNum = %d\n",SyncFWHeader.SeqNum); - cardp->CRC_OK = TRUE; - } else { - PRINTM(INFO, "FW received Blk with CRC error\n"); - cardp->CRC_OK = FALSE; - } - - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - - if (cardp->FWFinalBlk) { - cardp->FwDnldOver = TRUE; - cardp->IsFWDnld = FALSE; - goto rx_exit; - } - - if_prog_firmware(priv); - - if_usb_submit_rx_urb(priv); - - goto rx_exit; - } - - switch (RecvType) { - case CMD_TYPE_DATA: - if (RecvLength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + - MESSAGE_HEADER_LEN || RecvLength < MRVDRV_MIN_PKT_LEN) { - PRINTM(INFO, "Packet length is Invalid\n"); - - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - - break; - } - - usb_int_cause |= HIS_RxUpLdRdy; - skb_reserve(cardp->skb, IPFIELD_ALIGN_OFFSET); - skb_put(cardp->skb, RecvLength); - skb_pull(cardp->skb, MESSAGE_HEADER_LEN); - list_add_tail((struct list_head *)cardp->skb, - (struct list_head *)&priv->adapter->RxSkbQ); - - priv->wlan_dev.upld_len = (RecvLength - MESSAGE_HEADER_LEN); - - if_usb_interrupt(priv, HIS_RxUpLdRdy, RX_SUCCESS); - break; - - case CMD_TYPE_REQUEST: - if (RecvLength > MRVDRV_SIZE_OF_CMD_BUFFER) { - PRINTM(INFO, "The receive buffer is too large\n"); - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - - break; - } - - /* take care of CurCmd = NULL case by reading the - * data to clear the interrupt */ - if (!priv->adapter->CurCmd) { - cmdBuf = priv->wlan_dev.upld_buf; - priv->adapter->HisRegCpy &= ~HIS_CmdUpLdRdy; - } else { - cmdBuf = priv->adapter->CurCmd->BufVirtualAddr; - } - - usb_int_cause |= HIS_CmdUpLdRdy; - priv->wlan_dev.upld_len = (RecvLength - MESSAGE_HEADER_LEN); - memcpy(cmdBuf, RecvBuff+MESSAGE_HEADER_LEN, - priv->wlan_dev.upld_len); - - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - PRINTM(INFO, "Wake up main thread to handle cmd response\n"); - if_usb_interrupt(priv, HIS_CmdUpLdRdy, RX_SUCCESS); - break; - - case CMD_TYPE_INDICATION: - /* Event cause handling */ - priv->adapter->EventCause = *(u32 *)(RecvBuff + MESSAGE_HEADER_LEN); - - PRINTM(INFO, "**EVENT** 0x%X\n", priv->adapter->EventCause); - if (priv->adapter->EventCause & 0xffff0000) { - SendTxFeedback(priv); - break; - } - priv->adapter->EventCause = wlan_le32_to_cpu(priv->adapter->EventCause) << 3; - - usb_int_cause |= HIS_CardEvent; - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - if_usb_interrupt(priv, HIS_CardEvent, RX_SUCCESS); - - break; - - default: - if (cardp->skb) { - kfree_skb(cardp->skb); - cardp->skb = NULL; - } - break; - } - -setup_for_next: - if_usb_submit_rx_urb(priv); -rx_exit: - LEAVE(); - return; -} - -/******************************************************** - Global Functions -********************************************************/ - -/** - * @brief This function downloads data to FW - * @param priv pointer to wlan_private structure - * @param type type of data - * @param buf pointer to data buffer - * @param len number of bytes - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int sbi_host_to_card(wlan_private *priv, u8 type, u8 *payload, u16 nb) -{ - int ret = WLAN_STATUS_FAILURE; - u32 tmp; - struct usb_card_rec *cardp = - (struct usb_card_rec *)priv->wlan_dev.card; - - ENTER(); - - PRINTM(INFO, "*** type = %u\n",type); - PRINTM(INFO, "Size after = %d\n", nb); - - if (type == MVMS_CMD) { - tmp = wlan_cpu_to_le32(CMD_TYPE_REQUEST); - priv->wlan_dev.dnld_sent = DNLD_CMD_SENT; - memcpy(cardp->bulk_out_buffer, (u8 *)&tmp, MESSAGE_HEADER_LEN); - - } else { - tmp = wlan_cpu_to_le32(CMD_TYPE_DATA); - priv->wlan_dev.dnld_sent = DNLD_DATA_SENT; - memcpy(cardp->bulk_out_buffer, (u8*)&tmp, MESSAGE_HEADER_LEN); - } - - memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb); - - ret = usb_tx_block(priv, cardp->bulk_out_buffer, nb + MESSAGE_HEADER_LEN); - - return ret; -} - -/** - * @brief This function reads data from FW. - * @param priv pointer to wlan_private structure - * @param type type of data to read - * @param nb number of data bytes - * @param payload buffer for payload data - * @param npayload number of bytes to read - * @return WLAN_STATUS_SUCCESS - */ -int sbi_card_to_host(wlan_private *priv, u32 type, u32 *nb, u8 *payload, - u16 npayload) -{ - /* handle dummy conditions as upload buf is ready in the - * Rx callback - */ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_reenable_host_interrupt(wlan_private *priv, u8 bits) -{ - return WLAN_STATUS_SUCCESS; -} - -int sbi_get_int_status(wlan_private *priv , u8 *ireg) -{ - ENTER(); - - OS_INT_DISABLE; - *ireg = usb_int_cause; - usb_int_cause = 0; - OS_INT_RESTORE; - - PRINTM(INFO, "Int cause is 0x%X\n", *ireg); - - LEAVE(); - - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_read_event_cause(wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_get_cis_info(wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_unregister_dev(wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This function registers driver. - * @param add pointer to add_card callback function - * @param remove pointer to remove card callback function - * @param arg pointer to call back function parameter - * @return pointer to usb_cardp - */ -int *sbi_register(wlan_notifier_fn_add add, wlan_notifier_fn_remove remove, - void *arg) -{ - ENTER(); - - /* - * Make use of the global variable cardp, - * to assign the call backs - */ - - PRINTM(INFO, "udev pointer is at %p\n", usb_cardp.udev); - - usb_cardp.add = (usb_notifier_fn_add)add; - usb_cardp.remove = (usb_notifier_fn_remove)remove; - - /* - * API registers the Marvell USB driver - * to the USB system - */ - usb_register(&if_usb_driver); - - LEAVE(); - - /* Return the cardp structure to wlan layer */ - return (int *)&usb_cardp; -} - -/** - * @brief This function removes usb driver. - * @return N/A - */ -void sbi_unregister(void) -{ - ENTER(); - - // Need to send a Reset command to device before USB resources freed and wlan_remove_card() called, - // then device can handle FW download again. - if (pwlanpriv) { - PrepareAndSendCommand(pwlanpriv, HostCmd_CMD_802_11_RESET, - HostCmd_ACT_HALT, 0, 0, NULL); - os_sched_timeout(10); - } - - /* API unregisters thedriver from USB subsystem */ - usb_deregister(&if_usb_driver); - - LEAVE(); - return ; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_probe_card(void * card_p) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This function register usb device and initialize parameter - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int sbi_register_dev(wlan_private *priv) -{ - - struct usb_card_rec *cardp = - (struct usb_card_rec *)priv->wlan_dev.card; - ENTER(); - - cardp->priv = priv; - cardp->eth_dev = priv->wlan_dev.netdev; - priv->hotplug_device = &(cardp->udev->dev); - /* - * Receive hander is initialised for command - * or data receive - */ - PRINTM(INFO, "cardp = %p priv = %p\n", cardp, priv); - if (if_usb_submit_rx_urb(priv) < 0) { - PRINTM(INFO, "URB submission is failed\n"); - sbi_unregister(); - LEAVE(); - return WLAN_STATUS_FAILURE; - } - - PRINTM(INFO, "udev pointer is at %p\n", cardp->udev); - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief stub function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_verify_fw_download(wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This function download FW - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int if_prog_firmware(wlan_private *priv) -{ - struct usb_card_rec *cardp = priv->wlan_dev.card; - FWData fwdata; - - u8 *firmware = priv->firmware->data; - - ENTER(); - - if (!cardp->CRC_OK) { - cardp->TotalBytes = cardp->FwLastBlkSent; - cardp->FWSeqNum = cardp->LastSeqNum - 1; - } - - PRINTM(INFO, "TotalBytes = %d\n", cardp->TotalBytes); - - - memcpy(&fwdata.fwheader, &firmware[cardp->TotalBytes], sizeof(FWHeader)); - - - cardp->FwLastBlkSent = cardp->TotalBytes; - cardp->TotalBytes += sizeof(FWHeader); - - PRINTM(INFO, "Copy Data\n"); - memcpy(fwdata.data, &firmware[cardp->TotalBytes], fwdata.fwheader.DataLength); - - PRINTM(INFO, "Data Length = %d\n", fwdata.fwheader.DataLength); - - cardp->FWSeqNum = cardp->FWSeqNum + 1; - - fwdata.SeqNum = cardp->FWSeqNum; - cardp->LastSeqNum = fwdata.SeqNum; - cardp->TotalBytes += fwdata.fwheader.DataLength; - - if (fwdata.fwheader.DnldCmd == FW_HAS_DATA_TO_RECV) { - PRINTM(INFO, "There is data to follow\n"); - PRINTM(INFO, "SeqNum = %d TotalBytes = %d\n", cardp->FWSeqNum, cardp->TotalBytes); - memcpy(cardp->bulk_out_buffer, &fwdata.fwheader, FW_DATA_XMIT_SIZE); - usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); - - } else if (fwdata.fwheader.DnldCmd == FW_HAS_LAST_BLOCK) { - PRINTM(INFO, "Host has finished FW downloading\n"); - PRINTM(INFO, "Donwloading FW JUMP BLOCK\n"); - memcpy(cardp->bulk_out_buffer, &fwdata.fwheader, FW_DATA_XMIT_SIZE); - usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE); - - cardp->FWFinalBlk = TRUE; - } - - PRINTM(INFO, "The firmware download is done size is %d\n", cardp->TotalBytes); - - LEAVE(); - - return WLAN_STATUS_SUCCESS; -} - - -/** - * @brief This function download fw - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_prog_firmware(wlan_private *priv) -{ - struct usb_card_rec *cardp = priv->wlan_dev.card; - int i = 0; - - ENTER(); - - usb_fw_ready = FALSE; - - cardp->TotalBytes = 0; - cardp->FwLastBlkSent = 0; - cardp->CRC_OK = TRUE; - cardp->FwDnldOver = FALSE; - cardp->IsFWDnld = TRUE; - cardp->FWSeqNum = -1; - cardp->TotalBytes = 0; - cardp->FWFinalBlk = FALSE; - - if_prog_firmware(priv); - - do { - PRINTM(INFO, "Wlan sched timeout\n"); - i ++; - os_sched_timeout(100); - if (priv->adapter->SurpriseRemoved || i>=20) - break; - } while (!cardp->FwDnldOver); - - if (!cardp->FwDnldOver) { - PRINTM(FATAL, "FW download failure, time = %d ms\n", i*100); - LEAVE(); - return WLAN_STATUS_FAILURE; - } - - if_usb_submit_rx_urb(priv); - - /* Delay 200 ms to waiting for the FW ready */ - os_sched_timeout(200); - - usb_fw_ready = TRUE; - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_enable_host_int (wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -int sbi_disable_host_int(wlan_private *priv) -{ - return WLAN_STATUS_SUCCESS; -} - -#ifdef ENABLE_PM -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -inline int sbi_suspend(wlan_private * priv) -{ - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This is a dummy function - * @param priv pointer to wlan_private - * @return WLAN_STATUS_SUCCESS - */ -inline int sbi_resume(wlan_private * priv) -{ - return WLAN_STATUS_SUCCESS; -} -#endif - -static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_card_rec *cardp = usb_get_intfdata(intf); - wlan_private *priv = cardp->priv; - - ENTER(); - - if (priv->adapter->PSState != PS_STATE_FULL_POWER) - return -1; - netif_device_detach(cardp->eth_dev); - - cardp->rx_urb_recall = TRUE; - - LEAVE(); - return 0; -} - -static int if_usb_resume(struct usb_interface *intf) -{ - struct usb_card_rec *cardp = usb_get_intfdata(intf); - - ENTER(); - - cardp->rx_urb_recall = FALSE; - if (!cardp->rx_urb_pending) { - if_usb_submit_rx_urb(cardp->priv); - } - - netif_device_attach(cardp->eth_dev); - - LEAVE(); - return 0; -} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_usb/if_usb.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_usb/if_usb.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/if/if_usb/if_usb.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/if/if_usb/if_usb.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,132 +0,0 @@ -/** @file if_usb.h - * - * @brief This file contains definition for USB interface. - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - * - */ -/******************************************************** -Change log: - 10/11/05: Add Doxygen format comments - -********************************************************/ - -#include - -#define CMD_TYPE_REQUEST 0xF00DFACE -#define CMD_TYPE_DATA 0xBEADC0DE -#define CMD_TYPE_INDICATION 0xBEEFFACE - -#define BULK_ENDPOINT_PRESENT USB_ENDPOINT_DIR_MASK -#define BULK_ENDPOINT_MASK USB_ENDPOINT_XFERTYPE_MASK -#define BULK_ENDPOINT_FOUND USB_ENDPOINT_XFER_BULK -#define ENDPOINT_NUMBER_MASK USB_ENDPOINT_NUMBER_MASK - -#define BULK_OUT_PRESENT 0x00 - -#define IPFIELD_ALIGN_OFFSET 2 - -#define USB8388_VID_1 0x1286 -#define USB8388_PID_1 0x2001 -#define USB8388_VID_2 0x05a3 -#define USB8388_PID_2 0x8388 - -/** USB card description structure*/ -struct usb_card_rec -{ - struct net_device *eth_dev; - struct usb_device *udev; - struct urb *rx_urb, *tx_urb; - u16 irq; - u32 port; - u8 flag; - u16 host_int_mask; - void * (*add)(struct usb_card_rec *card); - int (*remove)(struct usb_card_rec *card); - void (*user_isr)(int, void*, struct pt_regs*); - void *priv; - - struct sk_buff *skb; - int bulk_in_size; - u8 bulk_in_endpointAddr; - - u8 *bulk_out_buffer; - int bulk_out_size; - u8 bulk_out_endpointAddr; - - u8 CRC_OK; - u8 SendNextBlk; - u8 IsFWDnld; - u32 FWSeqNum; - u32 LastSeqNum; - u32 TotalBytes; - u32 FwLastBlkSent; - u8 FwDnldOver; - u8 FWFinalBlk; - - BOOLEAN tx_urb_pending; - BOOLEAN rx_urb_pending; - BOOLEAN rx_urb_recall; -} ; - -typedef void * (*usb_notifier_fn_add) (struct usb_card_rec *); -typedef int (*usb_notifier_fn_remove) (struct usb_card_rec *); - -/** if_usb_context_data */ -typedef struct _if_usb_context_data { - int done; -} if_usb_context_data; - -/** TransmitBuffer */ -typedef struct _TransmitBuffer { - u32 TransmitType; - u8 payload[MRVDRV_ETH_TX_PACKET_BUFFER_SIZE]; -} TransmitBuffer; - -/** FWHeader */ -typedef struct _FWHeader { - u32 DnldCmd; - u32 BaseAddr; - u32 DataLength; - u32 CRC; -} __ATTRIB_PACK__ FWHeader, *pFWHeader; - -#define FW_MAX_DATA_BLK_SIZE 600 -/** FWData */ -typedef struct _FWData { - FWHeader fwheader; - u32 SeqNum; - u8 data[FW_MAX_DATA_BLK_SIZE]; -} __ATTRIB_PACK__ FWData, pFWData; - -/** FWSyncHeader */ -typedef struct _FWSyncHeader { - u32 Cmd __ATTRIB_ALIGN__; - u32 SeqNum __ATTRIB_ALIGN__; -} __ATTRIB_PACK__ FWSyncHeader; - -#define REQ_TYPE 0 /* for compilation only */ -#define REQ_CTRL 0 /* for compilation only */ -#define TIME_OUT_VALUE 0 /* for compilation only */ - - -#define FW_HAS_DATA_TO_RECV 0x00000001 -#define FW_HAS_LAST_BLOCK 0x00000004 - -#define FW_DATA_XMIT_SIZE \ - sizeof(FWHeader) + fwdata.fwheader.DataLength + sizeof(u32) - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/FpgaConfig.xml 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/FpgaConfig.xml --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/FpgaConfig.xml 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/FpgaConfig.xml 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,10 @@ + + + 1 + 4 + 1 + ef + 1 + 2 + + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/load 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/load --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/load 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/load 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,4 @@ +#cardctl resume +./mrvlsdio_load +insmod sdioapi.ko +insmod $1.ko diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/mrvlsdio_load 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/mrvlsdio_load --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/mrvlsdio_load 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/mrvlsdio_load 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,46 @@ +#!/bin/sh +module="mrvlsdio" +device="mrvlsdio" +mode="664" +par1="sdio_voltage=0xE8" +par2="clock_speed=0" +par3="bus_width=1" +par4="bus_type=1" +par5="debug_flags=0x0000030C" + +par1=`cat ./FpgaConfig.xml | awk -F"<|>" '/sdio_voltage/{print $2"=0x"$3}'` +par2=`cat ./FpgaConfig.xml | awk -F"<|>" '/clock_speed/{print $2"="$3}'` +par3=`cat ./FpgaConfig.xml | awk -F"<|>" '/bus_width/{print $2"="$3}'` +par4=`cat ./FpgaConfig.xml | awk -F"<|>" '/bus_type/{print $2"="$3}'` +#par5=`cat ./FpgaConfig.xml | awk -F"<|>" '/debug_flags/{print $2"=0x"$3}'` + +# Group: since distributions do it differently, look for wheel or use staff +if grep '^staff:' /etc/group > /dev/null; then + group="staff" +else + group="wheel" +fi + +# remove stale nodes +rm -f /dev/${device}? + +# invoke insmod with all arguments we got +# and use a pathname, as newer modutils don't look in . by default +#/sbin/insmod ./io/sdio/stdhost/$module.o $* || exit 1 + +/sbin/insmod ./$module.ko $par1 $par2 $par3 $par4 $par5 || exit 1 + +major=`cat /proc/devices | awk "\\$2==\"$module\" {print \\$1}"` + +# Remove stale nodes and replace them, then give gid and perms +# Usually the script is shorter, it's scull that has several devices in it. + +mknod /dev/${device}0 c $major 0 + +# give appropriate group/permissions +chgrp $group /dev/${device}0 +chmod $mode /dev/${device}0 + + + + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/mrvlsdio_unload 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/mrvlsdio_unload --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/mrvlsdio_unload 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/mrvlsdio_unload 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,11 @@ +#!/bin/sh +module="mrvlsdio" +device="mrvlsdio" + +# invoke rmmod with all arguments we got +/sbin/rmmod $module $* || exit 1 + +# remove nodes +rm -f /dev/${device}0 + +exit 0 diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/unload 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/unload --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/release2.6/unload 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/release2.6/unload 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,5 @@ +ifconfig eth1 down +#cardctl suspend +rmmod sd8xxx +rmmod sdioapi +./mrvlsdio_unload diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/apimain.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/apimain.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/apimain.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/apimain.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * Name: sdiobus.c + * Project: Export driver for SDIO API + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:30:19 $ + * Purpose: Export driver for SDIO API + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2005 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: apimain.c,v $ + * Revision 1.1 2007/01/18 09:30:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ +#ifndef _lint +static const char SysKonnectFileId[] = "@(#)" __FILE__ " (C) Marvell "; +#endif /* !_lint */ + +#include "drvvers.h" + +#define SDIO_BUS_DRIVER + +#include "h/sdioapi.h" + +#ifdef DBG +ULONG apiDebugLevel = DBG_DEFAULT; +#ifdef WINNT +LARGE_INTEGER t1Time, t1LastTime, t1CurTime; +LARGE_INTEGER t2Time, t2LastTime, t2CurTime; +LARGE_INTEGER t3Time, t3LastTime, t3CurTime; +LARGE_INTEGER t4Time, t4LastTime, t4CurTime; +LARGE_INTEGER t5Time, t5LastTime, t5CurTime; +LARGE_INTEGER t6Time, t6LastTime, t6CurTime; +#endif // #ifdef WINNT +#endif // #ifdef DBG + +#ifdef WINNT +NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, DriverEntry) +#endif + +// The DLL must have an entry point, but it is never called. +// +NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) +{ + return STATUS_SUCCESS; +} + +NTSTATUS +DllInitialize(IN PUNICODE_STRING RegistryPath) +{ + INITDEBUG(); + DBGPRINT(DBG_ALL, ("*** %s ***\n", SK_SIGNON_MSG)); + DBGPRINT(DBG_ALL, ("*** Built on %s %s ***\n", __DATE__, __TIME__)); + +#if DBG + DBGPRINT(DBG_ALL, ("*** DEBUG version ***\n")); +#else + DBGPRINT(DBG_ALL, ("*** FREE version ***\n")); +#endif + + return STATUS_SUCCESS; +} + +NTSTATUS +DllUnload() +{ + DBGPRINT(DBG_LOAD, ("SDIOAPI: DllUnload\n")); + return STATUS_SUCCESS; +} +#else // #ifdef WINNT +static int +sdioapi_init_module(void) +{ +// PSDIO_OBJECT pSdioObject; + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Module sdioapi init\n")); + + return 0; +} + +static void +sdioapi_exit_module(void) +{ + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Module sdioapi exit\n")); +} + +module_init(sdioapi_init_module); +module_exit(sdioapi_exit_module); + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/drvvers.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/drvvers.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/drvvers.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/drvvers.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Name: diagvers.h_ + * Project: Wireless LAN, SDIO Bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:30:19 $ + * Purpose: SDIO bus driver version control + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell. + * All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: drvvers.h,v $ + * Revision 1.1 2007/01/18 09:30:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ + +// #define SK_SIGNON_MSG "___OEM_SIGNONMSG__" +#define SK_SIGNON_MSG "Marvell SDIO API Export Driver V.1.0.0.0" diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/debug.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/debug.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/debug.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/debug.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,189 @@ +/***************************************************************************** +* +* Name: debug.h +* Project: SDIO API export driver +* Version: $Revision: 1.1 $ +* Date: $Date: 2007/01/18 09:31:25 $ +* Purpose: +* +* +*****************************************************************************/ +/****************************************************************************** + * + * (C)Copyright 2005 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ +/***************************************************************************** +* +* History: +* $Log: debug.h,v $ +* Revision 1.1 2007/01/18 09:31:25 pweber +* Put under CVS control +* +* +*****************************************************************************/ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#ifdef WINNT +#include +#endif + +#define DBG_NONE 0x00000000 // No debug - all off. +#define DBG_ERROR 0x00000001 // Debug for ERRORS +#define DBG_WARNING 0x00000002 // Debug for Warnings. +#define DBG_LOAD 0x00000004 // Debug for driver load +#define DBG_HWIF 0x00000008 +#define DBG_IRQ 0x00000080 + +#define DBG_T1 0x01000000 // Our various time stamps.. up to 6. +#define DBG_T2 0x02000000 // || +#define DBG_T3 0x04000000 // || +#define DBG_T4 0x08000000 // || +#define DBG_T5 0x10000000 // || +#define DBG_T6 0x20000000 // \/ +#define DBG_ALL 0xffffffff // All debug enabled. + +#define DBG_TIMESTAMPS ( DBG_T1 | DBG_T2 | DBG_T3 | DBG_T4 | DBG_T5 | DBG_T6 ) + +#define DBG_DEFAULT (DBG_NONE \ +| DBG_ERROR \ +| DBG_WARNING \ +| DBG_LOAD \ +| DBG_HWIF \ +) + +#ifdef DBG +extern ULONG apiDebugLevel; +#ifdef WINNT +extern unsigned char lptRegImage1; +extern unsigned char lptRegImage2; +extern LARGE_INTEGER t1Time, t1LastTime, t1CurTime; +extern LARGE_INTEGER t2Time, t2LastTime, t2CurTime; +extern LARGE_INTEGER t3Time, t3LastTime, t3CurTime; +extern LARGE_INTEGER t4Time, t4LastTime, t4CurTime; +extern LARGE_INTEGER t5Time, t5LastTime, t5CurTime; +extern LARGE_INTEGER t6Time, t6LastTime, t6CurTime; +#endif // WINNT +#endif // #ifdef DBG + +#ifdef WINNT +NTHALAPI + LARGE_INTEGER +KeQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL); + +extern LARGE_INTEGER isrTimeDelay; +#endif + +#ifdef DBG + +#define DBG_CRLF 0x00000000 // add some cr lfs before this message. +#define DBG_RAW 0x00000000 // raw debug output +#define DBG_DONTCARE (DBG_RAW | DBG_CRLF) // either of these by themselves should not cause debug to print. + +#define BUGPRINT(Str) DbgPrint Str +#ifdef WINNT + +#define KERN_DEBUG + +#define INITDEBUG() \ + KeQuerySystemTime(&t1Time); \ + KeQuerySystemTime(&t2Time); \ + KeQuerySystemTime(&t3Time); \ + KeQuerySystemTime(&t4Time); \ + KeQuerySystemTime(&t5Time); \ + KeQuerySystemTime(&t6Time); \ + KeQuerySystemTime(&t1CurTime); \ + KeQuerySystemTime(&t2CurTime); \ + KeQuerySystemTime(&t3CurTime); \ + KeQuerySystemTime(&t4CurTime); \ + KeQuerySystemTime(&t5CurTime); \ + KeQuerySystemTime(&t6CurTime); \ + KeQuerySystemTime(&t1LastTime); \ + KeQuerySystemTime(&t2LastTime); \ + KeQuerySystemTime(&t3LastTime); \ + KeQuerySystemTime(&t4LastTime); \ + KeQuerySystemTime(&t5LastTime); \ + KeQuerySystemTime(&t6LastTime); \ + +#define PrintMacro DbgPrint + +#define DBGPRINT(lvl, Str) \ + { \ + ULONG __lvl = lvl; \ + if ( apiDebugLevel & (__lvl & ~DBG_DONTCARE)) \ + { \ + if ( lvl & DBG_CRLF ) \ + { \ + PrintMacro("\n"); \ + } \ + KeQuerySystemTime(&t2CurTime); \ + PrintMacro("TS:%p:%d:%I64d - ",KeGetCurrentThread(),KeGetCurrentIrql(),(t2CurTime.QuadPart - t2LastTime.QuadPart)/10000); \ + t2LastTime.QuadPart = t2CurTime.QuadPart; \ + if ( __lvl & DBG_T1 ) \ + { \ + KeQuerySystemTime(&t1CurTime); \ + PrintMacro("T1:%I64d - ",t1CurTime.QuadPart - t1LastTime.QuadPart); \ + t1LastTime.QuadPart = t1CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T3 ) \ + { \ + KeQuerySystemTime(&t3CurTime); \ + PrintMacro("T3:%I64d - ",t3CurTime.QuadPart - t3LastTime.QuadPart); \ + t3LastTime.QuadPart = t3CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T4 ) \ + { \ + KeQuerySystemTime(&t4CurTime); \ + PrintMacro("T4:%I64d - ",t4CurTime.QuadPart - t4LastTime.QuadPart); \ + t4LastTime.QuadPart = t4CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T5 ) \ + { \ + KeQuerySystemTime(&t5CurTime); \ + PrintMacro("T5:%I64d - ",t5CurTime.QuadPart - t5LastTime.QuadPart); \ + t5LastTime.QuadPart = t5CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T6) \ + { \ + KeQuerySystemTime(&t6CurTime); \ + PrintMacro("T6:%I64d - ",t6CurTime.QuadPart - t6LastTime.QuadPart); \ + t6LastTime.QuadPart = t6CurTime.QuadPart; \ + } \ + PrintMacro Str; \ + }} +#else // #ifdef WINNT +#define PrintMacro printk + +#define INITDEBUG() + +#define DBGPRINT(lvl, Str) \ + { \ + ULONG __lvl = lvl; \ + if ( apiDebugLevel & (__lvl & ~DBG_DONTCARE)) \ + { \ + PrintMacro Str ; \ + }} + +#endif // #ifdef WINNT +#else +#define DBGPRINT(lvl,Str) +#define INITDEBUG() +#endif +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/sdioapi.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/sdioapi.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/sdioapi.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/sdioapi.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,40 @@ +#ifdef WINNT +#include +#include +#include +#define UDELAY KeStallExecutionProcessor + +#else // #ifndef WINNT + +#define UDELAY udelay + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#endif + +#include "../../stdhost/h/sktypes.h" + + /*--- mmoser 3/8/2006 ---*/ +#include "../../stdhost/h/sdio.h" + +#include "../h/sdio_if.h" +#include "../h/debug.h" + + /*--- mmoser 3/8/2006 ---*/ +/** +#ifdef SD8385 +#include "../h/sd8385.h" +#endif +*/ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/sdio_if.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/sdio_if.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/h/sdio_if.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/h/sdio_if.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,605 @@ +/** \file sdio_if.h + * + * Name: sdio_if.h + * Project: Wireless LAN, Interface to SDIO bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:31:25 $ + * Purpose: SDIO interface 2.0 to bus driver definitions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2005 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sdio_if.h,v $ + * Revision 1.1 2007/01/18 09:31:25 pweber + * Put under CVS control + * + * + ******************************************************************************/ +#ifndef __SDIO_IF_H +#define __SDIO_IF_H + +#ifndef WINNT +#include +#endif + + /*--- mmoser 3/20/2006 ---*/ +#include "sktypes.h" +#include "sdio.h" + +#ifdef WINNT +#pragma once +#endif + +#ifdef WINNT +#ifdef SDIO_API_INTERNAL +#define SDIO_API_IMPORT +#else +#define SDIO_API_IMPORT DECLSPEC_IMPORT +#endif // #ifdef SDIO_API_INTERNAL +#else +#define SDIO_API_IMPORT +#define EXTERN_C extern +#endif + +#ifdef USE_IF_SPINLOCK +#ifndef WINNT +#define LOCK_IF() unsigned long flags; \ + spin_lock_irqsave(&pSdio->IFSpinLock, flags); + +#define UNLOCK_IF() spin_unlock_irqrestore(&pSdio->fwSpinLock, flags); +#else +#define LOCK_IF() +#define UNLOCK_IF() +#endif +#else +#define LOCK_IF() +#define UNLOCK_IF() +#endif + +#ifdef USE_FW_SPINLOCK +#ifndef WINNT +#define LOCK_FW() unsigned long flags; \ + spin_lock_irqsave(&pSdio->IFSpinLock, flags); + +#define UNLOCK_FW() spin_unlock_irqrestore(&pSdio->fwSpinLock, flags); +#else +#define LOCK_FW() +#define UNLOCK_FW() +#endif +#else +#define LOCK_FW() +#define UNLOCK_FW() +#endif + +#ifndef WINNT +/* +// Call back functions for WLAN module +typedef void *(* add_card_notifier)(void *dev_id); +typedef int (* remove_card_notifier)(void *dev_id); +*/ + +// Call back functions for busdriver module +typedef void (*sdio_add_card_notifier) (void *); +typedef void (*sdio_remove_card_notifier) (void); + +void mrvlsdio_register_callbacks(sdio_add_card_notifier add, + sdio_remove_card_notifier _remove); +int mrvlsdio_get_interface(PGUID guid, ULONG size, ULONG version, + PVOID interface); + +#endif + +#define MILLI_SECOND 10000 + +#ifdef WINNT +#define _SLEEP_MS( pDev, millisecs ){\ +LARGE_INTEGER duetime;\ +if (KeGetCurrentIrql() < 2){\ +duetime.QuadPart = -((LONGLONG)MILLI_SECOND * (LONGLONG)(millisecs));\ +KeSetTimer ( &(pDev)->SleepTimer,duetime, NULL );\ +KeWaitForSingleObject( &(pDev)->SleepTimer,Executive,KernelMode,FALSE,NULL );\ +}else{\ +KeStallExecutionProcessor(millisecs*1000);}\ +} +#else +#define _SLEEP_MS( pDev, millisecs ) \ +mdelay(millisecs) +#endif + +/** \enum SDIO_API_STATUS + Status/ error codes returned by the abstracted interfaces +*/ +typedef enum +{ + SDIO_API_STATUS_SUCCESS = 0, + SDIO_API_STATUS_DEVICE_BUSY, //!< Device is busy... must wait. + SDIO_API_STATUS_NO_RESP, //!< No response is waiting from the device. + SDIO_API_STATUS_NO_DATA, //!< No data available at the device. + SDIO_API_STATUS_RESOURCES, //!< Out of whatever resource is being asked for + SDIO_API_STATUS_PENDING, //!< Unable to complete immediately + SDIO_API_STATUS_FAILURE, //!< Function call unsuccessful + SDIO_API_STATUS_INVALID_ARG, //!< Invalid argument passed by the caller + SDIO_API_STATUS_ERROR_UNKNOWN, //!< Unknown system error occurred + SDIO_API_STATUS_HWINIT_FAIL, //!< Hardware failed to initialize + SDIO_API_STATUS_BOOT_READY, //!< boot loader ready + SDIO_API_STATUS_HOST_BOOT_READY, + + /* Add new entries above this */ + SDIO_API_STATUS_INVALID_STATUS_VALUE // Anything equal or above this is invalid status. +} SDIO_API_STATUS; + +#define WLAN_UPLD_SIZE 2312 + +/** \def DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_INTERFACE_STANDARD) +* Define an Interface Guid to access the proprietary Marvell SDIO bus driver interface. +* This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE +* handler. +*/ + +DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_INTERFACE_STANDARD); +// {B92D63EC-F143-4711-9853-DE24D1B85843} + +/** \def DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_BUS_TYPE) +* Define a Guid for SDIO bus type. This is returned in response to +* IRP_MN_QUERY_BUS_INTERFACE on PDO. +*/ +DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_BUS_TYPE); +// {43159826-A758-4aa2-9F98-AB229C031ED1} + +/** \def DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD) +* Define an Interface Guid to access the proprietary Marvell SDIO bus driver interface. +* This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE +* handler. +*/ +// {1D5837EE-F656-46b4-A8DA-5484A25AB13A} +DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD); + +/** \def DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_BUS_2_TYPE) +* Define a Guid for SDIO bus type. This is returned in response to +* IRP_MN_QUERY_BUS_INTERFACE on PDO. +*/ +// {8C3E2C85-D056-4689-B678-83A2E6FADCF9} +DEFINE_EXTERN_GUID(GUID_MRVL_SDIOBUS_BUS_2_TYPE); + +// Definitions for IOCTL handling + +#ifdef WINNT + +#define FILE_DEVICE_SDIOBUSENUM FILE_DEVICE_BUS_EXTENDER +#define SDIOBUSENUM_IOCTL(_index_) \ + CTL_CODE (FILE_DEVICE_SDIOBUSENUM, _index_, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#else // #ifdef WINNT + +#define FILE_DEVICE_SDIOBUSENUM 0x2A // same as for Windows +#define SDIOBUSENUM_IOCTL(_index_) \ + _IOWR(FILE_DEVICE_SDIOBUSENUM, _index_, unsigned int ) + +#endif + +#define IOCTL_SDIOBUSENUM_PLUGIN_HARDWARE SDIOBUSENUM_IOCTL (0x0) +#define IOCTL_SDIOBUSENUM_UNPLUG_HARDWARE SDIOBUSENUM_IOCTL (0x1) +#define IOCTL_SDIOBUSENUM_EJECT_HARDWARE SDIOBUSENUM_IOCTL (0x2) +#define IOCTL_SDIOBUS_DONT_DISPLAY_IN_UI_DEVICE SDIOBUSENUM_IOCTL (0x3) +// IOCTL for FPGA Configuration GUI +#define IOCTL_SDIOBUSENUM_SET_VOLTAGE SDIOBUSENUM_IOCTL (0x4) +#define IOCTL_SDIOBUSENUM_SET_BUSTYPE SDIOBUSENUM_IOCTL (0x5) +#define IOCTL_SDIOBUSENUM_SET_BUSWIDTH SDIOBUSENUM_IOCTL (0x6) +#define IOCTL_SDIOBUSENUM_SET_CLKSPEED SDIOBUSENUM_IOCTL (0x7) +#define IOCTL_SDIOBUSENUM_GET_BOARDREV SDIOBUSENUM_IOCTL (0x8) +#define IOCTL_SDIOBUSENUM_GET_JUMPER SDIOBUSENUM_IOCTL (0x9) + +// +// Define Interface reference/dereference routines for +// Interfaces exported by IRP_MN_QUERY_INTERFACE +// + +typedef VOID(*PINTERFACE_REFERENCE) (PVOID Context); +typedef VOID(*PINTERFACE_DEREFERENCE) (PVOID Context); + +typedef + BOOLEAN + (*PSDIO_CMD52_READ) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, OUT UCHAR * pReturnData); +typedef + BOOLEAN + (*PSDIO_CMD52_WRITE) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, IN UCHAR Data); + +typedef + BOOLEAN + (*PSDIO_CMD53_READ) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, + IN UCHAR mode, + IN UCHAR opcode, OUT UCHAR * pData, IN ULONG Count); +typedef + BOOLEAN + (*PSDIO_CMD53_WRITE) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, + IN UCHAR mode, + IN UCHAR opcode, OUT UCHAR * pData, IN ULONG Count); + +typedef + BOOLEAN + (*PSDIO_CMD53_READ_EX) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, + IN UCHAR mode, + IN UCHAR opcode, + OUT UCHAR * pData, + IN ULONG Count, IN ULONG blksz); +typedef + BOOLEAN + (*PSDIO_CMD53_WRITE_EX) (IN PVOID Context, + IN ULONG Offset, + IN UCHAR function_number, + IN UCHAR mode, + IN UCHAR opcode, + OUT UCHAR * pData, + IN ULONG Count, IN ULONG blksz); + + /*--- mmoser 3/20/2006 ---*/ +/* + * reverse args order for compatibility of Marvell Linux drive + */ + +typedef + VOID + (*PSDIO_ISR_HANDLER) (IN ULONG irq_status, + IN PVOID Context, IN PVOID regs); + +typedef + VOID + (*PSDIO_REGISTER_ISR_HANDLER) (IN PVOID Context, + IN PVOID isrContext, + IN PSDIO_ISR_HANDLER pIsrHandler); + +typedef VOID(*PSDIO_ENABLE_IRQ) (IN PVOID Context); +typedef VOID(*PSDIO_DISABLE_IRQ) (IN PVOID Context); + +typedef BOOLEAN(*PSDIO_IS_CARD_PRESENT) (IN PVOID Context); + +typedef BOOLEAN(*PSDIO_CREATE_CARD_THREAD) (IN PVOID Context); +typedef BOOLEAN(*PSDIO_DESTROY_CARD_THREAD) (IN PVOID Context); + +typedef BOOLEAN(*PSDIO_SDIO_LOCKINTERFACE) (IN PVOID Context); +typedef VOID(*PSDIO_SDIO_UNLOCKINTERFACE) (IN PVOID Context); + +typedef VOID(*PSDIO_SET_LED) (IN PVOID Context, IN UCHAR val, IN UCHAR on); +typedef VOID(*PSDIO_PS_STATE) (IN PVOID Context, IN UCHAR State); + +typedef VOID(*PSDIO_SET_CLOCK_SPEED) (IN PVOID Context, IN ULONG bus_freq); + +typedef VOID(*PSDIO_SET_CLOCK) (IN PVOID Context, IN UCHAR on); + +typedef VOID(*PSDIO_SET_GPO) (IN PVOID Context, IN UCHAR on); + +typedef VOID(*PSDIO_SET_BUSWIDTH) (IN PVOID Context, IN UCHAR width); + +/** \struct MRVL_SDIO_INTERFACE_STANDARD +* \brief The Marvell SDIO Standard Interface to the bus driver +*/ +typedef struct _MRVL_SDIO_INTERFACE_STANDARD +{ + USHORT Size; /**< Size of this interface structure */ + USHORT Version; /**< Version of the interface */ + PINTERFACE_REFERENCE InterfaceReference; /**< Increments the interface reference counter */ + PINTERFACE_DEREFERENCE InterfaceDereference; /**< Decrements the interface reference counter */ + PVOID Context; /**< Pointer to a caller supplied structure */ + PSDIO_CMD52_READ SDIO_Cmd52_Read; /**< Pointer to CMD 52 Read function */ + PSDIO_CMD52_WRITE SDIO_Cmd52_Write; /**< Pointer to CMD 52 Write function */ + PSDIO_CMD53_READ SDIO_Cmd53_Read; /**< Pointer to CMD 53 Read function */ + PSDIO_CMD53_WRITE SDIO_Cmd53_Write; /**< Pointer to CMD 53 Write function */ + PSDIO_CMD53_READ_EX SDIO_Cmd53_Read_Ex; /**< Pointer to CMD 53 extended Read function */ + PSDIO_CMD53_WRITE_EX SDIO_Cmd53_Write_Ex; /**< Pointer to CMD 53 extended Write function */ + PSDIO_REGISTER_ISR_HANDLER SDIO_RegisterIsrHandler; /**< Pointer to register interrupt handler function */ + PSDIO_ENABLE_IRQ SDIO_EnableInterrupt; /**< Pointer to enable FPGA interrupt function */ + PSDIO_DISABLE_IRQ SDIO_DisableInterrupt; /**< Pointer to disable FPGA interrupt function */ + PSDIO_IS_CARD_PRESENT SDIO_isCardPresent; /**< Pointer to check card present function */ + PSDIO_SDIO_LOCKINTERFACE SDIO_lockInterface; /**< Pointer to lock SDIO physical interface function */ + PSDIO_SDIO_UNLOCKINTERFACE SDIO_unlockInterface; /**< Pointer to unlock SDIO physical interface function */ + PSDIO_SET_LED SDIO_SetLed; /**< Pointer to turn FPGA LED on/off function */ + // pweber 17.08.2005 + PSDIO_PS_STATE SDIO_PsState; /**< Pointer to set the power save state function */ + + /*--- mmoser 12/18/2006 ---*/ + PSDIO_SET_CLOCK SDIO_SetClock; /**< Pointer to set clock on/off function */ + PSDIO_SET_BUSWIDTH SDIO_SetBusWidth; /**< Pointer to set bus width function */ + /*--- mmoser 1/2/2007 ---*/ + PSDIO_SET_CLOCK_SPEED SDIO_SetClockSpeed; /**< Pointer to set clock speed */ + + /*--- mmoser 2/20/2007 ---*/ + PSDIO_SET_GPO SDIO_SetGPO; /**< Pointer to set general purpose output function */ +} MRVL_SDIO_INTERFACE_STANDARD, *PMRVL_SDIO_INTERFACE_STANDARD; + +// SDIO Interface macros + +#define SDIO_CMD52_READ(pSdio,offset,fn_nr, pBuf) \ + (*(pSdio)->sdio_if.SDIO_Cmd52_Read)((pSdio)->sdio_if.Context,(offset),(fn_nr), (pBuf)) + +#define SDIO_CMD52_WRITE(pSdio,offset,fn_nr, data) \ + (*(pSdio)->sdio_if.SDIO_Cmd52_Write)((pSdio)->sdio_if.Context,(offset),(fn_nr), (data)) + +#define SDIO_CMD53_READ(pSdio,offset,fn_nr,mode,opcode,pBuf,length) \ + (*(pSdio)->sdio_if.SDIO_Cmd53_Read)((pSdio)->sdio_if.Context,(offset),(fn_nr),(mode),(opcode),(pBuf),(length)) + +#define SDIO_CMD53_WRITE(pSdio,offset,fn_nr,mode,opcode,pBuf,length) \ + (*(pSdio)->sdio_if.SDIO_Cmd53_Write)((pSdio)->sdio_if.Context,(offset),(fn_nr),(mode),(opcode),(pBuf),(length)) + +#define SDIO_CMD53_READ_EX(pSdio,offset,fn_nr,mode,opcode,pBuf,length,blksz) \ + (*(pSdio)->sdio_if.SDIO_Cmd53_Read_Ex)((pSdio)->sdio_if.Context,(offset),(fn_nr),(mode),(opcode),(pBuf),(length),(blksz)) + +#define SDIO_CMD53_WRITE_EX(pSdio,offset,fn_nr,mode,opcode,pBuf,length,blksz) \ + (*(pSdio)->sdio_if.SDIO_Cmd53_Write_Ex)((pSdio)->sdio_if.Context,(offset),(fn_nr),(mode),(opcode),(pBuf),(length),(blksz)) + +#define SDIO_IS_CARD_PRESENT(pSdio) \ + (*(pSdio)->sdio_if.SDIO_isCardPresent)((pSdio)->sdio_if.Context) + +#define SDIO_SDIO_LOCKINTERFACE(pSdio) \ + (*(pSdio)->sdio_if.SDIO_lockInterface)((pSdio)->sdio_if.Context) + +#define SDIO_SDIO_UNLOCKINTERFACE(pSdio) \ + (*(pSdio)->sdio_if.SDIO_unlockInterface)((pSdio)->sdio_if.Context) + +#define SDIO_SET_LED(pSdio, led, on ) \ + (*(pSdio)->sdio_if.SDIO_SetLed)((pSdio)->sdio_if.Context,(led),(on)) + +// pweber 17.08.2005 +#define SDIO_PS_STATE(pSdio, State ) \ + (*(pSdio)->sdio_if.SDIO_PsState)((pSdio)->sdio_if.Context,(State) ) + +#define SDIO_ENABLE_IRQ(pSdio ) \ + (*(pSdio)->sdio_if.SDIO_EnableInterrupt)((pSdio)->sdio_if.Context ) + +#define SDIO_DISABLE_IRQ(pSdio ) \ + (*(pSdio)->sdio_if.SDIO_DisableInterrupt)((pSdio)->sdio_if.Context ) + +#define SDIO_REGISTER_ISR_HANDLER(pSdio, isrContext, pIsrHandler ) \ + (*(pSdio)->sdio_if.SDIO_RegisterIsrHandler)((pSdio)->sdio_if.Context,(isrContext),(pIsrHandler)) + +#define SDIO_SET_CLOCK(pSdio, on ) \ + (*(pSdio)->sdio_if.SDIO_SetClock)((pSdio)->sdio_if.Context,(on)) + +#define SDIO_SET_CLOCK_SPEED(pSdio, bus_freq ) \ + (*(pSdio)->sdio_if.SDIO_SetClockSpeed)((pSdio)->sdio_if.Context,(bus_freq)) + +#define SDIO_SET_BUSWIDTH(pSdio, width ) \ + (*(pSdio)->sdio_if.SDIO_SetBusWidth)((pSdio)->sdio_if.Context,(width)) + +#define SDIO_SET_GPO(pSdio, on ) \ + (*(pSdio)->sdio_if.SDIO_SetGPO)((pSdio)->sdio_if.Context,(on)) + +#define MAX_WLAN_TX_SIZE 3000 +#define MAX_WLAN_RX_SIZE 3000 +#define MAX_WLAN_RSP_SIZE 256 +#define MAX_FUNCTIONS 2 + +#ifndef WINNT + /*--- mmoser 3/20/2006 ---*/ + +#define sdio_write_ioreg(card, fn, reg, val) (sdio_Write_Byte(((mmc_card_t)(card))->ctrlr,(reg), (fn), (val)) ? 0 : -1 ) +#define sdio_read_ioreg( card, fn, reg, val) (sdio_Read_Byte(((mmc_card_t)(card))->ctrlr,(reg), (fn), (val)) ? 0 : -1 ) +#define sdio_write_iomem(card,fn,reg,blockmode,opcode,cnt,blksz,dat) \ + (sdio_Write_BlockEx(((mmc_card_t)(card))->ctrlr,reg,fn,blockmode,opcode,dat,cnt,blksz)? 0 : -1) +#define sdio_read_iomem(card,fn,reg,blockmode,opcode,cnt,blksz,dat) \ + (sdio_Read_BlockEx(((mmc_card_t)(card))->ctrlr,reg,fn,blockmode,opcode,dat,cnt,blksz)? 0 : -1) + +#define sdio_request_irq(card, handler, flags,devname,dev_id) sdio_Register_ISR_Handler(((mmc_card_t)(card))->ctrlr,dev_id,(PSDIO_ISR_HANDLER)handler) +// #define sdio_free_irq(card, dev_id) sdio_Register_ISR_Handler(((mmc_card_t)(card))->ctrlr,dev_id,NULL) +#define sdio_enable_SDIO_INT() sdio_EnableInterrupt(((mmc_card_t)((wlan_private *)priv)->wlan_dev.card)->ctrlr) + +void sdio_card_added(void *); +void sdio_card_removed(void); + +typedef struct _card_capability +{ + u8 num_of_io_funcs; /* Number of i/o functions */ + u8 memory_yes; /* Memory present ? */ + u16 rca; /* Relative Card Address */ + u32 ocr; /* Operation Condition register */ + u16 fnblksz[8]; + u32 cisptr[8]; +} card_capability; + +typedef struct _dummy_tmpl +{ + int irq_line; +} dummy_tmpl; + +typedef struct _mmc_card_rec +{ + u8 chiprev; + u8 block_size_512; + u8 async_int_mode; + struct device *dev; + card_capability info; + struct _SDIO_OBJECT *ctrlr; +} mmc_card_rec; + +typedef struct _mmc_card_rec *mmc_card_t; + +typedef int (*mmc_notifier_fn_t) (mmc_card_t); + +typedef struct _mmc_notifier_rec mmc_notifier_rec_t; +typedef struct _mmc_notifier_rec *mmc_notifier_t; + +typedef struct _SDIO_OBJECT *mmc_controller_t; + +struct _mmc_notifier_rec +{ + mmc_notifier_fn_t add; + mmc_notifier_fn_t remove; +}; +#endif // WINNT + +/** \struct SDIO_OBJECT +* \brief Structure of the SDIO object +*/ +typedef struct _SDIO_OBJECT +{ + MRVL_SDIO_INTERFACE_STANDARD sdio_if; //!< Standard interface to bus driver + + ULONG ioport; //!< Wireless SDIO port address + ULONG cisptr[MAX_FUNCTIONS]; //!< Pointer to CIS + UCHAR pUpl_Buf[WLAN_UPLD_SIZE]; //!< Buffer for data from card (upload) + UCHAR pDnl_Buf[WLAN_UPLD_SIZE]; //!< Buffer for data to card (download) +#ifdef WINNT + KTIMER SleepTimer; //!< \if .WINDOWS. Timer used in the _SLEEP_MS() macro \endif +#endif + /*--- mmoser 3/3/2006 ---*/ +#ifndef WINNT + spinlock_t IFSpinLock; //!< \if .LINUX. Interface spin lock \endif + spinlock_t fwSpinLock; //!< \if .LINUX. Firmware spin lock \endif + + /*--- mmoser 3/20/2006 ---*/ + struct _dummy_tmpl *tmpl; + mmc_card_t card; +#endif +} SDIO_OBJECT, *PSDIO_OBJECT; + +#ifndef WINNT + +// bhaake +// #define EXTERN_C + +#define SDIO_API_IMPORT +#define PDEVICE_OBJECT PVOID + +#endif + +EXTERN_C SDIO_API_IMPORT SDIO_API_STATUS sdio_CreateIface(PSDIO_OBJECT * + ppSdio_if, + PDEVICE_OBJECT + pSdioPDO, + PVOID irq_context, + PSDIO_ISR_HANDLER + irq_handler); +EXTERN_C SDIO_API_IMPORT SDIO_API_STATUS sdio_DestroyIface(PSDIO_OBJECT * + ppSdio_if); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Read_Byte(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR * pData); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Write_Byte(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR Data); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Read_Block(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR mode, UCHAR opcode, + UCHAR * pData, ULONG Count); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Write_Block(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR mode, UCHAR opcode, + UCHAR * pData, ULONG Count); + + /*--- mmoser 3/20/2006 ---*/ +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Read_BlockEx(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR mode, UCHAR opcode, + UCHAR * pData, ULONG Count, + ULONG blksz); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_Write_BlockEx(PSDIO_OBJECT pSdio, + ULONG Offset, + UCHAR function_number, + UCHAR mode, UCHAR opcode, + UCHAR * pData, + ULONG Count, ULONG blksz); + +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_isCardPresent(PSDIO_OBJECT pSdio_if); +EXTERN_C SDIO_API_IMPORT BOOLEAN sdio_lockInterface(PSDIO_OBJECT pSdio); +EXTERN_C SDIO_API_IMPORT VOID sdio_unlockInterface(PSDIO_OBJECT pSdio); +EXTERN_C SDIO_API_IMPORT VOID sdio_SetLed(PSDIO_OBJECT pSdio, UCHAR led, + UCHAR on); +EXTERN_C SDIO_API_IMPORT VOID sdio_PsState(PSDIO_OBJECT pSdio, UCHAR State); // pweber 17.08.2005 +EXTERN_C SDIO_API_IMPORT VOID sdio_EnableInterrupt(PSDIO_OBJECT pSdio); +EXTERN_C SDIO_API_IMPORT VOID sdio_DisableInterrupt(PSDIO_OBJECT pSdio); +EXTERN_C SDIO_API_IMPORT ULONG sdio_Register_ISR_Handler(PSDIO_OBJECT pSdio, + PVOID isrContext, + PSDIO_ISR_HANDLER + pIsrHandler); +EXTERN_C SDIO_API_IMPORT VOID sdio_SetClock(PSDIO_OBJECT pSdio, UCHAR on); +EXTERN_C SDIO_API_IMPORT VOID sdio_SetGPO(PSDIO_OBJECT pSdio, UCHAR on); +EXTERN_C SDIO_API_IMPORT VOID sdio_SetClockSpeed(PSDIO_OBJECT pSdio, + ULONG bus_freq); +EXTERN_C SDIO_API_IMPORT VOID sdio_SetBusWidth(PSDIO_OBJECT pSdio, + UCHAR width); + +EXTERN_C SDIO_API_IMPORT BOOLEAN card_Helper_Download(PSDIO_OBJECT pSdio, + UCHAR * helperImage, + ULONG helpersize); +EXTERN_C SDIO_API_IMPORT SDIO_API_STATUS card_Firmware_Download(PSDIO_OBJECT + pSdio, + UCHAR * + pFW_Image, + ULONG fmsize, + UCHAR * + pFW_helperImage, + ULONG + helperfmsize); +EXTERN_C SDIO_API_IMPORT BOOLEAN card_isCardReady(PSDIO_OBJECT pSdio); +EXTERN_C SDIO_API_IMPORT BOOLEAN card_disable_card_int(PSDIO_OBJECT pSdio, + UCHAR function_number, + UCHAR mask); +EXTERN_C SDIO_API_IMPORT BOOLEAN card_enable_card_int(PSDIO_OBJECT pSdio, + UCHAR function_number, + UCHAR mask); + +EXTERN_C SDIO_API_IMPORT SDIO_API_STATUS fw_CardToHost(PSDIO_OBJECT pSdio, + ULONG * type, + ULONG * length, + UCHAR * payload, + ULONG npayload); +EXTERN_C SDIO_API_IMPORT SDIO_API_STATUS fw_HostToCard(PSDIO_OBJECT pSdio, + UCHAR type, + UCHAR * payload, + ULONG npayload); + + /*--- mmoser 3/20/2006 ---*/ +#ifndef WINNT +EXTERN_C SDIO_API_IMPORT VOID *sdio_register(int type, void *ops, int memory); +EXTERN_C SDIO_API_IMPORT int sdio_unregister(int type, void *ops); +EXTERN_C SDIO_API_IMPORT int sdio_get_vendor_id(mmc_card_t card); +EXTERN_C SDIO_API_IMPORT int start_bus_clock(mmc_controller_t ctrlr); +EXTERN_C SDIO_API_IMPORT int sdio_free_irq(mmc_card_t card, void *dev_id); + +EXTERN_C SDIO_API_IMPORT void sdio_clear_imask(mmc_controller_t); +EXTERN_C SDIO_API_IMPORT int sdio_check_idle_state(mmc_controller_t); +EXTERN_C SDIO_API_IMPORT void sdio_print_imask(mmc_controller_t); +EXTERN_C SDIO_API_IMPORT void sdio_clear_imask(mmc_controller_t); + +EXTERN_C SDIO_API_IMPORT void sdio_unmask(void); +#endif + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/Makefile 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/Makefile --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/Makefile 2007-11-06 12:26:39.000000000 -0500 @@ -0,0 +1,32 @@ +# Things that need to export symbols +export-objs := sdio_if.o + +# Objects to compile in this module +# +SDIOAPIOBJS := sdio_if.o apimain.o + +#CFLAGS += -DSD8385 +CFLAGS += -DSDIO_API_INTERNAL +CFLAGS += -DDBG +# CFLAGS += -DSDIO_BUS_DRIVER +CFLAGS += -I$(PWD) +# +# Make target rules +# +all: sdioapi.o +ifeq ($(KVER),2.6) + @echo "Finished Making Marvell SDIO API Linux Driver for Kernel 2.6" +else + @echo "Finished Making Marvell SDIO API Linux Driver for Kernel 2.4" +endif + +sdioapi.o: $(SDIOAPIOBJS) + $(LD) -r $^ -o $@ + +clean: + find . -name "*.o" -exec rm {} \; + find . -name "*.*~" -exec rm {} \; + find . -name "*.d" -exec rm {} \; + find . -name "*.mod.c" -exec rm {} \; + find . -name "*.ko" -exec rm {} \; + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/sdio_if.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/sdio_if.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/sdio_if.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/sdio_if.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,1782 @@ +/****************************************************************************** + * + * Name: sdio_if.c + * Project: Wireless LAN, Interface to SDIO bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:30:19 $ + * Purpose: SDIO interface to bus driver definitions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sdio_if.c,v $ + * Revision 1.1 2007/01/18 09:30:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ +#define SDIO_BUS_DRIVER + +#include "h/sdioapi.h" + +// #define DEBUG_VERBOSE + +#ifdef DEBUG_VERBOSE +ULONG j, k; +UCHAR __buffer[1024]; +#endif + +// Initialize the interface GUIDS +// +// Define an Interface Guid to access the proprietary Marvell SDIO bus driver interface. +// This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE +// handler. +// +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_INTERFACE_STANDARD, + 0xB92D63EC, 0xF143, 0x4711, 0x98, 0x53, 0xDE, 0x24, 0xD1, + 0xB8, 0x58, 0x43); +// {B92D63EC-F143-4711-9853-DE24D1B85843} + +// +// Define a Guid for SDIO bus type. This is returned in response to +// IRP_MN_QUERY_BUS_INTERFACE on PDO. +// +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_BUS_TYPE, + 0x43159826, 0xA758, 0x4aa2, 0x9F, 0x98, 0xAB, 0x22, 0x9C, + 0x03, 0x1E, 0xD1); +// {43159826-A758-4aa2-9F98-AB229C031ED1} + +// +// Define an Interface Guid to access the proprietary Marvell SDIO bus driver interface. +// This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE +// handler. +// +// {1D5837EE-F656-46b4-A8DA-5484A25AB13A} +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD, + 0x1d5837ee, 0xf656, 0x46b4, 0xa8, 0xda, 0x54, 0x84, 0xa2, + 0x5a, 0xb1, 0x3a); + +// +// Define a Guid for SDIO bus type. This is returned in response to +// IRP_MN_QUERY_BUS_INTERFACE on PDO. +// +// {8C3E2C85-D056-4689-B678-83A2E6FADCF9} +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_BUS_2_TYPE, + 0x8c3e2c85, 0xd056, 0x4689, 0xb6, 0x78, 0x83, 0xa2, 0xe6, + 0xfa, 0xdc, 0xf9); + +#ifndef WINNT +MODULE_DESCRIPTION("SDIO Bus Interface Driver Module"); +MODULE_AUTHOR("Michael Moser (mmoser@syskonnect.de)"); +MODULE_LICENSE("Dual BSD/GPL"); +#endif + +#define FWDELAY 2000 // cycles should give us about 10 seconds +#define FWBLOCK_DELAY 5000 // cycles for fw block delay. + +// #define DEBUG_VERBOSE 1 + +#ifndef WINNT +int ps_sleep_confirmed = 0; + +mmc_notifier_t pNotifier; + +PSDIO_OBJECT global_pSdio = NULL; +#endif + + /*--- mmoser 3/31/2006 ---*/ +static int card_is_removed = 1; +static int card_is_inserted = 0; + +// private functions +ULONG card_GetCIS_Pointer(PSDIO_OBJECT pSdio, UCHAR function); +BOOLEAN card_ReadIO_Port(PSDIO_OBJECT pSdio); +UCHAR card_poll_card_status(PSDIO_OBJECT pSdio, UCHAR bits); +BOOLEAN card_read_scratch(PSDIO_OBJECT pSdio, ULONG * dat); +SDIO_API_STATUS sdio_GetStandardInterface(PVOID DevObject, + PMRVL_SDIO_INTERFACE_STANDARD + BusInterface); + +/** + * @brief Initialize the SDIO interface. + * + * @param ppSdio_if Address of a pointer which returns the SDIO interface + * @param pSdioPDO Pointer to the physical device object (only for Windows) + * @param irq_context Pointer to a data structure which is passed to the interrupt handler + * @param irq_handler Pointer to the interrupt handler function + * + * @return SDIO_API_STATUS_FAILURE or SDIO_API_STATUS_SUCCESS + */ +SDIO_API_STATUS +sdio_CreateIface(PSDIO_OBJECT * ppSdio_if, + PDEVICE_OBJECT pSdioPDO, + PVOID irq_context, PSDIO_ISR_HANDLER irq_handler) +{ + PSDIO_OBJECT pSdio; + SDIO_API_STATUS Status; + + DBGPRINT(DBG_HWIF, (KERN_DEBUG "sdio_CreateIface\n")); + +#ifdef WINNT + pSdio = + (PSDIO_OBJECT) ExAllocatePoolWithTag(NonPagedPool, + sizeof(SDIO_OBJECT), 'DSRM'); +#else + + pSdio = (PSDIO_OBJECT) kmalloc(sizeof(SDIO_OBJECT), GFP_KERNEL); +#endif + + if (pSdio == NULL) { + return SDIO_API_STATUS_FAILURE; + } + +#ifdef WINNT + RtlZeroMemory(pSdio, sizeof(SDIO_OBJECT)); +#else + memset(pSdio, '\0', sizeof(SDIO_OBJECT)); + + /*--- mmoser 3/20/2006 ---*/ + pSdio->card = (mmc_card_t) kmalloc(sizeof(mmc_card_rec), GFP_KERNEL); + if (pSdio->card == NULL) { + kfree(pSdio); + return SDIO_API_STATUS_FAILURE; + } + memset(pSdio->card, '\0', sizeof(mmc_card_t)); + pSdio->card->ctrlr = pSdio; + + if (!(pSdio->tmpl = kmalloc(sizeof(dummy_tmpl), GFP_ATOMIC))) { + kfree(pSdio->card); + kfree(pSdio); + return SDIO_API_STATUS_FAILURE; + } +#endif + + // Query the standard interface + Status = + sdio_GetStandardInterface(pSdioPDO, + (PMRVL_SDIO_INTERFACE_STANDARD) pSdio); + if (Status != SDIO_API_STATUS_SUCCESS) { + *ppSdio_if = NULL; +#ifdef WINNT + ExFreePool(pSdio); +#else + + /*--- mmoser 3/20/2006 ---*/ + kfree(pSdio->tmpl); + kfree(pSdio->card); + kfree(pSdio); +#endif + return SDIO_API_STATUS_FAILURE; + } + +#ifdef WINNT + KeInitializeTimer(&pSdio->SleepTimer); +#endif + + /*--- mmoser 3/3/2006 ---*/ +#ifndef WINNT + spin_lock_init(&pSdio->IFSpinLock); + spin_lock_init(&pSdio->fwSpinLock); +#endif + + *ppSdio_if = pSdio; + + /*--- mmoser 4/4/2006 ---*/ +#ifdef WINNT + card_ReadIO_Port(pSdio); + + pSdio->cisptr[0] = card_GetCIS_Pointer(pSdio, 0); + pSdio->cisptr[1] = card_GetCIS_Pointer(pSdio, 1); +#endif + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "sdio_CreateIface: ioport=0x%8.08X cisptr[0]=0x%8.08X cisptr[1]=0x%8.08X\n", + pSdio->ioport, pSdio->cisptr[0], pSdio->cisptr[1])); + + (*pSdio->sdio_if.SDIO_RegisterIsrHandler) (pSdio->sdio_if.Context, + irq_context, irq_handler); + return SDIO_API_STATUS_SUCCESS; +} + +/** + * @brief Deferences the SDIO interface. + * + * @param ppSdio_if Address of a pointer which returns the SDIO interface + * + * @return SDIO_API_STATUS_FAILURE or SDIO_API_STATUS_SUCCESS + */ +SDIO_API_STATUS +sdio_DestroyIface(PSDIO_OBJECT * ppSdio_if) +{ + PSDIO_OBJECT pSdio; + + DBGPRINT(DBG_HWIF, (KERN_DEBUG "sdio_DestroyIface\n")); + + if (!*ppSdio_if) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "Attempt to free interface with NULL POINTER\n")); + return SDIO_API_STATUS_FAILURE; + } + pSdio = *ppSdio_if; + + pSdio->sdio_if.InterfaceDereference((PVOID) pSdio->sdio_if.Context); + +#ifdef WINNT + KeCancelTimer(&pSdio->SleepTimer); +#endif + +#ifdef WINNT + ExFreePool(*ppSdio_if); +#else + kfree(*ppSdio_if); +#endif + + *ppSdio_if = NULL; + return SDIO_API_STATUS_SUCCESS; +} + +/** + * @brief Read one byte from the SDIO device (CMD52) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param pReturnData return data byte + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Read_Byte(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR * pReturnData // return data byte + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD52_READ(pSdio, Offset, function_number, pReturnData); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Write one byte to the SDIO device (CMD52) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param Data data byte + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Write_Byte(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR Data // data byte + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD52_WRITE(pSdio, Offset, function_number, Data); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Read 'Count' bytes from the SDIO device (CMD53) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param mode byte/block mode + * @param opcode fixed/incrementing address + * @param pData return data buffer + * @param Count size of data buffer + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Read_Block(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR mode, // byte/block mode + UCHAR opcode, // fixed/incrementing address + UCHAR * pData, // return data buffer + ULONG Count // size of data buffer + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD53_READ(pSdio, Offset, function_number, mode, opcode, pData, + Count); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Write 'Count' bytes to the SDIO device (CMD53) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param mode byte/block mode + * @param opcode fixed/incrementing address + * @param pData return data buffer + * @param Count size of data buffer + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Write_Block(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR mode, // byte/block mode + UCHAR opcode, // fixed/incrementing address + UCHAR * pData, // data buffer + ULONG Count // size of data buffer + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD53_WRITE(pSdio, Offset, function_number, mode, opcode, pData, + Count); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Read 'Count' bytes with block size 'blksz' from the SDIO device (CMD53) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param mode byte/block mode + * @param opcode fixed/incrementing address + * @param pData return data buffer + * @param Count size of data buffer + * @param blksz block size + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Read_BlockEx(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR mode, // byte/block mode + UCHAR opcode, // fixed/incrementing address + UCHAR * pData, // return data buffer + ULONG Count, // size of data buffer + ULONG blksz // block size + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD53_READ_EX(pSdio, Offset, function_number, mode, opcode, + pData, Count, blksz); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Write 'Count' bytes with block size 'blksz' to the SDIO device (CMD53) + * + * @param pSdio pointer to our interface object. + * @param Offset Address within the SDIO card + * @param function_number function number + * @param mode byte/block mode + * @param opcode fixed/incrementing address + * @param pData return data buffer + * @param Count size of data buffer + * @param blksz block size + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_Write_BlockEx(PSDIO_OBJECT pSdio, // pointer to our interface object. + ULONG Offset, // Address within the SDIO card + UCHAR function_number, // function number + UCHAR mode, // byte/block mode + UCHAR opcode, // fixed/incrementing address + UCHAR * pData, // data buffer + ULONG Count, // size of data buffer + ULONG blksz // block size + ) +{ + BOOLEAN rc; + LOCK_IF(); + rc = SDIO_CMD53_WRITE_EX(pSdio, Offset, function_number, mode, opcode, + pData, Count, blksz); + UNLOCK_IF(); + return rc; +} + +/** + * @brief Fetch one firmware message from the SDIO device + * + * @param pSdio pointer to our interface object. + * @param type type of firmware message + * @param nb received message size + * @param payload returns the message to the caller + * @param npayload max. allowed payload size + * + * @return SDIO_API_STATUS_FAILURE or SDIO_API_STATUS_SUCCESS + */ +SDIO_API_STATUS +fw_CardToHost(PSDIO_OBJECT pSdio, ULONG * type, ULONG * nb, UCHAR * payload, + ULONG npayload) +{ + BOOLEAN status = FALSE; + ULONG buf_len = 0; + ULONG blks; + LOCK_FW(); + + if (!sdio_isCardPresent(pSdio)) { + DBGPRINT(DBG_HWIF, (KERN_DEBUG "fw_CardToHost: No Card Present!\n")); + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } + + if (payload == NULL || nb == NULL || type == NULL) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "fw_CardToHost: Invalid parameters payload=0x%8.08X length=%d \n", + (ULONG) payload, *nb)); + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } + + /* Read the length of data to be transferred */ + status = card_read_scratch(pSdio, &buf_len); + if (!status) { + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } +#ifdef DEBUG_VERBOSE + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "fw_CardToHost: Receiving %d bytes from card at scratch reg value.\n", + buf_len)); +#endif + if (buf_len > WLAN_UPLD_SIZE || buf_len == 0) { + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } +#ifdef WINNT + RtlZeroMemory(pSdio->pUpl_Buf, buf_len * sizeof(UCHAR)); +#else + memset(pSdio->pUpl_Buf, '\0', buf_len * sizeof(UCHAR)); +#endif + + blks = (buf_len + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE; + status = sdio_Read_Block(pSdio, pSdio->ioport, 1, + BLOCK_MODE, FIXED_ADDRESS, + pSdio->pUpl_Buf, blks); + + if (status == TRUE) { +#ifdef DEBUG_VERBOSE + DBGPRINT(DBG_HWIF, (KERN_DEBUG "CardToHost : len=%d\n", buf_len)); +#ifdef WINNT + PrintMacro("CardToHost : len=%d\n", buf_len); + for (j = 0; j < buf_len && j < 64; j++) { + DbgPrint("%2.02X ", pSdio->pUpl_Buf[j]); + if ((j + 1) % SD_BLOCK_SIZE == 0) { + DbgPrint("\n"); + } + } + DbgPrint("\n"); +#else // #ifdef WINNT + k = 0; + for (j = 0; j < buf_len && j < 64; j++) { + sprintf(&__buffer[k], "%2.02X ", pSdio->pUpl_Buf[j]); + k += 3; + if ((j + 1) % 32 == 0) { + __buffer[k++] = '\n'; + __buffer[k++] = 0; + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s\n", __buffer)); + k = 0; + } + } + __buffer[k++] = '\n'; + __buffer[k++] = 0; + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s\n", __buffer)); +#endif +#endif + + *nb = *((PUCHAR) pSdio->pUpl_Buf + 0); + *nb |= *((PUCHAR) pSdio->pUpl_Buf + 1) << 8; + + if (*nb < 4 || *nb > npayload) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "*nb=%d (%d) !!!!!!!\n", *nb, buf_len)); + + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } + *nb -= 4; + *type = *((PUCHAR) pSdio->pUpl_Buf + 2); + *type |= *((PUCHAR) pSdio->pUpl_Buf + 3) << 8; + + if (npayload >= buf_len) { +#ifdef WINNT + RtlCopyMemory(payload, ((PUCHAR) pSdio->pUpl_Buf + 4), *nb); +#else + memcpy(payload, ((PUCHAR) pSdio->pUpl_Buf + 4), *nb); +#endif + } else { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "fw_CardToHost FAILURE : npayload < buf_len !!!!!!!\n")); + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; + } + + UNLOCK_FW(); + return SDIO_API_STATUS_SUCCESS; + } + + DBGPRINT(DBG_ERROR, (KERN_DEBUG "fw_CardToHost FAILURE !!!!!!!\n")); + UNLOCK_FW(); + return SDIO_API_STATUS_FAILURE; +} + +/** + * @brief Send one firmware message to the SDIO device + * + * @param pSdio pointer to our interface object. + * @param type type of firmware message + * @param payload message + * @param nb message size + * + * @return SDIO_API_STATUS_FAILURE or SDIO_API_STATUS_SUCCESS + */ +SDIO_API_STATUS +fw_HostToCard(PSDIO_OBJECT pSdio, UCHAR type, UCHAR * payload, ULONG nb) +{ + ULONG blks; + BOOLEAN status; + LOCK_FW(); + + /*--- mmoser 3/4/2006 ---*/ + sdio_DisableInterrupt(pSdio); + if (!sdio_isCardPresent(pSdio)) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "fw_HostToCard: No Card Present!\n")); + UNLOCK_FW(); + /*--- mmoser 3/4/2006 ---*/ + sdio_EnableInterrupt(pSdio); + return SDIO_API_STATUS_FAILURE; + } + + if (payload == NULL || nb == 0 || nb + 4 > WLAN_UPLD_SIZE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "fw_HostToCard: payload (%8.08X) or length (%d) is invalid!\n", + (ULONG) payload, nb)); + UNLOCK_FW(); + /*--- mmoser 3/4/2006 ---*/ + sdio_EnableInterrupt(pSdio); + return SDIO_API_STATUS_FAILURE; + } +#ifdef DEBUG_VERBOSE + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "fw_HostToCard(0x%8.08X): length=%d\n", + pSdio->ioport, nb)); +#endif + + /* The host polls for the DN_LD_CARD_RDY and IO_READY bits */ +// FW doesn't set the DN_LD_CARD_RDY correctly +// status = card_poll_card_status(pSdio, IO_READY|DN_LD_CARD_RDY); + + status = card_poll_card_status(pSdio, IO_READY); + + if (status == 0) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "fw_HostToCard failed\n")); + UNLOCK_FW(); + /*--- mmoser 3/4/2006 ---*/ + sdio_EnableInterrupt(pSdio); + return SDIO_API_STATUS_FAILURE; + } + + pSdio->pDnl_Buf[0] = (UCHAR) ((nb + 4) & 0xff); + pSdio->pDnl_Buf[1] = (UCHAR) (((nb + 4) >> 8) & 0xff); + pSdio->pDnl_Buf[2] = (type == MVSD_DAT) ? 0 : 1; + pSdio->pDnl_Buf[3] = 0; + + blks = ((nb + 4) + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE; + + /* Transfer data to card */ + +#ifdef WINNT + RtlCopyMemory(&pSdio->pDnl_Buf[4], payload, nb); +#else + memcpy(&pSdio->pDnl_Buf[4], payload, nb); +#endif + +#ifdef DEBUG_VERBOSE +#ifdef WINNT + for (j = 0; j < nb + 4 && j < nb + 4 && j < 64; j++) { + DbgPrint("%2.02X ", pSdio->pDnl_Buf[j]); + + if ((j + 1) % 32 == 0) { + DbgPrint("\n"); + } + } + DbgPrint("\n"); +#else // #ifdef WINNT + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "HostToCard : type=0x%2.02X%2.02X len=%d blocks=%d\n", + pSdio->pDnl_Buf[3], pSdio->pDnl_Buf[2], nb, blks)); + k = 0; + for (j = 0; j < nb + 4 && j < 64; j++) { + sprintf(&__buffer[k], "%2.02X ", pSdio->pDnl_Buf[j]); + k += 3; + if ((j + 1) % 32 == 0) { + __buffer[k++] = '\n'; + __buffer[k++] = 0; + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s\n", __buffer)); + k = 0; + } + } + __buffer[k++] = '\n'; + __buffer[k++] = 0; + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s\n", __buffer)); +#endif +#endif + + status = + sdio_Write_Block(pSdio, pSdio->ioport, 1, BLOCK_MODE, FIXED_ADDRESS, + pSdio->pDnl_Buf, blks); + + if (!status) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "fw_HostToCard(): IO error: transferring block\n")); + UNLOCK_FW(); + /*--- mmoser 3/4/2006 ---*/ + sdio_EnableInterrupt(pSdio); + return SDIO_API_STATUS_FAILURE; + } + UNLOCK_FW(); + /*--- mmoser 3/4/2006 ---*/ + sdio_EnableInterrupt(pSdio); + return SDIO_API_STATUS_SUCCESS; +} + +/** + * @brief Check whether a SDIO device is present + * + * @param pSdio pointer to our interface object. + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_isCardPresent(PSDIO_OBJECT pSdio) +{ + return SDIO_IS_CARD_PRESENT(pSdio); +} + +/** + * @brief Check whether the SDIO device is ready + * + * @param pSdio pointer to our interface object. + * + * @return TRUE or FALSE + */ +BOOLEAN +card_isCardReady(PSDIO_OBJECT pSdio) +{ + UCHAR cs; + + if (!sdio_Read_Byte(pSdio, CARD_STATUS_REG, 1, &cs)) { + return FALSE; + } + + return (cs & DN_LD_CARD_RDY) && (cs & IO_READY); +} + +/** + * @brief Lock the SDIO interface + * + * @param pSdio pointer to our interface object. + * + * @return TRUE or FALSE + */ +BOOLEAN +sdio_lockInterface(PSDIO_OBJECT pSdio) +{ + return SDIO_SDIO_LOCKINTERFACE(pSdio); +} + +/** + * @brief Unlock the SDIO interface + * + * @param pSdio pointer to our interface object. + * + */ +VOID +sdio_unlockInterface(PSDIO_OBJECT pSdio) +{ + SDIO_SDIO_UNLOCKINTERFACE(pSdio); +} + +/** + * @brief Turn on/off the LED on the FPGA interface + * + * @param pSdio pointer to our interface object. + * @param led LED number (0..4) + * @param on on/off + * + */ +VOID +sdio_SetLed(PSDIO_OBJECT pSdio, UCHAR led, UCHAR on) +{ + SDIO_SET_LED(pSdio, led, on); +} + +/** + * @brief Turn on/off the SDIO bus speed + * + * @param pSdio pointer to our interface object. + * @param bus_freq bus_freq + * + */ +VOID +sdio_SetClockSpeed(PSDIO_OBJECT pSdio, ULONG bus_freq) +{ + SDIO_SET_CLOCK_SPEED(pSdio, bus_freq); +} + +/** + * @brief Turn on/off the SDIO bus clock + * + * @param pSdio pointer to our interface object. + * @param on on/off + * + */ +VOID +sdio_SetClock(PSDIO_OBJECT pSdio, UCHAR on) +{ + SDIO_SET_CLOCK(pSdio, on); +} + +/** + * @brief Turn on/off the general purpose output clock + * + * @param pSdio pointer to our interface object. + * @param on on/off + * + */ +VOID +sdio_SetGPO(PSDIO_OBJECT pSdio, UCHAR on) +{ + SDIO_SET_GPO(pSdio, on); +} + +/** + * @brief Set the SDIO bus width to 1 or 4 bit + * + * @param pSdio pointer to our interface object. + * @param on on/off + * + */ +VOID +sdio_SetBusWidth(PSDIO_OBJECT pSdio, UCHAR width) +{ + SDIO_SET_BUSWIDTH(pSdio, width); +} + +// pweber 17.08.2005 +/** + * @brief Set the power save state in the bus driver + * + * @param pSdio pointer to our interface object. + * @param State power save state + * + */ +VOID +sdio_PsState(PSDIO_OBJECT pSdio, UCHAR State) +{ + SDIO_PS_STATE(pSdio, State); +} + + /*--- mmoser 3/20/2006 ---*/ +/** + * @brief Register an interrupt call back in the bus driver + * + * @param pSdio pointer to our interface object. + * @param isrContext Pointer to a data structure which is passed to the interrupt handler + * @param pIsrHandler Pointer to the interrupt handler function + * + */ +ULONG +sdio_Register_ISR_Handler(PSDIO_OBJECT pSdio, + PVOID isrContext, PSDIO_ISR_HANDLER pIsrHandler) +{ + SDIO_REGISTER_ISR_HANDLER(pSdio, isrContext, pIsrHandler); + return 0; +} + +/** + * @brief Enable the interrupt in the FPGA interface + * + * @param pSdio pointer to our interface object. + * + */ +VOID +sdio_EnableInterrupt(PSDIO_OBJECT pSdio) +{ + SDIO_ENABLE_IRQ(pSdio); +} + +/** + * @brief Disable the interrupt in the FPGA interface + * + * @param pSdio pointer to our interface object. + * + */ +VOID +sdio_DisableInterrupt(PSDIO_OBJECT pSdio) +{ + SDIO_DISABLE_IRQ(pSdio); +} + +// private helper functions + +/** + * @brief Get the pointer to the CIS + * + * @param pSdio pointer to our interface object. + * @param function function number + * + * @return address of CIS + * + */ +ULONG +card_GetCIS_Pointer(PSDIO_OBJECT pSdio, UCHAR function) +{ + UCHAR R; + ULONG _cis = 0; + + if (!sdio_Read_Byte(pSdio, FN_CIS_POINTER_0_REG(function), 0, &R)) { + return 0; + } + _cis = R; + if (!sdio_Read_Byte(pSdio, FN_CIS_POINTER_1_REG(function), 0, &R)) { + return 0; + } + _cis |= (R << 8); + if (!sdio_Read_Byte(pSdio, FN_CIS_POINTER_2_REG(function), 0, &R)) { + return 0; + } + _cis |= (R << 16); + + return _cis; +} + +/** + * @brief Get the IO port address for function 1 + * + * @param pSdio pointer to our interface object. + * + * @return TRUE or FALSE + */ +BOOLEAN +card_ReadIO_Port(PSDIO_OBJECT pSdio) +{ + UCHAR R; + ULONG _port = 0; + + if (!sdio_Read_Byte(pSdio, IO_PORT_0_REG, 1, &R)) { + return FALSE; + } + _port = R; + if (!sdio_Read_Byte(pSdio, IO_PORT_1_REG, 1, &R)) { + return FALSE; + } + _port |= (R << 8); + if (!sdio_Read_Byte(pSdio, IO_PORT_2_REG, 1, &R)) { + return FALSE; + } + _port |= (R << 16); + + pSdio->ioport = _port; + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "card_ReadIO_Port : IOPort=%8.08X\n", _port)); + + return TRUE; +} + +/** + * @brief Download the helper firmware image to the SDIO device + * + * @param pSdio pointer to our interface object. + * @param helperImage pointer to the helper firmware image + * @param helpersize size of the helper firmware image + * + * @return TRUE or FALSE + */ +BOOLEAN +card_Helper_Download(PSDIO_OBJECT pSdio, + UCHAR * helperImage, ULONG helpersize) +{ + ULONG txed_len, tries, txlen; + BOOLEAN status = FALSE; + UCHAR fwbuf[FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE]; /*FIRMWARE_DOWNLOAD_BLOCK_SIZE */ + + DBGPRINT(DBG_HWIF, (KERN_DEBUG "card_Helper_Download() \n")); + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Downloading helper image (%d bytes)\n", + helpersize)); + + // Perform firmware data transfer + txlen = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - 4; + for (txed_len = 0; txed_len < helpersize; txed_len += txlen) { + // The host polls for the DN_LD_CARD_RDY and IO_READY bits / + status = card_poll_card_status(pSdio, IO_READY | DN_LD_CARD_RDY); + + if ((status & (IO_READY | DN_LD_CARD_RDY)) != + (IO_READY | DN_LD_CARD_RDY)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Helper image download died @ %d \r\n", + txed_len)); + return FALSE; + } + + /* Set blocksize to transfer - checking for last block */ + if (helpersize - txed_len < txlen) { + txlen = helpersize - txed_len; + } + + fwbuf[0] = (UCHAR) ((txlen & 0x000000ff) >> 0); /* Little-endian */ + fwbuf[1] = (UCHAR) ((txlen & 0x0000ff00) >> 8); + fwbuf[2] = (UCHAR) ((txlen & 0x00ff0000) >> 16); + fwbuf[3] = (UCHAR) ((txlen & 0xff000000) >> 24); + + /* Copy payload to buffer */ +#ifdef WINNT + RtlCopyMemory(&fwbuf[4], &helperImage[txed_len], txlen); +#else + memcpy(&fwbuf[4], &helperImage[txed_len], txlen); +#endif + /* send data */ + status = sdio_Write_Block(pSdio, pSdio->ioport, 1, + BLOCK_MODE, + FIXED_ADDRESS, + fwbuf, FIRMWARE_TRANSFER_NBLOCK); + if (!status) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "IO error: transferring block @ %d\n", + txed_len)); + return FALSE; + } + } + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "\nHelper image download done (%d/%d bytes)\n", + txed_len, helpersize)); + + // The host polls for the DN_LD_CARD_RDY and IO_READY bits / + status = card_poll_card_status(pSdio, IO_READY | DN_LD_CARD_RDY); + + //Write last EOF data + DBGPRINT(DBG_HWIF, (KERN_DEBUG "Transferring EOF block\n")); + +#ifdef WINNT + RtlZeroMemory(fwbuf, sizeof(fwbuf)); +#else + memset(fwbuf, '\0', sizeof(fwbuf)); +#endif + + status = + sdio_Write_Block(pSdio, pSdio->ioport, 1, BLOCK_MODE, FIXED_ADDRESS, + fwbuf, FIRMWARE_TRANSFER_NBLOCK); + + if (!status) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "IO error in writing EOF firmware block\n")); + return FALSE; + } + // Wait for firmware initialization event + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Wait for firmware initialization event\n")); + for (tries = 0; tries < MAX_FIRMWARE_POLL_TRIES; tries++) { + _SLEEP_MS(pSdio, 10); + } + return TRUE; +} + +/** + * @brief Download the helper firmware image and the firmware image to the SDIO device + * + * @param pSdio pointer to our interface object. + * @param pFW_Image pointer to the firmware image + * @param fmsize size of the firmware image + * @param pFW_helperImage pointer to the helper firmware image + * @param helperfmsize size of the helper firmware image + * + * @return TRUE or FALSE + */ +SDIO_API_STATUS +card_Firmware_Download(PSDIO_OBJECT pSdio, + UCHAR * pFW_Image, ULONG fmsize, + UCHAR * pFW_helperImage, ULONG helperfmsize) +{ + ULONG loopCount; + UCHAR returndata; + SDIO_API_STATUS status = SDIO_API_STATUS_FAILURE; + UCHAR base0; + UCHAR base1; + ULONG timeout = 5000; // As per Hedley + USHORT len; + ULONG firmwarestat = 0; + ULONG txed_len, tries, txlen; + ULONG tx_len = 0; + ULONG fwblknow = 0; + UCHAR fwbuf[FIRMWARE_TRANSFER_NBLOCK * 32 * 8 + 8]; /*FIRMWARE_DOWNLOAD_BLOCK_SIZE */ + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "card_Firmware_Download(size=%d bytes) \n", fmsize)); + + status = card_read_scratch(pSdio, &firmwarestat); + if (!status) { + printk("Cannot get fw status!\n"); + return SDIO_API_STATUS_FAILURE; + } + + if (firmwarestat == FIRMWARE_READY) { + printk("FW already loaded!\n"); + return SDIO_API_STATUS_SUCCESS; + } + + loopCount = 0xff; + while (loopCount != 0) { + // need to check if FW is ready for download + + returndata = 0; + if (!sdio_Read_Byte(pSdio, 0x20, 1, &returndata)) { + return SDIO_API_STATUS_FAILURE; + } + if (!(returndata & 0x8) || !(returndata & 0x1)) { + // Not ready for packet download + loopCount--; + UDELAY(20); // wait 20 us + } else { + status = SDIO_API_STATUS_SUCCESS; + break; + } + } + + if (status != SDIO_API_STATUS_SUCCESS) { + printk("Bootloader not ready for download!\n"); + return SDIO_API_STATUS_FAILURE; + } +// printk("%s - %s:%d\n",__FUNCTION__,__FILE__,__LINE__); + //disable int + card_disable_card_int(pSdio, 1, 0xff); + + sdio_DisableInterrupt(pSdio); + + /*--- mmoser 11.10.2005 ---*/ + /*--- mmoser 10/26/2005 ---*/ +// card_ReadIO_Port(pSdio); --> do it in sdio_CreateIface() + + if (pFW_helperImage != NULL) { +// printk("Download Helper Image.\n"); + // download helper image first + if (! + (status = + card_Helper_Download(pSdio, pFW_helperImage, helperfmsize))) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Helper image download FAILED! \n")); + return SDIO_API_STATUS_FAILURE; + } + } + + /* Wait initially for the first non-zero value */ + do { + + if (!sdio_Read_Byte(pSdio, HOST_F1_RD_BASE_0, 1, &base0)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Failed to read FN1 blocksize 0!\n")); + return SDIO_API_STATUS_FAILURE; + } + if (!sdio_Read_Byte(pSdio, HOST_F1_RD_BASE_1, 1, &base1)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Failed to read FN1 blocksize 1!\n")); + return SDIO_API_STATUS_FAILURE; + } + len = (((USHORT) base1) << 8) | base0; + UDELAY(1000); // wait 1000 us + } while (!len && --timeout); + + if (!timeout) { + DBGPRINT(DBG_HWIF, (KERN_DEBUG "Failed to read FN1 blocksize!\n")); + return SDIO_API_STATUS_FAILURE; + } + len &= ~BIT_0; + + // The host polls for the DN_LD_CARD_RDY and IO_READY bits + status = + card_poll_card_status(pSdio, IO_READY | DN_LD_CARD_RDY /*0x05 */ ); + if ((status & (IO_READY | DN_LD_CARD_RDY)) != (IO_READY | DN_LD_CARD_RDY)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "DN_LD_CARD_RDY and IO_READY not ready!\n")); + return SDIO_API_STATUS_FAILURE; + } + + // Perform firmware data transfer + txlen = (SD_BLOCK_SIZE) - 4; + for (txed_len = 0; txed_len < fmsize; txed_len += txlen) { + txlen = len; + + /* Set blocksize to transfer - checking for last block */ + if (fmsize - txed_len < txlen) { + txlen = fmsize - txed_len; + } +// DBGPRINT(DBG_HWIF,( KERN_DEBUG "FW: txed_len=%d, txlen = 0x%04X(%d)\n", txed_len,txlen,txlen)); + + tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE * 8); + for (fwblknow = 0; fwblknow < txlen; fwblknow += tx_len) { + // The host polls for the DN_LD_CARD_RDY and IO_READY bits / + status = card_poll_card_status(pSdio, IO_READY | DN_LD_CARD_RDY); + + if ((status & (IO_READY | DN_LD_CARD_RDY)) != + (IO_READY | DN_LD_CARD_RDY)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Firmware download died @ %d \r\n", + txed_len)); + return SDIO_API_STATUS_FAILURE; + } + if (txlen - fwblknow < tx_len) { + tx_len = txlen - fwblknow; + } + + /* Copy payload to buffer */ +#ifdef WINNT + RtlCopyMemory(&fwbuf[0], &pFW_Image[txed_len + fwblknow], tx_len); +#else + memcpy(&fwbuf[0], &pFW_Image[txed_len + fwblknow], tx_len); +#endif + /* send data */ + status = + sdio_Write_Block(pSdio, pSdio->ioport, 1, BLOCK_MODE, + FIXED_ADDRESS, fwbuf, + FIRMWARE_TRANSFER_NBLOCK * 8); + + if (!status) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "IO error: transferring block @ %d\n", + txed_len + fwblknow)); + return SDIO_API_STATUS_FAILURE; + } + } + do { + /*--- mmoser 3/10/2006 ---*/ + UDELAY(10); // wait 10 us + if (!sdio_Read_Byte(pSdio, HOST_F1_CARD_RDY, 1, &base0)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Failed to read FN1 card ready !\n")); + return SDIO_API_STATUS_FAILURE; + } + } while (!(base0 & 0x08) || !(base0 & 0x01)); + + if (!sdio_Read_Byte(pSdio, HOST_F1_RD_BASE_0, 1, &base0)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Failed to read FN1 blocksize 0!\n")); + return SDIO_API_STATUS_FAILURE; + } + if (!sdio_Read_Byte(pSdio, HOST_F1_RD_BASE_1, 1, &base1)) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Failed to read FN1 blocksize 1!\n")); + return SDIO_API_STATUS_FAILURE; + } + len = (((USHORT) base1) << 8) | base0; + + if (!len) { + if (txed_len == fmsize) { + break; + } + len = 0x10; + } + if (len & BIT_0) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "CRC32 Error indicated by the helper: len=0x%04X(%d)\n", + len, len)); + len &= ~BIT_0; + /* Setting this to 0 to resend from same offset */ + txlen = 0; + } + } + + // Wait for firmware initialization event + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "Wait for firmware initialization event\n")); + for (tries = 0; tries < 10 * MAX_FIRMWARE_POLL_TRIES; tries++) { + status = card_read_scratch(pSdio, &firmwarestat); + if (!status) { + _SLEEP_MS(pSdio, 10); + continue; + } + + if (firmwarestat == FIRMWARE_READY) { + status = SDIO_API_STATUS_SUCCESS; + break; + } else { + _SLEEP_MS(pSdio, 10); + status = SDIO_API_STATUS_FAILURE; + } + } + + if (status == SDIO_API_STATUS_FAILURE) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "Timeout waiting for firmware to become active\n")); + } else { + DBGPRINT(DBG_HWIF, (KERN_DEBUG "Firmware Active OK\n")); + } + + card_enable_card_int(pSdio, 1, UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK); + + sdio_EnableInterrupt(pSdio); + return status; +} + +/** + * @brief Read from the special scratch 'port'. + * + * @param pSdio pointer to our interface object. + * @param dat returns scratch register value + * + * @return TRUE or FALSE + */ +BOOLEAN +card_read_scratch(PSDIO_OBJECT pSdio, ULONG * dat) +{ + + BOOLEAN ret = FALSE; + UCHAR r0, r1; + + ret = sdio_Read_Byte(pSdio, CARD_OCR_0_REG, 1, &r0); + + if (!ret) + return ret; + + ret = sdio_Read_Byte(pSdio, CARD_OCR_1_REG, 1, &r1); + if (!ret) + return ret; + + *dat = (((USHORT) r1) << 8) | r0; + + return TRUE; +} + +/** + * @brief Poll the Card Status register until the bits specified in the argument are turned on + * + * @param pSdio pointer to our interface object. + * @param bits card status bits to wait for + * + * @return TRUE or FALSE + */ +UCHAR +card_poll_card_status(PSDIO_OBJECT pSdio, UCHAR bits) +{ + int tries; + UCHAR cs; + BOOLEAN status = FALSE; + BOOLEAN status1 = FALSE; + + for (tries = 0; tries < MAX_POLL_TRIES * 100; tries++) { + status1 = sdio_Read_Byte(pSdio, CARD_STATUS_REG, 1, &cs); + if (status1) { + if ((cs & bits) == bits) { + status = TRUE; + break; + } + } else { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "card_poll_card_status() FAILED !!!!! ( --> sdio_Read_Byte() failed )\n")); + return 0; + } + + UDELAY(10); + } + + if (!status) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "card_poll_card_status() FAILED !!!!! (cs=0x%2.02X)\n", + cs)); + } + return cs; +} + +/** + * @brief Disable the interrupt of the SDIO device + * + * @param pSdio pointer to our interface object. + * @param function_number function number + * @param mask interrupt mask + * + * @return TRUE or FALSE + */ +BOOLEAN +card_disable_card_int(PSDIO_OBJECT pSdio, UCHAR function_number, UCHAR mask) +{ + BOOLEAN ret; + UCHAR host_int_mask; + UCHAR ucValue; + + /* Read back the host_int_mask register */ + sdio_Read_Byte(pSdio, HOST_INT_MASK_REG, function_number, &host_int_mask); + ucValue = 0; + /* Update with the mask and write back to the register */ + host_int_mask &= ~mask; + ret = + sdio_Write_Byte(pSdio, HOST_INT_MASK_REG, function_number, + host_int_mask); + sdio_Write_Byte(pSdio, HOST_INT_MASK_REG, 0, host_int_mask); + sdio_Write_Byte(pSdio, HOST_INTERRUPT_MASK_REG, 0, 0); + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "card_disable_card_int() : card:0x%2.02X bus:0x%2.02X\n", + host_int_mask, ucValue)); + + return ret; +} + +/** + * @brief Enable the interrupt of the SDIO device + * + * @param pSdio pointer to our interface object. + * @param function_number function number + * @param mask interrupt mask + * + * @return TRUE or FALSE + */ +BOOLEAN +card_enable_card_int(PSDIO_OBJECT pSdio, UCHAR function_number, UCHAR mask) +{ + BOOLEAN status; + UCHAR ucValue; + + /* Simply write the mask to the register */ +// mask = 0x03; + mask = 0x0F; + + /*--- mmoser 11.10.2005 ---*/ + sdio_Write_Byte(pSdio, HOST_INT_RSR_REG, 1, + UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK); + + status = sdio_Write_Byte(pSdio, HOST_INT_MASK_REG, function_number, mask); + sdio_Write_Byte(pSdio, HOST_INTERRUPT_MASK_REG, 0, 0x03); + + ucValue = 0; + + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "card_enable_card_int() : card:0x%2.02X bus:0x%2.02X\n", mask, + ucValue)); + return status; +} + +/** + * @brief Get the bus interface standard information from the bus driver. + * + * @param DevObject pointer to the device object. + * @param BusInterface pointer to the bus interface + * + * @return SDIO_API_STATUS_FAILURE or SDIO_API_STATUS_SUCCESS + */ +SDIO_API_STATUS +sdio_GetStandardInterface(IN PVOID DevObject, + OUT PMRVL_SDIO_INTERFACE_STANDARD BusInterface) +{ +#ifdef WINNT + KEVENT event; + NTSTATUS status; + PIRP irp; + IO_STATUS_BLOCK ioStatusBlock; + PIO_STACK_LOCATION irpStack; + PDEVICE_OBJECT targetObject; + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Init: sdio_GetStandardInterface\n")); + + KeInitializeEvent(&event, SynchronizationEvent, FALSE); + + targetObject = IoGetAttachedDeviceReference((PDEVICE_OBJECT) DevObject); + + irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + targetObject, + NULL, 0, NULL, &event, &ioStatusBlock); + if (irp == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + ObDereferenceObject(targetObject); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "Init: sdio_GetStandardInterface failed : insufficient resources\n")); + return SDIO_API_STATUS_FAILURE; + } + + irpStack = IoGetNextIrpStackLocation(irp); + irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE; + irpStack->Parameters.QueryInterface.InterfaceType = + (LPGUID) & GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD; + irpStack->Parameters.QueryInterface.Size = + sizeof(MRVL_SDIO_INTERFACE_STANDARD); + irpStack->Parameters.QueryInterface.Version = 1; + irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) BusInterface; + irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL; + + // + // Initialize the status to error in case the bus driver decides not to + // set it correctly. + // + + irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + status = IoCallDriver(targetObject, irp); + + if (status == STATUS_PENDING) { + LARGE_INTEGER Timeout; + + Timeout.QuadPart = -((LONGLONG) MILLI_SECOND * (LONGLONG) (2000)); + + if (STATUS_SUCCESS != + KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, + &Timeout)) { + // Failed !!! + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "Init: sdio_GetStandardInterface failed : no answer from bus driver (timeout)\n")); + ObDereferenceObject(targetObject); + return SDIO_API_STATUS_FAILURE; + } + status = ioStatusBlock.Status; + } + + if (STATUS_SUCCESS != status) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "Init: sdio_GetStandardInterface failed : no answer from bus driver (status=%8.08X)\n", + status)); + ObDereferenceObject(targetObject); + return SDIO_API_STATUS_FAILURE; + } + // + // Done with reference + // + ObDereferenceObject(targetObject); +#else // #ifdef WINNT + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Init: sdio_GetStandardInterface\n")); + + if (mrvlsdio_get_interface + ((PGUID) & GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD, + sizeof(MRVL_SDIO_INTERFACE_STANDARD), 1, (PVOID) BusInterface) < 0) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "Init: sdio_GetStandardInterface failed\n")); + return SDIO_API_STATUS_FAILURE; + } +#endif + return SDIO_API_STATUS_SUCCESS; +} + +#ifndef WINNT + +void +sdio_card_added(void *dev) +{ + /*--- mmoser 4/4/2006 ---*/ + if (pNotifier == NULL) { + printk("%s: pNotifier == NULL!!!\n", __FUNCTION__); + return; + } + DBGPRINT(DBG_HWIF, + (KERN_DEBUG "%s called :pNotifier->add=%p global_pSdio=%p\n", + __FUNCTION__, pNotifier->add, global_pSdio)); + /*--- mmoser 3/31/2006 ---*/ + card_is_removed = 0; + card_is_inserted = 1; + if (pNotifier->add != NULL) { + if (global_pSdio == NULL) { + printk("%s: global_pSdio == NULL!!!\n", __FUNCTION__); + return; + } + global_pSdio->card->dev = (struct device *) dev; + pNotifier->add(global_pSdio->card); + } +} + +void +sdio_card_removed() +{ + card_is_inserted = 0; + + /*--- mmoser 4/4/2006 ---*/ + if (global_pSdio == NULL) { + printk("%s: global_pSdio == NULL !!!!\n", __FUNCTION__); + return; + } + + if (pNotifier != NULL && pNotifier->remove != NULL) { + DBGPRINT(DBG_HWIF, + (KERN_DEBUG + "%s called :pNotifier->remove=%p global_pSdio=%p card_is_removed=%d\n", + __FUNCTION__, pNotifier->remove, global_pSdio, + card_is_removed)); + /*--- mmoser 3/31/2006 ---*/ + if (card_is_removed == 0 && global_pSdio) { + pNotifier->remove(global_pSdio->card); + } + } +} + +void * +sdio_register(int type, void *ops, int memory) +{ + + void *ret = NULL; + + switch (type) { + + case MMC_TYPE_HOST: + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "sdio_register: call with MMC_TYPE_HOST not supported!!!!!\n")); + break; + + case MMC_REG_TYPE_USER: + + /*--- mmoser 3/30/2006 ---*/ + pNotifier = (mmc_notifier_t) ops; + + if (sdio_CreateIface(&global_pSdio, NULL, NULL, NULL) == + SDIO_API_STATUS_SUCCESS) { + // pSdio is the pointer to the SDIO API interface structure - pass it + // to the wlan module. Will be needed for further calls to the SDIO + // interface. + ret = (void *) global_pSdio; + } + /*--- mmoser 3/31/2006 ---*/ + mrvlsdio_register_callbacks(sdio_card_added, sdio_card_removed); + ret = (void *) 1; + break; + + default: + break; + } + + return ret; +} + +int +sdio_unregister(int type, void *ops) +{ + + if (global_pSdio == NULL) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "sdio_unregister: global_pSdio == NULL !!!!!\n")); + + /*--- mmoser 4/4/2006 ---*/ + pNotifier = NULL; + mrvlsdio_register_callbacks(NULL, NULL); + return 1; + } + + switch (type) { + case MMC_TYPE_HOST: + break; + case MMC_REG_TYPE_USER: + if (card_is_inserted == 1 && + pNotifier != NULL && pNotifier->remove != NULL) { + pNotifier->remove(global_pSdio->card); + } + + if (global_pSdio->card) + kfree(global_pSdio->card); + + if (global_pSdio->tmpl) + kfree(global_pSdio->tmpl); + + /*--- mmoser 3/31/2006 ---*/ + pNotifier = NULL; + mrvlsdio_register_callbacks(NULL, NULL); + + sdio_DestroyIface(&global_pSdio); + + /*--- mmoser 4/4/2006 ---*/ + global_pSdio = NULL; + break; + + default: + break; + } + + return 0; +} + +int +sdio_free_irq(mmc_card_t card, void *dev_id) +{ + int ret; + +// _ENTER(); + + /*--- mmoser 3/31/2006 ---*/ + card_is_removed = 1; + + if (!card) { + ret = -ENODEV; + goto done; + } + + /* Disable function IOs on the card */ + sdio_write_ioreg(card, FN0, IO_ENABLE_REG, 0x0); + + /* Disable function interrupts on the function */ + sdio_write_ioreg(card, FN0, INT_ENABLE_REG, 0x0); + +// printk("%s: card=%p card->ctrlr=%p line=%d\n",__FUNCTION__,card,card->ctrlr,__LINE__); + sdio_Register_ISR_Handler(card->ctrlr, NULL, NULL); + + /* Release IRQ from OS */ + + return 0; + + done: + + return 0; +} + +int +sdio_get_vendor_id(mmc_card_t card) +{ + card->info.cisptr[0] = card_GetCIS_Pointer(card->ctrlr, 0); + card->info.cisptr[1] = card_GetCIS_Pointer(card->ctrlr, 1); + + return (int) 0x02df; +} + +int +start_bus_clock(mmc_controller_t ctrlr) +{ + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s", __FUNCTION__)); + sdio_SetClock(ctrlr, 1); + return 0; +} + +int +stop_bus_clock_2(mmc_controller_t ctrlr) +{ + DBGPRINT(DBG_HWIF, (KERN_DEBUG "%s", __FUNCTION__)); + sdio_SetClock(ctrlr, 0); + return 0; +} + +int +sdio_check_idle_state(mmc_controller_t ctrlr) +{ + return 0; +} + +void +sdio_print_imask(mmc_controller_t ctrlr) +{ +} + +void +sdio_clear_imask(mmc_controller_t ctrlr) +{ +} + +void +sdio_unmask(void) +{ + sdio_EnableInterrupt(global_pSdio); +} + +EXPORT_SYMBOL(sdio_CreateIface); +EXPORT_SYMBOL(sdio_DestroyIface); +EXPORT_SYMBOL(sdio_Read_Byte); +EXPORT_SYMBOL(sdio_Write_Byte); +EXPORT_SYMBOL(sdio_Read_Block); +EXPORT_SYMBOL(sdio_Write_Block); + + /*--- mmoser 3/20/2006 ---*/ +EXPORT_SYMBOL(sdio_Read_BlockEx); +EXPORT_SYMBOL(sdio_Write_BlockEx); + + /*--- mmoser 3/22/2006 ---*/ +EXPORT_SYMBOL(sdio_clear_imask); +EXPORT_SYMBOL(sdio_check_idle_state); +EXPORT_SYMBOL(sdio_print_imask); +EXPORT_SYMBOL(stop_bus_clock_2); + + /*--- mmoser 3/29/2006 ---*/ +EXPORT_SYMBOL(sdio_free_irq); +EXPORT_SYMBOL(sdio_register); +EXPORT_SYMBOL(sdio_get_vendor_id); +EXPORT_SYMBOL(sdio_unmask); +EXPORT_SYMBOL(sdio_unregister); +EXPORT_SYMBOL(start_bus_clock); + /*--- mmoser 2/20/2007 ---*/ +EXPORT_SYMBOL(sdio_SetGPO); + +EXPORT_SYMBOL(sdio_SetClock); +EXPORT_SYMBOL(sdio_SetBusWidth); +EXPORT_SYMBOL(sdio_SetClockSpeed); + +EXPORT_SYMBOL(sdio_isCardPresent); +EXPORT_SYMBOL(sdio_lockInterface); +EXPORT_SYMBOL(sdio_unlockInterface); +EXPORT_SYMBOL(sdio_SetLed); +EXPORT_SYMBOL(sdio_PsState); +EXPORT_SYMBOL(sdio_EnableInterrupt); +EXPORT_SYMBOL(sdio_DisableInterrupt); +EXPORT_SYMBOL(sdio_Register_ISR_Handler); +EXPORT_SYMBOL(card_isCardReady); +EXPORT_SYMBOL(card_disable_card_int); +EXPORT_SYMBOL(card_enable_card_int); +EXPORT_SYMBOL(card_Helper_Download); +EXPORT_SYMBOL(card_Firmware_Download); +EXPORT_SYMBOL(fw_CardToHost); +EXPORT_SYMBOL(fw_HostToCard); +EXPORT_SYMBOL(ps_sleep_confirmed); + + /*--- mmoser 3/31/2006 ---*/ +EXPORT_SYMBOL(sdio_card_added); +EXPORT_SYMBOL(sdio_card_removed); + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/sdio_spec.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/sdio_spec.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/sdioapi/sdio_spec.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/sdioapi/sdio_spec.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,220 @@ +/* + * File : sdio_spec.h + * Addresses defined by SDIO Specifications + * + * Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006 + */ + +#ifndef _SDIOSPEC_H_ +#define _SDIOSPEC_H_ + +#define MAX_SDIO_TUPLE_BODY_LEN 255 + +/* CCCR (Card Common Control Registers) */ +#define CCCR_SDIO_REV_REG 0x00 +#define CCCR_FORMAT_VERSION(reg) (((reg) & 0xf0 >> 4)) +#define SDIO_SPEC_REVISION(reg) (((reg) & 0x0f)) + +#define SD_SPEC_REV_REG 0x01 +#define SD_PHYS_SPEC_VERSION(reg) (((reg) & 0x0f)) + +#define IO_ENABLE_REG 0x02 +#define IOE(x) (0x1U << (x)) +#define IOE_1 IOE(1) +#define IOE_2 IOE(2) +#define IOE_3 IOE(3) +#define IOE_4 IOE(4) +#define IOE_5 IOE(5) +#define IOE_6 IOE(6) +#define IOE_7 IOE(7) + +#define IO_READY_REG 0x03 +#define IOR(x) (0x1U << (x)) +#define IOR_1 IOR(1) +#define IOR_2 IOR(2) +#define IOR_3 IOR(3) +#define IOR_4 IOR(4) +#define IOR_5 IOR(5) +#define IOR_6 IOR(6) +#define IOR_7 IOR(7) + +#define INT_ENABLE_REG 0x04 +#define IENM 0x1 +#define IEN(x) (0x1U << (x)) +#define IEN_1 IEN(1) +#define IEN_2 IEN(2) +#define IEN_3 IEN(3) +#define IEN_4 IEN(4) +#define IEN_5 IEN(5) +#define IEN_6 IEN(6) +#define IEN_7 IEN(7) + +#define INT_PENDING_REG 0x05 +#define INT(x) (0x1U << (x)) +#define INT_1 INT(1) +#define INT_2 INT(2) +#define INT_3 INT(3) +#define INT_4 INT(4) +#define INT_5 INT(5) +#define INT_6 INT(6) +#define INT_7 INT(7) + +#define IO_ABORT_REG 0x06 +#define AS(x) ((x) & 0x7) +#define AS_1 AS(1) +#define AS_2 AS(2) +#define AS_3 AS(3) +#define AS_4 AS(4) +#define AS_5 AS(5) +#define AS_6 AS(6) +#define AS_7 AS(7) + +#define RES (0x1U << 3) + +#define BUS_INTERFACE_CONTROL_REG 0x07 +#define BUS_WIDTH(reg) ((reg) & 0x3) +#define CD_DISABLE (0x1U << 7) + +#define CARD_CAPABILITY_REG 0x08 +#define SDC (0x1U << 0) +#define SMB (0x1U << 1) +#define SRW (0x1U << 2) +#define SBS (0x1U << 3) +#define S4MI (0x1U << 4) +#define E4MI (0x1U << 5) +#define LSC (0x1U << 6) +#define S4BLS (0x1U << 7) + +#define COMMON_CIS_POINTER_0_REG 0x09 + +#define COMMON_CIS_POINTER_1_REG 0x0a + +#define COMMON_CIS_POINTER_2_REG 0x0b + +#define BUS_SUSPEND_REG 0x0c +#define BUS_STATUS (0x1U << 0) +#define BUS_REL_REQ_STATUS (0x1U << 1) + +#define FUNCTION_SELECT_REG 0x0d +#define FS(x) ((x) & 0xf) +#define FS_1 FS(1) +#define FS_2 FS(2) +#define FS_3 FS(3) +#define FS_4 FS(4) +#define FS_5 FS(5) +#define FS_6 FS(6) +#define FS_7 FS(7) +#define FS_MEM FS(8) +#define DF (0x1U << 7) + +#define EXEC_FLAGS_REG 0x0e +#define EXM 0x0 +#define EX(x) (0x1U << (x)) +#define EX_1 EX(1) +#define EX_2 EX(2) +#define EX_3 EX(3) +#define EX_4 EX(4) +#define EX_5 EX(5) +#define EX_6 EX(6) +#define EX_7 EX(7) + +#define READY_FLAGS_REG 0x0f +#define RFM 0x0 +#define RF(x) (0x1U << (x)) +#define RF_1 RF(1) +#define RF_2 RF(2) +#define RF_3 RF(3) +#define RF_4 RF(4) +#define RF_5 RF(5) +#define RF_6 RF(6) +#define RF_7 IEN(7) + +/* FBR (Function Basic Registers) */ +#define FN_CSA_REG(x) (0x100 * (x) + 0x00) +#define FN_CIS_POINTER_0_REG(x) (0x100 * (x) + 0x09) +#define FN_CIS_POINTER_1_REG(x) (0x100 * (x) + 0x0a) +#define FN_CIS_POINTER_2_REG(x) (0x100 * (x) + 0x0b) +#define FN_CSA_DAT_REG(x) (0x100 * (x) + 0x0f) +#define FN_BLOCK_SIZE_0_REG(x) (0x100 * (x) + 0x10) +#define FN_BLOCK_SIZE_1_REG(x) (0x100 * (x) + 0x11) + +/* Function 0 -- duplicate, see the CCRC section */ +#define FN0_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(1) +#define FN0_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(1) +#define FN0_CIS_POINTER_2_REG FN_CIS_POINTER_1_REG(1) +#define FN0_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(1) +#define FN0_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(1) +/* Function 1 */ +#define FN1_CSA_REG FN_CSA_REG(1) +#define FN1_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(1) +#define FN1_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(1) +#define FN1_CIS_POINTER_2_REG FN_CIS_POINTER_1_REG(1) +#define FN1_CSA_DAT_REG FN_CSA_DAT_REG(1) +#define FN1_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(1) +#define FN1_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(1) +/* Function 2 */ +#define FN2_CSA_REG FN_CSA_REG(2) +#define FN2_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(2) +#define FN2_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(2) +#define FN2_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(2) +#define FN2_CSA_DAT_REG FN_CSA_DAT_REG(2) +#define FN2_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(2) +#define FN2_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(2) +/* Function 3 */ +#define FN3_CSA_REG FN_CSA_REG(3) +#define FN3_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(3) +#define FN3_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(3) +#define FN3_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(3) +#define FN3_CSA_DAT_REG FN_CSA_DAT_REG(3) +#define FN3_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(3) +#define FN3_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(3) +/* Function 4 */ +#define FN4_CSA_REG FN_CSA_REG(4) +#define FN4_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(4) +#define FN4_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(4) +#define FN4_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(4) +#define FN4_CSA_DAT_REG FN_CSA_DAT_REG(4) +#define FN4_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(4) +#define FN4_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(4) +/* Function 5 */ +#define FN5_CSA_REG FN_CSA_REG(5) +#define FN5_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(5) +#define FN5_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(5) +#define FN5_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(5) +#define FN5_CSA_DAT_REG FN_CSA_DAT_REG(5) +#define FN5_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(5) +#define FN5_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(5) +/* Function 6 */ +#define FN6_CSA_REG FN_CSA_REG(6) +#define FN6_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(6) +#define FN6_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(6) +#define FN6_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(6) +#define FN6_CSA_DAT_REG FN_CSA_DAT_REG(6) +#define FN6_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(6) +#define FN6_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(6) +/* Function 7 */ +#define FN7_CSA_REG FN_CSA_REG(7) +#define FN7_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(7) +#define FN7_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(7) +#define FN7_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(7) +#define FN7_CSA_DAT_REG FN_CSA_DAT_REG(7) +#define FN7_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(7) +#define FN7_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(7) + +/* FBR bit definitions */ +#define FN_IODEV_INTERFACE_CODE(reg) ((reg) & 0xf) +#define FN_SUPPORTS_CSA (0x1U << 6) +#define FN_CSA_ENABLE (0x1U << 7) + +/* Misc. helper definitions */ +#define FN(x) (x) +#define FN0 FN(0) +#define FN1 FN(1) +#define FN2 FN(2) +#define FN3 FN(3) +#define FN4 FN(4) +#define FN5 FN(5) +#define FN6 FN(6) +#define FN7 FN(7) + +#endif /* __SDIO_SPEC__H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/diagvers.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/diagvers.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/diagvers.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/diagvers.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Name: diagvers.h_ + * Project: Wireless LAN, SDIO Bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:23:14 $ + * Purpose: SDIO bus driver version control + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell. + * All Rights Reserved + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: diagvers.h,v $ + * Revision 1.1 2007/01/18 09:23:14 pweber + * Put under CVS control + * + * + ******************************************************************************/ + +// #define SK_SIGNON_MSG "___OEM_SIGNONMSG__" +#define SK_SIGNON_MSG "Marvell SD Standard Host Driver V.2.0.0.0" diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdiobus.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdiobus.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdiobus.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdiobus.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,526 @@ +/****************************************************************************** + * + * Name: sdiobus.h + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: Bus driver for SDIO interface definitions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sdiobus.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * YJBbT9UrnC + * + ******************************************************************************/ +#ifndef SDIOBUS_H +#define SDIOBUS_H + +#define CARD_ADD_EVENT 1 +#define CARD_REMOVED_EVENT 2 + +#define SDIOBUS_COMPATIBLE_IDS L"SDIOBUS\\MrvlCompatibleSDIOBus\0" +#define SDIOBUS_COMPATIBLE_IDS_LENGTH sizeof(SDIOBUS_COMPATIBLE_IDS) + +#define SDIOBUS_POOL_TAG (ULONG) 'lvrM' + +// #define SDIO_BUS_PERFORMANCE 1 + +//#define WAIT_SDIO_CMD_RESPONSE 10 // wait time in microseconds +#define WAIT_SDIO_CMD_RESPONSE() UDELAY(2) + +#define MILLI_SECOND 10000 + +#define SDIO_BUS_TYPE 1 +#define SDIO_SPI_TYPE 2 + +#define SDIO_1_BIT 1 +#define SDIO_4_BIT 4 + +#define DMA_WR_SUPPORT 0x01 +#define DMA_RD_SUPPORT 0x02 + + /*--- mmoser 8/29/2006 ---*/ +#ifndef WINNT +typedef struct _SDHOST_EVENT +{ + long event; + wait_queue_head_t wq; +} SDHOST_EVENT; +#endif + +//YJBbT9UrnC +// These are the states a PDO or FDO transition upon +// receiving a specific PnP Irp. Refer to the PnP Device States +// diagram in DDK documentation for better understanding. +// + +typedef enum _DEVICE_PNP_STATE +{ + + NotStarted = 0, // Not started yet + Started, // Device has received the START_DEVICE IRP + StopPending, // Device has received the QUERY_STOP IRP + Stopped, // Device has received the STOP_DEVICE IRP + RemovePending, // Device has received the QUERY_REMOVE IRP + SurpriseRemovePending, // Device has received the SURPRISE_REMOVE IRP + Deleted, // Device has received the REMOVE_DEVICE IRP + UnKnown // Unknown state +} DEVICE_PNP_STATE; + +// +// A common header for the device extensions of the PDOs and FDO +// + +#define DEVICE_NAME_LENGTH 256 + +typedef struct _COMMON_DEVICE_DATA +{ +#ifdef SYSKT_DMA_MALIGN_TEST + SK_U32 dma_rx_malign; + SK_U32 dma_tx_malign; + SK_U32 dma_start_malign; + SK_U8 dma_rbuff[1024 * 8]; //__attribute__((aligned(4))); + SK_U8 dma_tbuff[1024 * 8]; //__attribute__((aligned(4))); + // struct sk_buff *dma_skb; +#endif +#ifdef WINNT + // A back pointer to the device object for which this is the extension + + PDEVICE_OBJECT Self; + + // This flag helps distinguish between PDO and FDO + + BOOLEAN IsFDO; + + // We track the state of the device with every PnP Irp + // that affects the device through these two variables. + + DEVICE_PNP_STATE DevicePnPState; + + DEVICE_PNP_STATE PreviousPnPState; + + // Stores the current system power state + + SYSTEM_POWER_STATE SystemPowerState; + + // Stores current device power state + + DEVICE_POWER_STATE DevicePowerState; + + PKINTERRUPT InterruptObject; + + KIRQL IrqL; + KTIMER SleepTimer; + + PVOID ThreadObjectPointer; // pointer to a worker thread for this Device + KEVENT CardInEvent; + KEVENT CardOutEvent; + SK_BOOL CardOutEventPending; + FAST_MUTEX deviceMutex; + KSPIN_LOCK deviceLock; + + SK_BOOL TimeToTerminateThread; // TRUE == worker thread should kill itself via PsTerminateSystemThread() + KEVENT dnldFinishedEvent; +#else // #ifdef WINNT + + // Linux specific + + int thread_id; + wait_queue_head_t wq; + int stop_thread; + + // mmoser 2005-11-28 + atomic_t card_add_event; + atomic_t card_remove_event; + + /*--- mmoser 8/29/2006 ---*/ + SDHOST_EVENT trans_complete_evt; + SDHOST_EVENT cmd_complete_evt; + + /*--- mmoser 10/11/2006 ---*/ + struct pci_dev *dev; +#endif + + SK_U8 *indexReg; + SK_U8 *dataReg; + + SK_U16 blockSize; + SK_U16 lastBlockSize; + SK_U32 ioport; + // IOBase Addresses + SK_U32 *IOBase[2]; + SK_U32 IOBaseLength[2]; + SK_U32 IOBaseIx; + SK_U32 Interrupt; + SK_U32 Affinity; + SK_U32 InterruptMode; + SK_U32 lastIntStatus; + SK_U8 lastCardIntStatus; + SK_U8 MACEvent; + SK_U8 DeviceName[2 * (DEVICE_NAME_LENGTH + 1)]; + SK_U32 DeviceNameLength; + + SK_BOOL dump; + SK_U32 ClockSpeed; + SK_BOOL initialized; + + /*--- mmoser 13.09.2005 ---*/ + SK_BOOL SurpriseRemoved; + +#ifdef WINNT + SK_U32 if_lock; +#else + atomic_t if_lock; +#endif + + SK_U8 dnlType; + SK_U8 CmdInProgress; + + SK_U16 tmpIRQSignalMask; + SK_U16 lastIRQSignalMask; + SK_U16 lastErrorIRQSignalMask; + SK_U8 baseClockFreq; + SK_U8 maxSupplyVoltage; + SK_U16 max_block_size; + SK_U32 debug_flags; + SK_U32 sdio_voltage; + + SK_U32 errorOccured; + + SK_BOOL callCardToHost; + SK_U8 pTxBuf[WLAN_UPLD_SIZE]; + SK_U32 txed_len; + SK_BOOL crc_error; + SK_U32 bus_errors; + SK_U32 bus_width; + SK_U32 bus_type; + SK_U32 crc_len; + + SK_U8 pUpl_Buf[WLAN_UPLD_SIZE]; +// SK_U8 *pUpl_Buf; + SK_U32 upl_length; + SK_U32 uplBlocks; + SK_U32 uplCurrBlock; + SK_U32 bytesrxed; + SK_U8 uplType; + SK_U8 dma_support; + + PSDIO_ISR_HANDLER pIsr; + PVOID isrContext; + + SK_U8 PsState; // pweber 17.08.2005 + +} COMMON_DEVICE_DATA, *PCOMMON_DEVICE_DATA; + +#ifdef WINNT +// +// The device extension for the PDOs. +// That's of the toaster device which this bus driver enumerates. +// + +typedef struct _PDO_DEVICE_DATA +{ + COMMON_DEVICE_DATA common; + + // A back pointer to the bus + + PDEVICE_OBJECT ParentFdo; + + // An array of (zero terminated wide character strings). + // The array itself also null terminated + + PWCHAR HardwareIDs; + + // Unique serial number of the device on the bus + + ULONG SerialNo; + + // Link point to hold all the PDOs for a single bus together + + LIST_ENTRY Link; + + // + // Present is set to TRUE when the PDO is exposed via PlugIn IOCTL, + // and set to FALSE when a UnPlug IOCTL is received. + // We will delete the PDO in IRP_MN_REMOVE only after we have reported + // to the Plug and Play manager that it's missing. + // + + BOOLEAN Present; + BOOLEAN ReportedMissing; + UCHAR Reserved[2]; // for 4 byte alignment + + // + // Used to track the intefaces handed out to other drivers. + // If this value is non-zero, we fail query-remove. + // + ULONG SDIOInterfaceRefCount; + + LIST_ENTRY PendingQueue; + + // The spin lock that protects access to the queue + + KSPIN_LOCK PendingQueueLock; + +} PDO_DEVICE_DATA, *PPDO_DEVICE_DATA; +#endif + +// +// The device extension of the bus itself. From whence the PDO's are born. +// + +typedef struct _FDO_DEVICE_DATA +{ + COMMON_DEVICE_DATA common; + +#ifdef WINNT + PDEVICE_OBJECT UnderlyingPDO; + + // The underlying bus PDO and the actual device object to which our + // FDO is attached + + PDEVICE_OBJECT NextLowerDriver; + + // List of PDOs created so far + + LIST_ENTRY ListOfPDOs; + + // The PDOs currently enumerated. + + ULONG NumPDOs; + // A synchronization for access to the device extension. + + FAST_MUTEX Mutex; + + // + // The number of IRPs sent from the bus to the underlying device object + // + + ULONG OutstandingIO; // Biased to 1 + + // + // On remove device plug & play request we must wait until all outstanding + // requests have been completed before we can actually delete the device + // object. This event is when the Outstanding IO count goes to zero + // + + KEVENT RemoveEvent; + + // + // This event is set when the Outstanding IO count goes to 1. + // + + KEVENT StopEvent; + + // The name returned from IoRegisterDeviceInterface, + // which is used as a handle for IoSetDeviceInterfaceState. + + UNICODE_STRING InterfaceName; + +#else // #ifdef WINNT + // + // Used to track the intefaces handed out to other drivers. + // If this value is non-zero, we fail query-remove. + // + atomic_t SDIOInterfaceRefCount; +#endif // !#ifdef WINNTYJBbT9UrnC + + SK_BOOL CardIn; + +} FDO_DEVICE_DATA, *PFDO_DEVICE_DATA; + +#ifdef WINNT +#define FDO_FROM_PDO(pdoData) \ + ((PFDO_DEVICE_DATA) (pdoData)->ParentFdo->DeviceExtension) +#endif // #ifdef WINNT + +#define INITIALIZE_PNP_STATE(_Data_) \ + (_Data_)->common.DevicePnPState = NotStarted;\ + (_Data_)->common.PreviousPnPState = NotStarted; + +#define SET_NEW_PNP_STATE(_Data_, _state_) \ + (_Data_)->common.PreviousPnPState = (_Data_)->common.DevicePnPState;\ + (_Data_)->common.DevicePnPState = (_state_); + +#define RESTORE_PREVIOUS_PNP_STATE(_Data_) \ + (_Data_)->common.DevicePnPState = (_Data_)->common.PreviousPnPState;\ + + +#ifndef WINNT +void SDIO_RegisterIsrHandler(PCOMMON_DEVICE_DATA pDev, + PVOID isrContext, PSDIO_ISR_HANDLER pIsrHandler); + +BOOLEAN SDIOBus_CardPluggedIn(PFDO_DEVICE_DATA FdoData); +BOOLEAN SDIOBus_CardRemoved(PFDO_DEVICE_DATA FdoData); + +#else // #ifndef WINNT +// +// Prototypes of functions +// +// +// Defined in DriverEntry.C +// + +NTSTATUS DriverEntry(IN PDRIVER_OBJECT, PUNICODE_STRING); + +NTSTATUS SDIOBus_CreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +NTSTATUS SDIOBus_IoCtl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +VOID SDIOBus_DriverUnload(IN PDRIVER_OBJECT DriverObject); + +VOID SDIOBus_IncIoCount(PFDO_DEVICE_DATA Data); + +VOID SDIOBus_DecIoCount(PFDO_DEVICE_DATA Data); + +// +// Defined in PNP.C +// + +NTSTATUS SDIOBus_CreateSystemThread(PCOMMON_DEVICE_DATA pDev); + +VOID SDIOThread(IN PCOMMON_DEVICE_DATA pDev); + +PCHAR SDIOBus_PnPMinorFunctionString(UCHAR MinorFunction); + +NTSTATUS +SDIOBus_CompletionRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Pirp, IN PVOID Context); + +NTSTATUS +SDIOBus_SendIrpSynchronously(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +NTSTATUS SDIOBus_PnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +NTSTATUS +SDIOBus_AddDevice(IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT BusDeviceObject); + +VOID SDIOBus_InitializePdo(PDEVICE_OBJECT Pdo, PFDO_DEVICE_DATA FdoData); + +NTSTATUS SDIOBus_CardPluggedIn(IN PFDO_DEVICE_DATA FdoData); + +NTSTATUS SDIOBus_CardRemoved(IN PFDO_DEVICE_DATA FdoData); + +void SDIOBus_RemoveFdo(PFDO_DEVICE_DATA FdoData); + +NTSTATUS SDIOBus_DestroyPdo(PDEVICE_OBJECT Device, PPDO_DEVICE_DATA PdoData); + +NTSTATUS +SDIOBus_FDO_PnP(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpStack, YJBbT9UrnC + IN PFDO_DEVICE_DATA DeviceData); + +NTSTATUS SDIOBus_StartFdo(IN PFDO_DEVICE_DATA FdoData, IN PIRP Irp); + +PCHAR DbgDeviceIDString(BUS_QUERY_ID_TYPE Type); + +PCHAR DbgDeviceRelationString(IN DEVICE_RELATION_TYPE Type); + +// +// Defined in Power.c +// + +NTSTATUS SDIOBus_FDO_Power(PFDO_DEVICE_DATA FdoData, PIRP Irp); + +NTSTATUS SDIOBus_PDO_Power(PPDO_DEVICE_DATA PdoData, PIRP Irp); + +NTSTATUS SDIOBus_Power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +PCHAR SDIOBus_PowerMinorFunctionString(UCHAR MinorFunction); + +PCHAR DbgSystemPowerString(IN SYSTEM_POWER_STATE Type); +PCHAR DbgDevicePowerString(IN DEVICE_POWER_STATE Type); + +// +// Defined in sdioPDO.c +// + +NTSTATUS +SDIOBus_PDO_PnP(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpStack, + IN PPDO_DEVICE_DATA DeviceData); + +NTSTATUS +SDIOBus_PDO_QueryDeviceCaps(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryDeviceId(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryDeviceText(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryResources(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryResourceRequirements(IN PPDO_DEVICE_DATA DeviceData, + IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryDeviceRelations(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_PDO_QueryBusInformation(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +NTSTATUS +SDIOBus_GetDeviceCapabilities(IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_CAPABILITIES DeviceCapabilities); + +NTSTATUS +SDIOBus_PDO_QueryInterface(IN PPDO_DEVICE_DATA DeviceData, IN PIRP Irp); + +VOID SDIOBus_InterfaceReference(IN PVOID Context); +VOID SDIOBus_InterfaceDereference(IN PVOID Context); + +NTSTATUS SDIOBus_SystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); + +void SDIO_RegisterIsrHandler(PCOMMON_DEVICE_DATA pDev, + PVOID isrContext, PSDIO_ISR_HANDLER pIsrHandler); + +NTSTATUS +SDIO_RegGetDword(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ParameterName, IN OUT PULONG ParameterValue); + +NTSTATUS +SDIO_RegGetDeviceParameterDword(IN PDEVICE_OBJECT Pdo, + IN PWSTR ParameterName, + IN OUT PULONG ParameterValue); + +NTSTATUS +SDIO_RegSetDword(IN ULONG RelativeTo, + IN PCWSTR Path, + IN PCWSTR ValueName, + IN PVOID ValueData, IN ULONG ValueLength); +#endif +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdio.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdio.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdio.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdio.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,190 @@ +#ifndef _SDIO_H_ +#define _SDIO_H_ + +#include "sdio_spec.h" +#include "sdio_if.h" + +/* CMD53 parameter*/ +//mode +#define BLOCK_MODE 0x1 +#define BYTE_MODE 0x0 +//opcode +#define FIXED_ADDRESS 0x0 +#define INCREMENTAL_ADDRESS 0x1 + +#define MMC_TYPE_HOST 1 +#define MMC_TYPE_CARD 2 +#define MMC_REG_TYPE_USER 3 + +#ifdef SDIO_BUS_DRIVER + +#define MVSD_DAT 0 +#define MVSD_CMD 1 +#define MVSD_EVENT 3 + +#define SD_BLOCK_SIZE 32 + +/*** +// +// Bit definition +// +#define DW_BIT_0 0x00000001 +#define DW_BIT_1 0x00000002 +#define DW_BIT_2 0x00000004 +#define DW_BIT_3 0x00000008 +#define DW_BIT_4 0x00000010 +#define DW_BIT_5 0x00000020 +#define DW_BIT_6 0x00000040 +#define DW_BIT_7 0x00000080 +#define DW_BIT_8 0x00000100 +#define DW_BIT_9 0x00000200 +#define DW_BIT_10 0x00000400 +#define DW_BIT_11 0x00000800 +#define DW_BIT_12 0x00001000 +#define DW_BIT_13 0x00002000 +#define DW_BIT_14 0x00004000 +#define DW_BIT_15 0x00008000 +#define DW_BIT_16 0x00010000 +#define DW_BIT_17 0x00020000 +#define DW_BIT_18 0x00040000 +#define DW_BIT_19 0x00080000 +#define DW_BIT_20 0x00100000 +#define DW_BIT_21 0x00200000 +#define DW_BIT_22 0x00400000 +#define DW_BIT_23 0x00800000 +#define DW_BIT_24 0x01000000 +#define DW_BIT_25 0x02000000 +#define DW_BIT_26 0x04000000 +#define DW_BIT_27 0x08000000 +#define DW_BIT_28 0x10000000 +#define DW_BIT_29 0x20000000 +#define DW_BIT_30 0x30000000 +#define DW_BIT_31 0x80000000 + +#define W_BIT_0 0x0001 +#define W_BIT_1 0x0002 +#define W_BIT_2 0x0004 +#define W_BIT_3 0x0008 +#define W_BIT_4 0x0010 +#define W_BIT_5 0x0020 +#define W_BIT_6 0x0040 +#define W_BIT_7 0x0080 +#define W_BIT_8 0x0100 +#define W_BIT_9 0x0200 +#define W_BIT_10 0x0400 +#define W_BIT_11 0x0800 +#define W_BIT_12 0x1000 +#define W_BIT_13 0x2000 +#define W_BIT_14 0x4000 +#define W_BIT_15 0x8000 + +****/ + +#define BIT_0 0x01 +#define BIT_1 0x02 +#define BIT_2 0x04 +#define BIT_3 0x08 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 + +/* FBR (Function Basic Registers) */ +#define FN_CSA_REG(x) (0x100 * (x) + 0x00) +#define FN_CIS_POINTER_0_REG(x) (0x100 * (x) + 0x09) +#define FN_CIS_POINTER_1_REG(x) (0x100 * (x) + 0x0a) +#define FN_CIS_POINTER_2_REG(x) (0x100 * (x) + 0x0b) +#define FN_CSA_DAT_REG(x) (0x100 * (x) + 0x0f) +#define FN_BLOCK_SIZE_0_REG(x) (0x100 * (x) + 0x10) +#define FN_BLOCK_SIZE_1_REG(x) (0x100 * (x) + 0x11) + +/* The following defines function 1 registers of SD25 */ +/* Ref.: SD-25 SDIO Interface Specification Rev. 2.0. */ +/* Marvell Semiconductor, Inc. */ + +/* Host Control Registers */ + +#define IO_PORT_0_REG 0x00 +#define IO_PORT_1_REG 0x01 +#define IO_PORT_2_REG 0x02 +#define CONFIGURATION_REG 0x03 +#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2) +#define HOST_POWER_UP (0x1U << 1) +#define HOST_POWER_DOWN (0x1U << 0) +#define HOST_INT_MASK_REG 0x04 +#define UP_LD_HOST_INT_MASK (0x1U << 0) +#define DN_LD_HOST_INT_MASK (0x1U << 1) +#define HOST_INTSTATUS_REG 0x05 +#define UP_LD_HOST_INT_STATUS (0x1U) +#define DN_LD_HOST_INT_STATUS (0x2U) +#define IO_ABORT_REG 0x06 +#define HOST_INT_RSR_REG 0x06 +#define UP_LD_HOST_INT_RSR (0x1U) +#define HOST_INT_STATUS_REG 0x07 +#define UP_LD_CRC_ERR (0x1U << 2) +#define UP_LD_RESTART (0x1U << 1) +#define DN_LD_RESTART (0x1U << 0) + +/* Card Control Registers */ +#define SQ_READ_BASE_ADDRESS_A0_REG 0x10 +#define SQ_READ_BASE_ADDRESS_A1_REG 0x11 +#define SQ_READ_BASE_ADDRESS_A2_REG 0x12 +#define SQ_READ_BASE_ADDRESS_A3_REG 0x13 +#define SQ_READ_BASE_ADDRESS_B0_REG 0x14 +#define SQ_READ_BASE_ADDRESS_B1_REG 0x15 +#define SQ_READ_BASE_ADDRESS_B2_REG 0x16 +#define SQ_READ_BASE_ADDRESS_B3_REG 0x17 +#define CARD_STATUS_REG 0x20 +#define IO_READY (0x1U << 3) +#define CIS_CARD_RDY (0x1U << 2) +#define UP_LD_CARD_RDY (0x1U << 1) +#define DN_LD_CARD_RDY (0x1U << 0) +#define HOST_INTERRUPT_MASK_REG 0x24 +#define HOST_POWER_INT_MASK (0x1U << 3) +#define ABORT_CARD_INT_MASK (0x1U << 2) +#define UP_LD_CARD_INT_MASK (0x1U << 1) +#define DN_LD_CARD_INT_MASK (0x1U << 0) + +// 2005-02-18 mmoser +#define UP_LD_CARD_INT (0x1U << 0) +#define DN_LD_CARD_INT (0x1U << 1) + +#define CARD_INTERRUPT_STATUS_REG 0x28 +#define POWER_UP_INT (0x1U << 4) +#define POWER_DOWN_INT (0x1U << 3) +#define CARD_INTERRUPT_RSR_REG 0x2c +#define POWER_UP_RSR (0x1U << 4) +#define POWER_DOWN_RSR (0x1U << 3) +#define DEBUG_0_REG 0x30 +#define SD_TESTBUS0 (0x1U) +#define DEBUG_1_REG 0x31 +#define SD_TESTBUS1 (0x1U) +#define DEBUG_2_REG 0x32 +#define SD_TESTBUS2 (0x1U) +#define DEBUG_3_REG 0x33 +#define SD_TESTBUS3 (0x1U) +#define CARD_OCR_0_REG 0x34 +#define CARD_OCR_1_REG 0x35 +#define CARD_OCR_3_REG 0x36 +#define CARD_CONFIG_REG 0x38 +#define CMD53_FINISH_GBUS (0x1U << 1) +#define SD_NEG_EDGE (0x1U << 0) + +/* Special registers in function 0 of the SD25 card */ +#define SCRATCH_0_REG 0x80fe +#define SCRATCH_1_REG 0x80ff + +#define HOST_F1_RD_BASE_0 0x0010 +#define HOST_F1_RD_BASE_1 0x0011 +#define HOST_F1_CARD_RDY 0x0020 + + /**/ +#define FIRMWARE_READY 0xfedc +/* The number of times to try when polling for status bits */ +#define MAX_POLL_TRIES 100 +/*Firmware download parameter*/ +#define FIRMWARE_DOWNLOAD_BLOCK_SIZE 32 //include the size header 4 bytes +#define MAX_FIRMWARE_POLL_TRIES 100 +#define FIRMWARE_TRANSFER_NBLOCK 2 +#endif // SDIO_BUS_DRIVER +#endif /*sdio.h */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdio_spec.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdio_spec.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sdio_spec.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sdio_spec.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,223 @@ +/* + * File : sdio_spec.h + * Addresses defined by SDIO Specifications + * + * Copyright © Marvell International Ltd. and/or its affiliates, 2003-2006 + */ + +#ifndef _SDIOSPEC_H_ +#define _SDIOSPEC_H_ + +#define MAX_SDIO_TUPLE_BODY_LEN 255 + +/* CCCR (Card Common Control Registers) */ +#define CCCR_SDIO_REV_REG 0x00 +#define CCCR_FORMAT_VERSION(reg) (((reg) & 0xf0 >> 4)) +#define SDIO_SPEC_REVISION(reg) (((reg) & 0x0f)) + +#define SD_SPEC_REV_REG 0x01 +#define SD_PHYS_SPEC_VERSION(reg) (((reg) & 0x0f)) + +#define IO_ENABLE_REG 0x02 +#define IOE(x) (0x1U << (x)) +#define IOE_1 IOE(1) +#define IOE_2 IOE(2) +#define IOE_3 IOE(3) +#define IOE_4 IOE(4) +#define IOE_5 IOE(5) +#define IOE_6 IOE(6) +#define IOE_7 IOE(7) + +#define IO_READY_REG 0x03 +#define IOR(x) (0x1U << (x)) +#define IOR_1 IOR(1) +#define IOR_2 IOR(2) +#define IOR_3 IOR(3) +#define IOR_4 IOR(4) +#define IOR_5 IOR(5) +#define IOR_6 IOR(6) +#define IOR_7 IOR(7) + +#define INT_ENABLE_REG 0x04 +#define IENM 0x1 +#define IEN(x) (0x1U << (x)) +#define IEN_1 IEN(1) +#define IEN_2 IEN(2) +#define IEN_3 IEN(3) +#define IEN_4 IEN(4) +#define IEN_5 IEN(5) +#define IEN_6 IEN(6) +#define IEN_7 IEN(7) + +#define INT_PENDING_REG 0x05 +#define INT(x) (0x1U << (x)) +#define INT_1 INT(1) +#define INT_2 INT(2) +#define INT_3 INT(3) +#define INT_4 INT(4) +#define INT_5 INT(5) +#define INT_6 INT(6) +#define INT_7 INT(7) + +#define IO_ABORT_REG 0x06 +#define AS(x) ((x) & 0x7) +#define AS_1 AS(1) +#define AS_2 AS(2) +#define AS_3 AS(3) +#define AS_4 AS(4) +#define AS_5 AS(5) +#define AS_6 AS(6) +#define AS_7 AS(7) + +#define RES (0x1U << 3) + +#define BUS_INTERFACE_CONTROL_REG 0x07 +#define BUS_WIDTH(reg) ((reg) & 0x3) +#define CD_DISABLE (0x1U << 7) + +#define CARD_CAPABILITY_REG 0x08 +#define SDC (0x1U << 0) +#define SMB (0x1U << 1) +#define SRW (0x1U << 2) +#define SBS (0x1U << 3) +#define S4MI (0x1U << 4) +#define E4MI (0x1U << 5) +#define LSC (0x1U << 6) +#define S4BLS (0x1U << 7) + +#define COMMON_CIS_POINTER_0_REG 0x09 + +#define COMMON_CIS_POINTER_1_REG 0x0a + +#define COMMON_CIS_POINTER_2_REG 0x0b + +#define BUS_SUSPEND_REG 0x0c +#define BUS_STATUS (0x1U << 0) +#define BUS_REL_REQ_STATUS (0x1U << 1) + +#define FUNCTION_SELECT_REG 0x0d +#ifdef FS +#undef FS +#endif +#define FS(x) ((x) & 0xf) +#define FS_1 FS(1) +#define FS_2 FS(2) +#define FS_3 FS(3) +#define FS_4 FS(4) +#define FS_5 FS(5) +#define FS_6 FS(6) +#define FS_7 FS(7) +#define FS_MEM FS(8) +#define DF (0x1U << 7) + +#define EXEC_FLAGS_REG 0x0e +#define EXM 0x0 +#define EX(x) (0x1U << (x)) +#define EX_1 EX(1) +#define EX_2 EX(2) +#define EX_3 EX(3) +#define EX_4 EX(4) +#define EX_5 EX(5) +#define EX_6 EX(6) +#define EX_7 EX(7) + +#define READY_FLAGS_REG 0x0f +#define RFM 0x0 +#define RF(x) (0x1U << (x)) +#define RF_1 RF(1) +#define RF_2 RF(2) +#define RF_3 RF(3) +#define RF_4 RF(4) +#define RF_5 RF(5) +#define RF_6 RF(6) +#define RF_7 IEN(7) + +/* FBR (Function Basic Registers) */ +#define FN_CSA_REG(x) (0x100 * (x) + 0x00) +#define FN_CIS_POINTER_0_REG(x) (0x100 * (x) + 0x09) +#define FN_CIS_POINTER_1_REG(x) (0x100 * (x) + 0x0a) +#define FN_CIS_POINTER_2_REG(x) (0x100 * (x) + 0x0b) +#define FN_CSA_DAT_REG(x) (0x100 * (x) + 0x0f) +#define FN_BLOCK_SIZE_0_REG(x) (0x100 * (x) + 0x10) +#define FN_BLOCK_SIZE_1_REG(x) (0x100 * (x) + 0x11) + +/* Function 0 -- duplicate, see the CCRC section */ +#define FN0_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(1) +#define FN0_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(1) +#define FN0_CIS_POINTER_2_REG FN_CIS_POINTER_1_REG(1) +#define FN0_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(1) +#define FN0_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(1) +/* Function 1 */ +#define FN1_CSA_REG FN_CSA_REG(1) +#define FN1_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(1) +#define FN1_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(1) +#define FN1_CIS_POINTER_2_REG FN_CIS_POINTER_1_REG(1) +#define FN1_CSA_DAT_REG FN_CSA_DAT_REG(1) +#define FN1_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(1) +#define FN1_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(1) +/* Function 2 */ +#define FN2_CSA_REG FN_CSA_REG(2) +#define FN2_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(2) +#define FN2_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(2) +#define FN2_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(2) +#define FN2_CSA_DAT_REG FN_CSA_DAT_REG(2) +#define FN2_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(2) +#define FN2_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(2) +/* Function 3 */ +#define FN3_CSA_REG FN_CSA_REG(3) +#define FN3_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(3) +#define FN3_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(3) +#define FN3_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(3) +#define FN3_CSA_DAT_REG FN_CSA_DAT_REG(3) +#define FN3_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(3) +#define FN3_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(3) +/* Function 4 */ +#define FN4_CSA_REG FN_CSA_REG(4) +#define FN4_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(4) +#define FN4_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(4) +#define FN4_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(4) +#define FN4_CSA_DAT_REG FN_CSA_DAT_REG(4) +#define FN4_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(4) +#define FN4_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(4) +/* Function 5 */ +#define FN5_CSA_REG FN_CSA_REG(5) +#define FN5_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(5) +#define FN5_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(5) +#define FN5_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(5) +#define FN5_CSA_DAT_REG FN_CSA_DAT_REG(5) +#define FN5_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(5) +#define FN5_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(5) +/* Function 6 */ +#define FN6_CSA_REG FN_CSA_REG(6) +#define FN6_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(6) +#define FN6_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(6) +#define FN6_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(6) +#define FN6_CSA_DAT_REG FN_CSA_DAT_REG(6) +#define FN6_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(6) +#define FN6_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(6) +/* Function 7 */ +#define FN7_CSA_REG FN_CSA_REG(7) +#define FN7_CIS_POINTER_0_REG FN_CIS_POINTER_0_REG(7) +#define FN7_CIS_POINTER_1_REG FN_CIS_POINTER_1_REG(7) +#define FN7_CIS_POINTER_2_REG FN_CIS_POINTER_2_REG(7) +#define FN7_CSA_DAT_REG FN_CSA_DAT_REG(7) +#define FN7_BLOCK_SIZE_0_REG FN_BLOCK_SIZE_0_REG(7) +#define FN7_BLOCK_SIZE_1_REG FN_BLOCK_SIZE_1_REG(7) + +/* FBR bit definitions */ +#define FN_IODEV_INTERFACE_CODE(reg) ((reg) & 0xf) +#define FN_SUPPORTS_CSA (0x1U << 6) +#define FN_CSA_ENABLE (0x1U << 7) + +/* Misc. helper definitions */ +#define FN(x) (x) +#define FN0 FN(0) +#define FN1 FN(1) +#define FN2 FN(2) +#define FN3 FN(3) +#define FN4 FN(4) +#define FN5 FN(5) +#define FN6 FN(6) +#define FN7 FN(7) + +#endif /* __SDIO_SPEC__H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdebug.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdebug.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdebug.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdebug.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,238 @@ +/***************************************************************************** +* +* Name: skdebug.h +* Project: Wireless LAN SDIO bus driver +* Version: $Revision: 1.1 $ +* Date: $Date: 2007/01/18 09:26:19 $ +* Purpose: +* +* +*****************************************************************************/ +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ +/***************************************************************************** +* +* History: +* $Log: skdebug.h,v $ +* Revision 1.1 2007/01/18 09:26:19 pweber +* Put under CVS control +* +* +*****************************************************************************/ + +#ifndef _SKDEBUG_H_ +#define _SKDEBUG_H_ +#ifdef WINNT +#include +#endif + +// #define DEBUG_VERBOSE 1 + +#define DBG_NONE 0x00000000 // No debug - all off. +#define DBG_ERROR 0x00000001 // Debug for ERRORS +#define DBG_WARNING 0x00000002 // Debug for Warnings. +#define DBG_LOAD 0x00000004 // Debug for driver load +#define DBG_PNP 0x00000008 +#define DBG_PWR 0x00000010 +#define DBG_IOCTL 0x00000020 +#define DBG_PDO 0x00000040 +#define DBG_IRQ 0x00000080 +#define DBG_W528D 0x00000100 +#define DBG_W528D_CMD52 0x00000200 +#define DBG_W528D_CMD53 0x00000400 + +#define DBG_T1 0x01000000 // Our various time stamps.. up to 6. +#define DBG_T2 0x02000000 // || +#define DBG_T3 0x04000000 // || +#define DBG_T4 0x08000000 // || +#define DBG_T5 0x10000000 // || +#define DBG_T6 0x20000000 // \/ +#define DBG_ALL 0xffffffff // All debug enabled. + +#define DBG_TIMESTAMPS ( DBG_T1 | DBG_T2 | DBG_T3 | DBG_T4 | DBG_T5 | DBG_T6 ) + +#define DBG_DEFAULT (DBG_NONE \ +| DBG_ERROR \ +| DBG_WARNING \ +| DBG_LOAD \ +) +/*** +| DBG_W528D_CMD52 \ +| DBG_W528D_CMD53 \ +| DBG_TIMESTAMPS \ +| DBG_PNP \ +| DBG_IRQ \ +| DBG_PDO \ +| DBG_PWR \ +| DBG_W528D \ +| DBG_LOAD \ +| DBG_IOCTL \ +| DBG_ERROR \ +| DBG_WARNING \ + +****/ + +#ifdef DBG +extern unsigned char lptRegImage1; +extern unsigned char lptRegImage2; +extern ULONG stdDebugLevel; +#ifdef WINNT +extern LARGE_INTEGER t1Time, t1LastTime, t1CurTime; +extern LARGE_INTEGER t2Time, t2LastTime, t2CurTime; +extern LARGE_INTEGER t3Time, t3LastTime, t3CurTime; +extern LARGE_INTEGER t4Time, t4LastTime, t4CurTime; +extern LARGE_INTEGER t5Time, t5LastTime, t5CurTime; +extern LARGE_INTEGER t6Time, t6LastTime, t6CurTime; +#endif // #ifdef WINNT +#endif // #ifdef DBG + +#ifdef WINNT +NTHALAPI + LARGE_INTEGER +KeQueryPerformanceCounter(OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL); + +extern LARGE_INTEGER isrTimeDelay; +#endif + +#ifdef DBG + +#define DBG_CRLF 0x00000000 // add some cr lfs before this message. +#define DBG_RAW 0x00000000 // raw debug output +#define DBG_DONTCARE (DBG_RAW | DBG_CRLF) // either of these by themselves should not cause debug to print. + +/** +#define LED_ON(x){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<(16+(x)));\ + ___ulVal |= ___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} +#define LED_OFF(x){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<(16+(x)));\ + ___ulVal &= ~___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} +**/ + +#define BUGPRINT(Str) DbgPrint Str +#ifdef WINNT + +#define KERN_DEBUG + +#define ENTER() +#define LEAVE() + +#define INITDEBUG() \ + KeQuerySystemTime(&t1Time); \ + KeQuerySystemTime(&t2Time); \ + KeQuerySystemTime(&t3Time); \ + KeQuerySystemTime(&t4Time); \ + KeQuerySystemTime(&t5Time); \ + KeQuerySystemTime(&t6Time); \ + KeQuerySystemTime(&t1CurTime); \ + KeQuerySystemTime(&t2CurTime); \ + KeQuerySystemTime(&t3CurTime); \ + KeQuerySystemTime(&t4CurTime); \ + KeQuerySystemTime(&t5CurTime); \ + KeQuerySystemTime(&t6CurTime); \ + KeQuerySystemTime(&t1LastTime); \ + KeQuerySystemTime(&t2LastTime); \ + KeQuerySystemTime(&t3LastTime); \ + KeQuerySystemTime(&t4LastTime); \ + KeQuerySystemTime(&t5LastTime); \ + KeQuerySystemTime(&t6LastTime); \ + +#define PrintMacro DbgPrint + +#define DBGPRINT(lvl, Str) \ + { \ + ULONG __lvl = lvl; \ + if ( stdDebugLevel & (__lvl & ~DBG_DONTCARE)) \ + { \ + if ( lvl & DBG_CRLF ) \ + { \ + PrintMacro("\n"); \ + } \ + KeQuerySystemTime(&t2CurTime); \ + PrintMacro("TS:%p:%d:%I64d - ",KeGetCurrentThread(),KeGetCurrentIrql(),(t2CurTime.QuadPart - t2LastTime.QuadPart)/10000); \ + t2LastTime.QuadPart = t2CurTime.QuadPart; \ + if ( __lvl & DBG_T1 ) \ + { \ + KeQuerySystemTime(&t1CurTime); \ + PrintMacro("T1:%I64d - ",t1CurTime.QuadPart - t1LastTime.QuadPart); \ + t1LastTime.QuadPart = t1CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T3 ) \ + { \ + KeQuerySystemTime(&t3CurTime); \ + PrintMacro("T3:%I64d - ",t3CurTime.QuadPart - t3LastTime.QuadPart); \ + t3LastTime.QuadPart = t3CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T4 ) \ + { \ + KeQuerySystemTime(&t4CurTime); \ + PrintMacro("T4:%I64d - ",t4CurTime.QuadPart - t4LastTime.QuadPart); \ + t4LastTime.QuadPart = t4CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T5 ) \ + { \ + KeQuerySystemTime(&t5CurTime); \ + PrintMacro("T5:%I64d - ",t5CurTime.QuadPart - t5LastTime.QuadPart); \ + t5LastTime.QuadPart = t5CurTime.QuadPart; \ + } \ + else if ( __lvl & DBG_T6) \ + { \ + KeQuerySystemTime(&t6CurTime); \ + PrintMacro("T6:%I64d - ",t6CurTime.QuadPart - t6LastTime.QuadPart); \ + t6LastTime.QuadPart = t6CurTime.QuadPart; \ + } \ + PrintMacro Str; \ + }} +#else // #ifdef WINNT + +#define ENTER() DBGPRINT(DBG_LOAD,( KERN_DEBUG "Enter: %s, %s:%i\n", __FUNCTION__, \ + __FILE__, __LINE__)) +#define LEAVE() DBGPRINT(DBG_LOAD,( KERN_DEBUG "Exit: %s, %s:%i\n", __FUNCTION__, \ + __FILE__, __LINE__)) + +#define PrintMacro printk + +#define INITDEBUG() + +#define DBGPRINT(lvl, Str) \ + { \ + ULONG __lvl = lvl; \ + if (stdDebugLevel & (__lvl & ~DBG_DONTCARE)) \ + { \ + PrintMacro Str ; \ + }} + +#endif // #ifdef WINNT +#else +#define DBGPRINT(lvl,Str) +#define INITDEBUG() +#define ENTER() +#define LEAVE() +#endif +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdrv1st.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdrv1st.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdrv1st.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdrv1st.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Name: skdrv1st.h + * Project: Wireless LAN, SDIO bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: Contains all defines system specific definitions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * $Log: skdrv1st.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ + +#ifndef __INC_SKDRV1ST_H +#define __INC_SKDRV1ST_H + +#define SDIO_BUS_DRIVER + +#ifdef WINNT + +// Windows specific stuff +#include +#include "stdio.h" + +#define UDELAY KeStallExecutionProcessor + +#define INTERLOCKED_INC(x) InterlockedIncrement((x)) +#define INTERLOCKED_DEC(x) InterlockedDecrement((x)) +#define ZERO_MEMORY( pBuf,len) RtlZeroMemory((pBuf),(len)) + +extern UNICODE_STRING RegistryPath; + +#else // #ifdef WINNT + +// Linux specific stuff + +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // kernel_thread +#include // memory manager +#include +#include + +// kernel specific inludes ++++++++++++++++++++++ + +#include /* for struct work_queue */ + +// defines ++++++++++++++++++++ + +// #define UDELAY udelay +#define UDELAY(x) + +#define INTERLOCKED_INC(x) (atomic_inc((x)),atomic_read((x))) +#define INTERLOCKED_DEC(x) (atomic_dec((x)),atomic_read((x))) +#define ZERO_MEMORY( pBuf,len) memset((pBuf),0,(len)); + +// 2.6 : task queue mechanism +extern struct work_struct sdiobus_wq; + +#endif // !#ifdef WINNT + +#include "../h/sktypes.h" +#include "../h/sdio.h" + +#define MRVL_DEVICE_NAME "MrvlSdioBus" + +/* defines ********************************************************************/ +/* typedefs *******************************************************************/ +/* function prototypes ********************************************************/ + +#endif /* __INC_SKDRV1ST_H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdrv2nd.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdrv2nd.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skdrv2nd.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skdrv2nd.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Name: skdrv2nd.h + * Project: Wireless LAN SDIO Bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: Contains all defines system specific definitions + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of Marvell + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skdrv2nd.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * + * + * + ******************************************************************************/ + +#ifndef __INC_SKDRV2ND_H +#define __INC_SKDRV2ND_H + +#include "../h/skdebug.h" + +#ifdef WINNT +#include +#include "../h/public.h" +#endif + +#include "../../sdioapi/h/sdio_if.h" +#include "../h/sdiobus.h" +#include "../h/stdhost.h" +#include "../h/skisr.h" +#include "../h/sdio.h" + +/* defines ********************************************************************/ + +/* function prototypes ********************************************************/ +/* Macros ************************************************************/ + +#endif /* __INC_SKDRV2ND_H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skisr.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skisr.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/skisr.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/skisr.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Name: skisr.h + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: This module handles the interrupts. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skisr.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ +#ifdef WINNT + +VOID +SDIOBus_Dpc(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, IN PVOID SystemArgument2); + +BOOLEAN SDIOBus_Isr(IN PKINTERRUPT Interrupt, IN PVOID Context); + +#else // #ifdef WINNT + +void SDIOBus_Dpc(unsigned long arg); + +irqreturn_t SDIOBus_Isr(int irq, void *dev_id, struct pt_regs *regs); + +#endif // !#ifdef WINNT diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sktypes.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sktypes.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/sktypes.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/sktypes.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,132 @@ +/****************************************************************************** + * + * Name: sktypes.h + * Project: Wireless LAN, SDIO Bus driver + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: Define data types for SDIO bus driver + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell. + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of Marvell. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sktypes.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * + * + * + ******************************************************************************/ + +#ifndef __INC_SKTYPES_H +#define __INC_SKTYPES_H + +/* defines ********************************************************************/ + +/* + * Data types with a specific size. 'I' = signed, 'U' = unsigned. + */ +#ifdef WINNT +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef char *caddr_t; +#define SK_I8 CHAR +#define SK_U8 UCHAR +#define SK_I16 SHORT +#define SK_U16 USHORT +#define SK_I32 LONG +#define SK_U32 ULONG +#define SK_U64 long long + +#else // #ifdef WINNT +#define SK_I8 s8 +#define SK_U8 u8 +#define SK_I16 s16 +#define SK_U16 u16 +#define SK_I32 s32 +#define SK_U32 u32 +#define SK_U64 u64 +#endif + +#define SK_UPTR SK_U32 /* casting pointer <-> integral */ + +#define SK_CONSTI64(x) (x##L) +#define SK_CONSTU64(x) (x##UL) +/* + * Boolean type. + */ +#define SK_BOOL SK_U8 +#define SK_FALSE (SK_BOOL)0 +#define SK_TRUE (SK_BOOL)(!SK_FALSE) + +#ifndef WINNT + +#define VOID void +#define PVOID VOID* +#define ULONG SK_U32 +#define USHORT SK_U16 +#define UCHAR SK_U8 +#define PUCHAR SK_U8* +#define BOOLEAN SK_BOOL +#define IN +#define OUT + +typedef struct _GUID +{ + SK_U32 Data1; + SK_U16 Data2; + SK_U16 Data3; + SK_U8 Data4[8]; +} GUID, *PGUID; + +#define COMPARE_GUID(guid1,guid2) (\ +((guid1).Data1==(guid2).Data1) && \ +((guid1).Data2==(guid2).Data2) && \ +((guid1).Data3==(guid2).Data3) && \ +(memcmp((guid1).Data4,(guid2).Data4,8)==0)) + +#define SHOW_GUID(guid) { \ +int i; \ +printk("\n{ 0x%8.08X, 0x%4.04X, 0x%4.04X,{",(guid).Data1,(guid).Data2,(guid).Data3);\ +for (i=0;i < 8;i++){printk("0x%2.02X ",(guid).Data4[i]);} \ +printk("}\n");} + +#endif + +#define DEFINE_EXTERN_GUID(name) \ + extern const GUID name + +#define DEFINE_INIT_GUID(name, l, w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ + const GUID name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } + +/* typedefs *******************************************************************/ + +/* function prototypes ********************************************************/ + +#endif /* __INC_SKTYPES_H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/stdhost.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/stdhost.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/h/stdhost.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/h/stdhost.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,518 @@ +/****************************************************************************** + * + * Name: stdhost.h + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:26:19 $ + * Purpose: This module handles the SDIO Standard Host Interface. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: stdhost.h,v $ + * Revision 1.1 2007/01/18 09:26:19 pweber + * Put under CVS control + * + * + ******************************************************************************/ + +// pweber 17.08.2005 taken from eagledev.h +typedef enum +{ + // card is in full power + PS_STATE_FULL_POWER, + // PS mode, but card is ready for TX + PS_STATE_WAKEUP, + // PS Mode, card is not ready for TX + PS_STATE_SLEEP, + // SLEEP event is already received, but have not sent confirm yet + PS_STATE_SLEEP_PENDING, +} PS_STATE; + +#define MAX_BUS_ERRORS 10 + +// #define SD_BLOCK_SIZE 32 + +#define DEBUG_BREAK_CMD53_RD 0x00000001 +#define DEBUG_BREAK_CMD53_WR 0x00000002 +#define DEBUG_DISABLE_HW_WORKAROUND_RD 0x00000004 +#define DEBUG_DISABLE_HW_WORKAROUND_WR 0x00000008 +#define DEBUG_SHOW_REG_10_14 0x00000010 +#define DEBUG_USE_RD_DMA 0x00000100 +#define DEBUG_USE_WR_DMA 0x00000200 +#define DEBUG_BREAK_START_FDO 0x80000000 + +// SDIO CMD Macros +#define MAKE_SDIO_OFFSET(x) ((SK_U32)((SK_U32)(x)<<9)) +#define MAKE_SDIO_OP_CODE(x) ((SK_U32)((SK_U32)(x)<<26)) +#define MAKE_SDIO_BLOCK_MODE(x) ((SK_U32)((SK_U32)(x)<<27)) +#define MAKE_SDIO_FUNCTION(x) ((SK_U32)((SK_U32)(x)<<28)) +#define MAKE_SDIO_DIR(x) ((SK_U32)((SK_U32)(x)<<31)) + +// SD Host Standard Register +#define STDHOST_SYSTEM_ADDRESS 0x00 // System Address 4 bytes +#define STDHOST_BLOCK_SIZE 0x04 // 2 bytes +#define STDHOST_BLOCK_COUNT 0x06 // 2 bytes +#define STDHOST_CMD_ARGUMENT 0x08 // 4 bytes -> bit 39 - 8 of SDIO CMD +#define STDHOST_TRANSFER_MODE 0x0C // 2 bytes +#define STDHOST_MULTI_BLOCK_SELECT (1<<5) +#define STDHOST_READ_DIR_SELECT (1<<4) +#define STDHOST_AUTO_CMD12_ENA (1<<2) +#define STDHOST_BLOCK_COUNT_ENA (1<<1) +#define STDHOST_DMA_ENA (1<<0) + +#define STDHOST_COMMAND 0x0E // 2 bytes +#define STDHOST_CMD_TYPE_NORMAL 0x00 +#define STDHOST_CMD_TYPE_SUSPEND 0x01 +#define STDHOST_CMD_TYPE_RESUME 0x02 +#define STDHOST_CMD_TYPE_ABORT 0x03 +#define STDHOST_CMD_TYPE_MASK 0x03 +#define MK_CMD_TYPE(x) ((x)<<6) +#define MK_CMD(x) ((x)<<8) +#define MAX_WAIT_COMMAND_COMPLETE 1000 + +#define STDHOST_CMD_DATA_PRESENT (1<<5) +#define STDHOST_CMD_INDEX_CHK_ENA (1<<4) +#define STDHOST_CMD_CRC_CHK_ENA (1<<3) +#define STDHOST_RESP_TYPE_NONE 0x00 +#define STDHOST_RESP_TYPE_R2 0x01 +#define STDHOST_RESP_TYPE_R1 0x02 +#define STDHOST_RESP_TYPE_R3 0x02 +#define STDHOST_RESP_TYPE_R4 0x02 +#define STDHOST_RESP_TYPE_R5 0x02 +#define STDHOST_RESP_TYPE_R6 0x02 +#define STDHOST_RESP_TYPE_R1b 0x03 +#define STDHOST_RESP_TYPE_R5b 0x03 + +#define STDHOST_RESP_BITS_31_0 0x10 // 4 bytes +#define STDHOST_RESP_BITS_63_32 0x14 // 4 bytes +#define STDHOST_RESP_BITS_95_64 0x18 // 4 bytes +#define STDHOST_RESP_BITS_127_96 0x1C // 4 bytes + +#define GET_BITS_135_128(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_127_120(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_119_112(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_111_104(x) ((SK_U8)(x)) +#define GET_BITS_103_96(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_95_88(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_87_80(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_79_72(x) ((SK_U8)(x)) +#define GET_BITS_71_64(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_63_56(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_55_48(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_47_40(x) ((SK_U8)(x)) +#define GET_BITS_39_32(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_31_24(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_23_16(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_15_08(x) ((SK_U8)(x)) + +/* +#define GET_BITS_135_128(x) ((SK_U8)(x)) +#define GET_BITS_127_120(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_119_112(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_111_104(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_103_96(x) ((SK_U8)(x)) +#define GET_BITS_95_88(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_87_80(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_79_72(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_71_64(x) ((SK_U8)(x)) +#define GET_BITS_63_56(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_55_48(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_47_40(x) ((SK_U8)((SK_U32)(x)>>24)) +#define GET_BITS_39_32(x) ((SK_U8)(x)) +#define GET_BITS_31_24(x) ((SK_U8)((SK_U32)(x)>>8)) +#define GET_BITS_23_16(x) ((SK_U8)((SK_U32)(x)>>16)) +#define GET_BITS_15_08(x) ((SK_U8)((SK_U32)(x)>>24)) +*/ + +#define STDHOST_DATA_PORT 0x20 // 4 bytes + +#define STDHOST_PRESENT_STATE 0x24 // 4 bytes +#define STDHOST_STATE_CMD_LINE_LVL (1<<24) +#define STDHOST_STATE_DAT3_LINE_LVL (1<<23) +#define STDHOST_STATE_DAT2_LINE_LVL (1<<22) +#define STDHOST_STATE_DAT1_LINE_LVL (1<<21) +#define STDHOST_STATE_DAT0_LINE_LVL (1<<20) +#define STDHOST_STATE_WRITE_PROTECT_LVL (1<<19) +#define STDHOST_STATE_CARD_DETECT_LVL (1<<18) +#define STDHOST_STATE_CARD_STATE_STABLE (1<<17) +#define STDHOST_STATE_CARD_INSERTED (1<<16) +#define STDHOST_STATE_BUFFER_RD_ENABLE (1<<11) +#define STDHOST_STATE_BUFFER_WR_ENABLE (1<<10) +#define STDHOST_STATE_RD_TRANSFER_ACTIVE (1<<9) +#define STDHOST_STATE_WR_TRANSFER_ACTIVE (1<<8) +#define STDHOST_STATE_DAT_LINE_ACTIVE (1<<2) +#define STDHOST_STATE_CMD_INHIB_DAT (1<<1) +#define STDHOST_STATE_CMD_INHIB_CMD (1<<0) +#define MAX_WAIT_COMMAND_INHIBIT 1000 + +#define STDHOST_HOST_CTRL 0x28 // 1 byte +#define STDHOST_HIGH_SPEED_ENA (1<<2) +#define STDHOST_4_BIT_ENA (1<<1) +#define STDHOST_LED_ON (1<<0) + +#define STDHOST_POWER_CTRL 0x29 // 1 byte +#define STDHOST_VOLTAGE_3_3_V 0x07 +#define STDHOST_VOLTAGE_3_0_V 0x06 +#define STDHOST_VOLTAGE_1_8_V 0x05 +#define MK_VOLTAGE(x) ((x)<<1) +#define STDHOST_POWER_ON (1<<0) + +#define STDHOST_BLOCK_GAP_CTRL 0x2A // 1 byte +#define STDHOST_WAKEUP_CTRL 0x2B // 1 byte +#define STDHOST_WAKEUP_ON_CARD_REMOVE 0x04 +#define STDHOST_WAKEUP_ON_CARD_INSERT 0x02 +#define STDHOST_WAKEUP_ON_CARD_IRQ 0x01 + +#define STDHOST_CLOCK_CTRL 0x2C // 2 byte +#define STDHOST_CLOCK_DIV_BASE_CLK 0x00 +#define STDHOST_CLOCK_DIV_2 0x01 +#define STDHOST_CLOCK_DIV_4 0x02 +#define STDHOST_CLOCK_DIV_8 0x04 +#define STDHOST_CLOCK_DIV_16 0x08 +#define STDHOST_CLOCK_DIV_32 0x10 +#define STDHOST_CLOCK_DIV_64 0x20 +#define STDHOST_CLOCK_DIV_128 0x40 +#define STDHOST_CLOCK_DIV_256 0x80 +#define MK_CLOCK(x) ((x)<<8) +#define STDHOST_CLOCK_ENA (1<<2) +#define STDHOST_INTERNAL_CLK_STABLE (1<<1) +#define STDHOST_INTERNAL_CLK_ENA (1<<0) +#define MAX_WAIT_CLOCK_STABLE 1000 + +#define STDHOST_TIMEOUT_CTRL 0x2E // 1 byte +#define STDHOST_SW_RESET 0x2F // 1 byte +#define STDHOST_SW_RESET_DAT_LINE (1<<2) +#define STDHOST_SW_RESET_CMD_LINE (1<<1) +#define STDHOST_SW_RESET_ALL (1<<0) + +#define STDHOST_NORMAL_IRQ_STATUS 0x30 // 2 byte +#define STDHOST_NORMAL_IRQ_ERROR (1<<15) +#define STDHOST_NORMAL_IRQ_CARD (1<<8) +#define STDHOST_NORMAL_IRQ_CARD_OUT (1<<7) +#define STDHOST_NORMAL_IRQ_CARD_IN (1<<6) +#define STDHOST_NORMAL_IRQ_BUF_RD_RDY (1<<5) +#define STDHOST_NORMAL_IRQ_BUF_WR_RDY (1<<4) +#define STDHOST_NORMAL_IRQ_DMA (1<<3) +#define STDHOST_NORMAL_IRQ_BLOCK_GAP (1<<2) +#define STDHOST_NORMAL_IRQ_TRANS_COMPLETE (1<<1) +#define STDHOST_NORMAL_IRQ_CMD_COMPLETE (1<<0) + +#define STDHOST_ERROR_IRQ_STATUS 0x32 // 2 byte +#define STDHOST_ERROR_IRQ_VENDOR (0x0F<<12) +#define STDHOST_ERROR_IRQ_GPI_1 (1<<15) +#define STDHOST_ERROR_IRQ_GPI_0 (1<<14) +#define STDHOST_ERROR_IRQ_AUTO_CMD12 (1<<8) +#define STDHOST_ERROR_IRQ_CURRENT_LIMIT (1<<7) +#define STDHOST_ERROR_IRQ_DATA_END_BIT (1<<6) +#define STDHOST_ERROR_IRQ_DATA_CRC (1<<5) +#define STDHOST_ERROR_IRQ_DATA_TIMEOUT (1<<4) +#define STDHOST_ERROR_IRQ_CMD_INDEX (1<<3) +#define STDHOST_ERROR_IRQ_CMD_END_BIT (1<<2) +#define STDHOST_ERROR_IRQ_CMD_CRC (1<<1) +#define STDHOST_ERROR_IRQ_CMD_TIMEOUT (1<<0) + +#define STDHOST_NORMAL_IRQ_STATUS_ENABLE 0x34 // 2 byte +#define STDHOST_NORMAL_IRQ_CARD_ENA (1<<8) +#define STDHOST_NORMAL_IRQ_CARD_OUT_ENA (1<<7) +#define STDHOST_NORMAL_IRQ_CARD_IN_ENA (1<<6) +#define STDHOST_NORMAL_IRQ_BUF_RD_RDY_ENA (1<<5) +#define STDHOST_NORMAL_IRQ_BUF_WR_RDY_ENA (1<<4) +#define STDHOST_NORMAL_IRQ_DMA_ENA (1<<3) +#define STDHOST_NORMAL_IRQ_BLOCK_GAP_ENA (1<<2) +#define STDHOST_NORMAL_IRQ_TRANS_COMPLETE_ENA (1<<1) +#define STDHOST_NORMAL_IRQ_CMD_COMPLETE_ENA (1<<0) + +#define STDHOST_ERROR_IRQ_STATUS_ENABLE 0x36 // 2 byte +#define STDHOST_ERROR_IRQ_VENDOR_ENA (0x0F<<12) +#define STDHOST_ERROR_IRQ_AUTO_CMD12_ENA (1<<8) +#define STDHOST_ERROR_IRQ_CURRENT_LIMIT_ENA (1<<7) +#define STDHOST_ERROR_IRQ_DATA_END_BIT_ENA (1<<6) +#define STDHOST_ERROR_IRQ_DATA_CRC_ENA (1<<5) +#define STDHOST_ERROR_IRQ_DATA_TIMEOUT_ENA (1<<4) +#define STDHOST_ERROR_IRQ_CMD_INDEX_ENA (1<<3) +#define STDHOST_ERROR_IRQ_CMD_END_BIT_ENA (1<<2) +#define STDHOST_ERROR_IRQ_CMD_CRC_ENA (1<<1) +#define STDHOST_ERROR_IRQ_CMD_TIMEOUT_ENA (1<<0) + +#define STDHOST_NORMAL_IRQ_SIGNAL_ENABLE 0x38 // 2 byte +#define STDHOST_NORMAL_IRQ_ALL_SIG_ENA 0xFFFF +#define STDHOST_NORMAL_IRQ_CARD_SIG_ENA (1<<8) +#define STDHOST_NORMAL_IRQ_CARD_OUT_SIG_ENA (1<<7) +#define STDHOST_NORMAL_IRQ_CARD_IN_SIG_ENA (1<<6) +#define STDHOST_NORMAL_IRQ_BUF_RD_RDY_SIG_ENA (1<<5) +#define STDHOST_NORMAL_IRQ_BUF_WR_RDY_SIG_ENA (1<<4) +#define STDHOST_NORMAL_IRQ_DMA_SIG_ENA (1<<3) +#define STDHOST_NORMAL_IRQ_BLOCK_GAP_SIG_ENA (1<<2) +#define STDHOST_NORMAL_IRQ_TRANS_COMPLETE_SIG_ENA (1<<1) +#define STDHOST_NORMAL_IRQ_CMD_COMPLETE_SIG_ENA (1<<0) + +/* +#define STDHOST_NORMAL_IRQ_CARD_ALL_ENA ( STDHOST_NORMAL_IRQ_CARD_OUT_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_IN_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_SIG_ENA) +*/ + +/* +#define STDHOST_NORMAL_IRQ_CARD_ALL_ENA ( STDHOST_NORMAL_IRQ_CARD_OUT_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_IN_SIG_ENA | \ + STDHOST_NORMAL_IRQ_TRANS_COMPLETE_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_SIG_ENA) +*/ + /**/ +#define STDHOST_NORMAL_IRQ_CARD_ALL_ENA ( \ + STDHOST_NORMAL_IRQ_CARD_OUT_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_IN_SIG_ENA | \ + STDHOST_NORMAL_IRQ_TRANS_COMPLETE_SIG_ENA | \ + STDHOST_NORMAL_IRQ_CARD_SIG_ENA) + /**/ +#define STDHOST_ERROR_IRQ_SIGNAL_ENABLE 0x3A // 2 byte +#define STDHOST_ERROR_IRQ_VENDOR_SIG_ENA (0x0F<<12) +#define STDHOST_ERROR_IRQ_AUTO_CMD12_SIG_ENA (1<<8) +#define STDHOST_ERROR_IRQ_CURRENT_LIMIT_SIG_ENA (1<<7) +#define STDHOST_ERROR_IRQ_DATA_END_BIT_SIG_ENA (1<<6) +#define STDHOST_ERROR_IRQ_DATA_CRC_SIG_ENA (1<<5) +#define STDHOST_ERROR_IRQ_DATA_TIMEOUT_SIG_ENA (1<<4) +#define STDHOST_ERROR_IRQ_CMD_INDEX_SIG_ENA (1<<3) +#define STDHOST_ERROR_IRQ_CMD_END_BIT_SIG_ENA (1<<2) +#define STDHOST_ERROR_IRQ_CMD_CRC_SIG_ENA (1<<1) +#define STDHOST_ERROR_IRQ_CMD_TIMEOUT_SIG_ENA (1<<0) +#define STDHOST_AUTO_CMD12_ERROR_STATUS 0x3C // 2 byte +#define STDHOST_CAPABILITIES 0x40 // 4 byte +#define STDHOST_CAP_VOLTAGE_1_8 (1<<26) +#define STDHOST_CAP_VOLTAGE_3_0 (1<<25) +#define STDHOST_CAP_VOLTAGE_3_3 (1<<24) +#define STDHOST_CAP_SUSPENSE_RESUME (1<<23) +#define STDHOST_CAP_DMA (1<<22) +#define STDHOST_CAP_HIGH_SPEED (1<<21) +#define STDHOST_CAP_MAX_BLOCK_LEN (0x03<<16) +#define STDHOST_CAP_MAX_BLOCK_512 (0x00<<16) +#define STDHOST_CAP_MAX_BLOCK_1024 (0x01<<16) +#define STDHOST_CAP_MAX_BLOCK_2048 (0x02<<16) +#define STDHOST_CAP_BASE_CLOCK_FREQ (0x3F<<8) +#define GET_CAP_BASE_CLOCK_FREQ(x) (SK_U8)(((x)>>8)&0x000000FF) +#define STDHOST_CAP_TIMEOUT_CLOCK_UNIT (1<<7) +#define STDHOST_CAP_TIMEOUT_CLOCK_UNIT_MHZ (1<<7) +#define STDHOST_CAP_TIMEOUT_CLOCK_FREQ 0x3F +#define STDHOST_CAPABILITIES_RESERVED 0x44 // 4 byte +#define STDHOST_MAX_CURRENT_CAP 0x48 // 4 byte +#define STDHOST_MAX_CURRENT_CAP_1_8_V (0xFF<<16) +#define GET_MAX_CURRENT_CAP_1_8_V(x) (((x)>>16)&0x000000FF) +#define STDHOST_MAX_CURRENT_CAP_3_0_V (0xFF<<8) +#define GET_MAX_CURRENT_CAP_3_0_V(x) (((x)>>8)&0x000000FF) +#define STDHOST_MAX_CURRENT_CAP_3_3_V 0xFF +#define GET_MAX_CURRENT_CAP_3_3_V(x) ((x)&0x000000FF) +#define CALC_MAX_CURRENT_IN_MA(x) ((x)*4) +#define STDHOST_MAX_CURRENT_CAP_RESERVED 0x4C // 4 byte +#define STDHOST_SLOT_IRQ_STATUS 0xFC // 2 byte +#define STDHOST_SLOT_IRQ_SLOT_0 0x01 +#define STDHOST_SLOT_IRQ_SLOT_1 0x02 +#define STDHOST_SLOT_IRQ_SLOT_2 0x04 +#define STDHOST_SLOT_IRQ_SLOT_3 0x08 +#define STDHOST_SLOT_IRQ_SLOT_4 0x10 +#define STDHOST_SLOT_IRQ_SLOT_5 0x20 +#define STDHOST_SLOT_IRQ_SLOT_6 0x40 +#define STDHOST_SLOT_IRQ_SLOT_7 0x80 +#define STDHOST_HOST_CONTROLLER_VERSION 0xFE // 2 byte +#define GET_VENDOR_VERSION_NR(x) ((x)>>8) +#define GET_SPEC_VERSION_NR(x) ((x)&0x00FF) +// FPGA specific registers +#define FPGA_CARD_REVISION 0x210 +#define FPGA_CARD_REV_1_0 0x10 +#define FPGA_CARD_REV_1_1 0x11 +#define FPGA_CHIP_REVISION 0x211 +#define FPGA_CHIP_REV_1_0 0x10 // SDIO/SPI +#define FPGA_CHIP_REV_1_1 0x11 // SDIO/SPI/G-SPI +#define FPGA_CHIP_REV_2_0 0x20 // SDIO/SPI/G-SPI/DMA +#define FPGA_CONFIG_ID 0x212 +#define FPGA_CONFIG_3_3_V (1<<0) +#define FPGA_CONFIG_2_5_V (1<<1) +#define FPGA_CONFIG_1_8_V (1<<2) +#define FPGA_POWER_REG_DATA 0x20C +#define FPGA_POWER_REG_3_3_V 0xEF +#define FPGA_POWER_REG_2_5_V 0xDC +#define FPGA_POWER_REG_1_8_V 0xCC +#define FPGA_POWER_REG_CMD 0x20D +#define FPGA_POWER_REG_CMD_START 0x80 +#define FPGA_POWER_REG_STATUS 0x20E +#define FPGA_POWER_REG_STABLE (1<<0) +#define FPGA_POWER_REG_1_8_V_MIN 0xBC // 1.54 V +#define FPGA_POWER_REG_1_8_V_MAX 0xD9 // 2.31 V +#define FPGA_POWER_REG_2_5_V_MIN 0xCF // 1.98 V +#define FPGA_POWER_REG_2_5_V_MAX 0xEC // 3.08 V +#define FPGA_POWER_REG_3_3_V_MIN 0xE8 // 2.70 V +#define FPGA_POWER_REG_3_3_V_MAX 0xEF // 3.30 V +#define FPGA_POWER_REG_0_7_V 0x88 // 0.72 V +#define FPGA_POWER_REG_0_8_V 0x8B // 0.78 V +#define FPGA_POWER_REG_0_9_V 0x98 // 0.90 V +#define FPGA_POWER_REG_1_0_V 0x9B // 0.97 V +#define FPGA_POWER_REG_1_1_V 0xA8 // 1.08 V +#define FPGA_POWER_REG_1_2_V 0xAB // 1.17 V +#define FPGA_POWER_REG_1_2_5_V 0xAC // 1.23 V +#define FPGA_POWER_REG_1_3_V 0xAF // 1.32 V +#define FPGA_POWER_REG_1_4_V 0xBA // 1.42 V +#define FPGA_POWER_REG_1_5_V 0xBC // 1.53 V +#define FPGA_POWER_REG_1_6_V 0xC8 // 1.62 V +#define FPGA_POWER_REG_1_8_V 0xCC // 1.84 V +#define FPGA_POWER_REG_2_0_V 0xCF // 1.98 V +#define FPGA_POWER_REG_2_2_V 0xD8 // 2.25 V +#define FPGA_POWER_REG_2_4_V 0xDB // 2.43 V +#define FPGA_POWER_REG_2_6_V 0xDD // 2.62 V +#define FPGA_POWER_REG_2_7_V 0xDF // 2.75 V +#define FPGA_POWER_REG_2_9_V 0xEB // 2.92 V +#define FPGA_POWER_REG_3_1_V 0xED // 3.15 V +#define FPGA_POWER_REG_3_3_V 0xEF // 3.30 V +#define FPGA_POWER_STEPS 20 +//[mb] 300 is a good value for 3.3V +#define FPGA_POWER_RAMP_DELAY 300 +#define FPGA_POWER_VAL_ENUM { \ + FPGA_POWER_REG_0_7_V, \ + FPGA_POWER_REG_0_8_V, \ + FPGA_POWER_REG_0_9_V, \ + FPGA_POWER_REG_1_0_V, \ + FPGA_POWER_REG_1_1_V, \ + FPGA_POWER_REG_1_2_V, \ + FPGA_POWER_REG_1_2_5_V, \ + FPGA_POWER_REG_1_3_V, \ + FPGA_POWER_REG_1_4_V, \ + FPGA_POWER_REG_1_5_V, \ + FPGA_POWER_REG_1_6_V, \ + FPGA_POWER_REG_1_8_V, \ + FPGA_POWER_REG_2_0_V, \ + FPGA_POWER_REG_2_2_V, \ + FPGA_POWER_REG_2_4_V, \ + FPGA_POWER_REG_2_6_V, \ + FPGA_POWER_REG_2_7_V, \ + FPGA_POWER_REG_2_9_V, \ + FPGA_POWER_REG_3_1_V, \ + FPGA_POWER_REG_3_3_V} +#define SK_SLOT_0 0 +#define SK_SLOT_1 1 +#define SK_BAR( _pObj, _nr ) ((PCOMMON_DEVICE_DATA)(_pObj)->IOBase[_nr]) +// +// PCI memory mapped I/O access routines +// +#define MEM_WRITE_UCHAR(_pObj,_base, _offset, _value) *(SK_U8 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) = (SK_U8)(_value) +#define MEM_WRITE_USHORT(_pObj,_base, _offset, _value) *(SK_U16 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) = (SK_U16)(_value) +#define MEM_WRITE_ULONG(_pObj,_base, _offset, _value) *(SK_U32 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) = (SK_U32)(_value) +#define MEM_READ_UCHAR(_pObj,_base, _offset, _pBuf) *(SK_U8 *)(_pBuf) = *(volatile SK_U8 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) +#define MEM_READ_USHORT(_pObj,_base, _offset, _pBuf) *(SK_U16 *)(_pBuf) = *(volatile SK_U16 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) +#define MEM_READ_ULONG(_pObj,_base, _offset, _pBuf) *(SK_U32 *)(_pBuf) = *(volatile SK_U32 *)(((SK_U32)(SK_BAR((_pObj),(_base))))+(_offset)) +void SDHost_Init(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_isCardPresent(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_InitializeCard(PCOMMON_DEVICE_DATA pDev); +VOID SDHost_EnableInterrupt(PCOMMON_DEVICE_DATA pDev, SK_U16 mask); +VOID SDHost_DisableInterrupt(PCOMMON_DEVICE_DATA pDev, SK_U16 mask); +VOID SDHost_if_EnableInterrupt(PCOMMON_DEVICE_DATA pDev); +VOID SDHost_if_DisableInterrupt(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_ReadOCR(PCOMMON_DEVICE_DATA pDev, SK_U8 * pOcr); +SK_BOOL SDHost_SendCmd(PCOMMON_DEVICE_DATA pDev, SK_U8 cmd, SK_U32 arg, + SK_U16 transferMode, SK_U32 * pulResp); +VOID SDHost_SetCardOutEvent(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_WriteOCR(PCOMMON_DEVICE_DATA pDev, SK_U8 * pOcr); +SK_BOOL SDHost_ReadRCA(PCOMMON_DEVICE_DATA pDev, SK_U8 * pRca); +SK_BOOL SDHost_SendAbort(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_CMD52_Write(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 Data); +SK_BOOL SDHost_CMD52_Read(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 * pReturnData); +SK_BOOL SDHost_ReadCIS(PCOMMON_DEVICE_DATA pDev, SK_U8 function_number, + SK_U8 cistpl, SK_U8 * pBuf, SK_U32 * length); +SK_BOOL SDHost_CMD53_Write(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 mode, SK_U8 opcode, + SK_U8 * pData, SK_U32 Count); +SK_BOOL SDHost_CMD53_Write_DMA(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 mode, + SK_U8 opcode, SK_U8 * pData, SK_U32 Count); +SK_BOOL SDHost_CMD53_Read(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 mode, SK_U8 opcode, + SK_U8 * pData, SK_U32 Count); +SK_BOOL SDHost_CMD53_Read_DMA(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 mode, SK_U8 opcode, + SK_U8 * pData, SK_U32 Count); + +SK_BOOL SDHost_CMD53_WriteEx(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, + SK_U8 opcode, + SK_U8 * pData, SK_U32 Count, SK_U32 blksz); + +SK_BOOL SDHost_CMD53_ReadEx(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, + SK_U8 opcode, + SK_U8 * pData, SK_U32 Count, SK_U32 blksz); + +SK_BOOL SDHost_disable_host_int(PCOMMON_DEVICE_DATA pDev, + SK_U8 function_number, SK_U8 mask); +SK_BOOL SDHost_enable_host_int(PCOMMON_DEVICE_DATA pDev, + SK_U8 function_number, SK_U8 mask); +SK_U32 SDHost_send_cmd(PCOMMON_DEVICE_DATA pDev, SK_U8 * payload, + SK_U32 length, SK_BOOL wait_status); +VOID SDHost_ErrorRecovery(PCOMMON_DEVICE_DATA pDev); +SK_BOOL SDHost_lockInterface(PCOMMON_DEVICE_DATA pDev); +VOID SDHost_unlockInterface(PCOMMON_DEVICE_DATA pDev); +VOID SDHost_SetLed(PCOMMON_DEVICE_DATA pDev, SK_U8 led, SK_U8 on); +VOID SDHost_PsState(PCOMMON_DEVICE_DATA pDev, SK_U8 State); // pweber 17.08.2005 +VOID SDHost_SetGPO(PCOMMON_DEVICE_DATA pDev, SK_U8 on); // mmoser 2007-02-20 +SK_U32 SDHost_wait_event(PCOMMON_DEVICE_DATA pDev, SDHOST_EVENT * pEvt, + SK_U32 to); +VOID SDHost_SetClock(PCOMMON_DEVICE_DATA pDev, SK_U8 on); +VOID SDHost_SetBusWidth(PCOMMON_DEVICE_DATA pDev, SK_U8 width); +VOID SDHost_SetClockSpeed(PCOMMON_DEVICE_DATA pDev, SK_U32 bus_freq); + +#define LED_ON(x){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<(16+(x)));\ + ___ulVal |= ___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} +#define LED_OFF(x){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<(16+(x)));\ + ___ulVal &= ~___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} + +#define GPO_ON(){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<24);\ + ___ulVal |= ___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} +#define GPO_OFF(){\ +SK_U32 ___ulVal,___ulMask;\ + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &___ulVal);\ + ___ulMask = (1<<24);\ + ___ulVal &= ~___ulMask;\ + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, ___ulVal);\ +} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/macrodef.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/macrodef.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/macrodef.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/macrodef.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,189 @@ +/******************* (c) Marvell Semiconductor, Inc., 2001 ******************** + * + * $HEADER% + * + * Purpose: This file contains the macro and symbol definitions + * + * Notes: + * + *****************************************************************************/ + +#ifndef _MACRODEF_H_ +#define _MACRODEF_H_ + +/* +=============================================================================== + PUBLIC DEFINITIONS +=============================================================================== +*/ + +// +// Bit definition +// +#define DW_BIT_0 0x00000001 +#define DW_BIT_1 0x00000002 +#define DW_BIT_2 0x00000004 +#define DW_BIT_3 0x00000008 +#define DW_BIT_4 0x00000010 +#define DW_BIT_5 0x00000020 +#define DW_BIT_6 0x00000040 +#define DW_BIT_7 0x00000080 +#define DW_BIT_8 0x00000100 +#define DW_BIT_9 0x00000200 +#define DW_BIT_10 0x00000400 +#define DW_BIT_11 0x00000800 +#define DW_BIT_12 0x00001000 +#define DW_BIT_13 0x00002000 +#define DW_BIT_14 0x00004000 +#define DW_BIT_15 0x00008000 +#define DW_BIT_16 0x00010000 +#define DW_BIT_17 0x00020000 +#define DW_BIT_18 0x00040000 +#define DW_BIT_19 0x00080000 +#define DW_BIT_20 0x00100000 +#define DW_BIT_21 0x00200000 +#define DW_BIT_22 0x00400000 +#define DW_BIT_23 0x00800000 +#define DW_BIT_24 0x01000000 +#define DW_BIT_25 0x02000000 +#define DW_BIT_26 0x04000000 +#define DW_BIT_27 0x08000000 +#define DW_BIT_28 0x10000000 +#define DW_BIT_29 0x20000000 +#define DW_BIT_30 0x30000000 +#define DW_BIT_31 0x80000000 + +#define W_BIT_0 0x0001 +#define W_BIT_1 0x0002 +#define W_BIT_2 0x0004 +#define W_BIT_3 0x0008 +#define W_BIT_4 0x0010 +#define W_BIT_5 0x0020 +#define W_BIT_6 0x0040 +#define W_BIT_7 0x0080 +#define W_BIT_8 0x0100 +#define W_BIT_9 0x0200 +#define W_BIT_10 0x0400 +#define W_BIT_11 0x0800 +#define W_BIT_12 0x1000 +#define W_BIT_13 0x2000 +#define W_BIT_14 0x4000 +#define W_BIT_15 0x8000 + +#define B_BIT_0 0x01 +#define B_BIT_1 0x02 +#define B_BIT_2 0x04 +#define B_BIT_3 0x08 +#define B_BIT_4 0x10 +#define B_BIT_5 0x20 +#define B_BIT_6 0x40 +#define B_BIT_7 0x80 + +/* +=============================================================================== + MACRO DEFINITIONS +=============================================================================== +*/ + +// Check if the FW has WPA enabled +#define FW_IS_WPA_ENABLED(_adapter) (_adapter->FWCapInfo & MRVDRV_FW_CAPINFO_WPA) + +// +// Allocate and release tagged memory +// +#define MRVDRV_ALLOC_MEM(_pbuffer, _length) NdisAllocateMemoryWithTag( \ + (PVOID *)(_pbuffer),(_length), 'LVRM') + +#define MRVDRV_FREE_MEM(_buffer,_length) NdisFreeMemory((_buffer), (_length), 0) +#define MRVDRV_ZERO_MEM(_buffer,_length) NdisZeroMemory((PVOID *)(_buffer),(_length)); + +// +// PCI memory mapped I/O access routines +// +#define MEM_WRITE_UCHAR(_base, _offset, _value) NdisWriteRegisterUchar((PUCHAR)(((ULONG)_base)+_offset), (UCHAR)_value) +#define MEM_WRITE_USHORT(_base, _offset, _value) NdisWriteRegisterUshort((PUSHORT)(((ULONG)_base)+_offset), (USHORT)_value) +#define MEM_WRITE_ULONG(_base, _offset, _value) NdisWriteRegisterUlong((PULONG)(((ULONG)_base)+_offset), (ULONG)_value) + +#define MEM_READ_UCHAR(_base, _offset, _pBuf) NdisReadRegisterUchar((PUCHAR)(((ULONG)_base)+_offset), _pBuf) +#define MEM_READ_USHORT(_base, _offset, _pBuf) NdisReadRegisterUshort((PUSHORT)(((ULONG)_base)+_offset), _pBuf) +#define MEM_READ_ULONG(_base, _offset, _pBuf) NdisReadRegisterUlong((PULONG)(((ULONG)_base)+_offset), _pBuf) + +// +// Q data structures and useful Q operation macros. Right now Tx and command +// routines are using these macros to queue and retrieve NDIS_PACKETs and +// commands. + +// +// NDIS miniport driver cast queued item to Q_NODE type and link it to the +// queue maintained by Q_KEEPER +// +typedef struct _Q_NODE +{ + struct _Q_NODE *Next; +} Q_NODE, *PQ_NODE; + +// +// Q_KEEPER maintains the first and the last item on the queue +// +typedef struct _Q_KEEPER +{ + PQ_NODE First; + PQ_NODE Last; +} Q_KEEPER, *PQ_KEEPER; + +// +// Q_KEEPER initialization macro +// +#define InitializeQKeeper(QKeeper) \ + { \ + (QKeeper)->First = (QKeeper)->Last = NULL; \ + } + +// +// Q_NODE push macro +// +#define InsertQNodeFromHead(QKeeper, QNode) \ + { \ + ((PQ_NODE)QNode)->Next = (QKeeper)->First; \ + (QKeeper)->First = (PQ_NODE)(QNode); \ + if( (QKeeper)->Last == NULL ) \ + (QKeeper)->Last = (PQ_NODE)(QNode); \ + } + +// +// Q_NODE queue macro +// +#define InsertQNodeAtTail(QKeeper, QNode) \ + { \ + ((PQ_NODE)QNode)->Next = NULL; \ + if( (QKeeper)->Last ) \ + (QKeeper)->Last->Next = (PQ_NODE)(QNode); \ + else \ + (QKeeper)->First = (PQ_NODE)(QNode); \ + (QKeeper)->Last = (PQ_NODE)(QNode); \ + } + +// +// Q_NODE pop macro +// +#define PopFirstQNode(QKeeper) \ + (QKeeper)->First; \ + { \ + if( (QKeeper)->First ) \ + (QKeeper)->First = (QKeeper)->First->Next; \ + if( (QKeeper)->First == NULL ) \ + (QKeeper)->Last = NULL; \ + } + +// +// Q_KEEPER empty macro +// +#define IsQEmpty(QKeeper) ((QKeeper)->First == NULL) + +// +// S_SWAP : To swap 2 unsigned char +// +#define S_SWAP(a,b) do { unsigned char t = SArr[a]; SArr[a] = SArr[b]; SArr[b] = t; } while(0) + +#else +#endif /* _MACRODEF_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/Makefile 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/Makefile --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/Makefile 2007-11-06 12:26:39.000000000 -0500 @@ -0,0 +1,38 @@ +# Things that need to export symbols +export-objs := sdiobus.o + + +# Objects to compile in this module +# +STDHOSTOBJS = sdiobus.o \ + stdhost.o \ + skisr.o + + + +# EXTRA_CFLAGS += -DSD8385 +CFLAGS += -DDBG +CFLAGS += -DSDIO_API_INTERNAL +# CFLAGS += -DSDIO_BUS_DRIVER +CFLAGS += -I$(PWD) + +# +# Make target rules +# +all: mrvlsdio.o +ifeq ($(KVER),2.6) + @echo "Finished Making Marvell SDIO Stdhost Linux Driver for Kernel 2.6" +else + @echo "Finished Making Marvell SDIO Stdhost Linux Driver for Kernel 2.4" +endif + +mrvlsdio.o: $(STDHOSTOBJS) + $(LD) -r $^ -o $@ + +clean: + find . -name "*.o" -exec rm {} \; + find . -name "*.*~" -exec rm {} \; + find . -name "*.d" -exec rm {} \; + find . -name "*.mod.c" -exec rm {} \; + find . -name "*.ko" -exec rm {} \; + diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/sdiobus.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/sdiobus.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/sdiobus.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/sdiobus.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,1620 @@ +/****************************************************************************** + * + * Name: sdiobus.c + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:21:35 $ + * Purpose: Bus driver for SDIO interface + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2005 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: sdiobus.c,v $ + * Revision 1.1 2007/01/18 09:21:35 pweber + * Put under CVS control + * + * Revision 1.2 2005/12/08 12:01:00 ebauer + * Driver ckecks AND update voltage registry value if not correct + * + * Revision 1.1 2005/10/07 08:43:47 jschmalz + * Put SDIO with FPGA under CVS control + * + * + ******************************************************************************/ +#ifndef _lint +static const char SysKonnectFileId[] = "@(#)" __FILE__ " (C) Marvell "; +#endif /* !_lint */ + +#include "diagvers.h" /* diag version control */ + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +#ifndef WINNT +#include // proc filesystem +#endif +#ifdef WINNT +#ifndef POOL_COLD_ALLOCATION // Workaround for missing define in w2k header +#define POOL_COLD_ALLOCATION 256 // Note this cannot encode into the header. +#endif +#endif + +#ifdef DBG +SK_U32 stdDebugLevel = DBG_DEFAULT; +#ifdef WINNT +LARGE_INTEGER t1Time, t1LastTime, t1CurTime; +LARGE_INTEGER t2Time, t2LastTime, t2CurTime; +LARGE_INTEGER t3Time, t3LastTime, t3CurTime; +LARGE_INTEGER t4Time, t4LastTime, t4CurTime; +LARGE_INTEGER t5Time, t5LastTime, t5CurTime; +LARGE_INTEGER t6Time, t6LastTime, t6CurTime; +#endif // #ifdef WINNT +#endif // #ifdef DBG + +#define USE_DEBOUNCE_CARD_IN + /*--- mmoser 12/21/2006 ---*/ +#define MAX_DEBOUNCE_TIME 100 + +#ifdef WINNT +#ifdef ALLOC_PRAGMA +#pragma alloc_text (INIT, DriverEntry) +#pragma alloc_text (PAGE, SDIOBus_DriverUnload) +#pragma alloc_text (PAGE, SDIOBus_CreateClose) +#pragma alloc_text (PAGE, SDIOBus_IoCtl) +#endif // #ifdef ALLOC_PRAGMA + +UNICODE_STRING RegistryPath = { 0, 0, 0 }; +#else // #ifdef WINNT +MODULE_DESCRIPTION("SDIO Bus Driver Module"); +MODULE_AUTHOR("Michael Moser (mmoser@syskonnect.de)"); +MODULE_LICENSE("Dual BSD/GPL"); + +static int sdio_major = 0; + +int mrvlsdio_open(struct inode *inode, struct file *filp); +int mrvlsdio_release(struct inode *inode, struct file *filp); +int SDIOBus_IoCtl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); + +// +// Module parameters +// + +static int bus_type = SDIO_BUS_TYPE; +static int bus_width = SDIO_1_BIT; +static int block_size = SD_BLOCK_SIZE; +static int clock_speed = 0; +static int gpi_0_mode = 1; // edge triggered +static int gpi_0_level = 1; // high->low +static int gpi_1_mode = 1; // edge triggered +static int gpi_1_level = 0; // low->high + +//static int debug_flags = 0; +static int debug_flags = 0x0c; + +static int sdio_voltage = FPGA_POWER_REG_3_3_V; + +DECLARE_WAIT_QUEUE_HEAD(add_remove_queue); + +// kernel 2.6.x +module_param(bus_type, int, S_IRUGO); +module_param(bus_width, int, S_IRUGO); +module_param(block_size, int, S_IRUGO); +module_param(clock_speed, int, S_IRUGO); +module_param(debug_flags, int, S_IRUGO); +module_param(sdio_voltage, int, S_IRUGO); +module_param(gpi_0_mode, int, S_IRUGO); // 0 = level triggered 1 = edge triggered +module_param(gpi_0_level, int, S_IRUGO); // 0 = low->high or low 1 = high->low or high +module_param(gpi_1_mode, int, S_IRUGO); // 0 = level triggered 1 = edge triggered +module_param(gpi_1_level, int, S_IRUGO); // 0 = low->high or low 1 = high->low or high + +// prototypes +// for filling the "/proc/mrvsdio" entry +int mrvlsdio_read_procmem(char *buf, char **start, off_t offset, int count, + int *eof, void *data); + +#endif + +// +// Define an Interface Guid to access the proprietary Marvell SDIO bus driver interface. +// This guid is used to identify a specific interface in IRP_MN_QUERY_INTERFACE +// handler. +// +// {1D5837EE-F656-46b4-A8DA-5484A25AB13A} +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD, + 0x1d5837ee, 0xf656, 0x46b4, 0xa8, 0xda, 0x54, 0x84, 0xa2, + 0x5a, 0xb1, 0x3a); + +// +// Define a Guid for SDIO bus type. This is returned in response to +// IRP_MN_QUERY_BUS_INTERFACE on PDO. +// +DEFINE_INIT_GUID(GUID_MRVL_SDIOBUS_BUS_TYPE, + 0x43159826, 0xA758, 0x4aa2, 0x9F, 0x98, 0xAB, 0x22, 0x9C, + 0x03, 0x1E, 0xD1); +// {43159826-A758-4aa2-9F98-AB229C031ED1} + +#ifdef WINNT +/****************************************************************************** + * + * DriverEntry - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ + +NTSTATUS +DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath) +{ + INITDEBUG(); + DBGPRINT(DBG_LOAD, ("INIT - Enter DriverEntry\n")); + DBGPRINT(DBG_ALL, + ("*** %s - New SDIO-Bus Interface***\n", SK_SIGNON_MSG)); + DBGPRINT(DBG_ALL, ("*** Built on %s %s ***\n", __DATE__, __TIME__)); + + // + // Save a copy of *RegPath in driver global RegistryPath for future reference. + // + // UNICODE_NULL terminate the path so that we can safely use RegistryPath.Buffer + // as a PWSTR. + // + { + USHORT size = RegPath->Length + sizeof(WCHAR); + RegistryPath.Buffer = + ExAllocatePool((PagedPool | POOL_COLD_ALLOCATION), size); + + if (NULL == RegistryPath.Buffer) { + return STATUS_NO_MEMORY; + } + + RegistryPath.Length = 0; + RegistryPath.MaximumLength = size; + RtlCopyUnicodeString(&RegistryPath, RegPath); + RegistryPath.Buffer[size / sizeof(WCHAR) - 1] = UNICODE_NULL; + + DBGPRINT(DBG_LOAD, ("*** %S ***\n", RegistryPath)); + } + + // + // Set entry points into the driver + // + DriverObject->MajorFunction[IRP_MJ_CREATE] = SDIOBus_CreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = SDIOBus_CreateClose; + DriverObject->MajorFunction[IRP_MJ_PNP] = SDIOBus_PnP; + DriverObject->MajorFunction[IRP_MJ_POWER] = SDIOBus_Power; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SDIOBus_IoCtl; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = + SDIOBus_SystemControl; + DriverObject->DriverUnload = SDIOBus_DriverUnload; + DriverObject->DriverExtension->AddDevice = SDIOBus_AddDevice; + + return STATUS_SUCCESS; +} + +/****************************************************************************** + * + * SDIOBus_CreateClose - + * + * Description: + * Some outside source is trying to create a file against us. + * + * If this is for the FDO (the bus itself) then the caller + * is trying to open the proprietary connection to tell us + * to enumerate or remove a device. + * + * If this is for the PDO (an object on the bus) then this + * is a client that wishes to use the SDIO device. + * + * Notes: + * + * Context: + * + * Returns: + * + */ +NTSTATUS +SDIOBus_CreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + PFDO_DEVICE_DATA fdoData; + + PAGED_CODE(); + + fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; + + status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Information = 0; + + SDIOBus_IncIoCount(fdoData); + + // + // If it's not for the FDO. We don't allow create/close on PDO + // + if (fdoData->common.IsFDO) { + // + // Check to see whether the bus is removed + // + + if (fdoData->common.DevicePnPState == Deleted) { + status = STATUS_DELETE_PENDING; + } else { + irpStack = IoGetCurrentIrpStackLocation(Irp); + + switch (irpStack->MajorFunction) { + case IRP_MJ_CREATE: + { + DBGPRINT(DBG_LOAD, ("SDIOBus_CreateClose() : Create \n")); + status = STATUS_SUCCESS; + break; + } + case IRP_MJ_CLOSE: + { + DBGPRINT(DBG_LOAD, ("SDIOBus_CreateClose() : Close \n")); + status = STATUS_SUCCESS; + break; + } + default: + { + DBGPRINT(DBG_LOAD, + ("SDIOBus_CreateClose() : Unhandled major function : %d \n", + irpStack->MajorFunction)); + break; + } + } + } + } + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + SDIOBus_DecIoCount(fdoData); + + return status; +} + +/****************************************************************************** + * + * SDIOBus_IoCtl - + * + * Description: Handle user mode IOCTL requests. + * + * Notes: + * + * Context: + * + * Returns: + * + */ +NTSTATUS +SDIOBus_IoCtl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + ULONG inlen, outlen; + PCOMMON_DEVICE_DATA pDev; + PFDO_DEVICE_DATA fdoData; + PVOID buffer; + ULONG data, *pData; + ULONG ulDataRead; + ULONG cnt; + SK_U8 ucValue, ucPowerValue; + + PAGED_CODE(); + + fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; + + // + // We only take Device Control requests for the FDO. + // That is the bus itself. + // + + if (!fdoData->common.IsFDO) { + // + // These commands are only allowed to go to the FDO. + // + status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; + } + // + // Check to see whether the bus is removed + // + + if (fdoData->common.DevicePnPState == Deleted) { + Irp->IoStatus.Status = status = STATUS_DELETE_PENDING; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; + } + + SDIOBus_IncIoCount(fdoData); + + irpStack = IoGetCurrentIrpStackLocation(Irp); + + buffer = Irp->AssociatedIrp.SystemBuffer; + inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; + outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; + + status = STATUS_SUCCESS; + DBGPRINT(DBG_IOCTL, + ("SDIOBus_IoCtl() : IOCTL-Code : %d \n", + irpStack->Parameters.DeviceIoControl.IoControlCode)); + + pDev = (PCOMMON_DEVICE_DATA) & fdoData->common; + pData = &data; + + switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { + case IOCTL_SDIOBUSENUM_SET_VOLTAGE: + memcpy(pData, buffer, sizeof(ULONG)); + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_SET_VOLTAGE: %x\n", data)); + ucPowerValue = (SK_U8) data; + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_DATA, ucPowerValue); + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_CMD, + FPGA_POWER_REG_CMD_START); + DBGPRINT(DBG_LOAD, ("wait for stable voltage\n")); + cnt = 0; + do { + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_STATUS, &ucValue); + DBGPRINT(DBG_LOAD, ("PowerRegulatorControl: 0x%x\n", ucValue)); + } while (++cnt < 10000 && (ucValue & FPGA_POWER_REG_STABLE) == 0); + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_SET_VOLTAGE: cnt=%d\n", cnt)); + + break; + case IOCTL_SDIOBUSENUM_SET_BUSTYPE: + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_SET_BUSTYPE\n")); + break; + case IOCTL_SDIOBUSENUM_SET_BUSWIDTH: + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_SET_BUSWIDTH\n")); + break; + case IOCTL_SDIOBUSENUM_SET_CLKSPEED: + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_SET_CLKSPEED\n")); + break; + case IOCTL_SDIOBUSENUM_GET_BOARDREV: + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_GET_BOARDREV\n")); + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x210, &ulDataRead); + memcpy(buffer, &ulDataRead, sizeof(ulDataRead)); + Irp->IoStatus.Information = 4; + break; + case IOCTL_SDIOBUSENUM_GET_JUMPER: + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_GET_JUMPER\n")); + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x210, &ulDataRead); + memcpy(buffer, &ulDataRead, sizeof(ulDataRead)); + Irp->IoStatus.Information = 4; + break; + default: + DBGPRINT(DBG_LOAD, ("IOCTL DEFAULT\n")); + status = STATUS_INVALID_PARAMETER; + break; + } + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + SDIOBus_DecIoCount(fdoData); + return status; +} + +/****************************************************************************** + * + * SDIOBus_IoCtl - + * + * Description: Clean up everything we did in driver entry. + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDIOBus_DriverUnload(IN PDRIVER_OBJECT DriverObject) +{ + PAGED_CODE(); + + DBGPRINT(DBG_LOAD, ("SDIOBus_DriverUnload()\n")); + + // + // All the device objects should be gone. + // + + /*--- mmoser 13.09.2005 ---*/ +// ASSERT (NULL == DriverObject->DeviceObject); + + // + // Here we free all the resources allocated in the DriverEntry + // + + return; +} + +/****************************************************************************** + * + * SDIOBus_IncIoCount - + * + * Description: This routine increments the number of requests the device receives + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDIOBus_IncIoCount(IN PFDO_DEVICE_DATA FdoData) +{ + SK_U32 result; + + result = InterlockedIncrement(&FdoData->OutstandingIO); + + /*--- mmoser 13.09.2005 ---*/ +// ASSERT(result > 0); + // + // Need to clear StopEvent (when OutstandingIO bumps from 1 to 2) + // + if (result == 2) { + // + // We need to clear the event + // + KeClearEvent(&FdoData->StopEvent); + } + + return; +} + +/****************************************************************************** + * + * SDIOBus_DecIoCount - + * + * Description: This routine decrements as it complete the request it receives + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDIOBus_DecIoCount(IN PFDO_DEVICE_DATA FdoData) +{ + SK_U32 result; + + result = InterlockedDecrement(&FdoData->OutstandingIO); + + if (result == 1) { + // + // Set the stop event. Note that when this happens + // (i.e. a transition from 2 to 1), the type of requests we + // want to be processed are already held instead of being + // passed away, so that we can't "miss" a request that + // will appear between the decrement and the moment when + // the value is actually used. + // + + KeSetEvent(&FdoData->StopEvent, IO_NO_INCREMENT, FALSE); + } + + if (result == 0) { + // + // The count is 1-biased, so it can be zero only if an + // extra decrement is done when a remove Irp is received + // + /*--- mmoser 13.09.2005 ---*/ +// ASSERT(FdoData->common.DevicePnPState == Deleted); + + // + // Set the remove event, so the device object can be deleted + // + + KeSetEvent(&FdoData->RemoveEvent, IO_NO_INCREMENT, FALSE); + } + + return; +} + +/****************************************************************************** + * + * SDIOBus_SystemControl - + * + * Description: + * We have just received a System Control IRP. + * + * Notes: + * + * Context: + * + * Returns: + * + */ +NTSTATUS +SDIOBus_SystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) +{ + PFDO_DEVICE_DATA fdoData; + NTSTATUS status; + PIO_STACK_LOCATION stack; + PCOMMON_DEVICE_DATA commonData; + + DBGPRINT(DBG_LOAD, ("SDIOBus_SystemControl()\n")); + + PAGED_CODE(); + + stack = IoGetCurrentIrpStackLocation(Irp); + + commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; + + // + // Just complete the request with the current status + // + status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; +} + +NTSTATUS +SDIO_RegGetDword(IN ULONG RelativeTo, + IN PWSTR Path, + IN PWSTR ParameterName, IN OUT PULONG ParameterValue) +{ + NTSTATUS status; + RTL_QUERY_REGISTRY_TABLE paramTable[2]; + ULONG defaultValue; + + if ((NULL == Path) || (NULL == ParameterName) || (NULL == ParameterValue)) { + return STATUS_INVALID_PARAMETER; + } + + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDword - RelativeTo= %x, Path=<%S>, ParameterName=<%S>\n", + RelativeTo, Path, ParameterName)); + + // + // set up table entries for call to RtlQueryRegistryValues + // + // leave paramTable[1] as all zeros to terminate the table + // + // use original value as default value + // + // use RtlQueryRegistryValues to do the grunge work + // + RtlZeroMemory(paramTable, sizeof(paramTable)); + + defaultValue = *ParameterValue; + + paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + paramTable[0].Name = ParameterName; + paramTable[0].EntryContext = ParameterValue; + paramTable[0].DefaultType = REG_DWORD; + paramTable[0].DefaultData = &defaultValue; + paramTable[0].DefaultLength = sizeof(ULONG); + + status = RtlQueryRegistryValues(RelativeTo | RTL_REGISTRY_OPTIONAL, + Path, ¶mTable[0], NULL, NULL); + + if (status != STATUS_SUCCESS) { + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDword - RtlQueryRegistryValues FAILED w/status=%x\n", + status)); + } + + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDword - post-query <%S> *ParameterValue = %x\n", + ParameterName, *ParameterValue)); + + return status; +} + +NTSTATUS +SDIO_RegGetDeviceParameterDword(IN PDEVICE_OBJECT Pdo, + IN PWSTR ParameterName, + IN OUT PULONG ParameterValue) +{ + NTSTATUS status; + HANDLE hKey; + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + ULONG defaultValue; + + PAGED_CODE(); + + status = IoOpenDeviceRegistryKey(Pdo, + PLUGPLAY_REGKEY_DEVICE | + PLUGPLAY_REGKEY_CURRENT_HWPROFILE, + KEY_READ, &hKey); + + if (status != STATUS_SUCCESS) { + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDeviceParameterDword - RtlQueryRegistryValues FAILED w/status=%x\n", + status)); + return status; + } + + defaultValue = *ParameterValue; + + RtlZeroMemory(&queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + queryTable[0].Name = ParameterName; + queryTable[0].EntryContext = ParameterValue; + queryTable[0].DefaultType = REG_DWORD; + queryTable[0].DefaultData = &defaultValue; + queryTable[0].DefaultLength = sizeof(ULONG); + +// _asm int 3; + + status = + RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, hKey, queryTable, NULL, + NULL); + + if (status != STATUS_SUCCESS) { + *ParameterValue = defaultValue; + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDeviceParameterDword - RtlQueryRegistryValues FAILED w/status=%x\n", + status)); + } + + DBGPRINT(DBG_LOAD, + ("SDIO_RegGetDeviceParameterDword - post-query <%S> *ParameterValue = %x\n", + ParameterName, *ParameterValue)); + + ZwClose(hKey); + + return status; +} + +NTSTATUS +SDIO_RegSetDword(IN ULONG RelativeTo, + IN PCWSTR Path, + IN PCWSTR ValueName, + IN PVOID ValueData, IN ULONG ValueLength) +{ + NTSTATUS status; + ULONG defaultValue; + + PAGED_CODE(); + + if ((NULL == Path) || (NULL == ValueName) || (NULL == ValueData)) { + return STATUS_INVALID_PARAMETER; + } + + status = RtlWriteRegistryValue(RelativeTo | RTL_REGISTRY_OPTIONAL, + Path, + ValueName, + REG_DWORD, ValueData, ValueLength); + + if (status != STATUS_SUCCESS) { + DBGPRINT(DBG_LOAD, ("SDIO_RegSetDword Error")); + } + + return status; + +} + +#else // #ifdef WINNT +static PFDO_DEVICE_DATA fdo_data = NULL; + +static int SDIOThread(void *data); + +static int probe(struct pci_dev *dev, const struct pci_device_id *id); +static void remove(struct pci_dev *dev); + +// Call back functions for busdriver module + +static sdio_add_card_notifier sdio_add_card_callback = NULL; +static sdio_remove_card_notifier sdio_remove_card_callback = NULL; + +// 2.6 : task queue mechanism +struct work_struct sdiobus_wq; + +static DECLARE_COMPLETION(on_exit); + +// kernel 2.6 + +static struct pci_device_id ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x8000),}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, ids); + +/* + * The fops + */ + +struct file_operations mrvlsdio_fops = { + llseek:NULL, + read:NULL, + write:NULL, + ioctl:SDIOBus_IoCtl, + mmap:NULL, + open:mrvlsdio_open, + release:mrvlsdio_release, +}; + +/* + * Open and close + */ + +int +mrvlsdio_open(struct inode *inode, struct file *filp) +{ + ENTER(); + + if (fdo_data == NULL) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio_open: fdo_data==NULL -> Adapter not in CardBus slot!\n")); + return -ENODEV; + } + filp->f_op = &mrvlsdio_fops; + /* and use filp->private_data to point to the device data */ + filp->private_data = fdo_data; + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio_open: fdo_data=0x%p fdo_data.common=0x%p fdo_data.common.IOBase[0]= 0x%p\n", + fdo_data, &fdo_data->common, fdo_data->common.IOBase[0])); + + LEAVE(); + return 0; /* success */ +} + +int +mrvlsdio_release(struct inode *inode, struct file *filp) +{ + ENTER(); + LEAVE(); + return 0; +} + +/* + * The ioctl() implementation + */ + +int +SDIOBus_IoCtl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + UCHAR ucValue; + ULONG ulValue; + ULONG cnt; + PFDO_DEVICE_DATA fdo; + + ENTER(); + + fdo = (FDO_DEVICE_DATA *) filp->private_data; + if (fdo == NULL) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "SDIOBus_IoCtl : fdo= 0x%p !!!!!!!!!!!!!!!!\n", + fdo)); + return -ENOTTY; + } + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : fdo= 0x%p fdo->common.IOBase[0]= 0x%p\n", fdo, + fdo->common.IOBase[0])); + + switch (cmd) { + case IOCTL_SDIOBUSENUM_SET_VOLTAGE: + { + ret = get_user(ucValue, (int *) arg); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_SET_VOLTAGE: 0x%2.02X\n", + ucValue)); + MEM_WRITE_UCHAR(&fdo->common, SK_SLOT_0, FPGA_POWER_REG_DATA, + ucValue); + MEM_WRITE_UCHAR(&fdo->common, SK_SLOT_0, FPGA_POWER_REG_CMD, + FPGA_POWER_REG_CMD_START); + DBGPRINT(DBG_LOAD, (KERN_DEBUG "wait for stable voltage\n")); + cnt = 0; + do { + MEM_READ_UCHAR(&fdo->common, SK_SLOT_0, FPGA_POWER_REG_STATUS, + &ucValue); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "PowerRegulatorControl: 0x%x\n", + ucValue)); + } while (++cnt < 10000 && (ucValue & FPGA_POWER_REG_STABLE) == 0); + DBGPRINT(DBG_LOAD, + ("IOCTL_SDIOBUSENUM_SET_VOLTAGE: cnt=%d\n", cnt)); + break; + } + case IOCTL_SDIOBUSENUM_GET_BOARDREV: + { + MEM_READ_ULONG(&fdo->common, SK_SLOT_0, FPGA_CARD_REVISION, + &ulValue); + + ret = put_user(ulValue, (int *) arg); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_GET_BOARDREV 0x%8.08X\n", + ulValue)); + break; + } + case IOCTL_SDIOBUSENUM_GET_JUMPER: + { + DBGPRINT(DBG_LOAD, ("IOCTL_SDIOBUSENUM_GET_JUMPER\n")); + MEM_READ_ULONG(&fdo->common, SK_SLOT_0, FPGA_CARD_REVISION, + &ulValue); + ret = put_user(ulValue, (int *) arg); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_GET_JUMPER 0x%8.08X\n", + ulValue)); + break; + } + + case IOCTL_SDIOBUSENUM_SET_BUSTYPE: + { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_SET_BUSTYPE --> IGNORED!\n")); + break; + } + case IOCTL_SDIOBUSENUM_SET_BUSWIDTH: + { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_SET_BUSWIDTH --> IGNORED!\n")); + break; + } + case IOCTL_SDIOBUSENUM_SET_CLKSPEED: + { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : IOCTL_SDIOBUSENUM_SET_CLKSPEED --> IGNORED!\n")); + break; + } + default: + { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIOBus_IoCtl : invalid cmd=%d (0x%8.08X)!\n", cmd, + cmd)); + return -ENOTTY; + } + } + + LEAVE(); + return ret; + +} + +static struct pci_driver mrvlsdio = { + .name = "mrvlsdio", + .id_table = ids, + .probe = probe, + .remove = remove, +}; + +static int +probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int i, ret; + SK_U8 ucValue; + SK_U32 mem; + SK_U32 ulValue; + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "mrvlsdio : probe()\n")); + + pci_enable_device(dev); + if (pci_set_dma_mask(dev, 0xffffffff)) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: 32-bit PCI DMA not supported")); + pci_disable_device(dev); + return -EIO; + } + pci_set_master(dev); + /*--- mmoser 4/4/2006 ---*/ + if (fdo_data == NULL) { + fdo_data = + (PFDO_DEVICE_DATA) kmalloc(sizeof(FDO_DEVICE_DATA), GFP_KERNEL); + + if (fdo_data == NULL) { + return -ENOMEM; + } + memset(fdo_data, 0, sizeof(FDO_DEVICE_DATA)); + } + + fdo_data->common.IOBaseIx = 0; + /*--- mmoser 10/11/2006 ---*/ + fdo_data->common.dev = dev; + pci_request_regions(dev, "MRVL-SDIO"); + + for (i = 0; i < 5; i++) { + mem = pci_resource_start(dev, i); + + if (mem != 0) { + if (IORESOURCE_MEM == pci_resource_flags(dev, i)) { + fdo_data->common.IOBaseLength[fdo_data->common.IOBaseIx] = + pci_resource_end(dev, i) - mem + 1; + fdo_data->common.IOBase[fdo_data->common.IOBaseIx] = + ioremap_nocache(mem, + fdo_data->common.IOBaseLength[fdo_data-> + common. + IOBaseIx]); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio: IOBase[%d] = 0x%8.08X IOBaseLength = %u\n", + i, + (SK_U32) fdo_data->common.IOBase[fdo_data->common. + IOBaseIx], + fdo_data->common.IOBaseLength[fdo_data->common. + IOBaseIx])); + fdo_data->common.IOBaseIx++; + if (fdo_data->common.IOBaseIx >= 2) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio : Too many memory address ranges!\n")); + fdo_data->common.IOBaseIx = 0; + } + } + } + } + + // Dummy read. Function return SUCCESS but value is messy !!! + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, + (SK_U8 *) & fdo_data->common.Interrupt); + + for (i = 0; i < 3; i++) { + ret = + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, + (SK_U8 *) & fdo_data->common.Interrupt); + if (ret) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio: Failed to retrieve Interrupt Line (%d) %d ret=%d\n", + i, fdo_data->common.Interrupt, ret)); + UDELAY(100); + continue; + } else { + break; + if (fdo_data->common.Interrupt > 13) { + DBGPRINT(DBG_ALL, + ("mrvlsdio: common.Interrupt = %d\n", + fdo_data->common.Interrupt)); + if (fdo_data->common.Interrupt == 16) { + /* Dell Dimension 3000 & Dell Inspiron 6000 */ + break; + } + UDELAY(100); + continue; + } + break; + } + } + if (i >= 3) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio: Failed to retrieve Interrupt Line (%d) ret=%d\n", + i, ret)); + return -ENODEV; + } + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: Interrupt Line = %d (%d)\n", + fdo_data->common.Interrupt, i)); + + MEM_READ_UCHAR(&fdo_data->common, SK_SLOT_0, FPGA_CARD_REVISION, + &ucValue); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: CardRevision: 0x%X (fdo_data=0x%p)\n", + ucValue, &fdo_data)); + + init_waitqueue_head(&fdo_data->common.wq); + + fdo_data->common.bus_type = bus_type; + fdo_data->common.bus_width = bus_width; + fdo_data->common.ClockSpeed = clock_speed; + fdo_data->common.debug_flags = debug_flags; + fdo_data->common.blockSize = block_size; + fdo_data->common.sdio_voltage = sdio_voltage; + + pci_read_config_byte(dev, 0x0c, &ucValue); + if (ucValue == 0) + pci_write_config_byte(dev, 0x0c, 2); + pci_read_config_byte(dev, 0x0c, &ucValue); + printk("config[0x0c]=0x%2.02X\n", ucValue); + pci_read_config_byte(dev, 0x0d, &ucValue); + printk("config[0x0d]=0x%2.02X\n", ucValue); + printk("debug_flags=0x%8.08X\n", debug_flags); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: bus_type : SDIO%s\n", + bus_type == SDIO_BUS_TYPE ? "" : "/SPI")); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: bus_width : %s\n", + bus_width == SDIO_4_BIT ? "4-bit" : "1-bit")); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: block_size : %d\n", block_size)); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: clock_speed : %d\n", clock_speed)); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: debug_flags : 0x%8.08X\n", debug_flags)); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: sdio_voltage : %d\n", sdio_voltage)); + + /*--- mmoser 3/12/2007 ---*/ + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: gpi_0_mode : %s triggered\n", + gpi_0_mode == 0 ? "level" : "edge")); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: gpi_0_level : %s\n", + gpi_0_level == 0 ? (gpi_0_mode == + 0 ? "low" : "low->high") : (gpi_0_mode == + 0 ? "high" : + "high->low"))); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: gpi_1_mode : %s triggered\n", + gpi_1_mode == 0 ? "level" : "edge")); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: gpi_1_level : %s\n", + gpi_1_level == 0 ? (gpi_1_mode == + 0 ? "low" : "low->high") : (gpi_1_mode == + 0 ? "high" : + "high->low"))); + + // mmoser 2005-11-29 + atomic_set(&fdo_data->common.card_add_event, 0); + atomic_set(&fdo_data->common.card_remove_event, 0); + + /*--- mmoser 8/29/2006 ---*/ + init_waitqueue_head(&fdo_data->common.trans_complete_evt.wq); + init_waitqueue_head(&fdo_data->common.cmd_complete_evt.wq); + + /*--- mmoser 3/12/2007 ---*/ + MEM_READ_ULONG(&fdo_data->common, SK_SLOT_0, 0x200, &ulValue); + ulValue &= 0x0FFFFFFF; + ulValue |= + ((gpi_1_mode << 3 | gpi_1_level << 2 | gpi_0_mode << 1 | gpi_0_level) + << 28); + printk("mrvlsdio: ulValue = 0x%8.08X\n", ulValue); + MEM_WRITE_ULONG(&fdo_data->common, SK_SLOT_0, 0x200, ulValue); + + printk("mrvlsdio: reg[0x200] = 0x%8.08X\n", ulValue); + + SDHost_Init(&fdo_data->common); + + // mmoser 2005-11-29 + if (0 != request_irq(fdo_data->common.Interrupt, + SDIOBus_Isr, SA_SHIRQ, + MRVL_DEVICE_NAME, (PVOID) fdo_data) + ) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "mrvlsdio: Failed to register interrupt handler\n")); + return -ENODEV; + } + + if (SDHost_isCardPresent(&fdo_data->common) == SK_TRUE) { + if (SDIOBus_CardPluggedIn(fdo_data) == SK_TRUE) { + fdo_data->CardIn = SK_TRUE; + } + } +// mmoser 2005-11-22 start the thread as the last action + +// mmoser 2005-11-21 + fdo_data->common.stop_thread = SK_FALSE; + + fdo_data->common.thread_id = kernel_thread(SDIOThread, + fdo_data, + (CLONE_FS | CLONE_FILES | + CLONE_SIGHAND)); +#ifdef SYSKT_DMA_MALIGN_TEST + fdo_data->common.dma_tx_malign = 0; + fdo_data->common.dma_rx_malign = 0; + // fdo_data->common.dma_start_malign = 4096 - 32; + fdo_data->common.dma_start_malign = 0; +#endif + + if (fdo_data->common.thread_id == 0) + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio: Failed to start kernel thread!\n")); + + return 0; +} + +static void +remove(struct pci_dev *dev) +{ + DBGPRINT(DBG_LOAD, (KERN_DEBUG "remove mrvlsdio ... \n")); + + /* clean up any allocated resources and stuff here. + * like call release_region(); + */ + if (fdo_data != NULL) { + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: remove(fdo_data=%p)\n", __FUNCTION__, + fdo_data)); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "%s: remove_card_callback(%p) (surprise_removed:%d)\n", + __FUNCTION__, sdio_remove_card_callback, + fdo_data->common.SurpriseRemoved)); + + /*--- mmoser 3/31/2006 ---*/ + if (fdo_data->common.SurpriseRemoved && + sdio_remove_card_callback != NULL) { + sdio_remove_card_callback(); + } + + if (fdo_data->common.thread_id) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "remove() kill SDIOThread ... \n")); + + kill_proc(fdo_data->common.thread_id, SIGTERM, 1); + + // mmoser 2005-11-21 + fdo_data->common.stop_thread = SK_TRUE; + + wait_for_completion(&on_exit); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "remove() SDIOThread killed ... \n")); + } + + /*--- mmoser 4/4/2006 ---*/ + SDHost_DisableInterrupt(&fdo_data->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + + free_irq(fdo_data->common.Interrupt, &fdo_data->common); + + /*--- mmoser 10/11/2006 ---*/ + pci_release_regions(fdo_data->common.dev); + + } +} + +BOOLEAN +SDIOBus_CardRemoved(PFDO_DEVICE_DATA FdoData) +{ + + ENTER(); + + FdoData->CardIn = SK_FALSE; + + // mmoser 2005-11-29 + atomic_inc(&FdoData->common.card_remove_event); + + LEAVE(); + return SK_TRUE; +} + +BOOLEAN +SDIOBus_CardPluggedIn(PFDO_DEVICE_DATA FdoData) +{ + SK_U32 ulVal; + + ENTER(); +#ifdef USE_DEBOUNCE_CARD_IN + + /*--- mmoser 12/21/2006 ---*/ + mdelay(MAX_DEBOUNCE_TIME); + + // Read present state register to check whether a SD card is present + MEM_READ_ULONG(&FdoData->common, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulVal); + if ((ulVal & STDHOST_STATE_CARD_INSERTED) == 0) { + // There is probably no card in the socket + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_isCardPresent(): Card is NOT present. (%8.08X)\n", + ulVal)); + return SK_FALSE; + } +#endif // USE_DEBOUNCE_CARD_IN + + SDHost_Init(&FdoData->common); + + if (!SDHost_InitializeCard(&FdoData->common)) { + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) & FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + return SK_FALSE; + } + FdoData->CardIn = SK_TRUE; + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "Device Name : %s\n", FdoData->common.DeviceName)); + + // mmoser 2005-11-29 + atomic_inc(&FdoData->common.card_add_event); + LEAVE(); + return SK_TRUE; +} + +static int +SDIOThread(void *data) +{ + PFDO_DEVICE_DATA fdo; + SK_U16 usVal; + SK_U32 card_in = 0; + SK_U32 card_out = 0; + PCOMMON_DEVICE_DATA pDev; + + daemonize("SDIOThread"); + allow_signal(SIGTERM); + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDIOThread() started ... \n")); + + if (data == NULL) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDIOThread() data == NULL !\n")); + complete_and_exit(&on_exit, 0); + return 1; + } + fdo = (PFDO_DEVICE_DATA) data; + + pDev = (PCOMMON_DEVICE_DATA) & fdo->common; + LED_OFF(4); + + while (fdo != NULL && !fdo->common.stop_thread) { + LED_ON(4); + +// mmoser 2005-11-21 + // Read the Host Controller Version to check if SD Host adapter is available + MEM_READ_USHORT(&fdo->common, SK_SLOT_0, + STDHOST_HOST_CONTROLLER_VERSION, &usVal); + if (usVal == 0xFFFF) { + // There is probably no SD Host Adapter available + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_isCardPresent(): SD Host Adapter is NOT present. (%4.04X)\n", + usVal)); + fdo->common.SurpriseRemoved = SK_TRUE; + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDIOThread terminated ... \n")); + complete_and_exit(&on_exit, 0); + return -ENODEV; + } + // mmoser 2005-11-29 + card_in = atomic_read(&fdo->common.card_add_event); + card_out = atomic_read(&fdo->common.card_remove_event); + + // mmoser 2005-11-29 + if (sdio_add_card_callback == NULL || + sdio_remove_card_callback == NULL || + (card_in == 0 && card_out == 0)) { + LED_OFF(4); + + /*--- mmoser 6/21/2006 ---*/ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(10); + continue; + } + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: card_in=%d card_out=%d\n", __FUNCTION__, + card_in, card_out)); + + // mmoser 2005-11-29 + if (card_in > 0) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: CARD_ADD_EVENT received.\n", + __FUNCTION__)); + if (sdio_add_card_callback != NULL) { + DBGPRINT(DBG_LOAD | DBG_ERROR, + (KERN_DEBUG + "%s: add_card_callback(0x%8.08X) SurpriseRemoved=0\n", + __FUNCTION__, (ULONG) fdo)); +// pPriv = add_card_callback((PVOID)fdo) ; + + /*--- mmoser 4/3/2006 ---*/ + fdo->common.SurpriseRemoved = 0; + /*--- mmoser 3/31/2006 ---*/ + sdio_add_card_callback(&pDev->dev->dev); + // mmoser 2006-01-24 + // mmoser 2005-11-29 + atomic_dec(&fdo->common.card_add_event); + + } else { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "%s: add_card_callback(0x%8.08X) NOT INSTALLED !!!!!!!!!!!!!!\n", + __FUNCTION__, (ULONG) fdo)); + } + } + // mmoser 2005-11-29 + else if (card_out > 0) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: CARD_REMOVE_EVENT received.\n", + __FUNCTION__)); + if (sdio_remove_card_callback != NULL) { + DBGPRINT(DBG_LOAD | DBG_ERROR, + (KERN_DEBUG "%s: remove_card_callback(0x%8.08X)\n", + __FUNCTION__, (ULONG) fdo)); + + /*--- mmoser 3/31/2006 ---*/ + sdio_remove_card_callback(); +// remove_card_callback((PVOID)fdo); + + // mmoser 2006-01-24 + // mmoser 2005-11-29 + + /*--- mmoser 3/31/2006 ---*/ + atomic_set(&fdo->common.card_remove_event, 0); + } else { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "%s: remove_card_callback(0x%8.08X) NOT INSTALLED !!!!!!!!!!!!!!\n", + __FUNCTION__, (ULONG) fdo)); + } + } else { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDIOThread terminated ... \n")); + complete_and_exit(&on_exit, 0); + return 1; + } + + } + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDIOThread terminated ... \n")); + + fdo->common.thread_id = 0; + complete_and_exit(&on_exit, 0); + return 0; +} + +VOID +SDIOBus_InterfaceReference(IN PVOID Context) +{ + atomic_inc(&((PFDO_DEVICE_DATA) Context)->SDIOInterfaceRefCount); +} + +VOID +SDIOBus_InterfaceDereference(IN PVOID Context) +{ + atomic_dec(&((PFDO_DEVICE_DATA) Context)->SDIOInterfaceRefCount); +} + +void +mrvlsdio_register_callbacks(sdio_add_card_notifier add, + sdio_remove_card_notifier _remove) +{ + ENTER(); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: add=%p remove=%p\n", __FUNCTION__, add, + _remove)); + + sdio_add_card_callback = add; + sdio_remove_card_callback = _remove; + + LEAVE(); +} + +int +mrvlsdio_get_interface(PGUID guid, ULONG size, ULONG version, PVOID interface) +{ + PMRVL_SDIO_INTERFACE_STANDARD SDIOInterfaceStandard; + + ENTER(); + + if (guid == NULL || size == 0 || version == 0 || interface == NULL) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "mrvlsdio_get_interface() called with illegal parameters!!!!\n")); + return -1; + } + DBGPRINT(DBG_LOAD, (KERN_DEBUG "mrvlsdio_get_interface() called\n")); + SHOW_GUID(*guid); + if (COMPARE_GUID(*guid, GUID_MRVL_SDIOBUS_INTERFACE_2_STANDARD)) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "mrvlsdio_get_interface() interface is OK!\n")); + + if (size < sizeof(MRVL_SDIO_INTERFACE_STANDARD) && version != 1) { + return -1; + } + + if (fdo_data == NULL) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "mrvlsdio_get_interface() fdo_data is NULL !!!!\n")); + return -1; + } + + SDIOInterfaceStandard = (PMRVL_SDIO_INTERFACE_STANDARD) interface; + + SDIOInterfaceStandard->Context = fdo_data; + // + // Fill in the exported functions + // + SDIOInterfaceStandard->InterfaceReference = + (PINTERFACE_REFERENCE) SDIOBus_InterfaceReference; + SDIOInterfaceStandard->InterfaceDereference = + (PINTERFACE_DEREFERENCE) SDIOBus_InterfaceDereference; + SDIOInterfaceStandard->SDIO_Cmd52_Read = + (PSDIO_CMD52_READ) SDHost_CMD52_Read; + SDIOInterfaceStandard->SDIO_Cmd52_Write = + (PSDIO_CMD52_WRITE) SDHost_CMD52_Write; + SDIOInterfaceStandard->SDIO_Cmd53_Read = + (PSDIO_CMD53_READ) SDHost_CMD53_Read; + SDIOInterfaceStandard->SDIO_Cmd53_Write = + (PSDIO_CMD53_WRITE) SDHost_CMD53_Write; + SDIOInterfaceStandard->SDIO_Cmd53_Read_Ex = + (PSDIO_CMD53_READ_EX) SDHost_CMD53_ReadEx; + SDIOInterfaceStandard->SDIO_Cmd53_Write_Ex = + (PSDIO_CMD53_WRITE_EX) SDHost_CMD53_WriteEx; + SDIOInterfaceStandard->SDIO_RegisterIsrHandler = + (PSDIO_REGISTER_ISR_HANDLER) SDIO_RegisterIsrHandler; + SDIOInterfaceStandard->SDIO_EnableInterrupt = + (PSDIO_ENABLE_IRQ) SDHost_if_EnableInterrupt; + SDIOInterfaceStandard->SDIO_DisableInterrupt = + (PSDIO_DISABLE_IRQ) SDHost_if_DisableInterrupt; + SDIOInterfaceStandard->SDIO_isCardPresent = + (PSDIO_IS_CARD_PRESENT) SDHost_isCardPresent; + SDIOInterfaceStandard->SDIO_lockInterface = + (PSDIO_SDIO_LOCKINTERFACE) SDHost_lockInterface; + SDIOInterfaceStandard->SDIO_unlockInterface = + (PSDIO_SDIO_UNLOCKINTERFACE) SDHost_unlockInterface; + SDIOInterfaceStandard->SDIO_SetLed = (PSDIO_SET_LED) SDHost_SetLed; + SDIOInterfaceStandard->SDIO_PsState = (PSDIO_PS_STATE) SDHost_PsState; // pweber 17.08.2005 + + /*--- mmoser 12/18/2006 ---*/ + SDIOInterfaceStandard->SDIO_SetClock = + (PSDIO_SET_CLOCK) SDHost_SetClock; + SDIOInterfaceStandard->SDIO_SetBusWidth = + (PSDIO_SET_BUSWIDTH) SDHost_SetBusWidth; + /*--- mmoser 1/2/2007 ---*/ + SDIOInterfaceStandard->SDIO_SetClockSpeed = + (PSDIO_SET_CLOCK_SPEED) SDHost_SetClockSpeed; + + /*--- mmoser 2/20/2007 ---*/ + SDIOInterfaceStandard->SDIO_SetGPO = (PSDIO_SET_GPO) SDHost_SetGPO; + + // + // Must take a reference before returning + // + SDIOBus_InterfaceReference(fdo_data); + + } + LEAVE(); + return 0; +} + +void +SDIO_RegisterIsrHandler(PCOMMON_DEVICE_DATA pDev, + PVOID isrContext, PSDIO_ISR_HANDLER pIsrHandler) +{ + ENTER(); + + pDev->isrContext = isrContext; + pDev->pIsr = pIsrHandler; + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SDIO_RegisterIsrHandler() fdo=0x%8.08X ctx=0x%p handler=0x%8.08X\n", + (ULONG) pDev, isrContext, (ULONG) pIsrHandler)); + LEAVE(); +} + +// for filling the "/proc/mrvsdio" entry +int +mrvlsdio_read_procmem(char *buf, + char **start, + off_t offset, int count, int *eof, void *data) +{ + int len = 0; + + if (fdo_data != NULL) { + // after probe-event, we have "good" data in /proc/mrvsdio + len = + sprintf(buf, + "mrvlsdio is running with:\nbus_type = 0x%x\nbus_with = 0x%x\nclock_speed = 0x%x\ndebug_flags = 0x%x\nblock_size = 0x%x\nsdio_voltage = 0x%x\n", + fdo_data->common.bus_type, fdo_data->common.bus_width, + fdo_data->common.ClockSpeed, fdo_data->common.debug_flags, + fdo_data->common.blockSize, + fdo_data->common.sdio_voltage); + } else { + // not probed yet + len = sprintf(buf, "mrvlsdio is up and waiting for card\n"); + } + + *eof = 1; + return (len); +} + +static int +mrvlsdio_init_module(void) +{ + int ret; + + // generate /proc/ entry + create_proc_read_entry("mrvlsdio", // entry in "/proc/mrvlsdio" + 0, // file attributes + NULL, // parent dir + mrvlsdio_read_procmem, // name of function + NULL); // client data + + DBGPRINT(DBG_ALL, ("*** mrvlsdio ***\n")); + DBGPRINT(DBG_ALL, ("*** Built on %s %s ***\n", __DATE__, __TIME__)); + + /*--- mmoser 4/4/2006 ---*/ + fdo_data = + (PFDO_DEVICE_DATA) kmalloc(sizeof(FDO_DEVICE_DATA), GFP_KERNEL); + + if (fdo_data == NULL) { + return -ENOMEM; + } + memset(fdo_data, 0, sizeof(FDO_DEVICE_DATA)); + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Module mrvlsdio init: INIT_WORK\n")); + + INIT_WORK(&sdiobus_wq, (void (*)(void *)) SDIOBus_Dpc, NULL); + + ret = register_chrdev(sdio_major, "mrvlsdio", &mrvlsdio_fops); + if (ret < 0) { + DBGPRINT(DBG_LOAD, + (KERN_WARNING "mrvlsdio: can't get major %d ret=%d\n", + sdio_major, ret)); + } else { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "mrvlsdio: major %d\n", ret)); + } + if (sdio_major == 0) + sdio_major = ret; /* dynamic */ + + /** from 2.4 kernel source: + * pci_register_driver - register a new pci driver + * + * Adds the driver structure to the list of registered drivers + * Returns the number of pci devices which were claimed by the driver + * during registration. The driver remains registered even if the + * return value is zero. + */ + + ret = pci_register_driver(&mrvlsdio); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: pci_register_driver with %d\n", __FILE__, ret)); + +// return (ret); + return 0; +} + +static void +mrvlsdio_exit_module(void) +{ + // remove proc entry + remove_proc_entry("mrvlsdio", NULL); + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Module mrvlsdio exit\n")); + + unregister_chrdev(sdio_major, "mrvlsdio"); + pci_unregister_driver(&mrvlsdio); + + /*--- mmoser 4/4/2006 ---*/ + kfree(fdo_data); + + fdo_data = NULL; +} + +module_init(mrvlsdio_init_module); +module_exit(mrvlsdio_exit_module); + +EXPORT_SYMBOL(mrvlsdio_get_interface); +EXPORT_SYMBOL(mrvlsdio_register_callbacks); + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/skisr.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/skisr.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/skisr.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/skisr.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,460 @@ +/****************************************************************************** + * + * Name: sdiobus.c + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:21:35 $ + * Purpose: This module handles the interrupts. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: skisr.c,v $ + * Revision 1.1 2007/01/18 09:21:35 pweber + * Put under CVS control + * + * + ******************************************************************************/ + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +#ifdef WINNT +VOID +SDIOBus_Dpc(IN PKDPC Dpc, + IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) +{ + SK_U8 is, rsr_value, ucValue = 0; + SK_U32 irq_status, status, j, ulVal, ulDataLineMask, loops; + SK_U16 usValue; + PCOMMON_DEVICE_DATA commonData; + PFDO_DEVICE_DATA FdoData; + + DBGPRINT(DBG_IRQ, ("SDIOBUS_Dpc\n")); + + if (DeviceObject == NULL) { + DBGPRINT(DBG_ERROR, ("SDIOBUS_Dpc : DeviceObject == NULL !\n")); + return; + } + + FdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; + + if (FdoData == NULL) { + DBGPRINT(DBG_ERROR, ("SDIOBUS_Dpc : FdoData == NULL !\n")); + return; + } + + irq_status = FdoData->common.lastIntStatus; + + if ((irq_status & STDHOST_NORMAL_IRQ_CARD_OUT) == + STDHOST_NORMAL_IRQ_CARD_OUT) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) FdoData, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CARD_OUT); + + /*--- mmoser 14.09.2005 ---*/ + if (FdoData->common.initialized) { + DmBGPRINT(DBG_IRQ | DBG_W528D, + ("SDIOBUS_Dpc : NORMAL_IRQ_CARD_OUT\n")); + + /*--- mmoser 10.08.2005 ---*/ + DBGPRINT(DBG_IRQ, ("CARD REMOVED\n")); + KeSetEvent(&FdoData->common.CardOutEvent, 0, FALSE); + } + return; + } + if ((irq_status & STDHOST_NORMAL_IRQ_CARD_IN) == + STDHOST_NORMAL_IRQ_CARD_IN) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) FdoData, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CARD_IN); + + DBGPRINT(DBG_IRQ, ("SDIOBUS_Dpc : NORMAL_IRQ_CARD_IN\n")); + DBGPRINT(DBG_IRQ, ("CARD PLUGGED IN\n")); + KeSetEvent(&FdoData->common.CardInEvent, 0, FALSE); + return; + } + if ((irq_status & STDHOST_NORMAL_IRQ_CARD) == STDHOST_NORMAL_IRQ_CARD) { + PCOMMON_DEVICE_DATA pDev = (PCOMMON_DEVICE_DATA) FdoData; + + status = (irq_status << 16); + + if (FdoData->common.pIsr != NULL) { + DBGPRINT(DBG_IRQ, ("Call registered interrupt handler.\n")); + (*FdoData->common.pIsr) (FdoData->common.isrContext, status); + } else { + DBGPRINT(DBG_IRQ, + ("No interrupt handler registered. (fdo=%p)\n", + FdoData)); + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) FdoData, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + return; + } + + MEM_READ_ULONG(&FdoData->common, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulVal); + if (FdoData->common.bus_type == SDIO_SPI_TYPE || + ((FdoData->common.bus_type == SDIO_BUS_TYPE) && + (FdoData->common.bus_width == SDIO_1_BIT))) { + if ((ulVal & STDHOST_STATE_DAT1_LINE_LVL) == 0) { + DBGPRINT(DBG_IRQ, + ("SDHost_Dpc() : Interrupt Line is active !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")); + } + } + } else { + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) FdoData, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, 0xFFFF); + DBGPRINT(DBG_ERROR, + ("SDIOBus_Dpc(): Unhandled IRQ : 0x%8.08X.\n", irq_status)); + } + + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) FdoData, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); +} + +BOOLEAN +SDIOBus_Isr(IN PKINTERRUPT Interrupt, IN PVOID Context) +{ + SK_U32 tmp; + SK_U8 ucValue, rsr_value; + PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context; + PCOMMON_DEVICE_DATA commonData; + + if (deviceObject == NULL) { + DBGPRINT(DBG_IRQ, ("SDIOBUS_Isr : deviceObject == NULL !\n")); + return SK_TRUE; + } + + commonData = (PCOMMON_DEVICE_DATA) deviceObject->DeviceExtension; + + if (commonData == NULL) { + DBGPRINT(DBG_IRQ, ("SDIOBUS_Isr : commonData == NULL !\n")); + return SK_TRUE; + } + // Clear ISR status + MEM_READ_ULONG(commonData, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, &tmp); + + DBGPRINT(DBG_IRQ, ("I%8.08X (%s:0x%8.08X)\n", tmp, + commonData->IsFDO ? "FDO" : "PDO", + commonData->lastIRQSignalMask)); + + // Check if interrupt came from our device + if (((tmp & STDHOST_NORMAL_IRQ_ERROR) != 0 || + (tmp & commonData->lastIRQSignalMask) != 0) && tmp != 0xFFFFFFFF) { + PCOMMON_DEVICE_DATA pDev = (PCOMMON_DEVICE_DATA) commonData; + commonData->lastIntStatus = tmp; + DBGPRINT(DBG_IRQ, + ("SDIOBUS_Isr (0x%4.04X)\n", commonData->lastIntStatus)); + + SDHost_DisableInterrupt(commonData, STDHOST_NORMAL_IRQ_ALL_SIG_ENA); + IoRequestDpc(deviceObject, deviceObject->CurrentIrp, NULL); + return SK_TRUE; + } else { + return SK_FALSE; + } +} +#else // #ifdef WINNT + +static void (*gpio_int_callback) (void *) = NULL; +static void *gpio_int_callback_arg = NULL; + +int +request_gpio_irq_callback(void (*callback) (void *), void *arg) +{ + if (!gpio_int_callback && !gpio_int_callback_arg) { + gpio_int_callback = callback; + gpio_int_callback_arg = arg; + return 0; + } + return -1; +} + +EXPORT_SYMBOL(request_gpio_irq_callback); + +int +release_gpio_irq_callback(void (*callback) (void *), void *arg) +{ + if ((callback == gpio_int_callback) + && (arg == gpio_int_callback_arg)) { + gpio_int_callback = NULL; + gpio_int_callback_arg = NULL; + return 0; + } + return -1; +} + +EXPORT_SYMBOL(release_gpio_irq_callback); + +DECLARE_TASKLET(SDIOBus_tasklet, SDIOBus_Dpc, 0); + +void +SDIOBus_Dpc(unsigned long arg) +{ + SK_U32 irq_status, status, ulVal; + SK_U16 errorIRQ_status = 0; + PFDO_DEVICE_DATA FdoData; + PCOMMON_DEVICE_DATA pDev; + + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc startet ....\n")); + + if (arg == 0) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "SDIOBUS_Dpc : arg == NULL !\n")); + return; + } + + FdoData = (PFDO_DEVICE_DATA) arg; + + if (FdoData == NULL) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "SDIOBUS_Dpc : FdoData == NULL !\n")); + return; + } + pDev = (PCOMMON_DEVICE_DATA) & FdoData->common; + irq_status = FdoData->common.lastIntStatus; + + if ((irq_status & STDHOST_NORMAL_IRQ_ERROR) != 0) { + MEM_READ_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_ERROR_IRQ_STATUS, &errorIRQ_status); + if ((errorIRQ_status & STDHOST_ERROR_IRQ_GPI_0) != 0) { + if ((FdoData->common. + lastErrorIRQSignalMask & STDHOST_ERROR_IRQ_GPI_0) != 0) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, + SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, + STDHOST_ERROR_IRQ_GPI_0); + } + } + if ((errorIRQ_status & STDHOST_ERROR_IRQ_GPI_1) != 0) { + if ((FdoData->common. + lastErrorIRQSignalMask & STDHOST_ERROR_IRQ_GPI_1) != 0) { + printk("GPI-1 interrupt fired (0x%4.04X)\n", errorIRQ_status); + /*--- mmoser 3/12/2007 ---*/ + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, + SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, + STDHOST_ERROR_IRQ_GPI_1); + + SDHost_SetClock(pDev, 1); + if (gpio_int_callback && gpio_int_callback_arg) + gpio_int_callback(gpio_int_callback_arg); + } + } + } + + if ((irq_status & STDHOST_NORMAL_IRQ_CARD_OUT) == + STDHOST_NORMAL_IRQ_CARD_OUT) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CARD_OUT); + + /*--- mmoser 14.09.2005 ---*/ + if (FdoData->common.initialized) { + DBGPRINT(DBG_IRQ | DBG_W528D, + (KERN_DEBUG "SDIOBUS_Dpc : NORMAL_IRQ_CARD_OUT\n")); + + /*--- mmoser 10.08.2005 ---*/ + DBGPRINT(DBG_IRQ, (KERN_DEBUG "CARD REMOVED\n")); + SDIOBus_CardRemoved(FdoData); + + /*--- mmoser 3/31/2006 ---*/ + FdoData->common.SurpriseRemoved = SK_TRUE; + } + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) & FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc finished.\n")); + return; + } + if ((irq_status & STDHOST_NORMAL_IRQ_CARD_IN) == + STDHOST_NORMAL_IRQ_CARD_IN) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CARD_IN); + + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc : NORMAL_IRQ_CARD_IN\n")); + DBGPRINT(DBG_IRQ, (KERN_DEBUG "CARD PLUGGED IN\n")); + SDIOBus_CardPluggedIn(FdoData); + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) & FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc finished.\n")); + return; + } + + if ((irq_status & STDHOST_NORMAL_IRQ_CARD) == STDHOST_NORMAL_IRQ_CARD) { + status = (irq_status << 16); + + if (FdoData->common.pIsr != NULL) { + DBGPRINT(DBG_IRQ, (KERN_DEBUG "Call registered interrupt handler.\n")); /*--- mmoser 3/20/2006 ---*/ + /* + * reverse args order for compatibility of Marvell Linux drive + */ + (*FdoData->common.pIsr) (status, FdoData->common.isrContext, + NULL); + return; + } else { + DBGPRINT(DBG_IRQ, + (KERN_DEBUG + "No interrupt handler registered. (fdo=%p)\n", + FdoData)); + SDHost_EnableInterrupt(&FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc finished.\n")); + return; + } + MEM_READ_ULONG(&FdoData->common, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulVal); + if (FdoData->common.bus_type == SDIO_SPI_TYPE || + ((FdoData->common.bus_type == SDIO_BUS_TYPE) && + (FdoData->common.bus_width == SDIO_1_BIT))) { + if ((ulVal & STDHOST_STATE_DAT1_LINE_LVL) == 0) { + DBGPRINT(DBG_IRQ, + (KERN_DEBUG + "SDHost_Dpc() : Interrupt Line is active !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")); + } + } + } + + if (irq_status & (STDHOST_NORMAL_IRQ_ERROR | + STDHOST_NORMAL_IRQ_TRANS_COMPLETE | + STDHOST_NORMAL_IRQ_CMD_COMPLETE)) { + if (((irq_status & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) && + (FdoData->common. + tmpIRQSignalMask & STDHOST_NORMAL_IRQ_TRANS_COMPLETE)) || + ((irq_status & STDHOST_NORMAL_IRQ_CMD_COMPLETE) && + (FdoData->common. + tmpIRQSignalMask & STDHOST_NORMAL_IRQ_CMD_COMPLETE)) || + ((errorIRQ_status & STDHOST_ERROR_IRQ_GPI_1) && + (FdoData->common. + lastErrorIRQSignalMask & STDHOST_ERROR_IRQ_GPI_1)) + + ) + { + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) & FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + } + return; + } else { + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, 0xFFFF); + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_ERROR_IRQ_STATUS, 0xFFFF); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "SDIOBus_Dpc(): Unhandled IRQ : 0x%8.08X.\n", + irq_status)); + } + + SDHost_EnableInterrupt((PCOMMON_DEVICE_DATA) & FdoData->common, + STDHOST_NORMAL_IRQ_CARD_ALL_ENA); + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Dpc finished.\n")); +} + +irqreturn_t +SDIOBus_Isr(int irq, void *dev_id, struct pt_regs *regs) +{ + SK_U32 tmp; + SK_U16 tmpsig; + PFDO_DEVICE_DATA FdoData; + PCOMMON_DEVICE_DATA pDev; + + if (dev_id == NULL) { + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Isr : dev_id == NULL !\n")); + return IRQ_HANDLED; + } + + FdoData = (PFDO_DEVICE_DATA) dev_id; + + if (FdoData == NULL) { + DBGPRINT(DBG_IRQ, (KERN_DEBUG "SDIOBUS_Isr : FdoData == NULL !\n")); + return IRQ_HANDLED; + } + + pDev = (PCOMMON_DEVICE_DATA) & FdoData->common; + MEM_READ_ULONG(&FdoData->common, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + &tmp); + MEM_READ_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_ERROR_IRQ_SIGNAL_ENABLE, &tmpsig); + + // Check if interrupt came from our device + if (((((tmp & STDHOST_NORMAL_IRQ_ERROR) != 0) && + ((tmpsig & (STDHOST_ERROR_IRQ_GPI_1 | STDHOST_ERROR_IRQ_GPI_0)) != + 0)) || ((tmp & FdoData->common.lastIRQSignalMask) != 0)) && + tmp != 0xFFFFFFFF) + { + /*--- mmoser 8/29/2006 ---*/ + if (tmp & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + if (FdoData->common. + lastIRQSignalMask & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, + SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_TRANS_COMPLETE); + + if (!test_and_set_bit + (0, &FdoData->common.trans_complete_evt.event)) { + wake_up(&FdoData->common.trans_complete_evt.wq); + } + } + } + + if (tmp & STDHOST_NORMAL_IRQ_CMD_COMPLETE) { + if (FdoData->common. + lastIRQSignalMask & STDHOST_NORMAL_IRQ_CMD_COMPLETE) { + // clear irq bit + MEM_WRITE_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, + SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CMD_COMPLETE); + + if (!test_and_set_bit + (0, &FdoData->common.cmd_complete_evt.event)) { + wake_up(&FdoData->common.cmd_complete_evt.wq); + } + } + } + + MEM_READ_USHORT((PCOMMON_DEVICE_DATA) & FdoData->common, SK_SLOT_0, + STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + &FdoData->common.lastErrorIRQSignalMask); + FdoData->common.lastIntStatus = tmp; + DBGPRINT(DBG_IRQ, + (KERN_DEBUG "SDIOBUS_Isr (0x%4.04X)\n", + FdoData->common.lastIntStatus)); + + SDHost_DisableInterrupt(&FdoData->common, + STDHOST_NORMAL_IRQ_ALL_SIG_ENA); + + SDIOBus_tasklet.data = (unsigned long) FdoData; + tasklet_schedule(&SDIOBus_tasklet); + + } else { + return IRQ_NONE; + } + return IRQ_HANDLED; + +} +#endif // !#ifdef WINNT diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/stdhost.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/stdhost.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/io/sdio/syskt/stdhost/stdhost.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/io/sdio/syskt/stdhost/stdhost.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,3516 @@ +/****************************************************************************** + * + * Name: stdhost.c + * Project: Wireless LAN, Bus driver for SDIO interface + * Version: $Revision: 1.1 $ + * Date: $Date: 2007/01/18 09:21:35 $ + * Purpose: This module handles the SDIO Standard Host Interface. + * + ******************************************************************************/ + +/****************************************************************************** + * + * (C)Copyright 2004-2005 Marvell + * + * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SYSKONNECT + * The copyright notice above does not evidence any + * actual or intended publication of such source code. + * + * This Module contains Proprietary Information of SysKonnect + * and should be treated as Confidential. + * + * The information in this file is provided for the exclusive use of + * the licensees of SysKonnect. + * Such users have the right to use, modify, and incorporate this code + * into products for purposes authorized by the license agreement + * provided they include this notice and the associated copyright notice + * with any such product. + * The information in this file is provided "AS IS" without warranty. + * + ******************************************************************************/ + +/****************************************************************************** + * + * History: + * + * $Log: stdhost.c,v $ + * Revision 1.1 2007/01/18 09:21:35 pweber + * Put under CVS control + * + * Revision 1.4 2005/12/08 12:00:27 ebauer + * Driver ckecks AND update voltage registry value if not correct + * + * Revision 1.3 2005/12/07 13:40:19 ebauer + * Modify check of registry voltage value + * + * Revision 1.2 2005/10/31 10:34:59 jschmalz + * Bugfixes Chariot (Interface hang) + * + * Revision 1.1 2005/10/07 08:43:47 jschmalz + * Put SDIO with FPGA under CVS control + * + * + ******************************************************************************/ + +#include "h/skdrv1st.h" +#include "h/skdrv2nd.h" + +//define the SD Block Size +//for SD8381-B0 chip, it could be 32,64,128,256,512 +//for all other chips including SD8381-A0, it must be 32 +#define POLLING_TIMES 2000 + +#define USE_FPGA_POWER_RAMP +// #define DMA_SUPPORT_RD +// #define DMA_SUPPORT_WR +// #define FIFO_CMD52_DEBUG + +/****************************************************************************** + * + * SDHost_InitializeCard - Initialize the plugged in SDIO card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * TRUE on success + */ +SK_BOOL +SDHost_InitializeCard(PCOMMON_DEVICE_DATA pDev) +{ + SK_U8 OCR[3]; + SK_U8 RCA[2]; + SK_U8 Cis[DEVICE_NAME_LENGTH]; + SK_U16 usVal, ucPowerCurr[FPGA_POWER_STEPS] = FPGA_POWER_VAL_ENUM; + SK_U8 ucValue; + SK_U8 ucConfigId; + SK_U8 ucPowerValue = 0; + SK_U8 R; + SK_U32 ulArg; + SK_U32 j, i, ulValue, ulResponse, cnt; + SK_U32 cislength; + SK_U32 RegVal; + + SDHost_DisableInterrupt(pDev, STDHOST_NORMAL_IRQ_ALL_SIG_ENA); + + _SLEEP_MS(pDev, 100); + + DBGPRINT(DBG_W528D, (KERN_DEBUG "SDHost_InitializeCard()\n")); + /*--- mmoser 3/7/2006 ---*/ + cnt = 0; + + pDev->crc_len = 0; + + ZERO_MEMORY(OCR, 3); + ZERO_MEMORY(RCA, 2); + ZERO_MEMORY(Cis, DEVICE_NAME_LENGTH); + + // Setup the SD clock + if (pDev->baseClockFreq == 0) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "Base clock frequency not available!\n")); + return SK_FALSE; + } + + usVal = MK_CLOCK((SK_U16) pDev->ClockSpeed) | STDHOST_INTERNAL_CLK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + for (j = 0; j < MAX_WAIT_CLOCK_STABLE; j++) { + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, &usVal); + if ((usVal & STDHOST_INTERNAL_CLK_STABLE) == + STDHOST_INTERNAL_CLK_STABLE) { + break; + } + } + if (j >= MAX_WAIT_CLOCK_STABLE) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "SD clock remains unstable!\n")); + return SK_FALSE; + } + // Enable clock to card + usVal |= STDHOST_CLOCK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + + // enable DMA support depending on ChipRev + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_CHIP_REVISION, &ucValue); + DBGPRINT(DBG_ERROR, (KERN_DEBUG "ChipRevision: 0x%x\n", ucValue)); + { + SK_U8 hi, lo; + lo = ucValue & 0x0F; + hi = (ucValue >> 4) & 0x0F; + printk("\n****************************************************\n"); + printk("********* FPGA-ChipRevision: %x.%x (0x%2.02X) *********\n", + hi, lo, ucValue); + printk("****************************************************\n"); + } + if (ucValue >= FPGA_CHIP_REV_2_0) { + pDev->dma_support = 0; + if ((pDev->debug_flags & DEBUG_USE_RD_DMA) == DEBUG_USE_RD_DMA) + pDev->dma_support |= DMA_RD_SUPPORT; + + if ((pDev->debug_flags & DEBUG_USE_WR_DMA) == DEBUG_USE_WR_DMA) + pDev->dma_support |= DMA_WR_SUPPORT; + + // pDev->dma_support = DMA_WR_SUPPORT | DMA_RD_SUPPORT; + // pDev->dma_support = DMA_RD_SUPPORT; + // pDev->dma_support = 0; + } else { + pDev->dma_support = 0; + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "***************************************************\n")); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "* CardBus-to-SDIO Adapter FPGA Rev: V0x%x *\n", + ucValue)); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "* This FPGA revision does NOT support DMA mode, *\n")); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "* please update your adapter to Rev 20 or higher *\n")); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "***************************************************\n")); + } + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "DMA_SUPPORT: 0x%x\n", pDev->dma_support)); + printk + ("**************++ DMA_SUPPORT: 0x%x debug_flags=0x%8.08X ++************************\n", + pDev->dma_support, pDev->debug_flags); + // pweber / tschrobenhauser 03.08.2005 + // check the power regulator output voltage is stable + // WAIT UNTIL ADDR 0x20E, Bit 0 == 1 + + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_CARD_REVISION, &ucValue); + DBGPRINT(DBG_ERROR, (KERN_DEBUG "CardRevision: 0x%x\n", ucValue)); + if (ucValue == FPGA_CARD_REV_1_1) { +// SK_U8 ucConfigId; +// SK_U8 ucPowerValue=0; +#ifdef WINNT + // ebauer 19.08.2005: Get Voltage Value from Registry + SDIO_RegGetDword(RTL_REGISTRY_ABSOLUTE, + RegistryPath.Buffer, L"SDIOVoltage", &RegVal); +#else + // LINUX: get voltage value from module parameter 'sdio_voltage' + RegVal = pDev->sdio_voltage; +#endif + + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_CONFIG_ID, &ucConfigId); + if (ucConfigId & FPGA_CONFIG_3_3_V) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "Configuration ID : 3.3V\n")); + // Check if registry value is ok + if ((RegVal >= FPGA_POWER_REG_3_3_V_MIN) && + (RegVal <= FPGA_POWER_REG_3_3_V_MAX)) { + ucPowerValue = (SK_U8) RegVal; + } else { + ucPowerValue = FPGA_POWER_REG_3_3_V; +#ifdef WINNT + RegVal = 0x00ff & ucPowerValue; + + SDIO_RegSetDword(RTL_REGISTRY_ABSOLUTE, + RegistryPath.Buffer, + L"SDIOVoltage", &RegVal, sizeof(SK_U32)); +#endif + } + } else if (ucConfigId & FPGA_CONFIG_2_5_V) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "Configuration ID : 2.5V\n")); + // Check if registry value is ok + if ((RegVal >= FPGA_POWER_REG_2_5_V_MIN) && + (RegVal <= FPGA_POWER_REG_2_5_V_MAX)) { + ucPowerValue = (SK_U8) RegVal; + } else { + ucPowerValue = FPGA_POWER_REG_2_5_V; +#ifdef WINNT + RegVal = 0x00ff & ucPowerValue; + SDIO_RegSetDword(RTL_REGISTRY_ABSOLUTE, + RegistryPath.Buffer, + L"SDIOVoltage", &RegVal, sizeof(SK_U32)); +#endif + } + } else if (ucConfigId & FPGA_CONFIG_1_8_V) { + DBGPRINT(DBG_ERROR, (KERN_DEBUG "Configuration ID : 1.8V\n")); + // Check if registry value is ok + if ((RegVal >= FPGA_POWER_REG_1_8_V_MIN) && + (RegVal <= FPGA_POWER_REG_1_8_V_MAX)) { + ucPowerValue = (SK_U8) RegVal; + } else { + ucPowerValue = FPGA_POWER_REG_1_8_V; +#ifdef WINNT + RegVal = 0x00ff & ucPowerValue; + SDIO_RegSetDword(RTL_REGISTRY_ABSOLUTE, + RegistryPath.Buffer, + L"SDIOVoltage", &RegVal, sizeof(SK_U32)); +#endif + } + } + } +#ifndef USE_FPGA_POWER_RAMP // [fhm] ramp-up SDIO port voltage + + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_DATA, ucPowerValue); + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_CMD, + FPGA_POWER_REG_CMD_START); + + DBGPRINT(DBG_ERROR, (KERN_DEBUG "wait for stable voltage\n")); + cnt = 0; + do { + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_STATUS, &ucValue); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "PowerRegulatorControl: 0x%x\n", ucValue)); + } while (++cnt < 10000 && (ucValue & FPGA_POWER_REG_STABLE) == 0); + DBGPRINT(DBG_ERROR, ("wait for stable voltage: cnt=%d\n", cnt)); + + // Turn on highest supplied voltage + ucValue = MK_VOLTAGE(pDev->maxSupplyVoltage); + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_POWER_CTRL, ucValue); + + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "MaxSupplyVoltage: %d\n", pDev->maxSupplyVoltage)); + + ucValue = MK_VOLTAGE(pDev->maxSupplyVoltage) | STDHOST_POWER_ON; + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_POWER_CTRL, ucValue); + +#else + _SLEEP_MS(pDev, 100); // [mb] for de-bounce + for (i = 0; i < FPGA_POWER_STEPS; i++) { + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_DATA, + (SK_U8) ucPowerCurr[i]); + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_CMD, + FPGA_POWER_REG_CMD_START); + + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "wait for stable voltage (0x%x)\n", + ucPowerCurr[i])); + cnt = 0; + do { + MEM_READ_UCHAR(pDev, SK_SLOT_0, FPGA_POWER_REG_STATUS, &ucValue); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "PowerRegulatorControl: 0x%x\n", ucValue)); + } while (++cnt < 10000 && (ucValue & FPGA_POWER_REG_STABLE) == 0); + DBGPRINT(DBG_ERROR, ("wait for stable voltage: cnt=%d\n", cnt)); + if (cnt == 10000) + return SK_FALSE; + + // switch on SDIO port voltage if lowest voltage is stable + if (ucPowerCurr[i] == FPGA_POWER_REG_0_7_V) { + ucValue = MK_VOLTAGE(pDev->maxSupplyVoltage); + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_POWER_CTRL, ucValue); + ucValue = MK_VOLTAGE(pDev->maxSupplyVoltage) | STDHOST_POWER_ON; +//[mb] + _SLEEP_MS(pDev, 50); //wait until voltage has reached the set level + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_POWER_CTRL, ucValue); + } + // leave for loop, if desired power level has been set + if (ucPowerCurr[i] == (SK_U16) ucPowerValue) + break; +//[mb] + if ((ucPowerCurr[i] < FPGA_POWER_REG_1_2_V) && + (ucPowerCurr[i] > FPGA_POWER_REG_1_0_V)) + UDELAY(FPGA_POWER_RAMP_DELAY * 6); + else + UDELAY(FPGA_POWER_RAMP_DELAY); + if (i < FPGA_POWER_STEPS - 1) { + if (ucPowerCurr[i + 1] > (SK_U16) ucPowerValue) + ucPowerCurr[i + 1] = (SK_U16) ucPowerValue; + } + } + +#endif // [fhm] + + _SLEEP_MS(pDev, 100); // pweber 03.08.2005 + + if (pDev->bus_type == SDIO_SPI_TYPE) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG "--------------> SPI-Mode : Send CMD0\n")); + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x200, &ulValue); + ulValue |= 0x00000001; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, 0x200, ulValue); + + SDHost_SendCmd(pDev, 0, 0, 0, &ulResponse); // CMD0 for transit to SPI mode + SDHost_SendCmd(pDev, 59, 0, 0, &ulResponse); // CMD59 turn off CRC + } +// _SLEEP_MS( pDev, 100); pweber 03.08.2005 + + if (!SDHost_ReadOCR(pDev, OCR)) { + DBGPRINT(DBG_W528D | DBG_ERROR, (KERN_DEBUG "ReadOCR failed!\n")); + return SK_FALSE; + } + // check if our supply voltage is supported + + if ((OCR[0] & 0xE0) == 0) // Support for 3.3 - 3.6 V + { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG "Card does not support our supply voltage!\n")); + return SK_FALSE; + } + + if (!SDHost_WriteOCR(pDev, OCR)) { + DBGPRINT(DBG_W528D | DBG_ERROR, (KERN_DEBUG "WriteOCR failed!\n")); + return SK_FALSE; + } + + if (pDev->bus_type == SDIO_BUS_TYPE) { + // Send CMD3 ident -> standby + if (!SDHost_ReadRCA(pDev, RCA)) { + return SK_FALSE; + } + + if (RCA[0] == 0 && RCA[1] == 0) { + // Try to get new RCA + if (!SDHost_ReadRCA(pDev, RCA)) { + return SK_FALSE; + } + if (RCA[0] == 0 && RCA[1] == 0) { + // Failed to get a valid RCA + return SK_FALSE; + } + } + ulArg = RCA[0] << 24 | RCA[1] << 16; + //CMD7 to select card and go to transfer state. + if (!SDHost_SendCmd(pDev, 7, ulArg, 0, &ulResponse)) { + if (++pDev->bus_errors > MAX_BUS_ERRORS) { + SDHost_SetCardOutEvent(pDev); + } + return SK_FALSE; + } + } + + j = 0; + while (j++ < 5) { + // IO Enable function 0 + if (SDHost_CMD52_Read(pDev, 0x02, 0, &R)) { + if (!R) { + if (SDHost_CMD52_Write(pDev, 0x02, 0, 0x02)) { + SDHost_CMD52_Read(pDev, 0x02, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 : I/O Enable(R/W) 0x%2.02X\n", + R)); + } + } + break; + } + } + + if (j >= 5) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 : I/O Enable FAILED!!!!!!!!!!!!\n")); + return SK_FALSE; + } + + /*--- mmoser 3/22/2006 ---*/ + j = 0; + while (j++ < 5) { + // INT Enable function 0 + if (SDHost_CMD52_Write(pDev, 0x04, 0, 0x03)) { + SDHost_CMD52_Read(pDev, 0x04, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 : INT Enable 0x%2.02X\n", R)); + break; + } + } + + if (j >= 5) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 : INT Enable FAILED!!!!!!!!!!!!\n")); + return SK_FALSE; + } + + // IO Ready function 1 + if (SDHost_CMD52_Read(pDev, 0x03, 0, &R)) { + DBGPRINT(DBG_W528D, (KERN_DEBUG "I/O Ready(R/O) 0x%2.02X\n", R)); + } + //Read Card Capability + if (SDHost_CMD52_Read(pDev, 0x08, 0, &R)) { +#ifdef DBG + DBGPRINT(DBG_W528D, (KERN_DEBUG "Card Capability\n")); + if (R & 0x01) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " SDC:CMD52 supported\n")); + } else { + DBGPRINT(DBG_W528D, + (KERN_DEBUG " SDC:CMD52 not support\n")); + } + if (R & 0x02) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " SMB:CMD53 supported\n")); + } else { + DBGPRINT(DBG_W528D, + (KERN_DEBUG " SMB:CMD53 not support\n")); + } + if (R & 0x04) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG " SRW:Read Wait supported\n")); + } else { + DBGPRINT(DBG_W528D, + (KERN_DEBUG " SRW:Read Wait not support\n")); + } + if (R & 0x08) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " SBS supported\n")); + } else { + DBGPRINT(DBG_W528D, (KERN_DEBUG " SBD not support\n")); + } + if (R & 0x10) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " S4MI supported\n")); + } else { + DBGPRINT(DBG_W528D, (KERN_DEBUG " S4MI not support\n")); + } + if (R & 0x20) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " E4MI supported(R/W)\n")); + } else { + DBGPRINT(DBG_W528D, + (KERN_DEBUG " E4MI not support(R/W)\n")); + } + if (R & 0x40) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " LSC supported\n")); + } else { + DBGPRINT(DBG_W528D, (KERN_DEBUG " LSC not support\n")); + } + if (R & 0x80) { + DBGPRINT(DBG_W528D, (KERN_DEBUG " 4BLS supported\n")); + } else { + DBGPRINT(DBG_W528D, (KERN_DEBUG " 4BLS not support\n")); + } +#endif + } + if (SDHost_CMD52_Read(pDev, 0x0D, 0, &R)) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "Card Function Selected for Suspend/Resume(R/W) 0x%2.02X!\n", + R)); + } + //Exec Flags + if (SDHost_CMD52_Read(pDev, 0x0E, 0, &R)) { + DBGPRINT(DBG_W528D, (KERN_DEBUG "Exec Flags(R/O)0x%2.02X\n", R)); + } + //Ready Flags + if (SDHost_CMD52_Read(pDev, 0x0F, 0, &R)) { + DBGPRINT(DBG_W528D, (KERN_DEBUG "Ready Flags(R/O)0x%2.02X\n", R)); + } + + if (pDev->bus_width == SDIO_4_BIT) { + SDHost_CMD52_Write(pDev, 0x07, 0, 0x82); //0x80:CD disable,1 bit;0x82:CD disable,4 bit + } else { + SDHost_CMD52_Write(pDev, 0x07, 0, 0x80); //0x80:CD disable,1 bit;0x82:CD disable,4 bit + } + + SDHost_CMD52_Read(pDev, 0x07, 0, &R); + + switch (R & 0x0F) { + case 0x02: + DBGPRINT(DBG_W528D, (KERN_DEBUG "4 bit mode,")); + break; + case 0x00: + DBGPRINT(DBG_W528D, (KERN_DEBUG "1 bit mode,")); + break; + default: + DBGPRINT(DBG_W528D, (KERN_DEBUG "1 or 4 bit mode error,")); + } + if ((R & 0xF0) == 0x80) { + DBGPRINT(DBG_W528D, (KERN_DEBUG "CD Disable!\n")); + } else { + DBGPRINT(DBG_W528D, (KERN_DEBUG "CD Enable!\n")); + } + + //function0 block size + + if (SDHost_CMD52_Read(pDev, 0x10, 0, &R)) { + if (R < (SK_U8) (pDev->blockSize & 0x00FF)) { + if (SDHost_CMD52_Write + (pDev, 0x10, 0, (SK_U8) (pDev->blockSize & 0x00FF))) { + SDHost_CMD52_Read(pDev, 0x10, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 block size:0x%2.02X (%d)\n", R, R)); + } + + if (SDHost_CMD52_Write + (pDev, 0x11, 0, (SK_U8) (pDev->blockSize >> 8))) { + SDHost_CMD52_Read(pDev, 0x11, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 block size:0x%2.02X (%d)\n", R, R)); + } + } + } + //function1 block size + if (SDHost_CMD52_Read(pDev, 0x110, 0, &R)) { + if (R < (SK_U8) (pDev->blockSize & 0x00FF)) { + if (SDHost_CMD52_Write + (pDev, 0x110, 0, (SK_U8) (pDev->blockSize & 0x00FF))) { + SDHost_CMD52_Read(pDev, 0x110, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 block size:0x%2.02X (%d)\n", R, R)); + } + + if (SDHost_CMD52_Write + (pDev, 0x111, 0, (SK_U8) (pDev->blockSize >> 8))) { + SDHost_CMD52_Read(pDev, 0x111, 0, &R); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "FN0 block size:0x%2.02X (%d)\n", R, R)); + } + } + } + + cislength = DEVICE_NAME_LENGTH; + if (!SDHost_ReadCIS(pDev, 0, 0x15, Cis, &cislength)) { + return SK_FALSE; + } + if (cislength > 0) { +#ifdef WINNT + memcpy(pDev->DeviceName, L"SDIOBus\\", 16); + for (i = 0, j = 16; i < cislength; i++) { + pDev->DeviceName[j++] = (Cis[i] == ' ' ? '_' : Cis[i]); + pDev->DeviceName[j++] = 0; + } + pDev->DeviceName[j++] = 0; + pDev->DeviceName[j++] = 0; + pDev->DeviceNameLength = j; + DBGPRINT(DBG_W528D, + (KERN_DEBUG " DeviceName (len=%d): %ws\n", + pDev->DeviceNameLength, pDev->DeviceName)); +#else + memcpy(pDev->DeviceName, "SDIOBus\\", 8); + for (i = 0, j = 8; i < cislength; i++) { + pDev->DeviceName[j++] = (Cis[i] == ' ' ? '_' : Cis[i]); + } + pDev->DeviceName[j++] = 0; + pDev->DeviceNameLength = j; + DBGPRINT(DBG_W528D, + (KERN_DEBUG " DeviceName (len=%d): %s\n", + pDev->DeviceNameLength, pDev->DeviceName)); +#endif + } + + // Clear irq status bits + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, 0xFFFF); + + /*--- mmoser 08.09.2005 ---*/ + pDev->initialized = SK_TRUE; + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_Init - Initialize the FPGA SDIO/CardBus interface + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +void +SDHost_Init(PCOMMON_DEVICE_DATA pDev) +{ + SK_U32 ulVal; + SK_U8 ucHostCtrl = 0; + SK_U16 usVal; + + ENTER(); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "SDHost_Init(pDev=0x%p, IOBase=0x%p)\n", pDev, + pDev->IOBase[0])); + + /*--- mmoser 4/4/2006 ---*/ + pDev->SurpriseRemoved = 0; + + // issue software reset + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_SW_RESET, STDHOST_SW_RESET_ALL); + + DBGPRINT(DBG_LOAD, (KERN_DEBUG "SDHost_Init() line=%d\n", __LINE__)); + + // Read the Host Controller Version + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_HOST_CONTROLLER_VERSION, &usVal); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG + "SD Host Spec Version 0x%2.02X - Vendor Version 0x%2.02x\n", + GET_SPEC_VERSION_NR(usVal), GET_VENDOR_VERSION_NR(usVal))); + + if (pDev->bus_type == SDIO_BUS_TYPE && pDev->bus_width == SDIO_4_BIT) { + ucHostCtrl |= STDHOST_4_BIT_ENA; + } + // Read capabilities + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_CAPABILITIES, &ulVal); + + if ((ulVal & STDHOST_CAP_VOLTAGE_1_8) == STDHOST_CAP_VOLTAGE_1_8) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "1.8V supported\n")); + pDev->maxSupplyVoltage = STDHOST_VOLTAGE_1_8_V; + } + if ((ulVal & STDHOST_CAP_VOLTAGE_3_0) == STDHOST_CAP_VOLTAGE_3_0) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "3.0V supported\n")); + pDev->maxSupplyVoltage = STDHOST_VOLTAGE_3_0_V; + } + if ((ulVal & STDHOST_CAP_VOLTAGE_3_3) == STDHOST_CAP_VOLTAGE_3_3) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "3.3V supported\n")); + pDev->maxSupplyVoltage = STDHOST_VOLTAGE_3_3_V; + } + if ((ulVal & STDHOST_CAP_SUSPENSE_RESUME) == STDHOST_CAP_SUSPENSE_RESUME) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Suspense/resume supported\n")); + } + if ((ulVal & STDHOST_CAP_DMA) == STDHOST_CAP_DMA) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "DMA supported\n")); + } + if ((ulVal & STDHOST_CAP_HIGH_SPEED) == STDHOST_CAP_HIGH_SPEED) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "High speed supported\n")); + ucHostCtrl |= STDHOST_HIGH_SPEED_ENA; + } + pDev->max_block_size = SD_BLOCK_SIZE; + if ((ulVal & STDHOST_CAP_MAX_BLOCK_512) == STDHOST_CAP_MAX_BLOCK_512) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Max Block Length : 512\n")); + pDev->max_block_size = 512; + } else if ((ulVal & STDHOST_CAP_MAX_BLOCK_1024) == + STDHOST_CAP_MAX_BLOCK_1024) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Max Block Length : 1024\n")); + pDev->max_block_size = 1024; + } else if ((ulVal & STDHOST_CAP_MAX_BLOCK_2048) == + STDHOST_CAP_MAX_BLOCK_2048) { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Max Block Length : 2048\n")); + pDev->max_block_size = 2048; + } + + pDev->baseClockFreq = GET_CAP_BASE_CLOCK_FREQ(ulVal); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "Base clock : %d MHz\n", pDev->baseClockFreq)); + + if ((ulVal & STDHOST_CAP_TIMEOUT_CLOCK_UNIT_MHZ) == + STDHOST_CAP_TIMEOUT_CLOCK_UNIT_MHZ) { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "Timeout clock : %d MHz\n", + (ulVal & STDHOST_CAP_TIMEOUT_CLOCK_FREQ))); + } else { + DBGPRINT(DBG_LOAD, (KERN_DEBUG "Timeout clock : %d kHz\n", + (ulVal & STDHOST_CAP_TIMEOUT_CLOCK_FREQ))); + } + + // Read the max current capabilities + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_MAX_CURRENT_CAP, &ulVal); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "Max. current @1.8V=%dmA @3.0V=%dmA @3.3V=%dmA\n", + CALC_MAX_CURRENT_IN_MA(GET_MAX_CURRENT_CAP_1_8_V(ulVal)), + CALC_MAX_CURRENT_IN_MA(GET_MAX_CURRENT_CAP_3_0_V(ulVal)), + CALC_MAX_CURRENT_IN_MA(GET_MAX_CURRENT_CAP_3_3_V(ulVal)))); + + // Setup host control register + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_HOST_CTRL, ucHostCtrl); + + /*--- mmoser 14.09.2005 ---*/ + // Reset all pending irq bits + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, 0xFFFF); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, 0xFFFF); + + // Enable error irq status + //usVal = 0xFFFF; + usVal = STDHOST_ERROR_IRQ_VENDOR_SIG_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS_ENABLE, usVal); + + /*--- mmoser 1/2/2007 ---*/ + // Enable GPI interrupts + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + STDHOST_ERROR_IRQ_VENDOR_SIG_ENA); + + // Enable card detect + usVal = 0xFFFF; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + usVal); + usVal = STDHOST_NORMAL_IRQ_CARD_ALL_ENA; + pDev->lastIRQSignalMask = usVal; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + usVal); + + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, &ulVal); + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "SDHost_Init() : present state=0x%8.08X\n", ulVal)); + + /*--- mmoser 12.09.2005 ---*/ + pDev->initialized = SK_TRUE; + + LEAVE(); + +} + +/****************************************************************************** + * + * SDHost_isCardPresent - checks whether a SDIO card is in the SDIO socket + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE card is in socket + * SK_FALSE no card in socket + * + */ +SK_BOOL +SDHost_isCardPresent(PCOMMON_DEVICE_DATA pDev) +{ + SK_U32 ulVal; + SK_U16 usVal; + PFDO_DEVICE_DATA fdodata; + +#ifdef WINNT + if (pDev->IsFDO) { + fdodata = (PFDO_DEVICE_DATA) pDev; + } else { + fdodata = FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev); + } +#else + fdodata = (PFDO_DEVICE_DATA) pDev; +#endif + +// mmoser 2005-11-21 + /*--- mmoser 13.09.2005 ---*/ + if (pDev->SurpriseRemoved) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_isCardPresent: Surprise Removal of Card!\n")); + return SK_FALSE; + } + + if (fdodata->common.initialized == SK_FALSE) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_isCardPresent(): SD Host Adapter is NOT initialized. (%d)\n", + fdodata->common.initialized)); + return SK_FALSE; + } + // Read the Host Controller Version to check if SD Host adapter is available + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_HOST_CONTROLLER_VERSION, &usVal); + if (usVal == 0xFFFF) { + // There is probably no SD Host Adapter available + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_isCardPresent(): SD Host Adapter is NOT present. (%4.04X)\n", + usVal)); + return SK_FALSE; + } + // Read present state register to check whether a SD card is present + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, &ulVal); + if ((ulVal & STDHOST_STATE_CARD_INSERTED) == 0) { + // There is probably no card in the socket + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_isCardPresent(): Card is NOT present. (%8.08X)\n", + ulVal)); + return SK_FALSE; + } + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_SendCmd - Send a SDIO command to the card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + */ +SK_BOOL +SDHost_SendCmd(PCOMMON_DEVICE_DATA pDev, SK_U8 cmd, SK_U32 arg, + SK_U16 transferMode, SK_U32 * pulResp) +{ + SK_U32 retry, max_retry; + SK_U32 ulVal; + SK_U16 usCmd; + SK_U32 ulIrq; + + clear_bit(0, &pDev->cmd_complete_evt.event); + + // max_retry depends on actual bus clock speed + max_retry = + MAX_WAIT_COMMAND_INHIBIT * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + // Read present state register to check whether Command Inhibit (CMD) = 0 + for (retry = 0; retry < max_retry; retry++) { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, &ulVal); + if (cmd == 53) { + if ((ulVal & STDHOST_STATE_CMD_INHIB_DAT) == 0) { + break; + } + } else { + if ((ulVal & STDHOST_STATE_CMD_INHIB_CMD) == 0) { + break; + } + } + /*--- mmoser 3/7/2006 ---*/ + if (retry & 0xFFFFFFFE) + UDELAY(1); + } + if (retry >= max_retry) { + if (cmd == 53) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_SendCmd() : Command Inhibit DAT remains busy! (max_retry=%d)\n", + max_retry)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + UDELAY(10); // wait until reset is complete + + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_SW_RESET, 0); + } else { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_SendCmd() : Command Inhibit CMD remains busy! (max_retry=%d)\n", + max_retry)); + // reset the cmd line + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_CMD_LINE); + UDELAY(10); // wait until reset is complete + + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_SW_RESET, 0); + } + return SK_FALSE; + } + // clear irq bit + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, 0xFFFF0000 | // ERROR_IRQ_STATUS + STDHOST_NORMAL_IRQ_ERROR | + STDHOST_NORMAL_IRQ_TRANS_COMPLETE | + STDHOST_NORMAL_IRQ_CMD_COMPLETE); + + usCmd = MK_CMD(cmd) | MK_CMD_TYPE(STDHOST_CMD_TYPE_NORMAL); + + switch (cmd) { + case 0: + { + usCmd |= STDHOST_RESP_TYPE_NONE; + break; + } + case 3: + { + usCmd |= STDHOST_CMD_INDEX_CHK_ENA | + STDHOST_CMD_CRC_CHK_ENA | STDHOST_RESP_TYPE_R6; + break; + } + case 5: + { + usCmd |= STDHOST_RESP_TYPE_R4; + break; + } + case 7: + { + usCmd |= STDHOST_CMD_INDEX_CHK_ENA | + STDHOST_CMD_CRC_CHK_ENA | STDHOST_RESP_TYPE_R1b; + break; + } + case 52: + case 53: + { + usCmd |= STDHOST_CMD_INDEX_CHK_ENA | + STDHOST_CMD_CRC_CHK_ENA | STDHOST_RESP_TYPE_R5; + break; + } + case 59: + { + usCmd |= STDHOST_RESP_TYPE_NONE; + break; + } + default: + { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_SendCmd() : Command 0x%2.02X not supported!\n", + cmd)); + return SK_FALSE; + } + } + + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, &ulVal); + + pDev->errorOccured = 0; + + // initiate the cmd + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_CMD_ARGUMENT, arg); + ulVal = (usCmd << 16) | transferMode; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_TRANSFER_MODE, ulVal); + +#ifdef DBG + if ((pDev->debug_flags & DEBUG_SHOW_REG_10_14) == DEBUG_SHOW_REG_10_14) { + if (cmd == 53) { + for (retry = 0; retry < 10; retry++) { + SK_U32 ulR1, ulR2; + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_RESP_BITS_31_0, + &ulR1); + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_RESP_BITS_63_32, + &ulR2); + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "retry=%d 63-32 : 0x%8.08X 31-0 : 0x%8.08X\n", + retry, ulR2, ulR1)); + } + } + } +#endif + + /**/ if (pDev->lastIRQSignalMask & STDHOST_NORMAL_IRQ_CMD_COMPLETE) { +//printk("%s @ %d: Wait CMD complete\n",__FUNCTION__,__LINE__); + if (SDHost_wait_event(pDev, &pDev->cmd_complete_evt, 100)) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "%s @ %d: Wait CMD complete ---> FAILED !\n", + __FUNCTION__, __LINE__)); + return SK_FALSE; + } + clear_bit(0, &pDev->cmd_complete_evt.event); + } else + /**/ { + max_retry = + MAX_WAIT_COMMAND_COMPLETE * 10 * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + // Wait for end of command + for (retry = 0; retry < max_retry; retry++) { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + &ulIrq); + if ((ulIrq & STDHOST_NORMAL_IRQ_CMD_COMPLETE) == + STDHOST_NORMAL_IRQ_CMD_COMPLETE) { + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_CMD_COMPLETE); + break; + } + /*--- mmoser 3/7/2006 ---*/ + if (retry & 0xFFFFFFFE) + UDELAY(1); + } + + if (retry >= max_retry) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_SendCmd() : Command not completed! (max_retry=%d)\n", + max_retry)); + return SK_FALSE; + } + + } + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_RESP_BITS_31_0, pulResp); + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_SendAbort - Aborts an SDIO CMD53 block transfer + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + */ +SK_BOOL +SDHost_SendAbort(PCOMMON_DEVICE_DATA pDev) +{ + +// return SDHost_CMD52_Write(pDev, IO_ABORT_REG, 0, 0x03); + +//#ifdef __XXX__ + SK_U32 retry, max_retry; + SK_U32 ulVal; + SK_U32 ulArg; + SK_U16 usCmd; +// SK_U32 ulIrq; + + ulArg = MAKE_SDIO_OFFSET(IO_ABORT_REG) | MAKE_SDIO_FUNCTION(0x00) | 0x03; + + // max_retry depends on actual bus clock speed + max_retry = + MAX_WAIT_COMMAND_INHIBIT * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + // clear irq bit + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_TRANS_COMPLETE | + STDHOST_NORMAL_IRQ_CMD_COMPLETE); + + /*--- mmoser 3/7/2006 ---*/ + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, &ulVal); + + usCmd = MK_CMD(52) | + MK_CMD_TYPE(STDHOST_CMD_TYPE_ABORT) | + STDHOST_CMD_INDEX_CHK_ENA | + STDHOST_CMD_CRC_CHK_ENA | STDHOST_RESP_TYPE_R5; + + // initiate the cmd + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_CMD_ARGUMENT, ulArg); + + ulVal = (usCmd << 16) | STDHOST_READ_DIR_SELECT; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_TRANSFER_MODE, ulVal); + + // Read present state register to check whether Command Inhibit (CMD) = 0 + for (retry = 0; retry < max_retry; retry++) { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, &ulVal); + if (((ulVal & STDHOST_STATE_CMD_INHIB_DAT) == 0) && + ((ulVal & STDHOST_STATE_CMD_INHIB_CMD) == 0)) { + break; + } + UDELAY(1); + } + if (retry >= max_retry) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_SendAbort() : Command Inhibit (CMD/DAT) remains busy! (max_retry=%d)\n", + max_retry)); + return SK_FALSE; + } + + return SK_TRUE; +//#endif +} + +/****************************************************************************** + * + * SDHost_CMD52_Read - Read one byte from the SDIO card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD52_Read(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 * pReturnData) +{ + SK_U8 Resp; + SK_U32 ulResponse; + SK_U8 D8, D16; + SK_U32 retry, Arg; + + /*--- mmoser 3/31/2006 ---*/ + if (pDev->SurpriseRemoved == SK_TRUE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD52 READ FAILED : Surprise Removed !!! fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } +#ifdef FIFO_CMD52_DEBUG + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x0204, &ulResponse); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "(3)RD Fifo Stat : 0x%x \n", ulResponse)); + + if (ulResponse != 0x40010000) { + SK_U32 tmp; + SK_U16 i; + printk("(3)RD Fifo Stat : 0x%x \n", ulResponse); + for (i = 0; i < (ulResponse & 0x3ff); i++) + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x20, &tmp); + } + + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x0208, &ulResponse); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "(3)WR Fifo Stat : 0x%x \n", ulResponse)); + if (ulResponse != 0x40000000) + printk("(3)WR Fifo Stat : 0x%x \n", ulResponse); +#endif + + Arg = MAKE_SDIO_OFFSET(Offset) | MAKE_SDIO_FUNCTION(function_number); + + retry = 0; + while (1) { + if (SDHost_SendCmd + (pDev, 52, Arg, STDHOST_READ_DIR_SELECT, &ulResponse)) { + break; + } + if (retry++ > 5) { + if (++pDev->bus_errors > MAX_BUS_ERRORS) { + SDHost_SetCardOutEvent(pDev); + } + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD52 READ FAILED : fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } +// mmoser 2006-02-22 + if (retry > 1) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD52 READ FAILED : fn=%2.02X reg=%8.08X (bus_errors=%d) retry=%d\n", + function_number, Offset, pDev->bus_errors, retry)); + } + + UDELAY(200); + } + + D16 = GET_BITS_23_16(ulResponse); + + Resp = D16; + + if (pDev->bus_type == SDIO_BUS_TYPE) { + // SDIO bus + + // mask 11001011 + if (Resp & 0xCB) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG + "CMD52 READ fn=%2.02X reg=%8.08X RESP Error:0x%2.02X (0x%8.08X)\n", + function_number, Offset, Resp, ulResponse)); + UDELAY(100); + return SK_FALSE; + } else if ((Resp & 0x30) == 0) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG + "CMD52 READ fn=%2.02X reg=%8.08X RESP Error,card not selected!:0x%2.02X (0x%8.08X)\n", + function_number, Offset, Resp, ulResponse)); + UDELAY(100); + return SK_FALSE; + } + } else { + // SPI bus + + if (Resp & 0x5C) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD52 READ RESP Error:0x%.2X\n", Resp)); + return SK_FALSE; + } + } + + D8 = GET_BITS_15_08(ulResponse); + *pReturnData = D8; + + if (pDev->bus_errors > 0) { + pDev->bus_errors--; + } + DBGPRINT(DBG_W528D_CMD52, + (KERN_DEBUG + "CMD52 READ : fn=%2.02X reg=%8.08X data=%2.02X (%2.02X %2.02X/%8.08X)\n", + function_number, Offset, *pReturnData, D16, D8, ulResponse)); + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_CMD52_Write - Write one byte from the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD52_Write(PCOMMON_DEVICE_DATA pDev, SK_U32 Offset, + SK_U8 function_number, SK_U8 Data) +{ + SK_U8 Resp; + SK_U32 ulResponse; + SK_U32 Arg, retry; + + /*--- mmoser 3/31/2006 ---*/ + if (pDev->SurpriseRemoved == SK_TRUE) { + DBGPRINT(DBG_W528D_CMD52, + (KERN_DEBUG + "CMD52 WRITE : Surprise Removed !!!! fn=%2.02X reg=%8.08X data=%2.02X (bus_errors=%d)\n", + function_number, Offset, Data, pDev->bus_errors)); + return SK_FALSE; + } + + DBGPRINT(DBG_W528D_CMD52, + (KERN_DEBUG + "CMD52 WRITE : fn=%2.02X reg=%8.08X data=%2.02X (bus_errors=%d)\n", + function_number, Offset, Data, pDev->bus_errors)); + +#ifdef FIFO_CMD52_DEBUG + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x0204, &ulResponse); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "(4)RD Fifo Stat : 0x%x \n", ulResponse)); + + if (ulResponse != 0x40010000) { + SK_U32 tmp; + SK_U16 i; + printk("(4)RD Fifo Stat : 0x%x \n", ulResponse); + for (i = 0; i < (ulResponse & 0x3ff); i++) + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x20, &tmp); + } + + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x0208, &ulResponse); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "(4)WR Fifo Stat : 0x%x \n", ulResponse)); + + if (ulResponse != 0x40000000) + printk("(4)WR Fifo Stat : 0x%x \n", ulResponse); +#endif + + Arg = MAKE_SDIO_OFFSET(Offset) | + MAKE_SDIO_FUNCTION(function_number) | MAKE_SDIO_DIR(1) | (SK_U8) Data; + retry = 0; + while (1) { + if (SDHost_SendCmd + (pDev, 52, Arg, STDHOST_READ_DIR_SELECT, &ulResponse)) { + break; + } + if (retry++ > 5) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD52 WRITE FAILED : fn=%2.02X reg=%8.08X data=%2.02X\n", + function_number, Offset, Data)); + return SK_FALSE; + } + UDELAY(200); + } + + Resp = GET_BITS_23_16(ulResponse); + + if (pDev->bus_type == SDIO_BUS_TYPE) { + // SDIO bus + + // mask 11001011 + if (Resp & 0xCB) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG + "CMD52 READ fn=%2.02X reg=%8.08X RESP Error:0x%2.02X (0x%8.08X)\n", + function_number, Offset, Resp, ulResponse)); + return SK_FALSE; + } else if ((Resp & 0x30) == 0) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG + "CMD52 READ fn=%2.02X reg=%8.08X RESP Error,card not selected!:0x%2.02X (0x%8.08X)\n", + function_number, Offset, Resp, ulResponse)); + return SK_FALSE; + } + } else { + // SPI bus + + if (Resp & 0x5C) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD52 READ RESP Error:0x%.2X\n", Resp)); + return SK_FALSE; + } + } + + if (pDev->bus_errors > 0) { + pDev->bus_errors--; + } + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_ReadRCA - Read the RCA from SDIO card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_ReadRCA(PCOMMON_DEVICE_DATA pDev, SK_U8 * pRca) +{ + SK_U8 ucStatus1, ucStatus2; + SK_U32 ulResponse; + + // CMD3 to read card RCA. + if (!SDHost_SendCmd(pDev, 3, 0, 0, &ulResponse)) { + if (++pDev->bus_errors > MAX_BUS_ERRORS) { + SDHost_SetCardOutEvent(pDev); + } + return SK_FALSE; + } + + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_RESP_BITS_31_0, &ulResponse); + + pRca[0] = GET_BITS_39_32(ulResponse); + pRca[1] = GET_BITS_31_24(ulResponse); + + ucStatus1 = GET_BITS_23_16(ulResponse); + ucStatus2 = GET_BITS_15_08(ulResponse); + + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ReadRCA: %2.02X%2.02X - CardStatus=%2.02X%2.02X\n", + pRca[0], pRca[1], ucStatus1 &= 0xE0, ucStatus2)); + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_ReadCIS - Read element 'cistpl' from the card's CIS + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_ReadCIS(PCOMMON_DEVICE_DATA pDev, SK_U8 function_number, SK_U8 cistpl, + SK_U8 * pBuf, SK_U32 * length) +{ + SK_U8 R; + SK_U8 lastR; + SK_U32 _cis = 0; + + if (pBuf == NULL || length == NULL || *length == 0) { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG + "SDHost_ReadCIS : Illegal Parameters pBuf=%p length=%d\n", + pBuf, *length)); + return SK_FALSE; + } + + if (!SDHost_CMD52_Read + (pDev, FN_CIS_POINTER_0_REG(function_number), 0, &R)) { + return SK_FALSE; + } + _cis = R; + if (!SDHost_CMD52_Read + (pDev, FN_CIS_POINTER_1_REG(function_number), 0, &R)) { + return SK_FALSE; + } + _cis |= (R << 8); + if (!SDHost_CMD52_Read + (pDev, FN_CIS_POINTER_2_REG(function_number), 0, &R)) { + return SK_FALSE; + } + _cis |= (R << 16); + + // Search for CISTPL + if (_cis != 0) { + SK_U32 i = 0; + SK_U32 j = 0; + + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ReadCIS : CIS=%8.08X\n", _cis)); + + R = 0; + + while (R != 0xFF && j < *length) { + SDHost_CMD52_Read(pDev, _cis + j, 0, &R); + j++; + if (R == cistpl) { + j += 3; + R = 0xFF; + lastR = 0xFF; + while (i < *length - 1) { + SDHost_CMD52_Read(pDev, _cis + j, 0, &R); + j++; + pBuf[i++] = (R == 0 ? ' ' : R); + if (R == 0 && lastR == 0) { + break; + } + lastR = R; + } + i -= 2; + pBuf[i] = 0; + break; + } + } + *length = i; + } else { + *length = 0; + } + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ReadCIS : fn=%d cistpl=%2.02X |%s| len=%d\n", + function_number, cistpl, pBuf, *length)); + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_ReadOCR - Read the OCR (supported voltages) from the SDIO card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_ReadOCR(PCOMMON_DEVICE_DATA pDev, SK_U8 * pOcr) +{ + SK_U32 i, j; + SK_U32 ulResponse; + SK_U8 ucValue = 0; +// SK_U8 R1,R2,R3,R4,R5,R6; + SK_U8 R2, R3, R4, R5; + + R2 = R3 = R4 = R5 = 0; + j = 0; + while (j++ < 5) { + // Wait until power cycle is complete + for (i = 0; i < 100; i++) { + if (!SDHost_SendCmd(pDev, 5, 0, 0, &ulResponse)) { + if (++pDev->bus_errors > MAX_BUS_ERRORS) { + SDHost_SetCardOutEvent(pDev); + return SK_FALSE; + } + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ReadOCR() retry=%d\n", j)); + + continue; + } + + R2 = GET_BITS_15_08(ulResponse); + R3 = GET_BITS_23_16(ulResponse); + R4 = GET_BITS_31_24(ulResponse); + R5 = GET_BITS_39_32(ulResponse); + + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ReadOCR(31-0) retry=%d : 0x%2.02X %2.02X %2.02X %2.02X\n", + j, R5, R4, R3, R2)); + + ucValue = GET_BITS_39_32(ulResponse); + + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ReadOCR(%d) : 0x%2.02X\n", + pDev->bus_type, ucValue)); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ReadOCR() : 0x%8.08X\n", + ulResponse)); + + if (ucValue & 0x80) { + // power cycle is complete + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ReadOCR() : power cycle is complete\n")); + break; + } + } + if (i == 100) { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG + "SDHost_ReadOCR() FAILED : Power cycle not complete after %d retries (0x%2.02X)!\n", + i, ucValue)); + return SK_FALSE; + } + + pOcr[0] = R4; + pOcr[1] = R3; + pOcr[2] = R2; + + if (R4 != 0 || R3 != 0) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ReadOCR() : PwrCycle:%X,IO_n:%X,Mem_p:%X,OCR:[0x%2.02X%2.02X%2.02X]\n", + ucValue & 0x80, ucValue & 0x70, ucValue & 0x40, pOcr[0], + pOcr[1], pOcr[2])); + + return SK_TRUE; + } + } + + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "SDHost_ReadOCR() FAILED : Cannot read OCR!\n")); + return SK_FALSE; +} + +/****************************************************************************** + * + * SDHost_WriteOCR - Write the OCR (supported voltages) to the SDIO card + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_WriteOCR(PCOMMON_DEVICE_DATA pDev, SK_U8 * pOcr) +{ + SK_U32 ulArg; + SK_U32 ulResponse; + SK_U8 ucValue; + SK_U32 i; + + ulArg = pOcr[0] << 16 | pOcr[1] << 8 | pOcr[2]; + // Wait until power cycle is complete + for (i = 0; i < 100; i++) { + if (!SDHost_SendCmd(pDev, 5, ulArg, 0, &ulResponse)) { + if (++pDev->bus_errors > MAX_BUS_ERRORS) { + SDHost_SetCardOutEvent(pDev); + } + return SK_FALSE; + } + + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_RESP_BITS_31_0, &ulResponse); + + ucValue = GET_BITS_39_32(ulResponse); + + if (ucValue & 0x80) { + // power cycle is complete + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "I/O Power up status is ready and set new voltage ok!\n")); + break; + } + } + if (i == 100) { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG + "SDHost_WriteOCR() FAILED : Power cycle not complete after %d retries!\n", + i)); + return SK_FALSE; + } + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_WriteOCR() : PwrCycle:%X,IO_n:%X,Mem_p:%X\n", + ucValue & 0x80, ucValue & 0x70, ucValue & 0x40)); + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_CMD53_Read - Read a block of data from the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD53_Read(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, SK_U8 opcode, SK_U8 * pData, SK_U32 Count) +{ + SK_U16 uwTransferMode; + SK_U32 size; + SK_U32 i, blkCnt, Arg; + SK_U32 ulResponse, retry, max_retry; + SK_U32 *pSrc32; + SK_U32 *pDest32; + SK_U8 RESP; + + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "CMD53 READ fn=%2.02X reg=%8.08X data=0x%2.0X\n", + function_number, Offset, *(pData))); + /*--- mmoser 3/31/2006 ---*/ + if (pDev->SurpriseRemoved == SK_TRUE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 READ FAILED : Surprise Removed !!! fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } + + if (Count > 0x1FF) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 %s READ : fn=%2.02X reg=%8.08X len=%d > 512 ERROR!!!!!!\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, Count)); + return SK_FALSE; + } + DBGPRINT(DBG_W528D_CMD53, + (KERN_DEBUG "CMD53 %s READ : fn=%2.02X reg=%8.08X len=%d\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, Count)); + + if (mode && (pDev->blockSize != pDev->lastBlockSize)) // block mode + { + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_0_REG(function_number), 0, + (SK_U8) (pDev->blockSize & 0x00ff)); + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_1_REG(function_number), 0, + (SK_U8) (pDev->blockSize >> 8)); + pDev->lastBlockSize = pDev->blockSize; + } + + uwTransferMode = STDHOST_READ_DIR_SELECT; + + if (mode == BYTE_MODE) { + size = Count; + + blkCnt = 1 << 16 | Count; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blkCnt); + } else { + size = pDev->blockSize * Count; + +/* 20050630 mmoser HW-Workaround */ + if ((pDev->debug_flags & DEBUG_DISABLE_HW_WORKAROUND_RD) == + DEBUG_DISABLE_HW_WORKAROUND_RD) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } else { + if (Count > 1) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } + } + uwTransferMode |= STDHOST_BLOCK_COUNT_ENA; + + blkCnt = Count << 16 | pDev->blockSize; + + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blkCnt); + } + + Arg = MAKE_SDIO_OFFSET(Offset) | + MAKE_SDIO_OP_CODE(opcode) | + MAKE_SDIO_BLOCK_MODE(mode) | + MAKE_SDIO_FUNCTION(function_number) | (Count & 0x01FF); + +#ifdef WINNT +#if DBG == 1 + if ((pDev->debug_flags & DEBUG_BREAK_CMD53_RD) == DEBUG_BREAK_CMD53_RD) { + _asm int 3; + } +#endif +#endif // #ifdef WINNT + + retry = 0; + while (1) { + if (SDHost_SendCmd(pDev, 53, Arg, uwTransferMode, &ulResponse)) { + break; + } + if (retry++ > 5) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "CMD53 READ FAILED : fn=%2.02X reg=%8.08X\n", + function_number, Offset)); + return SK_FALSE; + } + UDELAY(5); + } + + RESP = GET_BITS_23_16(ulResponse); + if (pDev->bus_type == SDIO_BUS_TYPE) { + if (RESP & 0xCB) { + DBGPRINT(DBG_W528D_CMD53, + (KERN_DEBUG "CMD53 Read RESP Error:0x%.2X\n", RESP)); + return SK_FALSE; + } else if ((RESP & 0x30) == 0) { + DBGPRINT(DBG_W528D_CMD53 | DBG_ERROR, + (KERN_DEBUG + "CMD53 Read RESP Error,card not selected!:0x%.2X\n", + RESP)); + return SK_FALSE; + } + } else { + if (RESP & 0x5C) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD53 READ RESP Error:0x%.2X\n", RESP)); + return SK_FALSE; + } + } + + pSrc32 = + (SK_U32 *) (((SK_U32) (SK_BAR((pDev), (SK_SLOT_0)))) + + (STDHOST_DATA_PORT)); + pDest32 = (SK_U32 *) pData; + + retry = 0; + max_retry = + MAX_WAIT_COMMAND_COMPLETE * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + i = 0; + while (i < size) { + if (i % pDev->blockSize == 0) { + retry = 0; + + do { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulResponse); + if ((ulResponse & STDHOST_STATE_BUFFER_RD_ENABLE) == + STDHOST_STATE_BUFFER_RD_ENABLE) { + break; + } + + /*--- mmoser 3/13/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + /*--- mmoser 3/3/2006 ---*/ + if (retry >= max_retry) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 READ FAILED : STDHOST_STATE_BUFFER_RD_ENABLE remains 0\nfn=%2.02X reg=%8.08X\n", + function_number, Offset)); + if (mode) { + SDHost_SendAbort(pDev); + } + return SK_FALSE; + } + } + *pDest32 = *pSrc32; + pDest32++; + i += 4; + } + +/* + { + SK_U16 i; + + printk( KERN_DEBUG "\n%s\n", __FUNCTION__ ); + for( i=0; iSurpriseRemoved == SK_TRUE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 READ FAILED : Surprise Removed !!! fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } + + if (Count > 0x1FF) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 %s READ : fn=%2.02X reg=%8.08X len=%d > 512 ERROR!!!!!!\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, Count)); + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + /*--- mmoser 1/10/2007 ---*/ + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + &lastIRQMask); + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + &lastErrorIRQMask); + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + (lastIRQMask & (~STDHOST_NORMAL_IRQ_CARD))); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + (lastErrorIRQMask & (~STDHOST_ERROR_IRQ_VENDOR_ENA))); + + DBGPRINT(DBG_W528D_CMD53, + (KERN_DEBUG "CMD53 %s READ : fn=%2.02X reg=%8.08X len=%d\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, Count)); + + if (mode && (pDev->blockSize != pDev->lastBlockSize)) // block mode + { + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_0_REG(function_number), 0, + (SK_U8) (pDev->blockSize & 0x00ff)); + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_1_REG(function_number), 0, + (SK_U8) (pDev->blockSize >> 8)); + pDev->lastBlockSize = pDev->blockSize; + } + + uwTransferMode = STDHOST_READ_DIR_SELECT; + + if (mode == BYTE_MODE) { + size = Count; + blkCnt = 1 << 16 | Count; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blkCnt); + } else { + size = pDev->blockSize * Count; + + /* 20050630 mmoser HW-Workaround */ + if ((pDev->debug_flags & DEBUG_DISABLE_HW_WORKAROUND_RD) == + DEBUG_DISABLE_HW_WORKAROUND_RD) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } else { + if (Count > 1) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } + } + + uwTransferMode |= STDHOST_BLOCK_COUNT_ENA | STDHOST_DMA_ENA; + + blkCnt = Count << 16 | pDev->blockSize; + + DBGPRINT(DBG_ERROR, (KERN_DEBUG "blkCnt: 0x%x \n", blkCnt)); + + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blkCnt); + } + + Arg = MAKE_SDIO_OFFSET(Offset) | + MAKE_SDIO_OP_CODE(opcode) | + MAKE_SDIO_BLOCK_MODE(mode) | + MAKE_SDIO_FUNCTION(function_number) | (Count & 0x01FF); + +#ifdef WINNT +#if DBG == 1 + if ((pDev->debug_flags & DEBUG_BREAK_CMD53_RD) == DEBUG_BREAK_CMD53_RD) { + _asm int 3; + } +#endif +#endif // #ifdef WINNT + +#ifdef SYSKT_DMA_MALIGN_TEST + // set the DMA address + PhysAddr = (SK_U64) pci_map_page(pDev->dev, + virt_to_page(pDev->dma_rbuff), + ((unsigned long) (pDev-> + dma_rbuff) & + ~PAGE_MASK), 8192, PCI_DMA_FROMDEVICE); + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS, + (SK_U32) (PhysAddr + pDev->dma_start_malign + + pDev->dma_rx_malign)); +// MEM_READ_ULONG (pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS,&ulResp); +// printk("dma_abuf:0x%p phys:0x%x rx_malign:%d (read-back=0x%x)\n", pDev->dma_rbuff, (SK_U32)PhysAddr, pDev->dma_rx_malign, ulResp ); +#else // SYSKT_DMA_MALIGN_TEST + + // set the DMA address + PhysAddr = (SK_U64) pci_map_page(pDev->dev, virt_to_page(pData), + ((unsigned long) pData & ~PAGE_MASK), + size, PCI_DMA_FROMDEVICE); + + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS, + (SK_U32) PhysAddr); + // printk("\n\nCMD53 READ PhysAddr: 0x%x (virt:0x%x)\n",(SK_U32) PhysAddr, (SK_U32) pData ); +#endif // SYSKT_DMA_MALIGN_TEST + +/* + DBGPRINT(DBG_ERROR,( KERN_DEBUG "\n\nCMD53 READ PhysAddr: 0x%x (virt:0x%x)\n",(SK_U32) PhysAddr, (SK_U32) pData ) ); + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x0204, &ulResp); + DBGPRINT(DBG_ERROR, (KERN_DEBUG "(1)RD Fifo Stat : 0x%x \n", ulResp )); + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x0208, &ulResp); + DBGPRINT(DBG_ERROR, (KERN_DEBUG "(1)WR Fifo Stat : 0x%x \n", ulResp )); +*/ + pDev->CmdInProgress = 1; + clear_bit(0, &pDev->trans_complete_evt.event); + + retry = 0; + while (1) { + if (SDHost_SendCmd(pDev, 53, Arg, uwTransferMode, &ulResponse)) { + break; + } + if (retry++ > 5) { + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "CMD53 READ FAILED : fn=%2.02X reg=%8.08X\n", + function_number, Offset)); +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + UDELAY(5); + } + + RESP = GET_BITS_23_16(ulResponse); + if (pDev->bus_type == SDIO_BUS_TYPE) { + if (RESP & 0xCB) { + DBGPRINT(DBG_W528D_CMD53, + (KERN_DEBUG "CMD53 Read RESP Error:0x%.2X\n", RESP)); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } else if ((RESP & 0x30) == 0) { + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; + + DBGPRINT(DBG_W528D_CMD53 | DBG_ERROR, + (KERN_DEBUG + "CMD53 Read RESP Error,card not selected!:0x%.2X\n", + RESP)); +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + } else { + if (RESP & 0x5C) { + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD53 READ RESP Error:0x%.2X\n", RESP)); +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + } + + retry = 0; + max_retry = + MAX_WAIT_COMMAND_COMPLETE * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + // wait for DMA to complete + if (pDev->lastIRQSignalMask & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + if (SDHost_wait_event(pDev, &pDev->trans_complete_evt, 1000)) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "%s -> SDHost_wait_event trans_complete failed\n", + __FUNCTION__)); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + } else { + retry = 0; + if (test_bit(0, &pDev->trans_complete_evt.event) == 0) { + // if ( SDHost_wait_event(pDev, &pDev->trans_complete_evt, 1 ) ) { + do { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + &ulResp); + if ((ulResp & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) == + STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_TRANS_COMPLETE); + break; + } + /*--- mmoser 3/14/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + } else { + clear_bit(0, &pDev->trans_complete_evt.event); + } + if (retry >= max_retry) { + DBGPRINT(DBG_WARNING | DBG_ERROR, + (KERN_DEBUG + "CMD53 Read : STDHOST_NORMAL_IRQ_TRANS_COMPLETE not set!(count=%d max_retry=%d)\n", + Count, max_retry)); + // reset the data line and FIFO +#ifdef WINNT + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); +#endif + } + } + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_TRANSFER_MODE, 0); + +#ifdef SYSKT_DMA_MALIGN_TEST + { + memcpy(pData, + (void *) (pDev->dma_rbuff + pDev->dma_start_malign + + pDev->dma_rx_malign), size); + // pDev->dma_rx_malign++; + pDev->dma_rx_malign %= 64; + } + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, size, + PCI_DMA_FROMDEVICE); +#endif + +#ifdef WAR_SEND_ABORT +// Needed for FPGA workaround + if (mode) { + SDHost_SendAbort(pDev); + } +#endif // WAR_SEND_ABORT + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_CMD53_Write - Write a block of data to the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD53_Write(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, SK_U8 opcode, SK_U8 * pData, SK_U32 Count) +{ + SK_U16 uwTransferMode; + SK_U32 Arg; + SK_U32 ulResponse; + SK_U32 blk_cnt, cnt; + SK_U32 *pSrc32, *pEnd32; + SK_U32 *pDest32; + SK_U8 RESP; + SK_U32 retry, max_retry; + SK_U32 i; + + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "CMD53 WRITE fn=%2.02X reg=%8.08X data=0x%2.0X\n", + function_number, Offset, *(pData))); + + /*--- mmoser 3/31/2006 ---*/ + if (pDev->SurpriseRemoved == SK_TRUE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : Surprise Removed !!! fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + + if (Count >= 512) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE : fn=%2.02X reg=%8.08X len=%d > 512 ERROR!!!!!!\n", + function_number, Offset, Count)); + return SK_FALSE; + } + + DBGPRINT(DBG_W528D_CMD53, + (KERN_DEBUG + "CMD53 WRITE %s MODE : fn=%2.02X reg=%8.08X %s=%d block_size=%d\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, + (mode ? "blocks" : "length"), Count, pDev->blockSize)); + + if ((*(pData + 4) == 0x03) && (Count == 2)) { + SK_U32 x; + DBGPRINT(DBG_ERROR, (KERN_DEBUG "\n**** TRIGGER *****\n")); + MEM_READ_ULONG(pDev, SK_SLOT_0, 0x200, &x); + x |= ((1 << 24) | (1 << 16)); + MEM_WRITE_ULONG(pDev, SK_SLOT_0, 0x200, x); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "**** pData 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n", + *(pData + 0), *(pData + 1), *(pData + 2), *(pData + 3), + *(pData + 4), *(pData + 5))); + } + + if (mode && (pDev->blockSize != pDev->lastBlockSize)) // block mode + { + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_0_REG(function_number), 0, + (SK_U8) (pDev->blockSize & 0x00ff)); + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_1_REG(function_number), 0, + (SK_U8) (pDev->blockSize >> 8)); + pDev->lastBlockSize = pDev->blockSize; + } + uwTransferMode = 0; + + if (mode == BYTE_MODE) { + cnt = Count; + + blk_cnt = 1 << 16 | Count; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blk_cnt); + } else { + cnt = Count * pDev->blockSize; + +/* 20050630 mmoser HW-Workaround */ + if ((pDev->debug_flags & DEBUG_DISABLE_HW_WORKAROUND_WR) == + DEBUG_DISABLE_HW_WORKAROUND_WR) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } else { + if (Count > 1) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } + } + + uwTransferMode |= STDHOST_BLOCK_COUNT_ENA; + + blk_cnt = Count << 16 | pDev->blockSize; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blk_cnt); + } + + pSrc32 = (SK_U32 *) pData; + pDest32 = + (SK_U32 *) (((SK_U32) (SK_BAR((pDev), (SK_SLOT_0)))) + + (STDHOST_DATA_PORT)); + + Arg = MAKE_SDIO_OFFSET(Offset) | + MAKE_SDIO_OP_CODE(opcode) | + MAKE_SDIO_BLOCK_MODE(mode) | + MAKE_SDIO_FUNCTION(function_number) | + MAKE_SDIO_DIR(1) | (Count & 0x01FF); + +#ifdef WINNT +#if DBG == 1 + if ((pDev->debug_flags & DEBUG_BREAK_CMD53_WR) == DEBUG_BREAK_CMD53_WR) { + _asm int 3; + } +#endif +#endif + + max_retry = + MAX_WAIT_COMMAND_COMPLETE * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + pEnd32 = (SK_U32 *) ((SK_U32) pSrc32 + cnt); + +// #define PREFILL_FIFO + +/*** mmoser 2006-03-03 **/ +#ifdef PREFILL_FIFO + // --> The whole message is always written to the FIFO! each FIFO has 2K + // Fill the FIFO before issuing the command + i = 0; + while (i < 2000 && pSrc32 < pEnd32) { + if (i % pDev->blockSize == 0) { + retry = 0; + + do { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulResponse); + if ((ulResponse & STDHOST_STATE_BUFFER_WR_ENABLE) == + STDHOST_STATE_BUFFER_WR_ENABLE) { + break; + } + + /*--- mmoser 3/13/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + + /*--- mmoser 3/3/2006 ---*/ + if (retry >= max_retry) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : STDHOST_STATE_BUFFER_WR_ENABLE remains 0\nfn=%2.02X reg=%8.08X\n", + function_number, Offset)); + return SK_FALSE; + } + } + + *pDest32 = *pSrc32; + pSrc32++; + i += 4; + } +#endif // PREFILL_FIFO + + /*--- mmoser 8/29/2006 ---*/ + clear_bit(0, &pDev->trans_complete_evt.event); + + retry = 0; + while (1) { + if (SDHost_SendCmd(pDev, 53, Arg, uwTransferMode, &ulResponse)) { + break; + } + if (retry++ > 5) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : fn=%2.02X reg=%8.08X\n", + function_number, Offset)); + return SK_FALSE; + } + UDELAY(5); + } + + RESP = GET_BITS_23_16(ulResponse); + + if (pDev->bus_type == SDIO_BUS_TYPE) { + if (RESP & 0xCB) { + DBGPRINT(DBG_W528D_CMD53 | DBG_ERROR, + (KERN_DEBUG "CMD53 WRITE RESP Error:0x%.2X\n", RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + return SK_FALSE; + } else if ((RESP & 0x30) == 0) { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE RESP Error,card not selected!:0x%.2X\n", + RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + return SK_FALSE; + } + + } else { + if (RESP & 0x5C) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD53 WRITE RESP Error:0x%.2X\n", RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + return SK_FALSE; + } + } + +#ifndef PREFILL_FIFO + i = 0; +#endif + + // Fill FIFO with remaining data, if any ... + while (pSrc32 < pEnd32) { + if (i % pDev->blockSize == 0) { + retry = 0; + + do { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, + &ulResponse); + if ((ulResponse & STDHOST_STATE_BUFFER_WR_ENABLE) == + STDHOST_STATE_BUFFER_WR_ENABLE) { + break; + } + + /*--- mmoser 3/13/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + /*--- mmoser 3/3/2006 ---*/ + if (retry >= max_retry) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : STDHOST_STATE_BUFFER_WR_ENABLE remains 0\nfn=%2.02X reg=%8.08X\n", + function_number, Offset)); + if (mode) { + SDHost_SendAbort(pDev); + } + return SK_FALSE; + } + } + + *pDest32 = *pSrc32; + pSrc32++; + i += 4; + } + + if (pDev->lastIRQSignalMask & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + if (SDHost_wait_event(pDev, &pDev->trans_complete_evt, 1000)) { + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + } else { + retry = 0; + do { + SK_U32 ulResp; + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + &ulResp); + if ((ulResp & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) == + STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_TRANS_COMPLETE); + break; + } + + /*--- mmoser 3/14/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + if (retry >= max_retry) { + DBGPRINT(DBG_WARNING, + (KERN_DEBUG + "CMD53 Write : STDHOST_NORMAL_IRQ_TRANS_COMPLETE not set!(count=%d max_retry=%d)\n", + Count, max_retry)); + // reset the data line and FIFO +#ifdef WINNT + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); +#endif + } + } + + if (mode) { + SDHost_SendAbort(pDev); + } + + /*--- mmoser 1/5/2007 ---*/ +// STDHOST_NORMAL_IRQ_ERROR is used for GPI interrupts !!!! +/* + MEM_READ_ULONG (pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, &ulVal); + if (ulVal&STDHOST_NORMAL_IRQ_ERROR) + { + SDHost_ErrorRecovery(pDev); + DBGPRINT(DBG_ERROR,( KERN_DEBUG "SDHost_CMD53_Write() : Command Error 0x%8.08X\n",ulVal)); + return SK_FALSE; + } +*/ + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_CMD53_Write_DMA - Write a block of data to the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD53_Write_DMA(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, SK_U8 opcode, SK_U8 * pData, SK_U32 Count) +{ + SK_U16 uwTransferMode; + SK_U32 Arg; + SK_U32 ulResponse; + SK_U32 blk_cnt, cnt; + SK_U32 *pSrc32; + SK_U32 *pDest32; + SK_U8 RESP; + SK_U32 retry, max_retry; + SK_U32 ulResp; + SK_U64 PhysAddr; + /*--- mmoser 1/10/2007 ---*/ + SK_U16 lastIRQMask; + SK_U16 lastErrorIRQMask; + + /*--- mmoser 3/31/2006 ---*/ + if (pDev->SurpriseRemoved == SK_TRUE) { + /*--- mmoser 1/10/2007 ---*/ + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : Surprise Removed !!! fn=%2.02X reg=%8.08X (bus_errors=%d)\n", + function_number, Offset, pDev->bus_errors)); + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + + if (Count >= 512) { + /*--- mmoser 1/10/2007 ---*/ + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE : fn=%2.02X reg=%8.08X len=%d > 512 ERROR!!!!!!\n", + function_number, Offset, Count)); + return SK_FALSE; + } + +/* + if(( *(pData) == 0x3C) && (Count == 2) ) { + SK_U32 x; + DBGPRINT(DBG_ERROR,( KERN_DEBUG "\n**** TRIGGER *****\n")); + MEM_READ_ULONG (pDev, SK_SLOT_0, 0x200, &x); + x |= ((1 << 24) | (1 << 16)); + MEM_WRITE_ULONG (pDev, SK_SLOT_0, 0x200, x); + DBGPRINT(DBG_ERROR,( KERN_DEBUG "**** pData 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n", + *(pData+0),*(pData+1),*(pData+2),*(pData+3), *(pData+4), *(pData+5))); + } +*/ + /*--- mmoser 1/10/2007 ---*/ + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + &lastIRQMask); + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + &lastErrorIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + (lastIRQMask & (~STDHOST_NORMAL_IRQ_CARD))); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + (lastErrorIRQMask & (~STDHOST_ERROR_IRQ_VENDOR_ENA))); + + DBGPRINT(DBG_W528D_CMD53 | DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE %s MODE : fn=%2.02X reg=%8.08X %s=%d block_size=%d\n", + (mode ? "BLOCK" : "BYTE"), function_number, Offset, + (mode ? "blocks" : "length"), Count, pDev->blockSize)); + + if (mode && (pDev->blockSize != pDev->lastBlockSize)) // block mode + { + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_0_REG(function_number), 0, + (SK_U8) (pDev->blockSize & 0x00ff)); + SDHost_CMD52_Write(pDev, FN_BLOCK_SIZE_1_REG(function_number), 0, + (SK_U8) (pDev->blockSize >> 8)); + pDev->lastBlockSize = pDev->blockSize; + } + uwTransferMode = 0; + + if (mode == BYTE_MODE) { + cnt = Count; + + blk_cnt = 1 << 16 | Count; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blk_cnt); + } else { + cnt = Count * pDev->blockSize; + +/* 20050630 mmoser HW-Workaround */ + if ((pDev->debug_flags & DEBUG_DISABLE_HW_WORKAROUND_WR) == + DEBUG_DISABLE_HW_WORKAROUND_WR) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } else { + if (Count > 1) { + uwTransferMode |= STDHOST_MULTI_BLOCK_SELECT; + } + } + + // enable DMA transfer + uwTransferMode |= (STDHOST_BLOCK_COUNT_ENA | STDHOST_DMA_ENA); + + blk_cnt = Count << 16 | pDev->blockSize; + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_BLOCK_SIZE, blk_cnt); + } + + pSrc32 = (SK_U32 *) pData; + pDest32 = + (SK_U32 *) (((SK_U32) (SK_BAR((pDev), (SK_SLOT_0)))) + + (STDHOST_DATA_PORT)); + + Arg = MAKE_SDIO_OFFSET(Offset) | + MAKE_SDIO_OP_CODE(opcode) | + MAKE_SDIO_BLOCK_MODE(mode) | + MAKE_SDIO_FUNCTION(function_number) | + MAKE_SDIO_DIR(1) | (Count & 0x01FF); + +#ifdef WINNT +#if DBG == 1 + if ((pDev->debug_flags & DEBUG_BREAK_CMD53_WR) == DEBUG_BREAK_CMD53_WR) { + _asm int 3; + } +#endif +#endif + max_retry = + MAX_WAIT_COMMAND_COMPLETE * (pDev->ClockSpeed == + 0 ? 1 : pDev->ClockSpeed); + + // max_retry = MAX_WAIT_COMMAND_COMPLETE * 100 * (pDev->ClockSpeed == 0 ? 1 : pDev->ClockSpeed); + /*--- mmoser 8/29/2006 ---*/ + +#ifdef SYSKT_DMA_MALIGN_TEST + // set the DMA address + PhysAddr = (SK_U64) pci_map_page(pDev->dev, + virt_to_page(pDev->dma_tbuff), + ((unsigned long) (pDev-> + dma_tbuff) & + ~PAGE_MASK), 8192, PCI_DMA_FROMDEVICE); + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS, + (SK_U32) (PhysAddr + pDev->dma_start_malign + + pDev->dma_tx_malign)); + +// MEM_READ_ULONG (pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS,&ulResp); +// printk("dma_abuf:0x%p phys:0x%x tx_malign:%d (read-back=0x%x)\n", pDev->dma_tbuff, (SK_U32)PhysAddr, pDev->dma_tx_malign, ulResp ); + memcpy((void *) (pDev->dma_tbuff + pDev->dma_start_malign + + pDev->dma_tx_malign), pData, cnt); +//printk("TX org: %2.02X %2.02X %2.02X %2.02X ...\n",pData[0],pData[1],pData[2],pData[3]); +//pTmp = (SK_U8 *)(pDev->dma_tbuff+pDev->dma_start_malign+pDev->dma_tx_malign); +//printk("TX cp : %2.02X %2.02X %2.02X %2.02X ...\n",pTmp[0],pTmp[1],pTmp[2],pTmp[3]); + pDev->dma_tx_malign++; + pDev->dma_tx_malign %= 64; + +#else // SYSKT_DMA_MALIGN_TEST + // set the DMA address + PhysAddr = (SK_U64) pci_map_page(pDev->dev, virt_to_page(pData), + ((unsigned long) pData & ~PAGE_MASK), + cnt, PCI_DMA_TODEVICE); + + MEM_WRITE_ULONG(pDev, SK_SLOT_0, STDHOST_SYSTEM_ADDRESS, + (SK_U32) PhysAddr); +#endif + + pDev->CmdInProgress = 1; + clear_bit(0, &pDev->trans_complete_evt.event); + + retry = 0; + while (1) { + if (SDHost_SendCmd(pDev, 53, Arg, uwTransferMode, &ulResponse)) { + break; + } + if (retry++ > 5) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE FAILED : fn=%2.02X reg=%8.08X\n", + function_number, Offset)); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + UDELAY(5); + } + RESP = GET_BITS_23_16(ulResponse); + + if (pDev->bus_type == SDIO_BUS_TYPE) { + if (RESP & 0xCB) { + DBGPRINT(DBG_W528D_CMD53 | DBG_ERROR, + (KERN_DEBUG "CMD53 WRITE RESP Error:0x%.2X\n", RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } else if ((RESP & 0x30) == 0) { + DBGPRINT(DBG_W528D | DBG_ERROR, + (KERN_DEBUG + "CMD53 WRITE RESP Error,card not selected!:0x%.2X\n", + RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + + } else { + if (RESP & 0x5C) { + DBGPRINT(DBG_W528D_CMD52 | DBG_ERROR, + (KERN_DEBUG "CMD53 WRITE RESP Error:0x%.2X\n", RESP)); + // reset the data line and FIFO + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + } + // wait for DMA to complete + if (pDev->lastIRQSignalMask & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + if (SDHost_wait_event(pDev, &pDev->trans_complete_evt, 1000)) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "%s -> SDHost_wait_event trans_complete failed\n", + __FUNCTION__)); + /*--- mmoser 1/10/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS_ENABLE, lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, + PCI_DMA_FROMDEVICE); +#endif + return SK_FALSE; + } + clear_bit(0, &pDev->trans_complete_evt.event); + } else { + retry = 0; + ulResp = 0; + if (test_bit(0, &pDev->trans_complete_evt.event) == 0) { + do { + + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + &ulResp); + if ((ulResp & STDHOST_NORMAL_IRQ_TRANS_COMPLETE) == + STDHOST_NORMAL_IRQ_TRANS_COMPLETE) { + MEM_WRITE_USHORT(pDev, SK_SLOT_0, + STDHOST_NORMAL_IRQ_STATUS, + STDHOST_NORMAL_IRQ_TRANS_COMPLETE); + break; + } + /*--- mmoser 3/14/2006 ---*/ + UDELAY(1); + } while (++retry < max_retry); + + } // check event + else { + clear_bit(0, &pDev->trans_complete_evt.event); + printk("%s xxx event instead of polling\n", __FUNCTION__); + } + if (retry >= max_retry) { + DBGPRINT(DBG_WARNING, + (KERN_DEBUG + "CMD53 Write : STDHOST_NORMAL_IRQ_TRANS_COMPLETE not set!(count=%d max_retry=%d)0x%x\n", + Count, max_retry, ulResp)); + // reset the data line and FIFO +#ifdef WINNT + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); +#endif + } + } + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_TRANSFER_MODE, 0); + +#ifdef SYSKT_DMA_MALIGN_TEST + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, 8192, + PCI_DMA_FROMDEVICE); +#else + pci_unmap_page(pDev->dev, (dma_addr_t) PhysAddr, cnt, PCI_DMA_FROMDEVICE); +#endif + +#ifdef WAR_SEND_ABORT +// Needed for FPGA workaround + if (mode) { + SDHost_SendAbort(pDev); + } +#endif // WAR_SEND_ABORT + + /*--- mmoser 1/5/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS_ENABLE, + lastIRQMask); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + lastErrorIRQMask); + pDev->CmdInProgress = 0; + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_CMD53_Read - Read a block of data from the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD53_ReadEx(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, + SK_U8 opcode, SK_U8 * pData, SK_U32 Count, SK_U32 blksz) +{ + SK_BOOL rc; + pDev->blockSize = blksz; + + if (pDev->dma_support & DMA_RD_SUPPORT) { + // printk("SDHost_CMD53_ReadEx (DMA): Count=%d blksz=%d\n",Count,blksz); + rc = SDHost_CMD53_Read_DMA(pDev, Offset, function_number, mode, + opcode, pData, Count); + } else { + // printk("SDHost_CMD53_ReadEx: Count=%d blksz=%d\n",Count,blksz); + rc = SDHost_CMD53_Read(pDev, Offset, function_number, mode, opcode, + pData, Count); + } + + return rc; +} + +/****************************************************************************** + * + * SDHost_CMD53_Write - Write a block of data to the SDIO card + * - + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * SK_TRUE on success + * + */ +SK_BOOL +SDHost_CMD53_WriteEx(PCOMMON_DEVICE_DATA pDev, + SK_U32 Offset, + SK_U8 function_number, + SK_U8 mode, + SK_U8 opcode, SK_U8 * pData, SK_U32 Count, SK_U32 blksz) +{ + pDev->blockSize = blksz; + + if (pDev->dma_support & DMA_WR_SUPPORT) { + //printk("SDHost_CMD53_WriteEx (DMA): Count=%d blksz=%d\n",Count,blksz); + return SDHost_CMD53_Write_DMA(pDev, Offset, function_number, mode, + opcode, pData, Count); + } else { + // printk("SDHost_CMD53_WriteEx: Count=%d blksz=%d\n",Count,blksz); + return SDHost_CMD53_Write(pDev, Offset, function_number, mode, opcode, + pData, Count); + } +} + +/****************************************************************************** + * + * SDHost_EnableInterrupt - Enable the interrupts on the FPGA + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_EnableInterrupt(PCOMMON_DEVICE_DATA pDev, SK_U16 mask) +{ + pDev->lastIRQSignalMask |= mask; + +#ifdef WINNT + /*--- mmoser 28.09.2005 ---*/ + if (!pDev->IsFDO) { + FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev)->common.lastIRQSignalMask = + pDev->lastIRQSignalMask; + } + DBGPRINT(DBG_IRQ, (KERN_DEBUG "Enable PCI Interrupt (%s:0x%4.04X)\n", + pDev->IsFDO ? "FDO" : "PDO", pDev->lastIRQSignalMask)); +#else + + DBGPRINT(DBG_IRQ, (KERN_DEBUG "Enable PCI Interrupt (0x%4.04X)\n", + pDev->lastIRQSignalMask)); +#endif + + /*--- mmoser 1/2/2007 ---*/ + if (pDev->CmdInProgress == 0) + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, + STDHOST_ERROR_IRQ_VENDOR_SIG_ENA); + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + pDev->lastIRQSignalMask); +} + +/****************************************************************************** + * + * SDHost_DisableInterrupt - Disable the interrupts on the FPGA + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_DisableInterrupt(PCOMMON_DEVICE_DATA pDev, SK_U16 mask) +{ + // save current irq mask + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + &pDev->lastIRQSignalMask); + + pDev->tmpIRQSignalMask = pDev->lastIRQSignalMask; + +#ifdef WINNT + /*--- mmoser 28.09.2005 ---*/ + if (!pDev->IsFDO) { + FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev)->common.lastIRQSignalMask = + pDev->lastIRQSignalMask & ~mask; + } + DBGPRINT(DBG_IRQ, (KERN_DEBUG "Disable PCI Interrupt (%s:0x%4.04X)\n", + pDev->IsFDO ? "FDO" : "PDO", + pDev->lastIRQSignalMask & ~mask)); +#else + + DBGPRINT(DBG_IRQ, (KERN_DEBUG "Disable PCI Interrupt (0x%4.04X)\n", + pDev->lastIRQSignalMask & ~mask)); +#endif + /*--- mmoser 1/2/2007 ---*/ + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_SIGNAL_ENABLE, 0); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + pDev->lastIRQSignalMask & ~mask); + pDev->lastIRQSignalMask &= ~mask; + +} + +/****************************************************************************** + * + * SDHost_if_EnableInterrupt - Exported interface function + * + * Description: + * Exported interface function : Enable only card related interrupts + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_if_EnableInterrupt(PCOMMON_DEVICE_DATA pDev) +{ + SDHost_EnableInterrupt(pDev, STDHOST_NORMAL_IRQ_CARD_ALL_ENA); +} + +/****************************************************************************** + * + * SDHost_if_DisableInterrupt - Exported interface function + * + * Description: + * Exported interface function : Disable only card related interrupts + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_if_DisableInterrupt(PCOMMON_DEVICE_DATA pDev) +{ + SDHost_DisableInterrupt(pDev, STDHOST_NORMAL_IRQ_CARD_ALL_ENA); +} + +/****************************************************************************** + * + * SDHost_SetCardOutEvent - Set the card out event + * + * Description: + * + * Notes: WINDOWS only + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetCardOutEvent(PCOMMON_DEVICE_DATA pDev) +{ + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_SetCardOutEvent() ---> CARD REMOVED\n")); +#ifdef WINNT + if (pDev->IsFDO) { + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_SetCardOutEvent() pDev is FDO !!!!!\n")); + ((PFDO_DEVICE_DATA) pDev)->CardIn = SK_FALSE; + pDev->CardOutEventPending = SK_TRUE; + KeSetEvent(&pDev->CardOutEvent, 0, FALSE); + } else { + FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev)->CardIn = SK_FALSE; + FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev)->common.CardOutEventPending = + SK_TRUE; + KeSetEvent(&FDO_FROM_PDO((PPDO_DEVICE_DATA) pDev)->common. + CardOutEvent, 0, FALSE); + } +#else + /*--- mmoser 3/31/2006 ---*/ + atomic_inc(&pDev->card_remove_event); + +#endif +} + +/****************************************************************************** + * + * SDHost_lockInterface - Lock the SDIO interface + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +SK_BOOL +SDHost_lockInterface(PCOMMON_DEVICE_DATA pDev) +{ +#ifdef SK_SDIO_LOCK_INTERFACE + if (INTERLOCKED_INC(&pDev->if_lock) > 1) { + INTERLOCKED_DEC(&pDev->if_lock); + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "SDHost_lockInterface() FAILED !!! if_lock=%d\n", + pDev->if_lock)); + return SK_FALSE; + } +#endif + + return SK_TRUE; +} + +/****************************************************************************** + * + * SDHost_unlockInterface - unlock the SDIO interface + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_unlockInterface(PCOMMON_DEVICE_DATA pDev) +{ +#ifdef SK_SDIO_LOCK_INTERFACE + if (INTERLOCKED_DEC(&pDev->if_lock) < 0) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_unlockInterface() was already zero !!!! --> ignore.\n", + pDev->if_lock)); + INTERLOCKED_INC(&pDev->if_lock); + } +#endif +} + +/****************************************************************************** + * + * SDHost_SetLed - Set the LED on the FPGA interface + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetLed(PCOMMON_DEVICE_DATA pDev, SK_U8 led, SK_U8 on) +{ + if (on) { + LED_ON(led); + } else { + LED_OFF(led); + } +} + +/****************************************************************************** + * + * SDHost_SetClockSpeed - Set the SDIO bus clock speed + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetClockSpeed(PCOMMON_DEVICE_DATA pDev, SK_U32 bus_freq) +{ + SK_U16 usVal; + SK_U32 freq = 0; + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: set clock to %d\n", __FUNCTION__, + bus_freq == 0 ? 25 : bus_freq)); + + if (bus_freq == 50) { + freq = 0; /* 50 MHz */ + } else if (bus_freq == 0 || bus_freq == 25) { + freq = 1; /* default: 25 MHz */ + } else if (bus_freq == 12) { + freq = 2; /* 12 MHz */ + } else if (bus_freq == 6) { + freq = 4; /* 6 MHz */ + } else if (bus_freq == 3) { + freq = 8; /* 3 MHz */ + } else if (bus_freq == 2) { + freq = 16; /* 1,5 MHz */ + } else if (bus_freq == 800) { + freq = 32; /* 800 kHz */ + } else if (bus_freq == 300) { + freq = 64; /* 300 kHz */ + } else if (bus_freq == 200) { + freq = 128; /* 200 kHz */ + } else { + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: illegal clock %d\n", __FUNCTION__, + bus_freq)); + return; + } + + // Turn Off Bus Clock + SDHost_SetClock(pDev, 0); + + pDev->ClockSpeed = freq; + + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, &usVal); + + usVal &= 0x00FF; + + usVal = MK_CLOCK((SK_U16) pDev->ClockSpeed); + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + + // Turn On Bus Clock + SDHost_SetClock(pDev, 1); +} + +/****************************************************************************** + * + * SDHost_SetClock - Set the SDIO bus clock on/off + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetClock(PCOMMON_DEVICE_DATA pDev, SK_U8 on) +{ + SK_U16 usVal; + int j; + + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, &usVal); + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: turn clock %s\n", __FUNCTION__, + (on == 1 ? "ON" : "OFF"))); + + if (on) { + if (usVal & STDHOST_INTERNAL_CLK_ENA) { + if (usVal & STDHOST_INTERNAL_CLK_STABLE) { + if (usVal & STDHOST_CLOCK_ENA) { + // clock is already stable and running + return; + } else { + // Enable clock to card + usVal |= STDHOST_CLOCK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, + usVal); + return; + } + } + // there is something fishy with the clock. + // -> disable internal clock first + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "%s: SD internal clock is unstable!\n", + __FUNCTION__)); + usVal &= ~STDHOST_INTERNAL_CLK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + } + + usVal |= STDHOST_INTERNAL_CLK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + for (j = 0; j < MAX_WAIT_CLOCK_STABLE; j++) { + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, &usVal); + if ((usVal & STDHOST_INTERNAL_CLK_STABLE) == + STDHOST_INTERNAL_CLK_STABLE) { + break; + } + } + if (j >= MAX_WAIT_CLOCK_STABLE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "%s: SD clock remains unstable!\n", + __FUNCTION__)); + return; + } + // Enable clock to card + usVal |= STDHOST_CLOCK_ENA; + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + } else { + // Disable clock to card + usVal &= ~(STDHOST_CLOCK_ENA | STDHOST_INTERNAL_CLK_ENA); + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_CLOCK_CTRL, usVal); + } +} + +/****************************************************************************** + * + * SDHost_SetBusWidth - Set the SDIO bus width + * + * Description: + * + * Notes: see Part_A2_Host_Controller.pdf p.61 + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetBusWidth(PCOMMON_DEVICE_DATA pDev, SK_U8 width) +{ + SK_U16 usValue, usOrgValue; + SK_U8 ucHostCtrl = 0; + + if (pDev->bus_type != SDIO_BUS_TYPE) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG "%s: not possible in current bus mode (%d)\n", + __FUNCTION__, pDev->bus_type)); + return; + } + + DBGPRINT(DBG_LOAD, + (KERN_DEBUG "%s: bus width = %d\n", __FUNCTION__, width)); + // save current irq mask + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + &usOrgValue); + + // disable card interrupt + usValue = usOrgValue; + usValue &= ~STDHOST_NORMAL_IRQ_CARD_SIG_ENA; + + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + usValue); + + // Disable Host Interrupt on card + SDHost_CMD52_Write(pDev, 0x04, 0, 0); + + // Read current host control register + MEM_READ_UCHAR(pDev, SK_SLOT_0, STDHOST_HOST_CTRL, &ucHostCtrl); + + if (width == SDIO_4_BIT) { + pDev->bus_width = SDIO_4_BIT; + SDHost_CMD52_Write(pDev, 0x07, 0, 0x82); //0x80:CD disable,1 bit;0x82:CD disable,4 bit + ucHostCtrl |= STDHOST_4_BIT_ENA; + } else { + pDev->bus_width = SDIO_1_BIT; + SDHost_CMD52_Write(pDev, 0x07, 0, 0x80); //0x80:CD disable,1 bit;0x80:CD disable,1 bit + ucHostCtrl &= ~STDHOST_4_BIT_ENA; + } + + // Setup host control register + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, STDHOST_HOST_CTRL, ucHostCtrl); + + // Re-enable Host Interrupt on card + SDHost_CMD52_Write(pDev, 0x04, 0, 0x03); + + // Re-enable card interrupt + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_SIGNAL_ENABLE, + usOrgValue); +} + +/****************************************************************************** + * + * SDHost_SetGPO - Set the GPO on/off + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_SetGPO(PCOMMON_DEVICE_DATA pDev, SK_U8 on) +{ + if (on) { + + GPO_ON(); + } else { + + GPO_OFF(); + } +} + +/****************************************************************************** + * + * SDHost_PsState - Set the power state of the upper layer driver + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_PsState(PCOMMON_DEVICE_DATA pDev, SK_U8 State) +{ + pDev->PsState = State; +} + +/****************************************************************************** + * + * SDHost_ErrorRecovery - SDIO Standard Host Spec conform error recovery + * + * Description: + * + * Notes: + * + * Context: + * + * Returns: + * + */ +VOID +SDHost_ErrorRecovery(PCOMMON_DEVICE_DATA pDev) +{ + SK_U8 ucValue; + SK_U16 usValue; + SK_U32 j, ulVal, ulDataLineMask; + + // We have to do spec conform error recovery + MEM_READ_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, &usValue); + DBGPRINT(DBG_ERROR, (KERN_DEBUG "~#~#~#~#\n")); + DBGPRINT(DBG_W528D, + (KERN_DEBUG "SDHost_ErrorRecovery : ERROR_IRQ_STATUS=0x%4.04X\n", + usValue)); + // 1.) check whether any of bits3-0 are set. + if (usValue & 0x000F) { + // reset the command line + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_CMD_LINE); + + // wait until CMD line reset is 0 + j = 0; + do { + MEM_READ_UCHAR(pDev, SK_SLOT_0, STDHOST_SW_RESET, &ucValue); + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ErrorRecovery : CMD-LINE SW_RESET=0x%2.02X\n", + ucValue)); + UDELAY(2); + } while ((ucValue & STDHOST_SW_RESET_CMD_LINE) && j++ < 10000); + } + // 2.) check whether any of bits6-4 are set. + if (usValue & 0x0070) { + + // reset the data line + MEM_WRITE_UCHAR(pDev, SK_SLOT_0, + STDHOST_SW_RESET, STDHOST_SW_RESET_DAT_LINE); + + // wait until data line reset is 0 + j = 0; + do { + + MEM_READ_UCHAR(pDev, SK_SLOT_0, STDHOST_SW_RESET, &ucValue); + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ErrorRecovery : DAT-LINE SW_RESET=0x%2.02X\n", + ucValue)); + UDELAY(2); + } while ((ucValue & STDHOST_SW_RESET_DAT_LINE) && j++ < 10000); + + } + // clear error irq bits + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, 0xFFFF); + + // wait for more than 40 us + UDELAY(100); + + if (pDev->bus_type == SDIO_SPI_TYPE) { + ulDataLineMask = STDHOST_STATE_DAT0_LINE_LVL; + } else { + if (pDev->bus_width == SDIO_1_BIT) { + ulDataLineMask = STDHOST_STATE_DAT0_LINE_LVL; + } else { + ulDataLineMask = + (STDHOST_STATE_DAT0_LINE_LVL | STDHOST_STATE_DAT1_LINE_LVL | + STDHOST_STATE_DAT2_LINE_LVL | STDHOST_STATE_DAT3_LINE_LVL); + } + } + for (j = 0; j < 50; j++) { + MEM_READ_ULONG(pDev, SK_SLOT_0, STDHOST_PRESENT_STATE, &ulVal); + UDELAY(5); + if ((ulVal & ulDataLineMask) == ulDataLineMask) { + break; + } + } + DBGPRINT(DBG_W528D, + (KERN_DEBUG + "SDHost_ErrorRecovery : DAT-LINE=%d %d %d %d CMD-Line=%d\n", + ulVal & STDHOST_STATE_DAT3_LINE_LVL ? 1 : 0, + ulVal & STDHOST_STATE_DAT2_LINE_LVL ? 1 : 0, + ulVal & STDHOST_STATE_DAT1_LINE_LVL ? 1 : 0, + ulVal & STDHOST_STATE_DAT0_LINE_LVL ? 1 : 0, + ulVal & STDHOST_STATE_CMD_LINE_LVL ? 1 : 0)); + if (j >= 50) { + DBGPRINT(DBG_ERROR, + (KERN_DEBUG + "SDHost_ErrorRecovery : Present state=8x%8.08X : Non-recoverable error (bad datalines 0x%8.08X)!!!!!!!!!!!!!!!!!!!!\n", + ulVal, ulVal & ulDataLineMask)); + } + // clear error irq bits + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_ERROR_IRQ_STATUS, 0xFFFF); + // clear normal irq bits + MEM_WRITE_USHORT(pDev, SK_SLOT_0, STDHOST_NORMAL_IRQ_STATUS, + ~(pDev->lastIRQSignalMask)); + + UDELAY(100); +} + +SK_U32 +SDHost_wait_event(PCOMMON_DEVICE_DATA pDev, SDHOST_EVENT * pEvt, SK_U32 to) +{ + SK_U32 timeOut = 0; + SK_U32 rc = 0; + + DECLARE_WAITQUEUE(sdwait, current); + + if (to == 0) { + timeOut = LONG_MAX; + } else { + timeOut = to; + } + +// DBGPRINT(DBG_ALL, (">>> %s: timeout=%d event=%ld\n",__FUNCTION__,timeOut,pEvt->event)); + + add_wait_queue(&pEvt->wq, &sdwait); + set_current_state(TASK_INTERRUPTIBLE); + + while ((test_bit(0, &pEvt->event) == 0) && timeOut) { + timeOut = schedule_timeout(timeOut); + if (signal_pending(current)) { + rc = 1; + DBGPRINT(DBG_ALL, ("%s: Signal pending!\n", __FUNCTION__)); + break; + } + } + + if (timeOut <= 0 || (test_bit(0, &pEvt->event) == 0)) { + rc = 2; + DBGPRINT(DBG_ALL, + ("%s: timeout=%d event=%ld\n", __FUNCTION__, timeOut, + pEvt->event)); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&pEvt->wq, &sdwait); + + // DBGPRINT(DBG_ALL, ("<<< %s: timeout=%d event=%ld\n",__FUNCTION__,timeOut,pEvt->event)); + + return (rc); +} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/license.txt 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/license.txt --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/license.txt 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/license.txt 1969-12-31 19:00:00.000000000 -0500 @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/Makefile 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/Makefile --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/Makefile 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/Makefile 2007-11-06 12:26:39.000000000 -0500 @@ -1,14 +1,12 @@ -# # File: Makefile # # (c) Copyright © 2003-2006, Marvell International Ltd. -# All Rights Reserved # # This software file (the "File") is distributed by Marvell International # Ltd. under the terms of the GNU General Public License Version 2, June 1991 # (the "License"). You may use, redistribute and/or modify this File in # accordance with the terms and conditions of the License, a copy of which -# is available along with the File in the license.txt file or by writing to +# is available along with the File in the gpl.txt file or by writing to # the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. # @@ -16,32 +14,21 @@ # IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE # ARE EXPRESSLY DISCLAIMED. The License provides additional details about # this warranty disclaimer. -# - -############################################################################# -# Directories -############################################################################# - -# Directory of kernel source -KERNELVER := $(shell uname -r) -KERNELDIR = /lib/modules/$(KERNELVER)/build - -# Directory of driver binary -BINDIR = ../bin_usb8388 -INSTALLDIR = /lib/modules/$(KERNELVER)/kernel/drivers/usb +CC= $(CROSS)gcc +LD= $(CROSS)ld +BACKUP= /root/backup +YMD= `date +%Y%m%d%H%M` ############################################################################# # Configuration Options ############################################################################# # Debug Option -# DEBUG LEVEL n/1/2/3/4: +# DEBUG LEVEL n/1/2: # n: NO DEBUG -# 1: Only PRINTM(MSG,...) -# 2: PRINTM(MSG,...) and PRINTM(FATAL,...) -# 3: PRINTM(MSG,...), PRINTM(FATAL,...) and PRINTM(WARN,...) -# 4: PRINTM(MSG,...), PRINTM(FATAL,...), PRINTM(WARN,...) and PRINTM(INFO,...) +# 1: Only PRINTM(MSG,...), PRINTM(FATAL,...), ... +# 2: All PRINTM() CONFIG_DEBUG=1 # Proc in /proc/net/wlan @@ -53,16 +40,37 @@ # Re-association in driver CONFIG_REASSOCIATION=y +# Manufacturing firmware support +CONFIG_MFG_CMD_SUPPORT=y ############################################################################# -# Compiler Flags +# Select Platform Tools ############################################################################# +MODEXT = ko CFLAGS += -I$(PWD)/os/linux CFLAGS += -I$(PWD)/wlan -CFLAGS += -I$(PWD)/if/if_usb + +LD += -S +KERNELVERSION_X86 := $(shell uname -r) + + KERNELDIR=/lib/modules/$(KERNELVERSION_X86)/build + PLATFORM=syskt + CFLAGS += -I$(PWD)/io/sdio/$(PLATFORM)/sdioapi -I$(PWD)/io/sdio/$(PLATFORM)/sdioapi/h + CFLAGS += -I$(PWD)/io/sdio/$(PLATFORM)/stdhost -I$(PWD)/io/sdio/$(PLATFORM)/stdhost/h + + CFLAGS += -I$(PWD)/if/if_sdio + CFLAGS += -I$(PWD)/io/sdio/$(PLATFORM) + BINDIR = ../bin_sd8686 + +############################################################################# +# Compiler Flags +############################################################################# + CFLAGS += -I$(KERNELDIR)/include + CFLAGS += -DFPNUM='"4"' + ifeq ($(CONFIG_DEBUG),1) CFLAGS += -DDEBUG_LEVEL1 endif @@ -73,23 +81,9 @@ DBG= -dbg endif -ifeq ($(CONFIG_DEBUG),3) - CFLAGS += -DDEBUG_LEVEL1 - CFLAGS += -DDEBUG_LEVEL2 - CFLAGS += -DDEBUG_LEVEL3 - DBG= -dbg -endif - -ifeq ($(CONFIG_DEBUG),4) - CFLAGS += -DDEBUG_LEVEL1 - CFLAGS += -DDEBUG_LEVEL2 - CFLAGS += -DDEBUG_LEVEL3 - CFLAGS += -DDEBUG_LEVEL4 - DBG= -dbg -endif - ifeq ($(CONFIG_PROC_DEBUG),y) CFLAGS += -DPROC_DEBUG + export CONFIG_PROC_DEBUG endif ifeq ($(CONFIG_ENABLE_PM),y) @@ -100,29 +94,42 @@ CFLAGS += -DREASSOCIATION endif +ifeq ($(CONFIG_MFG_CMD_SUPPORT),y) + CFLAGS += -DMFG_CMD_SUPPORT +endif ############################################################################# # Make Targets ############################################################################# -# If KERNELRELEASE is defined, we've been invoked from the kernel build -# system and can use it's language. - ifneq ($(KERNELRELEASE),) WLANOBJS = wlan/wlan_main.o wlan/wlan_fw.o wlan/wlan_wext.o \ wlan/wlan_rx.o wlan/wlan_tx.o \ wlan/wlan_cmd.o wlan/wlan_cmdresp.o \ - wlan/wlan_proc.o wlan/wlan_scan.o wlan/wlan_join.o \ - wlan/wlan_11d.o + wlan/wlan_scan.o wlan/wlan_join.o + +WLANOBJS += wlan/wlan_wmm.o +WLANOBJS += wlan/wlan_11d.o +ifdef CONFIG_PROC_FS +WLANOBJS += wlan/wlan_proc.o ifeq ($(CONFIG_PROC_DEBUG), y) WLANOBJS += wlan/wlan_debug.o endif +endif -IFOBJS := if/if_usb/if_usb.o -obj-m := usb8xxx.o -usb8xxx-objs := $(WLANOBJS) $(IFOBJS) +IFOBJS := if/if_sdio/if_sdio.o +obj-m := sd8xxx.o +sd8xxx-objs := $(WLANOBJS) $(IFOBJS) +SDIOAPI_OBJS := io/sdio/$(PLATFORM)/sdioapi/apimain.o +SDIOAPI_OBJS += io/sdio/$(PLATFORM)/sdioapi/sdio_if.o +STDHOST_OBJS := io/sdio/$(PLATFORM)/stdhost/stdhost.o +STDHOST_OBJS += io/sdio/$(PLATFORM)/stdhost/sdiobus.o +STDHOST_OBJS += io/sdio/$(PLATFORM)/stdhost/skisr.o +obj-m += sdioapi.o mrvlsdio.o +sdioapi-objs := $(SDIOAPI_OBJS) +mrvlsdio-objs := $(STDHOST_OBJS) # Otherwise we were called directly from the command line; invoke the kernel build system. else @@ -134,7 +141,7 @@ ############################################################### -export CFLAGS KERNELDIR +export CC LD CFLAGS KERNELDIR .PHONY: app/wlanconfig wlan clean distclean @@ -145,34 +151,43 @@ $(MAKE) -C $@ echo: - @echo "===> Driver will be put to ../bin_usb8388 directory..." + @echo "Please make sure the following are done before building:" + @echo " 1. Modify release_version.h to set correct version number" + @echo " 2. Updates the README files" build: echo default @if [ ! -d $(BINDIR) ]; then \ mkdir $(BINDIR); \ fi + cp -f sd8xxx.$(MODEXT) $(BINDIR)/sd8686$(DBG).$(MODEXT) + cp -f sdioapi.$(MODEXT) $(BINDIR)/ + cp -f mrvlsdio.$(MODEXT) $(BINDIR)/ + cp -f io/sdio/$(PLATFORM)/release2.6/* $(BINDIR)/ - mv usb8xxx.ko $(BINDIR)/usb8388$(DBG).ko cp -f README $(BINDIR) $(MAKE) -C app/wlanconfig $@ INSTALLDIR=$(BINDIR) cp -r config $(BINDIR) -install: default - cp -f usb8xxx.ko $(INSTALLDIR)/usb8388$(DBG).ko - @echo $(INSTALLDIR) - @echo "===> USB8388 driver installed" - clean: - rm -f *.ko .*.ko.cmd -find . -name "*.o" -exec rm {} \; - -find . -name ".*.o.cmd" -exec rm {} \; + -find . -name "*.ko" -exec rm {} \; + -find . -name ".*.cmd" -exec rm {} \; -find . -name "*.mod.c" -exec rm {} \; + -rm -rf .tmp_versions $(MAKE) -C app/wlanconfig $@ + $(MAKE) -C io/sdio/$(PLATFORM)/sdioapi $@ + $(MAKE) -C io/sdio/$(PLATFORM)/stdhost $@ + +install: default + + cp -f sdio.$(MODEXT) $(INSTALLDIR) + $(MAKE) -C app/wlanconfig $@ INSTALLDIR=$(INSTALLDIR) + cp -f sd8xxx.$(MODEXT) $(INSTALLDIR)/sd8686$(DBG).$(MODEXT) + echo "sd8686 Driver Installed" distclean: -find . -name "*.o" -exec rm {} \; - -find . -name ".*.o.cmd" -exec rm {} \; -find . -name "*.orig" -exec rm {} \; -find . -name "*.swp" -exec rm {} \; -find . -name "*.*~" -exec rm {} \; @@ -180,24 +195,11 @@ -find . -name "*.d" -exec rm {} \; -find . -name "*.a" -exec rm {} \; -find . -name "tags" -exec rm {} \; - -find . -name "*.mod.c" -exec rm {} \; - -find . -name "*.ko" -exec rm {} \; - -find . -name ".*.ko.cmd" -exec rm {} \; -find . -name ".*" -exec rm -rf 2> /dev/null \; - -rm -rf .tmp_versions/ + -find . -name "*.ko" -exec rm {} \; + -find . -name ".*.cmd" -exec rm {} \; + -find . -name "*.mod.c" -exec rm {} \; + -rm -rf .tmp_versions $(MAKE) -C app/wlanconfig $@ -newlogs: - rm -f /var/log/message* - sleep 1 - /etc/rc.d/init.d/syslog restart - -rmtags: - rm -f tags - -tags: rmtags - ctags -R *.[ch] wlan/*.[ch] if/if_usb/*.[ch] os/linux/*.[ch] \ - $(KERNELDIR)/include/linux \ - $(KERNELDIR)/include/net $(KERNELDIR)/include/asm - # End of file diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_defs.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_defs.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_defs.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_defs.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,12 @@ -/** +/* + * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -24,8 +24,7 @@ typedef char *PCHAR; typedef u8 *PUCHAR; typedef u16 *PUSHORT; -typedef long LONG; -typedef LONG *PLONG; +typedef long *PLONG; typedef PLONG LONG_PTR; typedef u32 *ULONG_PTR; typedef u32 *Pu32; @@ -36,13 +35,11 @@ typedef int WLAN_STATUS; typedef u8 BOOLEAN; typedef BOOLEAN *PBOOLEAN; -typedef u32 WLAN_OID; typedef PVOID PDRIVER_OBJECT; typedef PUCHAR PUNICODE_STRING; typedef long long LONGLONG; -typedef unsigned long long ULONGLONG; typedef LONGLONG *PLONGLONG; -typedef ULONGLONG *PULONGLONG; +typedef unsigned long long *PULONGLONG; typedef PUCHAR ANSI_STRING; typedef ANSI_STRING *PANSI_STRING; typedef unsigned short WCHAR; diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_headers.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_headers.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_headers.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_headers.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,12 @@ -/** +/* + * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -47,10 +47,12 @@ #include #include #include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include -#include +#endif -#include +#include /* New Code to synchronize between IEEE Power save and PM*/ #ifdef ENABLE_PM @@ -79,6 +81,4 @@ /* Wireless header */ #include -#include - #endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_macros.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_macros.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_macros.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_macros.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,12 @@ -/** +/* + * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -28,22 +27,13 @@ #define OS_INT_RESTORE spin_unlock_irqrestore(&driver_lock, driver_flags); \ driver_lock = SPIN_LOCK_UNLOCKED -#define TX_DISABLE /* require for threadx */ -#define TX_RESTORE /* require for threadx */ -#define ConfigureThreadPriority() /* required for threadx */ - -/* Define these to nothing, these are needed only for threadx */ -#define OS_INTERRUPT_SAVE_AREA -#define OS_FREE_LOCK(x) -#define TX_EVENT_FLAGS_SET(x, y, z) - #define UpdateTransStart(dev) { \ dev->trans_start = jiffies; \ } #define OS_SET_THREAD_STATE(x) set_current_state(x) -#define MODULE_GET try_module_get(THIS_MODULE) +#define MODULE_GET if(try_module_get(THIS_MODULE)==0) return WLAN_STATUS_FAILURE; #define MODULE_PUT module_put(THIS_MODULE) #define OS_INIT_SEMAPHORE(x) init_MUTEX(x) @@ -51,20 +41,33 @@ #define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x) #define OS_REL_SEMAPHORE(x) up(x) -static inline void os_sched_timeout(u32 millisec) +/* Definitions below are needed for other OS like threadx */ +#define TX_DISABLE +#define TX_RESTORE +#define ConfigureThreadPriority() +#define OS_INTERRUPT_SAVE_AREA +#define OS_FREE_LOCK(x) +#define TX_EVENT_FLAGS_SET(x, y, z) + +#define os_wait_interruptible_timeout(waitq, cond, timeout) \ + wait_event_interruptible_timeout(waitq, cond, timeout) + +static inline void +os_sched_timeout(u32 millisec) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((millisec * HZ) / 1000); } -static inline void os_schedule(u32 millisec) +static inline void +os_schedule(u32 millisec) { schedule_timeout((millisec * HZ) / 1000); } -static inline int CopyMulticastAddrs(wlan_adapter *Adapter, - struct net_device *dev) +static inline int +CopyMulticastAddrs(wlan_adapter * Adapter, struct net_device *dev) { int i = 0; struct dev_mc_list *mcptr = dev->mc_list; @@ -74,94 +77,104 @@ mcptr = mcptr->next; } - return i; +} +static inline u32 +get_utimeofday(void) +{ + struct timeval t; + u32 ut; + + do_gettimeofday(&t); + ut = (u32) t.tv_sec * 1000000 + ((u32) t.tv_usec); + return ut; } -static inline int os_upload_rx_packet(wlan_private *priv, - struct sk_buff *skb) +static inline int +os_upload_rx_packet(wlan_private * priv, struct sk_buff *skb) { #define IPFIELD_ALIGN_OFFSET 2 - PRINTM(INFO, "skb->data=%p\n", skb->data); skb->dev = priv->wlan_dev.netdev; skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev); skb->ip_summed = CHECKSUM_UNNECESSARY; - netif_rx(skb); return 0; } -static inline void os_free_tx_packet(wlan_private *priv) +static inline void +os_free_tx_packet(wlan_private * priv) { ulong flags; - spin_lock_irqsave(&priv->adapter->CurrentTxLock, flags); - if (priv->adapter->CurrentTxSkb) { kfree_skb(priv->adapter->CurrentTxSkb); - } - + spin_lock_irqsave(&priv->adapter->CurrentTxLock, flags); priv->adapter->CurrentTxSkb = NULL; - spin_unlock_irqrestore(&priv->adapter->CurrentTxLock, flags); } +} -/* netif carrier_on/off and start(wake)/stop_queue handling - carrier_on carrier_off start_queue stop_queue - open x(connect) x(disconnect) x - close x x - assoc x x - adhoc-start x x - adhoc-join x x - scan-begin x x - scan-end x x - deauth x x - ps-sleep x x - ps-awake x x - ds-enter x x - ds-exit x x - xmit x - xmit-done x - tx-timeout +/* + * netif carrier_on/off and start(wake)/stop_queue handling + * + * carrier_on carrier_off start_queue stop_queue + * open x(connect) x(disconnect) x + * close x x + * assoc x x + * deauth x x + * adhoc-start + * adhoc-join + * adhoc-link x x + * adhoc-bcnlost x x + * scan-begin x x + * scan-end x x + * ds-enter x x + * ds-exit x x + * xmit x + * xmit-done x + * tx-timeout */ - -static inline void os_carrier_on(wlan_private *priv) +static inline void +os_carrier_on(wlan_private * priv) { if (!netif_carrier_ok(priv->wlan_dev.netdev) && - (priv->adapter->MediaConnectStatus == WlanMediaStateConnected)) + (priv->adapter->MediaConnectStatus == WlanMediaStateConnected) && + ((priv->adapter->InfrastructureMode != Wlan802_11IBSS) || + (priv->adapter->AdhocLinkSensed))) { netif_carrier_on(priv->wlan_dev.netdev); } +} -static inline void os_carrier_off(wlan_private *priv) +static inline void +os_carrier_off(wlan_private * priv) { - if (netif_carrier_ok(priv->wlan_dev.netdev)) + if (netif_carrier_ok(priv->wlan_dev.netdev)) { netif_carrier_off(priv->wlan_dev.netdev); } +} -static inline void os_start_queue(wlan_private *priv) +static inline void +os_start_queue(wlan_private * priv) { if (netif_queue_stopped(priv->wlan_dev.netdev) && - (priv->adapter->MediaConnectStatus == WlanMediaStateConnected)) { + (priv->adapter->MediaConnectStatus == WlanMediaStateConnected) && + ((priv->adapter->InfrastructureMode != Wlan802_11IBSS) || + (priv->adapter->AdhocLinkSensed))) { netif_wake_queue(priv->wlan_dev.netdev); } } -static inline void os_stop_queue(wlan_private *priv) +static inline void +os_stop_queue(wlan_private * priv) { if (!netif_queue_stopped(priv->wlan_dev.netdev)) { netif_stop_queue(priv->wlan_dev.netdev); } } -static inline int os_queue_is_active(wlan_private *priv) -{ - return (netif_carrier_ok(priv->wlan_dev.netdev) - && !netif_queue_stopped(priv->wlan_dev.netdev)); -} - #endif /* _OS_MACROS_H */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_timers.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_timers.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/os_timers.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/os_timers.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,12 @@ -/** +/* + * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -30,21 +30,21 @@ BOOLEAN timer_is_canceled; } __ATTRIB_PACK__ WLAN_DRV_TIMER, *PWLAN_DRV_TIMER; -static inline void TimerHandler(unsigned long fcontext) +static inline void +TimerHandler(unsigned long fcontext) { PWLAN_DRV_TIMER timer = (PWLAN_DRV_TIMER) fcontext; timer->timer_function(timer->function_context); if (timer->timer_is_periodic == TRUE) { - mod_timer(&timer->tl, - jiffies + ((timer->time_period * HZ) / 1000)); + mod_timer(&timer->tl, jiffies + ((timer->time_period * HZ) / 1000)); } } -static inline void InitializeTimer(PWLAN_DRV_TIMER timer, - void (*TimerFunction)(void *context), - void *FunctionContext) +static inline void +InitializeTimer(PWLAN_DRV_TIMER timer, + void (*TimerFunction) (void *context), void *FunctionContext) { // first, setup the timer to trigger the WlanTimerHandler proxy init_timer(&timer->tl); @@ -57,7 +57,8 @@ timer->timer_is_canceled = FALSE; } -static inline void SetTimer(PWLAN_DRV_TIMER timer, UINT MillisecondPeriod) +static inline void +SetTimer(PWLAN_DRV_TIMER timer, UINT MillisecondPeriod) { timer->time_period = MillisecondPeriod; timer->timer_is_periodic = FALSE; @@ -66,7 +67,8 @@ timer->timer_is_canceled = FALSE; } -static inline void ModTimer(PWLAN_DRV_TIMER timer, UINT MillisecondPeriod) +static inline void +ModTimer(PWLAN_DRV_TIMER timer, UINT MillisecondPeriod) { timer->time_period = MillisecondPeriod; timer->timer_is_periodic = FALSE; @@ -74,8 +76,8 @@ timer->timer_is_canceled = FALSE; } -static inline void SetPeriodicTimer(PWLAN_DRV_TIMER timer, - UINT MillisecondPeriod) +static inline void +SetPeriodicTimer(PWLAN_DRV_TIMER timer, UINT MillisecondPeriod) { timer->time_period = MillisecondPeriod; timer->timer_is_periodic = TRUE; @@ -84,9 +86,10 @@ timer->timer_is_canceled = FALSE; } -#define FreeTimer CancelTimer +#define FreeTimer(x) do {} while (0) -static inline void CancelTimer(WLAN_DRV_TIMER *timer) +static inline void +CancelTimer(WLAN_DRV_TIMER * timer) { del_timer(&timer->tl); timer->timer_is_canceled = TRUE; diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/wlan_thread.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/wlan_thread.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/os/linux/wlan_thread.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/os/linux/wlan_thread.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,12 @@ -/** +/* + * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -22,15 +22,16 @@ #include - -typedef struct { +typedef struct +{ struct task_struct *task; wait_queue_head_t waitQ; pid_t pid; void *priv; } wlan_thread; -static inline void wlan_activate_thread(wlan_thread *thr) +static inline void +wlan_activate_thread(wlan_thread * thr) { /** Record the thread pid */ thr->pid = current->pid; @@ -39,7 +40,8 @@ init_waitqueue_head(&thr->waitQ); } -static inline void wlan_deactivate_thread(wlan_thread *thr) +static inline void +wlan_deactivate_thread(wlan_thread * thr) { ENTER(); @@ -47,14 +48,14 @@ LEAVE(); } - -static inline void wlan_create_thread(int (*wlanfunc)(void *), - wlan_thread *thr, char *name) +static inline void +wlan_create_thread(int (*wlanfunc) (void *), wlan_thread * thr, char *name) { thr->task = kthread_run(wlanfunc, thr, "%s", name); } -static inline int wlan_terminate_thread(wlan_thread *thr) +static inline int +wlan_terminate_thread(wlan_thread * thr) { ENTER(); diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/README 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/README --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/README 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/README 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,13 @@ -================================================================================ - README for USB8388 +=============================================================================== + U S E R M A N U A L - (c) Copyright © 2003-2006, Marvell International Ltd. - All Rights Reserved + (c) Copyright © 2003-2007, Marvell International Ltd. This software file (the "File") is distributed by Marvell International Ltd. under the terms of the GNU General Public License Version 2, June 1991 (the "License"). You may use, redistribute and/or modify this File in accordance with the terms and conditions of the License, a copy of which - is available along with the File in the license.txt file or by writing to + is available along with the File in the gpl.txt file or by writing to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. @@ -16,55 +15,118 @@ IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. The License provides additional details about this warranty disclaimer. -================================================================================ -******************* This driver works in kernel 2.6.x only ********************* +=============================================================================== -=================== 1) FOR DRIVER BUILD -=================== - - o. Untar the source into a directory - - tar xvzf usb8388-xxxx.tgz - o. Change to the source directory + Goto source code directory src_xxxx. + make [clean] build + The driver and utility binaries can be found in ../bin_xxxx directory. - cd usb8388-xxxx/src +2) FOR DRIVER INSTALL - o. Modify Makefile if needed to set correct directory of kernel source + a) Copy helper_sd.bin and sd8686.bin | sd8388v.bin | ... to /lib/firmware/mrvl/ directory, + create the directory if it doesn't exist. + b) Install sdio bus driver and WLAN driver: + ./load sd8686 | sd8388v | ... + c) Uninstall WLAN driver and sdio bus driver: + ./unload - o. Build the driver +3) FOR DRIVER PROC & DEBUG - make distclean - make build + The following info are provided in /proc/net/wlan/info, - This should create the files including usb8388.ko which is the driver as - a loadable module. + driver_name = "wlan" + driver_version = + InterfaceName = "ethX" + Mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" + State = "Disconnected" | "Connected" + MACAddress = <6-byte adapter MAC address> + MCCount = + ESSID = + Channel = + region_code = + MCAddr[n] = + num_tx_bytes = + num_rx_bytes = + num_tx_pkts = + num_rx_pkts = + num_tx_pkts_dropped = + num_rx_pkts_dropped = + num_tx_pkts_err = + num_rx_pkts_err = + carrier "on" | "off" + tx queue "stopped" | "started" + CurCmd "NULL" | -===================== -2) FOR DRIVER LOADING -===================== + The following debug info are provided in /proc/net/wlan/debug, - o. Copy the firmware image (e.g. usb8388.bin) to /lib/firmware/ + IntCounter = + ConnectStatus = <0/1, disconnected/connected> + wmmQStp = <0/1, WMM queue started/stopped> + wmmPkts = + wmmAcVo = + wmmAcVi = + wmmAcBE = + wmmAcBK = + PSMode = <0/1, CAM mode/PS mode> + PSState = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state> + IsDeepSleep = <0/1, not deep sleep state/deep sleep state> + IsAutoDeepSleepEnabled = <0/1, not auto deep sleep mode/auto deep sleep mode> + WakeupDevReq = <0/1, wakeup device not required/required> + WakeupTries = + HS_Configured = <0/1, host sleep not configured/configured> + HS_Activated = <0/1, extended host sleep not activated/activated> + num_tx_timeout = + num_cmd_timeout = + TimeoutCmdId = + TimeoutCmdAct = + LastCmdId = + LastCmdAct = + LastCmdIndex = <0 based last command index> + LastCmdRespId = + LastCmdRespIndex = <0 based last command response index> + LastEvent = + LastEventIndex = <0 based last event index> + num_cmd_h2c_fail = + num_cmd_sleep_cfm_fail = + num_tx_h2c_fail = + num_evt_deauth = + num_evt_disassoc = + num_evt_link_lost = + num_cmd_deauth = + num_cmd_assoc_ok = + num_cmd_assoc_fail = + dnld_sent = <0/1/2, send resources available/sending data to device/sending command to device> - o. Load driver by using the following command: + Use dmesg or cat /var/log/debug to check driver debug messages. + To log driver debug messages to file, + a) Edit /etc/syslog.conf, add one line "*.debug /var/log/debug" + b) touch /var/log/debug (if the file doesn't exist) + c) service syslog restart - insmod usb8388.ko [fw_name=usb8388.bin] + Update /proc/sys/kernel/printk to change message log levels. + For example, + echo 6 > /proc/sys/kernel/printk (messages with a higher priority than 6 + will be printed to the console) + echo 15 > /proc/sys/kernel/printk (all messages will be printed to console) -===================== -3) FOR IWPRIV COMMAND -===================== +4) FOR IWPRIV COMMAND NAME This manual describes the usage of private commands used in Marvell WLAN Linux Driver. All the commands available in Wlanconfig will not be available in the iwpriv. + To use parameters as hex format, a'0x' must precede it for the parameters to + be parsed properly. + SYNOPSIS iwpriv [sub-command] ... iwpriv ethX version + iwpriv ethX verext iwpriv ethX scantype [sub-command] iwpriv ethX getSNR iwpriv ethX getNF @@ -74,19 +136,22 @@ iwpriv ethX settxant iwpriv ethX gettxant iwpriv ethX authalgs - iwpriv ethX pre-TBTT - iwpriv ethX 8021xauthalgs iwpriv ethX encryptionmode iwpriv ethX setregioncode iwpriv ethX getregioncode iwpriv ethX setbcnavg iwpriv ethX getbcnavg iwpriv ethX setdataavg + iwpriv ethX getdataavg iwpriv ethX setlisteninter iwpriv ethX getlisteninter iwpriv ethX setmultipledtim iwpriv ethX getmultipledtim iwpriv ethX atimwindow + iwpriv ethX deepsleep + iwpriv ethX autodeepsleep + iwpriv ethX hscfg + iwpriv ethX hssetpara iwpriv ethX deauth iwpriv ethX adhocstop iwpriv ethX radioon @@ -95,8 +160,9 @@ iwpriv ethX reasso-off iwpriv ethX scanmode [sub-command] iwpriv ethX setwpaie - iwpriv ethX wlanidle-off - iwpriv ethX wlanidle-on + iwpriv ethX setaeskey + iwpriv ethX getaeskey + iwpriv ethX rmaeskey iwpriv ethX getcis iwpriv ethX getlog iwpriv ethX getadhocstatus @@ -106,24 +172,35 @@ iwpriv ethX inactvityto iwpriv ethX sleeppd iwpriv ethX enable11d + iwpriv ethX bgscan + iwpriv ethX wmm iwpriv ethX tpccfg - iwpriv ethX powercfg - iwpriv ethX setafc - iwpriv ethX getafc + iwpriv ethX sdioclock Version 5 Command: iwpriv ethX ledgpio + iwpriv ethX wmm_qosinfo iwpriv ethX scanprobes iwpriv ethX lolisteninter - iwpriv ethX rateadapt + iwpriv ethX rateadapt + iwpriv ethX fwwakeupmethod iwpriv ethX txcontrol + iwpriv ethX uapsdnullgen iwpriv ethX psnullinterval - iwpriv ethX prescan iwpriv ethX getrxinfo iwpriv ethX gettxrate iwpriv ethX bcninterval [n] - iwpriv ethX linkmode - iwpriv ethX radiomode + iwpriv ethX setcoalescing + iwpriv ethX bcnmisto + iwpriv ethX adhocawakepd + iwpriv ethX sdiopullctrl + iwpriv ethX scantime [s] [a] [p] + iwpriv ethX ldocfg [n] + iwpriv ethX dataevtcfg [a] [b] [c] [d] [e] [f] [g] [h] [i] + iwpriv ethX drvdbg [n] [m] + iwpriv ethX adhocgprot [n] + iwpriv ethX getrate + iwpriv ethX associate DESCRIPTION Those commands are used to send additional commands to the Marvell WLAN @@ -135,6 +212,15 @@ version This is used to get the current version of the driver and the firmware. +verext + Retrieve and display an extended version string from the firmware + + Usage: + iwpriv ethX verext [#] + + where [#] is an optional argument to retrieve a specific version string, + omission of the argument retrieves the 0 indexed string + scantype This command is used to set the scan type to be used by the driver in the scan command. This setting will not be used while performing a scan @@ -149,7 +235,7 @@ This command gets the average and non average value of Signal to Noise Ratio of Beacon and Data. - where value is:- + where value is: 0 -- Beacon non-average. 1 -- Beacon average. 2 -- Data non-average. @@ -164,7 +250,7 @@ This command gets the average and non average value os Receive Signal Strength of Beacon and Data. - where value is:- + where value is: 0 -- Beacon non-average. 1 -- Beacon average. 2 -- Data non-average. @@ -176,7 +262,7 @@ This command gets the average and non average value of Noise Floor of Beacon and Data. - where value is:- + where value is: 0 -- Beacon non-average. 1 -- Beacon average. 2 -- Data non-average. @@ -198,7 +284,6 @@ getrxant This command is used to get the mode for Rx antenna. - settxant This command is used to set the mode for Tx antenna. The options that can be sent are:- @@ -215,17 +300,6 @@ This command is used by the WPA supplicant to set the authentication algorithms in the station. -8021xauthalgs - This command is used by the WPA supplicant to set the 8021.x authentication algorithm type - station. - - where values can be:- - 1 -- None - 2 -- LEAP - 4 -- TLS - 8 -- TTLs - 16 -- MD5 - encryptionmode This command is used by the WPA supplicant to set the encryption algorithm. @@ -236,13 +310,10 @@ 3 -- CCMP 4 -- WEP104 -pre-TBTT - This command is used to set pre-TBTT time period where value is in microseconds. - setregioncode This command is used to set the region code in the station. where value is 'region code' for various regions like - USA FCC, Canada IC, Spain, France, Europe ETSI, Japan ... + USA FCC, Canada IC, France, Europe ETSI, Japan ... Usage: iwpriv ethX setregioncode 0x10: set region code to USA (0x10). @@ -252,13 +323,32 @@ station. setbcnavg - Set the weighting factor for calculating RSSI. + Set the weighting factor for calculating beacon average RSSI and SNR. + where value can be: + 0 -- default beacon averaging factor (8) + 1-8 -- beacon averaging factor + Usage: + iwpriv ethX setbcnavg 0 + iwpriv ethX setbcnavg 8 getbcnavg - Get weighting factor for calculating RSSI. + Get the weighting factor for calculating beacon average RSSI and SNR. + Usage: + iwpriv ethX getbcnavg setdataavg - Set the weighting factor for calculating SNR. + Set the weighting factor for calculating data average RSSI and SNR. + where value can be: + 0 -- default data averaging factor (8) + 1-8 -- data averaging factor + Usage: + iwpriv ethX setdataavg 0 + iwpriv ethX setdataavg 8 + +getdataavg + Get the weighting factor for calculating data average RSSI and SNR. + Usage: + iwpriv ethX getdataavg setlisteninter This command is used to set the listen interval in the @@ -274,17 +364,26 @@ This command is used to set the multiple dtim value in the station. where the value is 1,2,3,4,5,0xfffe - 0xfffe means the firmware will use listen interval in association - command for waking up + 65534 (0xfffe) means that the dtim will be ignored in firmware, + listen interval or local listen interval will be used. getmultipledtim This command is used to get the multiple dtim value set in the station. atimwindow - This command is used to set the atim value in the - station. + This command is used to set atim value in the station when an argument is given, + return the atim value set by the user and the current atim value if adapter is in connected state. + The valid atimwindow is between 0 - 50. - where the value ranges between 0 - 50 + Usage: + iwpriv ethX atimwindow 0 (set atimwindow to 0) + + not connected: + iwpriv ethX atimwindow (get atimwindow value set by user) + + connected: + iwpriv ethX atimwindow (get atimwindow set by user previously + and current atimwindow) deauth This command is used to send the de-authentication to the AP with which @@ -321,22 +420,113 @@ ibss -- Scan All the IBSS networks. any -- Scan both BSS and IBSS networks. +deepsleep + This command is used to configure the station in deepsleep mode. + + where the option is: + 1 -- Enable deepsleep mode + 0 -- Disable deepsleep mode + 2 -- Display deepsleep setting + Usage: + iwpriv ethX deepsleep 1 + Enable deepsleep mode + iwpriv ethX deepsleep 0 + Disable deepsleep mode + iwpriv ethX deepsleep 2 + Display deepsleep setting + +autodeepsleep + This command is used to configure the station in auto deepsleep mode. + + where the option is: + 1 -- Enable auto deepsleep mode + 0 -- Disable auto deepsleep mode + Usage: + iwpriv ethX autodeepsleep + Read the current auto deepsleep setting + iwpriv ethX autodeepsleep 1 + Enable auto deepsleep mode + iwpriv ethX autodeepsleep 0 + Disable auto deepsleep mode + +hscfg + This command is used to configure the host sleep parameters. + + iwpriv ethX hscfg Condition [GPIO# [Gap]] + + Note: + + 1) This command takes one (Condition) or two (Condition and GPIO#) or three (Condition, GPIO# and gap) + parameters. + + where Condition is: + bit 0 = 1 -- broadcast data + bit 1 = 1 -- unicast data + bit 2 = 1 -- mac event + bit 3 = 1 -- multicast packet + + where GPIO is the pin number of GPIO used to wakeup the host. It could be any valid + GPIO pin# (e.g. 0-7) or 0xff (Interface, e.g. SDIO will be used instead). + + where Gap is the gap in milli seconds between wakeup signal and wakeup event + or 0xff for special setting. + + 2) the Host Sleep mode will be cancelled if condition is set to -1. + + 3) Usage: + iwpriv eth1 hscfg -1 # cancel host sleep mode + + iwpriv eth1 hscfg 3 # broadcast and unicast data + # use GPIO and GAP set previously + + iwpriv eth1 hscfg 2 0x3 # unicast data + # use GPIO 3 + # use GAP set previously + + iwpriv eth1 hscfg 2 1 0xa0 # unicast data + # use GPIO 1 + # gap: 160 ms + + iwpriv eth1 hscfg 2 0xff # unicast data + # use Interface (e.g. SDIO) + # use GAP set previously + iwpriv eth1 hscfg 0x2 0x3 0xff # unicast data + # use GPIO 3 + # special host sleep mode + + iwpriv eth1 hscfg 0x2 0xff 0xff # unicast data + # use Interface (e.g. SDIO) + # special host sleep mode + +hssetpara + This command is used to set host sleep parameters. + + iwpriv ethX hssetpara Condition [GPIO# [Gap]] + + Note: + 1) The usages of parameters are the same as "hscfg" command. + 2) The parameters will be saved in the driver and be usded when host suspends. setwpaie This command is used by WPA supplicant to send the WPA-IE to the driver. -wlanidle-off - This command is used to get into idle state. - - Note: This command is available only when STA is connected. +setaeskey + This command is used to set the AES key, when the station is in Ad-hoc + mode. -wlanidle-on - This command is used to get off the idle state. + where value can be any 16 byte value. - Note: This command is available only when STA is connected. + Usage: + iwpriv ethX setaeskey 12345678901234567890123456789012 +getaeskey + This command is used to get the AES key, when the station is in Ad-hoc + mode. +rmaeskey + This command is used to remove the Ad-Hoc AES key that is previously set. + It will disable ad-hoc AES as well. getcis This command is used to read the Card Info Structure Table. @@ -364,32 +554,31 @@ and request(2) the status which g_rate is disabled/enabled, for Ad-hoc creator. - where value is:- - 0 -- Disabled - 1 -- Enabled + where value is: + 0 -- Disable + 1 -- Enable 2 -- Get ledgpio - This command is used to set/get LEDs. + This command is used to set/get LED settings. iwpriv ethX ledgpio will set the corresponding LED for the GPIO Line. iwpriv ethX ledgpio - will give u which LEDs are Enabled. + will get the current LEDs settings. Usage: - iwpriv eth1 ledgpio 1 0 2 1 3 4 - will enable + iwpriv eth1 ledgpio 1 0 2 1 3 16 LED 1 -> GPIO 0 LED 2 -> GPIO 1 - LED 3 -> GPIO 4 + LED 3 -> disable iwpriv eth1 ledgpio shows LED information in the format as mentioned above. Note: LED0 is invalid - Note: Maximum Number of LEDs are 16. + Maximum Number of LEDs are 3. inactivityto This command is used by the host to set/get the inactivity timeout value, @@ -425,13 +614,30 @@ enable11d This command is used to control 11d - where value is:- - 1 -- Enabled - 0 -- Disabled + where value is: + 1 -- Enable + 0 -- Disable 2 -- Get +wmm + This command is used to control WMM + + where value is: + 0 -- Disable + 1 -- Enable + 2 -- Get + + +bgscan + Enables or disables the Background scan. + The configuration for bg scan must be set using wlanconfig + Usage: + wlanconfig ethX bgscanconfig bg_scan_config.conf + iwpriv ethX bgscan 0 (disable) + iwpriv ethX bgscan 1 (enable) + iwpriv ethX bgscan 2 (display enable or disable) tpccfg Enables or disables automatic transmit power control. @@ -452,54 +658,20 @@ iwpriv ethX tpccfg 0x01 0x01 0x05 0x0a 0x0d: enable auto TPC; use SNR; P0=0x05; P1=0x0a; P2=0x0d. -powercfg - Enables or disables power adaptation. - - The first parameter turns this feature on (1) or off (0). When turning - on, the user must also supply three more parameters in the following - order: - -P0 (P0 power level for Power Adaptation), - -P1 (P1 power level for Power Adaptation), - -P2 (P2 power level for Power Adaptation). +sdioclock + Turn On(1) or Off(0) the SDIO clock. Usage: - iwpriv ethX powercfg: Get current configuration - iwpriv ethX powercfg 0: disable power adaptation - iwpriv ethX powercfg 1 0x0d 0x0f 0x12: enable power adaptation; - P0=0x0d; P1=0x0f; P2=0x12. - -getafc - This command returns automatic frequency control parameters. It returns - three integers: - -P0: automatic is on (1), or off (0), - -P1: current timing offset in PPM (part per million), and - -P2: current frequency offset in PPM. - -setafc - Set automatic frequency control options. - - The first parameter turns automatic on (1) or off (0). - The user must supply two more parameters in either case, in the following - order: - - When auto is on: - - -P0 (automatic adjustment frequency threshold in PPM), - -P1 (automatic adjustment period in beacon period), - - When auto is off: + iwpriv ethX sdioclock 1 (on) + iwpriv ethX sdioclock 0 (off) - -P0 (manual adjustment timing offset in PPM), and - -P1 (manual adjustment frequency offset in PPM). +wmm_qosinfo + This command sets WMM IE QOS info when an argument is given, and gets current WMM + IE QOS info when no argument is given. Usage: - iwpriv ethX setafc 0 10 10: manual adjustment, both timing and frequcncy - offset are 10 PPM. - - iwpriv ethX setafc 1 10 10 enable afc, automatic adjustment, - frequency threshold 10 PPM, for every 10 beacon periods. - - + iwpriv ethX wmm_qosinfo 0x0f (set WMM IE QOS info to 0x0f) + iwpriv ethX wmm_qosinfo (get WMM IE QOS info) scanprobes This command sets number of probe requests per channel. @@ -518,9 +690,9 @@ rateadapt This command sets the data rates bitmap. Where - 0: Disable auto rate adapt - 1: Enable auto rate adapt - + 0: no HW rate drop + 1: HW table rate drop + 2: HW single rate drop data rate bitmap Bit Data rate @@ -538,20 +710,68 @@ 11 48 Mbps 12 54 Mbps 12-15 Reserved + Threshold, Number of same rate retries before switch to Final rate. + Used only if HW single rate drop is selected. Typical values are from 3 to 6. + Final Rate, This value is used only if HW single rate drop is selected. + value Data rate + 0 1 Mbps + 1 2 Mbps + 2 5.5 Mbps + 3 11 Mbps + 4 Reserved + 5 6 Mbps + 6 9 Mbps + 7 12 Mbps + 8 18 Mbps + 9 24 Mbps + 10 36 Mbps + 11 48 Mbps + 12 54 Mbps + 13-15 Reserved Usage: iwpriv ethX rateadapt read the currect data rate setting iwpriv ethX rateadapt 1 0x07 - enable auto data rate adapt and + enable hardware auto data rate adapt and data rates are 1Mbps, 2Mbsp and 5.5Mbps + iwpriv ethX rateadapt 2 0x0f 6 2 + use HW single rate drop, data rates are 1Mbps, 2Mbsp and 5.5Mbps, 11Mbps + Threshold is 6, Final Rate is 5.5 Mbps +fwwakeupmethod + This command is used to set the firmware wakeup method. -txcontrol - This command is used to set the Tx rate, ack policy, and retry limit on a per packet basis. + where value is: + 0 -- Leave the current method to wakeup firmware unchanged + 1 -- Firmware wakeup through the interface command interrupt + -- (default setting for SDIO/GSPI) + 2 -- Firmware wakeup through the GPIO pin + -- (default setting for CF) - Where value is: - if bit[4] == 1: + Usage: + iwpriv ethX fwwakeupmethod + Read the current firmware wakeup method setting + iwpriv ethX fwwakeupmethod 0 + Leave the current method to wakeup firmware unchanged + iwpriv ethX fwwakeupmethod 1 + Firmware wakeup through the interface command interrupt + iwpriv ethX fwwakeupmethod 2 + Firmware wakeup through the GPIO pin + +txcontrol [DefaultFlags (if no UP setting)] [UserPriority] [UserPriorityFlags] + This command is used to set/get the TX rate, WMM ack policy, and + retry limit for all packets, or selectively the packets with a specific + user priority. + + The DefaultFlags setting is ignored for any command with 2 or more + arguments. + + The value of the u32 txcontrol flags returned and input for + DefaultFlags or UserPriorityFlags specific settings is given by the + following bitmap: + + bit[4:0], if bit[4] == 1: bit[3:0] -- 0 1 2 3 4 5 6 7 8 9 10 11 12 13-16 Data Rate(Mbps) -- 1 2 5.5 11 Rsv 6 9 12 18 24 36 48 54 Rsv @@ -559,33 +779,48 @@ if bit[12] == 1, bit[11:8] specifies the Tx retry limit. bit[14:13] specifies per packet ack policy: - bit[14:13] - 1 0 use immediate ack policy for this packet - 1 1 use no ack policy for this packet - 0 x use the per-packet ack policy setting + if bit[14] == 1, bit[13] == 1 specifies No Ack Policy + + All unused and reserved bits should be set to zero for the entire + u32 field. Usage: - iwpriv ethX txcontrol 0x7513 - Use no-ack policy, 5 retires for Tx, 11Mbps rate + Number of arguments given: + 0: Return the default setting for the txcontrol flags + > iwpriv eth1 txcontrol + 1: Set the default value for the txcontrol flags + > iwpriv eth1 txcontrol 0x6013 - No ACK, 11Mbps + > iwpriv eth1 txcontrol 0x151A - 5 retries, 36Mbps + + 2: Return a specific User Priority setting. If the UP setting is zero, + the default value will be used and returned: + > iwpriv eth1 txcontrol 0 7 - Return UP 7 txcontrol value (UP7 = VO) + + 3: Set a User Priority specific value for the txcontrol flags. A value + of zero will revert to the default setting: + > iwpriv eth1 txcontrol 0 5 0x6013 - (UP5 = VI), No ACK 11Mbps. + +uapsdnullgen + This command is used to enable(1) UAPSD null package generation, + Disable(0) UAPSD null package generation, and request(2) the status + which null package generation is disabled/enabled, + for Ad-hoc creator. + + where value is: + 0 -- Disable + 1 -- Enable + 2 -- Get psnullinterval This command is used to set/request NULL package interval for Power Save under infrastructure mode. - where value is:- - -1 -- Disabled + where value is: + -1 -- Disable n>0 -- Set interval as n (seconds) -prescan - This command is used to enable (1)/disable(0) auto prescan before assoicate to the ap - - where value is:- - 0 -- Disabled - 1 -- Enabled - 2 -- Get - getrxinfo This command gets non average value of Signal to Noise Ratio of Data and rate index. @@ -629,40 +864,234 @@ 13-15 Reserved bcninterval - This command is used to set beacon interval in adhoc mode when an argument is given, and get current adhoc - beacon interval when no argument is given. The valid beacon interval is between 20 - 1000, - default beacon interval is 100. + This command is used to set beacon interval in adhoc mode when an argument is given, + return the value set by the user and the current adhoc beacon interval if adapter is in connected state. + The valid beacon interval is between 20 - 1000, default beacon interval is 100. Usage: iwpriv ethX bcninterval 100 (set adhoc beacon interval to 100) - iwpriv ethX bcninterval (get adhoc beacon interval) -linkmode - This command is used to set link-layer mode, 802.11 (raw mode)/802.3 mode. + not connected: + iwpriv ethX bcninterval (get adhoc beacon interval set by user) - where value is:- - 0 -- 802.3 mode - 2 -- 802.11 mode + connected: + iwpriv ethX bcninterval (get adhoc beacon interval set by user previously + and current beacon interval) - Note: The firmware is either 802.3 or 803.11 (cannot change at runtime). +setcoalescing + This command is used to disable/enable IBSS coalescing function, and get IBSS coalescing status. -radiomode - This command is used to set radio header mode. + where value is: + 0 -- Disable IBSS coalescing function + 1 -- Enable IBSS coalescing function + 2 -- Get current IBSS coalescing status - where value is:- - 0 -- no radio header - 2 -- radiotap header +bcnmisto + This command is used to set/get beacon miss timeout for Power Save + under infrastructure mode. -========================= -4) FOR WLANCONFIG COMMAND -========================= + where value is: + 0xffff -- Disabled + 0 -- no change + 1--50 (miliseconds) + +adhocawakepd + This command is used to set/get adhoc awake period for Power Save Mode. + + where value is: + 0xff -- firmware will go to sleep after send out beacon + 0--no change + 1--31 (beacon interval) + +sdiopullctrl + This command is used to set/get seting of pulling up and pulling down of SDIO lines, + The PullUp is the delay before pulling SDIO lines up. The PullDown is the + delay before pull SDIO lines down. the unit is us for both PullUp and PullDown. + + where PullUp + 0--no delay is needed + 0xffff--no pulling up is needed + + PullDown + 0--no delay is needed + 0xffff--no pulling up is needed + + Usage: + iwpriv ethX sdiopullctrl + Read the currect firmware SDIO PullUp and PullDown settings + iwpriv ethX sdiopullctrl 5 5 + Set SDIO PullUp/PullDown to 5 us + iwpriv ethX sdiopullctrl 0xffff 0xffff + Disable SDIO PullUp and PullDown + +scantime + This command is used to set/get scan time per channel in milliseconds. + The current setting will be returned every time. + + Usage: + iwpriv ethX scantime [s] [a] [p] + + where the parameters are, + [s]: specific SSID/BSSID scan time, default 100 ms, max 500 ms + [a]: active scan time, default 100 ms, max 500 ms + [p]: passive scan time, default 100 ms, max 2000 ms + No change if the parameter is 0 or the parameter is not provided. + + For example: + iwpriv ethX scantime 30 (set specific scan time to 30 ms) + iwpriv ethX scantime 0 100 (set active scan time to 100 ms) + iwpriv ethX scantime 30 80 200 (set specific scan time to 30 ms, + set active scan time to 80 ms, + set passive scan time to 200 ms) + +ldocfg + This command is used to set/get internal/external core power voltage source. + By default firmware uses internal LDO for 1.2V core power supply. + The current setting will be returned if no parameter provided. + + Usage: + iwpriv ethX ldocfg [n] + + where the parameter is, + 0 -- internal + 1 -- external + +dataevtcfg + This command is used to set/get the subscription of low RSSI, low SNR, high RSSI and + high SNR events in data packet. + + Where value is: + Events bitmap + Bit + 0 RSSI_LOW RSSI_LOW event is generated when avg data RSSI is below threshold + 1 SNR_LOW SNR_LOW event is generated when avg data SNR is below threshold + 2 RSSI_HIGH RSSI_HIGH event is generated when avg data RSSI go above threshold + 3 SNR_HIGH SNR_HIGH event is generated when avg data SNR go above threshold + + Where value is: + RSSI_LOW threshold (Absolute value, the actual value should be negative) + Where value is: + RSSI_LOW reporting frequency. if set to 0, event will only report once. + if set to 1, event will be reported every time it occur. + if set to N, event will be reported only when the condition happens N consecutive times. + + Where value is: + SNR_LOW threshold + Where value is: + SNR_LOW reporting frequency. if set to 0, event will only report once. + if set to 1, event will be reported every time it occur. + if set to N, event will be reported only when the condition happens N consecutive times. + + Where value is: + RSSI_HIGH threshold (Absolute value, the actual value should be negative) + Where value is: + RSSI_HIGH reporting frequency. if set to 0, event will only report once. + if set to 1, event will be reported every time it occur. + if set to N, event will be reported only when the condition happens N consecutive times. + + Where value is: + SNR_HIGH threshold + Where value is: + SNR_HIGH reporting frequency. if set to 0, event will only report once. + if set to 1, event will be reported every time it occur. + if set to N, event will be reported only when the condition happens N consecutive times. + + Usage: + iwpriv ethX dataevtcfg (get current data subscribe event settings) + iwpriv ethX dataevtcfg 15 70 1 56 0 40 5 86 0 + (set current data subscribe event, + when avg data RSSI below -70, such as -80, + RSSI_LOW event will be generated every time; + when avg data RSSI above -40 happens 5 consecutive times, + such as -30,-32,-34,-29,-33, RSSI_HIGH event will be generated 1 times; + when avg data SNR below 56 or above 86, + SNR_LOW or SNR_HIGHT event will be generated once) + +drvdbg + This command is used to set/get the bit masks of driver debug message control. + + Usage: + iwpriv ethX drvdbg [n] [m] + + Where the parameter is the generic debug message control bit mask. + The following types of driver debug messages can be dynamically enabled or + disabled by setting or clearing the corresponding bits, + bit 0: MSG PRINTM(MSG,...) + bit 1: FATAL PRINTM(FATAL,...) + bit 2: ERROR PRINTM(ERROR,...) + bit 3: DATA PRINTM(DATA,...) + bit 4: CMND PRINTM(CMND,...) + bit 5: EVENT PRINTM(EVENT,...) + bit 6: INTR PRINTM(INTR,...) + ... + bit 16: DAT_D PRINTM(DAT_D,...), DBG_HEXDUMP(DAT_D,...) + bit 17: CMD_D PRINTM(CMD_D,...), DBG_HEXDUMP(CMD_D,...) + bit 18: FW_D PRINTM(FW_D,...) + ... + bit 28: ENTRY PRINTM(ENTRY,...), ENTER(), LEAVE() + bit 29: WARN PRINTM(WARN,...) + bit 30: INFO PRINTM(INFO,...) + + Where the parameter is the extended interface module debug message control + bit mask. The following types of debug messages can be controlled. + + bit 0: IF_D PRINTM(IF_D,...), DBG_HEXDUMP(IF_D,...) + + If CONFIG_DEBUG=2, all kinds of debug messages can be configured. + By default all debug messages are enabled except for EVENT and IF_D. + + If CONFIG_DEBUG=1, all kinds of debug messages can be configured except + for ENTRY, WARN and INFO. By default MSG and FATAL are enabled. + + Some special debug messages, + '*' // WLAN driver ISR is called (bit 6 INTR enabled) + '|' // PS awake event is received (bit 5 EVENT enabled) + '_' // PS sleep event is received (bit 5 EVENT enabled) + '+' // PS sleep confirm is sent (bit 5 EVENT enabled) + + For example: + iwpriv ethX drvdbg (get the current driver debug masks) + iwpriv ethX drvdbg 0 0 (disable all the debug messages) + iwpriv ethX drvdbg 7 (enable MSG, FATAL and ERROR messages, + no change for if debug control) + iwpriv ethX drvdbg 3 1 (enable MSG and FATAL messages, + enable IF_D message) + iwpriv ethX drvdbg -1 -1 (enable all the debug messages) + +adhocgprot + This command is used to set/get 802.11g ad-hoc protection state. + + where value is: + 0 -- Disable + 1 -- Enable + 2 -- Get + Usage: + iwpriv ethX adhocgprot 0 (disable 802.11g ad-hoc g protection) + iwpriv ethX adhocgprot 1 (enable 802.11g ad-hoc g protection) + iwpriv ethX adhocgprot 2 (get 802.11g ad-hoc g protection state) + +getrate + This command is used to get the supported rates. Returned rates are in 0.5M unit. + +associate + Associate to a specific BSS entry in the scan table. The enumeration + of the entries in the scan table is determined by the + getscantable API or from the iwlist scan results. A re-scan is not + performed before the association attempt is made. + + +=============================================================================== + + U S E R M A N U A L F O R W L A N _ C O N F I G NAME wlanconfig - configure the additional parameters available for the Marvell WLAN Linux Driver. SYNOPSIS +wlanconfig -v wlanconfig [parameters] ... + wlanconfig ethX version wlanconfig ethX wlanconfig ethX @@ -666,13 +1095,17 @@ wlanconfig ethX version wlanconfig ethX wlanconfig ethX +wlanconfig ethX sdcmd52r
+wlanconfig ethX sdcmd52w
+wlanconfig ethX caldataext wlanconfig ethX rdeeprom -wlanconfig ethX getrate wlanconfig ethX sleepparams +wlanconfig ethX bca-ts wlanconfig ethX extscan wlanconfig ethX getscanlist Version 4 Command: +wlanconfig ethX bgscanconfig Version 5 Command: wlanconfig ethX hostcmd @@ -681,14 +1114,42 @@ Version 6 Command: wlanconfig ethX setuserscan [ARGS] wlanconfig ethX getscantable +wlanconfig ethX getassocrsp Version 8 +wlanconfig ethX addts +wlanconfig ethX delts +wlanconfig ethX qconfig set msdu [Queue Id: 0-3] +wlanconfig ethX qconfig get [Queue Id: 0-3] +wlanconfig ethX qconfig def [Queue Id: 0-3] +wlanconfig ethX qstats on [Queue Id: 0-3] +wlanconfig ethX qstats off [Queue Id: 0-3] +wlanconfig ethX qstats get [Queue Id: 0-3] +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hostcmd +wlanconfig ethX hstest +wlanconfig ethX getcfptable [region] + +Version 9 +wlanconfig ethX gettsf +wlanconfig ethX arpfilter +wlanconfig ethX txpktstats DESCRIPTION those commands are used in Marvell specic applicaion called wlanconfig. =========== +-v + This command is used to display the version of wlanconfig utility. + Usage: + wlanconfig -v + rdmac rdbbp rdrf @@ -716,8 +1177,38 @@ wlanconfig ethX wrbbp 0x0123 0xaa wlanconfig ethX wrrf 0x0123 0xaa +sdcmd52r + This command is used to read a controller register in + Secure Digital I/O Interfaces. + + wlanconfig eth1 sdcmd52r + + Usage: + wlanconfig eth1 sdcmd52r 0x00 0x07 +sdcmd52w + This command is used to write to a controller register in + Secure Digital I/O Interfaces. + wlanconfig eth1 sdcmd52w + + Usage: + wlanconfig eth1 sdcmd52w 0x00 0x02 0x0a + +caldataext + In order to overcome the situation without EEPROM in the WLAN module, + we send the extension calibration command to modify the existing + hardware-spec command. This command takes one parameter that specifies + the file name of the configuration file. + + Usage: + wlanconfig eth1 caldataext .conf> + cal_data_ext_set_.conf is a configuration file to the + wlanconfig to set the calibration values. The 3 existing + versions are v5, vA and v7. + Example: + wlanconfig eth1 caldataext cal_data_ext_set_v5.conf + Edit this file for changing calibration values. rdeeprom To read the EEPROM contents of the card. @@ -725,9 +1216,6 @@ Usage: wlanconfig ethX rdeeprom 0x00 0x10 -getrate - To get the supported rates and the current rate. - sleepparams This command is used to set the sleepclock configurations @@ -744,9 +1232,41 @@ p5 is Control the use of external sleep clock (0-2) p6 is reserved for debug (0-65535) +bca-ts + This command is used to set/get the BCA timeshare parameters. + + This command only works after BCA been enabled. + + Usage: + wlanconfig ethX bca-ts + + where: + Traffic Type 0 - Wlan and bluetooth are low priority. + 1 - Wlan and bluetooth are high priority. + + TimeShareInterval value is not multiple of 10 then floor value + is taken and the valid range is < 20 ... 60,000 > in milliseconds. + + BTTime value is not multiple of 10 then floor value is + taken and the valid range is < 0 ... TimeShareInterval value > + in milliseconds. + + Example: + wlanconfig ethX bca-ts get 1 + get the BCA timeshare settings when wlan and bluetooth are set to high priority. + + wlanconfig ethX bca-ts set 1 30 20 + set wlan and bluetooth to high priority, wlan TimeShareInterval to 30ms, BTTime to 20ms. + +bgscanconfig + This will configure the various parameters for background scan. + wlanconfig ethX bgscanconfig bg_scan_config.conf + bg_scan_config.conf is the configuration file to wlanconfig + + Edit this file for changing bg scan values. hostcmd hostcmd @@ -761,7 +1281,6 @@ wlanconfig ethX hostcmd hostcmd.conf subevent_get wlanconfig ethX hostcmd hostcmd.conf subevent_set - extscan This command is used to do a specific scan. @@ -780,9 +1299,6 @@ Example: wlanconfig ethX getscanlist - - - setuserscan Initiate a customized scan and retrieve the results @@ -795,9 +1311,13 @@ blank for active or 'p' for passive bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan ssid="[SSID]" specify a SSID filter for the scan + wc="[WILDCARD SSID]" specify a UNIX pattern matching filter (using * + and ?) for SSIDs found in a broadcast probe keep=[0 or 1] keep the previous scan results (1), discard (0) dur=[scan time] time to scan for each channel in milliseconds probes=[#] number of probe requests to send on each chan + for each broadcast probe required and each SSID + specific probe required type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any) Any combination of the above arguments can be supplied on the command line. @@ -830,18 +1350,220 @@ BSSID/SSID matches with the new scan data: setuserscan chan=6g type=1 probes=2 keep=1 + 7) Scan channel 1 and 6, for all networks matching the Mrvl*AP + or AP*Mrvl? patterns and for MrvlTst SSID. Generate 3 broadcast + probes for the patterns and 3 SSID specific probes for MrvlTst on + both channel 1 and channel 6. + chan=1g,6g probes=3 wc="Mrvl*AP" wc="AP*Mrvl?" ssid="MrvlTst" + All entries in the scan table (not just the new scan data when keep=1) will be displayed upon completion by use of the getscantable ioctl. - getscantable Display the current contents of the driver scan table Usage: wlanconfig ethX getscantable + wlanconfig ethX getscantable [#] + wlanconfig ethX getscantable tsf + wlanconfig ethX getscantable help + + 1) Without argument, the entire scantable is displayed. + 2) Specifying a # will display detailed information about a specific scan + table entry. '0' displays driver cached information regarding the + current association (if any). + 3) The tsf argument will display the entire scan table with the recorded + TSF timestamp for the entry. + 4) The help argument will display the legend for the capability field + +getassocrsp + Display the contents of the driver association response buffer. The + driver buffer is cleared after the response is returned to prevent + state response buffer returns. + + Usage: + wlanconfig ethX getassocrsp + +setmrvltlv + Setup a test Marvell TLV for the driver to insert in the next + association command to the firmware. + + wlanconfig will provision a test TLV that can be verified in the assoc. + response to the AP. Used to test the IOCTL functionality. + + Usage: + wlanconfig ethX setmrvltlv + +addts + Send an ADDTS command to the associated AP. + + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in an ADDTS request to the associated AP. + + Return the execution status of the command as well as the ADDTS response + from the AP if any. + + Usage: + wlanconfig ethX addts + +delts + Send a DELTS command to the associated AP. + Process a given conf file for a specific TSPEC data block. Send the + TSPEC along with any other IEs to the driver/firmware for transmission + in a DELTS request to the associated AP. + Return the execution status of the command. There is no response to a + DELTS from the AP. + Usage: + wlanconfig ethX delts +qconfig + Send a WMM AC Queue configuration command to get/set/default params + + Configure or get the parameters of a WMM AC queue. The command takes + an optional Queue Id as a last parameter. Without the queue id, all + queues will be acted upon. + + Usage: + wlanconfig ethX qconfig set msdu [Queue Id: 0-3] + wlanconfig ethX qconfig get [Queue Id: 0-3] + wlanconfig ethX qconfig def [Queue Id: 0-3] + +qstats + Turn on/off or retrieve and clear the queue statistics for an AC + + Turn the queue statistics collection on/off for a given AC or retrieve the + current accumulated stats and clear them from the firmware. The command + takes an optional Queue Id as a last parameter. Without the queue id, + all queues will be acted upon. + + Usage: + wlanconfig ethX qstats on [Queue Id: 0-3] + wlanconfig ethX qstats off [Queue Id: 0-3] + wlanconfig ethX qstats get [Queue Id: 0-3] + +hostcmd +hostcmd + This configures the power adaptation paramemters + + Usage: + wlanconfig ethX hostcmd hostcmd.conf pa_cfg_ext_get + wlanconfig ethX hostcmd hostcmd.conf pa_cfg_ext_set + + hostcmd.conf is a generic configuration file containing multiple configuration enties + for power adapation + pa_cfg_ext_get: get pa_cfg_ext parameters + pa_cfg_ext_set: set pa_cfg_ext parameters + + The following table shows the bitmap of the rates (bit 0 is the least significant bit): + + Bit Data rate + 0 1 Mbps + 1 2 Mbps + 2 5.5 Mbps + 3 11 Mbps + 4 Reserved + 5 6 Mbps + 6 9 Mbps + 7 12 Mbps + 8 18 Mbps + 9 24 Mbps + 10 36 Mbps + 11 48 Mbps + 12 54 Mbps + 13-15 Reserved + + Up to 5 power level groups are supported. + + The default power adaptation groups: + + Power Level Rate Bitmap (Mbps) + 13 dbm 0x1800 (54, 48) + 15 dbm 0x07e0 (36, 24, 18, 12, 9, 6) + 18 dbm 0x000f (11, 5.5, 2, 1) + + Edit the hostcmd.conf file to change the settings + +hostcmd + This is an extended host_sleep_cfg command to configure the ARP filtering parameters. + + Usage: + wlanconfig ethX hostcmd hostcmd.conf arp_filter + + Edit the arp_filter section in hostcmd.conf file to change the settings + +hostcmd +hostcmd +hostcmd + This configures the Frame Auto Transmission paramemters + + Usage: + wlanconfig ethX hostcmd hostcmd.conf auto_tx_get + wlanconfig ethX hostcmd hostcmd.conf NatKeepAlive + wlanconfig ethX hostcmd hostcmd.conf auto_tx_unreg + + hostcmd.conf is a generic configuration file containing multiple configuration enties + for Frame Auto Transmission + auto_tx_get: get auto_tx parameters + NatKeepAlive: register to firmware for sending NAT Keep Alive packet + auto_tx_unreg: unregister to firmware auto_tx + + Edit the auto_tx section in hostcmd.conf file to change the settings + +hostcmd + This command is used to set/get LED control. + + Usage: + wlanconfig ethX hostcmd hostcmd.conf ledctrl_get + wlanconfig ethX hostcmd hostcmd.conf ledctrl_set + + hostcmd.conf is a generic configuration file containing multiple configuration enties + for LED Ctrl + led_ctrl_get: get auto_tx parameters + led_ctrl_set: set auto_tx parameters + + Edit the ledctrl section in hostcmd.conf file to change the settings + +hstest + This command runs in the background to handle GPIO/SDIO interrupt events + in HOST SLEEP mode. + + Usage: + wlanconfig ethX hstest & + +getcfptable + This command is used to get Channel-Freq-MaxTxPower table based on the region code. + If no parameter provided, the CFP table for current region code will be returned. + + Usage: + wlanconfig ethX getcfptable [region] + +gettsf + Display the current MAC TSF value. + +arpfilter + This command is used to configure the ARP filtering parameters. + + Usage: + wlanconfig ethX arpfilter arpfilter.conf + + Edit arpfilter.conf file to change the settings + +txpktstats + Retrieve and clear transmit packet statistics collected by the firmware: + + The API displays the following statistics for each rate: + - Number of packets initially queued using the rate + - Number of total attempts for the packets queued using this initial + rate. This includes attempts at other rates in case of hardware or + single rate drop modes. + - Number of retry exhaustion failures for packets queued using this + initial rate. + - Number of MSDU lifetime expiry failures for packets queued using + this initial rate. + - Number of packets successfully completed at this rate ============================================================================== diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/release_version.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/release_version.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/release_version.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/release_version.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,12 +1,11 @@ /** * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -17,6 +16,4 @@ * */ -#define KERVER "26" -#define DRIVER_RELEASE_VERSION KERVER"318.p7" - +#define DRIVER_RELEASE_VERSION "26409.p39" diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/hostcmd.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/hostcmd.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/hostcmd.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/hostcmd.h 2007-11-06 12:26:40.000000000 -0500 @@ -3,14 +3,13 @@ * @brief This file contains the function prototypes, data structure * and defines for all the host/station commands * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -28,7 +27,10 @@ 04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API - + 05/03/06: Add auto_tx hostcmd + 05/04/06: Add IBSS coalescing related new hostcmd + 08/28/06: Add LED_CTRL hostcmd + 08/29/06: Add ledgpio private command ********************************************************/ #ifndef __HOSTCMD__H @@ -46,14 +48,12 @@ u32 TxPacketLocation; /** Tx packet length */ u16 TxPacketLength; - /** First 2 byte of destination MAC address */ - u8 TxDestAddrHigh[2]; - /** Last 4 byte of destination MAC address */ - u8 TxDestAddrLow[4]; + /**Destination MAC address */ + u8 TxDestAddr[MRVDRV_ETH_ADDR_LEN]; /** Pkt Priority */ u8 Priority; - /** Pkt Trasnit Power control*/ - u8 PowerMgmt; + /** Trasnit Pkt Flags*/ + u8 Flags; /** Amount of time the packet has been queued in the driver (units = 2ms)*/ u8 PktDelay_2ms; /** Reserved */ @@ -61,11 +61,11 @@ } __ATTRIB_PACK__ TxPD, *PTxPD; - /** RxPD Descriptor */ -typedef struct _RxPD { +typedef struct _RxPD +{ /** Current Rx packet status */ - u16 Status; + u16 RxStatus; /** SNR */ u8 SNR; @@ -82,12 +82,10 @@ /** Rx Packet Rate */ u8 RxRate; - /** Pkt addr*/ - u32 PktPtr; - - /** Next Rx RxPD addr */ - u32 NextRxPDPtr; - + /** Pkt offset */ + u32 PktOffset; + u8 RxPacketType; + u8 Reserved_1[3]; /** Pkt Priority */ u8 Priority; u8 Reserved[3]; @@ -145,10 +143,11 @@ WLAN_802_11_MAC_ADDRESS BSSID; WLAN_802_11_KEY_RSC KeyRSC; u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH]; -} __ATTRIB_PACK__ WLAN_802_11_KEY, *PWLAN_802_11_KEY; +} __ATTRIB_PACK__ WLAN_802_11_KEY; /** MRVL_WPA_KEY */ -typedef struct _MRVL_WPA_KEY { +typedef struct _MRVL_WPA_KEY +{ u32 KeyIndex; u32 KeyLength; u32 KeyRSC; @@ -156,21 +155,13 @@ } MRVL_WPA_KEY, *PMRVL_WPA_KEY; /** MRVL_WLAN_WPA_KEY */ -typedef struct _MRVL_WLAN_WPA_KEY { +typedef struct _MRVL_WLAN_WPA_KEY +{ u8 EncryptionKey[16]; u8 MICKey1[8]; u8 MICKey2[8]; } MRVL_WLAN_WPA_KEY, *PMRVL_WLAN_WPA_KEY; -/** IE_WPA */ -typedef struct _IE_WPA { - u8 Elementid; - u8 Len; - u8 oui[4]; - u16 version; -} IE_WPA,*PIE_WPA; - - /* Received Signal Strength Indication in dBm*/ typedef LONG WLAN_802_11_RSSI; @@ -188,71 +179,70 @@ /* variable length depending on above field */ u8 KeyMaterial[1]; -} __ATTRIB_PACK__ WLAN_802_11_WEP, *PWLAN_802_11_WEP; +} __ATTRIB_PACK__ WLAN_802_11_WEP; /** WLAN_802_11_SSID */ -typedef struct _WLAN_802_11_SSID { +typedef struct _WLAN_802_11_SSID +{ /* SSID Length*/ u32 SsidLength; /* SSID information field */ u8 Ssid[WLAN_MAX_SSID_LENGTH]; -}__ATTRIB_PACK__ WLAN_802_11_SSID, *PWLAN_802_11_SSID; - -typedef struct _WPA_SUPPLICANT { - u8 Wpa_ie[256]; - u8 Wpa_ie_len; -} WPA_SUPPLICANT, *PWPA_SUPPLICANT; - +} __ATTRIB_PACK__ WLAN_802_11_SSID; typedef u32 WLAN_802_11_FRAGMENTATION_THRESHOLD; typedef u32 WLAN_802_11_RTS_THRESHOLD; typedef u32 WLAN_802_11_ANTENNA; /** wlan_offset_value */ -typedef struct _wlan_offset_value { +typedef struct _wlan_offset_value +{ u32 offset; u32 value; } wlan_offset_value; /** WLAN_802_11_FIXED_IEs */ -typedef struct _WLAN_802_11_FIXED_IEs { +typedef struct _WLAN_802_11_FIXED_IEs +{ u8 Timestamp[8]; u16 BeaconInterval; u16 Capabilities; -} WLAN_802_11_FIXED_IEs, *PWLAN_802_11_FIXED_IEs; +} WLAN_802_11_FIXED_IEs; /** WLAN_802_11_VARIABLE_IEs */ -typedef struct _WLAN_802_11_VARIABLE_IEs { +typedef struct _WLAN_802_11_VARIABLE_IEs +{ u8 ElementID; u8 Length; u8 data[1]; -} WLAN_802_11_VARIABLE_IEs, *PWLAN_802_11_VARIABLE_IEs; +} WLAN_802_11_VARIABLE_IEs; /** WLAN_802_11_AI_RESFI */ -typedef struct _WLAN_802_11_AI_RESFI { +typedef struct _WLAN_802_11_AI_RESFI +{ u16 Capabilities; u16 StatusCode; u16 AssociationId; -} WLAN_802_11_AI_RESFI, *PWLAN_802_11_AI_RESFI; +} WLAN_802_11_AI_RESFI; /** WLAN_802_11_AI_REQFI */ -typedef struct _WLAN_802_11_AI_REQFI { +typedef struct _WLAN_802_11_AI_REQFI +{ u16 Capabilities; u16 ListenInterval; WLAN_802_11_MAC_ADDRESS CurrentAPAddress; -} WLAN_802_11_AI_REQFI, *PWLAN_802_11_AI_REQFI; - +} WLAN_802_11_AI_REQFI; /* Define general data structure */ /** HostCmd_DS_GEN */ -typedef struct _HostCmd_DS_GEN { +typedef struct _HostCmd_DS_GEN +{ u16 Command; u16 Size; u16 SeqNum; u16 Result; -} __ATTRIB_PACK__ HostCmd_DS_GEN, *PHostCmd_DS_GEN - ; +} __ATTRIB_PACK__ HostCmd_DS_GEN, HostCmd_DS_802_11_DEEP_SLEEP; #define S_DS_GEN sizeof(HostCmd_DS_GEN) /* @@ -286,32 +276,19 @@ /* FW release number, example 0x1234=1.2.3.4 */ u32 FWReleaseNumber; - /* Base Address of TxPD queue */ - u32 WcbBase; - /* Read Pointer of RxPd queue */ - u32 RxPdRdPtr; + u32 Reserved_1; - /* Write Pointer of RxPd queue */ - u32 RxPdWrPtr; + u32 Reserved_2; + + u32 Reserved_3; /*FW/HW Capability*/ u32 fwCapInfo; -} __ATTRIB_PACK__ HostCmd_DS_GET_HW_SPEC, *PHostCmd_DS_GET_HW_SPEC; - -/** HostCmd_CMD_EEPROM_UPDATE */ -typedef struct _HostCmd_DS_EEPROM_UPDATE { - u16 Action; - u32 Value; -} __ATTRIB_PACK__ HostCmd_DS_EEPROM_UPDATE, *PHostCmd_DS_EEPROM_UPDATE; +} __ATTRIB_PACK__ HostCmd_DS_GET_HW_SPEC; -/** HostCmd_CMD_802_11_RESET */ -typedef struct _HostCmd_DS_802_11_RESET +typedef struct _HostCmd_DS_802_11_SUBSCRIBE_EVENT { u16 Action; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RESET, *PHostCmd_DS_802_11_RESET; - -typedef struct _HostCmd_DS_802_11_SUBSCRIBE_EVENT { - u16 Action; u16 Events; } __ATTRIB_PACK__ HostCmd_DS_802_11_SUBSCRIBE_EVENT; @@ -320,7 +297,8 @@ * Define data structure for HostCmd_CMD_802_11_SCAN */ /** HostCmd_DS_802_11_SCAN */ -typedef struct _HostCmd_DS_802_11_SCAN { +typedef struct _HostCmd_DS_802_11_SCAN +{ u8 BSSType; u8 BSSID[ETH_ALEN]; u8 TlvBuffer[1]; @@ -328,18 +306,19 @@ * MrvlIEtypes_ChanListParamSet_t ChanListParamSet; * MrvlIEtypes_RatesParamSet_t OpRateSet; * */ -} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN, *PHostCmd_DS_802_11_SCAN; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN; -typedef struct _HostCmd_DS_802_11_SCAN_RSP { +typedef struct _HostCmd_DS_802_11_SCAN_RSP +{ u16 BSSDescriptSize; u8 NumberOfSets; u8 BssDescAndTlvBuffer[1]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN_RSP, - *PHostCmd_DS_802_11_SCAN_RSP; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SCAN_RSP; /** HostCmd_CMD_802_11_GET_LOG */ -typedef struct _HostCmd_DS_802_11_GET_LOG { +typedef struct _HostCmd_DS_802_11_GET_LOG +{ u32 mcasttxframe; u32 failed; u32 retry; @@ -352,49 +331,30 @@ u32 mcastrxframe; u32 fcserror; u32 txframe; - u32 wepundecryptable; -} __ATTRIB_PACK__ HostCmd_DS_802_11_GET_LOG, - *PHostCmd_DS_802_11_GET_LOG; + u32 reserved; +} __ATTRIB_PACK__ HostCmd_DS_802_11_GET_LOG; /** HostCmd_CMD_MAC_CONTROL */ typedef struct _HostCmd_DS_MAC_CONTROL { u16 Action; u16 Reserved; -} __ATTRIB_PACK__ HostCmd_DS_MAC_CONTROL, *PHostCmd_DS_MAC_CONTROL; +} __ATTRIB_PACK__ HostCmd_DS_MAC_CONTROL; /** HostCmd_CMD_MAC_MULTICAST_ADR */ -typedef struct _HostCmd_DS_MAC_MULTICAST_ADR { +typedef struct _HostCmd_DS_MAC_MULTICAST_ADR +{ u16 Action; u16 NumOfAdrs; u8 MACList[MRVDRV_ETH_ADDR_LEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -} __ATTRIB_PACK__ HostCmd_DS_MAC_MULTICAST_ADR, - *PHostCmd_DS_MAC_MULTICAST_ADR; - -/** HostCmd_CMD_802_11_AUTHENTICATE */ -typedef struct _HostCmd_DS_802_11_AUTHENTICATE { - u8 MacAddr[ETH_ALEN]; - u8 AuthType; - u8 Reserved[10]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTHENTICATE, - *PHostCmd_DS_802_11_AUTHENTICATE; - -/** HostCmd_RET_802_11_AUTHENTICATE */ -typedef struct _HostCmd_DS_802_11_AUTHENTICATE_RSP -{ - u8 MacAddr[6]; - u8 AuthType; - u8 AuthStatus; -} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTHENTICATE_RSP, - *PHostCmd_DS_802_11_AUTHENTICATE_RSP; +} __ATTRIB_PACK__ HostCmd_DS_MAC_MULTICAST_ADR; /** HostCmd_CMD_802_11_DEAUTHENTICATE */ typedef struct _HostCmd_DS_802_11_DEAUTHENTICATE { u8 MacAddr[6]; u16 ReasonCode; -} __ATTRIB_PACK__ HostCmd_DS_802_11_DEAUTHENTICATE, - *PHostCmd_DS_802_11_DEAUTHENTICATE; +} __ATTRIB_PACK__ HostCmd_DS_802_11_DEAUTHENTICATE; /** HostCmd_DS_802_11_ASSOCIATE */ typedef struct _HostCmd_DS_802_11_ASSOCIATE @@ -402,8 +362,7 @@ u8 PeerStaAddr[6]; IEEEtypes_CapInfo_t CapInfo; u16 ListenInterval; - u16 BcnPeriod; - u8 DtimPeriod; + u8 Reserved1[3]; /* * MrvlIEtypes_SsIdParamSet_t SsIdParamSet; @@ -411,16 +370,7 @@ * MrvlIEtypes_SsParamSet_t SsParamSet; * MrvlIEtypes_RatesParamSet_t RatesParamSet; */ -} __ATTRIB_PACK__ HostCmd_DS_802_11_ASSOCIATE, - *PHostCmd_DS_802_11_ASSOCIATE; - -/** HostCmd_CMD_802_11_DISASSOCIATE */ -typedef struct _HostCmd_DS_802_11_DISASSOCIATE -{ - u8 DestMacAddr[6]; - u16 ReasonCode; -} __ATTRIB_PACK__ HostCmd_DS_802_11_DISASSOCIATE, - *PHostCmd_DS_802_11_DISASSOCIATE; +} __ATTRIB_PACK__ HostCmd_DS_802_11_ASSOCIATE; /** HostCmd_RET_802_11_ASSOCIATE */ typedef struct @@ -433,8 +383,7 @@ { u8 PAD[3]; u8 BSSID[MRVDRV_ETH_ADDR_LEN]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_RESULT, - *PHostCmd_DS_802_11_AD_HOC_RESULT; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_RESULT; /** HostCmd_CMD_802_11_SET_WEP */ typedef struct _HostCmd_DS_802_11_SET_WEP @@ -455,55 +404,13 @@ u8 WEP2[16]; u8 WEP3[16]; u8 WEP4[16]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_SET_WEP, - *PHostCmd_DS_802_11_SET_WEP; - -/** HostCmd_CMD_802_3_GET_STAT */ -typedef struct _HostCmd_DS_802_3_GET_STAT -{ - u32 XmitOK; - u32 RcvOK; - u32 XmitError; - u32 RcvError; - u32 RcvNoBuffer; - u32 RcvCRCError; -} __ATTRIB_PACK__ HostCmd_DS_802_3_GET_STAT, - *PHostCmd_DS_802_3_GET_STAT; - -/** HostCmd_CMD_802_11_GET_STAT */ -typedef struct _HostCmd_DS_802_11_GET_STAT -{ - u32 TXFragmentCnt; - u32 MCastTXFrameCnt; - u32 FailedCnt; - u32 RetryCnt; - u32 MultipleRetryCnt; - u32 RTSSuccessCnt; - u32 RTSFailureCnt; - u32 ACKFailureCnt; - u32 FrameDuplicateCnt; - u32 RXFragmentCnt; - u32 MCastRXFrameCnt; - u32 FCSErrorCnt; - u32 BCastTXFrameCnt; - u32 BCastRXFrameCnt; - u32 TXBeacon; - u32 RXBeacon; - u32 WEPUndecryptable; -} __ATTRIB_PACK__ HostCmd_DS_802_11_GET_STAT, - *PHostCmd_DS_802_11_GET_STAT; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SET_WEP; /** HostCmd_DS_802_11_AD_HOC_STOP */ -typedef struct _HostCmd_DS_802_11_AD_HOC_STOP { - -} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_STOP, - *PHostCmd_DS_802_11_AD_HOC_STOP; - -/** HostCmd_DS_802_11_BEACON_STOP */ -typedef struct _HostCmd_DS_802_11_BEACON_STOP { +typedef struct _HostCmd_DS_802_11_AD_HOC_STOP +{ -} __ATTRIB_PACK__ HostCmd_DS_802_11_BEACON_STOP, - *PHostCmd_DS_802_11_BEACON_STOP; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_STOP; /** HostCmd_CMD_802_11_SNMP_MIB */ typedef struct _HostCmd_DS_802_11_SNMP_MIB @@ -512,32 +419,7 @@ u16 OID; u16 BufSize; u8 Value[128]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_SNMP_MIB, - *PHostCmd_DS_802_11_SNMP_MIB; - -/** HostCmd_CMD_MAC_REG_MAP */ -typedef struct _HostCmd_DS_MAC_REG_MAP -{ - u16 BufferSize; - u8 RegMap[128]; - u16 Reserved; -} __ATTRIB_PACK__ HostCmd_DS_MAC_REG_MAP, *PHostCmd_DS_MAC_REG_MAP; - -/* HostCmd_CMD_BBP_REG_MAP */ -typedef struct _HostCmd_DS_BBP_REG_MAP -{ - u16 BufferSize; - u8 RegMap[128]; - u16 Reserved; -} __ATTRIB_PACK__ HostCmd_DS_BBP_REG_MAP, *PHostCmd_DS_BBP_REG_MAP; - -/** HostCmd_CMD_RF_REG_MAP */ -typedef struct _HostCmd_DS_RF_REG_MAP -{ - u16 BufferSize; - u8 RegMap[64]; - u16 Reserved; -} __ATTRIB_PACK__ HostCmd_DS_RF_REG_MAP, *PHostCmd_DS_RF_REG_MAP; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SNMP_MIB; /** HostCmd_CMD_MAC_REG_ACCESS */ typedef struct _HostCmd_DS_MAC_REG_ACCESS @@ -545,8 +427,7 @@ u16 Action; u16 Offset; u32 Value; -} __ATTRIB_PACK__ HostCmd_DS_MAC_REG_ACCESS, - *PHostCmd_DS_MAC_REG_ACCESS; +} __ATTRIB_PACK__ HostCmd_DS_MAC_REG_ACCESS; /** HostCmd_CMD_BBP_REG_ACCESS */ typedef struct _HostCmd_DS_BBP_REG_ACCESS @@ -555,8 +436,7 @@ u16 Offset; u8 Value; u8 Reserved[3]; -} __ATTRIB_PACK__ HostCmd_DS_BBP_REG_ACCESS, - *PHostCmd_DS_BBP_REG_ACCESS; +} __ATTRIB_PACK__ HostCmd_DS_BBP_REG_ACCESS; /** HostCmd_CMD_RF_REG_ACCESS */ typedef struct _HostCmd_DS_RF_REG_ACCESS @@ -565,16 +445,14 @@ u16 Offset; u8 Value; u8 Reserved[3]; -} __ATTRIB_PACK__ HostCmd_DS_RF_REG_ACCESS, - *PHostCmd_DS_RF_REG_ACCESS; +} __ATTRIB_PACK__ HostCmd_DS_RF_REG_ACCESS; /** HostCmd_CMD_802_11_RADIO_CONTROL */ typedef struct _HostCmd_DS_802_11_RADIO_CONTROL { u16 Action; u16 Control; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RADIO_CONTROL, - *PHostCmd_DS_802_11_RADIO_CONTROL; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RADIO_CONTROL; /* HostCmd_DS_802_11_SLEEP_PARAMS */ typedef struct _HostCmd_DS_802_11_SLEEP_PARAMS @@ -599,8 +477,7 @@ /* Reserved field, should be set to zero */ u16 Reserved; -} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PARAMS, - *PHostCmd_DS_802_11_SLEEP_PARAMS; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PARAMS; /* HostCmd_DS_802_11_SLEEP_PERIOD */ typedef struct _HostCmd_DS_802_11_SLEEP_PERIOD @@ -610,9 +487,23 @@ /* Sleep Period in msec */ u16 Period; -} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PERIOD, - *PHostCmd_DS_802_11_SLEEP_PERIOD; +} __ATTRIB_PACK__ HostCmd_DS_802_11_SLEEP_PERIOD; +/* HostCmd_DS_802_11_BCA_TIMESHARE */ +typedef struct _HostCmd_DS_802_11_BCA_TIMESHARE +{ + /* ACT_GET/ACT_SET */ + u16 Action; + + /* Type: WLAN, BT */ + u16 TrafficType; + + /* 20msec - 60000msec */ + u32 TimeShareInterval; + + /* PTA arbiter time in msec */ + u32 BTTime; +} __ATTRIB_PACK__ HostCmd_DS_802_11_BCA_TIMESHARE; /* HostCmd_DS_802_11_INACTIVITY_TIMEOUT */ typedef struct _HostCmd_DS_802_11_INACTIVITY_TIMEOUT @@ -622,8 +513,7 @@ /* Inactivity timeout in msec */ u16 Timeout; -} __ATTRIB_PACK__ HostCmd_DS_802_11_INACTIVITY_TIMEOUT, - *PHostCmd_DS_802_11_INACTIVITY_TIMEOUT; +} __ATTRIB_PACK__ HostCmd_DS_802_11_INACTIVITY_TIMEOUT; /** HostCmd_CMD_802_11_RF_CHANNEL */ typedef struct _HostCmd_DS_802_11_RF_CHANNEL @@ -633,50 +523,53 @@ u16 RFType; u16 Reserved; u8 ChannelList[32]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_CHANNEL, - *PHostCmd_DS_802_11_RF_CHANNEL; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_CHANNEL; /** HostCmd_CMD_802_11_RSSI */ -typedef struct _HostCmd_DS_802_11_RSSI { +typedef struct _HostCmd_DS_802_11_RSSI +{ /* weighting factor */ u16 N; u16 Reserved_0; u16 Reserved_1; u16 Reserved_2; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI, *PHostCmd_DS_802_11_RSSI; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI; /** HostCmd_DS_802_11_RSSI_RSP */ -typedef struct _HostCmd_DS_802_11_RSSI_RSP { +typedef struct _HostCmd_DS_802_11_RSSI_RSP +{ u16 SNR; u16 NoiseFloor; u16 AvgSNR; u16 AvgNoiseFloor; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI_RSP, *PHostCmd_DS_802_11_RSSI_RSP; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RSSI_RSP; /** HostCmd_DS_802_11_MAC_ADDRESS */ -typedef struct _HostCmd_DS_802_11_MAC_ADDRESS { +typedef struct _HostCmd_DS_802_11_MAC_ADDRESS +{ u16 Action; u8 MacAdd[ETH_ALEN]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_MAC_ADDRESS, - *PHostCmd_DS_802_11_MAC_ADDRESS; +} __ATTRIB_PACK__ HostCmd_DS_802_11_MAC_ADDRESS; /** HostCmd_CMD_802_11_RF_TX_POWER */ -typedef struct _HostCmd_DS_802_11_RF_TX_POWER { +typedef struct _HostCmd_DS_802_11_RF_TX_POWER +{ u16 Action; u16 CurrentLevel; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_TX_POWER, - *PHostCmd_DS_802_11_RF_TX_POWER; + u8 MaxPower; + u8 MinPower; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_TX_POWER; /** HostCmd_CMD_802_11_RF_ANTENNA */ -typedef struct _HostCmd_DS_802_11_RF_ANTENNA { +typedef struct _HostCmd_DS_802_11_RF_ANTENNA +{ u16 Action; /* Number of antennas or 0xffff(diversity) */ u16 AntennaMode; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_ANTENNA, - *PHostCmd_DS_802_11_RF_ANTENNA; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RF_ANTENNA; /** HostCmd_CMD_802_11_PS_MODE */ typedef struct _HostCmd_DS_802_11_PS_MODE @@ -684,13 +577,14 @@ u16 Action; u16 NullPktInterval; u16 MultipleDtim; - u16 Reserved; + u16 BCNMissTimeOut; u16 LocalListenInterval; -} __ATTRIB_PACK__ HostCmd_DS_802_11_PS_MODE, - *PHostCmd_DS_802_11_PS_MODE; + u16 AdhocAwakePeriod; +} __ATTRIB_PACK__ HostCmd_DS_802_11_PS_MODE; /** PS_CMD_ConfirmSleep */ -typedef struct _PS_CMD_ConfirmSleep { +typedef struct _PS_CMD_ConfirmSleep +{ u16 Command; u16 Size; u16 SeqNum; @@ -703,22 +597,22 @@ u16 LocalListenInterval; } __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep; - -/** HostCmd_CMD_802_11_DATA_RATE */ -typedef struct _HostCmd_DS_802_11_DATA_RATE { +/** HostCmd_CMD_802_11_FW_WAKE_METHOD */ +typedef struct _HostCmd_DS_802_11_FW_WAKEUP_METHOD +{ u16 Action; - u16 Reserverd; - u8 DataRate[HOSTCMD_SUPPORTED_RATES]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_DATA_RATE, - *PHostCmd_DS_802_11_DATA_RATE; + u16 Method; +} __ATTRIB_PACK__ HostCmd_DS_802_11_FW_WAKEUP_METHOD; /** HostCmd_DS_802_11_RATE_ADAPT_RATESET */ -typedef struct _HostCmd_DS_802_11_RATE_ADAPT_RATESET { +typedef struct _HostCmd_DS_802_11_RATE_ADAPT_RATESET +{ u16 Action; - u16 EnableHwAuto; + u16 HWRateDropMode; u16 Bitmap; -} __ATTRIB_PACK__ HostCmd_DS_802_11_RATE_ADAPT_RATESET, - *PHostCmd_DS_802_11_RATE_ADAPT_RATESET; + u16 Threshold; + u16 FinalRate; +} __ATTRIB_PACK__ HostCmd_DS_802_11_RATE_ADAPT_RATESET; /** HostCmd_DS_802_11_AD_HOC_START*/ typedef struct _HostCmd_DS_802_11_AD_HOC_START @@ -729,15 +623,14 @@ u8 DTIMPeriod; IEEEtypes_SsParamSet_t SsParamSet; IEEEtypes_PhyParamSet_t PhyParamSet; - u16 ProbeDelay; + u16 Reserved1; IEEEtypes_CapInfo_t Cap; u8 DataRate[HOSTCMD_SUPPORTED_RATES]; - u8 tlv_memory_size_pad[100]; -} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_START, - *PHostCmd_DS_802_11_AD_HOC_START; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_START; /** AdHoc_BssDesc_t */ -typedef struct _AdHoc_BssDesc_t { +typedef struct _AdHoc_BssDesc_t +{ u8 BSSID[6]; u8 SSID[32]; u8 BSSType; @@ -756,59 +649,17 @@ */ } __ATTRIB_PACK__ AdHoc_BssDesc_t; - /** HostCmd_DS_802_11_AD_HOC_JOIN */ typedef struct _HostCmd_DS_802_11_AD_HOC_JOIN { AdHoc_BssDesc_t BssDescriptor; - u16 FailTimeOut; - u16 ProbeDelay; - -} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_JOIN, - *PHostCmd_DS_802_11_AD_HOC_JOIN; - -/** HostCmd_DS_802_11_ENABLE_RSN */ -typedef struct _HostCmd_DS_802_11_ENABLE_RSN { - u16 Action; - u16 Enable; -}__ATTRIB_PACK__ HostCmd_DS_802_11_ENABLE_RSN, - *PHostCmd_DS_802_11_ENABLE_RSN; - -/** HostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS */ -typedef struct _HostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS { - u16 CmdCode; - u16 Size; - u16 SeqNum; - u16 Result; - u32 NumTkipCntrs; -}__ATTRIB_PACK__ HostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS, - *PHostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS; - -/** HostCmd_DS_802_11_PAIRWISE_TSC */ -typedef struct _HostCmd_DS_802_11_PAIRWISE_TSC { - u16 CmdCode; - u16 Size; - u16 SeqNum; - u16 Result; - u16 Action; - u32 Txlv32; - u16 Txlv16; -}__ATTRIB_PACK__ HostCmd_DS_802_11_PAIRWISE_TSC, - *PHostCmd_DS_802_11_PAIRWISE_TSC; + u16 Reserved1; + u16 Reserved2; -/** HostCmd_DS_802_11_GROUP_TSC */ -typedef struct _HostCmd_DS_802_11_GROUP_TSC { - u16 CmdCode; - u16 Size; - u16 SeqNum; - u16 Result; - u16 Action; - u32 Txlv32; - u16 Txlv16; -}__ATTRIB_PACK__ HostCmd_DS_802_11_GROUP_TSC, - *PHostCmd_DS_802_11_GROUP_TSC; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AD_HOC_JOIN; -typedef union _KeyInfo_WEP_t { +typedef union _KeyInfo_WEP_t +{ u8 Reserved; /* bits 1-4: Specifies the index of key */ @@ -820,7 +671,8 @@ u8 isWepDefaultKey; } __ATTRIB_PACK__ KeyInfo_WEP_t; -typedef union _KeyInfo_TKIP_t { +typedef union _KeyInfo_TKIP_t +{ u8 Reserved; /* bit 2: Specifies that this key is @@ -836,7 +688,8 @@ u8 isMulticastKey; } __ATTRIB_PACK__ KeyInfo_TKIP_t; -typedef union _KeyInfo_AES_t { +typedef union _KeyInfo_AES_t +{ u8 Reserved; /* bit 2: Specifies that this key is @@ -853,7 +706,8 @@ } __ATTRIB_PACK__ KeyInfo_AES_t; /** KeyMaterial_TKIP_t */ -typedef struct _KeyMaterial_TKIP_t { +typedef struct _KeyMaterial_TKIP_t +{ /* TKIP encryption/decryption key */ u8 TkipKey[16]; @@ -862,18 +716,18 @@ /* TKIP RX MIC Key */ u8 TkipRxMicKey[16]; -} __ATTRIB_PACK__ KeyMaterial_TKIP_t, - *PKeyMaterial_TKIP_t; +} __ATTRIB_PACK__ KeyMaterial_TKIP_t, *PKeyMaterial_TKIP_t; /** KeyMaterial_AES_t */ -typedef struct _KeyMaterial_AES_t { +typedef struct _KeyMaterial_AES_t +{ /* AES encryption/decryption key */ u8 AesKey[16]; -} __ATTRIB_PACK__ KeyMaterial_AES_t, - *PKeyMaterial_AES_t; +} __ATTRIB_PACK__ KeyMaterial_AES_t, *PKeyMaterial_AES_t; /** MrvlIEtype_KeyParamSet_t */ -typedef struct _MrvlIEtype_KeyParamSet_t { +typedef struct _MrvlIEtype_KeyParamSet_t +{ /* Type ID */ u16 Type; @@ -891,36 +745,129 @@ /* Key material of size KeyLen */ u8 Key[32]; -} __ATTRIB_PACK__ MrvlIEtype_KeyParamSet_t, - *PMrvlIEtype_KeyParamSet_t; +} __ATTRIB_PACK__ MrvlIEtype_KeyParamSet_t, *PMrvlIEtype_KeyParamSet_t; /** HostCmd_DS_802_11_KEY_MATERIAL */ -typedef struct _HostCmd_DS_802_11_KEY_MATERIAL { +typedef struct _HostCmd_DS_802_11_KEY_MATERIAL +{ u16 Action; MrvlIEtype_KeyParamSet_t KeyParamSet; -} __ATTRIB_PACK__ HostCmd_DS_802_11_KEY_MATERIAL, - *PHostCmd_DS_802_11_KEY_MATERIAL; +} __ATTRIB_PACK__ HostCmd_DS_802_11_KEY_MATERIAL; +/** HostCmd_DS_802_11_HOST_SLEEP_CFG */ +typedef struct _HostCmd_DS_HOST_802_11_HOST_SLEEP_CFG +{ + /* bit0=1: non-unicast data + * bit1=1: unicast data + * bit2=1: mac events + * bit3=1: magic packet + */ + u32 conditions; + u8 gpio; + /* in milliseconds */ + u8 gap; +} __ATTRIB_PACK__ HostCmd_DS_802_11_HOST_SLEEP_CFG; + +#define CAL_DATA_HEADER_LEN 6 /* sizeof(HostCmd_DS_802_11_CAL_DATA_EXT)-sizeof(CalData) */ + +/** HostCmd_DS_802_11_CAL_DATA_EXT */ +typedef struct _HostCmd_DS_802_11_CAL_DATA_EXT +{ + u16 Action; + u16 Revision; + u16 CalDataLen; + u8 CalData[1]; +} __ATTRIB_PACK__ HostCmd_DS_802_11_CAL_DATA_EXT; /** HostCmd_DS_802_11_EEPROM_ACCESS */ -typedef struct _HostCmd_DS_802_11_EEPROM_ACCESS { +typedef struct _HostCmd_DS_802_11_EEPROM_ACCESS +{ u16 Action; /* multiple 4 */ u16 Offset; u16 ByteCount; u8 Value; -} __ATTRIB_PACK__ HostCmd_DS_802_11_EEPROM_ACCESS, - *pHostCmd_DS_802_11_EEPROM_ACCESS; +} __ATTRIB_PACK__ HostCmd_DS_802_11_EEPROM_ACCESS; + +/** HostCmd_DS_802_11_BG_SCAN_CONFIG */ +typedef struct _HostCmd_DS_802_11_BG_SCAN_CONFIG +{ + /** Action */ + u16 Action; + + /** + * Enable/Disable + * 0 - Disable + * 1 - Enable + */ + u8 Enable; + + /** + * bssType + * 1 - Infrastructure + * 2 - IBSS + * 3 - any + */ + u8 BssType; + + /** + * ChannelsPerScan + * Number of channels to scan during a single scanning opportunity + */ + u8 ChannelsPerScan; + u8 Reserved1[3]; + + /** ScanInterval */ + u32 ScanInterval; + + /** + * StoreCondition + * - SSID Match + * - SSID Match & Exceed SNR Threshold + */ + u32 StoreCondition; + /** + * ReportConditions + * - SSID Match + * - SSID Match & Exceed SNR Threshold + */ + u32 ReportConditions; + + u16 Reserved2; + + /* Attach TLV based parameters as needed: + * + * MrvlIEtypes_SsIdParamSet_t Set specific SSID filter + * MrvlIEtypes_ChanListParamSet_t Set the channels & channel params + * MrvlIEtypes_NumProbes_t Number of probes per SSID/broadcast + * MrvlIEtypes_WildCardSsIdParamSet_t Wildcard SSID matching patterns + * MrvlIEtypes_SnrThreshold_t SNR Threshold for match/report + */ + +} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_CONFIG; + +/** HostCmd_DS_802_11_BG_SCAN_QUERY */ +typedef struct _HostCmd_DS_802_11_BG_SCAN_QUERY +{ + u8 Flush; +} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_QUERY; +/** HostCmd_DS_802_11_BG_SCAN_QUERY_RSP */ +typedef struct _HostCmd_DS_802_11_BG_SCAN_QUERY_RSP +{ + u32 ReportCondition; + HostCmd_DS_802_11_SCAN_RSP scanresp; +} __ATTRIB_PACK__ HostCmd_DS_802_11_BG_SCAN_QUERY_RSP; /** HostCmd_DS_802_11_TPC_CFG */ -typedef struct _HostCmd_DS_802_11_TPC_CFG { +typedef struct _HostCmd_DS_802_11_TPC_CFG +{ u16 Action; u8 Enable; s8 P0; @@ -930,68 +877,113 @@ } __ATTRIB_PACK__ HostCmd_DS_802_11_TPC_CFG; /** HostCmd_DS_802_11_LED_CTRL */ -typedef struct _HostCmd_DS_802_11_LED_CTRL { - u16 Action; - u16 NumLed; - u8 data[256]; +typedef struct _HostCmd_DS_802_11_LED_CTRL +{ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + u16 LedNums; /* Numbers of LEDs supported */ + MrvlIEtypes_LedGpio_t LedGpio; + MrvlIEtypes_LedBehavior_t LedBehavior[1]; } __ATTRIB_PACK__ HostCmd_DS_802_11_LED_CTRL; -/*** HostCmd_DS_802_11_PWR_CFG */ -typedef struct _HostCmd_DS_802_11_PWR_CFG { - u16 Action; - u8 Enable; - s8 PA_P0; - s8 PA_P1; - s8 PA_P2; -} __ATTRIB_PACK__ HostCmd_DS_802_11_PWR_CFG; +/** HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT */ +typedef struct _HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT +{ + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + u16 EnablePA; /* 0 = disable; 1 = enable; */ + MrvlIEtypes_PowerAdapt_Group_t PowerAdaptGroup; +} __ATTRIB_PACK__ HostCmd_DS_802_11_POWER_ADAPT_CFG_EXT; +typedef struct _HostCmd_DS_SDIO_PULL_CTRL +{ + u16 Action; /* 0: get; 1: set */ + u16 PullUp; /* the delay of pulling up in us */ + u16 PullDown; /* the delay of pulling down in us */ +} __ATTRIB_PACK__ HostCmd_DS_SDIO_PULL_CTRL; +typedef struct _HostCmd_DS_802_11_IBSS_Status +{ + u16 Action; + u16 Enable; + u8 BSSID[ETH_ALEN]; + u16 BeaconInterval; + u16 ATIMWindow; + u16 UseGRateProtection; +} __ATTRIB_PACK__ HostCmd_DS_802_11_IBSS_Status; -/** HostCmd_DS_802_11_AFC */ -typedef struct _HostCmd_DS_802_11_AFC { - u16 afc_auto; - union { - struct { - u16 threshold; - u16 period; - } auto_mode; +typedef struct _HostCmd_TX_RATE_QUERY +{ + u16 TxRate; +} __ATTRIB_PACK__ HostCmd_TX_RATE_QUERY; - struct { - s16 timing_offset; - s16 carrier_offset; - } manual_mode; - } b; -} __ATTRIB_PACK__ HostCmd_DS_802_11_AFC; +/** HostCmd_DS_802_11_AUTO_TX */ +typedef struct _HostCmd_DS_802_11_AUTO_TX +{ + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + MrvlIEtypes_AutoTx_t AutoTx; +} __ATTRIB_PACK__ HostCmd_DS_802_11_AUTO_TX; -#define afc_data b.data -#define afc_thre b.auto_mode.threshold -#define afc_period b.auto_mode.period -#define afc_toff b.manual_mode.timing_offset -#define afc_foff b.manual_mode.carrier_offset +/** HostCmd_MEM_ACCESS */ +typedef struct _HostCmd_DS_MEM_ACCESS +{ + /** Action */ + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + u16 Reserved; + u32 Addr; + u32 Value; +} __ATTRIB_PACK__ HostCmd_DS_MEM_ACCESS; +typedef struct +{ + u64 TsfValue; +} __ATTRIB_PACK__ HostCmd_DS_GET_TSF; +#define LDO_INTERNAL 0 +#define LDO_EXTERNAL 1 -typedef struct _HostCmd_TX_RATE_QUERY +typedef struct _HostCmd_DS_802_11_LDO_CONFIG { - u16 TxRate; -} __ATTRIB_PACK__ HostCmd_TX_RATE_QUERY, *PHostCmd_TX_RATE_QUERY; + u16 Action; /* 0 = ACT_GET; 1 = ACT_SET; */ + u16 PMSource; /* 0 = LDO_INTERNAL; 1 = LDO_EXTERNAL */ +} __ATTRIB_PACK__ HostCmd_DS_802_11_LDO_CONFIG; +typedef struct _HostCmd_DS_VERSION_EXT +{ + u8 versionStrSel; + char versionStr[128]; +} __ATTRIB_PACK__ HostCmd_DS_VERSION_EXT; -typedef struct { - u64 TsfValue; -} __ATTRIB_PACK__ HostCmd_DS_GET_TSF; +/** Define data structure for HostCmd_CMD_802_11D_DOMAIN_INFO */ +typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO +{ + u16 Action; + MrvlIEtypes_DomainParamSet_t Domain; +} __ATTRIB_PACK__ HostCmd_DS_802_11D_DOMAIN_INFO; -/** HostCmd_CMD_DFT_ACCESS */ -typedef struct _HostCmd_DS_DFT_ACCESS +/** Define data structure for HostCmd_RET_802_11D_DOMAIN_INFO */ +typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO_RSP { u16 Action; - u32 id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; -} __ATTRIB_PACK__ HostCmd_DS_DFT_ACCESS, - *PHostCmd_DS_DFT_ACCESS; + MrvlIEtypes_DomainParamSet_t Domain; +} __ATTRIB_PACK__ HostCmd_DS_802_11D_DOMAIN_INFO_RSP; + +typedef struct +{ + u32 PktInitCnt; + u32 PktSuccessCnt; + u32 TxAttempts; + u32 RetryFailure; + u32 ExpiryFailure; +} __ATTRIB_PACK__ HostCmd_DS_TX_PKT_STAT_Entry; + +typedef struct +{ + HostCmd_DS_TX_PKT_STAT_Entry StatEntry[HOSTCMD_SUPPORTED_RATES]; +} __ATTRIB_PACK__ HostCmd_DS_TX_PKT_STATS; /** _HostCmd_DS_COMMAND*/ -struct _HostCmd_DS_COMMAND { +struct _HostCmd_DS_COMMAND +{ /** Command Header */ u16 Command; @@ -1000,7 +992,8 @@ u16 Result; /** Command Body */ - union { + union + { HostCmd_DS_GET_HW_SPEC hwspec; HostCmd_DS_802_11_PS_MODE psmode; HostCmd_DS_802_11_SCAN scan; @@ -1011,17 +1004,11 @@ HostCmd_DS_802_11_DEAUTHENTICATE deauth; HostCmd_DS_802_11_SET_WEP wep; HostCmd_DS_802_11_AD_HOC_START ads; - HostCmd_DS_802_11_RESET reset; HostCmd_DS_802_11_AD_HOC_RESULT result; HostCmd_DS_802_11_GET_LOG glog; - HostCmd_DS_802_11_AUTHENTICATE auth; - HostCmd_DS_802_11_AUTHENTICATE_RSP rauth; - HostCmd_DS_802_11_GET_STAT gstat; - HostCmd_DS_802_3_GET_STAT gstat_8023; HostCmd_DS_802_11_SNMP_MIB smib; HostCmd_DS_802_11_RF_TX_POWER txp; HostCmd_DS_802_11_RF_ANTENNA rant; - HostCmd_DS_802_11_DATA_RATE drate; HostCmd_DS_802_11_RATE_ADAPT_RATESET rateset; HostCmd_DS_MAC_MULTICAST_ADR madr; HostCmd_DS_802_11_AD_HOC_JOIN adj; @@ -1029,32 +1016,41 @@ HostCmd_DS_802_11_RF_CHANNEL rfchannel; HostCmd_DS_802_11_RSSI rssi; HostCmd_DS_802_11_RSSI_RSP rssirsp; - HostCmd_DS_802_11_DISASSOCIATE dassociate; HostCmd_DS_802_11_AD_HOC_STOP adhoc_stop; HostCmd_DS_802_11_MAC_ADDRESS macadd; - HostCmd_DS_802_11_ENABLE_RSN enbrsn; HostCmd_DS_802_11_KEY_MATERIAL keymaterial; HostCmd_DS_MAC_REG_ACCESS macreg; HostCmd_DS_BBP_REG_ACCESS bbpreg; HostCmd_DS_RF_REG_ACCESS rfreg; - HostCmd_DS_802_11_BEACON_STOP beacon_stop; + HostCmd_DS_802_11_CAL_DATA_EXT caldataext; + HostCmd_DS_802_11_HOST_SLEEP_CFG hostsleepcfg; HostCmd_DS_802_11_EEPROM_ACCESS rdeeprom; - HostCmd_DS_802_11D_DOMAIN_INFO domaininfo; HostCmd_DS_802_11D_DOMAIN_INFO_RSP domaininforesp; - + HostCmd_DS_802_11_BG_SCAN_CONFIG bgscancfg; + HostCmd_DS_802_11_BG_SCAN_QUERY bgscanquery; + HostCmd_DS_802_11_BG_SCAN_QUERY_RSP bgscanqueryresp; + HostCmd_DS_WMM_GET_STATUS getWmmStatus; + HostCmd_DS_WMM_ADDTS_REQ addTsReq; + HostCmd_DS_WMM_DELTS_REQ delTsReq; + HostCmd_DS_WMM_QUEUE_CONFIG queueConfig; + HostCmd_DS_WMM_QUEUE_STATS queueStats; + HostCmd_DS_TX_PKT_STATS txPktStats; HostCmd_DS_802_11_SLEEP_PARAMS sleep_params; + HostCmd_DS_802_11_BCA_TIMESHARE bca_timeshare; HostCmd_DS_802_11_INACTIVITY_TIMEOUT inactivity_timeout; HostCmd_DS_802_11_SLEEP_PERIOD ps_sleeppd; HostCmd_DS_802_11_TPC_CFG tpccfg; - HostCmd_DS_802_11_PWR_CFG pwrcfg; - HostCmd_DS_802_11_AFC afc; HostCmd_DS_802_11_LED_CTRL ledgpio; + HostCmd_DS_802_11_FW_WAKEUP_METHOD fwwakeupmethod; HostCmd_TX_RATE_QUERY txrate; - HostCmd_DS_DFT_ACCESS dft; HostCmd_DS_GET_TSF gettsf; + HostCmd_DS_802_11_IBSS_Status ibssCoalescing; + HostCmd_DS_SDIO_PULL_CTRL sdiopullctl; + HostCmd_DS_802_11_LDO_CONFIG ldocfg; + HostCmd_DS_VERSION_EXT verext; } params; } __ATTRIB_PACK__; diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/host.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/host.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/host.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/host.h 2007-11-06 12:26:40.000000000 -0500 @@ -2,14 +2,13 @@ * * @brief This file contains definitions of WLAN commands. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -27,92 +26,39 @@ 04/10/06: Add power_adapt_cfg_ext command 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 05/03/06: Add auto_tx hostcmd + 05/04/06: Add IBSS coalescing related new hostcmd and event + 08/28/06: Add LED_CTRL hostcmd ********************************************************/ #ifndef _HOST_H_ #define _HOST_H_ /** PUBLIC DEFINITIONS */ -#define DEFAULT_CHANNEL 1 -#define DEFAULT_CHANNEL_A 36 #define DEFAULT_AD_HOC_CHANNEL 6 #define DEFAULT_AD_HOC_CHANNEL_A 36 /** IEEE 802.11 OIDs */ -#define OID_802_11_BSSID 0x00008001 -#define OID_802_11_SSID 0x00008002 -#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x00008003 -#define OID_802_11_NETWORK_TYPE_IN_USE 0x00008004 -#define OID_802_11_RSSI 0x00008006 -#define OID_802_11_RSSI_TRIGGER 0x00008007 -#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008 -#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009 -#define OID_802_11_RTS_THRESHOLD 0x0000800A -#define OID_802_11_NUMBER_OF_ANTENNAS 0x0000800B -#define OID_802_11_RX_ANTENNA_SELECTED 0x0000800C -#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D -#define OID_802_11_SUPPORTED_RATES 0x0000800E -#define OID_802_11_DESIRED_RATES 0x00008010 -#define OID_802_11_CONFIGURATION 0x00008011 -#define OID_802_11_STATISTICS 0x00008012 -#define OID_802_11_ADD_WEP 0x00008013 -#define OID_802_11_REMOVE_WEP 0x00008014 -#define OID_802_11_DISASSOCIATE 0x00008015 -#define OID_802_11_POWER_MODE 0x00008016 -#define OID_802_11_BSSID_LIST 0x00008017 -#define OID_802_11_AUTHENTICATION_MODE 0x00008018 -#define OID_802_11_PRIVACY_FILTER 0x00008019 -#define OID_802_11_BSSID_LIST_SCAN 0x0000801A -#define OID_802_11_WEP_STATUS 0x0000801B -#define OID_802_11_RELOAD_DEFAULTS 0x0000801C -#define OID_802_11_TX_RETRYCOUNT 0x0000801D -#define OID_802_11D_ENABLE 0x00008020 - -/** Marvel specific OIDs */ -#define OID_MRVL_OEM_GET_ULONG 0xff010201 -#define OID_MRVL_OEM_SET_ULONG 0xff010202 -#define OID_MRVL_OEM_GET_STRING 0xff010203 -#define OID_MRVL_OEM_COMMAND 0xff010204 - -/** Command Processing States and Options */ -#define HostCmd_STATE_IDLE 0x0000 -#define HostCmd_STATE_IN_USE_BY_HOST 0x0001 -#define HostCmd_STATE_IN_USE_BY_MINIPORT 0x0002 -#define HostCmd_STATE_FINISHED 0x000f - -#define HostCmd_Q_NONE 0x0000 -#define HostCmd_Q_INIT 0x0001 -#define HostCmd_Q_RESET 0x0002 -#define HostCmd_Q_STAT 0x0003 +#define OID_802_11_INFRASTRUCTURE_MODE 0x00008001 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008002 +#define OID_802_11_RTS_THRESHOLD 0x00008003 +#define OID_802_11_ADD_WEP 0x00008004 +#define OID_802_11_REMOVE_WEP 0x00008005 +#define OID_802_11_TX_RETRYCOUNT 0x00008006 +#define OID_802_11D_ENABLE 0x00008007 #define HostCmd_OPTION_WAITFORRSP 0x0002 -/* 512 usec */ -#define HostCmd_DELAY_NORMAL 0x00000200 -/* 256 usec */ -#define HostCmd_DELAY_MIN 0x00000100 -/* 1024 usec */ -#define HostCmd_DELAY_MAX 0x00000400 - - /** Host Command ID */ -#define HostCmd_CMD_NONE 0x0000 -#define HostCmd_CMD_CODE_DNLD 0x0002 #define HostCmd_CMD_GET_HW_SPEC 0x0003 -#define HostCmd_CMD_EEPROM_UPDATE 0x0004 #define HostCmd_CMD_802_11_RESET 0x0005 #define HostCmd_CMD_802_11_SCAN 0x0006 #define HostCmd_CMD_802_11_GET_LOG 0x000b #define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010 -#define HostCmd_CMD_802_11_AUTHENTICATE 0x0011 #define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 -#define HostCmd_CMD_802_11_ASSOCIATE 0x0050 +#define HostCmd_CMD_802_11_ASSOCIATE 0x0012 #define HostCmd_CMD_802_11_SET_WEP 0x0013 -#define HostCmd_CMD_802_11_GET_STAT 0x0014 -#define HostCmd_CMD_802_3_GET_STAT 0x0015 #define HostCmd_CMD_802_11_SNMP_MIB 0x0016 -#define HostCmd_CMD_MAC_REG_MAP 0x0017 -#define HostCmd_CMD_BBP_REG_MAP 0x0018 #define HostCmd_CMD_MAC_REG_ACCESS 0x0019 #define HostCmd_CMD_BBP_REG_ACCESS 0x001a #define HostCmd_CMD_RF_REG_ACCESS 0x001b @@ -124,72 +70,80 @@ #define HostCmd_CMD_802_11_PS_MODE 0x0021 -#define HostCmd_CMD_802_11_DATA_RATE 0x0022 -#define HostCmd_CMD_RF_REG_MAP 0x0023 #define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 -#define HostCmd_CMD_802_11_REASSOCIATE 0x0025 -#define HostCmd_CMD_802_11_DISASSOCIATE 0x0026 #define HostCmd_CMD_MAC_CONTROL 0x0028 #define HostCmd_CMD_802_11_AD_HOC_START 0x002b #define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c -#define HostCmd_CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e -#define HostCmd_CMD_802_11_ENABLE_RSN 0x002f -#define HostCmd_CMD_802_11_PAIRWISE_TSC 0x0036 -#define HostCmd_CMD_802_11_GROUP_TSC 0x0037 #define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e - -#define HostCmd_CMD_802_11_SET_AFC 0x003c -#define HostCmd_CMD_802_11_GET_AFC 0x003d +#define HostCmd_CMD_802_11_DEEP_SLEEP 0x003e #define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040 - -#define HostCmd_CMD_802_11_BEACON_STOP 0x0049 +#define HostCmd_CMD_802_11_HOST_SLEEP_CFG 0x0043 +#define HostCmd_CMD_802_11_WAKEUP_CONFIRM 0x0044 +#define HostCmd_CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 #define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D #define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 - - #define HostCmd_CMD_802_11_BAND_CONFIG 0x0058 #define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b - - #define HostCmd_CMD_802_11_SLEEP_PARAMS 0x0066 #define HostCmd_CMD_802_11_INACTIVITY_TIMEOUT 0x0067 #define HostCmd_CMD_802_11_SLEEP_PERIOD 0x0068 +#define HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE 0x0069 +#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b +#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c +#define HostCmd_CMD_802_11_CAL_DATA_EXT 0x006d - +#define HostCmd_CMD_WMM_ADDTS_REQ 0x006E +#define HostCmd_CMD_WMM_DELTS_REQ 0x006F +#define HostCmd_CMD_WMM_QUEUE_CONFIG 0x0070 +#define HostCmd_CMD_WMM_GET_STATUS 0x0071 #define HostCmd_CMD_802_11_TPC_CFG 0x0072 -#define HostCmd_CMD_802_11_PWR_CFG 0x0073 +#define HostCmd_CMD_802_11_FW_WAKE_METHOD 0x0074 -#define HostCmd_CMD_802_11_LED_GPIO_CTRL 0x004e +#define HostCmd_CMD_802_11_LED_CONTROL 0x004e #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 #define HostCmd_CMD_802_11_RATE_ADAPT_RATESET 0x0076 - #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f +#define HostCmd_CMD_802_11_POWER_ADAPT_CFG_EXT 0x007e #define HostCmd_CMD_GET_TSF 0x0080 +#define HostCmd_CMD_WMM_QUEUE_STATS 0x0081 +#define HostCmd_CMD_802_11_AUTO_TX 0x0082 +#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 +#define HostCmd_CMD_MEM_ACCESS 0x0086 -#define HostCmd_CMD_DFT_ACCESS 0x0087 -#define HostCmd_RET_DFT_ACCESS 0x8087 +#ifdef MFG_CMD_SUPPORT +#define HostCmd_CMD_MFG_COMMAND 0x0089 +#define HostCmd_RET_MFG_COMMAND 0x8089 +#endif + +#define HostCmd_CMD_TX_PKT_STATS 0x008d + +#define HostCmd_CMD_SDIO_PULL_CTRL 0x0093 + +#define HostCmd_CMD_802_11_LDO_CONFIG 0x0096 + +#define HostCmd_CMD_VERSION_EXT 0x0097 /* For the IEEE Power Save */ #define HostCmd_SubCmd_Enter_PS 0x0030 @@ -199,26 +153,17 @@ #define HostCmd_SubCmd_Full_PowerUp 0x0036 /* Command RET code, MSB is set to 1 */ -#define HostCmd_RET_NONE 0x8000 #define HostCmd_RET_HW_SPEC_INFO 0x8003 -#define HostCmd_RET_EEPROM_UPDATE 0x8004 #define HostCmd_RET_802_11_RESET 0x8005 #define HostCmd_RET_802_11_SCAN 0x8006 #define HostCmd_RET_802_11_GET_LOG 0x800b #define HostCmd_RET_MAC_CONTROL 0x8028 #define HostCmd_RET_MAC_MULTICAST_ADR 0x8010 -#define HostCmd_RET_802_11_AUTHENTICATE 0x8011 #define HostCmd_RET_802_11_DEAUTHENTICATE 0x8024 #define HostCmd_RET_802_11_ASSOCIATE 0x8012 -#define HostCmd_RET_802_11_REASSOCIATE 0x8025 -#define HostCmd_RET_802_11_DISASSOCIATE 0x8026 #define HostCmd_RET_802_11_SET_WEP 0x8013 -#define HostCmd_RET_802_11_STAT 0x8014 #define HostCmd_RET_802_3_STAT 0x8015 #define HostCmd_RET_802_11_SNMP_MIB 0x8016 -#define HostCmd_RET_MAC_REG_MAP 0x8017 -#define HostCmd_RET_BBP_REG_MAP 0x8018 -#define HostCmd_RET_RF_REG_MAP 0x8023 #define HostCmd_RET_MAC_REG_ACCESS 0x8019 #define HostCmd_RET_BBP_REG_ACCESS 0x801a #define HostCmd_RET_RF_REG_ACCESS 0x801b @@ -228,42 +173,24 @@ #define HostCmd_RET_802_11_RF_TX_POWER 0x801e #define HostCmd_RET_802_11_RF_ANTENNA 0x8020 #define HostCmd_RET_802_11_PS_MODE 0x8021 -#define HostCmd_RET_802_11_DATA_RATE 0x8022 #define HostCmd_RET_802_11_AD_HOC_START 0x802B #define HostCmd_RET_802_11_AD_HOC_JOIN 0x802C -#define HostCmd_RET_802_11_QUERY_TKIP_REPLY_CNTRS 0x802e -#define HostCmd_RET_802_11_ENABLE_RSN 0x802f -#define HostCmd_RET_802_11_PAIRWISE_TSC 0x8036 -#define HostCmd_RET_802_11_GROUP_TSC 0x8037 #define HostCmd_RET_802_11_KEY_MATERIAL 0x805e -#define HostCmd_ENABLE_RSN 0x0001 -#define HostCmd_DISABLE_RSN 0x0000 -#define TYPE_ANTENNA_DIVERSITY 0xffff - #define HostCmd_ACT_SET 0x0001 #define HostCmd_ACT_GET 0x0000 -#define HostCmd_ACT_GET_AES (HostCmd_ACT_GET + 2) -#define HostCmd_ACT_SET_AES (HostCmd_ACT_SET + 2) -#define HostCmd_ACT_REMOVE_AES (HostCmd_ACT_SET + 3) - - -#define HostCmd_RET_802_11_SET_AFC 0x803c -#define HostCmd_RET_802_11_GET_AFC 0x803d - #define HostCmd_RET_802_11_AD_HOC_STOP 0x8040 - -#define HostCmd_RET_802_11_BEACON_STOP 0x8049 +#define HostCmd_RET_802_11_HOST_SLEEP_CFG 0x8043 +#define HostCmd_RET_802_11_WAKEUP_CONFIRM 0x8044 +#define HostCmd_RET_802_11_HOST_SLEEP_ACTIVATE 0x8045 #define HostCmd_RET_802_11_MAC_ADDRESS 0x804D #define HostCmd_RET_802_11_EEPROM_ACCESS 0x8059 - - #define HostCmd_RET_802_11_BAND_CONFIG 0x8058 #define HostCmd_RET_802_11_SLEEP_PARAMS 0x8066 @@ -271,31 +198,51 @@ #define HostCmd_RET_802_11_INACTIVITY_TIMEOUT 0x8067 #define HostCmd_RET_802_11_SLEEP_PERIOD 0x8068 +#define HostCmd_RET_802_11_BCA_CONFIG_TIMESHARE 0x8069 -#define HostCmd_RET_802_11D_DOMAIN_INFO (0x8000 | \ - HostCmd_CMD_802_11D_DOMAIN_INFO) +#define HostCmd_RET_802_11D_DOMAIN_INFO 0x805B +#define HostCmd_RET_802_11_BG_SCAN_CONFIG 0x806b +#define HostCmd_RET_802_11_BG_SCAN_QUERY 0x806c +#define HostCmd_RET_802_11_CAL_DATA_EXT 0x806d +#define HostCmd_RET_WMM_ADDTS_REQ 0x806E +#define HostCmd_RET_WMM_DELTS_REQ 0x806F +#define HostCmd_RET_WMM_QUEUE_CONFIG 0x8070 +#define HostCmd_RET_WMM_GET_STATUS 0x8071 +#define HostCmd_RET_802_11_TPC_CFG 0x8072 -#define HostCmd_RET_802_11_TPC_CFG (HostCmd_CMD_802_11_TPC_CFG | 0x8000) -#define HostCmd_RET_802_11_PWR_CFG (HostCmd_CMD_802_11_PWR_CFG | 0x8000) +#define HostCmd_RET_802_11_LED_CONTROL 0x804e -#define HostCmd_RET_802_11_LED_GPIO_CTRL 0x804e +#define HostCmd_RET_802_11_FW_WAKE_METHOD 0x8074 +#define HostCmd_RET_802_11_SUBSCRIBE_EVENT 0x8075 -#define HostCmd_RET_802_11_SUBSCRIBE_EVENT (HostCmd_CMD_802_11_SUBSCRIBE_EVENT | 0x8000) +#define HostCmd_RET_802_11_RATE_ADAPT_RATESET 0x8076 -#define HostCmd_RET_802_11_RATE_ADAPT_RATESET (HostCmd_CMD_802_11_RATE_ADAPT_RATESET | 0x8000) +#define HostCmd_RTE_802_11_TX_RATE_QUERY 0x807f +#define HostCmd_RET_GET_TSF 0x8080 -#define HostCmd_RTE_802_11_TX_RATE_QUERY (HostCmd_CMD_802_11_TX_RATE_QUERY | 0x8000) +#define HostCmd_RET_WMM_QUEUE_STATS 0x8081 -#define HostCmd_RET_GET_TSF 0x8080 +#define HostCmd_RET_802_11_POWER_ADAPT_CFG_EXT 0x807e + +#define HostCmd_RET_802_11_AUTO_TX 0x8082 + +#define HostCmd_RET_802_11_IBSS_COALESCING_STATUS 0x8083 +#define HostCmd_RET_MEM_ACCESS 0x8086 +#define HostCmd_RET_TX_PKT_STATS 0x808d +#define HostCmd_RET_SDIO_PULL_CTRL 0x8093 + +#define HostCmd_RET_802_11_LDO_CONFIG 0x8096 + +#define HostCmd_RET_VERSION_EXT 0x8097 /** General Result Code*/ /* OK */ @@ -322,38 +269,15 @@ #define HostCmd_ACT_GEN_OFF 0x0000 #define HostCmd_ACT_GEN_ON 0x0001 -/* Define action or option for HostCmd_CMD_802_11_AUTHENTICATE */ -#define HostCmd_ACT_AUTHENTICATE 0x0001 -#define HostCmd_ACT_DEAUTHENTICATE 0x0002 - -/* Define action or option for HostCmd_CMD_802_11_ASSOCIATE */ -#define HostCmd_ACT_ASSOCIATE 0x0001 -#define HostCmd_ACT_DISASSOCIATE 0x0002 -#define HostCmd_ACT_REASSOCIATE 0x0003 - -#define HostCmd_CAPINFO_ESS 0x0001 -#define HostCmd_CAPINFO_IBSS 0x0002 -#define HostCmd_CAPINFO_CF_POLLABLE 0x0004 -#define HostCmd_CAPINFO_CF_REQUEST 0x0008 -#define HostCmd_CAPINFO_PRIVACY 0x0010 - /* Define action or option for HostCmd_CMD_802_11_SET_WEP */ #define HostCmd_ACT_ADD 0x0002 #define HostCmd_ACT_REMOVE 0x0004 -#define HostCmd_ACT_USE_DEFAULT 0x0008 #define HostCmd_TYPE_WEP_40_BIT 0x0001 #define HostCmd_TYPE_WEP_104_BIT 0x0002 -#define HostCmd_NUM_OF_WEP_KEYS 4 - #define HostCmd_WEP_KEY_INDEX_MASK 0x3fff -/* Define action or option for HostCmd_CMD_802_11_RESET */ -#define HostCmd_ACT_NOT_REVERT_MIB 0x0001 -#define HostCmd_ACT_REVERT_MIB 0x0002 -#define HostCmd_ACT_HALT 0x0003 - /* Define action or option for HostCmd_CMD_802_11_SCAN */ #define HostCmd_BSS_TYPE_BSS 0x0001 #define HostCmd_BSS_TYPE_IBSS 0x0002 @@ -363,84 +287,32 @@ #define HostCmd_SCAN_TYPE_ACTIVE 0x0000 #define HostCmd_SCAN_TYPE_PASSIVE 0x0001 -#define HostCmd_SCAN_802_11_B_CHANNELS 11 - -#define HostCmd_SCAN_MIN_CH_TIME 6 - - -#define HostCmd_SCAN_MAX_CH_TIME 100 - +/* Radio type definitions for the channel TLV */ #define HostCmd_SCAN_RADIO_TYPE_BG 0 #define HostCmd_SCAN_RADIO_TYPE_A 1 -#define HostCmd_SCAN_PASSIVE_MAX_CH_TIME 100 - -#define HostCmd_SCAN_PROBE_DELAY_TIME 0 /* Define action or option for HostCmd_CMD_MAC_CONTROL */ #define HostCmd_ACT_MAC_RX_ON 0x0001 #define HostCmd_ACT_MAC_TX_ON 0x0002 #define HostCmd_ACT_MAC_LOOPBACK_ON 0x0004 #define HostCmd_ACT_MAC_WEP_ENABLE 0x0008 -#define HostCmd_ACT_MAC_INT_ENABLE 0x0010 -#define HostCmd_ACT_MAC_MULTICAST_ENABLE 0x0020 -#define HostCmd_ACT_MAC_BROADCAST_ENABLE 0x0040 +#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 #define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 #define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 #define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 +#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 + /* Define action or option or constant for HostCmd_CMD_MAC_MULTICAST_ADR */ #define HostCmd_SIZE_MAC_ADR 6 #define HostCmd_MAX_MCAST_ADRS 32 -/* Define action or option for HostCmd_CMD_802_11_SNMP_MIB */ -/* Boolean */ -#define HostCmd_TYPE_MIB_FLD_BOOLEAN 0x0001 -/* Integer */ -#define HostCmd_TYPE_MIB_FLD_INTEGER 0x0002 -/* Counter */ -#define HostCmd_TYPE_MIB_FLD_COUNTER 0x0003 -/* Octet string */ -#define HostCmd_TYPE_MIB_FLD_OCT_STR 0x0004 -/* String */ -#define HostCmd_TYPE_MIB_FLD_DISPLAY_STR 0x0005 -/* MAC address */ -#define HostCmd_TYPE_MIB_FLD_MAC_ADR 0x0006 -/* IP address */ -#define HostCmd_TYPE_MIB_FLD_IP_ADR 0x0007 -/* WEP */ -#define HostCmd_TYPE_MIB_FLD_WEP 0x0008 - -/* Define action or option for HostCmd_CMD_802_11_RADIO_CONTROL */ -#define HostCmd_TYPE_AUTO_PREAMBLE 0x0001 -#define HostCmd_TYPE_SHORT_PREAMBLE 0x0002 -#define HostCmd_TYPE_LONG_PREAMBLE 0x0003 - -#define TURN_ON_RF 0x01 #define RADIO_ON 0x01 #define RADIO_OFF 0x00 -#define SET_AUTO_PREAMBLE 0x05 -#define SET_SHORT_PREAMBLE 0x03 -#define SET_LONG_PREAMBLE 0x01 - /* Define action or option for CMD_802_11_RF_CHANNEL */ #define HostCmd_OPT_802_11_RF_CHANNEL_GET 0x00 #define HostCmd_OPT_802_11_RF_CHANNEL_SET 0x01 -/* Define action or option for HostCmd_CMD_802_11_RF_TX_POWER */ -#define HostCmd_ACT_TX_POWER_OPT_GET 0x0000 -#define HostCmd_ACT_TX_POWER_OPT_SET_HIGH 0x8007 -#define HostCmd_ACT_TX_POWER_OPT_SET_MID 0x8004 -#define HostCmd_ACT_TX_POWER_OPT_SET_LOW 0x8000 - -#define HostCmd_ACT_TX_POWER_INDEX_HIGH 0x0007 -#define HostCmd_ACT_TX_POWER_INDEX_MID 0x0004 -#define HostCmd_ACT_TX_POWER_INDEX_LOW 0x0000 - -/* Define action or option for HostCmd_CMD_802_11_DATA_RATE */ -#define HostCmd_ACT_SET_TX_AUTO 0x0000 -#define HostCmd_ACT_SET_TX_FIX_RATE 0x0001 -#define HostCmd_ACT_GET_TX_RATE 0x0002 - #define HostCmd_ACT_SET_RX 0x0001 #define HostCmd_ACT_SET_TX 0x0002 #define HostCmd_ACT_SET_BOTH 0x0003 @@ -448,30 +320,11 @@ #define HostCmd_ACT_GET_TX 0x0008 #define HostCmd_ACT_GET_BOTH 0x000c -/* Define action or option for HostCmd_CMD_802_11_PS_MODE */ -#define HostCmd_TYPE_CAM 0x0000 -#define HostCmd_TYPE_MAX_PSP 0x0001 -#define HostCmd_TYPE_FAST_PSP 0x0002 - -/* Define action or option for HostCmd_CMD_DFT_ACCESS */ -enum HostCmd_CMD_DFT_ACCESS_OPTS { - HostCmd_ACT_DFT_ACCESS_ADD = 1, - HostCmd_ACT_DFT_ACCESS_DEL, - HostCmd_ACT_DFT_ACCESS_LIST, - HostCmd_ACT_DFT_ACCESS_RESET, - HostCmd_ACT_BT_ACCESS_ADD, - HostCmd_ACT_BT_ACCESS_DEL, - HostCmd_ACT_BT_ACCESS_LIST, - HostCmd_ACT_BT_ACCESS_RESET -}; - /** Card Event definition */ -#define MACREG_INT_CODE_TX_PPA_FREE 0x00000000 -#define MACREG_INT_CODE_TX_DMA_DONE 0x00000001 -#define MACREG_INT_CODE_LINK_LOSE_W_SCAN 0x00000002 -#define MACREG_INT_CODE_LINK_LOSE_NO_SCAN 0x00000003 +#define MACREG_INT_CODE_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 +#define MACREG_INT_CODE_LINK_LOST_WITH_SCAN 0x00000002 +#define MACREG_INT_CODE_LINK_LOST 0x00000003 #define MACREG_INT_CODE_LINK_SENSED 0x00000004 -#define MACREG_INT_CODE_CMD_FINISHED 0x00000005 #define MACREG_INT_CODE_MIB_CHANGED 0x00000006 #define MACREG_INT_CODE_INIT_DONE 0x00000007 #define MACREG_INT_CODE_DEAUTHENTICATED 0x00000008 @@ -481,12 +334,21 @@ #define MACREG_INT_CODE_MIC_ERR_MULTICAST 0x0000000d #define MACREG_INT_CODE_MIC_ERR_UNICAST 0x0000000e #define MACREG_INT_CODE_WM_AWAKE 0x0000000f +#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 0x00000010 #define MACREG_INT_CODE_ADHOC_BCN_LOST 0x00000011 +#define MACREG_INT_CODE_HOST_SLEEP_AWAKE 0x00000012 +#define MACREG_INT_CODE_WMM_STATUS_CHANGE 0x00000017 +#define MACREG_INT_CODE_BG_SCAN_REPORT 0x00000018 #define MACREG_INT_CODE_RSSI_LOW 0x00000019 #define MACREG_INT_CODE_SNR_LOW 0x0000001a #define MACREG_INT_CODE_MAX_FAIL 0x0000001b #define MACREG_INT_CODE_RSSI_HIGH 0x0000001c #define MACREG_INT_CODE_SNR_HIGH 0x0000001d +#define MACREG_INT_CODE_IBSS_COALESCED 0x0000001e +/* Define bitmap conditions for HOST_SLEEP_CFG */ +#define HOST_SLEEP_CFG_CANCEL 0xffffffff +#define HOST_SLEEP_CFG_WAKEUP_THRU_INTERFACE 0xff +#define HOST_SLEEP_CFG_GAP_FF 0xff #endif /* _HOST_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/include.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/include.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/include.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/include.h 2007-11-06 12:26:40.000000000 -0500 @@ -2,14 +2,13 @@ * * @brief This file contains all the necessary include file. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -22,10 +21,8 @@ /******************************************************** Change log: 10/11/05: Add Doxygen format comments - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support - Monahans/Zylonite 01/11/06: Conditional include file removal/addition - 01/30/06: Add kernel 2.6 support on GSPI8xxx/Bulverde + 01/30/06: Add kernel 2.6 support ********************************************************/ @@ -33,12 +30,11 @@ #define _INCLUDE_H_ #include "os_headers.h" +#include "wlan_types.h" #include "wlan_defs.h" #include "wlan_thread.h" -#include "radiotap.h" -#include -#include "wlan_types.h" +#include "wlan_wmm.h" #include "wlan_11d.h" #include "os_timers.h" @@ -53,8 +49,8 @@ #include "os_macros.h" #include "sbi.h" +#include -#include "wlan_fw.h" #include "wlan_wext.h" #include "wlan_decl.h" #endif /* _INCLUDE_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/radiotap.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/radiotap.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/radiotap.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/radiotap.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,294 +0,0 @@ -/** - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - * - */ - -#ifndef _NET_IF_IEEE80211RADIOTAP_H_ -#define _NET_IF_IEEE80211RADIOTAP_H_ - -/* A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. - * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. - * - * I am trying to describe precisely what the application programmer - * should expect in the following, and for that reason I tell the - * units and origin of each measurement (where it applies), or else I - * use sufficiently weaselly language ("is a monotonically nondecreasing - * function of...") that I cannot set false expectations for lawyerly - * readers. - */ -#if defined(__KERNEL__) || defined(_KERNEL) -#ifndef DLT_IEEE802_11_RADIO -#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ -#endif -#endif /* defined(__KERNEL__) || defined(_KERNEL) */ - -/* XXX tcpdump/libpcap do not tolerate variable-length headers, - * yet, so we pad every radiotap header to 64 bytes. Ugh. - */ -#define IEEE80211_RADIOTAP_HDRLEN 64 - -/* The radio capture header precedes the 802.11 header. */ -struct ieee80211_radiotap_header { - u_int8_t it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - u_int8_t it_pad; - u_int16_t it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - u_int32_t it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -} __attribute__((__packed__)); - -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT u_int64_t microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x u_int16_t MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS u_int16_t see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL u_int8_t decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE u_int8_t decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY u_int16_t unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION u_int16_t unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION u_int16_t decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS u_int8_t bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA u_int8_t antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS u_int16_t bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS u_int16_t bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES u_int8_t data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES u_int8_t data - * - * Number of unicast retries a transmitted frame used. - * - */ -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13, - IEEE80211_RADIOTAP_RX_FLAGS = 14, - IEEE80211_RADIOTAP_TX_FLAGS = 15, - IEEE80211_RADIOTAP_RTS_RETRIES = 16, - IEEE80211_RADIOTAP_DATA_RETRIES = 17, - IEEE80211_RADIOTAP_EXT = 31 -}; - -#if !defined(__KERNEL__) && !defined(_KERNEL) -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ -#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ -#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ -#endif /* !defined(__KERNEL__) && !defined(_KERNEL) */ - -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ - -typedef struct -{ - u16 FrameControl; - u16 DurationID; - u8 address1[6]; - u8 address2[6]; - u8 address3[6]; - u16 SeqControl; - u8 address4[6]; - -} __ATTRIB_PACK__ IEEE80211_Hdr_t; - -typedef struct -{ - struct ieee80211_radiotap_header hdr; - u8 rate; - u8 txpower; - u8 rts_retries; - u8 data_retries; - //u8 pad[IEEE80211_RADIOTAP_HDRLEN - 12]; -} __ATTRIB_PACK__ TxRadiotapHdr_t; - -#define TX_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \ - (1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \ - (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \ - 0) - -#define IEEE80211_FC_VERSION_MASK 0x0003 -#define IEEE80211_FC_TYPE_MASK 0x000c -#define IEEE80211_FC_TYPE_MGT 0x0000 -#define IEEE80211_FC_TYPE_CTL 0x0004 -#define IEEE80211_FC_TYPE_DATA 0x0008 -#define IEEE80211_FC_SUBTYPE_MASK 0x00f0 -#define IEEE80211_FC_TOFROMDS_MASK 0x0300 -#define IEEE80211_FC_TODS_MASK 0x0100 -#define IEEE80211_FC_FROMDS_MASK 0x0200 -#define IEEE80211_FC_NODS 0x0000 -#define IEEE80211_FC_TODS 0x0100 -#define IEEE80211_FC_FROMDS 0x0200 -#define IEEE80211_FC_DSTODS 0x0300 - -typedef struct -{ - struct ieee80211_radiotap_header hdr; - u8 flags; - u8 rate; - u16 chan_freq; - u16 chan_flags; - u8 antenna; - u8 antsignal; - u16 rx_flags; - //u8 pad[IEEE80211_RADIOTAP_HDRLEN - 18]; -} __ATTRIB_PACK__ RxRadiotapHdr_t; - -#define RX_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_CHANNEL) | \ - (1 << IEEE80211_RADIOTAP_ANTENNA) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \ - (1 << IEEE80211_RADIOTAP_RX_FLAGS) | \ - 0) - -#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/sbi.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/sbi.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/sbi.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/sbi.h 2007-11-06 12:26:40.000000000 -0500 @@ -3,13 +3,12 @@ * @brief This file contains IF layer definitions. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -72,57 +71,52 @@ #define FIRMWARE_TRANSFER_NBLOCK 2 #define SBI_EVENT_CAUSE_SHIFT 3 -typedef enum _mv_sd_type{ +typedef enum _mv_sd_type +{ MVSD_DAT = 0, MVSD_CMD = 1, - MVSD_TXDONE = 2, - MVSD_EVENT + MVSD_EVENT = 3 } mv_sd_type; /** Function Prototype Declaration */ typedef wlan_private * (*wlan_notifier_fn_add)(void *dev_id); typedef int (*wlan_notifier_fn_remove)(void *dev_id); -typedef IRQ_RET_TYPE (*isr_notifier_fn_t)(s32 irq, void *dev_id, struct pt_regs *reg); +typedef IRQ_RET_TYPE(*isr_notifier_fn_t) (s32 irq, void *dev_id, + struct pt_regs * reg); typedef IRQ_RET_TYPE (*handler_fn_t)(s32 irq, void *dev_id, struct pt_regs *); /* Probe and Check if the card is present*/ int sbi_probe_card (void *card); +int *sbi_register(wlan_notifier_fn_add, wlan_notifier_fn_remove, void *); int sbi_register_dev (wlan_private *priv); int sbi_unregister_dev (wlan_private *); int sbi_disable_host_int(wlan_private *priv); int sbi_get_int_status(wlan_private *priv, u8 *); -int *sbi_register(wlan_notifier_fn_add,wlan_notifier_fn_remove,void *); void sbi_unregister(void); int sbi_prog_firmware(wlan_private *); int sbi_verify_fw_download(wlan_private *); +int sbi_prog_helper(wlan_private *); +int sbi_prog_firmware_w_helper(wlan_private *); int sbi_read_event_cause(wlan_private *); -int sbi_reenable_host_interrupt(wlan_private *, u8); int sbi_host_to_card(wlan_private *priv, u8 type, u8 *payload, u16 nb); int sbi_card_to_host(wlan_private *priv, u32 type, u32 *nb, u8 *payload, u16 npayload); int sbi_enable_host_int(wlan_private *); +int sbi_exit_deep_sleep(wlan_private *); +int sbi_reset_deepsleep_wakeup(wlan_private *); #ifdef ENABLE_PM -inline int sbi_suspend(wlan_private *); -inline int sbi_resume(wlan_private *); +int sbi_suspend(wlan_private *); +int sbi_resume(wlan_private *); #endif +int sbi_read_ioreg(wlan_private * priv, u8 func, u32 reg, u8 * dat); +int sbi_write_ioreg(wlan_private * priv, u8 func, u32 reg, u8 dat); +int sbi_set_bus_clock(wlan_private * priv, u8 option); int sbi_get_cis_info(wlan_private *priv); -static inline u32 get_utimeofday(void) -{ - struct timeval t; - u32 ut; - - do_gettimeofday(&t); - ut = (u32)t.tv_sec * 1000000 + ((u32)t.tv_usec); - return ut; -} - - #endif /* _SBI_H */ - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_11d.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_11d.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_11d.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_11d.c 2007-11-06 12:26:40.000000000 -0500 @@ -2,13 +2,12 @@ * @brief This file contains functions for 802.11D. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -30,10 +29,9 @@ ********************************************************/ #define TX_PWR_DEFAULT 10 -static region_code_mapping_t region_code_mapping[] = -{ +static region_code_mapping_t region_code_mapping[] = { { "US ", 0x10 }, /* US FCC */ - { "CA ", 0x10 }, /* IC Canada */ + {"CA ", 0x20}, /* IC Canada */ { "SG ", 0x10 }, /* Singapore */ { "EU ", 0x30 }, /* ETSI */ { "AU ", 0x30 }, /* Australia */ @@ -41,6 +39,7 @@ { "ES ", 0x31 }, /* Spain */ { "FR ", 0x32 }, /* France */ { "JP ", 0x40 }, /* Japan */ + {"JP ", 0x41}, /* Japan */ }; /******************************************************** @@ -106,7 +105,6 @@ extern CHANNEL_FREQ_POWER *wlan_get_region_cfp_table( u8 region, u8 band, int * cfp_no); - /******************************************************** Local Functions ********************************************************/ @@ -115,17 +113,17 @@ * @param region region string * @return region id */ -static u8 wlan_region_2_code( s8 *region ) +static u8 +wlan_region_2_code(s8 * region) { u8 i; u8 size = sizeof(region_code_mapping)/sizeof(region_code_mapping_t); - for ( i=0; region[i] && i< COUNTRY_CODE_LEN; i++ ) + for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++) region[i] = toupper( region[i] ); for (i=0; ichanPwr; u8 NoOfChan = parsed_region_chan->NoOfChan; @@ -232,14 +231,14 @@ * @param band band * @return channel frequency */ -u32 chan_2_freq ( u8 chan, u8 band ) +u32 +chan_2_freq(u8 chan, u8 band) { CHANNEL_FREQ_POWER *cf; u16 cnt; u16 i; u32 freq = 0; - ENTER(); { @@ -262,8 +261,8 @@ * @param domaininfo pointer to wlan_802_11d_domain_reg_t * @return WLAN_STATUS_SUCCESS */ -int wlan_generate_domain_info_11d( - parsed_region_chan_11d_t * parsed_region_chan, +int +wlan_generate_domain_info_11d(parsed_region_chan_11d_t * parsed_region_chan, wlan_802_11d_domain_reg_t *domaininfo) { u8 NoOfSubband =0; @@ -275,13 +274,11 @@ u8 i, flag =0; - ENTER(); memcpy( domaininfo->CountryCode, parsed_region_chan->CountryCode, COUNTRY_CODE_LEN); - PRINTM(INFO, "11D:NoOfChan=%d\n",NoOfChan ); HEXDUMP( "11D:parsed_region_chan:", (char *)parsed_region_chan, sizeof(parsed_region_chan_11d_t) ); @@ -299,12 +296,12 @@ parsed_region_chan->chanPwr[i].pwr == maxPwr ) { nextChan++; NoOfParsedChan++; - } - else { + } else { domaininfo->Subband[NoOfSubband].FirstChan = firstChan; domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan; domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr; NoOfSubband++; + NoOfParsedChan = 1; nextChan = firstChan = parsed_region_chan->chanPwr[i].chan; maxPwr = parsed_region_chan->chanPwr[i].pwr; } @@ -332,9 +329,10 @@ * @param *parsed_region_chan pointer to parsed_region_chan_11d_t * @return N/A */ -void wlan_generate_parsed_region_chan_11d( - REGION_CHANNEL *region_chan, - parsed_region_chan_11d_t *parsed_region_chan ) +void +wlan_generate_parsed_region_chan_11d(REGION_CHANNEL * region_chan, + parsed_region_chan_11d_t * + parsed_region_chan) { u8 i; CHANNEL_FREQ_POWER *cfp; @@ -355,8 +353,7 @@ parsed_region_chan->band = region_chan->Band; parsed_region_chan->region = region_chan->Region; memcpy( parsed_region_chan->CountryCode, - wlan_code_2_region(region_chan->Region), - COUNTRY_CODE_LEN); + wlan_code_2_region(region_chan->Region), COUNTRY_CODE_LEN); PRINTM(INFO, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region, parsed_region_chan->band ); @@ -364,7 +361,8 @@ for( i=0; i< region_chan->NrCFP; i++, cfp++ ) { parsed_region_chan->chanPwr[i].chan = cfp->Channel; parsed_region_chan->chanPwr[i].pwr = cfp->MaxTxPower; - PRINTM(INFO, "11D: Chan[%d] Pwr[%d]\n", parsed_region_chan->chanPwr[i].chan, + PRINTM(INFO, "11D: Chan[%d] Pwr[%d]\n", + parsed_region_chan->chanPwr[i].chan, parsed_region_chan->chanPwr[i].pwr ); } parsed_region_chan->NoOfChan = region_chan->NrCFP; @@ -382,7 +380,8 @@ * @param chan chan * @return TRUE;FALSE */ -BOOLEAN wlan_region_chan_supported_11d( u8 region, u8 band, u8 chan ) +BOOLEAN +wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan) { CHANNEL_FREQ_POWER *cfp; int cfp_no; @@ -399,8 +398,7 @@ /* If Mrvl Chip Supported? */ if( (cfp+idx)->Unsupported ) { return FALSE; - } - else { + } else { return TRUE; } } @@ -417,14 +415,14 @@ * @param parsed_region_chan pointer to parsed_region_chan_11d_t * @return WLAN_STATUS_SUCCESS */ -int wlan_parse_domain_info_11d( - IEEEtypes_CountryInfoFullSet_t *CountryInfo, u8 band, +int +wlan_parse_domain_info_11d(IEEEtypes_CountryInfoFullSet_t * CountryInfo, + u8 band, parsed_region_chan_11d_t * parsed_region_chan ) { u8 NoOfSubband, NoOfChan; - u8 lastChan, firstChan; + u8 lastChan, firstChan, curChan; u8 region; - u8 curChan = 0; u8 idx =0; /*chan index in parsed_region_chan*/ @@ -443,18 +441,20 @@ HEXDUMP("CountryInfo:", (s8 *)CountryInfo, 30 ); - if( (*(CountryInfo->CountryCode))==0 || (CountryInfo->Len <= COUNTRY_CODE_LEN ) ){ + if ((*(CountryInfo->CountryCode)) == 0 || + (CountryInfo->Len <= COUNTRY_CODE_LEN)) { /* No region Info or Wrong region info: treat as No 11D info*/ LEAVE(); - return WLAN_STATUS_SUCCESS; + return WLAN_STATUS_FAILURE; } /*Step1: check region_code*/ parsed_region_chan->region = region = - wlan_region_2_code(CountryInfo->CountryCode); + wlan_region_2_code((s8 *) CountryInfo->CountryCode); PRINTM(INFO, "regioncode=%x\n",(u8)parsed_region_chan->region); - HEXDUMP("CountryCode:", (char *)CountryInfo->CountryCode, COUNTRY_CODE_LEN); + HEXDUMP("CountryCode:", (char *) CountryInfo->CountryCode, + COUNTRY_CODE_LEN); parsed_region_chan->band = band; @@ -464,7 +464,6 @@ NoOfSubband = (CountryInfo->Len - COUNTRY_CODE_LEN)/ sizeof(IEEEtypes_SubbandSet_t); - for ( j=0, lastChan=0; jSubband[j].FirstChan <= lastChan ) { @@ -489,19 +488,12 @@ lastChan = curChan; - if ( wlan_region_chan_supported_11d( region, band, curChan) ) { - /*step5: Check if curChan is supported by mrvl in region*/ + /*step5: We don't need to Check if curChan is supported by mrvl in region */ parsed_region_chan->chanPwr[idx].chan = curChan; parsed_region_chan->chanPwr[idx].pwr = CountryInfo->Subband[j].MaxTxPwr; idx++; } - else { - /*not supported and ignore the chan*/ - PRINTM(INFO, "11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n", - i, curChan, region, band ); - } - } /*Step6: Add other checking if any*/ @@ -511,8 +503,7 @@ PRINTM(INFO, "NoOfChan=%x\n", parsed_region_chan->NoOfChan ); HEXDUMP( "11D:parsed_region_chan:", (s8 *)parsed_region_chan, - 2 + COUNTRY_CODE_LEN + - sizeof(parsed_region_chan_11d_t)*idx ); + 2 + COUNTRY_CODE_LEN + sizeof(parsed_region_chan_11d_t) * idx); LEAVE(); return WLAN_STATUS_SUCCESS; @@ -524,8 +515,8 @@ * @param parsed_region_chan pointer to parsed_region_chan_11d_t * @return PASSIVE if chan is unknown; ACTIVE if chan is known */ -u8 wlan_get_scan_type_11d( u8 chan, - parsed_region_chan_11d_t *parsed_region_chan) +u8 +wlan_get_scan_type_11d(u8 chan, parsed_region_chan_11d_t * parsed_region_chan) { u8 scan_type = HostCmd_SCAN_TYPE_PASSIVE; @@ -534,8 +525,7 @@ if ( wlan_channel_known_11d( chan, parsed_region_chan) ) { PRINTM(INFO, "11D: Found and do Active Scan\n"); scan_type = HostCmd_SCAN_TYPE_ACTIVE; - } - else { + } else { PRINTM(INFO, "11D: Not Find and do Passive Scan\n"); } @@ -549,7 +539,8 @@ * @param priv pointer to wlan_private * @return ENABLE_11D;DISABLE_11D */ -state_11d_t wlan_get_state_11d( wlan_private *priv ) +state_11d_t +wlan_get_state_11d(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; wlan_802_11d_state_t *state = &Adapter->State11D; @@ -561,7 +552,8 @@ * @param priv pointer to wlan_private * @return N/A */ -void wlan_init_11d( wlan_private *priv) +void +wlan_init_11d(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; wlan_802_11d_state_t *state = &Adapter->State11D; @@ -580,28 +572,16 @@ * @param flag enable/disable flag * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE */ -int wlan_enable_11d( wlan_private * priv, state_11d_t flag ) +int +wlan_enable_11d(wlan_private * priv, state_11d_t flag) { wlan_adapter *Adapter = priv->adapter; wlan_802_11d_state_t *state = &Adapter->State11D; - int ret; - state_11d_t enable = flag; ENTER(); state->Enable11D = flag; - /* send cmd to FW to enable/disable 11D fucntion in FW */ - ret = PrepareAndSendCommand(priv, - HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_SET, - HostCmd_OPTION_WAITFORRSP, - OID_802_11D_ENABLE, - &enable ); - if (ret) { - PRINTM(INFO, "11D: Fail to enable 11D \n"); - } - LEAVE(); return WLAN_STATUS_SUCCESS; } @@ -611,19 +591,14 @@ * @param priv pointer to wlan_private * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE */ -int wlan_set_domain_info_11d( wlan_private * priv ) +int +wlan_set_domain_info_11d(wlan_private * priv) { int ret; - if( !wlan_get_state_11d( priv) ) { - PRINTM(INFO, "11D: dnld domain Info with 11d disabled\n"); - return WLAN_STATUS_SUCCESS; - } - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, HostCmd_ACT_GEN_SET, - HostCmd_OPTION_WAITFORRSP, - 0, NULL); + HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { PRINTM(INFO, "11D: Fail to dnld domain Info\n"); } @@ -638,7 +613,8 @@ * @param band band * @return WLAN_STATUS_SUCCESS */ -int wlan_set_universaltable(wlan_private *priv, u8 band) +int +wlan_set_universaltable(wlan_private * priv, u8 band) { wlan_adapter *Adapter = priv->adapter; u16 size = sizeof(CHANNEL_FREQ_POWER); @@ -654,20 +630,17 @@ PRINTM(INFO, "11D: BG-band NrCFP=%d\n", Adapter->universal_channel[i].NrCFP ); - Adapter->universal_channel[i].CFP = - channel_freq_power_UN_BG; + Adapter->universal_channel[i].CFP = channel_freq_power_UN_BG; Adapter->universal_channel[i].Valid = TRUE; Adapter->universal_channel[i].Region = UNIVERSAL_REGION_CODE; Adapter->universal_channel[i].Band = band; i++; } - LEAVE(); return WLAN_STATUS_SUCCESS; } - /** * @brief This function implements command CMD_802_11D_DOMAIN_INFO * @param priv pointer to wlan_private @@ -676,9 +649,10 @@ * @param CmdOption cmd action * @return WLAN_STATUS_SUCCESS */ -int wlan_cmd_802_11d_domain_info(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, u16 cmdno, u16 CmdOption) - +int +wlan_cmd_802_11d_domain_info(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmdno, + u16 CmdOption) { HostCmd_DS_802_11D_DOMAIN_INFO *pDomainInfo = &cmd->params.domaininfo; MrvlIEtypes_DomainParamSet_t *domain = &pDomainInfo->Domain; @@ -713,8 +687,7 @@ cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action)+ domain->Header.Len + sizeof(MrvlIEtypesHeader_t) + S_DS_GEN); - } - else { + } else { cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action) + S_DS_GEN); } @@ -725,14 +698,14 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief This function implements private cmd: enable/disable 11D * @param priv pointer to wlan_private * @param wrq pointer to user data * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_enable_11d( wlan_private *priv, struct iwreq *wrq ) +int +wlan_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq) { int data = 0; int *val; @@ -742,7 +715,8 @@ data = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - PRINTM(INFO, "Enable 11D: %s\n", (data== CMD_ENABLED)?"Enable":"Disable"); + PRINTM(INFO, "Enable 11D: %s\n", + (data == CMD_ENABLED) ? "Enable" : "Disable"); switch ( data ) { case CMD_ENABLED: wlan_enable_11d(priv, ENABLE_11D ); @@ -754,7 +728,9 @@ break; } - data = (Adapter->State11D.Enable11D==ENABLE_11D)?CMD_ENABLED:CMD_DISABLED; + data = + (Adapter->State11D.Enable11D == + ENABLE_11D) ? CMD_ENABLED : CMD_DISABLED; val = (int *)wrq->u.name; *val = data; @@ -762,30 +738,29 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief This function parses countryinfo from AP and download country info to FW * @param priv pointer to wlan_private * @param resp pointer to command response buffer * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE */ -int wlan_ret_802_11d_domain_info(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +int +wlan_ret_802_11d_domain_info(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11D_DOMAIN_INFO_RSP *domaininfo = &resp->params.domaininforesp; - MrvlIEtypes_DomainParamSet_t - *domain = &domaininfo->Domain; + MrvlIEtypes_DomainParamSet_t * domain = &domaininfo->Domain; u16 Action = wlan_le16_to_cpu(domaininfo->Action); s16 ret= WLAN_STATUS_SUCCESS; u8 NoOfSubband = 0; ENTER(); - HEXDUMP( "11D DOMAIN Info Rsp Data:", (u8 *)resp, - (int)wlan_le16_to_cpu(resp->Size) ); + HEXDUMP("11D DOMAIN Info Rsp Data:", (u8 *) resp, resp->Size); - NoOfSubband = ( domain->Header.Len - 3 ) / sizeof(IEEEtypes_SubbandSet_t); + NoOfSubband = + (wlan_le16_to_cpu(domain->Header.Len) - + 3) / sizeof(IEEEtypes_SubbandSet_t); /* countrycode 3 bytes */ PRINTM(INFO, "11D Domain Info Resp: NoOfSubband=%d\n", NoOfSubband); @@ -811,40 +786,43 @@ return ret; } - /** * @brief This function parses countryinfo from AP and download country info to FW * @param priv pointer to wlan_private * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE */ -int wlan_parse_dnld_countryinfo_11d( wlan_private *priv ) +int +wlan_parse_dnld_countryinfo_11d(wlan_private * priv) { int ret; wlan_adapter * Adapter = priv->adapter; ENTER(); + + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + /* Skip new 11d download when roaming */ + return WLAN_STATUS_SUCCESS; + } + if( wlan_get_state_11d( priv) == ENABLE_11D ) { - memset( &Adapter->parsed_region_chan, 0, sizeof(parsed_region_chan_11d_t) ); + memset(&Adapter->parsed_region_chan, 0, + sizeof(parsed_region_chan_11d_t)); - ret = wlan_parse_domain_info_11d( - &Adapter->pAttemptedBSSDesc->CountryInfo, - 0, - &Adapter->parsed_region_chan - ); + ret = + wlan_parse_domain_info_11d(&Adapter->pAttemptedBSSDesc-> + CountryInfo, 0, + &Adapter->parsed_region_chan); if( ret == WLAN_STATUS_FAILURE ) { - PRINTM(INFO, "11D: Err Parse domain_info from AP..\n"); + PRINTM(INFO, "11D: No region info in the AP BssDesc..\n"); LEAVE(); - return ret; + return WLAN_STATUS_SUCCESS; } - memset( &Adapter->DomainReg,0, sizeof(wlan_802_11d_domain_reg_t) ); - wlan_generate_domain_info_11d( - &Adapter->parsed_region_chan, - &Adapter->DomainReg - ); + wlan_generate_domain_info_11d(&Adapter->parsed_region_chan, + &Adapter->DomainReg); ret = wlan_set_domain_info_11d( priv ); @@ -863,7 +841,8 @@ * @param priv pointer to wlan_private * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE */ -int wlan_create_dnld_countryinfo_11d( wlan_private *priv ) +int +wlan_create_dnld_countryinfo_11d(wlan_private * priv, u8 band) { int ret; wlan_adapter * Adapter = priv->adapter; @@ -871,43 +850,38 @@ u8 j; ENTER(); - PRINTM(INFO, "11D:CurBssParams.Band[%d]\n", Adapter->CurBssParams.band); + PRINTM(INFO, "11D:Band[%d]\n", band); - if( wlan_get_state_11d(priv) == ENABLE_11D ) { /* update parsed_region_chan_11; dnld domaininf to FW */ for (j = 0; j < sizeof(Adapter->region_channel) / sizeof(Adapter->region_channel[0]); j++ ) { region_chan = &Adapter->region_channel[j]; - PRINTM(INFO, "11D:[%d] region_chan->Band[%d]\n",j, region_chan->Band); + PRINTM(INFO, "11D:[%d] region_chan->Band[%d]\n", j, + region_chan->Band); if(!region_chan || !region_chan->Valid || !region_chan->CFP) continue; - if (region_chan->Band != Adapter->CurBssParams.band ) + if (region_chan->Band != band) continue; break; } if (j >= sizeof(Adapter->region_channel)/ sizeof(Adapter->region_channel[0]) ) { - PRINTM(INFO, "11D:region_chan not found. Band[%d]\n", - Adapter->CurBssParams.band); + PRINTM(INFO, "11D:region_chan not found. Band[%d]\n", band); LEAVE(); return WLAN_STATUS_FAILURE; } memset( &Adapter->parsed_region_chan, 0, sizeof(parsed_region_chan_11d_t) ); - wlan_generate_parsed_region_chan_11d( - region_chan, - &Adapter->parsed_region_chan - ); + wlan_generate_parsed_region_chan_11d(region_chan, + &Adapter->parsed_region_chan); memset( &Adapter->DomainReg,0, sizeof(wlan_802_11d_domain_reg_t) ); - wlan_generate_domain_info_11d( - &Adapter->parsed_region_chan, - &Adapter->DomainReg - ); + wlan_generate_domain_info_11d(&Adapter->parsed_region_chan, + &Adapter->DomainReg); ret = wlan_set_domain_info_11d( priv ); @@ -917,11 +891,6 @@ return ret; } - } - LEAVE(); return WLAN_STATUS_SUCCESS; } - - - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_11d.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_11d.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_11d.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_11d.h 2007-11-06 12:26:40.000000000 -0500 @@ -3,13 +3,12 @@ * function declarations of 802.11d * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -33,62 +32,16 @@ /** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) */ -#define MRVDRV_MAX_SUBBAND_802_11D 83 - -#define COUNTRY_CODE_LEN 3 #define MAX_NO_OF_CHAN 40 typedef struct _REGION_CHANNEL *PREGION_CHANNEL; -typedef enum { +typedef enum +{ DISABLE_11D = 0, ENABLE_11D = 1, } state_11d_t; -/** Data structure for Country IE*/ -typedef struct _IEEEtypes_SubbandSet { - u8 FirstChan; - u8 NoOfChan; - u8 MaxTxPwr; -} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t; - -typedef struct _IEEEtypes_CountryInfoSet { - u8 ElementId; - u8 Len; - u8 CountryCode[COUNTRY_CODE_LEN]; - IEEEtypes_SubbandSet_t Subband[1]; -} __ATTRIB_PACK__ IEEEtypes_CountryInfoSet_t; - -typedef struct _IEEEtypes_CountryInfoFullSet { - u8 ElementId; - u8 Len; - u8 CountryCode[COUNTRY_CODE_LEN]; - IEEEtypes_SubbandSet_t Subband[MRVDRV_MAX_SUBBAND_802_11D]; -} __ATTRIB_PACK__ IEEEtypes_CountryInfoFullSet_t; - - -typedef struct _MrvlIEtypes_DomainParamSet { - MrvlIEtypesHeader_t Header; - u8 CountryCode[COUNTRY_CODE_LEN]; - IEEEtypes_SubbandSet_t Subband[1]; -} __ATTRIB_PACK__ MrvlIEtypes_DomainParamSet_t; - - - -/** Define data structure for HostCmd_CMD_802_11D_DOMAIN_INFO */ -typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO { - u16 Action; - MrvlIEtypes_DomainParamSet_t Domain; -} __ATTRIB_PACK__ HostCmd_DS_802_11D_DOMAIN_INFO, - *PHostCmd_DS_802_11D_DOMAIN_INFO; - -/** Define data structure for HostCmd_RET_802_11D_DOMAIN_INFO */ -typedef struct _HostCmd_DS_802_11D_DOMAIN_INFO_RSP { - u16 Action; - MrvlIEtypes_DomainParamSet_t Domain; -} __ATTRIB_PACK__ HostCmd_DS_802_11D_DOMAIN_INFO_RSP, - *PHostCmd_DS_802_11D_DOMIAN_INFO_RSP; - /** domain regulatory information */ typedef struct _wlan_802_11d_domain_reg { @@ -99,13 +52,14 @@ IEEEtypes_SubbandSet_t Subband[MRVDRV_MAX_SUBBAND_802_11D]; } wlan_802_11d_domain_reg_t; - -typedef struct _chan_power_11d { +typedef struct _chan_power_11d +{ u8 chan; u8 pwr; } __ATTRIB_PACK__ chan_power_11d_t; -typedef struct _parsed_region_chan_11d { +typedef struct _parsed_region_chan_11d +{ u8 band; u8 region; s8 CountryCode[COUNTRY_CODE_LEN]; @@ -114,24 +68,25 @@ } __ATTRIB_PACK__ parsed_region_chan_11d_t; /** Data for state machine */ -typedef struct _wlan_802_11d_state { +typedef struct _wlan_802_11d_state +{ /** True for Enabling 11D*/ BOOLEAN Enable11D; } wlan_802_11d_state_t; - -typedef struct _region_code_mapping{ +typedef struct _region_code_mapping +{ s8 region[COUNTRY_CODE_LEN]; u8 code; } region_code_mapping_t; /* function prototypes*/ -int wlan_generate_domain_info_11d( - parsed_region_chan_11d_t * parsed_region_chan, +int wlan_generate_domain_info_11d(parsed_region_chan_11d_t * + parsed_region_chan, wlan_802_11d_domain_reg_t *domaininfo); -int wlan_parse_domain_info_11d( - IEEEtypes_CountryInfoFullSet_t *CountryInfo, u8 band, +int wlan_parse_domain_info_11d(IEEEtypes_CountryInfoFullSet_t * CountryInfo, + u8 band, parsed_region_chan_11d_t * parsed_region_chan ); u8 wlan_get_scan_type_11d( u8 chan, @@ -149,13 +104,13 @@ int wlan_set_universaltable(wlan_private *priv, u8 band); -void wlan_generate_parsed_region_chan_11d( - PREGION_CHANNEL region_chan, - parsed_region_chan_11d_t *parsed_region_chan ); - +void wlan_generate_parsed_region_chan_11d(PREGION_CHANNEL region_chan, + parsed_region_chan_11d_t * + parsed_region_chan); int wlan_cmd_802_11d_domain_info(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, u16 cmdno, u16 CmdOption); + HostCmd_DS_COMMAND * cmd, u16 cmdno, + u16 CmdOption); int wlan_cmd_enable_11d( wlan_private *priv, struct iwreq *wrq ); @@ -164,7 +119,6 @@ int wlan_parse_dnld_countryinfo_11d( wlan_private *priv ); -int wlan_create_dnld_countryinfo_11d( wlan_private *priv ); +int wlan_create_dnld_countryinfo_11d(wlan_private * priv, u8 band); #endif /* _WLAN_11D_ */ - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_cmd.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_cmd.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_cmd.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_cmd.c 2007-11-06 12:26:40.000000000 -0500 @@ -4,14 +4,13 @@ * it prepares command and sends it to firmware when * it is ready. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -25,14 +24,14 @@ Change log: 10/04/05: Add Doxygen format comments 01/05/06: Add kernel 2.6.x support - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support - Monahans/Zylonite 01/11/06: Conditionalize new scan/join structures 01/31/06: Add support to selectively enabe the FW Scan channel filter 02/16/06: Clear scan in progress flag when scan command failed and dropped 04/06/06: Add TSPEC, queue metrics, and MSDU expiry support 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 05/04/06: Add IBSS coalescing related new hostcmd handling + 08/29/06: Add ledgpio private command ********************************************************/ #include "include.h" @@ -43,6 +42,8 @@ static u16 Commands_Allowed_In_PS[] = { HostCmd_CMD_802_11_RSSI, + HostCmd_CMD_802_11_HOST_SLEEP_CFG, + HostCmd_CMD_802_11_WAKEUP_CONFIRM, }; /******************************************************** @@ -60,7 +61,8 @@ * @param Command the command ID * @return TRUE or FALSE */ -static BOOLEAN Is_Command_Allowed_In_PS(u16 Command) +static BOOLEAN +Is_Command_Allowed_In_PS(u16 Command) { int count = sizeof(Commands_Allowed_In_PS) / sizeof(Commands_Allowed_In_PS[0]); @@ -81,8 +83,8 @@ * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_hw_spec(wlan_private * priv, - HostCmd_DS_COMMAND * cmd) +static int +wlan_cmd_hw_spec(wlan_private * priv, HostCmd_DS_COMMAND * cmd) { HostCmd_DS_GET_HW_SPEC *hwspec = &cmd->params.hwspec; @@ -104,9 +106,9 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_ps_mode(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u16 cmd_action) +static int +wlan_cmd_802_11_ps_mode(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmd_action) { HostCmd_DS_802_11_PS_MODE *psm = &cmd->params.psmode; u16 Action = cmd_action; @@ -115,7 +117,8 @@ ENTER(); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PS_MODE) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PS_MODE) + S_DS_GEN); psm->Action = wlan_cpu_to_le16(cmd_action); psm->MultipleDtim = 0; switch (Action) { @@ -126,9 +129,12 @@ psm->LocalListenInterval = wlan_cpu_to_le16(Adapter->LocalListenInterval); - psm->NullPktInterval = - wlan_cpu_to_le16(Adapter->NullPktInterval); + psm->NullPktInterval = wlan_cpu_to_le16(Adapter->NullPktInterval); psm->MultipleDtim = wlan_cpu_to_le16(priv->adapter->MultipleDtim); + psm->BCNMissTimeOut = wlan_cpu_to_le16(priv->adapter->BCNMissTimeOut); + if (priv->adapter->InfrastructureMode == Wlan802_11IBSS) + psm->AdhocAwakePeriod = + wlan_cpu_to_le16(priv->adapter->AdhocAwakePeriod); break; case HostCmd_SubCmd_Exit_PS: @@ -147,7 +153,154 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief This function prepares command of fw_wakeup_method. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action the action: GET or SET + * @param pdata_buf A pointer to data buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_cmd_802_11_fw_wakeup_method(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, + int cmd_action, void *pdata_buf) +{ + HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &cmd->params.fwwakeupmethod; + u16 action = (u16) cmd_action; + u16 method = *((u16 *) pdata_buf); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_FW_WAKE_METHOD); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_FW_WAKEUP_METHOD) + + S_DS_GEN); + fwwm->Action = wlan_cpu_to_le16(action); + switch (action) { + case HostCmd_ACT_SET: + fwwm->Method = wlan_cpu_to_le16(method); + break; + case HostCmd_ACT_GET: + default: + fwwm->Method = 0; + break; + } + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function sends the HS_Activated event to the application + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +wlan_host_sleep_activated_event(wlan_private * priv) +{ + ENTER(); + + priv->adapter->HS_Activated = TRUE; + os_carrier_off(priv); + os_stop_queue(priv); + wmm_stop_queue(priv); + +#if WIRELESS_EXT > 14 + send_iwevcustom_event(priv, CUS_EVT_HS_ACTIVATED); +#endif /* WIRELESS_EXT */ + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function sends the HS_DeActivated event to the application + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +wlan_host_sleep_deactivated_event(wlan_private * priv) +{ + ENTER(); + + priv->adapter->HS_Activated = FALSE; + +#if WIRELESS_EXT > 14 + send_iwevcustom_event(priv, CUS_EVT_HS_DEACTIVATED); +#endif /* WIRELESS_EXT */ + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function sends the HS_GPIO_INT event to the application + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_host_sleep_gpio_int_event(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (Adapter->bHostSleepConfigured) { +#if WIRELESS_EXT > 14 + send_iwevcustom_event(priv, CUS_EVT_HS_GPIO_INT); +#endif /* WIRELESS_EXT */ + } else { + PRINTM(INFO, "hs_gpio_int: HS not configured !!!\n"); + } + + LEAVE(); + + return ret; +} + +/** + * @brief This function prepares command of host_sleep_cfg. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param pdata_buf A pointer to HostCmd_DS_802_11_HOST_SLEEP_CFG structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_cmd_802_11_host_sleep_cfg(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, + HostCmd_DS_802_11_HOST_SLEEP_CFG * pdata_buf) +{ + HostCmd_DS_802_11_HOST_SLEEP_CFG *phwuc = &cmd->params.hostsleepcfg; + + ENTER(); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_HOST_SLEEP_CFG); + if ((pdata_buf->conditions != HOST_SLEEP_CFG_CANCEL) + && ((priv->adapter->ArpFilterSize > 0) + && (priv->adapter->ArpFilterSize <= ARP_FILTER_MAX_BUF_SIZE))) { + PRINTM(INFO, "Attach %d bytes ArpFilter to HSCfg cmd\n", + priv->adapter->ArpFilterSize); + memcpy(((u8 *) phwuc) + sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG), + priv->adapter->ArpFilter, priv->adapter->ArpFilterSize); + cmd->Size = + wlan_cpu_to_le16(priv->adapter->ArpFilterSize + + sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG) + + S_DS_GEN); + } else + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_HOST_SLEEP_CFG) + + S_DS_GEN); + phwuc->conditions = wlan_cpu_to_le32(pdata_buf->conditions); + phwuc->gpio = pdata_buf->gpio; + phwuc->gap = pdata_buf->gap; + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief This function prepares command of inactivity_timeout. @@ -158,15 +311,17 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv, +static int +wlan_cmd_802_11_inactivity_timeout(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - u16 cmd_action, - void *pdata_buf) + u16 cmd_action, void *pdata_buf) { u16 *timeout = (u16 *) pdata_buf; cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_INACTIVITY_TIMEOUT); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_INACTIVITY_TIMEOUT) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_INACTIVITY_TIMEOUT) + + S_DS_GEN); cmd->params.inactivity_timeout.Action = wlan_cpu_to_le16(cmd_action); @@ -187,16 +342,19 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_sleep_period(wlan_private * priv, +static int +wlan_cmd_802_11_sleep_period(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - u16 cmd_action, - void *pdata_buf) + u16 cmd_action, void *pdata_buf) { + HostCmd_DS_802_11_SLEEP_PERIOD *pSleepPeriod = &cmd->params.ps_sleeppd; + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PERIOD); cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SLEEP_PERIOD) + S_DS_GEN); - memmove(&cmd->params.ps_sleeppd, pdata_buf, - sizeof(HostCmd_DS_802_11_SLEEP_PERIOD)); + memmove(pSleepPeriod, pdata_buf, sizeof(HostCmd_DS_802_11_SLEEP_PERIOD)); + pSleepPeriod->Action = wlan_cpu_to_le16(pSleepPeriod->Action); + pSleepPeriod->Period = wlan_cpu_to_le16(pSleepPeriod->Period); return WLAN_STATUS_SUCCESS; } @@ -209,9 +367,9 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_sleep_params(wlan_private *priv, - HostCmd_DS_COMMAND *cmd, - u16 cmd_action) +static int +wlan_cmd_802_11_sleep_params(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmd_action) { wlan_adapter *Adapter = priv->adapter; HostCmd_DS_802_11_SLEEP_PARAMS *sp = &cmd->params.sleep_params; @@ -240,7 +398,6 @@ return WLAN_STATUS_SUCCESS; } - #define WEP_40_BIT_LEN 5 #define WEP_104_BIT_LEN 13 @@ -252,9 +409,9 @@ * @param cmd_oid OID: ADD_WEP KEY or REMOVE_WEP KEY * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_set_wep(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u32 cmd_oid) +static int +wlan_cmd_802_11_set_wep(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u32 cmd_oid) { HostCmd_DS_802_11_SET_WEP *wep = &cmd->params.wep; wlan_adapter *Adapter = priv->adapter; @@ -264,7 +421,8 @@ if (cmd_oid == OID_802_11_ADD_WEP) { cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP); - cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN); wep->Action = wlan_cpu_to_le16(HostCmd_ACT_ADD); /* default tx key index */ @@ -276,16 +434,19 @@ switch (Adapter->WepKey[0].KeyLength) { case WEP_40_BIT_LEN: wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_40_BIT; - memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial, Adapter->WepKey[0].KeyLength); + memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial, + Adapter->WepKey[0].KeyLength); break; case WEP_104_BIT_LEN: wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_104_BIT; - memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial, Adapter->WepKey[0].KeyLength); + memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial, + Adapter->WepKey[0].KeyLength); break; case 0: break; default: - PRINTM(INFO, "Key1 Length = %d is incorrect\n", Adapter->WepKey[0].KeyLength); + PRINTM(INFO, "Key1 Length = %d is incorrect\n", + Adapter->WepKey[0].KeyLength); ret = WLAN_STATUS_FAILURE; goto done; } @@ -293,16 +454,19 @@ switch (Adapter->WepKey[1].KeyLength) { case WEP_40_BIT_LEN: wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_40_BIT; - memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial, Adapter->WepKey[1].KeyLength); + memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial, + Adapter->WepKey[1].KeyLength); break; case WEP_104_BIT_LEN: wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_104_BIT; - memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial, Adapter->WepKey[1].KeyLength); + memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial, + Adapter->WepKey[1].KeyLength); break; case 0: break; default: - PRINTM(INFO, "Key2 Length = %d is incorrect\n", Adapter->WepKey[1].KeyLength); + PRINTM(INFO, "Key2 Length = %d is incorrect\n", + Adapter->WepKey[1].KeyLength); ret = WLAN_STATUS_FAILURE; goto done; } @@ -310,16 +474,19 @@ switch (Adapter->WepKey[2].KeyLength) { case WEP_40_BIT_LEN: wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_40_BIT; - memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial, Adapter->WepKey[2].KeyLength); + memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial, + Adapter->WepKey[2].KeyLength); break; case WEP_104_BIT_LEN: wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_104_BIT; - memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial, Adapter->WepKey[2].KeyLength); + memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial, + Adapter->WepKey[2].KeyLength); break; case 0: break; default: - PRINTM(INFO, "Key3 Length = %d is incorrect\n", Adapter->WepKey[2].KeyLength); + PRINTM(INFO, "Key3 Length = %d is incorrect\n", + Adapter->WepKey[2].KeyLength); ret = WLAN_STATUS_FAILURE; goto done; } @@ -327,28 +494,32 @@ switch (Adapter->WepKey[3].KeyLength) { case WEP_40_BIT_LEN: wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_40_BIT; - memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial, Adapter->WepKey[3].KeyLength); + memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial, + Adapter->WepKey[3].KeyLength); break; case WEP_104_BIT_LEN: wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_104_BIT; - memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial, Adapter->WepKey[3].KeyLength); + memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial, + Adapter->WepKey[3].KeyLength); break; case 0: break; default: - PRINTM(INFO, "Key4 Length = %d is incorrect\n", Adapter->WepKey[3].KeyLength); + PRINTM(INFO, "Key4 Length = %d is incorrect\n", + Adapter->WepKey[3].KeyLength); ret = WLAN_STATUS_FAILURE; goto done; } - } - else if (cmd_oid == OID_802_11_REMOVE_WEP) { + } else if (cmd_oid == OID_802_11_REMOVE_WEP) { cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP); - cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_SET_WEP)) + S_DS_GEN); wep->Action = wlan_cpu_to_le16(HostCmd_ACT_REMOVE); /* default tx key index */ wep->KeyIndex = wlan_cpu_to_le16((u16) (Adapter->CurrentWepKeyIndex & - (u32) HostCmd_WEP_KEY_INDEX_MASK)); + (u32) + HostCmd_WEP_KEY_INDEX_MASK)); } ret = WLAN_STATUS_SUCCESS; @@ -357,36 +528,6 @@ return ret; } - -/** - * @brief This function prepares command of enable_rsn. - * - * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @param cmd_action the action: GET or SET - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u16 cmd_action) -{ - HostCmd_DS_802_11_ENABLE_RSN *pEnableRSN = &cmd->params.enbrsn; - wlan_adapter *Adapter = priv->adapter; - - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ENABLE_RSN); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_ENABLE_RSN) + S_DS_GEN); - pEnableRSN->Action = wlan_cpu_to_le16(cmd_action); - if (Adapter->SecInfo.WPAEnabled - || Adapter->SecInfo.WPA2Enabled - ) { - pEnableRSN->Enable = wlan_cpu_to_le16(HostCmd_ENABLE_RSN); - } else { - pEnableRSN->Enable = wlan_cpu_to_le16(HostCmd_DISABLE_RSN); - } - - return WLAN_STATUS_SUCCESS; -} - /** * @brief This function prepares command of key_material. * @@ -397,14 +538,14 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_key_material(wlan_private * priv, +static int +wlan_cmd_802_11_key_material(wlan_private * priv, HostCmd_DS_COMMAND * cmd, u16 cmd_action, - WLAN_OID cmd_oid, - void *pdata_buf) + WLAN_OID cmd_oid, void *pdata_buf) { HostCmd_DS_802_11_KEY_MATERIAL *pKeyMaterial = &cmd->params.keymaterial; - PWLAN_802_11_KEY pKey = (PWLAN_802_11_KEY)pdata_buf; + WLAN_802_11_KEY *pKey = (WLAN_802_11_KEY *) pdata_buf; u16 KeyParamSet_len; int ret = WLAN_STATUS_SUCCESS; @@ -423,40 +564,51 @@ if (pKey->KeyLength == WPA_AES_KEY_LEN) { PRINTM(INFO, "WPA_AES\n"); - pKeyMaterial->KeyParamSet.KeyTypeId = wlan_cpu_to_le16(KEY_TYPE_ID_AES); + pKeyMaterial->KeyParamSet.KeyTypeId = + wlan_cpu_to_le16(KEY_TYPE_ID_AES); if ( cmd_oid == (WLAN_OID)KEY_INFO_ENABLED ) - pKeyMaterial->KeyParamSet.KeyInfo = wlan_cpu_to_le16(KEY_INFO_AES_ENABLED); + pKeyMaterial->KeyParamSet.KeyInfo = + wlan_cpu_to_le16(KEY_INFO_AES_ENABLED); else - pKeyMaterial->KeyParamSet.KeyInfo = !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED)); + pKeyMaterial->KeyParamSet.KeyInfo = + !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED)); if (pKey->KeyIndex & 0x40000000) //AES pairwise key: unicast - pKeyMaterial->KeyParamSet.KeyInfo |= wlan_cpu_to_le16(KEY_INFO_AES_UNICAST); + pKeyMaterial->KeyParamSet.KeyInfo |= + wlan_cpu_to_le16(KEY_INFO_AES_UNICAST); else //AES group key: multicast - pKeyMaterial->KeyParamSet.KeyInfo |= wlan_cpu_to_le16(KEY_INFO_AES_MCAST); - } - else if (pKey->KeyLength == WPA_TKIP_KEY_LEN) { + pKeyMaterial->KeyParamSet.KeyInfo |= + wlan_cpu_to_le16(KEY_INFO_AES_MCAST); + } else if (pKey->KeyLength == WPA_TKIP_KEY_LEN) { PRINTM(INFO, "WPA_TKIP\n"); - pKeyMaterial->KeyParamSet.KeyTypeId = wlan_cpu_to_le16(KEY_TYPE_ID_TKIP); - pKeyMaterial->KeyParamSet.KeyInfo = wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED); + pKeyMaterial->KeyParamSet.KeyTypeId = + wlan_cpu_to_le16(KEY_TYPE_ID_TKIP); + pKeyMaterial->KeyParamSet.KeyInfo = + wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED); if (pKey->KeyIndex & 0x40000000) //TKIP pairwise key: unicast - pKeyMaterial->KeyParamSet.KeyInfo |= wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST); + pKeyMaterial->KeyParamSet.KeyInfo |= + wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST); else //TKIP group key: multicast - pKeyMaterial->KeyParamSet.KeyInfo |= wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST); + pKeyMaterial->KeyParamSet.KeyInfo |= + wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST); } if (pKeyMaterial->KeyParamSet.KeyTypeId) { - pKeyMaterial->KeyParamSet.Type = wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + pKeyMaterial->KeyParamSet.Type = + wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); pKeyMaterial->KeyParamSet.KeyLen = wlan_cpu_to_le16(pKey->KeyLength); memcpy(pKeyMaterial->KeyParamSet.Key, pKey->KeyMaterial, pKey->KeyLength); - pKeyMaterial->KeyParamSet.Length = wlan_cpu_to_le16(pKey->KeyLength + 6); + pKeyMaterial->KeyParamSet.Length = + wlan_cpu_to_le16(pKey->KeyLength + 6); #define TYPE_LEN_FIELDS_LEN 4 - KeyParamSet_len = pKeyMaterial->KeyParamSet.Length + TYPE_LEN_FIELDS_LEN; + KeyParamSet_len = (pKey->KeyLength + 6) + TYPE_LEN_FIELDS_LEN; #define ACTION_FIELD_LEN 2 - cmd->Size = wlan_cpu_to_le16(KeyParamSet_len + ACTION_FIELD_LEN + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(KeyParamSet_len + ACTION_FIELD_LEN + S_DS_GEN); } ret = WLAN_STATUS_SUCCESS; @@ -466,55 +618,18 @@ } /** - * @brief This function prepares command of reset. - * - * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @param cmd_action the action: GET or SET - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_cmd_802_11_reset(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - int cmd_action) -{ - HostCmd_DS_802_11_RESET *reset = &cmd->params.reset; - - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RESET); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RESET) + S_DS_GEN); - reset->Action = wlan_cpu_to_le16(cmd_action); - - return WLAN_STATUS_SUCCESS; -} - -/** * @brief This function prepares command of get_log. * * @param priv A pointer to wlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_get_log(wlan_private * priv, - HostCmd_DS_COMMAND * cmd) +static int +wlan_cmd_802_11_get_log(wlan_private * priv, HostCmd_DS_COMMAND * cmd) { cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN); - - return WLAN_STATUS_SUCCESS; -} - - -/** - * @brief This function prepares command of get_stat. - * - * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_cmd_802_11_get_stat(wlan_private * priv, - HostCmd_DS_COMMAND * cmd) -{ - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_STAT); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_STAT) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_GET_LOG) + S_DS_GEN); return WLAN_STATUS_SUCCESS; } @@ -529,11 +644,10 @@ * @param pdata_buf the pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_snmp_mib(wlan_private * priv, +static int +wlan_cmd_802_11_snmp_mib(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - int cmd_action, - int cmd_oid, - void *pdata_buf) + int cmd_action, int cmd_oid, void *pdata_buf) { HostCmd_DS_802_11_SNMP_MIB *pSNMPMIB = &cmd->params.smib; wlan_adapter *Adapter = priv->adapter; @@ -544,13 +658,14 @@ PRINTM(INFO, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SNMP_MIB) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_SNMP_MIB) + S_DS_GEN); switch (cmd_oid) { case OID_802_11_INFRASTRUCTURE_MODE: pSNMPMIB->QueryType = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); pSNMPMIB->OID = wlan_cpu_to_le16((u16) DesiredBssType_i); - pSNMPMIB->BufSize = sizeof(u8); + pSNMPMIB->BufSize = wlan_cpu_to_le16(sizeof(u8)); if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) ucTemp = SNMP_MIB_VALUE_INFRA; else @@ -567,8 +682,8 @@ pSNMPMIB->OID = wlan_cpu_to_le16((u16) Dot11D_i); if (cmd_action == HostCmd_ACT_SET) { - pSNMPMIB->QueryType = HostCmd_ACT_GEN_SET; - pSNMPMIB->BufSize = sizeof(u16); + pSNMPMIB->QueryType = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + pSNMPMIB->BufSize = wlan_cpu_to_le16(sizeof(u16)); ulTemp = *(u32*) pdata_buf; *((PUSHORT) (pSNMPMIB->Value)) = wlan_cpu_to_le16((u16) ulTemp); @@ -576,12 +691,10 @@ break; } - case OID_802_11_FRAGMENTATION_THRESHOLD: { WLAN_802_11_FRAGMENTATION_THRESHOLD ulTemp; - pSNMPMIB->OID = wlan_cpu_to_le16((u16) FragThresh_i); if (cmd_action == HostCmd_ACT_GET) { @@ -603,18 +716,16 @@ { WLAN_802_11_RTS_THRESHOLD ulTemp; - pSNMPMIB->OID = wlan_le16_to_cpu((u16)RtsThresh_i); + pSNMPMIB->OID = wlan_cpu_to_le16((u16) RtsThresh_i); if (cmd_action == HostCmd_ACT_GET) { pSNMPMIB->QueryType = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); } else if (cmd_action == HostCmd_ACT_SET) { pSNMPMIB->QueryType = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); pSNMPMIB->BufSize = wlan_cpu_to_le16(sizeof(u16)); - ulTemp = - *((WLAN_802_11_RTS_THRESHOLD *) + ulTemp = *((WLAN_802_11_RTS_THRESHOLD *) pdata_buf); - *(PUSHORT) (pSNMPMIB->Value) = - wlan_cpu_to_le16((u16) ulTemp); + *(PUSHORT) (pSNMPMIB->Value) = wlan_cpu_to_le16((u16) ulTemp); } break; @@ -636,10 +747,12 @@ break; } - PRINTM(INFO, "SNMP_CMD: Command=0x%x, Size=0x%x, SeqNum=0x%x, Result=0x%x\n", + PRINTM(INFO, + "SNMP_CMD: Command=0x%x, Size=0x%x, SeqNum=0x%x, Result=0x%x\n", cmd->Command, cmd->Size, cmd->SeqNum, cmd->Result); - PRINTM(INFO, "SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n", + PRINTM(INFO, + "SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n", pSNMPMIB->QueryType, pSNMPMIB->OID, pSNMPMIB->BufSize, *(u16 *) pSNMPMIB->Value); @@ -655,45 +768,67 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_radio_control(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - int cmd_action) +static int +wlan_cmd_802_11_radio_control(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, int cmd_action) { wlan_adapter *Adapter = priv->adapter; HostCmd_DS_802_11_RADIO_CONTROL *pRadioControl = &cmd->params.radio; ENTER(); - cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL)) + S_DS_GEN); + cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RADIO_CONTROL)) + + S_DS_GEN); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL); pRadioControl->Action = wlan_cpu_to_le16(cmd_action); + pRadioControl->Control = wlan_cpu_to_le16(Adapter->RadioOn); - switch (Adapter->Preamble) { - case HostCmd_TYPE_SHORT_PREAMBLE: - pRadioControl->Control = wlan_cpu_to_le16(SET_SHORT_PREAMBLE); - break; + LEAVE(); + return WLAN_STATUS_SUCCESS; +} - case HostCmd_TYPE_LONG_PREAMBLE: - pRadioControl->Control = wlan_cpu_to_le16(SET_LONG_PREAMBLE); - break; +/** + * @brief This function prepares command of bca_timeshare. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action the action: GET or SET + * @param user_bca_ts A pointer to HostCmd_DS_802_11_BCA_TIMESHARE structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_cmd_802_11_bca_timeshare(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, + u16 cmd_action, + HostCmd_DS_802_11_BCA_TIMESHARE * user_bca_ts) +{ + wlan_adapter *Adapter = priv->adapter; + HostCmd_DS_802_11_BCA_TIMESHARE *bca_ts = &cmd->params.bca_timeshare; - case HostCmd_TYPE_AUTO_PREAMBLE: - default: - pRadioControl->Control = wlan_cpu_to_le16(SET_AUTO_PREAMBLE); - break; - } + ENTER(); - if (Adapter->RadioOn) - pRadioControl->Control |= wlan_cpu_to_le16(TURN_ON_RF); - else - pRadioControl->Control &= wlan_cpu_to_le16(~TURN_ON_RF); + cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_BCA_TIMESHARE)) + + S_DS_GEN); + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE); + + if (cmd_action == HostCmd_ACT_GEN_GET) { + memset(&Adapter->bca_ts, 0, sizeof(bca_ts)); + memset(bca_ts, 0, sizeof(HostCmd_DS_802_11_BCA_TIMESHARE)); + bca_ts->Action = wlan_cpu_to_le16(cmd_action); + bca_ts->TrafficType = wlan_cpu_to_le16(user_bca_ts->TrafficType); + } else if (cmd_action == HostCmd_ACT_GEN_SET) { + bca_ts->Action = wlan_cpu_to_le16(cmd_action); + bca_ts->TrafficType = wlan_cpu_to_le16(user_bca_ts->TrafficType); + bca_ts->TimeShareInterval = + wlan_cpu_to_le32(user_bca_ts->TimeShareInterval); + bca_ts->BTTime = wlan_cpu_to_le32(user_bca_ts->BTTime); + } LEAVE(); return WLAN_STATUS_SUCCESS; } - /** * @brief This function prepares command of rf_tx_power. * @@ -703,42 +838,31 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv, +static int +wlan_cmd_802_11_rf_tx_power(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - u16 cmd_action, - void *pdata_buf) + u16 cmd_action, void *pdata_buf) { HostCmd_DS_802_11_RF_TX_POWER *pRTP = &cmd->params.txp; ENTER(); - cmd->Size = wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RF_TX_POWER)) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16((sizeof(HostCmd_DS_802_11_RF_TX_POWER)) + S_DS_GEN); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER); pRTP->Action = cmd_action; - PRINTM(INFO, "RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n", cmd->Size, cmd->Command, - pRTP->Action); + PRINTM(INFO, "RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n", cmd->Size, + cmd->Command, pRTP->Action); switch (cmd_action) { - case HostCmd_ACT_TX_POWER_OPT_GET: + case HostCmd_ACT_GEN_GET: pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); pRTP->CurrentLevel = 0; break; - case HostCmd_ACT_TX_POWER_OPT_SET_HIGH: - pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); - pRTP->CurrentLevel = - wlan_cpu_to_le16(HostCmd_ACT_TX_POWER_INDEX_HIGH); - break; - - case HostCmd_ACT_TX_POWER_OPT_SET_MID: - pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); - pRTP->CurrentLevel = - wlan_cpu_to_le16(HostCmd_ACT_TX_POWER_INDEX_MID); - break; - - case HostCmd_ACT_TX_POWER_OPT_SET_LOW: + case HostCmd_ACT_GEN_SET: pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); pRTP->CurrentLevel = wlan_cpu_to_le16(*((u16 *)pdata_buf)); break; @@ -756,15 +880,16 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_rf_antenna(wlan_private * priv, +static int +wlan_cmd_802_11_rf_antenna(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - u16 cmd_action, - void *pdata_buf) + u16 cmd_action, void *pdata_buf) { HostCmd_DS_802_11_RF_ANTENNA *rant = &cmd->params.rant; cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RF_ANTENNA) + S_DS_GEN); rant->Action = wlan_cpu_to_le16(cmd_action); if ((cmd_action == HostCmd_ACT_SET_RX) || @@ -784,68 +909,30 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private *priv, - HostCmd_DS_COMMAND *cmd, - u16 cmd_action) +static int +wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmd_action) { - HostCmd_DS_802_11_RATE_ADAPT_RATESET - *rateadapt = &cmd->params.rateset; + HostCmd_DS_802_11_RATE_ADAPT_RATESET * rateadapt = &cmd->params.rateset; wlan_adapter *Adapter = priv->adapter; cmd->Size = - wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RATE_ADAPT_RATESET) + S_DS_GEN); - cmd->Command = - wlan_cpu_to_le16(HostCmd_CMD_802_11_RATE_ADAPT_RATESET); - - ENTER(); - - rateadapt->Action = cmd_action; - rateadapt->EnableHwAuto = Adapter->EnableHwAuto; - rateadapt->Bitmap = Adapter->RateBitmap; - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief This function prepares command of rate_adapt_rateset. - * - * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @param cmd_action the action: GET or SET - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_cmd_802_11_data_rate(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u16 cmd_action) -{ - HostCmd_DS_802_11_DATA_RATE *pDataRate = &cmd->params.drate; - wlan_adapter *Adapter = priv->adapter; - u16 Action = cmd_action; + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RATE_ADAPT_RATESET) + + S_DS_GEN); + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RATE_ADAPT_RATESET); ENTER(); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DATA_RATE) + S_DS_GEN); - - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_DATA_RATE); - - memset(pDataRate, 0, sizeof(HostCmd_DS_802_11_DATA_RATE)); - - pDataRate->Action = wlan_cpu_to_le16(cmd_action); - - if (Action == HostCmd_ACT_SET_TX_FIX_RATE) { - pDataRate->DataRate[0] = data_rate_to_index(Adapter->DataRate); - PRINTM(INFO, "Setting FW for fixed rate 0x%02X\n", Adapter->DataRate); - } - else if(Action == HostCmd_ACT_SET_TX_AUTO) { - PRINTM(INFO, "Setting FW for AUTO rate\n"); - } + rateadapt->Action = wlan_cpu_to_le16(cmd_action); + rateadapt->HWRateDropMode = wlan_cpu_to_le16(Adapter->HWRateDropMode); + rateadapt->Threshold = wlan_cpu_to_le16(Adapter->Threshold); + rateadapt->FinalRate = wlan_cpu_to_le16(Adapter->FinalRate); + rateadapt->Bitmap = wlan_cpu_to_le16(Adapter->RateBitmap); LEAVE(); return WLAN_STATUS_SUCCESS; } - /** * @brief This function prepares command of mac_multicast_adr. * @@ -854,18 +941,20 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_mac_multicast_adr(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u16 cmd_action) +static int +wlan_cmd_mac_multicast_adr(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmd_action) { HostCmd_DS_MAC_MULTICAST_ADR *pMCastAdr = &cmd->params.madr; wlan_adapter *Adapter = priv->adapter; - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_MULTICAST_ADR) + S_DS_GEN); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); pMCastAdr->Action = wlan_cpu_to_le16(cmd_action); - pMCastAdr->NumOfAdrs = wlan_cpu_to_le16((u16) Adapter->NumOfMulticastMACAddr); + pMCastAdr->NumOfAdrs = + wlan_cpu_to_le16((u16) Adapter->NumOfMulticastMACAddr); memcpy(pMCastAdr->MACList, Adapter->MulticastList, Adapter->NumOfMulticastMACAddr * ETH_ALEN); @@ -881,10 +970,10 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_rf_channel(wlan_private * priv, +static int +wlan_cmd_802_11_rf_channel(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - int option, - void *pdata_buf) + int option, void *pdata_buf) { HostCmd_DS_802_11_RF_CHANNEL *rfchan = &cmd->params.rfchannel; @@ -908,14 +997,14 @@ * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_rssi(wlan_private * priv, - HostCmd_DS_COMMAND * cmd) +static int +wlan_cmd_802_11_rssi(wlan_private * priv, HostCmd_DS_COMMAND * cmd) { wlan_adapter *Adapter = priv->adapter; cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RSSI); cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_RSSI) + S_DS_GEN); - cmd->params.rssi.N = priv->adapter->bcn_avg_factor; + cmd->params.rssi.N = wlan_cpu_to_le16(Adapter->bcn_avg_factor); /* reset Beacon SNR/NF/RSSI values */ Adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; @@ -928,7 +1017,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief This function prepares command of reg_access. * @@ -938,10 +1026,10 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_reg_access(wlan_private * priv, +static int +wlan_cmd_reg_access(wlan_private * priv, HostCmd_DS_COMMAND * CmdPtr, - u8 cmd_action, - void *pdata_buf) + u8 cmd_action, void *pdata_buf) { wlan_offset_value *offval; @@ -954,8 +1042,10 @@ { HostCmd_DS_MAC_REG_ACCESS *macreg; - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_REG_ACCESS) + S_DS_GEN); - macreg = (PHostCmd_DS_MAC_REG_ACCESS) & CmdPtr->params.macreg; + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_REG_ACCESS) + + S_DS_GEN); + macreg = (HostCmd_DS_MAC_REG_ACCESS *) & CmdPtr->params.macreg; macreg->Action = wlan_cpu_to_le16(cmd_action); macreg->Offset = wlan_cpu_to_le16((u16) offval->offset); @@ -968,8 +1058,10 @@ { HostCmd_DS_BBP_REG_ACCESS *bbpreg; - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_BBP_REG_ACCESS) + S_DS_GEN); - bbpreg = (PHostCmd_DS_BBP_REG_ACCESS) & CmdPtr->params.bbpreg; + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_BBP_REG_ACCESS) + + S_DS_GEN); + bbpreg = (HostCmd_DS_BBP_REG_ACCESS *) & CmdPtr->params.bbpreg; bbpreg->Action = wlan_cpu_to_le16(cmd_action); bbpreg->Offset = wlan_cpu_to_le16((u16) offval->offset); @@ -982,8 +1074,9 @@ { HostCmd_DS_RF_REG_ACCESS *rfreg; - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) + S_DS_GEN); - rfreg = (PHostCmd_DS_RF_REG_ACCESS) & CmdPtr->params.rfreg; + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_RF_REG_ACCESS) + S_DS_GEN); + rfreg = (HostCmd_DS_RF_REG_ACCESS *) & CmdPtr->params.rfreg; rfreg->Action = wlan_cpu_to_le16(cmd_action); rfreg->Offset = wlan_cpu_to_le16((u16) offval->offset); @@ -1008,9 +1101,9 @@ * @param cmd_action the action: GET or SET * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_mac_address(wlan_private * priv, - HostCmd_DS_COMMAND * cmd, - u16 cmd_action) +static int +wlan_cmd_802_11_mac_address(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, u16 cmd_action) { wlan_adapter *Adapter = priv->adapter; @@ -1022,20 +1115,58 @@ cmd->params.macadd.Action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_SET) { - memcpy(cmd->params.macadd.MacAdd, - Adapter->CurrentAddr, - ETH_ALEN); - HEXDUMP("SET_CMD: MAC ADDRESS-", - Adapter->CurrentAddr, 6); + memcpy(cmd->params.macadd.MacAdd, Adapter->CurrentAddr, ETH_ALEN); + HEXDUMP("SET_CMD: MAC ADDRESS-", Adapter->CurrentAddr, 6); } return WLAN_STATUS_SUCCESS; } +/** + * @brief This function prepares command of cal_data_ext. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param pdata_buf A pointer to data buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_cmd_802_11_cal_data_ext(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pdata_buf) +{ + HostCmd_DS_802_11_CAL_DATA_EXT *PCalDataext = pdata_buf; + + HostCmd_DS_802_11_CAL_DATA_EXT *pCmdCalData = + (HostCmd_DS_802_11_CAL_DATA_EXT *) & cmd->params.caldataext; + + ENTER(); + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_CAL_DATA_EXT); + + PRINTM(INFO, "CalDataLen = %d(d)\n", PCalDataext->CalDataLen); + + if (PCalDataext->CalDataLen > + MAX_SETGET_CONF_CMD_LEN - CAL_DATA_HEADER_LEN) { + PRINTM(MSG, "CAL_DATA_EXT: Cal data lenght too large!\n"); + return WLAN_STATUS_FAILURE; + } + + memcpy(pCmdCalData, PCalDataext, + PCalDataext->CalDataLen + CAL_DATA_HEADER_LEN); + pCmdCalData->Action = wlan_cpu_to_le16(pCmdCalData->Action); + pCmdCalData->Revision = wlan_cpu_to_le16(pCmdCalData->Revision); + pCmdCalData->CalDataLen = wlan_cpu_to_le16(pCmdCalData->CalDataLen); + cmd->Size = wlan_cpu_to_le16(PCalDataext->CalDataLen + + CAL_DATA_HEADER_LEN + S_DS_GEN); + PRINTM(INFO, "CAL_DATA_EXT: cmd->Size = %d(d)\n", cmd->Size); + cmd->Result = 0; + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief This function prepares command of eeprom_access. @@ -1046,17 +1177,18 @@ * @param pdata_buf A pointer to data buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_802_11_eeprom_access(wlan_private *priv, +static int +wlan_cmd_802_11_eeprom_access(wlan_private * priv, HostCmd_DS_COMMAND *cmd, - int cmd_action, - void *pdata_buf) + int cmd_action, void *pdata_buf) { wlan_ioctl_regrdwr *ea = pdata_buf; ENTER(); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_EEPROM_ACCESS); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_EEPROM_ACCESS) + S_DS_GEN); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_EEPROM_ACCESS) + S_DS_GEN); cmd->Result = 0; cmd->params.rdeeprom.Action = wlan_cpu_to_le16(ea -> Action); @@ -1067,68 +1199,33 @@ return WLAN_STATUS_SUCCESS; } - - -/** - * @brief This function prepares command of DFT access. - * - * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @param cmd_action the action: ADD, DEL, RESET, or LIST - * @param pdata_buf A pointer to data buffer - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_cmd_dft_access(wlan_private * priv, +static int +wlan_cmd_802_11_IBSS_Coalesced_Status(wlan_private * priv, HostCmd_DS_COMMAND * cmd, - u16 cmd_action, - void *pdata_buf) + int cmd_action, void *pdata_buf) { - HostCmd_DS_DFT_ACCESS *dft_access = &cmd->params.dft; - PRINTM(INFO, "DFT CMD(%d)\n", cmd_action); + HostCmd_DS_802_11_IBSS_Status *pIBSSReq = &(cmd->params.ibssCoalescing); + u16 *enable = pdata_buf; - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_DFT_ACCESS); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_DFT_ACCESS) - + S_DS_GEN); + PRINTM(INFO, "HostCmd_CMD_802_11_BSSID_QUERY request"); + + cmd->Command = + wlan_cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_IBSS_Status) + S_DS_GEN); cmd->Result = 0; - dft_access->Action = wlan_cpu_to_le16(cmd_action); + pIBSSReq->Action = wlan_cpu_to_le16(cmd_action); switch (cmd_action) { - case HostCmd_ACT_DFT_ACCESS_ADD: - memcpy(dft_access->addr1, pdata_buf, 2*ETH_ALEN); - HEXDUMP("DFT_ADD: index mac address-", - dft_access->addr1, 6); - HEXDUMP("DFT_ADD: yield mac address-", - dft_access->addr2, 6); - break; - case HostCmd_ACT_DFT_ACCESS_DEL: - memcpy(dft_access->addr1, pdata_buf, 1*ETH_ALEN); - HEXDUMP("DFT_DEL: index mac address-", - dft_access->addr1, 6); - break; - case HostCmd_ACT_DFT_ACCESS_LIST: - dft_access->id = wlan_cpu_to_le32(*(u32 *)pdata_buf); - break; - case HostCmd_ACT_DFT_ACCESS_RESET: - break; - case HostCmd_ACT_BT_ACCESS_ADD: - memcpy(dft_access->addr1, pdata_buf, 2*ETH_ALEN); - HEXDUMP("BT_ADD: blinded mac address-", - dft_access->addr1, 6); - break; - case HostCmd_ACT_BT_ACCESS_DEL: - memcpy(dft_access->addr1, pdata_buf, 1*ETH_ALEN); - HEXDUMP("BT_DEL: blinded mac address-", - dft_access->addr1, 6); - break; - case HostCmd_ACT_BT_ACCESS_LIST: - dft_access->id = wlan_cpu_to_le32(*(u32 *)pdata_buf); - break; - case HostCmd_ACT_BT_ACCESS_RESET: + case HostCmd_ACT_SET: + pIBSSReq->Enable = wlan_cpu_to_le16(*enable); break; + + /* In other case.. Noting to do */ + case HostCmd_ACT_GET: default: break; } - return WLAN_STATUS_SUCCESS; } @@ -1140,62 +1237,92 @@ * @param addtail specify if the cmd needs to be queued in the header or tail * @return n/a */ -void QueueCmd(wlan_adapter *Adapter, CmdCtrlNode *CmdNode, BOOLEAN addtail) +void +QueueCmd(wlan_adapter * Adapter, CmdCtrlNode * CmdNode, BOOLEAN addtail) { ulong flags; HostCmd_DS_COMMAND *CmdPtr; + u16 command; ENTER(); if (!CmdNode) { - PRINTM(INFO, "QUEUE_CMD: CmdNode is NULL\n"); + PRINTM(WARN, "QUEUE_CMD: CmdNode is NULL\n"); goto done; } CmdPtr = (HostCmd_DS_COMMAND *)CmdNode->BufVirtualAddr; if (!CmdPtr) { - PRINTM(INFO, "QUEUE_CMD: CmdPtr is NULL\n"); + PRINTM(WARN, "QUEUE_CMD: CmdPtr is NULL\n"); goto done; } + command = wlan_le16_to_cpu(CmdPtr->Command); + /* Exit_PS command needs to be queued in the header always. */ - if (CmdPtr->Command == HostCmd_CMD_802_11_PS_MODE) { + if (command == HostCmd_CMD_802_11_PS_MODE) { HostCmd_DS_802_11_PS_MODE *psm = &CmdPtr->params.psmode; - if (psm->Action == HostCmd_SubCmd_Exit_PS) { + if (wlan_le16_to_cpu(psm->Action) == HostCmd_SubCmd_Exit_PS) { if (Adapter->PSState != PS_STATE_FULL_POWER) addtail = FALSE; } } + if ((command == HostCmd_CMD_802_11_WAKEUP_CONFIRM) + || (command == HostCmd_CMD_802_11_HOST_SLEEP_ACTIVATE) + || (command == HostCmd_CMD_802_11_HOST_SLEEP_CFG) + ) { + addtail = FALSE; + } spin_lock_irqsave(&Adapter->QueueSpinLock, flags); if (addtail) - list_add_tail((struct list_head *)CmdNode, - &Adapter->CmdPendingQ); + list_add_tail((struct list_head *) CmdNode, &Adapter->CmdPendingQ); else - list_add((struct list_head *)CmdNode, - &Adapter->CmdPendingQ); + list_add((struct list_head *) CmdNode, &Adapter->CmdPendingQ); spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); - PRINTM(INFO, "QUEUE_CMD: Inserted node=0x%x, cmd=0x%x in CmdPendingQ\n", - (u32)CmdNode, - ((HostCmd_DS_GEN *)CmdNode->BufVirtualAddr)->Command); + PRINTM(INFO, "QUEUE_CMD: cmd=0x%x is queued\n", command); done: LEAVE(); return; } - -/* - * TODO: Fix the issue when DownloadCommandToStation is being called the - * second time when the command timesout. All the CmdPtr->xxx are in little - * endian and therefore all the comparissions will fail. - * For now - we are not performing the endian conversion the second time - but - * for PS and DEEP_SLEEP we need to worry +#ifdef MFG_CMD_SUPPORT +/** + * @brief This function sends general command to firmware. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param pdata_buf A pointer to data buffer + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ +static int +wlan_cmd_mfg_cmd(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pdata_buf) +{ + HostCmd_DS_GEN *pCmdPtr; + + ENTER(); + + pCmdPtr = (HostCmd_DS_GEN *) pdata_buf; + + /* copy the MFG command to command buffer */ + memcpy((void *) cmd, pdata_buf, pCmdPtr->Size); + + PRINTM(INFO, "MFG command size = %d\n", pCmdPtr->Size); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MFG_COMMAND); + cmd->Size = wlan_cpu_to_le16(cmd->Size); + cmd->Result = 0; + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} +#endif /** * @brief This function downloads the command to firmware. @@ -1204,7 +1331,8 @@ * @param CmdNode A pointer to CmdCtrlNode structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int DownloadCommandToStation(wlan_private * priv, CmdCtrlNode * CmdNode) +static int +DownloadCommandToStation(wlan_private * priv, CmdCtrlNode * CmdNode) { ulong flags; HostCmd_DS_COMMAND *CmdPtr; @@ -1218,7 +1346,8 @@ ENTER(); if (!Adapter || !CmdNode) { - PRINTM(INFO, "DNLD_CMD: Adapter = %#x, CmdNode = %#x\n", (int)Adapter, (int)CmdNode); + PRINTM(ERROR, "DNLD_CMD: Adapter = %#x, CmdNode = %#x\n", + (int) Adapter, (int) CmdNode); if (CmdNode) CleanupAndInsertCmd(priv, CmdNode); ret = WLAN_STATUS_FAILURE; @@ -1228,25 +1357,26 @@ CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr; if (!CmdPtr || !CmdPtr->Size) { - PRINTM(INFO, "DNLD_CMD: CmdPtr is Null or Cmd Size is Zero, " + PRINTM(ERROR, "DNLD_CMD: CmdPtr is Null or Cmd Size is Zero, " "Not sending\n"); CleanupAndInsertCmd(priv, CmdNode); ret = WLAN_STATUS_FAILURE; goto done; } + /* Set command sequence number */ + Adapter->SeqNum++; + CmdPtr->SeqNum = wlan_cpu_to_le16(Adapter->SeqNum); + spin_lock_irqsave(&Adapter->QueueSpinLock, flags); Adapter->CurCmd = CmdNode; spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); Adapter->CurCmdRetCode = 0; - PRINTM(INFO, "DNLD_CMD:: Before download, Size of Cmd = %d\n", CmdPtr->Size); - - CmdSize = CmdPtr->Size; - Command = wlan_cpu_to_le16(CmdPtr->Command); + Command = wlan_le16_to_cpu(CmdPtr->Command); + CmdSize = wlan_le16_to_cpu(CmdPtr->Size); CmdNode->CmdWaitQWoken = FALSE; - CmdSize = wlan_cpu_to_le16(CmdSize); ret = sbi_host_to_card(priv, MVMS_CMD, (u8 *) CmdPtr, CmdSize); @@ -1256,28 +1386,96 @@ OS_INT_RESTORE; if (ret != 0) { - PRINTM(INFO, "DNLD_CMD: Host to Card Failed\n"); + PRINTM(ERROR, "DNLD_CMD: Host to Card Failed\n"); + /* set error code that will be transferred back to PrepareAndSendCommand() */ + Adapter->CurCmdRetCode = WLAN_STATUS_FAILURE; CleanupAndInsertCmd(priv, Adapter->CurCmd); spin_lock_irqsave(&Adapter->QueueSpinLock, flags); Adapter->CurCmd = NULL; spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); + Adapter->dbg.num_cmd_host_to_card_failure++; ret = WLAN_STATUS_FAILURE; goto done; } - PRINTM(INFO, "DNLD_CMD: Sent command 0x%x @ %lu\n", Command, os_time_get()); - HEXDUMP("DNLD_CMD: Command", CmdNode->BufVirtualAddr, CmdSize); + /* Save the last command id and action to debug log */ + Adapter->dbg.LastCmdIndex = (Adapter->dbg.LastCmdIndex + 1) % DBG_CMD_NUM; + Adapter->dbg.LastCmdId[Adapter->dbg.LastCmdIndex] = Command; + Adapter->dbg.LastCmdAct[Adapter->dbg.LastCmdIndex] = + wlan_le16_to_cpu(*(u16 *) ((u8 *) CmdPtr + S_DS_GEN)); + + PRINTM(CMND, "DNLD_CMD: 0x%x, act 0x%x, len %d, seqno %d @ %lu\n", + Command, wlan_le16_to_cpu(*(u16 *) ((u8 *) CmdPtr + S_DS_GEN)), + CmdSize, wlan_le16_to_cpu(CmdPtr->SeqNum), os_time_get()); + DBG_HEXDUMP(CMD_D, "DNLD_CMD", CmdNode->BufVirtualAddr, CmdSize); /* Setup the timer after transmit command */ if (Command == HostCmd_CMD_802_11_SCAN - || Command == HostCmd_CMD_802_11_AUTHENTICATE - || Command == HostCmd_CMD_802_11_ASSOCIATE) + || Command == HostCmd_CMD_802_11_DEAUTHENTICATE + || Command == HostCmd_CMD_802_11_ASSOCIATE + || Command == HostCmd_CMD_WMM_ADDTS_REQ) { ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_10S); - else + } else { ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_5S); + } Adapter->CommandTimerIsSet = TRUE; + if (Command == HostCmd_CMD_802_11_DEEP_SLEEP) { + if (Adapter->IntCounter || Adapter->CurrentTxSkb) + PRINTM(INFO, "DNLD_CMD: DS- IntCnt=%d CurTxSkb=%s\n", + Adapter->IntCounter, (Adapter->CurrentTxSkb) ? "Y" : "N"); + + if (Adapter->IntCounter) { + OS_INT_DISABLE; + Adapter->IntCounterSaved = Adapter->IntCounter; + Adapter->IntCounter = 0; + OS_INT_RESTORE; + } + if (Adapter->CurrentTxSkb) { + kfree_skb(Adapter->CurrentTxSkb); + OS_INT_DISABLE; + Adapter->CurrentTxSkb = NULL; + OS_INT_RESTORE; + priv->stats.tx_dropped++; + } + /* 1. change the PS state to DEEP_SLEEP + * 2. since there is no response for this command, so + * delete the command timer and free the Node. */ + + Adapter->IsDeepSleep = TRUE; + + CleanupAndInsertCmd(priv, CmdNode); + spin_lock_irqsave(&Adapter->QueueSpinLock, flags); + Adapter->CurCmd = NULL; + spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); + + if (Adapter->CommandTimerIsSet) { + CancelTimer(&Adapter->MrvDrvCommandTimer); + Adapter->CommandTimerIsSet = FALSE; + } + + if (!Adapter->IsAutoDeepSleepEnabled + || (Adapter->bHostSleepConfigured && + (Adapter->HSCfg.gpio != HOST_SLEEP_CFG_WAKEUP_THRU_INTERFACE)) + ) + /* stop clock to save more power */ + sbi_set_bus_clock(priv, FALSE); + + if (Adapter->IsAutoDeepSleepEnabled) { + Adapter->bWakeupDevRequired = TRUE; + /* For auto deep sleep mode, after entering deep sleep state, + * dnld_sent flag should be cleared so that the commands in + * pending queue can be handled by main thread. */ + priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + } + + if (Adapter->bHostSleepConfigured) { + Adapter->bWakeupDevRequired = TRUE; + wlan_host_sleep_activated_event(priv); + } + + } ret = WLAN_STATUS_SUCCESS; @@ -1293,16 +1491,18 @@ * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_cmd_mac_control(wlan_private * priv, - HostCmd_DS_COMMAND * cmd) +static int +wlan_cmd_mac_control(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) { HostCmd_DS_MAC_CONTROL *mac = &cmd->params.macctrl; + u16 Action = *((u16 *) InfoBuf); ENTER(); cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL); cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_MAC_CONTROL) + S_DS_GEN); - mac->Action = wlan_cpu_to_le16(priv->adapter->CurrentPacketFilter); + mac->Action = wlan_cpu_to_le16(Action); PRINTM(INFO, "wlan_cmd_mac_control(): Action=0x%X Size=%d\n", mac->Action,cmd->Size); @@ -1323,7 +1523,8 @@ * @param pTempCmd A pointer to CmdCtrlNode structure * @return n/a */ -void CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd) +void +CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd) { ulong flags; wlan_adapter *Adapter = priv->adapter; @@ -1343,55 +1544,6 @@ } /** - * @brief This function sets radio control. - * - * @param priv A pointer to wlan_private structure - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int SetRadioControl(wlan_private *priv) -{ - int ret = WLAN_STATUS_SUCCESS; - - ENTER(); - - ret = PrepareAndSendCommand(priv, - HostCmd_CMD_802_11_RADIO_CONTROL, - HostCmd_ACT_GEN_SET, - HostCmd_OPTION_WAITFORRSP, - 0, NULL); - - PRINTM(INFO, "RADIO_SET: on or off: 0x%X, Preamble = 0x%X\n", - priv->adapter->RadioOn, priv->adapter->Preamble); - - LEAVE(); - return ret; -} - -/** - * @brief This function sets packet filter. - * - * @param priv A pointer to wlan_private structure - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int SetMacPacketFilter(wlan_private * priv) -{ - int ret = WLAN_STATUS_SUCCESS; - - ENTER(); - - PRINTM(INFO, "SetMacPacketFilter Value = %x\n", - priv->adapter->CurrentPacketFilter); - - /* Send MAC control command to station */ - ret = PrepareAndSendCommand(priv, - HostCmd_CMD_MAC_CONTROL, - 0, 0, 0, NULL); - - LEAVE(); - return ret; -} - -/** * @brief This function prepare the command before send to firmware. * * @param priv A pointer to wlan_private structure @@ -1402,12 +1554,11 @@ * @param pdata_buf A pointer to informaion buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int PrepareAndSendCommand(wlan_private * priv, +int +PrepareAndSendCommand(wlan_private * priv, u16 cmd_no, u16 cmd_action, - u16 wait_option, - WLAN_OID cmd_oid, - void *pdata_buf) + u16 wait_option, WLAN_OID cmd_oid, void *pdata_buf) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -1417,14 +1568,13 @@ ENTER(); if (!Adapter) { - PRINTM(INFO, "PREP_CMD: Adapter is Null\n"); + PRINTM(ERROR, "PREP_CMD: Adapter is Null\n"); ret = WLAN_STATUS_FAILURE; goto done; } - if (Adapter->SurpriseRemoved) { - PRINTM(INFO, "PREP_CMD: Card is Removed\n"); + PRINTM(ERROR, "PREP_CMD: Card is Removed\n"); ret = WLAN_STATUS_FAILURE; goto done; } @@ -1444,9 +1594,6 @@ CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr; - PRINTM(INFO, "PREP_CMD: Val of Cmd ptr =0x%x, command=0x%X\n", - (u32) CmdPtr,cmd_no); - if (!CmdPtr) { PRINTM(MSG, "PREP_CMD: BufVirtualAddr of CmdNode is NULL\n"); CleanupAndInsertCmd(priv, CmdNode); @@ -1454,10 +1601,6 @@ goto done; } - /* Set sequence number, command and INT option */ - Adapter->SeqNum++; - CmdPtr->SeqNum = wlan_cpu_to_le16(Adapter->SeqNum); - CmdPtr->Command = cmd_no; CmdPtr->Result = 0; @@ -1475,11 +1618,10 @@ break; case HostCmd_CMD_MAC_CONTROL: - ret = wlan_cmd_mac_control(priv, CmdPtr); + ret = wlan_cmd_mac_control(priv, CmdPtr, pdata_buf); break; case HostCmd_CMD_802_11_ASSOCIATE: - case HostCmd_CMD_802_11_REASSOCIATE: ret = wlan_cmd_802_11_associate(priv, CmdPtr, pdata_buf); break; @@ -1492,29 +1634,17 @@ break; case HostCmd_CMD_802_11_AD_HOC_START: - ret = wlan_cmd_802_11_ad_hoc_start(priv, CmdPtr, - pdata_buf); - break; - case HostCmd_CMD_CODE_DNLD: + ret = wlan_cmd_802_11_ad_hoc_start(priv, CmdPtr, pdata_buf); break; - case HostCmd_CMD_802_11_RESET: - ret = wlan_cmd_802_11_reset(priv, CmdPtr, - cmd_action); + CmdPtr->Command = wlan_cpu_to_le16(cmd_no); + CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN); break; case HostCmd_CMD_802_11_GET_LOG: ret = wlan_cmd_802_11_get_log(priv, CmdPtr); break; - case HostCmd_CMD_802_11_AUTHENTICATE: - ret = wlan_cmd_802_11_authenticate(priv, CmdPtr, pdata_buf); - break; - - case HostCmd_CMD_802_11_GET_STAT: - ret = wlan_cmd_802_11_get_stat(priv, CmdPtr); - break; - case HostCmd_CMD_802_11_SNMP_MIB: ret = wlan_cmd_802_11_snmp_mib(priv, CmdPtr, cmd_action, cmd_oid, pdata_buf); @@ -1523,13 +1653,11 @@ case HostCmd_CMD_MAC_REG_ACCESS: case HostCmd_CMD_BBP_REG_ACCESS: case HostCmd_CMD_RF_REG_ACCESS: - ret = wlan_cmd_reg_access(priv, CmdPtr, cmd_action, - pdata_buf); + ret = wlan_cmd_reg_access(priv, CmdPtr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_RF_CHANNEL: - ret = wlan_cmd_802_11_rf_channel(priv, CmdPtr, - cmd_action, pdata_buf); + ret = wlan_cmd_802_11_rf_channel(priv, CmdPtr, cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_RF_TX_POWER: @@ -1538,32 +1666,23 @@ break; case HostCmd_CMD_802_11_RADIO_CONTROL: - ret = wlan_cmd_802_11_radio_control(priv, CmdPtr, - cmd_action); + ret = wlan_cmd_802_11_radio_control(priv, CmdPtr, cmd_action); break; case HostCmd_CMD_802_11_RF_ANTENNA: - ret = wlan_cmd_802_11_rf_antenna(priv, CmdPtr, - cmd_action, pdata_buf); + ret = wlan_cmd_802_11_rf_antenna(priv, CmdPtr, cmd_action, pdata_buf); break; - case HostCmd_CMD_802_11_DATA_RATE: - ret = wlan_cmd_802_11_data_rate(priv, CmdPtr, - cmd_action); - break; case HostCmd_CMD_802_11_RATE_ADAPT_RATESET: - ret = wlan_cmd_802_11_rate_adapt_rateset(priv, - CmdPtr, cmd_action); + ret = wlan_cmd_802_11_rate_adapt_rateset(priv, CmdPtr, cmd_action); break; case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = wlan_cmd_mac_multicast_adr(priv, CmdPtr, - cmd_action); + ret = wlan_cmd_mac_multicast_adr(priv, CmdPtr, cmd_action); break; case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = wlan_cmd_802_11_ad_hoc_join(priv, CmdPtr, - pdata_buf); + ret = wlan_cmd_802_11_ad_hoc_join(priv, CmdPtr, pdata_buf); break; case HostCmd_CMD_802_11_RSSI: @@ -1573,116 +1692,142 @@ case HostCmd_CMD_802_11_AD_HOC_STOP: ret = wlan_cmd_802_11_ad_hoc_stop(priv, CmdPtr); break; - - case HostCmd_CMD_802_11_ENABLE_RSN: - ret = wlan_cmd_802_11_enable_rsn(priv, CmdPtr, - cmd_action); - break; - - case HostCmd_CMD_802_11_KEY_MATERIAL: ret = wlan_cmd_802_11_key_material(priv, CmdPtr, cmd_action, cmd_oid, pdata_buf); break; - case HostCmd_CMD_802_11_PAIRWISE_TSC: + case HostCmd_CMD_802_11_MAC_ADDRESS: + ret = wlan_cmd_802_11_mac_address(priv, CmdPtr, cmd_action); break; - case HostCmd_CMD_802_11_GROUP_TSC: + case HostCmd_CMD_802_11_CAL_DATA_EXT: + ret = wlan_cmd_802_11_cal_data_ext(priv, CmdPtr, pdata_buf); break; - case HostCmd_CMD_802_11_MAC_ADDRESS: - ret = wlan_cmd_802_11_mac_address(priv, - CmdPtr, cmd_action); + case HostCmd_CMD_802_11_DEEP_SLEEP: + CmdPtr->Command = wlan_cpu_to_le16(cmd_no); + CmdPtr->Size = wlan_cpu_to_le16((u16) + (sizeof + (HostCmd_DS_802_11_DEEP_SLEEP))); break; + case HostCmd_CMD_802_11_HOST_SLEEP_CFG: + ret = wlan_cmd_802_11_host_sleep_cfg(priv, CmdPtr, pdata_buf); + break; + case HostCmd_CMD_802_11_WAKEUP_CONFIRM: + case HostCmd_CMD_802_11_HOST_SLEEP_ACTIVATE: + CmdPtr->Command = wlan_cpu_to_le16(cmd_no); + CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN); + break; case HostCmd_CMD_802_11_EEPROM_ACCESS: ret = wlan_cmd_802_11_eeprom_access(priv, CmdPtr, cmd_action, pdata_buf); break; - - - case HostCmd_CMD_802_11_SET_AFC: - case HostCmd_CMD_802_11_GET_AFC: - - CmdPtr->Command = wlan_cpu_to_le16(cmd_no); - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_AFC) + S_DS_GEN); - - memmove(&CmdPtr->params.afc, - pdata_buf, - sizeof(HostCmd_DS_802_11_AFC)); - - ret = WLAN_STATUS_SUCCESS; - goto done; +#ifdef MFG_CMD_SUPPORT + case HostCmd_CMD_MFG_COMMAND: + ret = wlan_cmd_mfg_cmd(priv, CmdPtr, pdata_buf); + break; +#endif case HostCmd_CMD_802_11D_DOMAIN_INFO: - ret = wlan_cmd_802_11d_domain_info(priv, CmdPtr, - cmd_no, cmd_action ); + ret = wlan_cmd_802_11d_domain_info(priv, CmdPtr, cmd_no, cmd_action); break; - - - case HostCmd_CMD_802_11_SLEEP_PARAMS: - ret = wlan_cmd_802_11_sleep_params(priv, CmdPtr, - cmd_action); + ret = wlan_cmd_802_11_sleep_params(priv, CmdPtr, cmd_action); + break; + case HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE: + ret = wlan_cmd_802_11_bca_timeshare(priv, CmdPtr, + cmd_action, pdata_buf); break; case HostCmd_CMD_802_11_INACTIVITY_TIMEOUT: ret = wlan_cmd_802_11_inactivity_timeout(priv, CmdPtr, cmd_action, pdata_buf); - SetCmdCtrlNode(priv, CmdNode, 0, 0, pdata_buf); + break; + case HostCmd_CMD_802_11_BG_SCAN_CONFIG: + ret = wlan_cmd_802_11_bg_scan_config(priv, CmdPtr, + cmd_action, pdata_buf); break; + case HostCmd_CMD_802_11_BG_SCAN_QUERY: + ret = wlan_cmd_802_11_bg_scan_query(priv, CmdPtr); + break; + case HostCmd_CMD_802_11_FW_WAKE_METHOD: + ret = wlan_cmd_802_11_fw_wakeup_method(priv, CmdPtr, + cmd_action, pdata_buf); + break; + case HostCmd_CMD_WMM_GET_STATUS: + ret = wlan_cmd_wmm_get_status(priv, CmdPtr, pdata_buf); + break; + + case HostCmd_CMD_WMM_ADDTS_REQ: + ret = wlan_cmd_wmm_addts_req(priv, CmdPtr, pdata_buf); + break; + case HostCmd_CMD_WMM_DELTS_REQ: + ret = wlan_cmd_wmm_delts_req(priv, CmdPtr, pdata_buf); + break; + case HostCmd_CMD_WMM_QUEUE_CONFIG: + ret = wlan_cmd_wmm_queue_config(priv, CmdPtr, pdata_buf); + break; + case HostCmd_CMD_WMM_QUEUE_STATS: + ret = wlan_cmd_wmm_queue_stats(priv, CmdPtr, pdata_buf); + break; + case HostCmd_CMD_TX_PKT_STATS: + CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_TX_PKT_STATS); + CmdPtr->Size = wlan_cpu_to_le16(S_DS_GEN); + ret = WLAN_STATUS_SUCCESS; + break; case HostCmd_CMD_802_11_TPC_CFG: CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TPC_CFG); - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_TPC_CFG) + S_DS_GEN); + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_TPC_CFG) + S_DS_GEN); memmove(&CmdPtr->params.tpccfg, pdata_buf, sizeof(HostCmd_DS_802_11_TPC_CFG)); + CmdPtr->params.tpccfg.Action = + wlan_cpu_to_le16(CmdPtr->params.tpccfg.Action); ret = WLAN_STATUS_SUCCESS; break; - case HostCmd_CMD_802_11_LED_GPIO_CTRL: + case HostCmd_CMD_802_11_LED_CONTROL: { - MrvlIEtypes_LedGpio_t *gpio = (MrvlIEtypes_LedGpio_t *)CmdPtr->params.ledgpio.data; + HostCmd_DS_802_11_LED_CTRL *pLedCtrl = &CmdPtr->params.ledgpio; + MrvlIEtypes_LedGpio_t *gpio = &pLedCtrl->LedGpio; + MrvlIEtypes_LedBehavior_t *pLedBehavior = pLedCtrl->LedBehavior; memmove(&CmdPtr->params.ledgpio, - pdata_buf, - sizeof(HostCmd_DS_802_11_LED_CTRL)); + pdata_buf, sizeof(HostCmd_DS_802_11_LED_CTRL)); CmdPtr->Command = - wlan_cpu_to_le16(HostCmd_CMD_802_11_LED_GPIO_CTRL); + wlan_cpu_to_le16(HostCmd_CMD_802_11_LED_CONTROL); #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 CmdPtr->Size = wlan_cpu_to_le16(gpio->Header.Len + S_DS_GEN - + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); + + + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); + + pLedCtrl->Action = wlan_cpu_to_le16(pLedCtrl->Action); + pLedCtrl->LedNums = wlan_cpu_to_le16(pLedCtrl->LedNums); + + gpio->Header.Type = wlan_cpu_to_le16(gpio->Header.Type); gpio->Header.Len = wlan_cpu_to_le16(gpio->Header.Len); - ret = WLAN_STATUS_SUCCESS; - break; - } - case HostCmd_CMD_802_11_PWR_CFG: - CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PWR_CFG); - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_PWR_CFG) + S_DS_GEN); - memmove(&CmdPtr->params.pwrcfg, - pdata_buf, - sizeof(HostCmd_DS_802_11_PWR_CFG)); + pLedBehavior->Header.Type = + wlan_cpu_to_le16(pLedBehavior->Header.Type); + pLedBehavior->Header.Len = + wlan_cpu_to_le16(pLedBehavior->Header.Len); ret = WLAN_STATUS_SUCCESS; break; + } case HostCmd_CMD_802_11_SLEEP_PERIOD: ret = wlan_cmd_802_11_sleep_period(priv, CmdPtr, cmd_action, pdata_buf); break; - - case HostCmd_CMD_DFT_ACCESS: - ret = wlan_cmd_dft_access(priv, CmdPtr, - cmd_action, pdata_buf); - break; - case HostCmd_CMD_GET_TSF: CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF); CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_GET_TSF) @@ -1691,10 +1836,56 @@ break; case HostCmd_CMD_802_11_TX_RATE_QUERY: CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); - CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) + S_DS_GEN); + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_TX_RATE_QUERY) + S_DS_GEN); Adapter->TxRate = 0; ret = WLAN_STATUS_SUCCESS; break; + case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: + ret = + wlan_cmd_802_11_IBSS_Coalesced_Status(priv, CmdPtr, cmd_action, + pdata_buf); + break; + + case HostCmd_CMD_SDIO_PULL_CTRL: + { + HostCmd_DS_SDIO_PULL_CTRL *pSdiopullctl = + &CmdPtr->params.sdiopullctl; + + CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_SDIO_PULL_CTRL); + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_SDIO_PULL_CTRL) + + S_DS_GEN); + + memcpy(pSdiopullctl, pdata_buf, + sizeof(HostCmd_DS_SDIO_PULL_CTRL)); + pSdiopullctl->Action = wlan_cpu_to_le16(pSdiopullctl->Action); + pSdiopullctl->PullUp = wlan_cpu_to_le16(pSdiopullctl->PullUp); + pSdiopullctl->PullDown = wlan_cpu_to_le16(pSdiopullctl->PullDown); + + ret = WLAN_STATUS_SUCCESS; + break; + } + + case HostCmd_CMD_802_11_LDO_CONFIG: + CmdPtr->Command = wlan_cpu_to_le16(cmd_no); + CmdPtr->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_LDO_CONFIG) + S_DS_GEN); + memcpy(&CmdPtr->params.ldocfg, pdata_buf, + sizeof(HostCmd_DS_802_11_LDO_CONFIG)); + CmdPtr->params.ldocfg.Action = + wlan_cpu_to_le16(CmdPtr->params.ldocfg.Action); + CmdPtr->params.ldocfg.PMSource = + wlan_cpu_to_le16(CmdPtr->params.ldocfg.PMSource); + break; + + case HostCmd_CMD_VERSION_EXT: + CmdPtr->Command = wlan_cpu_to_le16(cmd_no); + memcpy(&CmdPtr->params, pdata_buf, sizeof(HostCmd_DS_VERSION_EXT)); + CmdPtr->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_VERSION_EXT) + + S_DS_GEN); + break; + default: PRINTM(INFO, "PREP_CMD: unknown command- %#x\n", cmd_no); ret = WLAN_STATUS_FAILURE; @@ -1703,30 +1894,29 @@ /* return error, since the command preparation failed */ if (ret != WLAN_STATUS_SUCCESS) { - PRINTM(INFO, "PREP_CMD: Command preparation failed\n"); + PRINTM(ERROR, "PREP_CMD: Command 0x%x preparation failed\n", cmd_no); CleanupAndInsertCmd(priv, CmdNode); ret = WLAN_STATUS_FAILURE; goto done; } - CmdNode->CmdWaitQWoken = FALSE; + PRINTM(CMND, "PREP_CMD: 0x%x\n", cmd_no); + CmdNode->CmdWaitQWoken = FALSE; QueueCmd(Adapter, CmdNode, TRUE); wake_up_interruptible(&priv->MainThread.waitQ); - sbi_reenable_host_interrupt(priv, 0x00); - if (wait_option & HostCmd_OPTION_WAITFORRSP) { - PRINTM(INFO, "PREP_CMD: Wait for CMD response\n"); - wait_event_interruptible(CmdNode->cmdwait_q, - CmdNode->CmdWaitQWoken); - } + PRINTM(INFO, "PREP_CMD: Wait for CMD response...\n"); + wait_event_interruptible(CmdNode->cmdwait_q, CmdNode->CmdWaitQWoken); if (Adapter->CurCmdRetCode) { - PRINTM(INFO, "PREP_CMD: Command failed with return code=%d\n", Adapter->CurCmdRetCode); + PRINTM(INFO, "PREP_CMD: Command failed with return code=%d\n", + Adapter->CurCmdRetCode); Adapter->CurCmdRetCode = 0; ret = WLAN_STATUS_FAILURE; } + } done: LEAVE(); @@ -1740,7 +1930,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int AllocateCmdBuffer(wlan_private * priv) +int +AllocateCmdBuffer(wlan_private * priv) { int ret = WLAN_STATUS_SUCCESS; u32 ulBufSize; @@ -1795,7 +1986,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int FreeCmdBuffer(wlan_private * priv) +int +FreeCmdBuffer(wlan_private * priv) { u32 ulBufSize; UINT i; @@ -1841,7 +2033,8 @@ * @param priv A pointer to wlan_private structure * @return CmdCtrlNode A pointer to CmdCtrlNode structure or NULL */ -CmdCtrlNode *GetFreeCmdCtrlNode(wlan_private * priv) +CmdCtrlNode * +GetFreeCmdCtrlNode(wlan_private * priv) { CmdCtrlNode *TempNode; wlan_adapter *Adapter = priv->adapter; @@ -1858,15 +2051,13 @@ TempNode = (CmdCtrlNode *)Adapter->CmdFreeQ.next; list_del((struct list_head *)TempNode); } else { - PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode is not available\n"); + PRINTM(WARN, "GET_CMD_NODE: CmdCtrlNode is not available\n"); TempNode = NULL; } spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); if (TempNode) { - PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode available\n"); - PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode Address = %p\n", TempNode); CleanUpCmdCtrlNode(TempNode); } @@ -1880,7 +2071,8 @@ * @param pTempNode A pointer to CmdCtrlNode structure * @return n/a */ -void CleanUpCmdCtrlNode(CmdCtrlNode * pTempNode) +void +CleanUpCmdCtrlNode(CmdCtrlNode * pTempNode) { ENTER(); @@ -1891,6 +2083,7 @@ pTempNode->Status = 0; pTempNode->cmd_oid = (WLAN_OID) 0; pTempNode->wait_option = 0; + pTempNode->CmdFlags = 0; pTempNode->pdata_buf = NULL; if (pTempNode->BufVirtualAddr != NULL) @@ -1910,11 +2103,10 @@ * @param pdata_buf A pointer to informaion buffer * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -void SetCmdCtrlNode(wlan_private * priv, +void +SetCmdCtrlNode(wlan_private * priv, CmdCtrlNode * pTempNode, - WLAN_OID cmd_oid, - u16 wait_option, - void *pdata_buf) + WLAN_OID cmd_oid, u16 wait_option, void *pdata_buf) { ENTER(); @@ -1936,7 +2128,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int ExecuteNextCommand(wlan_private * priv) +int +ExecuteNextCommand(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; CmdCtrlNode *CmdNode = NULL; @@ -1952,7 +2145,6 @@ goto done; } - spin_lock_irqsave(&Adapter->QueueSpinLock, flags); if (Adapter->CurCmd) { @@ -1970,21 +2162,20 @@ spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); if (CmdNode) { - PRINTM(INFO, "EXEC_NEXT_CMD: Got next command from CmdPendingQ\n"); CmdPtr = (HostCmd_DS_COMMAND *) CmdNode->BufVirtualAddr; if (Is_Command_Allowed_In_PS(CmdPtr->Command)) { if ((Adapter->PSState == PS_STATE_SLEEP) || (Adapter->PSState == PS_STATE_PRE_SLEEP) ) { - PRINTM(INFO, "EXEC_NEXT_CMD: Cannot send cmd 0x%x in PSState %d\n", + PRINTM(INFO, + "EXEC_NEXT_CMD: Cannot send cmd 0x%x in PSState %d\n", CmdPtr->Command, Adapter->PSState); ret = WLAN_STATUS_FAILURE; goto done; } PRINTM(INFO, "EXEC_NEXT_CMD: OK to send command " - "0x%x in PSState %d\n", - CmdPtr->Command,Adapter->PSState); + "0x%x in PSState %d\n", CmdPtr->Command, Adapter->PSState); } else if (Adapter->PSState != PS_STATE_FULL_POWER) { /* * 1. Non-PS command: @@ -1997,7 +2188,8 @@ * otherwise send this command down to firmware * immediately. */ - if (CmdPtr->Command != wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE)) { + if (CmdPtr->Command != + wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE)) { /* Prepare to send Exit PS, * this non PS command will be sent later */ if ((Adapter->PSState == PS_STATE_SLEEP) @@ -2006,8 +2198,7 @@ /* w/ new scheme, it will not reach here. since it is blocked in main_thread. */ Adapter->NeedToWakeup = TRUE; - } - else + } else PSWakeup(priv, 0); ret = WLAN_STATUS_SUCCESS; @@ -2017,10 +2208,10 @@ * PS command. Ignore it if it is not Exit_PS. * otherwise send it down immediately. */ - HostCmd_DS_802_11_PS_MODE *psm = - &CmdPtr->params.psmode; + HostCmd_DS_802_11_PS_MODE *psm = &CmdPtr->params.psmode; - PRINTM(INFO, "EXEC_NEXT_CMD: PS cmd- Action=0x%x\n",psm->Action); + PRINTM(INFO, "EXEC_NEXT_CMD: PS cmd- Action=0x%x\n", + psm->Action); if (psm->Action != wlan_cpu_to_le16(HostCmd_SubCmd_Exit_PS)) { PRINTM(INFO, "EXEC_NEXT_CMD: Ignore Enter PS cmd\n"); list_del((struct list_head *) CmdNode); @@ -2033,7 +2224,8 @@ if ((Adapter->PSState == PS_STATE_SLEEP) || (Adapter->PSState == PS_STATE_PRE_SLEEP) ) { - PRINTM(INFO, "EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n"); + PRINTM(INFO, + "EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n"); list_del((struct list_head *) CmdNode); CleanupAndInsertCmd(priv,CmdNode); Adapter->NeedToWakeup = TRUE; @@ -2046,34 +2238,58 @@ } } list_del((struct list_head *) CmdNode); - PRINTM(INFO, "EXEC_NEXT_CMD: Sending 0x%04X Command\n", CmdPtr->Command); DownloadCommandToStation(priv, CmdNode); - } - else { + } else { + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { /* * check if in power save mode, if yes, put the device back * to PS mode */ if ((Adapter->PSMode != Wlan802_11PowerModeCAM) && - (Adapter->PSState == PS_STATE_FULL_POWER) && - (Adapter->MediaConnectStatus == - WlanMediaStateConnected)) { + (Adapter->PSState == PS_STATE_FULL_POWER)) { if(Adapter->SecInfo.WPAEnabled - || Adapter->SecInfo.WPA2Enabled - ) { + || Adapter->SecInfo.WPA2Enabled) { if(Adapter->IsGTK_SET) { PRINTM(INFO, "EXEC_NEXT_CMD: WPA enabled and GTK_SET" " go back to PS_SLEEP"); PSSleep(priv, 0); } - } else - { + } else { + if ((Adapter->InfrastructureMode != Wlan802_11IBSS) + || Adapter->CurBssParams.BSSDescriptor.ATIMWindow) { PRINTM(INFO, "EXEC_NEXT_CMD: Command PendQ is empty," " go back to PS_SLEEP"); PSSleep(priv, 0); } } } + } else { + /* + * check if in auto deep sleep mode, if yes, put the device back + * to DS mode + */ + if (Adapter->IsAutoDeepSleepEnabled && !Adapter->IntCounter) { + PRINTM(INFO, "Entering Auto Deep Sleep mode...\n"); + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_DEEP_SLEEP, 0, + 0, 0, NULL); + } + } + /* The hs_activate command is sent when Host Sleep is configured + and de-activated in full power mode. */ + if (Adapter->bHostSleepConfigured && !Adapter->HS_Activated + && ((Adapter->MediaConnectStatus == WlanMediaStateConnected) + || (!Adapter->IsAutoDeepSleepEnabled)) + && (((Adapter->PSMode == Wlan802_11PowerModeCAM) + && (Adapter->PSState == PS_STATE_FULL_POWER)) + || ((Adapter->InfrastructureMode == Wlan802_11IBSS) + && !Adapter->CurBssParams.BSSDescriptor.ATIMWindow) + )) { + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_HOST_SLEEP_ACTIVATE, + 0, 0, 0, NULL); + } + } ret = WLAN_STATUS_SUCCESS; done: @@ -2081,44 +2297,68 @@ return ret; } - -#if WIRELESS_EXT > 14 /** - * @brief This function sends customized event to application. + * @brief This function handles the timeout of command sending. + * It will re-send the same command again. * - * @param priv A pointer to wlan_private structure - * @para str A pointer to event string + * @param FunctionContext A pointer to FunctionContext * @return n/a */ -void send_iwevcustom_event(wlan_private *priv, s8 *str) +void +MrvDrvCommandTimerFunction(void *FunctionContext) { - union iwreq_data iwrq; - u8 buf[50]; + wlan_private *priv = (wlan_private *) FunctionContext; + wlan_adapter *Adapter = priv->adapter; + CmdCtrlNode *pTempNode; + HostCmd_DS_COMMAND *CmdPtr; ENTER(); - memset(&iwrq, 0, sizeof(union iwreq_data)); - memset(buf, 0, sizeof(buf)); + PRINTM(CMND, "Command timeout.\n"); - snprintf(buf, sizeof(buf) - 1, "%s", str); + Adapter->CommandTimerIsSet = FALSE; - iwrq.data.pointer = buf; - iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; + if (!Adapter->num_cmd_timeout) + Adapter->dbg.num_cmd_timeout++; - /* Send Event to upper layer */ - PRINTM(INFO, "Event Indication string = %s\n", (char *)iwrq.data.pointer); - PRINTM(INFO, "Event Indication String Length = %d\n", iwrq.data.length); + pTempNode = Adapter->CurCmd; - PRINTM(INFO, "Sending wireless event IWEVCUSTOM for %s\n", str); - wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf); + if (pTempNode == NULL) { + PRINTM(INFO, "CurCmd Empty\n"); + goto exit; + } - LEAVE(); - return; + CmdPtr = (HostCmd_DS_COMMAND *) pTempNode->BufVirtualAddr; + if (CmdPtr == NULL) { + goto exit; } -#endif + if (CmdPtr->Size) { + Adapter->dbg.TimeoutCmdId = wlan_cpu_to_le16(CmdPtr->Command); + Adapter->dbg.TimeoutCmdAct = + wlan_cpu_to_le16(*(u16 *) ((u8 *) CmdPtr + S_DS_GEN)); + PRINTM(CMND, "Timeout cmd = 0x%x, act = 0x%x\n", + Adapter->dbg.TimeoutCmdId, Adapter->dbg.TimeoutCmdAct); + } +#define MAX_CMD_TIMEOUT_COUNT 5 + Adapter->num_cmd_timeout++; + if (Adapter->num_cmd_timeout > MAX_CMD_TIMEOUT_COUNT) { + PRINTM(FATAL, "num_cmd_timeout=%d\n", Adapter->num_cmd_timeout); + goto exit; + } + + /* Restart the timer to trace command response again */ + ModTimer(&Adapter->MrvDrvCommandTimer, MRVDRV_TIMER_1S); + Adapter->CommandTimerIsSet = TRUE; + /* Wake up main thread to read int status register */ + Adapter->IntCounter++; + wake_up_interruptible(&priv->MainThread.waitQ); + exit: + LEAVE(); + return; +} /** * @brief This function sends sleep confirm command to firmware. @@ -2128,38 +2368,46 @@ * @param size the size of command * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int SendConfirmSleep(wlan_private * priv, u8 * CmdPtr, u16 size) +int +SendConfirmSleep(wlan_private * priv, u8 * CmdPtr, u16 size) { wlan_adapter *Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; + static u32 i = 0; ENTER(); - PRINTM(INFO, "SEND_SLEEPC_CMD: Before download, Size of cmd = %d\n", size); - - HEXDUMP("SEND_SLEEPC_CMD: Sleep confirm Command", CmdPtr, size); + HEXDUMP("SLEEP_CFM", CmdPtr, size); ret = sbi_host_to_card(priv, MVMS_CMD, CmdPtr, size); priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; - if(Adapter->IntCounter || Adapter->CurrentTxSkb) - PRINTM(INFO, "SEND_SLEEPC_CMD: IntCounter=%d CurrentTxSkb=%p\n", - Adapter->IntCounter,Adapter->CurrentTxSkb); if (ret) { - PRINTM(MSG, "SEND_SLEEPC_CMD: Host to Card Failed for Confirm Sleep\n"); + PRINTM(MSG, "SLEEP_CFM: sbi_host_to_card() failed\n"); + Adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; } else { - OS_INT_DISABLE; - if(!Adapter->IntCounter) { + sdio_clear_imask(((mmc_card_t) ((priv->wlan_dev).card))->ctrlr); Adapter->PSState = PS_STATE_SLEEP; + if (Adapter->bHostSleepConfigured && + (Adapter->sleep_period.period == 0)) { + Adapter->bWakeupDevRequired = TRUE; +#define SDIO_CLK_300KHZ 300 + sd_set_clock(priv, SDIO_CLK_300KHZ); /* set the clock to the lowest frequency */ + wlan_host_sleep_activated_event(priv); } - else { - PRINTM(INFO, "SEND_SLEEPC_CMD: After sent,IntC=%d\n", Adapter->IntCounter); +#define NUM_SC_PER_LINE 16 + if (++i % NUM_SC_PER_LINE == 0) { + PRINTM(EVENT, "+\n"); + } else { + PRINTM(EVENT, "+"); } - OS_INT_RESTORE; - - PRINTM(INFO, "SEND_SLEEPC_CMD: Sent Confirm Sleep command\n"); - PRINTM(INFO, "+"); + /* check if interrupt is received after sleep confirm */ + if (Adapter->IntCounter) { + PRINTM(INFO, "SLEEP_CFM: After sent, IntCnt=%d\n", + Adapter->IntCounter); + Adapter->PSState = PS_STATE_AWAKE; + } } LEAVE(); @@ -2173,19 +2421,14 @@ * @param wait_option wait response or not * @return n/a */ -void PSSleep(wlan_private *priv, int wait_option) +void +PSSleep(wlan_private * priv, int wait_option) { ENTER(); - /* - * PS is currently supported only in Infrastructure Mode - * Remove this check if it is to be supported in IBSS mode also - */ - PrepareAndSendCommand(priv, HostCmd_CMD_802_11_PS_MODE, - HostCmd_SubCmd_Enter_PS, - wait_option, 0, NULL); + HostCmd_SubCmd_Enter_PS, wait_option, 0, NULL); LEAVE(); return; @@ -2198,7 +2441,8 @@ * @param wait_option wait response or not * @return n/a */ -void PSWakeup(wlan_private *priv, int wait_option) +void +PSWakeup(wlan_private * priv, int wait_option) { WLAN_802_11_POWER_MODE LocalPSMode; @@ -2206,8 +2450,6 @@ LocalPSMode = Wlan802_11PowerModeCAM; - PRINTM(INFO, "Exit_PS: LocalPSMode = %d\n", LocalPSMode); - PrepareAndSendCommand(priv, HostCmd_CMD_802_11_PS_MODE, HostCmd_SubCmd_Exit_PS, wait_option, 0, &LocalPSMode); @@ -2224,33 +2466,23 @@ * @param PSMode Power Saving mode * @return n/a */ -void PSConfirmSleep(wlan_private * priv, u16 PSMode) +void +PSConfirmSleep(wlan_private * priv, u16 PSMode) { wlan_adapter *Adapter = priv->adapter; - BOOLEAN allowed = TRUE; ENTER(); - if(priv->wlan_dev.dnld_sent) { - allowed = FALSE; - PRINTM(INFO, "D"); - } - else if(Adapter->CurCmd) { - allowed = FALSE; - PRINTM(INFO, "C"); - } - else if(Adapter->IntCounter > 0) { - allowed = FALSE; - PRINTM(INFO, "I%d",Adapter->IntCounter); - } - - if(allowed) { - PRINTM(INFO, "Sending PSConfirmSleep\n"); + if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd && !Adapter->IntCounter) { SendConfirmSleep(priv, (u8 *) &Adapter->PSConfirmSleep, sizeof(PS_CMD_ConfirmSleep)); - } - else { - PRINTM(INFO, "Sleep Confirm has been delayed\n"); + + os_start_queue(priv); + } else { + PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n", + (priv->wlan_dev.dnld_sent) ? "D" : "", + (Adapter->CurCmd) ? "C" : "", + (Adapter->IntCounter) ? "I" : ""); } LEAVE(); diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_cmdresp.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_cmdresp.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_cmdresp.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_cmdresp.c 2007-11-06 12:26:40.000000000 -0500 @@ -2,14 +2,13 @@ * @brief This file contains the handling of command * responses as well as events generated by firmware. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -33,7 +32,10 @@ 04/10/06: Add hostcmd generic API 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API - 05/08/06: Remove Adapter->PermanentAddr memcpy + 05/04/06: Add IBSS coalescing related new hostcmd response handling + 05/08/06: Remove PermanentAddr from Adapter + 06/08/06: Remove function HandleMICFailureEvent() + 08/29/06: Add ledgpio private command ********************************************************/ #include "include.h" @@ -46,7 +48,6 @@ Global Variables ********************************************************/ - /******************************************************** Local Functions ********************************************************/ @@ -59,7 +60,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -void MacEventDisconnected(wlan_private * priv) +void +MacEventDisconnected(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; union iwreq_data wrqu; @@ -71,25 +73,13 @@ PRINTM(INFO, "Handles disconnect event.\n"); + /* Free Tx and Rx packets, report disconnect to upper layer */ + wlan_clean_txrx(priv); + memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - /* - * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. - * It causes problem in the Supplicant - */ - - os_sched_timeout(1000); - wireless_send_event(priv->wlan_dev.netdev, - SIOCGIWAP, &wrqu, NULL); - - /* Free Tx and Rx packets */ - os_free_tx_packet(priv); - wlan_send_rxskbQ(priv); - - /* report disconnect to upper layer */ - os_stop_queue(priv); - os_carrier_off(priv); + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); /* reset SNR/NF/RSSI values */ memset(Adapter->SNR, 0x00, sizeof(Adapter->SNR)); @@ -101,43 +91,32 @@ Adapter->numSNRNF = 0; Adapter->RxPDRate = 0; PRINTM(INFO, "Current SSID=%s, Ssid Length=%u\n", - Adapter->CurBssParams.ssid.Ssid, - Adapter->CurBssParams.ssid.SsidLength); + Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid, + Adapter->CurBssParams.BSSDescriptor.Ssid.SsidLength); PRINTM(INFO, "Previous SSID=%s, Ssid Length=%u\n", - Adapter->PreviousSSID.Ssid, - Adapter->PreviousSSID.SsidLength); - - /* reset internal flags */ - Adapter->AdHocCreated = FALSE; - - cleanup_txqueues(priv); + Adapter->PreviousSSID.Ssid, Adapter->PreviousSSID.SsidLength); Adapter->SecInfo.WPAEnabled = FALSE; Adapter->SecInfo.WPA2Enabled = FALSE; Adapter->Wpa_ie_len = 0; - Adapter->SecInfo.Auth1XAlg = WLAN_1X_AUTH_ALG_NONE; Adapter->SecInfo.EncryptionMode = CIPHER_NONE; - Adapter->MediaConnectStatus = WlanMediaStateDisconnected; - Adapter->LinkSpeed = MRVDRV_LINK_SPEED_1mbps; + Adapter->AdhocLinkSensed = FALSE; /* * memorize the previous SSID and BSSID * it could be used for re-assoc */ memcpy(&Adapter->PreviousSSID, - &Adapter->CurBssParams.ssid, + &Adapter->CurBssParams.BSSDescriptor.Ssid, sizeof(WLAN_802_11_SSID)); memcpy(Adapter->PreviousBSSID, - Adapter->CurBssParams.bssid, - MRVDRV_ETH_ADDR_LEN); + Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); /* need to erase the current SSID and BSSID info */ - Adapter->pAttemptedBSSDesc = 0; - memset(&Adapter->CurBssParams, 0, sizeof(Adapter->CurBssParams)); - + memset(&Adapter->CurBssParams, 0x00, sizeof(Adapter->CurBssParams)); if (Adapter->PSState != PS_STATE_FULL_POWER) { /* make firmware to exit PS mode */ @@ -155,7 +134,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -static void HandleDisconnectEvent(wlan_private * priv) +static void +HandleDisconnectEvent(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; @@ -166,7 +146,7 @@ #ifdef REASSOCIATION if (Adapter->Reassoc_on == TRUE ) { PRINTM(INFO, "RE-ASSOC: trigger the timer\n"); - Adapter->TimerIsSet = TRUE; + Adapter->ReassocTimerIsSet = TRUE; ModTimer(&Adapter->MrvDrvTimer, 0); } #endif /* REASSOCIATION */ @@ -174,34 +154,6 @@ } /** - * @brief This function handles MIC failure event. - * - * @param priv A pointer to wlan_private structure - * @para event the event id - * @return n/a - */ -static void HandleMICFailureEvent(wlan_private *priv, u32 event) -{ - u8 buf[50]; - - ENTER(); - - memset(buf, 0, sizeof(buf)); - - sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); - - if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { - strcat(buf, "unicast "); - } else { - strcat(buf, "multicast "); - } - - send_iwevcustom_event(priv, buf); - - LEAVE(); -} - -/** * @brief This function handles the command response of reg_access * * @param priv A pointer to wlan_private structure @@ -209,11 +161,12 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_reg_access(wlan_private * priv, - u16 type, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_reg_access(wlan_private * priv, u16 type, HostCmd_DS_COMMAND * resp) { wlan_adapter *Adapter = priv->adapter; + wlan_offset_value *pOffsetValue = + (wlan_offset_value *) Adapter->CurCmd->pdata_buf; ENTER(); @@ -222,33 +175,30 @@ { HostCmd_DS_MAC_REG_ACCESS *reg; - reg = (PHostCmd_DS_MAC_REG_ACCESS) & - resp->params.macreg; + reg = (HostCmd_DS_MAC_REG_ACCESS *) & resp->params.macreg; - Adapter->OffsetValue.offset = reg->Offset; - Adapter->OffsetValue.value = reg->Value; + pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset); + pOffsetValue->value = wlan_le32_to_cpu(reg->Value); break; } case HostCmd_RET_BBP_REG_ACCESS: { HostCmd_DS_BBP_REG_ACCESS *reg; - reg = (PHostCmd_DS_BBP_REG_ACCESS) & - resp->params.bbpreg; + reg = (HostCmd_DS_BBP_REG_ACCESS *) & resp->params.bbpreg; - Adapter->OffsetValue.offset = reg->Offset; - Adapter->OffsetValue.value = reg->Value; + pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset); + pOffsetValue->value = (u8) reg->Value; break; } case HostCmd_RET_RF_REG_ACCESS: { HostCmd_DS_RF_REG_ACCESS *reg; - reg = (PHostCmd_DS_RF_REG_ACCESS) & - resp->params.rfreg; + reg = (HostCmd_DS_RF_REG_ACCESS *) & resp->params.rfreg; - Adapter->OffsetValue.offset = reg->Offset; - Adapter->OffsetValue.value = reg->Value; + pOffsetValue->offset = wlan_le16_to_cpu(reg->Offset); + pOffsetValue->value = (u8) reg->Value; break; } @@ -268,8 +218,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_get_hw_spec(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_get_hw_spec(wlan_private * priv, HostCmd_DS_COMMAND * resp) { u32 i; HostCmd_DS_GET_HW_SPEC *hwspec = &resp->params.hwspec; @@ -278,26 +228,25 @@ ENTER(); - Adapter->HardwareStatus = WlanHardwareStatusReady; Adapter->fwCapInfo = wlan_le32_to_cpu(hwspec->fwCapInfo); + Adapter->FWReleaseNumber = wlan_le32_to_cpu(hwspec->FWReleaseNumber); - Adapter->FWReleaseNumber = hwspec->FWReleaseNumber; - - PRINTM(INFO, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n", Adapter->FWReleaseNumber); + PRINTM(INFO, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n", + Adapter->FWReleaseNumber); PRINTM(INFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n", hwspec->PermanentAddr[0], hwspec->PermanentAddr[1], hwspec->PermanentAddr[2], hwspec->PermanentAddr[3], hwspec->PermanentAddr[4], hwspec->PermanentAddr[5]); - PRINTM(INFO, "GET_HW_SPEC: HWIfVersion=0x%X Version=0x%X\n",hwspec->HWIfVersion, - hwspec->Version); + PRINTM(INFO, "GET_HW_SPEC: HWIfVersion=0x%X Version=0x%X\n", + wlan_le16_to_cpu(hwspec->HWIfVersion), + wlan_le16_to_cpu(hwspec->Version)); Adapter->RegionCode = wlan_le16_to_cpu(hwspec->RegionCode); for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { /* use the region code to search for the index */ if (Adapter->RegionCode == RegionCodeToIndex[i]) { - Adapter->RegionTableIndex = (u16) i; break; } } @@ -305,13 +254,11 @@ /* if it's unidentified region code, use the default (USA) */ if (i >= MRVDRV_MAX_REGION_CODE) { Adapter->RegionCode = 0x10; - Adapter->RegionTableIndex = 0; PRINTM(WARN, "unidentified region code, use the default (USA)\n"); } if (Adapter->CurrentAddr[0] == 0xff) { - memmove(Adapter->CurrentAddr, hwspec->PermanentAddr, - MRVDRV_ETH_ADDR_LEN); + memmove(Adapter->CurrentAddr, hwspec->PermanentAddr, ETH_ALEN); } memcpy(priv->wlan_dev.netdev->dev_addr, Adapter->CurrentAddr, ETH_ALEN); @@ -325,12 +272,73 @@ goto done; } - done: LEAVE(); return ret; } +/** + * @brief This function handles the command response of host_sleep_cfg + * + * @param priv A pointer to wlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_ret_host_sleep_cfg(wlan_private * priv, HostCmd_DS_COMMAND * resp) +{ + wlan_adapter *Adapter = priv->adapter; + HostCmd_DS_802_11_HOST_SLEEP_CFG *hscfg = &resp->params.hostsleepcfg; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (hscfg->conditions != HOST_SLEEP_CFG_CANCEL) { + Adapter->bHostSleepConfigured = TRUE; + } else { + Adapter->bHostSleepConfigured = FALSE; + if (Adapter->PSState == PS_STATE_FULL_POWER && Adapter->HS_Activated) { + wlan_host_sleep_deactivated_event(priv); + } + os_start_queue(priv); + os_carrier_on(priv); + wmm_start_queue(priv); + } + + LEAVE(); + return ret; +} + +/** + * @brief This function handles the command response of fw_wakeup_method + * + * @param priv A pointer to wlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_ret_fw_wakeup_method(wlan_private * priv, HostCmd_DS_COMMAND * resp) +{ + wlan_adapter *Adapter = priv->adapter; + HostCmd_DS_802_11_FW_WAKEUP_METHOD *fwwm = &resp->params.fwwakeupmethod; + u16 action; + + ENTER(); + + action = wlan_le16_to_cpu(fwwm->Action); + + switch (action) { + case HostCmd_ACT_GET: + case HostCmd_ACT_SET: + Adapter->fwWakeupMethod = wlan_le16_to_cpu(fwwm->Method); + break; + default: + break; + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief This function handles the command response of sleep_params @@ -339,8 +347,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_sleep_params(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_sleep_params(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_SLEEP_PARAMS *sp = &resp->params.sleep_params; wlan_adapter *Adapter = priv->adapter; @@ -368,8 +376,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_sleep_period(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_sleep_period(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_SLEEP_PERIOD *sp_period = &resp->params.ps_sleeppd; wlan_adapter *Adapter = priv->adapter; @@ -382,68 +390,72 @@ return WLAN_STATUS_SUCCESS; } - /** - * @brief This function handles the command response of mac_control + * @brief This function handles the command response of bca_timeshare * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_mac_control(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_bca_timeshare(wlan_private * priv, HostCmd_DS_COMMAND * resp) { + HostCmd_DS_802_11_BCA_TIMESHARE *bca_ts = &resp->params.bca_timeshare; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + PRINTM(MSG, "TrafficType=%x TimeShareInterva=%x BTTime=%x\n", + bca_ts->TrafficType, bca_ts->TimeShareInterval, bca_ts->BTTime); + + Adapter->bca_ts.TrafficType = wlan_le16_to_cpu(bca_ts->TrafficType); + Adapter->bca_ts.TimeShareInterval = + wlan_le32_to_cpu(bca_ts->TimeShareInterval); + Adapter->bca_ts.BTTime = wlan_le32_to_cpu(bca_ts->BTTime); + + LEAVE(); return WLAN_STATUS_SUCCESS; } - /** - * @brief This function handles the command response of set_wep + * @brief This function handles the command response of mac_control * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_set_wep(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_mac_control(wlan_private * priv, HostCmd_DS_COMMAND * resp) { return WLAN_STATUS_SUCCESS; } - /** - * @brief This function handles the command response of reset + * @brief This function handles the command response of set_wep * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_reset(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_set_wep(wlan_private * priv, HostCmd_DS_COMMAND * resp) { - ENTER(); - PRINTM(INFO, "HWAC - Reset command successful\n"); - return WLAN_STATUS_SUCCESS; } - /** - * @brief This function handles the command response of statistics + * @brief This function handles the command response of reset * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_stat(wlan_private * priv, HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_reset(wlan_private * priv, HostCmd_DS_COMMAND * resp) { - HostCmd_DS_802_11_GET_STAT *p11Stat = &resp->params.gstat; - wlan_adapter *Adapter = priv->adapter; + ENTER(); + PRINTM(INFO, "HWAC - Reset command successful\n"); - /* TODO Convert it to Big endian befor copy */ - memcpy(&Adapter->wlan802_11Stat, - p11Stat, - sizeof(HostCmd_DS_802_11_GET_STAT)); return WLAN_STATUS_SUCCESS; } @@ -454,8 +466,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_snmp_mib(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_snmp_mib(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_SNMP_MIB *smib = &resp->params.smib; u16 OID = wlan_le16_to_cpu(smib->OID); @@ -463,22 +475,29 @@ ENTER(); - PRINTM(INFO, "SNMP_RESP: value of the OID = %x, QueryType=%x\n", OID,QueryType); - PRINTM(INFO, "SNMP_RESP: Buf size = %x\n", wlan_le16_to_cpu(smib->BufSize)); + PRINTM(INFO, "SNMP_RESP: value of the OID = %x, QueryType=%x\n", OID, + QueryType); + PRINTM(INFO, "SNMP_RESP: Buf size = %x\n", + wlan_le16_to_cpu(smib->BufSize)); if(QueryType == HostCmd_ACT_GEN_GET){ switch(OID){ case FragThresh_i: - priv->adapter->FragThsd = wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); - PRINTM(INFO, "SNMP_RESP: FragThsd =%u\n", priv->adapter->FragThsd); + priv->adapter->FragThsd = + wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); + PRINTM(INFO, "SNMP_RESP: FragThsd =%u\n", + priv->adapter->FragThsd); break; case RtsThresh_i: - priv->adapter->RTSThsd = wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); + priv->adapter->RTSThsd = + wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); PRINTM(INFO, "SNMP_RESP: RTSThsd =%u\n", priv->adapter->RTSThsd); break; case ShortRetryLim_i: - priv->adapter->TxRetryCount = wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); - PRINTM(INFO, "SNMP_RESP: TxRetryCount =%u\n", priv->adapter->RTSThsd); + priv->adapter->TxRetryCount = + wlan_le16_to_cpu(*((PUSHORT) (smib->Value))); + PRINTM(INFO, "SNMP_RESP: TxRetryCount =%u\n", + priv->adapter->RTSThsd); break; default: break; @@ -496,8 +515,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_radio_control(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_radio_control(wlan_private * priv, HostCmd_DS_COMMAND * resp) { ENTER(); @@ -512,16 +531,23 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_key_material(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_key_material(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_KEY_MATERIAL *pKey = &resp->params.keymaterial; wlan_adapter *Adapter = priv->adapter; ENTER(); - if (pKey->Action == HostCmd_ACT_SET) + if (wlan_le16_to_cpu(pKey->Action) == HostCmd_ACT_SET) { + if ((wlan_le16_to_cpu(pKey->KeyParamSet.KeyInfo) & + KEY_INFO_TKIP_MCAST) + || (wlan_le16_to_cpu(pKey->KeyParamSet.KeyInfo) & + KEY_INFO_AES_MCAST)) { + PRINTM(INFO, "Key: GTK is set\n"); Adapter->IsGTK_SET = TRUE; + } + } memcpy(Adapter->aeskey.KeyParamSet.Key, pKey->KeyParamSet.Key, sizeof(pKey->KeyParamSet.Key)); @@ -537,8 +563,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_mac_address(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_mac_address(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_MAC_ADDRESS *MacAdd = &resp->params.macadd; wlan_adapter *Adapter = priv->adapter; @@ -558,17 +584,25 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_rf_tx_power(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_rf_tx_power(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp; wlan_adapter *Adapter = priv->adapter; + u16 Action = wlan_le16_to_cpu(rtp->Action); ENTER(); Adapter->TxPowerLevel = wlan_le16_to_cpu(rtp->CurrentLevel); - PRINTM(INFO, "Current TxPower Level = %d\n", Adapter->TxPowerLevel); + if (Action == HostCmd_ACT_GET) { + Adapter->MaxTxPowerLevel = rtp->MaxPower; + Adapter->MinTxPowerLevel = rtp->MinPower; + } + + PRINTM(INFO, "Current TxPower Level = %d,Max Power=%d, Min Power=%d\n", + Adapter->TxPowerLevel, Adapter->MaxTxPowerLevel, + Adapter->MinTxPowerLevel); LEAVE(); return WLAN_STATUS_SUCCESS; @@ -581,10 +615,10 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_rf_antenna(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_rf_antenna(wlan_private * priv, HostCmd_DS_COMMAND * resp) { - PHostCmd_DS_802_11_RF_ANTENNA pAntenna = &resp->params.rant; + HostCmd_DS_802_11_RF_ANTENNA *pAntenna = &resp->params.rant; wlan_adapter *Adapter = priv->adapter; u16 Action = wlan_le16_to_cpu(pAntenna->Action); @@ -607,8 +641,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_mac_multicast_adr(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_mac_multicast_adr(wlan_private * priv, HostCmd_DS_COMMAND * resp) { return WLAN_STATUS_SUCCESS; } @@ -620,18 +654,20 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_rate_adapt_rateset(wlan_private *priv, +static int +wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv, HostCmd_DS_COMMAND *resp) { - HostCmd_DS_802_11_RATE_ADAPT_RATESET *rates = - &resp->params.rateset; + HostCmd_DS_802_11_RATE_ADAPT_RATESET *rates = &resp->params.rateset; wlan_adapter *Adapter = priv->adapter; ENTER(); - if (rates->Action == HostCmd_ACT_GET) { - Adapter->EnableHwAuto = rates->EnableHwAuto; - Adapter->RateBitmap = rates->Bitmap; + if (wlan_le16_to_cpu(rates->Action) == HostCmd_ACT_GET) { + Adapter->HWRateDropMode = wlan_le16_to_cpu(rates->HWRateDropMode); + Adapter->Threshold = wlan_le16_to_cpu(rates->Threshold); + Adapter->FinalRate = wlan_le16_to_cpu(rates->FinalRate); + Adapter->RateBitmap = wlan_le16_to_cpu(rates->Bitmap); } LEAVE(); @@ -640,45 +676,14 @@ } /** - * @brief This function handles the command response of data_rate - * - * @param priv A pointer to wlan_private structure - * @param resp A pointer to HostCmd_DS_COMMAND - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -static int wlan_ret_802_11_data_rate(wlan_private * priv, - HostCmd_DS_COMMAND * resp) -{ - HostCmd_DS_802_11_DATA_RATE *pDataRate = &resp->params.drate; - wlan_adapter *Adapter = priv->adapter; - u8 Dot11DataRate; - - ENTER(); - - HEXDUMP("DATA_RATE_RESP: data_rate- ", - (u8 *)pDataRate,sizeof(HostCmd_DS_802_11_DATA_RATE)); - - Dot11DataRate = pDataRate->DataRate[0]; - if (pDataRate->Action == HostCmd_ACT_GET_TX_RATE) - { - memcpy(Adapter->SupportedRates, pDataRate->DataRate, - sizeof(Adapter->SupportedRates)); - } - Adapter->DataRate = index_to_data_rate(Dot11DataRate); - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** * @brief This function handles the command response of rf_channel * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_rf_channel(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_rf_channel(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_RF_CHANNEL *rfchannel = &resp->params.rfchannel; wlan_adapter *Adapter = priv->adapter; @@ -688,14 +693,12 @@ ENTER(); if (Action == HostCmd_OPT_802_11_RF_CHANNEL_GET - && Adapter->CurBssParams.channel != newChannel) - { + && Adapter->CurBssParams.BSSDescriptor.Channel != newChannel) { PRINTM(INFO, "Channel Switch: %d to %d\n", - Adapter->CurBssParams.channel, newChannel); - + Adapter->CurBssParams.BSSDescriptor.Channel, newChannel); /* Update the channel again */ - Adapter->CurBssParams.channel = newChannel; + Adapter->CurBssParams.BSSDescriptor.Channel = newChannel; } LEAVE(); @@ -709,18 +712,20 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_802_11_rssi(wlan_private * priv, - HostCmd_DS_COMMAND * resp) +static int +wlan_ret_802_11_rssi(wlan_private * priv, HostCmd_DS_COMMAND * resp) { HostCmd_DS_802_11_RSSI_RSP *rssirsp = &resp->params.rssirsp; wlan_adapter *Adapter = priv->adapter; /* store the non average value */ Adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = wlan_le16_to_cpu(rssirsp->SNR); - Adapter->NF[TYPE_BEACON][TYPE_NOAVG] = wlan_le16_to_cpu(rssirsp->NoiseFloor); + Adapter->NF[TYPE_BEACON][TYPE_NOAVG] = + wlan_le16_to_cpu(rssirsp->NoiseFloor); Adapter->SNR[TYPE_BEACON][TYPE_AVG] = wlan_le16_to_cpu(rssirsp->AvgSNR); - Adapter->NF[TYPE_BEACON][TYPE_AVG] = wlan_le16_to_cpu(rssirsp->AvgNoiseFloor); + Adapter->NF[TYPE_BEACON][TYPE_AVG] = + wlan_le16_to_cpu(rssirsp->AvgNoiseFloor); Adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG], @@ -736,7 +741,58 @@ return WLAN_STATUS_SUCCESS; } +#ifdef MFG_CMD_SUPPORT +/** + * @brief This function handles the command response of mfg_cmd + * + * @param priv A pointer to wlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_ret_mfg_cmd(wlan_private * priv, HostCmd_DS_COMMAND * resp) +{ + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + PRINTM(INFO, "MFG command response size = %d\n", resp->Size); + + resp->Size = MIN(resp->Size, MRVDRV_SIZE_OF_CMD_BUFFER); + memcpy(Adapter->CurCmd->pdata_buf, (void *) resp, resp->Size); + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} +#endif /* MFG_CMD_SUPPORT */ + +/** + * @brief This function handles the command response of cal_data_ext. + * + * @param priv A pointer to wlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +static int +wlan_ret_802_11_cal_data_ext(wlan_private * priv, HostCmd_DS_COMMAND * resp) +{ + wlan_adapter *Adapter = priv->adapter; + HostCmd_DS_802_11_CAL_DATA_EXT *pCalDataExt = &resp->params.caldataext; + + ENTER(); + if (wlan_le16_to_cpu(pCalDataExt->Action) == HostCmd_ACT_GEN_GET) { + pCalDataExt->Action = wlan_le16_to_cpu(pCalDataExt->Action); + pCalDataExt->Revision = wlan_le16_to_cpu(pCalDataExt->Revision); + pCalDataExt->CalDataLen = wlan_le16_to_cpu(pCalDataExt->CalDataLen); + + memmove(Adapter->CurCmd->pdata_buf, + pCalDataExt, pCalDataExt->CalDataLen + CAL_DATA_HEADER_LEN); + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief This function handles the command response of eeprom_access @@ -745,12 +801,15 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_eeprom_access(wlan_private *priv, - HostCmd_DS_COMMAND *resp) +int +wlan_ret_802_11_eeprom_access(wlan_private * priv, HostCmd_DS_COMMAND * resp) { wlan_adapter *Adapter = priv->adapter; - wlan_ioctl_regrdwr *pBuf = (wlan_ioctl_regrdwr*)Adapter -> pRdeeprom; - PRINTM(INFO,"eeprom read len=%x\n",wlan_le16_to_cpu(resp -> params.rdeeprom.ByteCount)); + wlan_ioctl_regrdwr *pBuf = + (wlan_ioctl_regrdwr *) Adapter->CurCmd->pdata_buf; + + PRINTM(INFO, "eeprom read len=%x\n", + wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount)); if(pBuf->NOB < wlan_le16_to_cpu(resp -> params.rdeeprom.ByteCount)){ pBuf->NOB = 0; PRINTM(INFO, "eeprom read return length is too big\n"); @@ -758,16 +817,12 @@ } pBuf->NOB = wlan_le16_to_cpu(resp -> params.rdeeprom.ByteCount); if(pBuf->NOB > 0){ - - memcpy(&pBuf->Value, (u8 *) &resp -> params.rdeeprom.Value, - wlan_le16_to_cpu(resp -> params.rdeeprom.ByteCount)); - HEXDUMP("Adapter", (char *)&pBuf->Value, wlan_le16_to_cpu(resp -> params.rdeeprom.ByteCount)); + memcpy(&pBuf->Value, (u8 *) & resp->params.rdeeprom.Value, pBuf->NOB); + HEXDUMP("EEPROM", (char *) &pBuf->Value, pBuf->NOB); } return WLAN_STATUS_SUCCESS; } - - /** * @brief This function handles the command response of get_log * @@ -775,34 +830,111 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_ret_get_log(wlan_private *priv, - HostCmd_DS_COMMAND *resp) +static int +wlan_ret_get_log(wlan_private * priv, HostCmd_DS_COMMAND * resp) { - PHostCmd_DS_802_11_GET_LOG LogMessage = - (PHostCmd_DS_802_11_GET_LOG)&resp->params.glog; + HostCmd_DS_802_11_GET_LOG *LogMessage = + (HostCmd_DS_802_11_GET_LOG *) & resp->params.glog; wlan_adapter *Adapter = priv->adapter; ENTER(); /* TODO Convert it to Big Endian before copy */ - memcpy(&Adapter->LogMsg, LogMessage, - sizeof(HostCmd_DS_802_11_GET_LOG)); + memcpy(&Adapter->LogMsg, LogMessage, sizeof(HostCmd_DS_802_11_GET_LOG)); + endian_convert_GET_LOG(Adapter->LogMsg); LEAVE(); return WLAN_STATUS_SUCCESS; } +static void +wlan_ret_802_11_IBSS_Coalesced_Status(wlan_private * priv, + HostCmd_DS_COMMAND * resp) +{ + HostCmd_DS_802_11_IBSS_Status *IBSSStatusRsp; + wlan_adapter *Adapter; + union iwreq_data wrqu; + u8 nullMac[6] = { 0, 0, 0, 0, 0, 0 }; + + Adapter = priv->adapter; + IBSSStatusRsp = &(resp->params.ibssCoalescing); + + if (Adapter->CurCmd->pdata_buf) + *(int *) Adapter->CurCmd->pdata_buf = IBSSStatusRsp->Enable; + + if (wlan_le16_to_cpu(IBSSStatusRsp->Action) == HostCmd_ACT_SET) { + return; + } + + PRINTM(INFO, "New BSSID %x:%x:%x:%x:%x:%x\n", + IBSSStatusRsp->BSSID[0], + IBSSStatusRsp->BSSID[1], + IBSSStatusRsp->BSSID[2], + IBSSStatusRsp->BSSID[3], + IBSSStatusRsp->BSSID[4], IBSSStatusRsp->BSSID[5]); + + /* if rsp has NULL BSSID, Just return.. No Action */ + if (!memcmp(IBSSStatusRsp->BSSID, nullMac, MRVDRV_ETH_ADDR_LEN)) { + PRINTM(MSG, "New BSSID is NULL\n"); + return; + } + + /* if BSSID is diff, Send evnet to Linux */ + if (memcmp(Adapter->CurBssParams.BSSDescriptor.MacAddress, + IBSSStatusRsp->BSSID, ETH_ALEN)) { + memcpy((void *) Adapter->CurBssParams.BSSDescriptor.MacAddress, + (void *) IBSSStatusRsp->BSSID, MRVDRV_ETH_ADDR_LEN); + + /* Beacon Interval and ATIM window */ + Adapter->CurBssParams.BSSDescriptor.BeaconPeriod + = IBSSStatusRsp->BeaconInterval; + Adapter->CurBssParams.BSSDescriptor.ATIMWindow + = IBSSStatusRsp->ATIMWindow; + //ERP Information + Adapter->CurBssParams.BSSDescriptor.ERPFlags = + (u8) IBSSStatusRsp->UseGRateProtection; + + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, + Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); + } +} + /******************************************************** Global Functions ********************************************************/ /** + * @brief This function stop tx/rx queue and free skb + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +void +wlan_clean_txrx(wlan_private * priv) +{ + os_stop_queue(priv); + os_carrier_off(priv); + + wmm_stop_queue(priv); + wmm_cleanup_queues(priv); + + /* Free Tx and Rx packets */ + os_free_tx_packet(priv); + wlan_send_rxskbQ(priv); +} + +/** * @brief This function handles the command response * * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_process_rx_command(wlan_private * priv) +int +wlan_process_rx_command(wlan_private * priv) { u16 RespCmd; HostCmd_DS_COMMAND *resp; @@ -813,8 +945,6 @@ ENTER(); - PRINTM(INFO, "CMD_RESP: @ %lu\n", os_time_get()); - /* Now we got response from FW, cancel the command timer */ if (Adapter->CommandTimerIsSet) { CancelTimer(&Adapter->MrvDrvCommandTimer); @@ -822,24 +952,37 @@ } if (!Adapter->CurCmd) { - PRINTM(INFO, "CMD_RESP: NULL CurCmd=%p\n", Adapter->CurCmd); + resp = (HostCmd_DS_COMMAND *) priv->wlan_dev.upld_buf; + resp->Command = wlan_le16_to_cpu(resp->Command); + PRINTM(ERROR, "CMD_RESP: NULL CurCmd, 0x%x\n", resp->Command); ret = WLAN_STATUS_FAILURE; goto done; } - resp = (HostCmd_DS_COMMAND *) (Adapter->CurCmd->BufVirtualAddr); + Adapter->num_cmd_timeout = 0; - HEXDUMP("CMD_RESP:", Adapter->CurCmd->BufVirtualAddr, + DBG_HEXDUMP(CMD_D, "CMD_RESP", Adapter->CurCmd->BufVirtualAddr, priv->wlan_dev.upld_len); - RespCmd = wlan_le16_to_cpu(resp->Command); + resp = (HostCmd_DS_COMMAND *) (Adapter->CurCmd->BufVirtualAddr); - Result = wlan_le16_to_cpu(resp->Result); + resp->Command = wlan_le16_to_cpu(resp->Command); + resp->Size = wlan_le16_to_cpu(resp->Size); + resp->SeqNum = wlan_le16_to_cpu(resp->SeqNum); + resp->Result = wlan_le16_to_cpu(resp->Result); - PRINTM(INFO, "CMD_RESP: %x Result: %d Length: %d\n", RespCmd, - Result, priv->wlan_dev.upld_len); + RespCmd = resp->Command; + Result = resp->Result; + + /* Save the last command response to debug log */ + Adapter->dbg.LastCmdRespIndex = + (Adapter->dbg.LastCmdRespIndex + 1) % DBG_CMD_NUM; + Adapter->dbg.LastCmdRespId[Adapter->dbg.LastCmdRespIndex] = RespCmd; + + PRINTM(CMND, "CMD_RESP: 0x%x, result %d, len %d, seqno %d @ %lu\n", + RespCmd, Result, resp->Size, resp->SeqNum, os_time_get()); if (!(RespCmd & 0x8000)) { - PRINTM(INFO, "Invalid response to command!"); + PRINTM(ERROR, "CMD_RESP: Invalid response to command!"); Adapter->CurCmdRetCode = WLAN_STATUS_FAILURE; CleanupAndInsertCmd(priv, Adapter->CurCmd); spin_lock_irqsave(&Adapter->QueueSpinLock, flags); @@ -851,7 +994,7 @@ } /* Store the response code to CurCmdRetCode. */ - Adapter->CurCmdRetCode = wlan_le16_to_cpu(resp->Result); + Adapter->CurCmdRetCode = resp->Result; if (RespCmd == HostCmd_RET_802_11_PS_MODE) { HostCmd_DS_802_11_PS_MODE *psmode; @@ -862,7 +1005,8 @@ psmode->Action = wlan_cpu_to_le16(psmode->Action); if (Result) { - PRINTM(INFO, "CMD_RESP: PS command failed- %#x \n", resp->Result); + PRINTM(ERROR, "CMD_RESP: PS command failed- %#x \n", + resp->Result); if (Adapter->InfrastructureMode == Wlan802_11IBSS) { /* * We should not re-try enter-ps command in @@ -870,25 +1014,23 @@ * ExecuteNextCommand(). */ if (psmode->Action == HostCmd_SubCmd_Enter_PS) - Adapter->PSMode = - Wlan802_11PowerModeCAM; + Adapter->PSMode = Wlan802_11PowerModeCAM; } } else if (psmode->Action == HostCmd_SubCmd_Enter_PS) { Adapter->NeedToWakeup = FALSE; Adapter->PSState = PS_STATE_AWAKE; - PRINTM(INFO, "CMD_RESP: Enter_PS command response\n"); if (Adapter->MediaConnectStatus != WlanMediaStateConnected){ /* * When Deauth Event received before Enter_PS command * response, We need to wake up the firmware. */ - PRINTM(INFO, "Disconnected, Going to invoke PSWakeup\n"); + PRINTM(INFO, + "CMD_RESP: Disconnected, Going to invoke PSWakeup\n"); PSWakeup(priv, 0); } } else if (psmode->Action == HostCmd_SubCmd_Exit_PS) { Adapter->NeedToWakeup = FALSE; Adapter->PSState = PS_STATE_FULL_POWER; - PRINTM(INFO, "CMD_RESP: Exit_PS command response\n"); } else { PRINTM(INFO, "CMD_RESP: PS- Action=0x%X\n",psmode->Action); } @@ -904,24 +1046,25 @@ if (Adapter->CurCmd->CmdFlags & CMD_F_HOSTCMD) { /* Copy the response back to response buffer */ - memcpy(Adapter->CurCmd->pdata_buf, - resp, resp->Size); + memcpy(Adapter->CurCmd->pdata_buf, resp, resp->Size); Adapter->CurCmd->CmdFlags &= ~CMD_F_HOSTCMD; - } + if ((Result == HostCmd_RESULT_OK) + && (RespCmd == HostCmd_RET_802_11_HOST_SLEEP_CFG)) { + ret = wlan_ret_host_sleep_cfg(priv, resp); + } + } else { /* If the command is not successful, cleanup and return failure */ if ((Result != HostCmd_RESULT_OK || !(RespCmd & 0x8000))) { - PRINTM(INFO, "CMD_RESP: command reply %#x result=%#x\n", + PRINTM(ERROR, "CMD_RESP: cmd %#x error, result=%#x\n", resp->Command, resp->Result); /* * Handling errors here */ switch (RespCmd) { case HostCmd_RET_HW_SPEC_INFO: - case HostCmd_RET_802_11_RESET: - PRINTM(INFO, "CMD_RESP: Reset command Failed\n"); - Adapter->HardwareStatus = WlanHardwareStatusNotReady; + PRINTM(INFO, "CMD_RESP: HW spec command Failed\n"); break; } @@ -945,6 +1088,17 @@ ret = wlan_ret_get_hw_spec(priv, resp); break; + case HostCmd_RET_802_11_BG_SCAN_QUERY: + { + union iwreq_data wrqu; + + ret = wlan_ret_802_11_scan(priv, resp); + memset(&wrqu, 0, sizeof(union iwreq_data)); + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, + NULL); + PRINTM(INFO, "CMD_RESP: BG_SCAN result is ready!\n"); + break; + } case HostCmd_RET_802_11_SCAN: ret = wlan_ret_802_11_scan(priv, resp); break; @@ -958,11 +1112,9 @@ break; case HostCmd_RET_802_11_ASSOCIATE: - case HostCmd_RET_802_11_REASSOCIATE: ret = wlan_ret_802_11_associate(priv, resp); break; - case HostCmd_RET_802_11_DISASSOCIATE: case HostCmd_RET_802_11_DEAUTHENTICATE: ret = wlan_ret_802_11_disassociate(priv, resp); break; @@ -973,21 +1125,13 @@ case HostCmd_RET_802_11_AD_HOC_START: case HostCmd_RET_802_11_AD_HOC_JOIN: - ret = wlan_ret_802_11_ad_hoc_start(priv, resp); + ret = wlan_ret_802_11_ad_hoc(priv, resp); break; case HostCmd_RET_802_11_RESET: ret = wlan_ret_802_11_reset(priv, resp); break; - case HostCmd_RET_802_11_AUTHENTICATE: - ret = wlan_ret_802_11_authenticate(priv, resp); - break; - - case HostCmd_RET_802_11_STAT: - ret = wlan_ret_802_11_stat(priv, resp); - break; - case HostCmd_RET_802_11_SNMP_MIB: ret = wlan_ret_802_11_snmp_mib(priv, resp); break; @@ -1000,15 +1144,19 @@ ret = wlan_ret_802_11_radio_control(priv, resp); break; - - - case HostCmd_RET_802_11_SET_AFC: - case HostCmd_RET_802_11_GET_AFC: - memmove(Adapter->CurCmd->pdata_buf, - &resp->params.afc, - sizeof(HostCmd_DS_802_11_AFC)); - + case HostCmd_RET_802_11_HOST_SLEEP_CFG: + ret = wlan_ret_host_sleep_cfg(priv, resp); + break; + case HostCmd_RET_802_11_WAKEUP_CONFIRM: + wlan_host_sleep_deactivated_event(priv); break; + case HostCmd_RET_802_11_HOST_SLEEP_ACTIVATE: + if (Adapter->bHostSleepConfigured + && Adapter->HSCfg.gap == HOST_SLEEP_CFG_GAP_FF) + Adapter->bWakeupDevRequired = TRUE; + wlan_host_sleep_activated_event(priv); + break; + case HostCmd_RET_802_11_RF_ANTENNA: ret = wlan_ret_802_11_rf_antenna(priv, resp); break; @@ -1017,9 +1165,6 @@ ret = wlan_ret_mac_multicast_adr(priv, resp); break; - case HostCmd_RET_802_11_DATA_RATE: - ret = wlan_ret_802_11_data_rate(priv, resp); - break; case HostCmd_RET_802_11_RATE_ADAPT_RATESET: ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp); break; @@ -1035,17 +1180,20 @@ ret = wlan_ret_802_11_mac_address(priv, resp); break; +#ifdef MFG_CMD_SUPPORT + case HostCmd_RET_MFG_COMMAND: + ret = wlan_ret_mfg_cmd(priv, resp); + break; +#endif case HostCmd_RET_802_11_AD_HOC_STOP: ret = wlan_ret_802_11_ad_hoc_stop(priv, resp); break; - case HostCmd_RET_802_11_BEACON_STOP: + case HostCmd_RET_802_11_CAL_DATA_EXT: + ret = wlan_ret_802_11_cal_data_ext(priv, resp); break; - case HostCmd_RET_802_11_ENABLE_RSN: - break; case HostCmd_RET_802_11_KEY_MATERIAL: - PRINTM(INFO, "CMD_RESP: KEY_MATERIAL command response\n"); ret = wlan_ret_802_11_key_material(priv, resp); break; @@ -1053,8 +1201,6 @@ ret = wlan_ret_802_11_eeprom_access(priv, resp); break; - - case HostCmd_RET_802_11D_DOMAIN_INFO: ret = wlan_ret_802_11d_domain_info(priv, resp); break; @@ -1062,45 +1208,100 @@ case HostCmd_RET_802_11_SLEEP_PARAMS: ret = wlan_ret_802_11_sleep_params(priv, resp); break; + case HostCmd_RET_802_11_BCA_CONFIG_TIMESHARE: + ret = wlan_ret_802_11_bca_timeshare(priv, resp); + break; case HostCmd_RET_802_11_INACTIVITY_TIMEOUT: *((u16 *)Adapter->CurCmd->pdata_buf) = wlan_le16_to_cpu(resp->params.inactivity_timeout.Timeout); break; + case HostCmd_RET_802_11_BG_SCAN_CONFIG: + break; + case HostCmd_RET_802_11_FW_WAKE_METHOD: + ret = wlan_ret_fw_wakeup_method(priv, resp); + break; case HostCmd_RET_802_11_SLEEP_PERIOD: ret = wlan_ret_802_11_sleep_period(priv, resp); break; - case HostCmd_RET_802_11_TPC_CFG: - memmove(Adapter->CurCmd->pdata_buf, - &resp->params.tpccfg, - sizeof(HostCmd_DS_802_11_TPC_CFG)); + case HostCmd_RET_WMM_GET_STATUS: + ret = wlan_cmdresp_wmm_get_status(priv, resp); break; - case HostCmd_RET_802_11_LED_GPIO_CTRL: - memmove(Adapter->CurCmd->pdata_buf, - &resp->params.ledgpio, - sizeof(HostCmd_DS_802_11_LED_CTRL)); + case HostCmd_RET_WMM_ADDTS_REQ: + ret = wlan_cmdresp_wmm_addts_req(priv, resp); break; - case HostCmd_RET_802_11_PWR_CFG: + case HostCmd_RET_WMM_DELTS_REQ: + ret = wlan_cmdresp_wmm_delts_req(priv, resp); + break; + case HostCmd_RET_WMM_QUEUE_CONFIG: + ret = wlan_cmdresp_wmm_queue_config(priv, resp); + break; + case HostCmd_RET_WMM_QUEUE_STATS: + ret = wlan_cmdresp_wmm_queue_stats(priv, resp); + break; + case HostCmd_RET_TX_PKT_STATS: + memcpy(Adapter->CurCmd->pdata_buf, + &resp->params.txPktStats, sizeof(HostCmd_DS_TX_PKT_STATS)); + ret = WLAN_STATUS_SUCCESS; + break; + case HostCmd_RET_802_11_TPC_CFG: memmove(Adapter->CurCmd->pdata_buf, - &resp->params.pwrcfg, - sizeof(HostCmd_DS_802_11_PWR_CFG)); + &resp->params.tpccfg, sizeof(HostCmd_DS_802_11_TPC_CFG)); + break; + case HostCmd_RET_802_11_LED_CONTROL: + { + HostCmd_DS_802_11_LED_CTRL *pLedCtrl = &resp->params.ledgpio; + MrvlIEtypes_LedGpio_t *pGpio = &pLedCtrl->LedGpio; + MrvlIEtypes_LedBehavior_t *pBehavior = pLedCtrl->LedBehavior; + pLedCtrl->Action = wlan_le16_to_cpu(pLedCtrl->Action); + pLedCtrl->LedNums = wlan_le16_to_cpu(pLedCtrl->LedNums); + pGpio->Header.Type = wlan_le16_to_cpu(pGpio->Header.Type); + pGpio->Header.Len = wlan_le16_to_cpu(pGpio->Header.Len); + pBehavior->Header.Type = + wlan_le16_to_cpu(pBehavior->Header.Type); + pBehavior->Header.Len = + wlan_le16_to_cpu(pBehavior->Header.Len); + memmove(Adapter->CurCmd->pdata_buf, &resp->params.ledgpio, + sizeof(HostCmd_DS_802_11_LED_CTRL)); break; + } case HostCmd_RET_GET_TSF: + resp->params.gettsf.TsfValue = + wlan_le64_to_cpu(resp->params.gettsf.TsfValue); memcpy(priv->adapter->CurCmd->pdata_buf, - &resp->params.gettsf.TsfValue, - sizeof(u64)); - break; - case HostCmd_RET_DFT_ACCESS: - if (Adapter->CurCmd->pdata_buf) - memcpy(Adapter->CurCmd->pdata_buf, &resp->params.dft.addr1, - 2*ETH_ALEN); + &resp->params.gettsf.TsfValue, sizeof(u64)); break; case HostCmd_RTE_802_11_TX_RATE_QUERY: - priv->adapter->TxRate = resp->params.txrate.TxRate; + priv->adapter->TxRate = + wlan_le16_to_cpu(resp->params.txrate.TxRate); + break; + case HostCmd_RET_802_11_IBSS_COALESCING_STATUS: + wlan_ret_802_11_IBSS_Coalesced_Status(priv, resp); + break; + + case HostCmd_RET_SDIO_PULL_CTRL: + memmove(Adapter->CurCmd->pdata_buf, + &resp->params.sdiopullctl, + sizeof(HostCmd_DS_SDIO_PULL_CTRL)); + break; + + case HostCmd_RET_802_11_LDO_CONFIG: + resp->params.ldocfg.Action = + wlan_le16_to_cpu(resp->params.ldocfg.Action); + resp->params.ldocfg.PMSource = + wlan_le16_to_cpu(resp->params.ldocfg.PMSource); + memmove(Adapter->CurCmd->pdata_buf, &resp->params.ldocfg, + sizeof(HostCmd_DS_802_11_LDO_CONFIG)); + break; + + case HostCmd_RET_VERSION_EXT: + memcpy(Adapter->CurCmd->pdata_buf, + &resp->params.verext, sizeof(HostCmd_DS_VERSION_EXT)); break; + default: PRINTM(INFO, "CMD_RESP: Unknown command response %#x\n", resp->Command); @@ -1106,6 +1307,7 @@ resp->Command); break; } + } if (Adapter->CurCmd) { /* Clean up and Put current command back to CmdFreeQ */ @@ -1120,44 +1322,104 @@ return ret; } +#if WIRELESS_EXT >= 18 +/** + * @brief This function sends mic error event to application. + * + * @param priv A pointer to wlan_private structure + * @para event MIC ERROR EVENT. + * @return n/a + */ +void +send_mic_error_event(wlan_private * priv, u32 event) +{ + union iwreq_data iwrq; + struct iw_michaelmicfailure mic; + + ENTER(); + + memset(&iwrq, 0, sizeof(iwrq)); + memset(&mic, 0, sizeof(mic)); + if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { + mic.flags = IW_MICFAILURE_PAIRWISE; + } else { + mic.flags = IW_MICFAILURE_GROUP; + } + + iwrq.data.pointer = &mic; + iwrq.data.length = sizeof(mic); + + wireless_send_event(priv->wlan_dev.netdev, IWEVMICHAELMICFAILURE, &iwrq, + (u8 *) & mic); + + LEAVE(); + return; +} +#endif + /** * @brief This function handles events generated by firmware * * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_process_event(wlan_private * priv) +int +wlan_process_event(wlan_private * priv) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; + u32 eventcause = Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT; ENTER(); - PRINTM(INFO, "EVENT Cause %x\n", Adapter->EventCause); + /* Save the last event to debug log */ + Adapter->dbg.LastEventIndex = + (Adapter->dbg.LastEventIndex + 1) % DBG_CMD_NUM; + Adapter->dbg.LastEvent[Adapter->dbg.LastEventIndex] = eventcause; - switch (Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT) { + if (eventcause != MACREG_INT_CODE_PS_SLEEP && + eventcause != MACREG_INT_CODE_PS_AWAKE) + PRINTM(EVENT, "EVENT: 0x%x @ %lu\n", eventcause, os_time_get()); + + switch (eventcause) { + case MACREG_INT_CODE_DUMMY_HOST_WAKEUP_SIGNAL: + PRINTM(INFO, "EVENT: DUMMY_HOST_WAKEUP_SIGNAL\n"); + if (!priv->adapter->HS_Activated) { + PRINTM(WARN, "DUMMY_HOST_WAKEUP_SIGNAL (HS_Deactivated)\n"); + } else { + wlan_host_sleep_gpio_int_event(priv); + } + break; case MACREG_INT_CODE_LINK_SENSED: - PRINTM(INFO, "EVENT: MACREG_INT_CODE_LINK_SENSED\n"); + PRINTM(INFO, "EVENT: LINK_SENSED\n"); + Adapter->AdhocLinkSensed = TRUE; + os_carrier_on(priv); + os_start_queue(priv); + wmm_start_queue(priv); + send_iwevcustom_event(priv, CUS_EVT_ADHOC_LINK_SENSED); break; case MACREG_INT_CODE_DEAUTHENTICATED: PRINTM(INFO, "EVENT: Deauthenticated\n"); + Adapter->dbg.num_event_deauth++; HandleDisconnectEvent(priv); break; case MACREG_INT_CODE_DISASSOCIATED: PRINTM(INFO, "EVENT: Disassociated\n"); + Adapter->dbg.num_event_disassoc++; HandleDisconnectEvent(priv); break; - case MACREG_INT_CODE_LINK_LOSE_NO_SCAN: + case MACREG_INT_CODE_LINK_LOST: PRINTM(INFO, "EVENT: Link lost\n"); + Adapter->dbg.num_event_link_lost++; HandleDisconnectEvent(priv); break; case MACREG_INT_CODE_PS_SLEEP: PRINTM(INFO, "EVENT: SLEEP\n"); - PRINTM(INFO, "_"); + PRINTM(EVENT, "_"); /* handle unexpected PS SLEEP event */ if (Adapter->PSState == PS_STATE_FULL_POWER) { @@ -1167,12 +1429,11 @@ Adapter->PSState = PS_STATE_PRE_SLEEP; PSConfirmSleep(priv, (u16) Adapter->PSMode); - break; case MACREG_INT_CODE_PS_AWAKE: PRINTM(INFO, "EVENT: AWAKE \n"); - PRINTM(INFO, "|"); + PRINTM(EVENT, "|"); /* handle unexpected PS AWAKE event */ if (Adapter->PSState == PS_STATE_FULL_POWER) { @@ -1180,13 +1441,12 @@ break; } - Adapter->TxLockFlag = 0; + Adapter->TxLockFlag = FALSE; if(TRUE == CheckLastPacketIndication(priv)){ - if(Adapter->gen_null_pkg) - { + if (!priv->wlan_dev.dnld_sent && Adapter->gen_null_pkg) { SendNullPacket(priv, MRVDRV_TxPD_POWER_MGMT_NULL_PACKET | MRVDRV_TxPD_POWER_MGMT_LAST_PACKET); - Adapter->TxLockFlag = 1; + Adapter->TxLockFlag = TRUE; } } @@ -1204,46 +1464,112 @@ } break; + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: + sbi_reset_deepsleep_wakeup(priv); + PRINTM(INFO, "EVENT: DS_AWAKE\n"); + if (priv->adapter->IsDeepSleep == TRUE) { + Adapter->IsDeepSleep = FALSE; + Adapter->bWakeupDevRequired = FALSE; + Adapter->WakeupTries = 0; + /* + * For auto DS + BGS case, some delay is needed to + * avoid going back to DS before getting BGS result + */ + if (Adapter->IsAutoDeepSleepEnabled && + Adapter->bgScanConfig->Enable) + os_sched_timeout(10); + priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + priv->adapter->HisRegCpy |= HIS_TxDnLdRdy; + } + send_iwevcustom_event(priv, CUS_EVT_DEEP_SLEEP_AWAKE); + wake_up_interruptible(&Adapter->ds_awake_q); + break; + case MACREG_INT_CODE_HOST_SLEEP_AWAKE: + PRINTM(INFO, "EVENT: HS_AWAKE\n"); + Adapter->bWakeupDevRequired = FALSE; + Adapter->WakeupTries = 0; + sbi_reset_deepsleep_wakeup(priv); + + /* + * in BG SCAN mode w/ deep sleep, WAKE UP event + * will be sent first, Deep Sleep Awake will + * be sent later. + */ + if (priv->adapter->IsDeepSleep == TRUE) { + priv->adapter->IsDeepSleep = FALSE; + priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + priv->adapter->HisRegCpy |= HIS_TxDnLdRdy; + } + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_WAKEUP_CONFIRM, + 0, 0, 0, NULL); + break; case MACREG_INT_CODE_MIC_ERR_UNICAST: PRINTM(INFO, "EVENT: UNICAST MIC ERROR\n"); - HandleMICFailureEvent(priv, - MACREG_INT_CODE_MIC_ERR_UNICAST); +#if WIRELESS_EXT >= 18 + send_mic_error_event(priv, MACREG_INT_CODE_MIC_ERR_UNICAST); +#else + send_iwevcustom_event(priv, CUS_EVT_MLME_MIC_ERR_UNI); +#endif break; case MACREG_INT_CODE_MIC_ERR_MULTICAST: PRINTM(INFO, "EVENT: MULTICAST MIC ERROR\n"); - HandleMICFailureEvent(priv, - MACREG_INT_CODE_MIC_ERR_MULTICAST); +#if WIRELESS_EXT >= 18 + send_mic_error_event(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); +#else + send_iwevcustom_event(priv, CUS_EVT_MLME_MIC_ERR_MUL); +#endif break; case MACREG_INT_CODE_MIB_CHANGED: case MACREG_INT_CODE_INIT_DONE: break; case MACREG_INT_CODE_ADHOC_BCN_LOST: - PRINTM(INFO, "EVENT: HWAC - ADHOC BCN LOST\n"); + PRINTM(INFO, "EVENT: ADHOC_BCN_LOST\n"); + Adapter->AdhocLinkSensed = FALSE; + wlan_clean_txrx(priv); + send_iwevcustom_event(priv, CUS_EVT_ADHOC_BCN_LOST); + break; + + case MACREG_INT_CODE_BG_SCAN_REPORT: + PRINTM(INFO, "EVENT: BGS_REPORT\n"); + Adapter->bgScanConfig->Enable = FALSE; + ret = sendBgScanQueryCmd(priv); + break; + case MACREG_INT_CODE_WMM_STATUS_CHANGE: + PRINTM(INFO, "EVENT: WMM status changed\n"); + ret = sendWMMStatusChangeCmd(priv); break; case MACREG_INT_CODE_RSSI_LOW: - PRINTM(MSG, "EVENT: RSSI_LOW\n"); + PRINTM(INFO, "EVENT: RSSI_LOW\n"); + send_iwevcustom_event(priv, CUS_EVT_BEACON_RSSI_LOW); break; case MACREG_INT_CODE_SNR_LOW: - PRINTM(MSG, "EVENT: SNR_LOW\n"); + PRINTM(INFO, "EVENT: SNR_LOW\n"); + send_iwevcustom_event(priv, CUS_EVT_BEACON_SNR_LOW); break; case MACREG_INT_CODE_MAX_FAIL: - PRINTM(MSG, "EVENT: MAX_FAIL\n"); + PRINTM(INFO, "EVENT: MAX_FAIL\n"); + send_iwevcustom_event(priv, CUS_EVT_MAX_FAIL); break; case MACREG_INT_CODE_RSSI_HIGH: - PRINTM(MSG, "EVENT: RSSI_HIGH\n"); + PRINTM(INFO, "EVENT: RSSI_HIGH\n"); + send_iwevcustom_event(priv, CUS_EVT_BEACON_RSSI_HIGH); break; case MACREG_INT_CODE_SNR_HIGH: - PRINTM(MSG, "EVENT: SNR_HIGH\n"); + PRINTM(INFO, "EVENT: SNR_HIGH\n"); + send_iwevcustom_event(priv, CUS_EVT_BEACON_SNR_HIGH); + break; + case MACREG_INT_CODE_IBSS_COALESCED: + PRINTM(INFO, "EVENT: IBSS_COALESCED\n"); + ret = sendADHOCBSSIDQuery(priv); break; - default: - PRINTM(INFO, "EVENT: unknown event id: %#x\n", - Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT); + PRINTM(INFO, "EVENT: unknown event id: %#x\n", eventcause); break; } @@ -1251,4 +1577,3 @@ LEAVE(); return ret; } - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_debug.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_debug.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_debug.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_debug.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,13 @@ /** @file wlan_debug.c * @brief This file contains functions for debug proc file. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -27,6 +26,7 @@ #include "include.h" +#ifdef CONFIG_PROC_FS /******************************************************** Local Variables ********************************************************/ @@ -34,18 +34,90 @@ #define item_size(n) (sizeof ((wlan_adapter *)0)->n) #define item_addr(n) ((u32) &((wlan_adapter *)0)->n) -struct debug_data { +#define item_dbg_size(n) (sizeof (((wlan_adapter *)0)->dbg.n)) +#define item_dbg_addr(n) ((u32) &(((wlan_adapter *)0)->dbg.n)) + +#define item1_size(n) (sizeof ((wlan_dev_t *)0)->n) +#define item1_addr(n) ((u32) &((wlan_dev_t *)0)->n) + +struct debug_data +{ char name[32]; u32 size; u32 addr; + u32 offset; }; -/* To debug any member of wlan_adapter, simply add one line here. +/* To debug any member of wlan_adapter or wlan_dev_t, simply add one line here. */ +#define ITEMS_FROM_WLAN_DEV 1 + static struct debug_data items[] = { - {"IntCounter", item_size(IntCounter), item_addr(IntCounter)}, - {"PSMode", item_size(PSMode), item_addr(PSMode)}, - {"PSState", item_size(PSState), item_addr(PSState)}, + {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter)}, + {"ConnectStatus", item_size(MediaConnectStatus), 0, + item_addr(MediaConnectStatus)}, + {"wmmQStp", item_size(wmm.queueStopped), 0, item_addr(wmm.queueStopped)}, + {"wmmPkts", item_size(wmm.packetsQueued), 0, + item_addr(wmm.packetsQueued)}, + {"wmmAcVo", item_size(wmm.packetsOut[WMM_AC_VO]), 0, + item_addr(wmm.packetsOut[WMM_AC_VO])}, + {"wmmAcVi", item_size(wmm.packetsOut[WMM_AC_VI]), 0, + item_addr(wmm.packetsOut[WMM_AC_VI])}, + {"wmmAcBE", item_size(wmm.packetsOut[WMM_AC_BE]), 0, + item_addr(wmm.packetsOut[WMM_AC_BE])}, + {"wmmAcBK", item_size(wmm.packetsOut[WMM_AC_BK]), 0, + item_addr(wmm.packetsOut[WMM_AC_BK])}, + {"PSMode", item_size(PSMode), 0, item_addr(PSMode)}, + {"PSState", item_size(PSState), 0, item_addr(PSState)}, + {"IsDeepSleep", item_size(IsDeepSleep), 0, item_addr(IsDeepSleep)}, + {"IsAutoDeepSleepEnabled", item_size(IsAutoDeepSleepEnabled), 0, + item_addr(IsAutoDeepSleepEnabled)}, + {"WakeupDevReq", item_size(bWakeupDevRequired), 0, + item_addr(bWakeupDevRequired)}, + {"WakeupTries", item_size(WakeupTries), 0, item_addr(WakeupTries)}, + {"HS_Configured", item_size(bHostSleepConfigured), 0, + item_addr(bHostSleepConfigured)}, + {"HS_Activated", item_size(HS_Activated), 0, item_addr(HS_Activated)}, + {"num_tx_timeout", item_dbg_size(num_tx_timeout), 0, + item_dbg_addr(num_tx_timeout)}, + {"num_cmd_timeout", item_dbg_size(num_cmd_timeout), 0, + item_dbg_addr(num_cmd_timeout)}, + {"TimeoutCmdId", item_dbg_size(TimeoutCmdId), 0, + item_dbg_addr(TimeoutCmdId)}, + {"TimeoutCmdAct", item_dbg_size(TimeoutCmdAct), 0, + item_dbg_addr(TimeoutCmdAct)}, + {"LastCmdId", item_dbg_size(LastCmdId), 0, item_dbg_addr(LastCmdId)}, + {"LastCmdAct", item_dbg_size(LastCmdAct), 0, item_dbg_addr(LastCmdAct)}, + {"LastCmdIndex", item_dbg_size(LastCmdIndex), 0, + item_dbg_addr(LastCmdIndex)}, + {"LastCmdRespId", item_dbg_size(LastCmdRespId), 0, + item_dbg_addr(LastCmdRespId)}, + {"LastCmdRespIndex", item_dbg_size(LastCmdRespIndex), 0, + item_dbg_addr(LastCmdRespIndex)}, + {"LastEvent", item_dbg_size(LastEvent), 0, item_dbg_addr(LastEvent)}, + {"LastEventIndex", item_dbg_size(LastEventIndex), 0, + item_dbg_addr(LastEventIndex)}, + {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0, + item_dbg_addr(num_cmd_host_to_card_failure)}, + {"num_cmd_sleep_cfm_fail", + item_dbg_size(num_cmd_sleep_cfm_host_to_card_failure), 0, + item_dbg_addr(num_cmd_sleep_cfm_host_to_card_failure)}, + {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0, + item_dbg_addr(num_tx_host_to_card_failure)}, + {"num_evt_deauth", item_dbg_size(num_event_deauth), 0, + item_dbg_addr(num_event_deauth)}, + {"num_evt_disassoc", item_dbg_size(num_event_disassoc), 0, + item_dbg_addr(num_event_disassoc)}, + {"num_evt_link_lost", item_dbg_size(num_event_link_lost), 0, + item_dbg_addr(num_event_link_lost)}, + {"num_cmd_deauth", item_dbg_size(num_cmd_deauth), 0, + item_dbg_addr(num_cmd_deauth)}, + {"num_cmd_assoc_ok", item_dbg_size(num_cmd_assoc_success), 0, + item_dbg_addr(num_cmd_assoc_success)}, + {"num_cmd_assoc_fail", item_dbg_size(num_cmd_assoc_failure), 0, + item_dbg_addr(num_cmd_assoc_failure)}, + + {"dnld_sent", item1_size(dnld_sent), 0, item1_addr(dnld_sent)}, }; static int num_of_items = sizeof(items)/sizeof(items[0]); @@ -54,45 +126,9 @@ Global Variables ********************************************************/ - /******************************************************** Local Functions ********************************************************/ - -/** - * @brief convert string to number - * - * @param s pointer to numbered string - * @return converted number from string s - */ -static int string_to_number(char *s) -{ - int r = 0; - int base = 0; - - if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) - base = 16; - else - base = 10; - - if (base == 16) - s += 2; - - for (s = s; *s !=0; s++) - { - if ((*s >= 48) && (*s <= 57)) - r = (r * base) + (*s - 48); - else if ((*s >= 65) && (*s <= 70)) - r = (r * base) + (*s - 55); - else if ((*s >= 97) && (*s <= 102)) - r = (r * base) + (*s - 87); - else - break; - } - - return r; -} - /** * @brief proc read function * @@ -104,7 +140,9 @@ * @param data data to output * @return number of output data */ -static int wlan_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data) +static int +wlan_debug_read(char *page, char **s, off_t off, int cnt, int *eof, + void *data) { int val = 0; char *p = page; @@ -114,21 +152,30 @@ MODULE_GET; - for (i = 0; i < num_of_items; i++) - { + for (i = 0; i < num_of_items; i++) { if (d[i].size == 1) val = *((u8 *)d[i].addr); else if (d[i].size == 2) val = *((u16 *)d[i].addr); else if (d[i].size == 4) val = *((u32 *)d[i].addr); + else { + int j; + p += sprintf(p, "%s=", d[i].name); + for (j = 0; j < d[i].size; j += 2) { + val = *(u16 *) (d[i].addr + j); + p += sprintf(p, "0x%x ", val); + } + p += sprintf(p, "\n"); + continue; + } + if (strstr(d[i].name, "Id")) + p += sprintf(p, "%s=0x%x\n", d[i].name, val); + else p += sprintf(p, "%s=%d\n", d[i].name, val); - } - MODULE_PUT; - return p-page; } @@ -141,7 +188,9 @@ * @param data data to write * @return number of data */ -static int wlan_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data) +static int +wlan_debug_write(struct file *f, const char *buf, unsigned long cnt, + void *data) { int r,i; char *pdata; @@ -154,19 +203,21 @@ MODULE_GET; pdata = (char *)kmalloc(cnt, GFP_KERNEL); - if(pdata == NULL) + if (pdata == NULL) { + MODULE_PUT; return 0; + } if (copy_from_user(pdata, buf, cnt)) { PRINTM(INFO, "Copy from user failed\n"); + kfree(pdata); + MODULE_PUT; return 0; } p0 = pdata; - for (i = 0; i < num_of_items; i++) - { - do - { + for (i = 0; i < num_of_items; i++) { + do { p = strstr(p0,d[i].name); if(p == NULL) break; @@ -189,11 +240,8 @@ }while (TRUE); } kfree(pdata); - MODULE_PUT; - return cnt; - } /******************************************************** @@ -206,7 +254,8 @@ * @param dev pointer net_device * @return N/A */ -void wlan_debug_entry(wlan_private *priv, struct net_device *dev) +void +wlan_debug_entry(wlan_private * priv, struct net_device *dev) { int i; struct proc_dir_entry *r; @@ -214,12 +263,13 @@ if (priv->proc_entry == NULL) return; - for (i = 0; i < num_of_items; i++) - { - items[i].addr += (u32)priv->adapter; + for (i = 0; i < (num_of_items - ITEMS_FROM_WLAN_DEV); i++) { + items[i].addr = items[i].offset + (u32) priv->adapter; + } + for (i = num_of_items - ITEMS_FROM_WLAN_DEV; i < num_of_items; i++) { + items[i].addr = items[i].offset + (u32) & priv->wlan_dev; } r = create_proc_entry("debug", 0644, priv->proc_entry); - if (r == NULL) return; @@ -236,7 +286,10 @@ * @param priv pointer wlan_private * @return N/A */ -void wlan_debug_remove(wlan_private *priv) +void +wlan_debug_remove(wlan_private * priv) { remove_proc_entry("debug", priv->proc_entry); } + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_decl.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_decl.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_decl.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_decl.h 2007-11-06 12:26:40.000000000 -0500 @@ -2,14 +2,13 @@ * @brief This file contains declaration referring to * functions defined in other source files * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -23,8 +22,6 @@ Change log: 09/29/05: add Doxygen format comments 01/05/06: Add kernel 2.6.x support - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support - Monahans/Zylonite 01/11/06: Conditionalize new scan/join structures. Move wlan_wext statics to their source file. ******************************************************/ @@ -33,15 +30,13 @@ #define _WLAN_DECL_H_ /** Function Prototype Declaration */ +int wlan_init_fw(wlan_private * priv); int wlan_tx_packet(wlan_private *priv, struct sk_buff *skb); void wlan_free_adapter(wlan_private *priv); -int SetMacPacketFilter(wlan_private *priv); -int SendNullPacket(wlan_private *priv, u8 pwr_mgmt); -void SendTxFeedback(wlan_private *priv); +int SendNullPacket(wlan_private * priv, u8 flags); BOOLEAN CheckLastPacketIndication(wlan_private *priv); - void Wep_encrypt(wlan_private *priv, u8* Buf, u32 Len); int FreeCmdBuffer(wlan_private *priv); void CleanUpCmdCtrlNode(CmdCtrlNode *pTempNode); @@ -49,16 +44,14 @@ void SetCmdCtrlNode(wlan_private * priv, CmdCtrlNode * pTempNode, - WLAN_OID cmd_oid, - u16 wait_option, - void *pdata_buf); + WLAN_OID cmd_oid, u16 wait_option, void *pdata_buf); + +BOOLEAN Is_Command_Allowed(wlan_private * priv); int PrepareAndSendCommand(wlan_private * priv, u16 cmd_no, u16 cmd_action, - u16 wait_option, - WLAN_OID cmd_oid, - void *pdata_buf); + u16 wait_option, WLAN_OID cmd_oid, void *pdata_buf); void QueueCmd(wlan_adapter *Adapter, CmdCtrlNode *CmdNode, BOOLEAN addtail); @@ -67,46 +60,63 @@ int ExecuteNextCommand(wlan_private *priv); int wlan_process_event(wlan_private *priv); void wlan_interrupt(struct net_device *); -int SetRadioControl( wlan_private *priv ); u32 index_to_data_rate(u8 index); u8 data_rate_to_index(u32 rate); void HexDump(char *prompt, u8 *data, int len); void get_version(wlan_adapter *adapter, char *version, int maxlen); void wlan_read_write_rfreg(wlan_private *priv); +#ifdef CONFIG_PROC_FS /** The proc fs interface */ void wlan_proc_entry(wlan_private *priv, struct net_device *dev); void wlan_proc_remove(wlan_private *priv); +int string_to_number(char *s); +#ifdef PROC_DEBUG void wlan_debug_entry(wlan_private *priv, struct net_device *dev); void wlan_debug_remove(wlan_private *priv); +#endif /* PROC_DEBUG */ +#endif /* CONFIG_PROC_FS */ int wlan_process_rx_command(wlan_private * priv); void wlan_process_tx(wlan_private * priv); void CleanupAndInsertCmd(wlan_private * priv, CmdCtrlNode * pTempCmd); void MrvDrvCommandTimerFunction(void *FunctionContext); #ifdef REASSOCIATION -void MrvDrvTimerFunction(void *FunctionContext); +void MrvDrvReassocTimerFunction(void *FunctionContext); #endif /* REASSOCIATION */ int wlan_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra); int wlan_set_regiontable(wlan_private *priv, u8 region, u8 band); +void wlan_clean_txrx(wlan_private * priv); -int ProcessRxedPacket(wlan_private *priv, struct sk_buff *); +int wlan_host_sleep_activated_event(wlan_private * priv); +int wlan_host_sleep_deactivated_event(wlan_private * priv); +int wlan_host_sleep_gpio_int_event(wlan_private * priv); +int wlan_deep_sleep_ioctl(wlan_private * priv, struct ifreq *rq); -int ProcessRxed_802_11_Packet(wlan_private *priv, struct sk_buff *); +int ProcessRxedPacket(wlan_private * priv, struct sk_buff *); void PSSleep(wlan_private *priv, int wait_option); void PSConfirmSleep(wlan_private *priv, u16 PSMode); void PSWakeup(wlan_private *priv, int wait_option); +void sdio_clear_imask(mmc_controller_t); +int sdio_check_idle_state(mmc_controller_t); +void sdio_print_imask(mmc_controller_t); +void sdio_clear_imask(mmc_controller_t); -#define SDIO_HEADER_LEN 4 +int sd_set_clock(wlan_private * priv, u32 slotFreq); +int sd_start_clock(wlan_private * priv); +int sd_stop_clock(wlan_private * priv); +int sd_set_bus_width(wlan_private * priv, u8 width); +int sd_set_gpo(wlan_private * priv, u8 on); void wlan_send_rxskbQ(wlan_private *priv); -extern CHANNEL_FREQ_POWER *find_cfp_by_band_and_channel(wlan_adapter *adapter, - u8 band, u16 channel); +extern CHANNEL_FREQ_POWER *find_cfp_by_band_and_channel(wlan_adapter * + adapter, u8 band, + u16 channel); extern void MacEventDisconnected(wlan_private * priv); @@ -114,8 +124,4 @@ void send_iwevcustom_event(wlan_private *priv, s8 *str); #endif -void cleanup_txqueues(wlan_private *priv); -void wlan_process_txqueue(wlan_private * priv); - - #endif /* _WLAN_DECL_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_defs.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_defs.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_defs.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_defs.h 2007-11-06 12:26:40.000000000 -0500 @@ -2,14 +2,13 @@ * @brief This header file contains global constant/enum definitions, * global variable declaration. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -22,8 +21,6 @@ /************************************************************* Change log: 10/11/05: add Doxygen format comments - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support - Monahans/Zylonite 01/11/06: Add NELEMENTS, BAND_XX defines 04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command ************************************************************/ @@ -95,68 +92,119 @@ #define B_BIT_6 0x40 #define B_BIT_7 0x80 - /** Debug Macro definition*/ -#ifdef DEBUG_LEVEL4 -#define PRINTM_INFO(msg...) printk(KERN_DEBUG msg) -#ifndef DEBUG_LEVEL3 -#define DEBUG_LEVEL3 -#endif -#else -#define PRINTM_INFO(msg...) -#endif +#ifdef DEBUG_LEVEL1 -#ifdef DEBUG_LEVEL3 -#define PRINTM_WARN(msg...) printk(KERN_DEBUG msg) -#ifndef DEBUG_LEVEL2 -#define DEBUG_LEVEL2 -#endif -#else -#define PRINTM_WARN(msg...) -#endif +extern u32 drvdbg; +extern u32 ifdbg; + +/* Debug message control bit definition for drvdbg */ +#define DBG_MSG DW_BIT_0 +#define DBG_FATAL DW_BIT_1 +#define DBG_ERROR DW_BIT_2 +#define DBG_DATA DW_BIT_3 +#define DBG_CMND DW_BIT_4 +#define DBG_EVENT DW_BIT_5 +#define DBG_INTR DW_BIT_6 + +#define DBG_DAT_D DW_BIT_16 +#define DBG_CMD_D DW_BIT_17 +#define DBG_FW_D DW_BIT_18 + +#define DBG_ENTRY DW_BIT_28 +#define DBG_WARN DW_BIT_29 +#define DBG_INFO DW_BIT_30 + +/* Debug message control bit definition for ifdbg */ +#define DBG_IF_D DW_BIT_0 #ifdef DEBUG_LEVEL2 -#define PRINTM_FATAL(msg...) printk(KERN_DEBUG msg) -#ifndef DEBUG_LEVEL1 -#define DEBUG_LEVEL1 -#endif +#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);} +#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);} +#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);} #else -#define PRINTM_FATAL(msg...) -#endif +#define PRINTM_INFO(msg...) do {} while (0) +#define PRINTM_WARN(msg...) do {} while (0) +#define PRINTM_ENTRY(msg...) do {} while (0) +#endif /* DEBUG_LEVEL2 */ -#ifdef DEBUG_LEVEL1 -#define PRINTM_MSG(msg...) printk(KERN_ALERT msg) -#else -#define PRINTM_MSG(msg...) -#endif +#define PRINTM_FW_D(msg...) {if (drvdbg & DBG_FW_D) printk(KERN_DEBUG msg);} +#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);} +#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);} + +#define PRINTM_INTR(msg...) {if (drvdbg & DBG_INTR) printk(KERN_DEBUG msg);} +#define PRINTM_EVENT(msg...) {if (drvdbg & DBG_EVENT) printk(msg);} +#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);} +#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);} +#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);} +#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);} +#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);} + +#define PRINTM_IF_D(msg...) {if (ifdbg & DBG_IF_D) printk(KERN_DEBUG msg);} #define PRINTM(level,msg...) PRINTM_##level(msg) +#else + +#define PRINTM(level,msg...) do {} while (0) + +#endif /* DEBUG_LEVEL1 */ + #define ASSERT(cond) \ do { \ if (!(cond)) \ PRINTM(INFO, "ASSERT: %s, %s:%i\n", \ __FUNCTION__, __FILE__, __LINE__); \ } while(0) -#define ENTER() PRINTM(INFO, "Enter: %s, %s:%i\n", __FUNCTION__, \ + +#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \ __FILE__, __LINE__) -#define LEAVE() PRINTM(INFO, "Leave: %s, %s:%i\n", __FUNCTION__, \ +#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \ __FILE__, __LINE__) -#if defined(DEBUG_LEVEL4) && defined(__KERNEL__) -static inline void HEXDUMP(char *prompt, u8 * buf, int len) +#if defined(DEBUG_LEVEL1) && defined(__KERNEL__) +#define DBG_DUMP_BUF_LEN 64 +#define MAX_DUMP_PER_LINE 16 +#define MAX_DATA_DUMP_LEN 48 + +static inline void +hexdump(char *prompt, u8 * buf, int len) { - int i = 0; + int i; + char dbgdumpbuf[DBG_DUMP_BUF_LEN]; + char *ptr = dbgdumpbuf; - printk(KERN_DEBUG "%s: ", prompt); + printk(KERN_DEBUG "%s:\n", prompt); for (i = 1; i <= len; i++) { - printk("%02x ", (u8) * buf); + ptr += sprintf(ptr, "%02x ", *buf); buf++; + if (i % MAX_DUMP_PER_LINE == 0) { + *ptr = 0; + printk(KERN_DEBUG "%s\n", dbgdumpbuf); + ptr = dbgdumpbuf; } - printk("\n"); } + if (len % MAX_DUMP_PER_LINE) { + *ptr = 0; + printk(KERN_DEBUG "%s\n", dbgdumpbuf); + } +} + +#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);} +#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);} +#define DBG_HEXDUMP_IF_D(x,y,z) {if (ifdbg & DBG_IF_D) hexdump(x,y,z);} +#define DBG_HEXDUMP_FW_D(x,y,z) {if (drvdbg & DBG_FW_D) hexdump(x,y,z);} + +#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z) + #else -#define HEXDUMP(x,y,z) +#define DBG_HEXDUMP(level,x,y,z) do {} while (0) +#endif + +#if defined(DEBUG_LEVEL2) && defined(__KERNEL__) +#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);} +#else +#define HEXDUMP(x,y,z) do {} while (0) #endif #ifndef TRUE @@ -170,6 +218,10 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + #ifndef NELEMENTS #define NELEMENTS(x) (sizeof(x)/sizeof(x[0])) #endif @@ -191,19 +243,17 @@ #define MRVDRV_SIZE_OF_PPA 0x00000008 #define MRVDRV_SIZE_OF_DPA 0x00000008 #define MRVDRV_NUM_OF_TxPD 0x00000020 -#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 #define MRVDRV_NUM_OF_CMD_BUFFER 10 #define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024) -#define MRVDRV_MAX_CHANNEL_SIZE 14 #define MRVDRV_MAX_BSSID_LIST 64 #define MRVDRV_TIMER_10S 10000 #define MRVDRV_TIMER_5S 5000 #define MRVDRV_TIMER_1S 1000 -#define MRVDRV_ASSOCIATION_TIME_OUT 255 #define MRVDRV_SNAP_HEADER_LEN 8 -#define MRVDRV_ETH_ADDR_LEN 6 #define MRVDRV_ETH_HEADER_SIZE 14 +#define ARP_FILTER_MAX_BUF_SIZE 20 + #define WLAN_UPLD_SIZE 2312 #define DEV_NAME_LEN 32 @@ -213,10 +263,9 @@ /** Misc constants */ /* This section defines 802.11 specific contants */ +#define SDIO_HEADER_LEN 4 -#define MRVDRV_MAX_SSID_LENGTH 32 -#define MRVDRV_MAX_BSS_DESCRIPTS 16 -#define MRVDRV_MAX_REGION_CODE 6 +#define MRVDRV_MAX_REGION_CODE 7 #define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe #define MRVDRV_MIN_MULTIPLE_DTIM 1 @@ -226,18 +275,15 @@ #define MRVDRV_DEFAULT_LISTEN_INTERVAL 10 #define MRVDRV_DEFAULT_LOCAL_LISTEN_INTERVAL 0 -#define MRVDRV_CHANNELS_PER_SCAN 4 -#define MRVDRV_MAX_CHANNELS_PER_SCAN 14 - #define MRVDRV_CHANNELS_PER_ACTIVE_SCAN 14 - -#define MRVDRV_DEBUG_RX_PATH 0x00000001 -#define MRVDRV_DEBUG_TX_PATH 0x00000002 - #define MRVDRV_MIN_BEACON_INTERVAL 20 #define MRVDRV_MAX_BEACON_INTERVAL 1000 #define MRVDRV_BEACON_INTERVAL 100 +#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ) +#define MRVDRV_SCAN_WATCHDOG_TIMEOUT (10 * HZ) +#define MRVDRV_DEEP_SLEEP_EXIT_TIMEOUT (10 * HZ) + /** TxPD Status */ /* Station firmware use TxPD status field to report final Tx transmit @@ -251,23 +297,10 @@ #define MRVDRV_TX_CTRL_NODE_STATUS_IDLE 0x0000 - -/** RxPD Status */ - -#define MRVDRV_RXPD_STATUS_OK 0x0001 -#define MRVDRV_RXPD_STATUS_MULTICAST_RX 0x0002 - - -/** RxPD Status - Received packet types */ - -#define MRVDRV_RXPD_STATUS_MAXTYPES_RX 6 - - /* Link spped */ #define MRVDRV_LINK_SPEED_1mbps 10000 /* in unit of 100bps */ #define MRVDRV_LINK_SPEED_11mbps 110000 - /** RSSI-related defines */ /* RSSI constants are used to implement 802.11 RSSI threshold * indication. if the Rx packet signal got too weak for 5 consecutive @@ -299,9 +332,6 @@ #define CMD_F_HOSTCMD (1 << 0) -/** WEP list macros & data structures */ -#define MRVL_KEY_BUFFER_SIZE_IN_BYTE 16 - /* to resolve CISCO AP extension */ #define MRVDRV_SCAN_LIST_VAR_IE_SPACE 256 #define FW_IS_WPA_ENABLED(_adapter) \ @@ -316,44 +346,33 @@ #define WLAN_802_11_AI_RESFI_STATUSCODE 2 #define WLAN_802_11_AI_RESFI_ASSOCIATIONID 4 +#define MRVL_NUM_WEP_KEY 4 + /** WPA Key LENGTH*/ /* Support 4 keys per key set */ #define MRVL_NUM_WPA_KEY_PER_SET 4 #define MRVL_MAX_WPA_KEY_LENGTH 32 -#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32 #define WPA_AES_KEY_LEN 16 #define WPA_TKIP_KEY_LEN 32 /* A few details needed for WEP (Wireless Equivalent Privacy) */ /* 104 bits */ -#define MAX_KEY_SIZE 13 +#define MAX_WEP_KEY_SIZE 13 /*40 bits RC4 - WEP*/ -#define MIN_KEY_SIZE 5 -#define MAX_SIZE_ARRA 64 +#define MIN_WEP_KEY_SIZE 5 #define RF_ANTENNA_1 0x1 #define RF_ANTENNA_2 0x2 #define RF_ANTENNA_AUTO 0xFFFF -#define HOSTCMD_SUPPORTED_RATES G_SUPPORTED_RATES - -#define BAND_B (0x01) -#define BAND_G (0x02) -#define ALL_802_11_BANDS (BAND_B | BAND_G) - - #define KEY_INFO_ENABLED 0x01 -/* For Wireless Extensions */ -#define OID_MRVL_MFG_COMMAND 1 - #define SNR_BEACON 0 #define SNR_RXPD 1 #define NF_BEACON 2 #define NF_RXPD 3 - /** MACRO DEFINITIONS */ #define CAL_NF(NF) ((s32)(-(s32)(NF))) #define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF))) @@ -361,6 +380,10 @@ #define DEFAULT_BCN_AVG_FACTOR 8 #define DEFAULT_DATA_AVG_FACTOR 8 +#define MIN_BCN_AVG_FACTOR 1 +#define MAX_BCN_AVG_FACTOR 8 +#define MIN_DATA_AVG_FACTOR 1 +#define MAX_DATA_AVG_FACTOR 8 #define AVG_SCALE 100 #define CAL_AVG_SNR_NF(AVG, SNRNF, N) \ (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \ @@ -371,14 +394,12 @@ #define WLAN_STATUS_FAILURE (-1) #define WLAN_STATUS_NOT_ACCEPTED (-2) -#define B_SUPPORTED_RATES 8 -#define G_SUPPORTED_RATES 14 - -#define WLAN_SUPPORTED_RATES 14 -#define WLAN_MAX_SSID_LENGTH 32 - -#define MAX_LEDS 8 +#define MAX_LEDS 3 +#define LED_DISABLED 16 +#define LED_BLINKING 2 +/* Max loop count (* 100ms) for waiting device ready at init time */ +#define MAX_WAIT_DEVICE_READY_COUNT 50 /* S_SWAP : To swap 2 u8 */ #define S_SWAP(a,b) do { \ @@ -399,6 +420,10 @@ #define wlan_cpu_to_le32(x) x #define wlan_cpu_to_le64(x) x +#define endian_convert_TxPD(x) +#define endian_convert_RxPD(x) +#define endian_convert_GET_LOG(x) + /** Global Varibale Declaration */ typedef struct _wlan_private wlan_private; typedef struct _wlan_adapter wlan_adapter; @@ -418,17 +443,22 @@ extern u8 AdhocRates_B[4]; extern wlan_private *wlanpriv; +#ifdef MFG_CMD_SUPPORT +#define SIOCCFMFG SIOCDEVPRIVATE +#endif /* MFG_CMD_SUPPORT */ /** ENUM definition*/ /** SNRNF_TYPE */ -typedef enum _SNRNF_TYPE { +typedef enum _SNRNF_TYPE +{ TYPE_BEACON = 0, TYPE_RXPD, MAX_TYPE_B } SNRNF_TYPE; /** SNRNF_DATA*/ -typedef enum _SNRNF_DATA { +typedef enum _SNRNF_DATA +{ TYPE_NOAVG = 0, TYPE_AVG, MAX_TYPE_AVG @@ -442,16 +472,6 @@ AUTH_ALG_NETWORK_EAP = 8, } WLAN_802_11_AUTH_ALG; -/** WLAN_802_1X_AUTH_ALG */ -typedef enum _WLAN_802_1X_AUTH_ALG -{ - WLAN_1X_AUTH_ALG_NONE = 1, - WLAN_1X_AUTH_ALG_LEAP = 2, - WLAN_1X_AUTH_ALG_TLS = 4, - WLAN_1X_AUTH_ALG_TTLS = 8, - WLAN_1X_AUTH_ALG_MD5 = 16, -} WLAN_802_1X_AUTH_ALG; - /** WLAN_802_11_ENCRYPTION_MODE */ typedef enum _WLAN_802_11_ENCRYPTION_MODE { @@ -471,10 +491,11 @@ /*not a real mode, defined as an upper bound */ Wlan802_11PowerModeMax -} WLAN_802_11_POWER_MODE, *PWLAN_802_11_POWER_MODE; +} WLAN_802_11_POWER_MODE; /** PS_STATE */ -typedef enum _PS_STATE{ +typedef enum _PS_STATE +{ PS_STATE_FULL_POWER, PS_STATE_AWAKE, PS_STATE_PRE_SLEEP, @@ -482,85 +503,66 @@ } PS_STATE; /** DNLD_STATE */ -typedef enum _DNLD_STATE{ +typedef enum _DNLD_STATE +{ DNLD_RES_RECEIVED, DNLD_DATA_SENT, DNLD_CMD_SENT } DNLD_STATE; /** WLAN_MEDIA_STATE */ -typedef enum _WLAN_MEDIA_STATE { - WlanMediaStateConnected, - WlanMediaStateDisconnected -} WLAN_MEDIA_STATE, *PWLAN_MEDIA_STATE; +typedef enum _WLAN_MEDIA_STATE +{ + WlanMediaStateDisconnected, + WlanMediaStateConnected +} WLAN_MEDIA_STATE; /** WLAN_802_11_PRIVACY_FILTER */ -typedef enum _WLAN_802_11_PRIVACY_FILTER { +typedef enum _WLAN_802_11_PRIVACY_FILTER +{ Wlan802_11PrivFilterAcceptAll, Wlan802_11PrivFilter8021xWEP -} WLAN_802_11_PRIVACY_FILTER, *PWLAN_802_11_PRIVACY_FILTER; +} WLAN_802_11_PRIVACY_FILTER; /** mv_ms_type */ -typedef enum _mv_ms_type{ +typedef enum _mv_ms_type +{ MVMS_DAT = 0, MVMS_CMD = 1, - MVMS_TXDONE = 2, - MVMS_EVENT + /* 2: reserved */ + MVMS_EVENT = 3 } mv_ms_type; -/* Set of 8 data rates */ -typedef u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES]; -typedef u8 WLAN_802_11_MAC_ADDRESS[ETH_ALEN]; - -/* Hardware status codes (OID_GEN_HARDWARE_STATUS). */ -/** WLAN_HARDWARE_STATUS */ -typedef enum _WLAN_HARDWARE_STATUS { +/* Hardware status codes */ +typedef enum _WLAN_HARDWARE_STATUS +{ WlanHardwareStatusReady, WlanHardwareStatusInitializing, WlanHardwareStatusReset, WlanHardwareStatusClosing, WlanHardwareStatusNotReady -} WLAN_HARDWARE_STATUS, *PWLAN_HARDWARE_STATUS; - -/** WLAN_802_11_NETWORK_TYPE */ -typedef enum _WLAN_802_11_NETWORK_TYPE { - Wlan802_11FH, - Wlan802_11DS, - /*defined as upper bound*/ - Wlan802_11NetworkTypeMax -} WLAN_802_11_NETWORK_TYPE, *PWLAN_802_11_NETWORK_TYPE; - -/** WLAN_802_11_NETWORK_INFRASTRUCTURE */ -typedef enum _WLAN_802_11_NETWORK_INFRASTRUCTURE { - Wlan802_11IBSS, - Wlan802_11Infrastructure, - Wlan802_11AutoUnknown, - /*defined as upper bound*/ - Wlan802_11InfrastructureMax -} WLAN_802_11_NETWORK_INFRASTRUCTURE, *PWLAN_802_11_NETWORK_INFRASTRUCTURE; +} WLAN_HARDWARE_STATUS; /** WLAN_802_11_AUTHENTICATION_MODE */ -typedef enum _WLAN_802_11_AUTHENTICATION_MODE { +typedef enum _WLAN_802_11_AUTHENTICATION_MODE +{ Wlan802_11AuthModeOpen = 0x00, Wlan802_11AuthModeShared = 0x01, Wlan802_11AuthModeNetworkEAP = 0x80, -} WLAN_802_11_AUTHENTICATION_MODE, *PWLAN_802_11_AUTHENTICATION_MODE; +} WLAN_802_11_AUTHENTICATION_MODE; /** WLAN_802_11_WEP_STATUS */ -typedef enum _WLAN_802_11_WEP_STATUS { +typedef enum _WLAN_802_11_WEP_STATUS +{ Wlan802_11WEPEnabled, Wlan802_11WEPDisabled, Wlan802_11WEPKeyAbsent, Wlan802_11WEPNotSupported - ,Wlan802_11Encryption2Enabled, - Wlan802_11Encryption2KeyAbsent, - Wlan802_11Encryption3Enabled, - Wlan802_11Encryption3KeyAbsent -} WLAN_802_11_WEP_STATUS, *PWLAN_802_11_WEP_STATUS -,WLAN_802_11_ENCRYPTION_STATUS, *PWLAN_802_11_ENCRYPTION_STATUS; +} WLAN_802_11_WEP_STATUS; /** SNMP_MIB_INDEX_e */ -typedef enum _SNMP_MIB_INDEX_e{ +typedef enum _SNMP_MIB_INDEX_e +{ DesiredBssType_i = 0, OpRateSet_i, BcnPeriod_i, @@ -581,35 +583,54 @@ } SNMP_MIB_INDEX_e; /** KEY_TYPE_ID */ -typedef enum _KEY_TYPE_ID{ +typedef enum _KEY_TYPE_ID +{ KEY_TYPE_ID_WEP = 0, KEY_TYPE_ID_TKIP, KEY_TYPE_ID_AES } KEY_TYPE_ID; /** KEY_INFO_WEP*/ -typedef enum _KEY_INFO_WEP{ +typedef enum _KEY_INFO_WEP +{ KEY_INFO_WEP_DEFAULT_KEY = 0x01 } KEY_INFO_WEP; /** KEY_INFO_TKIP */ -typedef enum _KEY_INFO_TKIP{ +typedef enum _KEY_INFO_TKIP +{ KEY_INFO_TKIP_MCAST = 0x01, KEY_INFO_TKIP_UNICAST = 0x02, KEY_INFO_TKIP_ENABLED = 0x04 } KEY_INFO_TKIP; /** KEY_INFO_AES*/ -typedef enum _KEY_INFO_AES{ +typedef enum _KEY_INFO_AES +{ KEY_INFO_AES_MCAST = 0x01, KEY_INFO_AES_UNICAST = 0x02, KEY_INFO_AES_ENABLED = 0x04 } KEY_INFO_AES; /** SNMP_MIB_VALUE_e */ -typedef enum _SNMP_MIB_VALUE_e{ +typedef enum _SNMP_MIB_VALUE_e +{ SNMP_MIB_VALUE_INFRA = 1, SNMP_MIB_VALUE_ADHOC } SNMP_MIB_VALUE_e; +/** HWRateDropMode */ +typedef enum _HWRateDropMode +{ + NO_HW_RATE_DROP, + HW_TABLE_RATE_DROP, + HW_SINGLE_RATE_DROP +} HWRateDropMode; + +#ifdef __KERNEL__ +extern struct iw_handler_def wlan_handler_def; +struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev); +int wlan_do_ioctl(struct net_device *dev, struct ifreq *req, int i); +#endif + #endif /* _WLAN_DEFS_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_dev.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_dev.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_dev.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_dev.h 2007-11-06 12:26:40.000000000 -0500 @@ -3,14 +3,13 @@ * to Marvell 802.11 NIC. It contains the Device Information * structure wlan_adapter. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -35,18 +34,18 @@ #define MAX_BSSID_PER_CHANNEL 16 -#define MAX_NUM_IN_TX_Q 3 - /* For the extended Scan */ #define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \ MRVDRV_MAX_CHANNEL_SIZE + 1 -typedef struct _PER_CHANNEL_BSSID_LIST_DATA { +typedef struct _PER_CHANNEL_BSSID_LIST_DATA +{ u8 ucStart; u8 ucNumEntry; } PER_CHANNEL_BSSID_LIST_DATA, *PPER_CHANNEL_BSSID_LIST_DATA; -typedef struct _MRV_BSSID_IE_LIST { +typedef struct _MRV_BSSID_IE_LIST +{ WLAN_802_11_FIXED_IEs FixedIE; u8 VariableIE[MRVDRV_SCAN_LIST_VAR_IE_SPACE]; } MRV_BSSID_IE_LIST, *PMRV_BSSID_IE_LIST; @@ -54,7 +53,8 @@ #define MAX_REGION_CHANNEL_NUM 2 /** Chan-Freq-TxPower mapping table*/ -typedef struct _CHANNEL_FREQ_POWER { +typedef struct _CHANNEL_FREQ_POWER +{ /** Channel Number */ u16 Channel; /** Frequency of this Channel */ @@ -66,7 +66,8 @@ } CHANNEL_FREQ_POWER; /** region-band mapping table*/ -typedef struct _REGION_CHANNEL { +typedef struct _REGION_CHANNEL +{ /** TRUE if this entry is valid */ BOOLEAN Valid; /** Region code for US, Japan ... */ @@ -79,36 +80,35 @@ CHANNEL_FREQ_POWER *CFP; } REGION_CHANNEL; - typedef struct _wlan_802_11_security_t { BOOLEAN WPAEnabled; BOOLEAN WPA2Enabled; WLAN_802_11_WEP_STATUS WEPStatus; WLAN_802_11_AUTHENTICATION_MODE AuthenticationMode; - WLAN_802_1X_AUTH_ALG Auth1XAlg; WLAN_802_11_ENCRYPTION_MODE EncryptionMode; } wlan_802_11_security_t; /** Current Basic Service Set State Structure */ -typedef struct CurrentBSSParams +typedef struct { - BSSDescriptor_t BSSDescriptor; - /** bssid */ - u8 bssid[MRVDRV_ETH_ADDR_LEN]; - /** ssid */ - WLAN_802_11_SSID ssid; /** band */ u8 band; - /** channel */ - u8 channel; + /** number of rates supported */ int NumOfRates; + /** supported rates*/ u8 DataRates[WLAN_SUPPORTED_RATES]; -} CurrentBSSParams; + + /** wmm enable? */ + u8 wmm_enabled; + + /** uapsd enable?*/ + u8 wmm_uapsd_enabled; +} CurrentBSSParams_t; /** sleep_params */ typedef struct SleepParams @@ -128,8 +128,36 @@ u16 reserved; } SleepPeriod; +#define DBG_CMD_NUM 5 + +/** info for debug purpose */ +typedef struct _wlan_dbg +{ + u32 num_cmd_host_to_card_failure; + u32 num_cmd_sleep_cfm_host_to_card_failure; + u32 num_tx_host_to_card_failure; + u32 num_event_deauth; + u32 num_event_disassoc; + u32 num_event_link_lost; + u32 num_cmd_deauth; + u32 num_cmd_assoc_success; + u32 num_cmd_assoc_failure; + u32 num_tx_timeout; + u32 num_cmd_timeout; + u16 TimeoutCmdId; + u16 TimeoutCmdAct; + u16 LastCmdId[DBG_CMD_NUM]; + u16 LastCmdAct[DBG_CMD_NUM]; + u16 LastCmdIndex; + u16 LastCmdRespId[DBG_CMD_NUM]; + u16 LastCmdRespIndex; + u16 LastEvent[DBG_CMD_NUM]; + u16 LastEventIndex; +} wlan_dbg; + /** Data structure for the Marvell WLAN device */ -typedef struct _wlan_dev { +typedef struct _wlan_dev +{ /** device name */ char name[DEV_NAME_LEN]; /** card pointer */ @@ -153,8 +181,16 @@ u8 dnld_sent; } wlan_dev_t, *pwlan_dev_t; +/* Data structure for WPS information */ +typedef struct +{ + IEEEtypes_VendorSpecific_t wpsIe; + BOOLEAN SessionEnable; +} wps_t; + /** Private structure for the MV device */ -struct _wlan_private { +struct _wlan_private +{ int open; wlan_adapter *adapter; @@ -163,8 +199,11 @@ struct net_device_stats stats; struct iw_statistics wstats; +#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_dev; +#endif + const struct firmware *fw_helper; const struct firmware *firmware; struct device *hotplug_device; @@ -177,16 +216,14 @@ #endif /* REASSOCIATION */ }; - /** Wlan Adapter data structure*/ struct _wlan_adapter { + u8 TmpTxBuf[WLAN_UPLD_SIZE] __ATTRIB_ALIGN__; /** STATUS variables */ WLAN_HARDWARE_STATUS HardwareStatus; u32 FWReleaseNumber; u32 fwCapInfo; - - u8 TmpTxBuf[WLAN_UPLD_SIZE]; u8 chip_rev; /** Command-related variables */ @@ -220,7 +257,7 @@ #ifdef REASSOCIATION /**Reassociation timer*/ - BOOLEAN TimerIsSet; + BOOLEAN ReassocTimerIsSet; WLAN_DRV_TIMER MrvDrvTimer __ATTRIB_ALIGN__; #endif /* REASSOCIATION */ @@ -229,12 +266,15 @@ u8 HisRegCpy; + /** bg scan related variable */ + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgScanConfig; + u32 bgScanConfigSize; - - + /** WMM related variable*/ + WMM_DESC wmm; /** current ssid/bssid related parameters*/ - CurrentBSSParams CurBssParams; + CurrentBSSParams_t CurBssParams; WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; @@ -249,12 +289,13 @@ u8 ScanType; u32 ScanMode; + u16 SpecificScanTime; + u16 ActiveScanTime; + u16 PassiveScanTime; u16 BeaconPeriod; u8 AdhocCreate; - - /** Capability Info used in Association, start, join */ - IEEEtypes_CapInfo_t capInfo; + BOOLEAN AdhocLinkSensed; #ifdef REASSOCIATION /** Reassociation on and off */ @@ -270,14 +311,10 @@ [MRVDRV_ETH_ADDR_LEN]; u32 NumOfMulticastMACAddr; - /** 802.11 statistics */ - HostCmd_DS_802_11_GET_STAT wlan802_11Stat; - - BOOLEAN AdHocCreated; - BOOLEAN AdHocFailed; - - u16 EnableHwAuto; + u16 HWRateDropMode; u16 RateBitmap; + u16 Threshold; + u16 FinalRate; /** control G Rates */ BOOLEAN adhoc_grate_enabled; @@ -292,28 +329,23 @@ BOOLEAN Is_DataRate_Auto; /** number of association attempts for the current SSID cmd */ - u32 m_NumAssociationAttemp; u16 ListenInterval; - u16 Prescan; u8 TxRetryCount; /** Tx-related variables (for single packet tx) */ - spinlock_t TxSpinLock __ATTRIB_ALIGN__; struct sk_buff *CurrentTxSkb; struct sk_buff RxSkbQ; - struct sk_buff TxSkbQ; - u32 TxSkbNum; - u16 TxLockFlag; + BOOLEAN TxLockFlag; u16 gen_null_pkg; spinlock_t CurrentTxLock __ATTRIB_ALIGN__; /** NIC Operation characteristics */ - u32 LinkSpeed; u16 CurrentPacketFilter; u32 MediaConnectStatus; u16 RegionCode; - u16 RegionTableIndex; u16 TxPowerLevel; + u8 MaxTxPowerLevel; + u8 MinTxPowerLevel; /** POWER MANAGEMENT AND PnP SUPPORT */ BOOLEAN SurpriseRemoved; @@ -322,19 +354,53 @@ u16 PSMode; /* Wlan802_11PowerModeCAM=disable Wlan802_11PowerModeMAX_PSP=enable */ u16 MultipleDtim; + u16 BCNMissTimeOut; u32 PSState; BOOLEAN NeedToWakeup; PS_CMD_ConfirmSleep PSConfirmSleep; u16 LocalListenInterval; u16 NullPktInterval; + u16 AdhocAwakePeriod; + u16 fwWakeupMethod; + BOOLEAN IsDeepSleep; + BOOLEAN IsAutoDeepSleepEnabled; + BOOLEAN bWakeupDevRequired; + u32 WakeupTries; + BOOLEAN bHostSleepConfigured; + HostCmd_DS_802_11_HOST_SLEEP_CFG HSCfg; + /** ARP filter related variable */ + u8 ArpFilter[ARP_FILTER_MAX_BUF_SIZE]; + u32 ArpFilterSize; + BOOLEAN HS_Activated; /** Encryption parameter */ wlan_802_11_security_t SecInfo; - MRVL_WEP_KEY WepKey[4]; + MRVL_WEP_KEY WepKey[MRVL_NUM_WEP_KEY]; u16 CurrentWepKeyIndex; - WLAN_802_11_ENCRYPTION_STATUS EncryptionStatus; + + /** Buffer for TLVs passed from the application to be inserted into the + * association request to firmware + */ + u8 mrvlAssocTlvBuffer[MRVDRV_ASSOC_TLV_BUF_SIZE]; + + /** Length of the data stored in mrvlAssocTlvBuffer*/ + u8 mrvlAssocTlvBufferLen; + + /** Buffer to store the association response for application retrieval */ + u8 assocRspBuffer[MRVDRV_ASSOC_RSP_BUF_SIZE]; + + /** Length of the data stored in assocRspBuffer */ + int assocRspSize; + + /** Generice IEEE IEs passed from the application to be inserted into the + * association request to firmware + */ + u8 genIeBuffer[MRVDRV_GENIE_BUF_SIZE]; + + /** Length of the data stored in genIeBuffer */ + u8 genIeBufferLen; BOOLEAN IsGTK_SET; @@ -342,11 +408,11 @@ u8 Wpa_ie[256]; u8 Wpa_ie_len; - MRVL_WPA_KEY WpaPwkKey, WpaGrpKey; - HostCmd_DS_802_11_KEY_MATERIAL aeskey; /* Advanced Encryption Standard */ + BOOLEAN AdhocAESEnabled; + wait_queue_head_t cmd_EncKey __ATTRIB_ALIGN__; u16 RxAntennaMode; u16 TxAntennaMode; @@ -361,16 +427,13 @@ u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; u16 nextSNRNF; u16 numSNRNF; - u32 RxPDSNRAge; + u32 RxPDAge; u16 RxPDRate; BOOLEAN RadioOn; - u32 Preamble; - - /** Multi Bands Parameter*/ - u8 SupportedRates[G_SUPPORTED_RATES]; /** Blue Tooth Co-existence Arbitration */ + HostCmd_DS_802_11_BCA_TIMESHARE bca_ts; /** sleep_params */ SleepParams sp; @@ -378,8 +441,6 @@ /** sleep_period (Enhanced Power Save) */ SleepPeriod sleep_period; - /** RF calibration data */ - #define MAX_REGION_CHANNEL_NUM 2 /** Region Channel data */ REGION_CHANNEL region_channel[MAX_REGION_CHANNEL_NUM]; @@ -392,15 +453,13 @@ /** FSM variable for 11d support */ wlan_802_11d_state_t State11D; + u8 beaconBuffer[MAX_SCAN_BEACON_BUFFER]; + u8 *pBeaconBufEnd; /** MISCELLANEOUS */ /* Card Information Structure */ u8 CisInfoBuf[512]; u16 CisInfoLen; - u8 *pRdeeprom; - wlan_offset_value OffsetValue; - - wait_queue_head_t cmd_get_log; HostCmd_DS_802_11_GET_LOG LogMsg; u16 ScanProbes; @@ -408,11 +467,12 @@ u32 PktTxCtrl; u16 TxRate; - u32 linkmode; - u32 radiomode; - u32 debugmode; -}; + wps_t wps; + + wlan_dbg dbg; + wlan_subscribe_event subevent; + u32 num_cmd_timeout; +}; #endif /* _WLAN_DEV_H_ */ - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_fw.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_fw.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_fw.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_fw.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,14 @@ /** @file wlan_fw.c - * @brief This file contains the initialization for FW and HW + * @brief This file contains the initialization for FW + * and HW * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -26,6 +26,7 @@ Cleanup association response handler initialization. 01/06/05: Add FW file read 05/08/06: Remove the 2nd GET_HW_SPEC command and TempAddr/PermanentAddr + 06/30/06: replaced MODULE_PARM(name, type) with module_param(name, type, perm) ********************************************************/ @@ -38,12 +39,16 @@ Local Variables ********************************************************/ -u8 *helper_name=NULL; -u8 *fw_name=NULL; +char *helper_name = NULL; +char *fw_name = NULL; -MODULE_PARM( helper_name, "s"); -MODULE_PARM( fw_name, "s" ); +module_param(helper_name, charp, 0); +module_param(fw_name, charp, 0); +#ifdef MFG_CMD_SUPPORT +int mfgmode = 0; +module_param(mfgmode, int, 0); +#endif /******************************************************** Global Variables @@ -61,7 +66,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_setup_station_hw(wlan_private *priv) +int +wlan_setup_station_hw(wlan_private * priv) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *adapter = priv->adapter; @@ -70,37 +76,50 @@ sbi_disable_host_int(priv); - - if ((ret=request_firmware(&priv->firmware, fw_name, + if ((ret = + request_firmware(&priv->fw_helper, helper_name, priv->hotplug_device)) < 0) { - PRINTM(MSG, "request_firmware() failed, error code = %#x\n", ret); - PRINTM(MSG, "%s not found in /lib/firmware\n", fw_name); + PRINTM(FATAL, + "request_firmware() failed (helper), error code = %#x\n", ret); goto done; } - ret = sbi_prog_firmware(priv); + if ((ret = + request_firmware(&priv->firmware, fw_name, + priv->hotplug_device)) < 0) { + PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret); + goto done; + } - release_firmware(priv->firmware); + /* Download the helper */ + ret = sbi_prog_helper(priv); if (ret) { PRINTM(INFO, "Bootloader in invalid state!\n"); ret = WLAN_STATUS_FAILURE; goto done; } - + /* Download the main firmware via the helper firmware */ + if (sbi_prog_firmware_w_helper(priv)) { + PRINTM(INFO, "Wlan FW download failed!\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } /* check if the fimware is downloaded successfully or not */ if (sbi_verify_fw_download(priv)) { - PRINTM(INFO, "Firmware failed to be active in time!\n"); + PRINTM(INFO, "FW failed to be active in time!\n"); ret = WLAN_STATUS_FAILURE; goto done; } - #define RF_REG_OFFSET 0x07 #define RF_REG_VALUE 0xc8 sbi_enable_host_int(priv); +#ifdef MFG_CMD_SUPPORT + if (mfgmode == 0) { +#endif /* * Read MAC address from HW @@ -108,31 +127,71 @@ memset(adapter->CurrentAddr, 0xff, MRVDRV_ETH_ADDR_LEN); ret = PrepareAndSendCommand(priv, HostCmd_CMD_GET_HW_SPEC, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { ret = WLAN_STATUS_FAILURE; goto done; } - SetMacPacketFilter(priv); + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_MAC_CONTROL, + 0, HostCmd_OPTION_WAITFORRSP, 0, + &adapter->CurrentPacketFilter); + if (ret) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_FW_WAKE_METHOD, + HostCmd_ACT_GET, + HostCmd_OPTION_WAITFORRSP, 0, + &priv->adapter->fwWakeupMethod); + if (ret) { + ret = WLAN_STATUS_FAILURE; + goto done; + } +#ifdef MFG_CMD_SUPPORT + } +#endif - /* Get the supported Data Rates */ - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DATA_RATE, - HostCmd_ACT_GET_TX_RATE, - HostCmd_OPTION_WAITFORRSP, - 0, NULL); +#ifdef MFG_CMD_SUPPORT + if (mfgmode == 0) { +#endif + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_RATE_ADAPT_RATESET, + HostCmd_ACT_GEN_GET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); + if (ret) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + priv->adapter->DataRate = 0; + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_RF_TX_POWER, + HostCmd_ACT_GEN_GET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { ret = WLAN_STATUS_FAILURE; goto done; } +#ifdef MFG_CMD_SUPPORT + } +#endif ret = WLAN_STATUS_SUCCESS; done: + if (priv->fw_helper) { + release_firmware(priv->fw_helper); + } + if (priv->firmware) { + release_firmware(priv->firmware); + } + LEAVE(); return (ret); @@ -144,7 +203,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -static void init_sync_objects(wlan_private *priv) +static void +init_sync_objects(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; @@ -154,9 +214,8 @@ #ifdef REASSOCIATION /* Initialize the timer for the reassociation */ - InitializeTimer(&Adapter->MrvDrvTimer, - MrvDrvTimerFunction, priv); - Adapter->TimerIsSet = FALSE; + InitializeTimer(&Adapter->MrvDrvTimer, MrvDrvReassocTimerFunction, priv); + Adapter->ReassocTimerIsSet = FALSE; #endif /* REASSOCIATION */ return; @@ -169,7 +228,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_allocate_adapter(wlan_private *priv) +static int +wlan_allocate_adapter(wlan_private * priv) { u32 ulBufSize; wlan_adapter *Adapter = priv->adapter; @@ -179,24 +239,35 @@ /* Allocate buffer to store the BSSID list */ ulBufSize = sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST; if (!(pTempScanTable = kmalloc(ulBufSize, GFP_KERNEL))) { - wlan_free_adapter(priv); return WLAN_STATUS_FAILURE; } Adapter->ScanTable = pTempScanTable; memset(Adapter->ScanTable, 0, ulBufSize); + if (!(Adapter->bgScanConfig = + kmalloc(sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG), GFP_KERNEL))) { + return WLAN_STATUS_FAILURE; + } + Adapter->bgScanConfigSize = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG); + memset(Adapter->bgScanConfig, 0, Adapter->bgScanConfigSize); + spin_lock_init(&Adapter->QueueSpinLock); /* Allocate the command buffers */ - AllocateCmdBuffer(priv); + if (AllocateCmdBuffer(priv) != WLAN_STATUS_SUCCESS) { + return WLAN_STATUS_FAILURE; + } memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep)); Adapter->PSConfirmSleep.SeqNum = wlan_cpu_to_le16(++Adapter->SeqNum); - Adapter->PSConfirmSleep.Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE); - Adapter->PSConfirmSleep.Size = wlan_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep)); + Adapter->PSConfirmSleep.Command = + wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE); + Adapter->PSConfirmSleep.Size = + wlan_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep)); Adapter->PSConfirmSleep.Result = 0; - Adapter->PSConfirmSleep.Action = wlan_cpu_to_le16(HostCmd_SubCmd_Sleep_Confirmed); + Adapter->PSConfirmSleep.Action = + wlan_cpu_to_le16(HostCmd_SubCmd_Sleep_Confirmed); return WLAN_STATUS_SUCCESS; } @@ -208,7 +279,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -static void wlan_init_adapter(wlan_private *priv) +static void +wlan_init_adapter(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; int i; @@ -223,7 +295,7 @@ Adapter->ATIMEnabled = FALSE; Adapter->MediaConnectStatus = WlanMediaStateDisconnected; - Adapter->LinkSpeed = MRVDRV_LINK_SPEED_1mbps; + memset(Adapter->CurrentAddr, 0xff, MRVDRV_ETH_ADDR_LEN); /* Status variables */ @@ -235,14 +307,19 @@ /* scan mode */ Adapter->ScanMode = HostCmd_BSS_TYPE_ANY; + /* scan time */ + Adapter->SpecificScanTime = MRVDRV_SPECIFIC_SCAN_CHAN_TIME; + Adapter->ActiveScanTime = MRVDRV_ACTIVE_SCAN_CHAN_TIME; + Adapter->PassiveScanTime = MRVDRV_PASSIVE_SCAN_CHAN_TIME; + /* 802.11 specific */ Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled; for(i = 0; i < sizeof(Adapter->WepKey)/sizeof(Adapter->WepKey[0]); i++) memset(&Adapter->WepKey[i], 0, sizeof(MRVL_WEP_KEY)); Adapter->CurrentWepKeyIndex = 0; Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen; - Adapter->SecInfo.Auth1XAlg = WLAN_1X_AUTH_ALG_NONE; Adapter->SecInfo.EncryptionMode = CIPHER_NONE; + Adapter->AdhocAESEnabled = FALSE; Adapter->InfrastructureMode = Wlan802_11Infrastructure; Adapter->NumInScanTable = 0; @@ -250,8 +327,8 @@ #ifdef REASSOCIATION OS_INIT_SEMAPHORE(&Adapter->ReassocSem); #endif + Adapter->pBeaconBufEnd = Adapter->beaconBuffer; - Adapter->Prescan = CMD_ENABLED; Adapter->HisRegCpy |= HIS_TxDnLdRdy; memset(&Adapter->CurBssParams, 0, sizeof(Adapter->CurBssParams)); @@ -264,19 +341,19 @@ Adapter->RadioOn = RADIO_ON; #ifdef REASSOCIATION +#if (WIRELESS_EXT >= 18) + Adapter->Reassoc_on = FALSE; +#else Adapter->Reassoc_on = TRUE; +#endif #endif /* REASSOCIATION */ Adapter->TxAntenna = RF_ANTENNA_2; Adapter->RxAntenna = RF_ANTENNA_AUTO; + Adapter->HWRateDropMode = HW_TABLE_RATE_DROP; Adapter->Is_DataRate_Auto = TRUE; Adapter->BeaconPeriod = MRVDRV_BEACON_INTERVAL; - // set default value of capInfo. -#define SHORT_PREAMBLE_ALLOWED 1 - memset(&Adapter->capInfo, 0, sizeof(Adapter->capInfo)); - Adapter->capInfo.ShortPreamble = SHORT_PREAMBLE_ALLOWED; - Adapter->AdhocChannel = DEFAULT_AD_HOC_CHANNEL; Adapter->PSMode = Wlan802_11PowerModeCAM; @@ -287,21 +364,29 @@ Adapter->PSState = PS_STATE_FULL_POWER; Adapter->NeedToWakeup = FALSE; Adapter->LocalListenInterval = 0; /* default value in firmware will be used */ + Adapter->fwWakeupMethod = WAKEUP_FW_UNCHANGED; + Adapter->IsDeepSleep = FALSE; + Adapter->IsAutoDeepSleepEnabled = FALSE; + Adapter->bWakeupDevRequired = FALSE; + Adapter->WakeupTries = 0; + Adapter->bHostSleepConfigured = FALSE; + Adapter->HSCfg.conditions = HOST_SLEEP_CFG_CANCEL; + Adapter->HSCfg.gpio = 0; + Adapter->HSCfg.gap = 0; Adapter->DataRate = 0; // Initially indicate the rate as auto Adapter->adhoc_grate_enabled=FALSE; Adapter->IntCounter = Adapter->IntCounterSaved = 0; - INIT_LIST_HEAD((struct list_head *)&Adapter->RxSkbQ); - INIT_LIST_HEAD((struct list_head *)&Adapter->TxSkbQ); - Adapter->TxSkbNum = 0; + INIT_LIST_HEAD((struct list_head *) &Adapter->RxSkbQ); + Adapter->gen_null_pkg = TRUE; /*Enable NULL Pkg generation */ - Adapter->EncryptionStatus = Wlan802_11WEPDisabled; + init_waitqueue_head(&Adapter->cmd_EncKey); spin_lock_init(&Adapter->CurrentTxLock); @@ -321,9 +406,11 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_init_fw(wlan_private *priv) +int +wlan_init_fw(wlan_private * priv) { int ret = WLAN_STATUS_SUCCESS; + wlan_adapter *Adapter = priv->adapter; ENTER(); @@ -340,13 +427,14 @@ /* download fimrware etc. */ if ((ret = wlan_setup_station_hw(priv)) != WLAN_STATUS_SUCCESS) { + Adapter->HardwareStatus = WlanHardwareStatusNotReady; ret = WLAN_STATUS_FAILURE; goto done; } - /* init 802.11d */ wlan_init_11d( priv ); + Adapter->HardwareStatus = WlanHardwareStatusReady; ret = WLAN_STATUS_SUCCESS; done: LEAVE(); @@ -359,7 +447,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -void wlan_free_adapter(wlan_private *priv) +void +wlan_free_adapter(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; @@ -381,26 +470,27 @@ FreeTimer(&Adapter->MrvDrvCommandTimer); #ifdef REASSOCIATION PRINTM(INFO, "Free MrvDrvTimer\n"); - if (Adapter->TimerIsSet) { + if (Adapter->ReassocTimerIsSet) { CancelTimer(&Adapter->MrvDrvTimer); - Adapter->TimerIsSet = FALSE; + Adapter->ReassocTimerIsSet = FALSE; } FreeTimer(&Adapter->MrvDrvTimer); #endif /* REASSOCIATION */ + if (Adapter->bgScanConfig) { + kfree(Adapter->bgScanConfig); + Adapter->bgScanConfig = NULL; + } - /* The following is needed for Threadx and are dummy in linux */ OS_FREE_LOCK(&Adapter->CurrentTxLock); OS_FREE_LOCK(&Adapter->QueueSpinLock); - PRINTM(INFO, "Free ScanTable\n"); if (Adapter->ScanTable) { kfree(Adapter->ScanTable); Adapter->ScanTable = NULL; } - PRINTM(INFO, "Free Adapter\n"); /* Free the adapter object itself */ @@ -408,82 +498,3 @@ priv->adapter = NULL; LEAVE(); } - -/** - * @brief This function handles the timeout of command sending. - * It will re-send the same command again. - * - * @param FunctionContext A pointer to FunctionContext - * @return n/a - */ -void MrvDrvCommandTimerFunction(void *FunctionContext) -{ - wlan_private *priv = (wlan_private *)FunctionContext; - wlan_adapter *Adapter = priv->adapter; - CmdCtrlNode *pTempNode; - ulong flags; - - ENTER(); - - PRINTM(FATAL, "MrvDrvCommandTimer fired.\n"); - - Adapter->CommandTimerIsSet = FALSE; - - pTempNode = Adapter->CurCmd; - - if(pTempNode == NULL){ - PRINTM(INFO, "PTempnode Empty\n"); - return ; - } - - spin_lock_irqsave(&Adapter->QueueSpinLock, flags); - Adapter->CurCmd = NULL; - spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); - - PRINTM(INFO, "Re-sending same command as it timeout...!\n"); - QueueCmd(Adapter,pTempNode, FALSE); - - wake_up_interruptible(&priv->MainThread.waitQ); - - LEAVE(); - return; -} - -#ifdef REASSOCIATION -/** - * @brief This function triggers re-association by waking up - * re-assoc thread. - * - * @param FunctionContext A pointer to FunctionContext - * @return n/a - */ -void MrvDrvTimerFunction(void *FunctionContext) -{ - wlan_private *priv = (wlan_private *) FunctionContext; - wlan_adapter *Adapter = priv->adapter; - OS_INTERRUPT_SAVE_AREA; - - ENTER(); - - PRINTM(INFO, "MrvDrvTimer fired.\n"); - Adapter->TimerIsSet = FALSE; - if (Adapter->PSState != PS_STATE_FULL_POWER) { - /* wait until Exit_PS command returns */ - Adapter->TimerIsSet = TRUE; - ModTimer(&Adapter->MrvDrvTimer, MRVDRV_TIMER_1S); - PRINTM(INFO, "MrvDrvTimerFunction(PSState=%d) waiting" - "for Exit_PS done\n",Adapter->PSState); - LEAVE(); - return; - } - - PRINTM(INFO, "Waking Up the Event Thread\n"); - - wake_up_interruptible(&priv->ReassocThread.waitQ); - - LEAVE(); - return; -} -#endif /* REASSOCIATION */ - - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_fw.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_fw.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_fw.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_fw.h 1969-12-31 19:00:00.000000000 -0500 @@ -1,48 +0,0 @@ -/** @file wlan_fw.h - * @brief This header file contains FW interface related definitions. - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - * - */ -/************************************************************* -Change log: - 09/26/05: add Doxygen format comments - ************************************************************/ - -#ifndef _WLAN_FW_H_ -#define _WLAN_FW_H_ - -#ifndef DEV_NAME_LEN -#define DEV_NAME_LEN 32 -#endif - -#define MAXKEYLEN 13 - -/* The number of times to try when waiting for downloaded firmware to - become active. (polling the scratch register). */ - -#define MAX_FIRMWARE_POLL_TRIES 100 - -#define FIRMWARE_TRANSFER_BLOCK_SIZE 1536 - -/** function prototypes */ -int wlan_init_fw(wlan_private *priv); -int wlan_disable_host_int(wlan_private *priv,u8 reg); -int wlan_enable_host_int(wlan_private *priv, u8 mask); -int wlan_free_cmd_buffers(wlan_private *priv); - -#endif /* _WLAN_FW_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_join.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_join.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_join.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_join.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,6 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** @file wlan_join.c * * @brief Functions implementing wlan infrastructure and adhoc join routines @@ -9,16 +6,13 @@ * for sending adhoc start, adhoc join, and association commands * to the firmware. * - * @sa wlan_join.h - * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -38,7 +32,6 @@ #include "include.h" - /** * @brief This function finds out the common rates between rate1 and rate2. * @@ -55,33 +48,36 @@ * * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int get_common_rates(wlan_adapter* Adapter, u8* rate1, +static int +get_common_rates(wlan_adapter * Adapter, u8 * rate1, int rate1_size, u8* rate2, int rate2_size) { u8* ptr = rate1; int ret = WLAN_STATUS_SUCCESS; - u8 tmp[30]; - int i; + u8 *tmp = NULL; + int i, j; - memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp, rate1, MIN(rate1_size,sizeof(tmp))); - memset(rate1, 0, rate1_size); + if (!(tmp = kmalloc(rate1_size, GFP_KERNEL))) { + PRINTM(WARN, "Allocate buffer for common rates failed\n"); + return -ENOMEM; + } - /* Mask the top bit of the original values */ - for (i = 0; tmp[i] && i < sizeof(tmp); i++) - tmp[i] &= 0x7F; + memcpy(tmp, rate1, rate1_size); + memset(rate1, 0, rate1_size); for (i = 0; rate2[i] && i < rate2_size; i++) { - /* Check for Card Rate in tmp, excluding the top bit */ - if (strchr(tmp, rate2[i] & 0x7F)) { - /* Values match, so copy the Card Rate to rate1 */ - *rate1++ = rate2[i]; + for (j = 0; tmp[j] && j < rate1_size; j++) { + /* Check common rate, excluding the bit for basic rate */ + if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { + *rate1++ = tmp[j]; + break; + } } } - HEXDUMP("rate1 (AP) Rates:", tmp, sizeof(tmp)); - HEXDUMP("rate2 (Card) Rates:", rate2, rate2_size); - HEXDUMP("Common Rates:", ptr, rate1_size); + HEXDUMP("rate1 (AP) Rates", tmp, rate1_size); + HEXDUMP("rate2 (Card) Rates", rate2, rate2_size); + HEXDUMP("Common Rates", ptr, rate1 - ptr); PRINTM(INFO, "Tx DataRate is set to 0x%X\n", Adapter->DataRate); if (!Adapter->Is_DataRate_Auto) { @@ -101,37 +97,136 @@ ret = WLAN_STATUS_SUCCESS; done: + kfree(tmp); return ret; } +/** + * @brief Create the intersection of the rates supported by a target BSS and + * our Adapter settings for use in an assoc/join command. + * + * @param Adapter A pointer to wlan_adapter structure + * @param pBSSDesc BSS Descriptor whose rates are used in the setup + * @param pOutRates Output: Octet array of rates common between the BSS + * and the Adapter supported rates settings + * @param pOutRatesSize Output: Number of rates/octets set in pOutRates + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + * + */ +static int +setup_rates_from_bssdesc(wlan_adapter * Adapter, + BSSDescriptor_t * pBSSDesc, + u8 * pOutRates, int *pOutRatesSize) +{ + u8 *card_rates; + int card_rates_size; + + ENTER(); + + memcpy(pOutRates, pBSSDesc->SupportedRates, WLAN_SUPPORTED_RATES); + + card_rates = SupportedRates; + card_rates_size = sizeof(SupportedRates); + + if (get_common_rates(Adapter, pOutRates, WLAN_SUPPORTED_RATES, + card_rates, card_rates_size)) { + *pOutRatesSize = 0; + PRINTM(INFO, "get_common_rates failed\n"); + LEAVE(); + return WLAN_STATUS_FAILURE; + } + + *pOutRatesSize = MIN(strlen(pOutRates), WLAN_SUPPORTED_RATES); + + LEAVE(); + + return WLAN_STATUS_SUCCESS; +} /** - * @brief Send Deauth Request + * @brief Retrieve the association response * * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -int wlan_send_deauth(wlan_private* priv) +int +wlan_get_assoc_rsp_ioctl(wlan_private * priv, struct iwreq *wrq) { wlan_adapter* Adapter = priv->adapter; - int ret = WLAN_STATUS_SUCCESS; + int copySize; - ENTER(); + /* + * Set the amount to copy back to the application as the minimum of the + * available assoc resp data or the buffer provided by the application + */ + copySize = MIN(Adapter->assocRspSize, wrq->u.data.length); - if (Adapter->InfrastructureMode == Wlan802_11Infrastructure && - Adapter->MediaConnectStatus == WlanMediaStateConnected) { + /* Copy the (re)association response back to the application */ + if (copy_to_user(wrq->u.data.pointer, Adapter->assocRspBuffer, copySize)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } - ret = SendDeauthentication(priv); + /* Returned copy length */ + wrq->u.data.length = copySize; + + /* Reset assoc buffer */ + Adapter->assocRspSize = 0; + + /* No error on return */ + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Set an opaque block of Marvell TLVs for insertion into the + * association command + * + * Pass an opaque block of data, expected to be Marvell TLVs, to the driver + * for eventual passthrough to the firmware in an associate/join + * (and potentially start) command. + * + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_set_mrvl_tlv_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; + /* If the passed length is zero, reset the buffer */ + if (wrq->u.data.length == 0) { + Adapter->mrvlAssocTlvBufferLen = 0; } else { - LEAVE(); - return -ENOTSUPP; + /* + * Verify that the passed length is not larger than the available + * space remaining in the buffer + */ + if (wrq->u.data.length < (sizeof(Adapter->mrvlAssocTlvBuffer) + - Adapter->mrvlAssocTlvBufferLen)) { + /* Append the passed data to the end of the mrvlAssocTlvBuffer */ + if (copy_from_user(Adapter->mrvlAssocTlvBuffer + + Adapter->mrvlAssocTlvBufferLen, + wrq->u.data.pointer, wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; } - LEAVE(); - return ret; + /* Increment the stored buffer length by the size passed */ + Adapter->mrvlAssocTlvBufferLen += wrq->u.data.length; + } else { + /* Passed data does not fit in the remaining buffer space */ + ret = WLAN_STATUS_FAILURE; + } } + /* Return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ + return ret; +} /** * @brief Stop Adhoc Network @@ -139,7 +234,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_do_adhocstop_ioctl(wlan_private* priv) +int +wlan_do_adhocstop_ioctl(wlan_private * priv) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -161,7 +257,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Set essid * @@ -171,7 +266,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -int wlan_set_essid(struct net_device* dev, struct iw_request_info* info, +int +wlan_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point* dwrq, char* extra) { wlan_private* priv = dev->priv; @@ -182,17 +278,23 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + /* Clear any past association response stored for application retrieval */ + Adapter->assocRspSize = 0; #ifdef REASSOCIATION // cancel re-association timer if there's one - if (Adapter->TimerIsSet == TRUE) { + if (Adapter->ReassocTimerIsSet == TRUE) { CancelTimer(&Adapter->MrvDrvTimer); - Adapter->TimerIsSet = FALSE; + Adapter->ReassocTimerIsSet = FALSE; } if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->ReassocSem)) { - PRINTM(FATAL, "Acquire semaphore error, wlan_set_essid\n"); + PRINTM(ERROR, "Acquire semaphore error, wlan_set_essid\n"); return -EBUSY; } #endif /* REASSOCIATION */ @@ -216,8 +318,9 @@ } } else { /* Set the SSID */ - memcpy(reqSSID.Ssid, extra, dwrq->length); reqSSID.SsidLength = dwrq->length - 1; + memcpy(reqSSID.Ssid, extra, reqSSID.SsidLength); + } PRINTM(INFO, "Requested new SSID = %s\n", @@ -229,28 +332,28 @@ goto setessid_ret; } - /* If the requested SSID is not a NULL string, join */ - if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { /* infrastructure mode */ PRINTM(INFO, "SSID requested = %s\n", reqSSID.Ssid); - if (Adapter->MediaConnectStatus == WlanMediaStateConnected){ - PRINTM(INFO, "Already Connected ..\n"); - ret = SendDeauthentication(priv); + if ((dwrq->flags & IW_ENCODE_INDEX) > 1) { + i = (dwrq->flags & IW_ENCODE_INDEX) - 1; /* convert to 0 based */ - if (ret){ - goto setessid_ret; + PRINTM(INFO, "Request SSID by index = %d\n", i); + + if (i > Adapter->NumInScanTable) { + /* Failed to find in table since index is > current max. */ + i = -EINVAL; } + } else { + SendSpecificSSIDScan(priv, &reqSSID); + i = FindSSIDInList(Adapter, + &reqSSID, NULL, Wlan802_11Infrastructure); } - if(Adapter->Prescan) - SendSpecificSSIDScan(priv, &reqSSID, TRUE); - i = FindSSIDInList(Adapter, &reqSSID, NULL, - Wlan802_11Infrastructure); + if (i >= 0) { PRINTM(INFO, "SSID found in scan list ... associating...\n"); - ret = wlan_associate(priv, &Adapter->ScanTable[i]); if (ret) { @@ -263,7 +366,7 @@ } else { /* ad hoc mode */ /* If the requested SSID matches current SSID return */ - if (!SSIDcmp(&Adapter->CurBssParams.ssid, &reqSSID)) { + if (!SSIDcmp(&Adapter->CurBssParams.BSSDescriptor.Ssid, &reqSSID)) { ret = WLAN_STATUS_SUCCESS; goto setessid_ret; } @@ -278,16 +381,22 @@ if (ret) { goto setessid_ret; } - } + Adapter->AdhocLinkSensed = FALSE; - /* Scan for the network, do not save previous results. Stale - * scan data will cause us to join a non-existant adhoc network - */ - SendSpecificSSIDScan(priv, &reqSSID, FALSE); + if ((dwrq->flags & IW_ENCODE_INDEX) > 1) { + i = (dwrq->flags & IW_ENCODE_INDEX) - 1; /* 0 based */ + if (i > Adapter->NumInScanTable) { + /* Failed to find in table since index is > current max. */ + i = -EINVAL; + } + } else { + /* Scan for the network */ + SendSpecificSSIDScan(priv, &reqSSID); /* Search for the requested SSID in the scan table */ i = FindSSIDInList(Adapter, &reqSSID, NULL, Wlan802_11IBSS); + } if (i >= 0) { PRINTM(INFO, "SSID found at %d in List, so join\n", i); @@ -295,14 +404,12 @@ } else { /* else send START command */ PRINTM(INFO, "SSID not found in list, " - "so creating adhoc with ssid = %s\n", - reqSSID.Ssid); + "so creating adhoc with ssid = %s\n", reqSSID.Ssid); StartAdhocNetwork(priv, &reqSSID); } /* end of else (START command) */ } /* end of else (Ad hoc mode) */ - /* * The MediaConnectStatus change can be removed later when * the ret code is being properly returned. @@ -326,13 +433,16 @@ /** * @brief Connect to the AP or Ad-hoc Network with specific bssid * + * NOTE: Scan should be issued by application before this function is called + * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param awrq A pointer to iw_param structure * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_wap(struct net_device* dev, struct iw_request_info* info, +int +wlan_set_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr* awrq, char* extra) { wlan_private* priv = dev->priv; @@ -344,8 +454,13 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } -//Application should call scan before call this function. + /* Clear any past association response stored for application retrieval */ + Adapter->assocRspSize = 0; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; @@ -357,15 +472,22 @@ #ifdef REASSOCIATION // cancel re-association timer if there's one - if (Adapter->TimerIsSet == TRUE) { + if (Adapter->ReassocTimerIsSet == TRUE) { CancelTimer(&Adapter->MrvDrvTimer); - Adapter->TimerIsSet = FALSE; + Adapter->ReassocTimerIsSet = FALSE; } #endif /* REASSOCIATION */ if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) { i = FindBestSSIDInList(Adapter); } else { + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + if (memcmp + (awrq->sa_data, + Adapter->CurBssParams.BSSDescriptor.MacAddress, + ETH_ALEN) == 0) + return WLAN_STATUS_SUCCESS; + } memcpy(reqBSSID, awrq->sa_data, ETH_ALEN); PRINTM(INFO, "ASSOC: WAP: Bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -382,14 +504,7 @@ } if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { - if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { - ret = SendDeauthentication(priv); - if (ret) { - LEAVE(); - return ret; - } - } ret = wlan_associate(priv, &Adapter->ScanTable[i]); if (ret) { @@ -406,6 +521,7 @@ return ret; } } + Adapter->AdhocLinkSensed = FALSE; JoinAdhocNetwork(priv, &Adapter->ScanTable[i]); } @@ -421,7 +537,6 @@ return ret; } - /** * @brief Associated to a specific BSS discovered in a scan * @@ -430,28 +545,134 @@ * * @return WLAN_STATUS_SUCCESS-success, otherwise fail */ -int wlan_associate(wlan_private* priv, BSSDescriptor_t* pBSSDesc) +int +wlan_associate(wlan_private * priv, BSSDescriptor_t * pBSSDesc) { + wlan_adapter *Adapter = priv->adapter; + int enableData = TRUE; + union iwreq_data wrqu; int ret; + IEEEtypes_AssocRsp_t *pAssocRsp; + u8 currentBSSID[MRVDRV_ETH_ADDR_LEN]; + int reassocAttempt = FALSE; + ENTER(); - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AUTHENTICATE, - 0, HostCmd_OPTION_WAITFORRSP, - 0, pBSSDesc->MacAddress); - - if (ret) { + /* Return error if the Adapter or table entry is not marked as infra */ + if ((Adapter->InfrastructureMode != Wlan802_11Infrastructure) + || (pBSSDesc->InfrastructureMode != Wlan802_11Infrastructure)) { LEAVE(); - return ret; + return -EINVAL; } + memcpy(¤tBSSID, + &Adapter->CurBssParams.BSSDescriptor.MacAddress, + sizeof(currentBSSID)); + + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + reassocAttempt = TRUE; + PRINTM(INFO, "Attempting reassociation, stopping wmm queues\n"); + wmm_stop_queue(priv); + } + + /* Clear any past association response stored for application retrieval */ + Adapter->assocRspSize = 0; + ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_ASSOCIATE, - 0, HostCmd_OPTION_WAITFORRSP, - 0, pBSSDesc); + 0, HostCmd_OPTION_WAITFORRSP, 0, pBSSDesc); + + if (Adapter->wmm.enabled) { + /* Don't re-enable carrier until we get the WMM_GET_STATUS event */ + enableData = FALSE; + } else { + /* Since WMM is not enabled, setup the queues with the defaults */ + wmm_setup_queues(priv); + } + + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + + if (reassocAttempt + && (memcmp(¤tBSSID, + &Adapter->CurBssParams.BSSDescriptor.MacAddress, + sizeof(currentBSSID)) == 0)) { + + /* Reassociation attempt failed, still associated to old AP, + ** no need to wait for WMM notification to restart data + */ + enableData = TRUE; + } + if (enableData) { + PRINTM(INFO, "Post association, re-enabling data flow\n"); + wmm_start_queue(priv); + os_carrier_on(priv); + os_start_queue(priv); + } + } else { + PRINTM(INFO, "Post association, stopping data flow\n"); + os_carrier_off(priv); + os_stop_queue(priv); + } + + memcpy(wrqu.ap_addr.sa_data, + &Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); + + pAssocRsp = (IEEEtypes_AssocRsp_t *) Adapter->assocRspBuffer; + + if (ret || pAssocRsp->StatusCode) { + ret = -ENETUNREACH; + } LEAVE(); return ret; } +/** + * @brief Associated to a specific indexed entry in the ScanTable + * + * @param priv A pointer to wlan_private structure + * @param tableIdx Index into the ScanTable to associate to, index parameter + * base value is 1. No scanning is done before the + * association attempt. + * + * @return WLAN_STATUS_SUCCESS-success, otherwise fail + */ +int +wlan_associate_to_table_idx(wlan_private * priv, int tableIdx) +{ + wlan_adapter *Adapter = priv->adapter; + int ret; + + ENTER(); + +#ifdef REASSOCIATION + if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->ReassocSem)) { + PRINTM(ERROR, "Acquire semaphore error\n"); + return -EBUSY; + } +#endif + + PRINTM(INFO, "ASSOC: iwpriv: Index = %d, NumInScanTable = %d\n", + tableIdx, Adapter->NumInScanTable); + + /* Check index in table, subtract 1 if within range and call association + * sub-function. ScanTable[] is 0 based, parameter is 1 based to + * conform with IW_ENCODE_INDEX flag parameter passing in iwconfig/iwlist + */ + if (tableIdx && (tableIdx <= Adapter->NumInScanTable)) { + ret = wlan_associate(priv, &Adapter->ScanTable[tableIdx - 1]); + } else { + ret = -EINVAL; + } + +#ifdef REASSOCIATION + OS_REL_SEMAPHORE(&Adapter->ReassocSem); +#endif + LEAVE(); + + return ret; +} /** * @brief Start an Adhoc Network @@ -460,7 +681,8 @@ * @param AdhocSSID The ssid of the Adhoc Network * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -int StartAdhocNetwork(wlan_private* priv, WLAN_802_11_SSID* AdhocSSID) +int +StartAdhocNetwork(wlan_private * priv, WLAN_802_11_SSID * AdhocSSID) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -469,24 +691,13 @@ Adapter->AdhocCreate = TRUE; - if (!Adapter->capInfo.ShortPreamble) { - PRINTM(INFO, "AdhocStart: Long Preamble\n"); - Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE; - } else { - PRINTM(INFO, "AdhocStart: Short Preamble\n"); - Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE; - } - - SetRadioControl(priv); - - PRINTM(INFO, "Adhoc Channel = %d\n", Adapter->AdhocChannel); - PRINTM(INFO, "CurBssParams.channel = %d\n", Adapter->CurBssParams.channel); + PRINTM(INFO, "CurBssParams.channel = %d\n", + Adapter->CurBssParams.BSSDescriptor.Channel); PRINTM(INFO, "CurBssParams.band = %d\n", Adapter->CurBssParams.band); ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AD_HOC_START, - 0, HostCmd_OPTION_WAITFORRSP, - 0, AdhocSSID); + 0, HostCmd_OPTION_WAITFORRSP, 0, AdhocSSID); LEAVE(); return ret; @@ -501,7 +712,8 @@ * * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -int JoinAdhocNetwork(wlan_private* priv, BSSDescriptor_t* pBSSDesc) +int +JoinAdhocNetwork(wlan_private * priv, BSSDescriptor_t * pBSSDesc) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -509,17 +721,17 @@ ENTER(); PRINTM(INFO, "JoinAdhocNetwork: CurBss.ssid =%s\n", - Adapter->CurBssParams.ssid.Ssid); + Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid); PRINTM(INFO, "JoinAdhocNetwork: CurBss.ssid_len =%u\n", - Adapter->CurBssParams.ssid.SsidLength); - PRINTM(INFO, "JoinAdhocNetwork: ssid =%s\n", - pBSSDesc->Ssid.Ssid); + Adapter->CurBssParams.BSSDescriptor.Ssid.SsidLength); + PRINTM(INFO, "JoinAdhocNetwork: ssid =%s\n", pBSSDesc->Ssid.Ssid); PRINTM(INFO, "JoinAdhocNetwork: ssid len =%u\n", pBSSDesc->Ssid.SsidLength); /* check if the requested SSID is already joined */ - if (Adapter->CurBssParams.ssid.SsidLength - && !SSIDcmp(&pBSSDesc->Ssid, &Adapter->CurBssParams.ssid) + if (Adapter->CurBssParams.BSSDescriptor.Ssid.SsidLength + && !SSIDcmp(&pBSSDesc->Ssid, + &Adapter->CurBssParams.BSSDescriptor.Ssid) && (Adapter->CurBssParams.BSSDescriptor.InfrastructureMode == Wlan802_11IBSS)) { @@ -530,22 +742,8 @@ return WLAN_STATUS_FAILURE; } - - /*Use ShortPreamble only when both creator and card supports - short preamble*/ - if (!pBSSDesc->Cap.ShortPreamble - || !Adapter->capInfo.ShortPreamble) { - PRINTM(INFO, "AdhocJoin: Long Preamble\n"); - Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE; - } - else { - PRINTM(INFO, "AdhocJoin: Short Preamble\n"); - Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE; - } - - SetRadioControl(priv); - - PRINTM(INFO, "CurBssParams.channel = %d\n", Adapter->CurBssParams.channel); + PRINTM(INFO, "CurBssParams.channel = %d\n", + Adapter->CurBssParams.BSSDescriptor.Channel); PRINTM(INFO, "CurBssParams.band = %c\n", Adapter->CurBssParams.band); Adapter->AdhocCreate = FALSE; @@ -553,12 +751,10 @@ // store the SSID info temporarily memset(&Adapter->AttemptedSSIDBeforeScan, 0, sizeof(WLAN_802_11_SSID)); memcpy(&Adapter->AttemptedSSIDBeforeScan, - &pBSSDesc->Ssid, - sizeof(WLAN_802_11_SSID)); + &pBSSDesc->Ssid, sizeof(WLAN_802_11_SSID)); ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, - 0, HostCmd_OPTION_WAITFORRSP, - OID_802_11_SSID, pBSSDesc); + 0, HostCmd_OPTION_WAITFORRSP, 0, pBSSDesc); LEAVE(); return ret; @@ -570,11 +766,11 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -int StopAdhocNetwork(wlan_private* priv) +int +StopAdhocNetwork(wlan_private * priv) { return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_AD_HOC_STOP, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); } /** @@ -583,11 +779,11 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -int SendDeauthentication(wlan_private* priv) +int +SendDeauthentication(wlan_private * priv) { return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); } /** @@ -596,7 +792,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlanidle_off(wlan_private* priv) +int +wlanidle_off(wlan_private * priv) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -607,8 +804,7 @@ if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) { if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { - if (memcmp(Adapter->PreviousBSSID, zeroMac, - sizeof(zeroMac)) != 0) { + if (memcmp(Adapter->PreviousBSSID, zeroMac, sizeof(zeroMac)) != 0) { PRINTM(INFO, "Previous SSID = %s\n", Adapter->PreviousSSID.Ssid); @@ -624,7 +820,7 @@ Adapter->InfrastructureMode); if (i < 0) { - SendSpecificBSSIDScan(priv, Adapter->PreviousBSSID, TRUE); + SendSpecificBSSIDScan(priv, Adapter->PreviousBSSID); i = FindSSIDInList(Adapter, &Adapter->PreviousSSID, Adapter->PreviousBSSID, @@ -635,16 +831,14 @@ /* If the BSSID could not be found, try just the SSID */ i = FindSSIDInList(Adapter, &Adapter->PreviousSSID, - NULL, - Adapter->InfrastructureMode); + NULL, Adapter->InfrastructureMode); } if (i < 0) { - SendSpecificSSIDScan(priv, &Adapter->PreviousSSID, TRUE); + SendSpecificSSIDScan(priv, &Adapter->PreviousSSID); i = FindSSIDInList(Adapter, &Adapter->PreviousSSID, - NULL, - Adapter->InfrastructureMode); + NULL, Adapter->InfrastructureMode); } if (i >= 0) { @@ -671,7 +865,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlanidle_on(wlan_private* priv) +int +wlanidle_on(wlan_private * priv) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -680,23 +875,21 @@ if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { - PRINTM(INFO, "Previous SSID = %s\n", - Adapter->PreviousSSID.Ssid); - memmove(&Adapter->PreviousSSID, - &Adapter->CurBssParams.ssid, + PRINTM(INFO, "Previous SSID = %s\n", Adapter->PreviousSSID.Ssid); + memcpy(&Adapter->PreviousSSID, + &Adapter->CurBssParams.BSSDescriptor.Ssid, sizeof(WLAN_802_11_SSID)); - wlan_send_deauth(priv); + SendDeauthentication(priv); } else if (Adapter->InfrastructureMode == Wlan802_11IBSS) { ret = StopAdhocNetwork(priv); } } - #ifdef REASSOCIATION - if (Adapter->TimerIsSet == TRUE) { + if (Adapter->ReassocTimerIsSet == TRUE) { CancelTimer(&Adapter->MrvDrvTimer); - Adapter->TimerIsSet = FALSE; + Adapter->ReassocTimerIsSet = FALSE; } #endif /* REASSOCIATION */ @@ -706,49 +899,175 @@ return ret; } +/** + * @brief Append a generic IE as a passthrough TLV to a TLV buffer. + * + * This function is called from the network join command prep. routine. + * If the IE buffer has been setup by the application, this routine appends + * the buffer as a passthrough TLV type to the request. + * + * @param priv A pointer to wlan_private structure + * @param ppBuffer pointer to command buffer pointer + * + * @return bytes added to the buffer + */ +static int +wlan_cmd_append_generic_ie(wlan_private * priv, u8 ** ppBuffer) +{ + wlan_adapter *Adapter = priv->adapter; + int retLen = 0; + MrvlIEtypesHeader_t ieHeader; + + /* Null Checks */ + if (ppBuffer == 0) + return 0; + if (*ppBuffer == 0) + return 0; + + /* + * If there is a generic ie buffer setup, append it to the return + * parameter buffer pointer. + */ + if (Adapter->genIeBufferLen) { + PRINTM(INFO, "append generic %d to %p\n", Adapter->genIeBufferLen, + *ppBuffer); + + /* Wrap the generic IE buffer with a passthrough TLV type */ + ieHeader.Type = wlan_cpu_to_le16(TLV_TYPE_PASSTHROUGH); + ieHeader.Len = wlan_cpu_to_le16(Adapter->genIeBufferLen); + memcpy(*ppBuffer, &ieHeader, sizeof(ieHeader)); + + /* Increment the return size and the return buffer pointer param */ + *ppBuffer += sizeof(ieHeader); + retLen += sizeof(ieHeader); + /* Copy the generic IE buffer to the output buffer, advance pointer */ + memcpy(*ppBuffer, Adapter->genIeBuffer, Adapter->genIeBufferLen); + + /* Increment the return size and the return buffer pointer param */ + *ppBuffer += Adapter->genIeBufferLen; + retLen += Adapter->genIeBufferLen; + + /* Reset the generic IE buffer */ + Adapter->genIeBufferLen = 0; + } + /* return the length appended to the buffer */ + return retLen; +} /** - * @brief This function prepares command of authenticate. + * @brief Append any application provided Marvell TLVs to a TLV buffer. + * + * This function is called from the network join command prep. routine. + * If the Marvell TLV buffer has been setup by the application, this routine + * appends the buffer to the request. * * @param priv A pointer to wlan_private structure - * @param cmd A pointer to HostCmd_DS_COMMAND structure - * @param pdata_buf Void cast of pointer to a BSSID to authenticate with + * @param ppBuffer pointer to command buffer pointer * - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + * @return bytes added to the buffer */ -int wlan_cmd_802_11_authenticate(wlan_private* priv, - HostCmd_DS_COMMAND* cmd, - void* pdata_buf) +static int +wlan_cmd_append_marvell_tlv(wlan_private * priv, u8 ** ppBuffer) { wlan_adapter* Adapter = priv->adapter; - HostCmd_DS_802_11_AUTHENTICATE* pAuthenticate = &cmd->params.auth; - u8* bssid = (u8*)pdata_buf; + int retLen = 0; - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AUTHENTICATE); - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_AUTHENTICATE) - + S_DS_GEN); + /* Null Checks */ + if (ppBuffer == 0) + return 0; + if (*ppBuffer == 0) + return 0; - pAuthenticate->AuthType = Adapter->SecInfo.AuthenticationMode; - memcpy(pAuthenticate->MacAddr, bssid, MRVDRV_ETH_ADDR_LEN); + /* + * If there is a Marvell TLV buffer setup, append it to the return + * parameter buffer pointer. + */ + if (Adapter->mrvlAssocTlvBufferLen) { + PRINTM(INFO, "append tlv %d to %p\n", + Adapter->mrvlAssocTlvBufferLen, *ppBuffer); - PRINTM(INFO, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + /* Copy the TLV buffer to the output buffer, advance pointer */ + memcpy(*ppBuffer, + Adapter->mrvlAssocTlvBuffer, Adapter->mrvlAssocTlvBufferLen); - return WLAN_STATUS_SUCCESS; + /* Increment the return size and the return buffer pointer param */ + *ppBuffer += Adapter->mrvlAssocTlvBufferLen; + retLen += Adapter->mrvlAssocTlvBufferLen; + + /* Reset the Marvell TLV buffer */ + Adapter->mrvlAssocTlvBufferLen = 0; } + /* return the length appended to the buffer */ + return retLen; +} /** - * @brief This function prepares command of deauthenticat. + * @brief Append TSF tracking info from the scan table for the target AP + * + * This function is called from the network join command prep. routine. + * The TSF table TSF sent to the firmware contians two TSF values: + * - the TSF of the target AP from its previous beacon/probe response + * - the TSF timestamp of our local MAC at the time we observed the + * beacon/probe response. + * + * The firmware uses the timestamp values to set an initial TSF value + * in the MAC for the new association after a reassociation attempt. + * + * @param priv A pointer to wlan_private structure + * @param ppBuffer A pointer to command buffer pointer + * @param pBSSDesc A pointer to the BSS Descriptor from the scan table of + * the AP we are trying to join + * + * @return bytes added to the buffer + */ +static int +wlan_cmd_append_tsf_tlv(wlan_private * priv, u8 ** ppBuffer, + BSSDescriptor_t * pBSSDesc) +{ + MrvlIEtypes_TsfTimestamp_t tsfTlv; + u64 tsfVal; + + /* Null Checks */ + if (ppBuffer == 0) + return 0; + if (*ppBuffer == 0) + return 0; + + tsfTlv.Header.Type = wlan_cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); + tsfTlv.Header.Len = wlan_cpu_to_le16(2 * sizeof(tsfVal)); + + memcpy(*ppBuffer, &tsfTlv, sizeof(tsfTlv.Header)); + *ppBuffer += sizeof(tsfTlv.Header); + + /* TSF timestamp from the firmware TSF when the bcn/prb rsp was received */ + tsfVal = wlan_cpu_to_le64(pBSSDesc->networkTSF); + memcpy(*ppBuffer, &tsfVal, sizeof(tsfVal)); + *ppBuffer += sizeof(tsfVal); + + memcpy(&tsfVal, pBSSDesc->TimeStamp, sizeof(tsfVal)); + + PRINTM(INFO, "ASSOC: TSF offset calc: %016llx - %016llx\n", + tsfVal, pBSSDesc->networkTSF); + + tsfVal = wlan_cpu_to_le64(tsfVal); + memcpy(*ppBuffer, &tsfVal, sizeof(tsfVal)); + *ppBuffer += sizeof(tsfVal); + + return (sizeof(tsfTlv.Header) + (2 * sizeof(tsfVal))); +} + +/** + * @brief This function prepares command of deauthenticate. * * @param priv A pointer to wlan_private structure * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_802_11_deauthenticate(wlan_private* priv, - HostCmd_DS_COMMAND* cmd) +int +wlan_cmd_802_11_deauthenticate(wlan_private * priv, HostCmd_DS_COMMAND * cmd) { wlan_adapter* Adapter = priv->adapter; HostCmd_DS_802_11_DEAUTHENTICATE* dauth = &cmd->params.deauth; @@ -760,7 +1079,8 @@ wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_DEAUTHENTICATE) + S_DS_GEN); /* set AP MAC address */ - memmove(dauth->MacAddr, Adapter->CurBssParams.bssid, MRVDRV_ETH_ADDR_LEN); + memcpy(dauth->MacAddr, + &Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); /* Reason code 3 = Station is leaving */ #define REASON_CODE_STA_LEAVING 3 @@ -770,7 +1090,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief This function prepares command of association. * @@ -779,146 +1098,131 @@ * @param pdata_buf Void cast of BSSDescriptor_t from the scan table to assoc * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_802_11_associate(wlan_private* priv, - HostCmd_DS_COMMAND* cmd, - void* pdata_buf) +int +wlan_cmd_802_11_associate(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pdata_buf) { wlan_adapter* Adapter = priv->adapter; HostCmd_DS_802_11_ASSOCIATE* pAsso = &cmd->params.associate; int ret = WLAN_STATUS_SUCCESS; BSSDescriptor_t* pBSSDesc; - u8* card_rates; + WLAN_802_11_RATES rates; + int ratesSize; u8* pos; - int card_rates_size; u16 TmpCap; - MrvlIEtypes_SsIdParamSet_t* ssid; - MrvlIEtypes_PhyParamSet_t* phy; - MrvlIEtypes_SsParamSet_t* ss; - MrvlIEtypes_RatesParamSet_t* rates; - MrvlIEtypes_RsnParamSet_t* rsn; + MrvlIEtypes_SsIdParamSet_t *pSsidTlv; + MrvlIEtypes_PhyParamSet_t *pPhyTlv; + MrvlIEtypes_SsParamSet_t *pSsTlv; + MrvlIEtypes_RatesParamSet_t *pRatesTlv; + MrvlIEtypes_AuthType_t *pAuthTlv; + MrvlIEtypes_RsnParamSet_t *pRsnTlv; ENTER(); pBSSDesc = (BSSDescriptor_t*)pdata_buf; pos = (u8*)pAsso; - if (!Adapter) { - ret = WLAN_STATUS_FAILURE; - goto done; - } - cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); /* Save so we know which BSS Desc to use in the response handler */ Adapter->pAttemptedBSSDesc = pBSSDesc; memcpy(pAsso->PeerStaAddr, - pBSSDesc->MacAddress, - sizeof(pAsso->PeerStaAddr)); + pBSSDesc->MacAddress, sizeof(pAsso->PeerStaAddr)); pos += sizeof(pAsso->PeerStaAddr); - /* set preamble to firmware */ - if (Adapter->capInfo.ShortPreamble && pBSSDesc->Cap.ShortPreamble) { - Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE; - } else { - Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE; - } - - SetRadioControl(priv); - /* set the listen interval */ - pAsso->ListenInterval = Adapter->ListenInterval; + pAsso->ListenInterval = wlan_cpu_to_le16(Adapter->ListenInterval); pos += sizeof(pAsso->CapInfo); pos += sizeof(pAsso->ListenInterval); - pos += sizeof(pAsso->BcnPeriod); - pos += sizeof(pAsso->DtimPeriod); + pos += sizeof(pAsso->Reserved1); - ssid = (MrvlIEtypes_SsIdParamSet_t *)pos; - ssid->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID); - ssid->Header.Len = pBSSDesc->Ssid.SsidLength; - memcpy(ssid->SsId, pBSSDesc->Ssid.Ssid, ssid->Header.Len); - pos += sizeof(ssid->Header) + ssid->Header.Len; - ssid->Header.Len = wlan_cpu_to_le16(ssid->Header.Len); + pSsidTlv = (MrvlIEtypes_SsIdParamSet_t *) pos; + pSsidTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID); + pSsidTlv->Header.Len = pBSSDesc->Ssid.SsidLength; + memcpy(pSsidTlv->SsId, pBSSDesc->Ssid.Ssid, pSsidTlv->Header.Len); + pos += sizeof(pSsidTlv->Header) + pSsidTlv->Header.Len; + pSsidTlv->Header.Len = wlan_cpu_to_le16(pSsidTlv->Header.Len); - phy = (MrvlIEtypes_PhyParamSet_t *)pos; - phy->Header.Type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS); - phy->Header.Len = sizeof(phy->fh_ds.DsParamSet); - memcpy(&phy->fh_ds.DsParamSet, + pPhyTlv = (MrvlIEtypes_PhyParamSet_t *) pos; + pPhyTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS); + pPhyTlv->Header.Len = sizeof(pPhyTlv->fh_ds.DsParamSet); + memcpy(&pPhyTlv->fh_ds.DsParamSet, &pBSSDesc->PhyParamSet.DsParamSet.CurrentChan, - sizeof(phy->fh_ds.DsParamSet)); - pos += sizeof(phy->Header) + phy->Header.Len; - phy->Header.Len = wlan_cpu_to_le16(phy->Header.Len); - - ss = (MrvlIEtypes_SsParamSet_t *)pos; - ss->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CF); - ss->Header.Len = sizeof(ss->cf_ibss.CfParamSet); - pos += sizeof(ss->Header) + ss->Header.Len; - ss->Header.Len = wlan_cpu_to_le16(ss->Header.Len); - - rates = (MrvlIEtypes_RatesParamSet_t *)pos; - rates->Header.Type = wlan_cpu_to_le16(TLV_TYPE_RATES); - - memcpy(&rates->Rates,&pBSSDesc->SupportedRates, WLAN_SUPPORTED_RATES); + sizeof(pPhyTlv->fh_ds.DsParamSet)); + pos += sizeof(pPhyTlv->Header) + pPhyTlv->Header.Len; + pPhyTlv->Header.Len = wlan_cpu_to_le16(pPhyTlv->Header.Len); - card_rates = SupportedRates; - card_rates_size = sizeof(SupportedRates); + pSsTlv = (MrvlIEtypes_SsParamSet_t *) pos; + pSsTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CF); + pSsTlv->Header.Len = sizeof(pSsTlv->cf_ibss.CfParamSet); + pos += sizeof(pSsTlv->Header) + pSsTlv->Header.Len; + pSsTlv->Header.Len = wlan_cpu_to_le16(pSsTlv->Header.Len); - if (get_common_rates(Adapter, rates->Rates, WLAN_SUPPORTED_RATES, - card_rates, card_rates_size)) { + /* Get the common rates supported between the driver and the BSS Desc */ + if (setup_rates_from_bssdesc(Adapter, pBSSDesc, rates, &ratesSize)) { ret = WLAN_STATUS_FAILURE; goto done; } - rates->Header.Len = MIN(strlen(rates->Rates), WLAN_SUPPORTED_RATES); - Adapter->CurBssParams.NumOfRates = rates->Header.Len; - - pos += sizeof(rates->Header) + rates->Header.Len; - rates->Header.Len = wlan_cpu_to_le16(rates->Header.Len); + /* Setup the Rates TLV in the association command */ + pRatesTlv = (MrvlIEtypes_RatesParamSet_t *) pos; + pRatesTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_RATES); + pRatesTlv->Header.Len = wlan_cpu_to_le16(ratesSize); + memcpy(pRatesTlv->Rates, rates, ratesSize); + pos += sizeof(pRatesTlv->Header) + ratesSize; + PRINTM(INFO, "ASSOC_CMD: Rates size = %d\n", ratesSize); + /* Add the Authentication type to be used for Auth frames if needed */ + pAuthTlv = (MrvlIEtypes_AuthType_t *) pos; + pAuthTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_AUTH_TYPE); + pAuthTlv->Header.Len = sizeof(pAuthTlv->AuthType); + pAuthTlv->AuthType = Adapter->SecInfo.AuthenticationMode; + pos += sizeof(pAuthTlv->Header) + pAuthTlv->Header.Len; + pAuthTlv->Header.Len = wlan_cpu_to_le16(pAuthTlv->Header.Len); - if (Adapter->SecInfo.WPAEnabled - || Adapter->SecInfo.WPA2Enabled - ) - { - rsn = (MrvlIEtypes_RsnParamSet_t *)pos; - rsn->Header.Type = (u16)Adapter->Wpa_ie[0]; /* WPA_IE or WPA2_IE */ - rsn->Header.Type = wlan_cpu_to_le16(rsn->Header.Type); - rsn->Header.Len = (u16)Adapter->Wpa_ie[1]; - memcpy(rsn->RsnIE, &Adapter->Wpa_ie[2], rsn->Header.Len); - HEXDUMP("ASSOC_CMD: RSN IE", (u8*)rsn, - sizeof(rsn->Header) + rsn->Header.Len); - pos += sizeof(rsn->Header) + rsn->Header.Len; - rsn->Header.Len = wlan_cpu_to_le16(rsn->Header.Len); + if (!Adapter->wps.SessionEnable) { + if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled) { + pRsnTlv = (MrvlIEtypes_RsnParamSet_t *) pos; + pRsnTlv->Header.Type = (u16) Adapter->Wpa_ie[0]; /* WPA_IE or WPA2_IE */ + pRsnTlv->Header.Type = pRsnTlv->Header.Type & 0x00FF; + pRsnTlv->Header.Type = wlan_cpu_to_le16(pRsnTlv->Header.Type); + pRsnTlv->Header.Len = (u16) Adapter->Wpa_ie[1]; + pRsnTlv->Header.Len = pRsnTlv->Header.Len & 0x00FF; + if (pRsnTlv->Header.Len <= (sizeof(Adapter->Wpa_ie) - 2)) { + memcpy(pRsnTlv->RsnIE, &Adapter->Wpa_ie[2], + pRsnTlv->Header.Len); + } else { + ret = WLAN_STATUS_FAILURE; + goto done; } + HEXDUMP("ASSOC_CMD: RSN IE", (u8 *) pRsnTlv, + sizeof(pRsnTlv->Header) + pRsnTlv->Header.Len); + pos += sizeof(pRsnTlv->Header) + pRsnTlv->Header.Len; + pRsnTlv->Header.Len = wlan_cpu_to_le16(pRsnTlv->Header.Len); + } + } + wlan_wmm_process_association_req(priv, &pos, &pBSSDesc->wmmIE); + wlan_cmd_append_generic_ie(priv, &pos); + wlan_cmd_append_marvell_tlv(priv, &pos); - /* update CurBssParams */ - Adapter->CurBssParams.channel = (pBSSDesc - ->PhyParamSet.DsParamSet.CurrentChan); - - /* Copy the infra. association rates into Current BSS state structure */ - memcpy(&Adapter->CurBssParams.DataRates, &rates->Rates, - MIN(sizeof(Adapter->CurBssParams.DataRates), rates->Header.Len)); - - PRINTM(INFO, "ASSOC_CMD: rates->Header.Len = %d\n", rates->Header.Len); + wlan_cmd_append_tsf_tlv(priv, &pos, pBSSDesc); - /* set IBSS field */ - if (pBSSDesc->InfrastructureMode == Wlan802_11Infrastructure) { -#define CAPINFO_ESS_MODE 1 - pAsso->CapInfo.Ess = CAPINFO_ESS_MODE; + if (wlan_create_dnld_countryinfo_11d(priv, 0)) { + PRINTM(INFO, "Dnld_countryinfo_11d failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; } - if (wlan_parse_dnld_countryinfo_11d( priv )) { ret = WLAN_STATUS_FAILURE; goto done; } - - cmd->Size = wlan_cpu_to_le16((u16)(pos - (u8 *)pAsso) + S_DS_GEN); /* set the Capability info at last */ @@ -934,7 +1238,6 @@ return ret; } - /** * @brief This function prepares command of ad_hoc_start. * @@ -943,9 +1246,9 @@ * @param pssid A pointer to WLAN_802_11_SSID structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_802_11_ad_hoc_start(wlan_private* priv, - HostCmd_DS_COMMAND * cmd, - void *pssid) +int +wlan_cmd_802_11_ad_hoc_start(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pssid) { wlan_adapter* Adapter = priv->adapter; HostCmd_DS_802_11_AD_HOC_START* adhs = &cmd->params.ads; @@ -970,33 +1273,34 @@ /* * Fill in the parameters for 2 data structures: * 1. HostCmd_DS_802_11_AD_HOC_START Command - * 2. Adapter->ScanTable[i] + * 2. pBSSDesc * * Driver will fill up SSID, BSSType,IBSS param, Physical Param, * probe delay, and Cap info. * - * Firmware will fill up beacon period, DTIM, Basic rates + * Firmware will fill up beacon period, Basic rates * and operational rates. */ memset(adhs->SSID, 0, MRVDRV_MAX_SSID_LENGTH); - memcpy(adhs->SSID,((PWLAN_802_11_SSID) pssid)->Ssid, - ((PWLAN_802_11_SSID) pssid)->SsidLength); + memcpy(adhs->SSID, ((WLAN_802_11_SSID *) pssid)->Ssid, + ((WLAN_802_11_SSID *) pssid)->SsidLength); PRINTM(INFO, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID); memset(pBSSDesc->Ssid.Ssid, 0, MRVDRV_MAX_SSID_LENGTH); memcpy(pBSSDesc->Ssid.Ssid, - ((PWLAN_802_11_SSID) pssid)->Ssid, - ((PWLAN_802_11_SSID) pssid)->SsidLength); + ((WLAN_802_11_SSID *) pssid)->Ssid, + ((WLAN_802_11_SSID *) pssid)->SsidLength); - pBSSDesc->Ssid.SsidLength = ((PWLAN_802_11_SSID) pssid)->SsidLength; + pBSSDesc->Ssid.SsidLength = ((WLAN_802_11_SSID *) pssid)->SsidLength; /* set the BSS type */ adhs->BSSType = HostCmd_BSS_TYPE_IBSS; pBSSDesc->InfrastructureMode = Wlan802_11IBSS; - adhs->BeaconPeriod = Adapter->BeaconPeriod; + adhs->BeaconPeriod = wlan_cpu_to_le16(Adapter->BeaconPeriod); + pBSSDesc->BeaconPeriod = Adapter->BeaconPeriod; /* set Physical param set */ #define DS_PARA_IE_ID 3 @@ -1010,7 +1314,7 @@ PRINTM(INFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n", Adapter->AdhocChannel); - Adapter->CurBssParams.channel = Adapter->AdhocChannel; + Adapter->CurBssParams.BSSDescriptor.Channel = Adapter->AdhocChannel; pBSSDesc->Channel = Adapter->AdhocChannel; adhs->PhyParamSet.DsParamSet.CurrentChan = Adapter->AdhocChannel; @@ -1026,22 +1330,20 @@ adhs->SsParamSet.IbssParamSet.ElementId = IBSS_PARA_IE_ID; adhs->SsParamSet.IbssParamSet.Len = IBSS_PARA_IE_LEN; - adhs->SsParamSet.IbssParamSet.AtimWindow = Adapter->AtimWindow; + adhs->SsParamSet.IbssParamSet.AtimWindow + = wlan_cpu_to_le16(Adapter->AtimWindow); + pBSSDesc->ATIMWindow = Adapter->AtimWindow; memcpy(&pBSSDesc->SsParamSet, - &adhs->SsParamSet, - sizeof(IEEEtypes_SsParamSet_t)); + &adhs->SsParamSet, sizeof(IEEEtypes_SsParamSet_t)); /* set Capability info */ adhs->Cap.Ess = 0; adhs->Cap.Ibss = 1; pBSSDesc->Cap.Ibss = 1; - /* ProbeDelay */ - adhs->ProbeDelay = wlan_cpu_to_le16(HostCmd_SCAN_PROBE_DELAY_TIME); - - /* set up privacy in Adapter->ScanTable[i] */ + /* set up privacy in pBSSDesc */ if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled - ) { + || Adapter->AdhocAESEnabled) { #define AD_HOC_CAP_PRIVACY_ON 1 PRINTM(INFO, "ADHOC_S_CMD: WEPStatus set, Privacy to WEP\n"); @@ -1058,21 +1360,31 @@ if (Adapter->adhoc_grate_enabled == TRUE) { memcpy(adhs->DataRate, AdhocRates_G, MIN(sizeof(adhs->DataRate), sizeof(AdhocRates_G))); + if (Adapter-> + CurrentPacketFilter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON) { + ret = + PrepareAndSendCommand(priv, HostCmd_CMD_MAC_CONTROL, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &Adapter->CurrentPacketFilter); + if (ret) { + PRINTM(INFO, "ADHOC_S_CMD: G Protection config failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + } } else { memcpy(adhs->DataRate, AdhocRates_B, MIN(sizeof(adhs->DataRate), sizeof(AdhocRates_B))); } /* Find the last non zero */ - for (i = 0; i < sizeof(adhs->DataRate) && adhs->DataRate[i]; i++) - ; + for (i = 0; i < sizeof(adhs->DataRate) && adhs->DataRate[i]; i++); Adapter->CurBssParams.NumOfRates = i; /* Copy the ad-hoc creating rates into Current BSS state structure */ memcpy(&Adapter->CurBssParams.DataRates, - &adhs->DataRate, - Adapter->CurBssParams.NumOfRates); + &adhs->DataRate, Adapter->CurBssParams.NumOfRates); PRINTM(INFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x \n", adhs->DataRate[0], adhs->DataRate[1], @@ -1080,14 +1392,12 @@ PRINTM(INFO, "ADHOC_S_CMD: AD HOC Start command is ready\n"); - - if (wlan_create_dnld_countryinfo_11d( priv )) { + if (wlan_create_dnld_countryinfo_11d(priv, Adapter->CurBssParams.band)) { PRINTM(INFO, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); ret = WLAN_STATUS_FAILURE; goto done; } - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_AD_HOC_START) + S_DS_GEN + cmdAppendSize); @@ -1108,14 +1418,13 @@ * @param cmd A pointer to HostCmd_DS_COMMAND structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_802_11_ad_hoc_stop(wlan_private* priv, - HostCmd_DS_COMMAND* cmd) +int +wlan_cmd_802_11_ad_hoc_stop(wlan_private * priv, HostCmd_DS_COMMAND * cmd) { cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_AD_HOC_STOP) + S_DS_GEN); - return WLAN_STATUS_SUCCESS; } @@ -1128,46 +1437,57 @@ * * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_cmd_802_11_ad_hoc_join(wlan_private* priv, - HostCmd_DS_COMMAND* cmd, - void* pdata_buf) +int +wlan_cmd_802_11_ad_hoc_join(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pdata_buf) { wlan_adapter* Adapter = priv->adapter; HostCmd_DS_802_11_AD_HOC_JOIN* pAdHocJoin = &cmd->params.adj; BSSDescriptor_t* pBSSDesc = (BSSDescriptor_t*)pdata_buf; int cmdAppendSize = 0; int ret = WLAN_STATUS_SUCCESS; - u8* card_rates; - int card_rates_size; + WLAN_802_11_RATES rates; + int ratesSize; u16 TmpCap; - int i; - + u16 CurrentPacketFilter; ENTER(); +#define USE_G_PROTECTION 0x02 + if (pBSSDesc->ERPFlags & USE_G_PROTECTION) { + CurrentPacketFilter = + Adapter-> + CurrentPacketFilter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; + ret = + PrepareAndSendCommand(priv, HostCmd_CMD_MAC_CONTROL, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &CurrentPacketFilter); + if (ret) { + PRINTM(INFO, "ADHOC_S_CMD: G Protection config failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } + } Adapter->pAttemptedBSSDesc = pBSSDesc; cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); pAdHocJoin->BssDescriptor.BSSType = HostCmd_BSS_TYPE_IBSS; - pAdHocJoin->BssDescriptor.BeaconPeriod = pBSSDesc->BeaconPeriod; + pAdHocJoin->BssDescriptor.BeaconPeriod + = wlan_cpu_to_le16(pBSSDesc->BeaconPeriod); memcpy(&pAdHocJoin->BssDescriptor.BSSID, - &pBSSDesc->MacAddress, - MRVDRV_ETH_ADDR_LEN); + &pBSSDesc->MacAddress, MRVDRV_ETH_ADDR_LEN); memcpy(&pAdHocJoin->BssDescriptor.SSID, - &pBSSDesc->Ssid.Ssid, - pBSSDesc->Ssid.SsidLength); + &pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength); memcpy(&pAdHocJoin->BssDescriptor.PhyParamSet, - &pBSSDesc->PhyParamSet, - sizeof(IEEEtypes_PhyParamSet_t)); + &pBSSDesc->PhyParamSet, sizeof(IEEEtypes_PhyParamSet_t)); memcpy(&pAdHocJoin->BssDescriptor.SsParamSet, - &pBSSDesc->SsParamSet, - sizeof(IEEEtypes_SsParamSet_t)); + &pBSSDesc->SsParamSet, sizeof(IEEEtypes_SsParamSet_t)); memcpy(&TmpCap, &pBSSDesc->Cap, sizeof(IEEEtypes_CapInfo_t)); @@ -1179,7 +1499,8 @@ sizeof(IEEEtypes_CapInfo_t)); /* information on BSSID descriptor passed to FW */ - PRINTM(INFO, "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n", + PRINTM(INFO, + "ADHOC_J_CMD: BSSID = %02x-%02x-%02x-%02x-%02x-%02x, SSID = %s\n", pAdHocJoin->BssDescriptor.BSSID[0], pAdHocJoin->BssDescriptor.BSSID[1], pAdHocJoin->BssDescriptor.BSSID[2], @@ -1188,55 +1509,26 @@ pAdHocJoin->BssDescriptor.BSSID[5], pAdHocJoin->BssDescriptor.SSID); - PRINTM(INFO, "ADHOC_J_CMD: Data Rate = %x\n", - (u32)pAdHocJoin->BssDescriptor.DataRates); - - /* FailTimeOut */ - pAdHocJoin->FailTimeOut = wlan_cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); - - /* ProbeDelay */ - pAdHocJoin->ProbeDelay = wlan_cpu_to_le16(HostCmd_SCAN_PROBE_DELAY_TIME); - - /* Copy Data Rates from the Rates recorded in scan response */ - memset(pAdHocJoin->BssDescriptor.DataRates, 0, - sizeof(pAdHocJoin->BssDescriptor.DataRates)); - memcpy(pAdHocJoin->BssDescriptor.DataRates, pBSSDesc->DataRates, - MIN(sizeof(pAdHocJoin->BssDescriptor.DataRates), - sizeof(pBSSDesc->DataRates))); - - card_rates = SupportedRates; - card_rates_size = sizeof(SupportedRates); - - Adapter->CurBssParams.channel = pBSSDesc->Channel; - - if (get_common_rates(Adapter, pAdHocJoin->BssDescriptor.DataRates, - sizeof(pAdHocJoin->BssDescriptor.DataRates), - card_rates, - card_rates_size)) { - PRINTM(INFO, "ADHOC_J_CMD: get_common_rates returns error.\n"); + /* Get the common rates supported between the driver and the BSS Desc */ + if (setup_rates_from_bssdesc(Adapter, pBSSDesc, rates, &ratesSize)) { ret = WLAN_STATUS_FAILURE; goto done; } - /* Find the last non zero */ - for (i=0; i < sizeof(pAdHocJoin->BssDescriptor.DataRates) - && pAdHocJoin->BssDescriptor.DataRates[i]; i++) - ; - - Adapter->CurBssParams.NumOfRates = i; + /* Copy Data Rates from the Rates recorded in scan response */ + memset(pAdHocJoin->BssDescriptor.DataRates, 0, + sizeof(pAdHocJoin->BssDescriptor.DataRates)); + memcpy(pAdHocJoin->BssDescriptor.DataRates, rates, ratesSize); - /* - * Copy the adhoc joining rates to Current BSS State structure - */ - memcpy(Adapter->CurBssParams.DataRates, - pAdHocJoin->BssDescriptor.DataRates, - Adapter->CurBssParams.NumOfRates); + /* Copy the adhoc join rates into Current BSS state structure */ + Adapter->CurBssParams.NumOfRates = ratesSize; + memcpy(&Adapter->CurBssParams.DataRates, rates, ratesSize); - pAdHocJoin->BssDescriptor.SsParamSet.IbssParamSet.AtimWindow = - wlan_cpu_to_le16(pBSSDesc->ATIMWindow); + /* Copy the channel information */ + Adapter->CurBssParams.BSSDescriptor.Channel = pBSSDesc->Channel; if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled - ) { + || Adapter->AdhocAESEnabled) { pAdHocJoin->BssDescriptor.Cap.Privacy = AD_HOC_CAP_PRIVACY_ON; } @@ -1247,8 +1539,7 @@ LocalPSMode = Wlan802_11PowerModeCAM; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_PS_MODE, - HostCmd_ACT_GEN_SET, - 0, 0, &LocalPSMode); + HostCmd_ACT_GEN_SET, 0, 0, &LocalPSMode); if (ret) { ret = WLAN_STATUS_FAILURE; @@ -1256,13 +1547,17 @@ } } + if (wlan_create_dnld_countryinfo_11d(priv, 0)) { + PRINTM(INFO, "Dnld_countryinfo_11d failed\n"); + ret = WLAN_STATUS_FAILURE; + goto done; + } if (wlan_parse_dnld_countryinfo_11d( priv )) { ret = WLAN_STATUS_FAILURE; goto done; } - cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_AD_HOC_JOIN) + S_DS_GEN + cmdAppendSize); @@ -1271,59 +1566,109 @@ TmpCap = wlan_cpu_to_le16(TmpCap); memcpy(&pAdHocJoin->BssDescriptor.Cap, - &TmpCap, - sizeof(IEEEtypes_CapInfo_t)); + &TmpCap, sizeof(IEEEtypes_CapInfo_t)); done: LEAVE(); return ret; } - /** - * @brief This function handles the command response of authenticate + * @brief Association firmware command response handler * - * @param priv A pointer to wlan_private structure - * @param resp A pointer to HostCmd_DS_COMMAND - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int wlan_ret_802_11_authenticate(wlan_private* priv, - HostCmd_DS_COMMAND* resp) -{ - return WLAN_STATUS_SUCCESS; -} - - -/** - * @brief This function handles the command response of associate + * The response buffer for the association command has the following + * memory layout. + * + * For cases where an association response was not received (indicated + * by the CapInfo and AId field): + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | CapInfo/Error Return(u16): | + * | 0xFFFF(-1): Internal error | + * | 0xFFFE(-2): Authentication unhandled message | + * | 0xFFFD(-3): Authentication refused | + * | 0xFFFC(-4): Timeout waiting for AP response | + * .------------------------------------------------------------. + * | StatusCode(u16): | + * | If CapInfo is -1: | + * | An internal firmware failure prevented the | + * | command from being processed. The StatusCode | + * | will be set to 1. | + * | | + * | If CapInfo is -2: | + * | An authentication frame was received but was | + * | not handled by the firmware. IEEE Status | + * | code for the failure is returned. | + * | | + * | If CapInfo is -3: | + * | An authentication frame was received and the | + * | StatusCode is the IEEE Status reported in the | + * | response. | + * | | + * | If CapInfo is -4: | + * | (1) Association response timeout | + * | (2) Authentication response timeout | + * .------------------------------------------------------------. + * | AId(u16): 0xFFFF | + * .------------------------------------------------------------. + * + * + * For cases where an association response was received, the IEEE + * standard association response frame is returned: + * + * .------------------------------------------------------------. + * | Header(4 * sizeof(u16)): Standard command response hdr | + * .------------------------------------------------------------. + * | CapInfo(u16): IEEE Capability | + * .------------------------------------------------------------. + * | StatusCode(u16): IEEE Status Code | + * .------------------------------------------------------------. + * | AId(u16): IEEE Association ID | + * .------------------------------------------------------------. + * | IEEE IEs(variable): Any received IEs comprising the | + * | remaining portion of a received | + * | association response frame. | + * .------------------------------------------------------------. + * + * For simplistic handling, the StatusCode field can be used to determine + * an association success (0) or failure (non-zero). * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_associate(wlan_private* priv, - HostCmd_DS_COMMAND* resp) +int +wlan_ret_802_11_associate(wlan_private * priv, HostCmd_DS_COMMAND * resp) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; - union iwreq_data wrqu; IEEEtypes_AssocRsp_t* pAssocRsp; BSSDescriptor_t* pBSSDesc; + WLAN_802_11_RATES rates; + int ratesSize; ENTER(); pAssocRsp = (IEEEtypes_AssocRsp_t*)&resp->params; - if (pAssocRsp->StatusCode) { + HEXDUMP("ASSOC_RESP:", (void *) &resp->params, + wlan_le16_to_cpu(resp->Size) - S_DS_GEN); - if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { - MacEventDisconnected(priv); - } + Adapter->assocRspSize = MIN(wlan_le16_to_cpu(resp->Size) - S_DS_GEN, + sizeof(Adapter->assocRspBuffer)); - PRINTM(INFO, "ASSOC_RESP: Association Failed, status code = %d\n", - pAssocRsp->StatusCode); + memcpy(Adapter->assocRspBuffer, &resp->params, Adapter->assocRspSize); + + if (pAssocRsp->StatusCode) { + priv->adapter->dbg.num_cmd_assoc_failure++; + PRINTM(CMND, "ASSOC_RESP: Association Failed, " + "status code = %d, error = %d\n", + pAssocRsp->StatusCode, *(short *) &pAssocRsp->Capability); ret = WLAN_STATUS_FAILURE; + goto done; } @@ -1327,44 +1672,59 @@ goto done; } - HEXDUMP("ASSOC_RESP:", (void*)&resp->params, - wlan_le16_to_cpu(resp->Size) - S_DS_GEN); - - /* Send a Media Connected event, according to the Spec */ Adapter->MediaConnectStatus = WlanMediaStateConnected; - Adapter->LinkSpeed = MRVDRV_LINK_SPEED_11mbps; /* Set the attempted BSSID Index to current */ pBSSDesc = Adapter->pAttemptedBSSDesc; PRINTM(INFO, "ASSOC_RESP: %s\n", pBSSDesc->Ssid.Ssid); - /* Set the new SSID to current SSID */ - memcpy(&Adapter->CurBssParams.ssid, - &pBSSDesc->Ssid, - sizeof(WLAN_802_11_SSID)); - - /* Set the new BSSID (AP's MAC address) to current BSSID */ - memcpy(Adapter->CurBssParams.bssid, - pBSSDesc->MacAddress, - MRVDRV_ETH_ADDR_LEN); - /* Make a copy of current BSSID descriptor */ memcpy(&Adapter->CurBssParams.BSSDescriptor, - pBSSDesc, - sizeof(BSSDescriptor_t)); + pBSSDesc, sizeof(BSSDescriptor_t)); + /* update CurBssParams */ + Adapter->CurBssParams.BSSDescriptor.Channel + = pBSSDesc->PhyParamSet.DsParamSet.CurrentChan; + if (setup_rates_from_bssdesc(Adapter, pBSSDesc, rates, &ratesSize)) { + ret = WLAN_STATUS_FAILURE; + goto done; + } + + /* Copy the infra. association rates into Current BSS state structure */ + Adapter->CurBssParams.NumOfRates = ratesSize; + memcpy(&Adapter->CurBssParams.DataRates, rates, ratesSize); + + /* Adjust the timestamps in the scan table to be relative to the newly + * associated AP's TSF + */ + wlan_scan_update_tsf_timestamps(priv, pBSSDesc); + + if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) { + Adapter->CurBssParams.wmm_enabled = TRUE; + } else { + Adapter->CurBssParams.wmm_enabled = FALSE; + } + + if (Adapter->wmm.required && Adapter->CurBssParams.wmm_enabled) { + Adapter->wmm.enabled = TRUE; + } else { + Adapter->wmm.enabled = FALSE; + } + + Adapter->CurBssParams.wmm_uapsd_enabled = FALSE; + + if (Adapter->wmm.enabled == TRUE) { + Adapter->CurBssParams.wmm_uapsd_enabled + = pBSSDesc->wmmIE.QoSInfo.QosUAPSD; + } PRINTM(INFO, "ASSOC_RESP: CurrentPacketFilter is %x\n", Adapter->CurrentPacketFilter); - Adapter->MediaConnectStatus = WlanMediaStateConnected; - - if (Adapter->SecInfo.WPAEnabled - || Adapter->SecInfo.WPA2Enabled - ) + if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled) Adapter->IsGTK_SET = FALSE; Adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0; @@ -1375,18 +1735,9 @@ Adapter->nextSNRNF = 0; Adapter->numSNRNF = 0; - - { - os_carrier_on(priv); - os_start_queue(priv); - } - + priv->adapter->dbg.num_cmd_assoc_success++; PRINTM(INFO, "ASSOC_RESP: Associated \n"); - memcpy(wrqu.ap_addr.sa_data, Adapter->CurBssParams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); - done: LEAVE(); return ret; @@ -1399,11 +1750,12 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_disassociate(wlan_private* priv, - HostCmd_DS_COMMAND* resp) +int +wlan_ret_802_11_disassociate(wlan_private * priv, HostCmd_DS_COMMAND * resp) { ENTER(); + priv->adapter->dbg.num_cmd_deauth++; MacEventDisconnected(priv); LEAVE(); @@ -1411,19 +1763,20 @@ } /** - * @brief This function handles the command response of ad_hoc_start + * @brief This function handles the command response of ad_hoc_start and + * ad_hoc_join * * @param priv A pointer to wlan_private structure * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_ad_hoc_start(wlan_private* priv, - HostCmd_DS_COMMAND* resp) +int +wlan_ret_802_11_ad_hoc(wlan_private * priv, HostCmd_DS_COMMAND * resp) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; - u16 Command = wlan_le16_to_cpu(resp->Command); - u16 Result = wlan_le16_to_cpu(resp->Result); + u16 Command = resp->Command; + u16 Result = resp->Result; HostCmd_DS_802_11_AD_HOC_RESULT* pAdHocResult; union iwreq_data wrqu; BSSDescriptor_t* pBSSDesc; @@ -1432,10 +1785,6 @@ pAdHocResult = &resp->params.result; - PRINTM(INFO, "ADHOC_S_RESP: Size = %d\n", wlan_le16_to_cpu(resp->Size)); - PRINTM(INFO, "ADHOC_S_RESP: Command = %x\n", Command); - PRINTM(INFO, "ADHOC_S_RESP: Result = %x\n", Result); - pBSSDesc = Adapter->pAttemptedBSSDesc; /* @@ -1448,72 +1797,54 @@ } memset(&Adapter->CurBssParams.BSSDescriptor, - 0x00, - sizeof(Adapter->CurBssParams.BSSDescriptor)); + 0x00, sizeof(Adapter->CurBssParams.BSSDescriptor)); - Adapter->AdHocFailed = TRUE; LEAVE(); return WLAN_STATUS_FAILURE; } - /* - * Now the join cmd should be successful - * If BSSID has changed use SSID to compare instead of BSSID - */ - PRINTM(INFO, "ADHOC_J_RESP %s\n", pBSSDesc->Ssid.Ssid); - /* Send a Media Connected event, according to the Spec */ Adapter->MediaConnectStatus = WlanMediaStateConnected; - Adapter->LinkSpeed = MRVDRV_LINK_SPEED_11mbps; if (Command == HostCmd_RET_802_11_AD_HOC_START) { - Adapter->AdHocCreated = TRUE; + PRINTM(INFO, "ADHOC_S_RESP %s\n", pBSSDesc->Ssid.Ssid); /* Update the created network descriptor with the new BSSID */ memcpy(pBSSDesc->MacAddress, - pAdHocResult->BSSID, - MRVDRV_ETH_ADDR_LEN); + pAdHocResult->BSSID, MRVDRV_ETH_ADDR_LEN); } else { + /* + * Now the join cmd should be successful + * If BSSID has changed use SSID to compare instead of BSSID + */ + PRINTM(INFO, "ADHOC_J_RESP %s\n", pBSSDesc->Ssid.Ssid); /* Make a copy of current BSSID descriptor, only needed for join since * the current descriptor is already being used for adhoc start */ - memmove(&Adapter->CurBssParams.BSSDescriptor, - pBSSDesc, - sizeof(BSSDescriptor_t)); + memcpy(&Adapter->CurBssParams.BSSDescriptor, + pBSSDesc, sizeof(BSSDescriptor_t)); } - /* Set the BSSID from the joined/started descriptor */ - memcpy(&Adapter->CurBssParams.bssid, - pBSSDesc->MacAddress, - MRVDRV_ETH_ADDR_LEN); - - /* Set the new SSID to current SSID */ - memcpy(&Adapter->CurBssParams.ssid, - &pBSSDesc->Ssid, - sizeof(WLAN_802_11_SSID)); - - os_carrier_on(priv); - os_start_queue(priv); - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, Adapter->CurBssParams.bssid, ETH_ALEN); + memcpy(wrqu.ap_addr.sa_data, + &Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); - - PRINTM(INFO, "ADHOC_RESP: - Joined/Started Ad Hoc\n"); PRINTM(INFO, "ADHOC_RESP: Channel = %d\n", Adapter->AdhocChannel); PRINTM(INFO, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n", - pAdHocResult->BSSID[0], pAdHocResult->BSSID[1], - pAdHocResult->BSSID[2], pAdHocResult->BSSID[3], - pAdHocResult->BSSID[4], pAdHocResult->BSSID[5]); + Adapter->CurBssParams.BSSDescriptor.MacAddress[0], + Adapter->CurBssParams.BSSDescriptor.MacAddress[1], + Adapter->CurBssParams.BSSDescriptor.MacAddress[2], + Adapter->CurBssParams.BSSDescriptor.MacAddress[3], + Adapter->CurBssParams.BSSDescriptor.MacAddress[4], + Adapter->CurBssParams.BSSDescriptor.MacAddress[5]); LEAVE(); return ret; } - /** * @brief This function handles the command response of ad_hoc_stop * @@ -1521,8 +1852,8 @@ * @param resp A pointer to HostCmd_DS_COMMAND * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_ad_hoc_stop(wlan_private* priv, - HostCmd_DS_COMMAND* resp) +int +wlan_ret_802_11_ad_hoc_stop(wlan_private * priv, HostCmd_DS_COMMAND * resp) { ENTER(); @@ -1532,7 +1863,6 @@ return WLAN_STATUS_SUCCESS; } - #ifdef REASSOCIATION /** * @brief This function handles re-association. it is triggered @@ -1541,13 +1871,15 @@ * @param data A pointer to wlan_thread structure * @return WLAN_STATUS_SUCCESS */ -int wlan_reassociation_thread(void *data) +int +wlan_reassociation_thread(void *data) { wlan_thread* thread = data; wlan_private* priv = thread->priv; wlan_adapter* Adapter = priv->adapter; wait_queue_t wait; int i; + int ret = WLAN_STATUS_SUCCESS; OS_INTERRUPT_SAVE_AREA; @@ -1556,6 +1888,8 @@ wlan_activate_thread(thread); init_waitqueue_entry(&wait, current); + current->flags |= PF_NOFREEZE; + for (;;) { add_wait_queue(&thread->waitQ, &wait); OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); @@ -1566,7 +1900,6 @@ OS_SET_THREAD_STATE(TASK_RUNNING); remove_wait_queue(&thread->waitQ, &wait); - try_to_freeze(); if (Adapter->SurpriseRemoved) { break; @@ -1578,8 +1911,9 @@ PRINTM(INFO, "Reassoc: Thread waking up...\n"); - if (Adapter->InfrastructureMode != Wlan802_11Infrastructure) { - PRINTM(MSG, "Reassoc: non infra mode is not supported\n"); + if (Adapter->InfrastructureMode != Wlan802_11Infrastructure || + Adapter->HardwareStatus != WlanHardwareStatusReady) { + PRINTM(MSG, "Reassoc: mode or hardware status is not correct\n"); continue; } @@ -1589,7 +1923,7 @@ wlan_set_user_scan_ioctl/wlan_set_wap is used. */ if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->ReassocSem)) { - PRINTM(FATAL, "Acquire semaphore error, reassociation thread\n"); + PRINTM(ERROR, "Acquire semaphore error, reassociation thread\n"); goto settimer; } @@ -1602,25 +1936,31 @@ PRINTM(INFO, "Reassoc: Required ESSID: %s\n", Adapter->PreviousSSID.Ssid); - PRINTM(INFO, "Reassoc: Performing Active Scan @ %lu\n", os_time_get()); - - SendSpecificSSIDScan(priv, &Adapter->PreviousSSID, TRUE); + PRINTM(INFO, "Reassoc: Performing Active Scan @ %lu\n", + os_time_get()); + SendSpecificSSIDScan(priv, &Adapter->PreviousSSID); - /* Try to find the specific BSSID we were associated to first */ i = FindSSIDInList(Adapter, &Adapter->PreviousSSID, Adapter->PreviousBSSID, Adapter->InfrastructureMode); if (i < 0) { - /* If the BSSID could not be found, try just the SSID */ + /* If the SSID could not be found, try just the SSID */ i = FindSSIDInList(Adapter, &Adapter->PreviousSSID, - NULL, - Adapter->InfrastructureMode); + NULL, Adapter->InfrastructureMode); } if (i >= 0) { + if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) { + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_SET_WEP, + 0, HostCmd_OPTION_WAITFORRSP, + OID_802_11_ADD_WEP, NULL); + if (ret) + PRINTM(INFO, "Ressoc: Fail to set WEP KEY\n"); + } wlan_associate(priv, &Adapter->ScanTable[i]); } @@ -1631,8 +1971,8 @@ PRINTM(INFO, "Reassoc: No AP found or assoc failed." "Restarting re-assoc Timer @ %lu\n", os_time_get()); - Adapter->TimerIsSet = TRUE; - ModTimer(&Adapter->MrvDrvTimer, 10 * 1000); /* 10s (in ms) */ + Adapter->ReassocTimerIsSet = TRUE; + ModTimer(&Adapter->MrvDrvTimer, MRVDRV_TIMER_10S); } } @@ -1641,4 +1981,48 @@ LEAVE(); return WLAN_STATUS_SUCCESS; } + +/** + * @brief This function triggers re-association by waking up + * re-assoc thread. + * + * @param FunctionContext A pointer to FunctionContext + * @return n/a + */ +void +MrvDrvReassocTimerFunction(void *FunctionContext) +{ + wlan_private *priv = (wlan_private *) FunctionContext; + wlan_adapter *Adapter = priv->adapter; + OS_INTERRUPT_SAVE_AREA; + + ENTER(); + + PRINTM(INFO, "MrvDrvReassocTimer fired.\n"); + Adapter->ReassocTimerIsSet = FALSE; + if (Adapter->PSState != PS_STATE_FULL_POWER) { + /* wait until Exit_PS command returns */ + Adapter->ReassocTimerIsSet = TRUE; + ModTimer(&Adapter->MrvDrvTimer, MRVDRV_TIMER_1S); + PRINTM(INFO, "MrvDrvTimerFunction(PSState=%d) waiting" + "for Exit_PS done\n", Adapter->PSState); + LEAVE(); + return; + } + + PRINTM(INFO, "Waking Up the Reassoc Thread\n"); + + wake_up_interruptible(&priv->ReassocThread.waitQ); + + LEAVE(); + return; +} #endif /* REASSOCIATION */ + +int +sendADHOCBSSIDQuery(wlan_private * priv) +{ + return PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_GET, 0, 0, NULL); +} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_join.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_join.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_join.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_join.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,6 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** @file wlan_join.h * * @brief Interface for the wlan infrastructure and adhoc join routines @@ -9,16 +6,13 @@ * implemented in wlan_join.c. Process all start/join requests for * both adhoc and infrastructure networks * - * @sa wlan_join.c - * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -40,6 +34,12 @@ //! Size of buffer allocated to store the association response from firmware #define MRVDRV_ASSOC_RSP_BUF_SIZE 500 +//! Size of buffer allocated to store IEs passed to firmware in the assoc req +#define MRVDRV_GENIE_BUF_SIZE 256 + +//! Size of buffer allocated to store TLVs passed to firmware in the assoc req +#define MRVDRV_ASSOC_TLV_BUF_SIZE 256 + extern int wlan_cmd_802_11_authenticate(wlan_private* priv, HostCmd_DS_COMMAND* cmd, void* pdata_buf); @@ -56,16 +56,9 @@ extern int wlan_cmd_802_11_associate(wlan_private* priv, HostCmd_DS_COMMAND* cmd, void* pdata_buf); -extern int wlan_cmd_append_reassoc_tlv( wlan_private* priv, u8** ppBuffer ); - -extern int wlan_cmd_append_marvell_tlv( wlan_private* priv, u8** ppBuffer ); - -extern int wlan_cmd_append_generic_ie( wlan_private* priv, u8** ppBuffer ); - - extern int wlan_ret_802_11_authenticate(wlan_private* priv, HostCmd_DS_COMMAND* resp); -extern int wlan_ret_802_11_ad_hoc_start(wlan_private* priv, +extern int wlan_ret_802_11_ad_hoc(wlan_private * priv, HostCmd_DS_COMMAND* resp); extern int wlan_ret_802_11_ad_hoc_stop(wlan_private* priv, HostCmd_DS_COMMAND* resp); @@ -74,8 +67,8 @@ extern int wlan_ret_802_11_associate(wlan_private* priv, HostCmd_DS_COMMAND* resp); - extern int wlan_associate(wlan_private* priv, BSSDescriptor_t* pBSSDesc); +extern int wlan_associate_to_table_idx(wlan_private * priv, int tableIdx); extern int wlanidle_on(wlan_private* priv); extern int wlanidle_off(wlan_private* priv); @@ -83,12 +76,11 @@ extern int wlan_do_adhocstop_ioctl(wlan_private* priv); extern int wlan_reassociation_thread(void* data); -extern int StartAdhocNetwork(wlan_private* priv, WLAN_802_11_SSID* AdhocSSID); +extern int StartAdhocNetwork(wlan_private * priv, + WLAN_802_11_SSID * AdhocSSID); extern int JoinAdhocNetwork(wlan_private* priv, BSSDescriptor_t* pBSSDesc); extern int StopAdhocNetwork(wlan_private* priv); - extern int SendDeauthentication(wlan_private* priv); -extern int wlan_send_deauth(wlan_private* priv); extern int wlan_do_adhocstop_ioctl(wlan_private* priv); extern int wlan_get_assoc_rsp_ioctl(wlan_private* priv, struct iwreq* wrq); @@ -99,4 +91,6 @@ struct sockaddr* awrq, char* extra); #endif +extern int sendADHOCBSSIDQuery(wlan_private * priv); + #endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_main.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_main.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_main.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_main.c 2007-11-06 12:26:40.000000000 -0500 @@ -4,25 +4,13 @@ * driver. It includes init, exit, open, close and main * thread etc.. * - */ -/** - * @mainpage M-WLAN Linux Driver - * - * @section overview_sec Overview - * - * The M-WLAN is a Linux reference driver for Marvell - * 802.11 (a/b/g) WLAN chipset. - * - * @section copyright_sec Copyright - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -32,17 +20,27 @@ * this warranty disclaimer. * */ +/** + * @mainpage M-WLAN Linux Driver + * + * @section overview_sec Overview + * + * The M-WLAN is a Linux reference driver for Marvell + * 802.11 (a/b/g) WLAN chipset. + * + * @section copyright_sec Copyright + * + * Copyright © Marvell International Ltd. and/or its affiliates, 2003-2007 + * + */ /******************************************************** Change log: 09/30/05: Add Doxygen format comments 12/09/05: Add TX_QUEUE support 01/05/06: Add kernel 2.6.x support - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support - Monahans/Zylonite 01/11/06: Conditionalize new scan/join functions. 01/12/06: Add TxLockFlag for UAPSD power save mode and Proprietary Periodic sleep support - 02/13/06: Add a patch for USB interoperability issue ********************************************************/ #include "include.h" @@ -52,7 +50,28 @@ ********************************************************/ #ifdef ENABLE_PM -static struct pm_dev *wlan_pm_dev = NULL; +#define WLAN_PM_DRV_NAME "wlan_pm_drv" + +static int wlan_pm_suspend(struct device *pmdev, u32 state, u32 level); +static int wlan_pm_resume(struct device *pmdev, u32 level); +static void wlan_pm_release(struct device *pmdev); + +/*! + * This structure contains pointers to the power management callback functions. + */ +static struct device_driver wlan_pm_driver = { + .name = WLAN_PM_DRV_NAME, + .bus = &platform_bus_type, + .suspend = wlan_pm_suspend, + .resume = wlan_pm_resume, +}; + +/*! Device Definition for WLAN */ +static struct platform_device wlan_pm_platform_device = { + .name = WLAN_PM_DRV_NAME, + .id = 0, + .dev.release = wlan_pm_release, +}; #endif spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; @@ -61,7 +80,7 @@ #define WLAN_TX_PWR_DEFAULT 20 /*100mW*/ #define WLAN_TX_PWR_US_DEFAULT 20 /*100mW*/ #define WLAN_TX_PWR_JP_DEFAULT 16 /*50mW*/ -#define WLAN_TX_PWR_FR_DEFAULT 20 /*100mW*/ +#define WLAN_TX_PWR_FR_100MW 20 /*100mW */ #define WLAN_TX_PWR_EMEA_DEFAULT 20 /*100mW*/ /* Format { Channel, Frequency (MHz), MaxTxPower } */ @@ -105,14 +124,14 @@ /* Band: 'B/G', Region: France */ static CHANNEL_FREQ_POWER channel_freq_power_FR_BG[] = { - {10, 2457, WLAN_TX_PWR_FR_DEFAULT}, - {11, 2462, WLAN_TX_PWR_FR_DEFAULT}, - {12, 2467, WLAN_TX_PWR_FR_DEFAULT}, - {13, 2472, WLAN_TX_PWR_FR_DEFAULT} + {10, 2457, WLAN_TX_PWR_FR_100MW}, + {11, 2462, WLAN_TX_PWR_FR_100MW}, + {12, 2467, WLAN_TX_PWR_FR_100MW}, + {13, 2472, WLAN_TX_PWR_FR_100MW} }; /* Band: 'B/G', Region: Japan */ -static CHANNEL_FREQ_POWER channel_freq_power_JPN_BG[] = { +static CHANNEL_FREQ_POWER channel_freq_power_JPN41_BG[] = { {1, 2412, WLAN_TX_PWR_JP_DEFAULT}, {2, 2417, WLAN_TX_PWR_JP_DEFAULT}, {3, 2422, WLAN_TX_PWR_JP_DEFAULT}, @@ -125,10 +144,13 @@ {10, 2457, WLAN_TX_PWR_JP_DEFAULT}, {11, 2462, WLAN_TX_PWR_JP_DEFAULT}, {12, 2467, WLAN_TX_PWR_JP_DEFAULT}, - {13, 2472, WLAN_TX_PWR_JP_DEFAULT}, - {14, 2484, WLAN_TX_PWR_JP_DEFAULT} + {13, 2472, WLAN_TX_PWR_JP_DEFAULT} }; +/* Band: 'B/G', Region: Japan */ +static CHANNEL_FREQ_POWER channel_freq_power_JPN40_BG[] = { + {14, 2484, WLAN_TX_PWR_JP_DEFAULT} +}; /******************************************************** Global Variables @@ -137,7 +159,8 @@ /** * the structure for channel, frequency and power */ -typedef struct _region_cfp_table { +typedef struct _region_cfp_table +{ u8 region; CHANNEL_FREQ_POWER *cfp_BG; int cfp_no_BG; @@ -150,27 +173,33 @@ { 0x10, /*US FCC*/ channel_freq_power_US_BG, sizeof(channel_freq_power_US_BG)/sizeof(CHANNEL_FREQ_POWER), - }, + } + , { 0x20, /*CANADA IC*/ channel_freq_power_US_BG, sizeof(channel_freq_power_US_BG)/sizeof(CHANNEL_FREQ_POWER), - }, - { 0x30, /*EU*/ - channel_freq_power_EU_BG, + } + , + {0x30, /*EU*/ channel_freq_power_EU_BG, sizeof(channel_freq_power_EU_BG)/sizeof(CHANNEL_FREQ_POWER), - }, - { 0x31, /*SPAIN*/ - channel_freq_power_SPN_BG, + } + , + {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, sizeof(channel_freq_power_SPN_BG)/sizeof(CHANNEL_FREQ_POWER), - }, - { 0x32, /*FRANCE*/ - channel_freq_power_FR_BG, + } + , + {0x32, /*FRANCE*/ channel_freq_power_FR_BG, sizeof(channel_freq_power_FR_BG)/sizeof(CHANNEL_FREQ_POWER), - }, - { 0x40, /*JAPAN*/ - channel_freq_power_JPN_BG, - sizeof(channel_freq_power_JPN_BG)/sizeof(CHANNEL_FREQ_POWER), - }, + } + , + {0x40, /*JAPAN*/ channel_freq_power_JPN40_BG, + sizeof(channel_freq_power_JPN40_BG) / sizeof(CHANNEL_FREQ_POWER), + } + , + {0x41, /*JAPAN*/ channel_freq_power_JPN41_BG, + sizeof(channel_freq_power_JPN41_BG) / sizeof(CHANNEL_FREQ_POWER), + } + , /*Add new region here */ }; @@ -179,25 +208,28 @@ */ u8 WlanDataRates[WLAN_SUPPORTED_RATES] = { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, - 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 }; + 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 +}; /** * the rates supported */ u8 SupportedRates[G_SUPPORTED_RATES] = - { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0}; + { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, + 0x60, 0x6c, 0 +}; /** * the rates supported for ad-hoc G mode */ u8 AdhocRates_G[G_SUPPORTED_RATES] = - { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0}; + { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, +0 }; /** * the rates supported for ad-hoc B mode */ -u8 AdhocRates_B[4] = - { 0x82, 0x84, 0x8b, 0x96}; +u8 AdhocRates_B[4] = { 0x82, 0x84, 0x8b, 0x96 }; /** * the global variable of a pointer to wlan_private @@ -214,13 +246,7 @@ * the table to keep region code */ u16 RegionCodeToIndex[MRVDRV_MAX_REGION_CODE] = - { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; - -extern BOOLEAN usb_fw_ready; - -u8 *default_fw_name = "usb8388.bin"; -extern u8 *fw_name; - + { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40, 0x41 }; /******************************************************** Local Functions @@ -232,24 +258,26 @@ * @param dev A pointer to net_device structure * @return WLAN_STATUS_SUCCESS */ -static int wlan_open(struct net_device *dev) +static int +wlan_open(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv; wlan_adapter *adapter = priv->adapter; ENTER(); - // For USB adapter, on some systems the device open handler will be called before FW ready. + // On some systems the device open handler will be called before HW ready. // Use the following flag check and wait function to work around the issue. { int i = 0; - while (!usb_fw_ready && i<20) { + while ((adapter->HardwareStatus != WlanHardwareStatusReady) && + (i < MAX_WAIT_DEVICE_READY_COUNT)) { i ++; os_sched_timeout(100); } - if (!usb_fw_ready) { - PRINTM(FATAL, "FW not ready, wlan_open() return failure\n"); + if (i >= MAX_WAIT_DEVICE_READY_COUNT) { + PRINTM(FATAL, "HW not ready, wlan_open() return failure\n"); LEAVE(); return WLAN_STATUS_FAILURE; } @@ -259,7 +287,9 @@ priv->open = TRUE; - if (adapter->MediaConnectStatus == WlanMediaStateConnected) + if ((adapter->MediaConnectStatus == WlanMediaStateConnected) + && (adapter->InfrastructureMode != Wlan802_11IBSS + || adapter->AdhocLinkSensed == TRUE)) os_carrier_on(priv); else os_carrier_off(priv); @@ -276,16 +306,15 @@ * @param dev A pointer to net_device structure * @return WLAN_STATUS_SUCCESS */ -static int wlan_close(struct net_device *dev) +static int +wlan_close(struct net_device *dev) { wlan_private *priv = dev->priv; ENTER(); - /* Flush all the packets upto the OS before stopping */ - wlan_send_rxskbQ(priv); - os_stop_queue(priv); - os_carrier_off(priv); + if (priv->adapter) + wlan_clean_txrx(priv); MODULE_PUT; @@ -296,39 +325,45 @@ } #ifdef ENABLE_PM - /** - * @brief This function is a callback function. it is called by - * kernel to enter or exit power saving mode. + * @brief + * This function is called to put the SDHC in a low power state. Refer to the + * document driver-model/driver.txt in the kernel source tree for more + * information. * - * @param pmdev A pointer to pm_dev - * @param pmreq pm_request_t - * @param pmdata A pointer to pmdata - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + * @param dev the device structure used to give information on which SDHC + * to suspend + * @param state the power state the device is entering + * @param level the stage in device suspension process that we want the + * device to be put in + * + * @return 0 : go to sleep mode + * -1 : do not accept to go to sleep mode. */ -static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq, - void *pmdata) +static int +wlan_pm_suspend(struct device *pmdev, u32 state, u32 level) { wlan_private *priv = wlanpriv; wlan_adapter *Adapter = priv->adapter; struct net_device *dev = priv->wlan_dev.netdev; - PRINTM(INFO, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq); + switch (level) { - switch (pmreq) { - case PM_SUSPEND: - PRINTM(INFO, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n"); + case SUSPEND_DISABLE: + PRINTM(INFO, "WIFI_PM_SUSPEND_CALLBACK: enter SUSPEND_DISABLE.\n"); - /* in associated mode */ + /* in associated mode : check that chipset is in IEEE PS and well configured to wake up the host if needed */ if(Adapter->MediaConnectStatus == WlanMediaStateConnected) { - if( - (Adapter->PSState != PS_STATE_SLEEP) - ) { - PRINTM(INFO, "wlan_pm_callback: can't enter sleep mode\n"); + if ((Adapter->PSState != PS_STATE_SLEEP) + || (!Adapter->bWakeupDevRequired) + || (Adapter->WakeupTries != 0)) { + PRINTM(INFO, "WIFI_PM_SUSPEND_CALLBACK: can't enter sleep mode because \ + PSstate=%d, bWakeupDevRequired=%d, wakeupTries=%d\n", + Adapter->PSState, Adapter->bWakeupDevRequired, Adapter->WakeupTries); return WLAN_STATUS_FAILURE; } - else - { + + else { /* * Detach the network interface @@ -338,73 +373,151 @@ netif_device_detach(dev); PRINTM(INFO, "netif_device_detach().\n"); } - sbi_suspend(priv); + /* Stop bus clock */ + sbi_set_bus_clock(priv, FALSE); } - break; } - /* in non associated mode */ - + /* in non associated mode : check that chipset is in Deepsleep mode */ + else { + if (Adapter->IsDeepSleep == FALSE) { + PRINTM(INFO, + "WIFI_PM_SUSPEND_CALLBACK: No allowed to enter sleep while in FW in full power.\n"); + return WLAN_STATUS_FAILURE; + } /* * Detach the network interface * if the network is running */ - if (netif_running(dev)) + if (netif_running(dev)) { netif_device_detach(dev); + } + } + break; - /* - * Storing and restoring of the regs be taken care - * at the driver rest will be done at wlan driver - * this makes driver independent of the card - */ + case SUSPEND_SAVE_STATE: + PRINTM(INFO, "WIFI_PM_SUSPEND_CALLBACK: enter SUSPEND_SAVE_STATE.\n"); + /* Save bus state to restore it when waking up */ sbi_suspend(priv); break; - case PM_RESUME: + case SUSPEND_POWER_DOWN: + + PRINTM(INFO, "WIFI_PM_SUSPEND_CALLBACK: enter SUSPEND_POWER_DOWN.\n"); + /* nothing to do */ + break; + + default: + + break; + + } + + return WLAN_STATUS_SUCCESS; + +} + +/** + * @brief + * This function is called to bring the SDHC back from a low power state. Refer + * to the document driver-model/driver.txt in the kernel source tree for more + * information. + * + * @param dev the device structure used to give information on which SDHC + * to resume + * @param level the stage in device resumption process that we want the + * device to be put in + * + * @return The function always returns 0. + */ +static int +wlan_pm_resume(struct device *pmdev, u32 level) +{ + wlan_private *priv = wlanpriv; + wlan_adapter *Adapter = priv->adapter; + struct net_device *dev = priv->wlan_dev.netdev; + + switch (level) { + + case RESUME_POWER_ON: + + PRINTM(INFO, "WIFI_PM_RESUME_CALLBACK: enter RESUME_POWER_ON.\n"); + /* nothing to do */ + break; + + case RESUME_RESTORE_STATE: + + PRINTM(INFO, + "WIFI_PM_RESUME_CALLBACK: enter RESUME_RESTORE_STATE.\n"); + /* Restore bus state */ + sbi_resume(priv); + break; + + case RESUME_ENABLE: + + PRINTM(INFO, "WIFI_PM_RESUME_CALLBACK: enter RESUME_ENABLE.\n"); + /* in associated mode */ if(Adapter->MediaConnectStatus == WlanMediaStateConnected) { - { + + if (Adapter->bWakeupDevRequired == FALSE) { + /* could never happen */ + PRINTM(MSG, "WIFI_PM_RESUME_CALLBACK: serious error.\n"); + } else { /* - * Bring the inteface up first - * This case should not happen still ... + * Start bus clock */ - sbi_resume(priv); - + sbi_set_bus_clock(priv, TRUE); /* * Attach the network interface * if the network is running */ if (netif_running(dev)) { netif_device_attach(dev); - PRINTM(INFO, "after netif_device_attach().\n"); + PRINTM(INFO, "WIFI_PM : after netif_device_attach().\n"); } - PRINTM(INFO, "After netif attach, in associated mode.\n"); + PRINTM(INFO, + "WIFI_PM : After netif attach, in associated mode.\n"); } - break; } /* in non associated mode */ + else { + if (netif_running(dev)) { + netif_device_attach(dev); + } - /* - * Bring the inteface up first - * This case should not happen still ... - */ - - - sbi_resume(priv); + PRINTM(INFO, + "WIFI_PM : after netif attach, in NON associated mode.\n"); + } + break; + default: + break; - if (netif_running(dev)) - netif_device_attach(dev); + } + return WLAN_STATUS_SUCCESS; - PRINTM(INFO, "after netif attach, in NON associated mode.\n"); - break; } - return WLAN_STATUS_SUCCESS; +/** + * @brief + * Dummy function to be compliant with Linux Power Management framework. + * + * @param pmdev the device structure used to give information on which SDHC + * to use + * + * @return None. + */ +static void +wlan_pm_release(struct device *pmdev) +{ + PRINTM(INFO, "WIFI_PM_DRIVER : Into pm_device release function\n"); + return; } + #endif /* ENABLE_PM */ /** @@ -414,30 +527,22 @@ * @param dev A pointer to net_device structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +static int +wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { int ret; wlan_private *priv = dev->priv; - ENTER(); + ret = WLAN_STATUS_SUCCESS; + ENTER(); + PRINTM(DATA, "Data <= kernel\n"); if (wlan_tx_packet(priv, skb)) { /* Transmit failed */ ret = WLAN_STATUS_FAILURE; - goto done; - } else { - /* Transmit succeeded */ - if(priv->adapter->TxSkbNum >= MAX_NUM_IN_TX_Q) - { - UpdateTransStart(dev); - os_stop_queue(priv); } - } - - ret = WLAN_STATUS_SUCCESS; -done: LEAVE(); return ret; @@ -450,29 +555,20 @@ * @param dev A pointer to net_device structure * @return n/a */ -static void wlan_tx_timeout(struct net_device *dev) +static void +wlan_tx_timeout(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv; ENTER(); - PRINTM(FATAL, "tx watch dog timeout!\n"); - - priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED; + PRINTM(DATA, "Tx timeout\n"); UpdateTransStart(dev); - if (priv->adapter->CurrentTxSkb) { - if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { - /* If we are here, we have not received feedback from - the previous packet. Assume TX_FAIL and move on. */ - priv->adapter->EventCause = 0x01000000; - SendTxFeedback(priv); - } else + priv->adapter->dbg.num_tx_timeout++; + + priv->adapter->IntCounter++; wake_up_interruptible(&priv->MainThread.waitQ); - } - else { - os_start_queue(priv); - } LEAVE(); } @@ -483,7 +579,8 @@ * @param dev A pointer to wlan_private structure * @return A pointer to net_device_stats structure */ -static struct net_device_stats *wlan_get_stats(struct net_device *dev) +static struct net_device_stats * +wlan_get_stats(struct net_device *dev) { wlan_private *priv = (wlan_private *) dev->priv; @@ -497,7 +594,8 @@ * @param pRxPD A pointer to RxPD structure of received packet * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int wlan_set_mac_address(struct net_device *dev, void *addr) +static int +wlan_set_mac_address(struct net_device *dev, void *addr) { int ret = WLAN_STATUS_SUCCESS; wlan_private *priv = (wlan_private *) dev->priv; @@ -516,8 +614,7 @@ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_MAC_ADDRESS, HostCmd_ACT_SET, - HostCmd_OPTION_WAITFORRSP, - 0, NULL); + HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { PRINTM(INFO, "set mac address failed.\n"); @@ -539,7 +636,8 @@ * @param dev A pointer to net_device structure * @return n/a */ -static void wlan_set_multicast_list(struct net_device *dev) +static void +wlan_set_multicast_list(struct net_device *dev) { wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; @@ -551,23 +649,17 @@ if (dev->flags & IFF_PROMISC) { PRINTM(INFO, "Enable Promiscuous mode\n"); - Adapter->CurrentPacketFilter |= - HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - Adapter->CurrentPacketFilter &= - ~(HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE | - HostCmd_ACT_MAC_MULTICAST_ENABLE); + Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; + Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; } else { /* Multicast */ - Adapter->CurrentPacketFilter &= - ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; + Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; if (dev->flags & IFF_ALLMULTI || dev->mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { PRINTM(INFO, "Enabling All Multicast!\n"); Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - Adapter->CurrentPacketFilter &= - ~HostCmd_ACT_MAC_MULTICAST_ENABLE; } else { Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; @@ -575,19 +667,14 @@ if (!dev->mc_count) { PRINTM(INFO, "No multicast addresses - " "disabling multicast!\n"); - Adapter->CurrentPacketFilter &= - ~HostCmd_ACT_MAC_MULTICAST_ENABLE; + } else { int i; - Adapter->CurrentPacketFilter |= - HostCmd_ACT_MAC_MULTICAST_ENABLE; - Adapter->NumOfMulticastMACAddr = CopyMulticastAddrs(Adapter, dev); - PRINTM(INFO, "Multicast addresses: %d\n", - dev->mc_count); + PRINTM(INFO, "Multicast addresses: %d\n", dev->mc_count); for (i = 0; i < dev->mc_count; i++) { PRINTM(INFO, "Multicast address %d:" @@ -601,14 +688,15 @@ } /* set multicast addresses to firmware */ PrepareAndSendCommand(priv, HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, - 0, 0, NULL); + HostCmd_ACT_GEN_SET, 0, 0, NULL); } } } if (Adapter->CurrentPacketFilter != OldPacketFilter) { - SetMacPacketFilter(priv); + PrepareAndSendCommand(priv, + HostCmd_CMD_MAC_CONTROL, + 0, 0, 0, &Adapter->CurrentPacketFilter); } LEAVE(); @@ -620,7 +708,8 @@ * @param RxSkbQ A pointer to rx_skb queue * @return A pointer to skb */ -static struct sk_buff* wlan_pop_rx_skb(struct sk_buff *RxSkbQ) +static struct sk_buff * +wlan_pop_rx_skb(struct sk_buff *RxSkbQ) { struct sk_buff* skb_data = NULL; @@ -640,7 +729,8 @@ * @param data A pointer to wlan_thread structure * @return WLAN_STATUS_SUCCESS */ -static int wlan_service_main_thread(void *data) +static int +wlan_service_main_thread(void *data) { wlan_thread *thread = data; wlan_private *priv = thread->priv; @@ -648,7 +738,6 @@ wait_queue_t wait; u8 ireg = 0; - OS_INTERRUPT_SAVE_AREA; ENTER(); @@ -657,62 +746,58 @@ init_waitqueue_entry(&wait, current); + current->flags |= PF_NOFREEZE; + wmm_init(priv); for (;;) { - PRINTM(INFO, "main-thread 111: IntCounter=%d " - "CurrentTxSkb=%p dnld_sent=%d\n", - Adapter->IntCounter, - Adapter->CurrentTxSkb, - priv->wlan_dev.dnld_sent); - add_wait_queue(&thread->waitQ, &wait); OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); TX_DISABLE; - if ( + if ((Adapter->WakeupTries) || (Adapter->PSState == PS_STATE_SLEEP - ) || - ( - !Adapter->IntCounter - && (priv->wlan_dev.dnld_sent || !Adapter->TxSkbNum ) + && !Adapter->bWakeupDevRequired) || + (!Adapter->IntCounter && + Adapter->PSState == PS_STATE_PRE_SLEEP) || + (!Adapter->IntCounter + && (priv->wlan_dev.dnld_sent || Adapter->TxLockFlag + || wmm_lists_empty(priv) || wmm_is_queue_stopped(priv)) + && (priv->wlan_dev.dnld_sent || !Adapter->CurrentTxSkb) && (priv->wlan_dev.dnld_sent || Adapter->CurCmd || list_empty(&Adapter->CmdPendingQ)) ) ) { - PRINTM(INFO, "main-thread sleeping... Conn=%d IntC=%d PS_Mode=%d PS_State=%d\n", - Adapter->MediaConnectStatus, - Adapter->IntCounter, - Adapter->PSMode, - Adapter->PSState); + PRINTM(INFO, "main-thread sleeping... " + "HS_Act=%s WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d\n", + (Adapter->HS_Activated) ? "Y" : "N", + (Adapter->bWakeupDevRequired) ? "Y" : "N", + (Adapter->MediaConnectStatus) ? "Y" : "N", + Adapter->PSMode, Adapter->PSState); TX_RESTORE; schedule(); + PRINTM(INFO, "main-thread waking up: IntCnt=%d " + "CurCmd=%s CmdPending=%s\n" + " Connect=%s " + "CurTxSkb=%s dnld_sent=%d\n", + Adapter->IntCounter, + (Adapter->CurCmd) ? "Y" : "N", + list_empty(&Adapter->CmdPendingQ) ? "N" : "Y", + (Adapter->MediaConnectStatus) ? "Y" : "N", + (Adapter->CurrentTxSkb) ? "Y" : "N", + priv->wlan_dev.dnld_sent); } else { TX_RESTORE; } - PRINTM(INFO, "main-thread 222 (waking up): IntCounter=%d CurrentTxSkb=%p " - "dnld_sent=%d\n", - Adapter->IntCounter, - Adapter->CurrentTxSkb, - priv->wlan_dev.dnld_sent); - OS_SET_THREAD_STATE(TASK_RUNNING); remove_wait_queue(&thread->waitQ, &wait); - try_to_freeze(); - - PRINTM(INFO, "main-thread 333: IntCounter=%d CurrentTxSkb=%p " - "dnld_sent=%d\n", - Adapter->IntCounter, - Adapter->CurrentTxSkb, - priv->wlan_dev.dnld_sent); - if (kthread_should_stop() - || Adapter->SurpriseRemoved) { - PRINTM(INFO, "main-thread: break from main thread: SurpriseRemoved=0x%x\n", - Adapter->SurpriseRemoved); + if (kthread_should_stop() || Adapter->SurpriseRemoved) { + PRINTM(INFO, "main-thread: break from main thread: " + "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); break; } @@ -722,25 +807,33 @@ OS_INT_RESTORE; if (sbi_get_int_status(priv, &ireg)) { - PRINTM(INFO, "main-thread: reading HOST_INT_STATUS_REG failed\n"); + PRINTM(ERROR, + "main-thread: reading HOST_INT_STATUS_REG failed\n"); continue; } OS_INT_DISABLE; Adapter->HisRegCpy |= ireg; OS_INT_RESTORE; - } - - PRINTM(INFO, "main-thread 444: IntCounter=%d CurrentTxSkb=%p " - "dnld_sent=%d\n", - Adapter->IntCounter, - Adapter->CurrentTxSkb, - priv->wlan_dev.dnld_sent); + PRINTM(INTR, "INT: status = 0x%x\n", Adapter->HisRegCpy); + } else if (Adapter->bWakeupDevRequired + && (Adapter->HS_Activated || (Adapter->IsDeepSleep) + ) + ) { + Adapter->WakeupTries++; + PRINTM(CMND, + "Wakeup device... WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d\n", + (Adapter->bWakeupDevRequired) ? "Y" : "N", + (priv->adapter->MediaConnectStatus) ? "Y" : "N", + priv->adapter->PSMode, priv->adapter->PSState); + /* Wake up device */ + if (sbi_exit_deep_sleep(priv)) + PRINTM(MSG, "main-thread: wakeup dev failed\n"); + continue; + } /* Command response? */ if (Adapter->HisRegCpy & HIS_CmdUpLdRdy) { - PRINTM(INFO, "main-thread: Cmd response ready.\n"); - OS_INT_DISABLE; Adapter->HisRegCpy &= ~HIS_CmdUpLdRdy; OS_INT_RESTORE; @@ -750,8 +843,6 @@ /* Any received data? */ if (Adapter->HisRegCpy & HIS_RxUpLdRdy) { - PRINTM(INFO, "main-thread: Rx Packet ready.\n"); - OS_INT_DISABLE; Adapter->HisRegCpy &= ~HIS_RxUpLdRdy; OS_INT_RESTORE; @@ -761,14 +852,12 @@ /* Any Card Event */ if (Adapter->HisRegCpy & HIS_CardEvent) { - PRINTM(INFO, "main-thread: Card Event Activity.\n"); - OS_INT_DISABLE; Adapter->HisRegCpy &= ~HIS_CardEvent; OS_INT_RESTORE; if (sbi_read_event_cause(priv)) { - PRINTM(MSG, "main-thread: sbi_read_event_cause failed.\n"); + PRINTM(ERROR, "main-thread: sbi_read_event_cause failed.\n"); continue; } wlan_process_event(priv); @@ -777,30 +866,30 @@ /* Check if we need to confirm Sleep Request received previously */ if (Adapter->PSState == PS_STATE_PRE_SLEEP) { if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) { - if(Adapter->MediaConnectStatus == WlanMediaStateConnected) { - PRINTM(INFO, "main_thread: PRE_SLEEP--IntCounter=%d CurrentTxSkb=%p " - "dnld_sent=%d CurCmd=%p, confirm now\n", - Adapter->IntCounter, - Adapter->CurrentTxSkb, - priv->wlan_dev.dnld_sent, - Adapter->CurCmd); - + ASSERT(Adapter->MediaConnectStatus == + WlanMediaStateConnected); PSConfirmSleep(priv, (u16) Adapter->PSMode); } - else { - /* workaround for firmware sending deauth/linkloss event - immediately after sleep request, remove this after - firmware fixes it */ - Adapter->PSState = PS_STATE_AWAKE; - PRINTM(MSG, "main-thread: ignore PS_SleepConfirm in non-connected state\n"); - } } + + /* The PS state is changed during processing of + * Sleep Request event above + */ + if ((Adapter->PSState == PS_STATE_SLEEP) + || (Adapter->PSState == PS_STATE_PRE_SLEEP)) { + continue; } - /* The PS state is changed during processing of Sleep Request event above */ - if ((priv->adapter->PSState == PS_STATE_SLEEP) - || (priv->adapter->PSState == PS_STATE_PRE_SLEEP) - ) { + if (Adapter->IsDeepSleep) + continue; + + /* The HS_Activated flag is changed during processing of + HS_Activate command resp */ + /* We cannot send command or data if HS_Activated and + WakeupDevRequired are TRUE */ + if (Adapter->HS_Activated && Adapter->bWakeupDevRequired) { + PRINTM(INFO, "main-thread: cannot send command or data, " + "HS_Activated=%d\n", Adapter->HS_Activated); continue; } @@ -809,11 +898,15 @@ ExecuteNextCommand(priv); } - - if(!priv->wlan_dev.dnld_sent && (Adapter->TxLockFlag == 0) - && !list_empty((struct list_head *)&priv->adapter->TxSkbQ)){ - wlan_process_txqueue(priv); + if (!priv->wlan_dev.dnld_sent + && !wmm_lists_empty(priv) && !wmm_is_queue_stopped(priv)) { + if ((Adapter->PSState == PS_STATE_FULL_POWER) + || (Adapter->sleep_period.period == 0) + || (Adapter->TxLockFlag == FALSE)) { + wmm_process_tx(priv); + } } + } wlan_deactivate_thread(thread); @@ -829,7 +922,8 @@ * @param card A pointer to card * @return A pointer to wlan_private structure */ -static wlan_private *wlan_add_card(void *card) +static wlan_private * +wlan_add_card(void *card) { struct net_device *dev = NULL; wlan_private *priv = NULL; @@ -872,12 +966,9 @@ dev->do_ioctl = wlan_do_ioctl; dev->set_mac_address = wlan_set_mac_address; - -#define WLAN_WATCHDOG_TIMEOUT (2 * HZ) - dev->tx_timeout = wlan_tx_timeout; dev->get_stats = wlan_get_stats; - dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT; + dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; #ifdef WIRELESS_EXT dev->get_wireless_stats = wlan_get_wireless_stats; @@ -888,31 +979,40 @@ dev->flags |= IFF_BROADCAST | IFF_MULTICAST; dev->set_multicast_list = wlan_set_multicast_list; - init_waitqueue_head(&priv->adapter->ds_awake_q); #ifdef ENABLE_PM - if(!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback))) - PRINTM(MSG, "Failed to register PM callback\n"); + /* register Driver to Linux Power Management system. */ + if (!driver_register(&wlan_pm_driver)) { + /* Register one device to Linux Power Management system. */ + if (platform_device_register(&wlan_pm_platform_device)) { + PRINTM(MSG, + "WiFi driver, wlan_main : error when registering device to Linux Power Managment.\n"); + driver_unregister(&wlan_pm_driver); + } else { + PRINTM(INFO, + "WiFi device and driver registered to Linux Power Managment.\n"); + } + } else { + PRINTM(MSG, + "WiFi driver, wlan_main : error when registering driver to Linux Power Managment.\n"); + } #endif INIT_LIST_HEAD(&priv->adapter->CmdFreeQ); INIT_LIST_HEAD(&priv->adapter->CmdPendingQ); - PRINTM(INFO, "Starting kthread...\n"); priv->MainThread.priv = priv; wlan_create_thread(wlan_service_main_thread, - &priv->MainThread, - "wlan_main_service"); + &priv->MainThread, "wlan_main_service"); ConfigureThreadPriority(); #ifdef REASSOCIATION priv->ReassocThread.priv = priv; wlan_create_thread(wlan_reassociation_thread, - &priv->ReassocThread, - "wlan_reassoc_service"); + &priv->ReassocThread, "wlan_reassoc_service"); #endif /* REASSOCIATION */ /* @@ -926,21 +1026,25 @@ goto err_registerdev; } + SET_NETDEV_DEV(dev, priv->hotplug_device); + PRINTM(WARN, "%s: Marvell Wlan 802.11 Adapter " "revision 0x%02X at IRQ %i\n", dev->name, priv->adapter->chip_rev, dev->irq); +#ifdef CONFIG_PROC_FS wlan_proc_entry(priv, dev); #ifdef PROC_DEBUG wlan_debug_entry(priv, dev); #endif +#endif /* CPNFIG_PROC_FS */ /* Get the CIS Table */ sbi_get_cis_info(priv); /* init FW and HW */ if (wlan_init_fw(priv)) { - PRINTM(INFO, "Firmware Init Failed\n"); + PRINTM(FATAL, "Firmware Init Failed\n"); goto err_init_fw; } @@ -955,6 +1059,13 @@ err_init_fw: sbi_unregister_dev(priv); +#ifdef CONFIG_PROC_FS +#ifdef PROC_DEBUG + wlan_debug_remove(priv); +#endif + wlan_proc_remove(priv); +#endif + err_registerdev: /* Stop the thread servicing the interrupts */ wake_up_interruptible(&priv->MainThread.waitQ); @@ -964,9 +1075,10 @@ wake_up_interruptible(&priv->ReassocThread.waitQ); wlan_terminate_thread(&priv->ReassocThread); #endif /* REASSOCIATION */ + err_kmalloc: unregister_netdev(dev); - kfree(priv->adapter); + wlan_free_adapter(priv); wlanpriv = NULL; LEAVE(); @@ -979,7 +1091,8 @@ * @param priv A pointer to card * @return WLAN_STATUS_SUCCESS */ -static int wlan_remove_card(void *card) +static int +wlan_remove_card(void *card) { wlan_private *priv = wlanpriv; wlan_adapter *Adapter; @@ -1000,10 +1113,8 @@ return WLAN_STATUS_SUCCESS; } - dev = priv->wlan_dev.netdev; - wake_up_interruptible(&Adapter->ds_awake_q); if (Adapter->CurCmd) { @@ -1013,10 +1124,26 @@ Adapter->CurCmd = NULL; + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + wlan_clean_txrx(priv); + Adapter->MediaConnectStatus = WlanMediaStateDisconnected; + } + if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) { Adapter->PSMode = Wlan802_11PowerModeCAM; PSWakeup(priv, HostCmd_OPTION_WAITFORRSP); } + if (Adapter->IsDeepSleep == TRUE) { + sbi_exit_deep_sleep(priv); + if (Adapter->IsDeepSleep == TRUE) { + if (os_wait_interruptible_timeout(Adapter->ds_awake_q, + !Adapter->IsDeepSleep, + MRVDRV_DEEP_SLEEP_EXIT_TIMEOUT) + == 0) { + PRINTM(MSG, "ds_awake_q: timer expired\n"); + } + } + } memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; @@ -1025,21 +1152,16 @@ /* Disable interrupts on the card as we cannot handle them after RESET */ sbi_disable_host_int(priv); - PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RESET, - HostCmd_ACT_HALT, 0, 0, NULL); + PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RESET, 0, 0, 0, NULL); os_sched_timeout(200); #ifdef ENABLE_PM - pm_unregister(wlan_pm_dev); + /* unregister driver and device from Linux Power Management system. */ + platform_device_unregister(&wlan_pm_platform_device); + driver_unregister(&wlan_pm_driver); #endif - /* Flush all the packets upto the OS before stopping */ - wlan_send_rxskbQ(priv); - cleanup_txqueues(priv); - os_stop_queue(priv); - os_carrier_off(priv); - Adapter->SurpriseRemoved = TRUE; /* Stop the thread servicing the interrupts */ @@ -1049,10 +1171,12 @@ wake_up_interruptible(&priv->ReassocThread.waitQ); #endif /* REASSOCIATION */ +#ifdef CONFIG_PROC_FS #ifdef PROC_DEBUG wlan_debug_remove(priv); #endif wlan_proc_remove(priv); +#endif PRINTM(INFO, "unregester dev\n"); sbi_unregister_dev(priv); @@ -1063,8 +1187,6 @@ /* Last reference is our one */ PRINTM(INFO, "refcnt = %d\n", atomic_read(&dev->refcnt)); - os_schedule(10); - PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name, (dev->features & NETIF_F_DYNALLOC)?"":", old style"); @@ -1083,52 +1205,6 @@ /******************************************************** Global Functions ********************************************************/ -/** - * @brief Cleanup TX queue - * @param priv pointer to wlan_private - * @return N/A -*/ -void cleanup_txqueues(wlan_private *priv) -{ - struct sk_buff *delNode, *Q; - - Q = &priv->adapter->TxSkbQ; - while (!list_empty((struct list_head *)Q)) { - delNode = Q->next; - list_del((struct list_head *)delNode); - kfree_skb(delNode); - } - priv->adapter->TxSkbNum = 0; -} - - -/** - * @brief handle TX Queue - * @param priv pointer to wlan_private - * @return N/A -*/ -void wlan_process_txqueue(wlan_private * priv) -{ - wlan_adapter *Adapter = priv->adapter; - ulong flags; - struct sk_buff *Q; - OS_INTERRUPT_SAVE_AREA; /* Needed for Threadx; Dummy for Linux */ - ENTER(); - spin_lock_irqsave(&Adapter->CurrentTxLock, flags); - if(Adapter->TxSkbNum > 0){ - Q = &priv->adapter->TxSkbQ; - Adapter->CurrentTxSkb = Q->next; - list_del((struct list_head *) Adapter->CurrentTxSkb); - Adapter->TxSkbNum --; - } - spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); - if (Adapter->CurrentTxSkb) { - wlan_process_tx(priv); - } - - LEAVE(); -} - /** * @brief This function sends the rx packets to the os from the skb queue @@ -1136,7 +1212,8 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -void wlan_send_rxskbQ(wlan_private *priv) +void +wlan_send_rxskbQ(wlan_private * priv) { struct sk_buff *skb; @@ -1159,7 +1236,8 @@ * @param cfp_no A pointer to CFP number * @return A pointer to CFP */ -CHANNEL_FREQ_POWER *wlan_get_region_cfp_table(u8 region, u8 band, int *cfp_no) +CHANNEL_FREQ_POWER * +wlan_get_region_cfp_table(u8 region, u8 band, int *cfp_no) { int i; @@ -1167,7 +1245,8 @@ for ( i=0; i< sizeof(region_cfp_table)/sizeof(region_cfp_table_t); i++ ) { - PRINTM(INFO, "region_cfp_table[i].region=%d\n", region_cfp_table[i].region ); + PRINTM(INFO, "region_cfp_table[i].region=%d\n", + region_cfp_table[i].region); if (region_cfp_table[i].region == region ) { { *cfp_no = region_cfp_table[i].cfp_no_BG; @@ -1189,7 +1268,8 @@ * @param band The band * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_set_regiontable(wlan_private *priv, u8 region, u8 band) +int +wlan_set_regiontable(wlan_private * priv, u8 region, u8 band) { wlan_adapter *Adapter = priv->adapter; int i = 0; @@ -1206,8 +1286,7 @@ if ( cfp != NULL ) { Adapter->region_channel[i].NrCFP = cfp_no; Adapter->region_channel[i].CFP = cfp; - } - else { + } else { PRINTM(INFO, "wrong region code %#x in Band B-G\n",region); return WLAN_STATUS_FAILURE; } @@ -1228,26 +1307,24 @@ * @param dev A pointer to net_device structure * @return n/a */ -void wlan_interrupt(struct net_device *dev) +void +wlan_interrupt(struct net_device *dev) { wlan_private *priv = dev->priv; - ENTER(); - - PRINTM(INFO, "wlan_interrupt: IntCounter=%d\n", - priv->adapter->IntCounter); - priv->adapter->IntCounter++; + PRINTM(INTR, "*\n"); + + priv->adapter->WakeupTries = 0; + if (priv->adapter->bWakeupDevRequired) + sd_set_clock(priv, 0); /* default clock frequency */ if(priv->adapter->PSState == PS_STATE_SLEEP) { priv->adapter->PSState = PS_STATE_AWAKE; } - wake_up_interruptible(&priv->MainThread.waitQ); - - LEAVE(); } /** @@ -1256,16 +1333,13 @@ * @param n/a A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_init_module(void) +int +wlan_init_module(void) { int ret = WLAN_STATUS_SUCCESS; ENTER(); - if(fw_name == NULL) { - fw_name = default_fw_name; - } - if (sbi_register(wlan_add_card, wlan_remove_card, NULL) == NULL) { ret = WLAN_STATUS_FAILURE; goto done; @@ -1282,7 +1356,8 @@ * @param priv n/a * @return n/a */ -void wlan_cleanup_module(void) +void +wlan_cleanup_module(void) { ENTER(); diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_proc.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_proc.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_proc.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_proc.c 2007-11-06 12:26:40.000000000 -0500 @@ -2,13 +2,12 @@ * @brief This file contains functions for proc fin proc file. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -26,7 +25,7 @@ ********************************************************/ #include "include.h" - +#ifdef CONFIG_PROC_FS /******************************************************** Local Variables ********************************************************/ @@ -34,19 +33,14 @@ static char *szModes[] = { "Ad-hoc", "Managed", - "Auto" -}; - -static char *szStates[] = { - "Connected", - "Disconnected" + "Auto", + "Unknown" }; /******************************************************** Global Variables ********************************************************/ - /******************************************************** Local Functions ********************************************************/ @@ -61,40 +56,45 @@ * @param data data to output * @return number of output data */ -static int wlan_proc_read(char *page, char **start, off_t offset, +static int +wlan_proc_read(char *page, char **start, off_t offset, int count, int *eof, void *data) { -#ifdef CONFIG_PROC_FS int i; char *p = page; struct net_device *netdev = data; struct dev_mc_list *mcptr = netdev->mc_list; char fmt[64]; wlan_private *priv = netdev->priv; -#endif + wlan_adapter *Adapter = priv->adapter; + ulong flags; if (offset != 0) { *eof = 1; goto exit; } - get_version(priv->adapter, fmt, sizeof(fmt) - 1); + get_version(Adapter, fmt, sizeof(fmt) - 1); p += sprintf(p, "driver_name = " "\"wlan\"\n"); p += sprintf(p, "driver_version = %s", fmt); p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name); - p += sprintf(p, "Mode=\"%s\"\n", szModes[priv->adapter->InfrastructureMode]); + p += sprintf(p, "Mode=\"%s\"\n", szModes[Adapter->InfrastructureMode]); p += sprintf(p, "State=\"%s\"\n", - szStates[priv->adapter->MediaConnectStatus]); + ((Adapter->MediaConnectStatus == + WlanMediaStateDisconnected) ? "Disconnected" : + "Connected")); p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); p += sprintf(p, "MCCount=\"%d\"\n", netdev->mc_count); - p += sprintf(p, "ESSID=\"%s\"\n", (u8 *)priv->adapter->CurBssParams.ssid.Ssid); - p += sprintf(p, "Channel=\"%d\"\n", priv->adapter->CurBssParams.channel); - p += sprintf(p, "region_code = \"%02x\"\n", (u32)priv->adapter->RegionCode); + p += sprintf(p, "ESSID=\"%s\"\n", + (u8 *) Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid); + p += sprintf(p, "Channel=\"%d\"\n", + Adapter->CurBssParams.BSSDescriptor.Channel); + p += sprintf(p, "region_code = \"%02x\"\n", (u32) Adapter->RegionCode); /* * Put out the multicast list @@ -109,14 +109,31 @@ mcptr = mcptr->next; } - p += sprintf(p, "num_tx_bytes_transmited = \"%lu\"\n",priv->stats.tx_bytes); - p += sprintf(p, "num_rx_bytes_recieved = \"%lu\"\n",priv->stats.rx_bytes); - p += sprintf(p, "num_tx_packets_transmited = \"%lu\"\n",priv->stats.tx_packets); - p += sprintf(p, "num_rx_packets_received = \"%lu\"\n",priv->stats.rx_packets); - p += sprintf(p, "num_tx_packets_dropped = \"%lu\"\n",priv->stats.tx_dropped); - p += sprintf(p, "num_rx_packets_dropped = \"%lu\"\n",priv->stats.rx_dropped); - p += sprintf(p, "num_tx_errors= \"%lu\"\n",priv->stats.tx_errors); - p += sprintf(p, "num_rx_errors= \"%lu\"\n",priv->stats.rx_errors); + p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); + p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); + p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); + p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); + p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); + p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); + p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); + p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); + p += sprintf(p, "carrier %s\n", + ((netif_carrier_ok(priv->wlan_dev.netdev)) ? "on" : "off")); + p += sprintf(p, "tx queue %s\n", + ((netif_queue_stopped(priv->wlan_dev.netdev)) ? "stopped" : + "started")); + + spin_lock_irqsave(&Adapter->QueueSpinLock, flags); + if (Adapter->CurCmd) { + HostCmd_DS_COMMAND *CmdPtr = + (HostCmd_DS_COMMAND *) Adapter->CurCmd->BufVirtualAddr; + p += sprintf(p, "CurCmd ID = 0x%x, 0x%x\n", + wlan_cpu_to_le16(CmdPtr->Command), + wlan_cpu_to_le16(*(u16 *) ((u8 *) CmdPtr + S_DS_GEN))); + } else { + p += sprintf(p, "CurCmd NULL\n"); + } + spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags); exit: return (p - page); @@ -133,10 +150,10 @@ * @param dev pointer net_device * @return N/A */ -void wlan_proc_entry(wlan_private *priv, struct net_device *dev) +void +wlan_proc_entry(wlan_private * priv, struct net_device *dev) { -#ifdef CONFIG_PROC_FS PRINTM(INFO, "Creating Proc Interface\n"); if (!priv->proc_entry) { @@ -147,7 +164,6 @@ ("info", 0, priv->proc_entry, wlan_proc_read, dev); } } -#endif } /** @@ -156,11 +172,47 @@ * @param priv pointer wlan_private * @return N/A */ -void wlan_proc_remove(wlan_private *priv) +void +wlan_proc_remove(wlan_private * priv) { -#ifdef CONFIG_PROC_FS - if (priv->proc_entry) + + if (priv->proc_entry) { remove_proc_entry("info", priv->proc_entry); + } remove_proc_entry("wlan", proc_net); -#endif + +} + +/** + * @brief convert string to number + * + * @param s pointer to numbered string + * @return converted number from string s + */ +int +string_to_number(char *s) +{ + int r = 0; + int base = 0; + + if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) + base = 16; + else + base = 10; + if (base == 16) + s += 2; + for (s = s; *s != 0; s++) { + if ((*s >= 48) && (*s <= 57)) + r = (r * base) + (*s - 48); + else if ((*s >= 65) && (*s <= 70)) + r = (r * base) + (*s - 55); + else if ((*s >= 97) && (*s <= 102)) + r = (r * base) + (*s - 87); + else + break; } + + return r; +} + +#endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_rx.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_rx.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_rx.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_rx.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,14 @@ /** @file wlan_rx.c - * @brief This file contains the handling of RX in wlan driver. + * @brief This file contains the handling of RX in wlan + * driver. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -51,7 +51,6 @@ typedef struct { - RxPD rx_pd; Eth803Hdr_t eth803_hdr; Rfc1042Hdr_t rfc1042_hdr; @@ -59,10 +58,11 @@ typedef struct { - RxPD rx_pd; - void* eth80211_hdr; + u8 dest_addr[6]; + u8 src_addr[6]; + u16 ethertype; -} __ATTRIB_PACK__ Rx80211PacketHdr_t; +} __ATTRIB_PACK__ EthII_Hdr_t; /******************************************************** Global Variables @@ -78,7 +78,8 @@ * @param priv A pointer to wlan_private structure * @return AvgSNR */ -static u8 wlan_getAvgSNR(wlan_private * priv) +static u8 +wlan_getAvgSNR(wlan_private * priv) { u8 i; u16 temp = 0; @@ -97,7 +98,8 @@ * @param priv A pointer to wlan_private structure * @return AvgNF */ -static u8 wlan_getAvgNF(wlan_private * priv) +static u8 +wlan_getAvgNF(wlan_private * priv) { u8 i; u16 temp = 0; @@ -117,7 +119,8 @@ * @param pRxPD A pointer to RxPD structure of received packet * @return n/a */ -static void wlan_save_rawSNRNF(wlan_private * priv, RxPD * pRxPD) +static void +wlan_save_rawSNRNF(wlan_private * priv, RxPD * pRxPD) { wlan_adapter *Adapter = priv->adapter; if(Adapter->numSNRNF < Adapter->data_avg_factor) @@ -130,6 +133,100 @@ return; } +#define DATA_RSSI_LOW_BIT 0x01 +#define DATA_SNR_LOW_BIT 0x02 +#define DATA_RSSI_HIGH_BIT 0x04 +#define DATA_SNR_HIGH_BIT 0x08 +/** + * @brief This function computes the RSSI in received packet. + * + * @param priv A pointer to wlan_private structure + * @return n/a + */ +static void +wlan_check_subscribe_event(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int temp; + if (Adapter->subevent.EventsBitmap == 0) + return; + if ((Adapter->subevent.EventsBitmap & DATA_RSSI_LOW_BIT) || + (Adapter->subevent.EventsBitmap & DATA_RSSI_HIGH_BIT)) { + temp = + -CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, + Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); + if (Adapter->subevent.EventsBitmap & DATA_RSSI_LOW_BIT) { + if (temp > Adapter->subevent.Rssi_low.value) { + if (!Adapter->subevent.Rssi_low.Freq) { + Adapter->subevent.EventsBitmap &= ~DATA_RSSI_LOW_BIT; + send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW); + } else { + Adapter->subevent.Rssi_low_count++; + if (Adapter->subevent.Rssi_low_count >= + Adapter->subevent.Rssi_low.Freq) { + Adapter->subevent.Rssi_low_count = 0; + send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_LOW); + } + } + } else + Adapter->subevent.Rssi_low_count = 0; + } + if (Adapter->subevent.EventsBitmap & DATA_RSSI_HIGH_BIT) { + if (temp < Adapter->subevent.Rssi_high.value) { + if (!Adapter->subevent.Rssi_high.Freq) { + Adapter->subevent.EventsBitmap &= ~DATA_RSSI_HIGH_BIT; + send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_HIGH); + } else { + Adapter->subevent.Rssi_high_count++; + if (Adapter->subevent.Rssi_high_count >= + Adapter->subevent.Rssi_high.Freq) { + Adapter->subevent.Rssi_high_count = 0; + send_iwevcustom_event(priv, CUS_EVT_DATA_RSSI_HIGH); + } + } + } else + Adapter->subevent.Rssi_high_count = 0; + } + } + if ((Adapter->subevent.EventsBitmap & DATA_SNR_LOW_BIT) || + (Adapter->subevent.EventsBitmap & DATA_SNR_HIGH_BIT)) { + temp = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; + if (Adapter->subevent.EventsBitmap & DATA_SNR_LOW_BIT) { + if (temp < Adapter->subevent.Snr_low.value) { + if (!Adapter->subevent.Snr_low.Freq) { + send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW); + Adapter->subevent.EventsBitmap &= ~DATA_SNR_LOW_BIT; + } else { + Adapter->subevent.Snr_low_count++; + if (Adapter->subevent.Snr_low_count >= + Adapter->subevent.Snr_low.Freq) { + Adapter->subevent.Snr_low_count = 0; + send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_LOW); + } + } + } else + Adapter->subevent.Snr_low_count = 0; + } + if (Adapter->subevent.EventsBitmap & DATA_SNR_HIGH_BIT) { + if (temp > Adapter->subevent.Snr_high.value) { + if (!Adapter->subevent.Snr_high.Freq) { + Adapter->subevent.EventsBitmap &= ~DATA_SNR_HIGH_BIT; + send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH); + } else { + Adapter->subevent.Snr_high_count++; + if (Adapter->subevent.Snr_high_count >= + Adapter->subevent.Snr_high.Freq) { + Adapter->subevent.Snr_high_count = 0; + send_iwevcustom_event(priv, CUS_EVT_DATA_SNR_HIGH); + } + } + + } else + Adapter->subevent.Snr_high_count = 0; + } + } + return; +} /** * @brief This function computes the RSSI in received packet. @@ -138,27 +235,25 @@ * @param pRxPD A pointer to RxPD structure of received packet * @return n/a */ -static void wlan_compute_rssi(wlan_private *priv, RxPD *pRxPD) +static void +wlan_compute_rssi(wlan_private * priv, RxPD * pRxPD) { wlan_adapter *Adapter = priv->adapter; ENTER(); PRINTM(INFO, "RxPD: SNR = %d, NF = %d\n", pRxPD->SNR, pRxPD->NF); - PRINTM(INFO, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n", - Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, - Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); Adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = pRxPD->SNR; Adapter->NF[TYPE_RXPD][TYPE_NOAVG] = pRxPD->NF; wlan_save_rawSNRNF(priv , pRxPD); - Adapter->RxPDSNRAge = os_time_get(); + Adapter->RxPDAge = os_time_get(); Adapter->RxPDRate = pRxPD->RxRate; Adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getAvgSNR(priv) * AVG_SCALE; Adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getAvgNF(priv ) * AVG_SCALE; - PRINTM(INFO, "After computing SNR: SNR-avg = %d, NF-avg = %d\n", + PRINTM(INFO, "SNR-avg = %d, NF-avg = %d\n", Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); @@ -169,7 +264,7 @@ Adapter->RSSI[TYPE_RXPD][TYPE_AVG] = CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - + wlan_check_subscribe_event(priv); LEAVE(); } @@ -185,9 +280,9 @@ * @param skb A pointer to skb which includes the received packet * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int ProcessRxedPacket(wlan_private *priv, struct sk_buff *skb) +int +ProcessRxedPacket(wlan_private * priv, struct sk_buff *skb) { - wlan_adapter *Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; RxPacketHdr_t* pRxPkt; @@ -195,45 +290,29 @@ int hdrChop; EthII_Hdr_t* pEthHdr; - + u32 u32SkbLen = skb->len; const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; ENTER(); - if ( priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH ) - HEXDUMP("RX packet: ", skb->data, MIN(skb->len, 100)); - - if ( priv->adapter->linkmode == WLAN_LINKMODE_802_11 ) - return ProcessRxed_802_11_Packet(priv, skb); - - pRxPkt = (RxPacketHdr_t*)skb->data; - pRxPD = &pRxPkt->rx_pd; + pRxPD = (RxPD *) skb->data; + pRxPkt = (RxPacketHdr_t *) ((u8 *) pRxPD + pRxPD->PktOffset); - HEXDUMP("RX Data: Before chop RxPD", skb->data, MIN(skb->len, 100)); + DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, MAX_DATA_DUMP_LEN)); + endian_convert_RxPD(pRxPD); - if (skb->len < (ETH_HLEN + 8 + sizeof(RxPD))) { - PRINTM(INFO, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n"); + if (skb->len < (ETH_HLEN + 8 + pRxPD->PktOffset)) { + PRINTM(ERROR, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n"); priv->stats.rx_length_errors++; ret = WLAN_STATUS_SUCCESS; + kfree_skb(skb); goto done; } - /* - * Check RxPD status and update 802.3 stat, - */ - if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK)) { - PRINTM(INFO, "RX Error: frame received with bad status\n"); - printk("<1> RxPD Not OK\n"); - priv->stats.rx_errors++; - ret = WLAN_STATUS_SUCCESS; - goto done; - } - - - PRINTM(INFO, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n", - skb->len, sizeof(RxPD), skb->len - sizeof(RxPD)); + PRINTM(INFO, "RX Data: skb->len - pRxPD->PktOffset = %d - %d = %d\n", + skb->len, pRxPD->PktOffset, skb->len - pRxPD->PktOffset); HEXDUMP("RX Data: Dest", pRxPkt->eth803_hdr.dest_addr, sizeof(pRxPkt->eth803_hdr.dest_addr)); @@ -267,13 +346,13 @@ /* Chop off the RxPD + the excess memory from the 802.2/llc/snap header * that was removed */ - hdrChop = (u8*)pEthHdr - (u8*)pRxPkt; + hdrChop = (u8 *) pEthHdr - (u8 *) pRxPD; } else { HEXDUMP("RX Data: LLC/SNAP", (u8*)&pRxPkt->rfc1042_hdr, sizeof(pRxPkt->rfc1042_hdr)); /* Chop off the RxPD */ - hdrChop = (u8*)&pRxPkt->eth803_hdr - (u8*)pRxPkt; + hdrChop = (u8 *) & pRxPkt->eth803_hdr - (u8 *) pRxPD; } /* Chop off the leading header bytes so the skb points to the start of @@ -281,182 +360,22 @@ */ skb_pull(skb, hdrChop); - /* Take the data rate from the RxPD structure - * only if the rate is auto - */ - if (Adapter->Is_DataRate_Auto) { - Adapter->DataRate = index_to_data_rate(pRxPD->RxRate); - } - + u32SkbLen = skb->len; wlan_compute_rssi(priv, pRxPD); - PRINTM(INFO, "RX Data: Size of actual packet = %d\n", skb->len); if (os_upload_rx_packet(priv, skb)) { - PRINTM(INFO, "RX Error: os_upload_rx_packet" - " returns failure\n"); + PRINTM(ERROR, "RX Error: os_upload_rx_packet" " returns failure\n"); ret = WLAN_STATUS_FAILURE; goto done; } - priv->stats.rx_bytes += skb->len; + priv->stats.rx_bytes += u32SkbLen; priv->stats.rx_packets++; - ret = WLAN_STATUS_SUCCESS; -done: - LEAVE(); - - return (ret); -} - -/** - * @brief This function converts Tx/Rx rates from the Marvell WLAN format - * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) - * - * @param rate Input rate - * @return Output Rate (0 if invalid) - */ -u8 convert_mv_rate_to_radiotap(u8 rate) -{ - switch (rate) { - case 0: /* 1 Mbps */ return 2; - case 1: /* 2 Mbps */ return 4; - case 2: /* 5.5 Mbps */ return 11; - case 3: /* 11 Mbps */ return 22; - case 4: /* 6 Mbps */ return 12; - case 5: /* 9 Mbps */ return 18; - case 6: /* 12 Mbps */ return 24; - case 7: /* 18 Mbps */ return 36; - case 8: /* 24 Mbps */ return 48; - case 9: /* 36 Mbps */ return 72; - case 10: /* 48 Mbps */ return 96; - case 11: /* 54 Mbps */ return 108; - } - PRINTM(MSG, "Invalid Marvell WLAN rate (%i)\n", rate); - return 0; -} - -/** - * @brief This function processes a received 802.11 packet and forwards it - * to kernel/upper layer - * - * @param priv A pointer to wlan_private - * @param skb A pointer to skb which includes the received packet - * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE - */ -int ProcessRxed_802_11_Packet(wlan_private *priv, struct sk_buff *skb) -{ - wlan_adapter *Adapter = priv->adapter; - int ret = WLAN_STATUS_SUCCESS; - - Rx80211PacketHdr_t* pRxPkt; - RxPD* pRxPD; - RxRadiotapHdr_t radiotap_hdr; - RxRadiotapHdr_t *pradiotap_hdr; - - ENTER(); - - pRxPkt = (Rx80211PacketHdr_t*)skb->data; - pRxPD = &pRxPkt->rx_pd; - - // HEXDUMP("RX Data: Before chop RxPD", skb->data, MIN(skb->len, 100)); - - if (skb->len < (ETH_HLEN + 8 + sizeof(RxPD))) { - PRINTM(INFO, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n"); - priv->stats.rx_length_errors++; - ret = WLAN_STATUS_SUCCESS; - goto done; - } - - /* - * Check RxPD status and update 802.3 stat, - */ - if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK)) { - //PRINTM(INFO, "RX Error: frame received with bad status\n"); - priv->stats.rx_errors++; - } - - PRINTM(INFO, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n", - skb->len, sizeof(RxPD), skb->len - sizeof(RxPD)); - - /* create the exported radio header */ - switch (priv->adapter->radiomode) { - case WLAN_RADIOMODE_NONE: - /* no radio header */ - /* chop the RxPD */ - skb_pull(skb, sizeof(RxPD)); - break; - - case WLAN_RADIOMODE_RADIOTAP: - /* radiotap header */ - radiotap_hdr.hdr.it_version = 0; - /* XXX must check this value for pad */ - radiotap_hdr.hdr.it_pad = 0; - radiotap_hdr.hdr.it_len = sizeof(RxRadiotapHdr_t); - radiotap_hdr.hdr.it_present = RX_RADIOTAP_PRESENT; - /* unknown values */ - radiotap_hdr.flags = 0; - radiotap_hdr.chan_freq = 0; - radiotap_hdr.chan_flags = 0; - radiotap_hdr.antenna = 0; - /* known values */ - radiotap_hdr.rate = convert_mv_rate_to_radiotap(pRxPD->RxRate); - /* XXX must check no carryout */ - radiotap_hdr.antsignal = pRxPD->SNR + pRxPD->NF; - radiotap_hdr.rx_flags = 0; - if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK)) - radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS; - //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18); - - // HEXDUMP1("RX radiomode packet BEF: ", skb->data, MIN(skb->len, 100)); - - /* chop the RxPD */ - skb_pull(skb, sizeof(RxPD)); - - /* add space for the new radio header */ - if ( (skb_headroom(skb) < sizeof(RxRadiotapHdr_t)) && - pskb_expand_head(skb, sizeof(RxRadiotapHdr_t), 0, GFP_ATOMIC)) { - PRINTM(MSG, "%s: couldn't pskb_expand_head\n", __func__); - } - - - pradiotap_hdr = (RxRadiotapHdr_t *) skb_push(skb, sizeof(RxRadiotapHdr_t)); - memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(RxRadiotapHdr_t)); - //HEXDUMP1("RX radiomode packet AFT: ", skb->data, MIN(skb->len, 100)); - break; - - default: - /* unknown header */ - PRINTM(MSG, "Unknown radiomode (%i)\n", priv->adapter->radiomode); - /* don't export any header */ - /* chop the RxPD */ - skb_pull(skb, sizeof(RxPD)); - break; - } - - /* Take the data rate from the RxPD structure - * only if the rate is auto - */ - if (Adapter->Is_DataRate_Auto) { - Adapter->DataRate = index_to_data_rate(pRxPD->RxRate); - } - - wlan_compute_rssi(priv, pRxPD); - - PRINTM(INFO, "RX Data: Size of actual packet = %d\n", skb->len); - - if (os_upload_rx_packet(priv, skb)) { - PRINTM(INFO, "RX Error: os_upload_rx_packet returns failure\n"); - ret = WLAN_STATUS_FAILURE; - goto done; - } - - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; + PRINTM(DATA, "Data => kernel\n"); ret = WLAN_STATUS_SUCCESS; done: LEAVE(); - skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ - return (ret); } diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_scan.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_scan.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_scan.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_scan.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,6 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** @file wlan_scan.c * * @brief Functions implementing wlan scan IOCTL and firmware command APIs @@ -8,16 +5,13 @@ * IOCTL handlers as well as command preperation and response routines * for sending scan commands to the firmware. * - * @sa wlan_scan.h - * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -37,7 +31,6 @@ #include "include.h" - /******************************************************** Local Constants ********************************************************/ @@ -60,11 +53,15 @@ //! Memory needed to store a max number/size SSID TLV for a firmware scan #define SSID_TLV_MAX_SIZE (1 * sizeof(MrvlIEtypes_SsIdParamSet_t)) +//! WPS TLV MAX size is MAX IE size plus 2 bytes for u16 MRVL TLV extension +#define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2) + //! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max #define MAX_SCAN_CFG_ALLOC (sizeof(wlan_scan_cmd_config) \ + sizeof(MrvlIEtypes_NumProbes_t) \ + CHAN_TLV_MAX_SIZE \ - + SSID_TLV_MAX_SIZE) + + SSID_TLV_MAX_SIZE \ + + WPS_TLV_MAX_SIZE) //! The maximum number of channels the firmware can scan per command #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 @@ -77,13 +74,6 @@ */ #define MRVDRV_CHANNELS_PER_SCAN_CMD 4 -//! Scan time specified in the channel TLV for each channel for passive scans -#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100 - -//! Scan time specified in the channel TLV for each channel for active scans -#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 - - //! Macro to enable/disable SSID checking before storing a scan table #ifdef DISCARD_BAD_SSID #define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.Ssid) @@ -91,7 +81,6 @@ #define CHECK_SSID_IS_VALID(x) TRUE #endif - /******************************************************** Local Variables and Types ********************************************************/ @@ -99,23 +88,23 @@ /** * @brief Interally used to send a configured scan cmd between driver routines */ -typedef union { +typedef union +{ wlan_scan_cmd_config config; //!< Scan configuration (variable length) u8 configAllocBuf[MAX_SCAN_CFG_ALLOC]; //!< Max allocated block } wlan_scan_cmd_config_tlv; - - /** * @brief Check if a scanned network compatible with the driver settings * * WEP WPA WPA2 ad-hoc encrypt Network * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible * 0 0 0 0 NONE 0 0 0 yes No security - * 1 0 0 0 NONE 1 0 0 yes Static WEP * 0 1 0 0 x 1x 1 x yes WPA * 0 0 1 0 x 1x x 1 yes WPA2 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES + * + * 1 0 0 0 NONE 1 0 0 yes Static WEP * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP * * @@ -125,96 +114,118 @@ * * @return Index in ScanTable, or error code if negative */ -static int IsNetworkCompatible(wlan_adapter* Adapter, int index, int mode) +static int +IsNetworkCompatible(wlan_adapter * Adapter, int index, int mode) { + BSSDescriptor_t *pBSSDesc; + ENTER(); - if (Adapter->ScanTable[index].InfrastructureMode == mode) { + pBSSDesc = &Adapter->ScanTable[index]; + + /* Don't check for compatibility if roaming */ + if ((Adapter->MediaConnectStatus == WlanMediaStateConnected) + && (Adapter->InfrastructureMode == Wlan802_11Infrastructure) + && (pBSSDesc->InfrastructureMode == Wlan802_11Infrastructure)) { + LEAVE(); + return index; + } + + if (Adapter->wps.SessionEnable == TRUE) { + PRINTM(INFO, "Return success directly in WPS period\n"); + LEAVE(); + return index; + } + + if (pBSSDesc->InfrastructureMode == mode) { if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled && !Adapter->SecInfo.WPAEnabled && !Adapter->SecInfo.WPA2Enabled - && Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0] != WPA_IE - && Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0] != WPA2_IE + && pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE + && pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE + && !Adapter->AdhocAESEnabled && Adapter->SecInfo.EncryptionMode == CIPHER_NONE - && !Adapter->ScanTable[index].Privacy - ) { + && !pBSSDesc->Privacy) { /* no security */ LEAVE(); return index; - } - else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled + } else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled && !Adapter->SecInfo.WPAEnabled && !Adapter->SecInfo.WPA2Enabled - && Adapter->ScanTable[index].Privacy - ) { + && !Adapter->AdhocAESEnabled && pBSSDesc->Privacy) { /* static WEP enabled */ LEAVE(); return index; - } - else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled + } else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled && Adapter->SecInfo.WPAEnabled && !Adapter->SecInfo.WPA2Enabled - && (Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0] - == WPA_IE) + && (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE) + && !Adapter->AdhocAESEnabled /* Privacy bit may NOT be set in some APs like LinkSys WRT54G - && Adapter->ScanTable[index].Privacy */ + && pBSSDesc->Privacy */ ) { /* WPA enabled */ PRINTM(INFO, "IsNetworkCompatible() WPA: index=%d wpa_ie=%#x " "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x " "privacy=%#x\n", index, - Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0], - Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0], - (Adapter->SecInfo.WEPStatus==Wlan802_11WEPEnabled)?"e":"d", + pBSSDesc->wpaIE.VendHdr.ElementId, + pBSSDesc->rsnIE.IeeeHdr.ElementId, + (Adapter->SecInfo.WEPStatus == + Wlan802_11WEPEnabled) ? "e" : "d", (Adapter->SecInfo.WPAEnabled)?"e":"d", (Adapter->SecInfo.WPA2Enabled)?"e":"d", - Adapter->SecInfo.EncryptionMode, - Adapter->ScanTable[index].Privacy); + Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy); LEAVE(); return index; - } - else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled + } else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled && !Adapter->SecInfo.WPAEnabled && Adapter->SecInfo.WPA2Enabled - && (Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0] - == WPA2_IE) + && (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE) + && !Adapter->AdhocAESEnabled /* Privacy bit may NOT be set in some APs like LinkSys WRT54G - && Adapter->ScanTable[index].Privacy */ + && pBSSDesc->Privacy */ ) { /* WPA2 enabled */ PRINTM(INFO, "IsNetworkCompatible() WPA2: index=%d wpa_ie=%#x " "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x " "privacy=%#x\n", index, - Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0], - Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0], - (Adapter->SecInfo.WEPStatus==Wlan802_11WEPEnabled)?"e":"d", + pBSSDesc->wpaIE.VendHdr.ElementId, + pBSSDesc->rsnIE.IeeeHdr.ElementId, + (Adapter->SecInfo.WEPStatus == + Wlan802_11WEPEnabled) ? "e" : "d", (Adapter->SecInfo.WPAEnabled)?"e":"d", (Adapter->SecInfo.WPA2Enabled)?"e":"d", - Adapter->SecInfo.EncryptionMode, - Adapter->ScanTable[index].Privacy); + Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy); LEAVE(); return index; - } - else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled + } else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled && !Adapter->SecInfo.WPAEnabled && !Adapter->SecInfo.WPA2Enabled - && (Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0] - != WPA_IE) - && (Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0] - != WPA2_IE) + && (pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE) + && (pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE) + && Adapter->AdhocAESEnabled + && Adapter->SecInfo.EncryptionMode == CIPHER_NONE + && pBSSDesc->Privacy) { + /* Ad-hoc AES enabled */ + LEAVE(); + return index; + } else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled + && !Adapter->SecInfo.WPAEnabled + && !Adapter->SecInfo.WPA2Enabled + && (pBSSDesc->wpaIE.VendHdr.ElementId != WPA_IE) + && (pBSSDesc->rsnIE.IeeeHdr.ElementId != RSN_IE) + && !Adapter->AdhocAESEnabled && Adapter->SecInfo.EncryptionMode != CIPHER_NONE - && Adapter->ScanTable[index].Privacy - ) { + && pBSSDesc->Privacy) { /* dynamic WEP enabled */ PRINTM(INFO, "IsNetworkCompatible() dynamic WEP: index=%d " "wpa_ie=%#x wpa2_ie=%#x EncMode=%#x privacy=%#x\n", index, - Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0], - Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0], - Adapter->SecInfo.EncryptionMode, - Adapter->ScanTable[index].Privacy); + pBSSDesc->wpaIE.VendHdr.ElementId, + pBSSDesc->rsnIE.IeeeHdr.ElementId, + Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy); LEAVE(); return index; } @@ -223,13 +234,13 @@ PRINTM(INFO, "IsNetworkCompatible() FAILED: index=%d wpa_ie=%#x " "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", index, - Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0], - Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0], - (Adapter->SecInfo.WEPStatus==Wlan802_11WEPEnabled)?"e":"d", + pBSSDesc->wpaIE.VendHdr.ElementId, + pBSSDesc->rsnIE.IeeeHdr.ElementId, + (Adapter->SecInfo.WEPStatus == + Wlan802_11WEPEnabled) ? "e" : "d", (Adapter->SecInfo.WPAEnabled)?"e":"d", (Adapter->SecInfo.WPA2Enabled)?"e":"d", - Adapter->SecInfo.EncryptionMode, - Adapter->ScanTable[index].Privacy); + Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy); LEAVE(); return -ECONNREFUSED; } @@ -246,7 +257,8 @@ * * @return TRUE or FALSE */ -static BOOLEAN ssid_valid(WLAN_802_11_SSID* pSsid) +static BOOLEAN +ssid_valid(WLAN_802_11_SSID * pSsid) { int ssidIdx; @@ -259,13 +271,12 @@ return TRUE; } - /** * @brief Post process the scan table after a new scan command has completed * * Inspect each entry of the scan table and try to find an entry that * matches our current associated/joined network from the scan. If - * one is found, update the stored copy of the BssDescriptor for our + * one is found, update the stored copy of the BSSDescriptor for our * current network. * * Debug dump the current scan table contents if compiled accordingly. @@ -274,27 +285,26 @@ * * @return void */ -static void wlan_scan_process_results(wlan_private* priv) +static void +wlan_scan_process_results(wlan_private * priv) { wlan_adapter* Adapter = priv->adapter; - int foundCurrent; int i; + int foundCurrent; foundCurrent = FALSE; if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { - /* try to find the current BSSID in the new scan list */ - for (i = 0; i < Adapter->NumInScanTable; i++) { - if (!SSIDcmp(&Adapter->ScanTable[i].Ssid, - &Adapter->CurBssParams.ssid) && - !memcmp(Adapter->CurBssParams.bssid, - Adapter->ScanTable[i].MacAddress, - MRVDRV_ETH_ADDR_LEN)) { - foundCurrent = TRUE; - } - } + Adapter->CurBssParams.BSSDescriptor.pBeaconBuf = NULL; + Adapter->CurBssParams.BSSDescriptor.beaconBufSize = 0; + Adapter->CurBssParams.BSSDescriptor.beaconBufSizeMax = 0; + i = FindSSIDInList(Adapter, + &Adapter->CurBssParams.BSSDescriptor.Ssid, + Adapter->CurBssParams.BSSDescriptor.MacAddress, + Adapter->InfrastructureMode); - if (foundCurrent) { + if (i >= 0) { + PRINTM(INFO, "Found current ssid/bssid in list @ index #%d\n", i); /* Make a copy of current BSSID descriptor */ memcpy(&Adapter->CurBssParams.BSSDescriptor, &Adapter->ScanTable[i], @@ -334,7 +344,8 @@ * * @return void */ -static void wlan_scan_create_channel_list(wlan_private* priv, +static void +wlan_scan_create_channel_list(wlan_private * priv, ChanScanParamSet_t* scanChanList, BOOLEAN filteredScan) { @@ -366,23 +377,21 @@ /* clear the parsed_region_chan for the first scan */ memset(&Adapter->parsed_region_chan, 0x00, sizeof(Adapter->parsed_region_chan)); - } - else - { + } else { if (!Adapter->region_channel[rgnIdx].Valid) continue; scanRegion = &Adapter->region_channel[rgnIdx]; } for (nextChan = 0; - nextChan < scanRegion->NrCFP; - nextChan++, chanIdx++) { + nextChan < scanRegion->NrCFP; nextChan++, chanIdx++) { cfp = scanRegion->CFP + nextChan; if (wlan_get_state_11d(priv) == ENABLE_11D) { - scanType = wlan_get_scan_type_11d( - cfp->Channel, &Adapter->parsed_region_chan); + scanType = + wlan_get_scan_type_11d(cfp->Channel, + &Adapter->parsed_region_chan); } switch (scanRegion->Band) { @@ -395,24 +404,43 @@ if (scanType == HostCmd_SCAN_TYPE_PASSIVE) { scanChanList[chanIdx].MaxScanTime = - wlan_cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); + wlan_cpu_to_le16(Adapter->PassiveScanTime); scanChanList[chanIdx].ChanScanMode.PassiveScan = TRUE; } else { scanChanList[chanIdx].MaxScanTime = - wlan_cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); + wlan_cpu_to_le16(Adapter->ActiveScanTime); scanChanList[chanIdx].ChanScanMode.PassiveScan = FALSE; } scanChanList[chanIdx].ChanNumber = cfp->Channel; - if (filteredScan) - { + if (filteredScan) { + scanChanList[chanIdx].MaxScanTime = + wlan_cpu_to_le16(Adapter->SpecificScanTime); scanChanList[chanIdx].ChanScanMode.DisableChanFilt = TRUE; } } } } +static void +wlan_add_wps_probe_request_ie(wlan_private * priv, u8 ** ppTlvOut) +{ + wlan_adapter *Adapter = priv->adapter; + MrvlIEtypesHeader_t *tlv; + + if (Adapter->wps.wpsIe.VendHdr.Len) { + tlv = (MrvlIEtypesHeader_t *) * ppTlvOut; + tlv->Type = wlan_cpu_to_le16(TLV_TYPE_WPS_ENROLLEE_PROBE_REQ_TLV); + tlv->Len = wlan_cpu_to_le16(Adapter->wps.wpsIe.VendHdr.Len); + *ppTlvOut += sizeof(MrvlIEtypesHeader_t); + memcpy(*ppTlvOut, + Adapter->wps.wpsIe.VendHdr.Oui, + Adapter->wps.wpsIe.VendHdr.Len); + *ppTlvOut += (Adapter->wps.wpsIe.VendHdr.Len + + sizeof(MrvlIEtypesHeader_t)); + } +} /** * @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds @@ -453,8 +481,8 @@ * * @return void */ -static -void wlan_scan_setup_scan_config(wlan_private* priv, +static void +wlan_scan_setup_scan_config(wlan_private * priv, const wlan_ioctl_user_scan_cfg* pUserScanIn, wlan_scan_cmd_config* pScanCfgOut, MrvlIEtypes_ChanListParamSet_t** ppChanTlvOut, @@ -466,7 +494,6 @@ wlan_adapter* Adapter = priv->adapter; const u8 zeroMac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; MrvlIEtypes_NumProbes_t* pNumProbesTlv; - MrvlIEtypes_SsIdParamSet_t* pSsidTlv; u8* pTlvPos; u16 numProbes; u16 ssidLen; @@ -475,6 +502,10 @@ int scanDur; int channel; int radioType; + int ssidIdx; + BOOLEAN ssidFilter; + + MrvlIEtypes_WildCardSsIdParamSet_t *pWildCardSsidTlv; /* The tlvBufferLen is calculated for each scan command. The TLVs added * in this routine will be preserved since the routine that sends @@ -494,10 +525,10 @@ * BSSID or SSID is used, the number of channels in the scan command * will be increased to the absolute maximum */ - *pMaxChanPerScan = MRVDRV_CHANNELS_PER_SCAN_CMD; + *pMaxChanPerScan = MRVDRV_MAX_CHANNELS_PER_SCAN; - /* Initialize the scan as un-filtered by firmware, set to TRUE below if - * a SSID or BSSID filter is sent in the command + /* Initialize the scan as un-filtered; the flag is later set to + * TRUE below if a SSID or BSSID filter is sent in the command */ *pFilteredScan = FALSE; @@ -509,6 +540,12 @@ if (pUserScanIn) { + /* Default the ssidFilter flag to TRUE, set false under certain + * wildcard conditions and qualified by the existence of an SSID + * list before marking the scan as filtered + */ + ssidFilter = TRUE; + /* Set the bss type scan filter, use Adapter setting if unset */ pScanCfgOut->bssType = (pUserScanIn->bssType ? pUserScanIn->bssType : Adapter->ScanMode); @@ -525,14 +562,41 @@ pUserScanIn->specificBSSID, sizeof(pScanCfgOut->specificBSSID)); - ssidLen = strlen(pUserScanIn->specificSSID); + for (ssidIdx = 0; ((ssidIdx < NELEMENTS(pUserScanIn->ssidList)) + && (*pUserScanIn->ssidList[ssidIdx].ssid + || pUserScanIn->ssidList[ssidIdx].maxLen)); + ssidIdx++) { - if (ssidLen) { - pSsidTlv = (MrvlIEtypes_SsIdParamSet_t*)pScanCfgOut->tlvBuffer; - pSsidTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID); - pSsidTlv->Header.Len = wlan_cpu_to_le16(ssidLen); - memcpy(pSsidTlv->SsId, pUserScanIn->specificSSID, ssidLen); - pTlvPos += sizeof(pSsidTlv->Header) + ssidLen; + ssidLen = strlen(pUserScanIn->ssidList[ssidIdx].ssid) + 1; + + pWildCardSsidTlv = (MrvlIEtypes_WildCardSsIdParamSet_t *) pTlvPos; + pWildCardSsidTlv->Header.Type + = wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID); + pWildCardSsidTlv->Header.Len + = ssidLen + sizeof(pWildCardSsidTlv->MaxSsidLength); + pWildCardSsidTlv->MaxSsidLength + = pUserScanIn->ssidList[ssidIdx].maxLen; + + memcpy(pWildCardSsidTlv->SsId, + pUserScanIn->ssidList[ssidIdx].ssid, ssidLen); + + pTlvPos += (sizeof(pWildCardSsidTlv->Header) + + pWildCardSsidTlv->Header.Len); + + pWildCardSsidTlv->Header.Len + = wlan_cpu_to_le16(pWildCardSsidTlv->Header.Len); + + PRINTM(INFO, "Scan: ssidList[%d]: %s, %d\n", + ssidIdx, + pWildCardSsidTlv->SsId, pWildCardSsidTlv->MaxSsidLength); + + /* Empty wildcard ssid with a maxlen will match many or potentially + * all SSIDs (maxlen == 32), therefore do not treat the scan + * as filtered. + */ + if ((ssidLen == 0) && pWildCardSsidTlv->MaxSsidLength) { + ssidFilter = FALSE; + } } /* @@ -541,11 +605,11 @@ * scan results. That is not an issue with an SSID or BSSID * filter applied to the scan results in the firmware. */ - if (ssidLen || (memcmp(pScanCfgOut->specificBSSID, - &zeroMac, sizeof(zeroMac)) != 0)) { - *pMaxChanPerScan = MRVDRV_MAX_CHANNELS_PER_SCAN; + if ((ssidIdx && ssidFilter) + || memcmp(pScanCfgOut->specificBSSID, &zeroMac, sizeof(zeroMac))) { *pFilteredScan = TRUE; } + } else { pScanCfgOut->bssType = Adapter->ScanMode; numProbes = Adapter->ScanProbes; @@ -553,6 +617,9 @@ /* If the input config or adapter has the number of Probes set, add tlv */ if (numProbes) { + + PRINTM(INFO, "Scan: numProbes = %d\n", numProbes); + pNumProbesTlv = (MrvlIEtypes_NumProbes_t*)pTlvPos; pNumProbesTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_NUMPROBES); pNumProbesTlv->Header.Len = sizeof(pNumProbesTlv->NumProbes); @@ -560,10 +627,12 @@ pTlvPos += sizeof(pNumProbesTlv->Header) + pNumProbesTlv->Header.Len; - pNumProbesTlv->Header.Len = wlan_cpu_to_le16(pNumProbesTlv - ->Header.Len); + pNumProbesTlv->Header.Len = + wlan_cpu_to_le16(pNumProbesTlv->Header.Len); } + wlan_add_wps_probe_request_ie(priv, &pTlvPos); + /* * Set the output for the channel TLV to the address in the tlv buffer * past any TLVs that were added in this fuction (SSID, numProbes). @@ -598,19 +667,24 @@ scanDur = pUserScanIn->chanList[chanIdx].scanTime; } else { if (scanType == HostCmd_SCAN_TYPE_PASSIVE) { - scanDur = MRVDRV_PASSIVE_SCAN_CHAN_TIME; + scanDur = Adapter->PassiveScanTime; + } else if (*pFilteredScan) { + scanDur = Adapter->SpecificScanTime; } else { - scanDur = MRVDRV_ACTIVE_SCAN_CHAN_TIME; + scanDur = Adapter->ActiveScanTime; } } - (pScanChanList + chanIdx)->MinScanTime = wlan_cpu_to_le16(scanDur); - (pScanChanList + chanIdx)->MaxScanTime = wlan_cpu_to_le16(scanDur); + (pScanChanList + chanIdx)->MinScanTime = + wlan_cpu_to_le16(scanDur); + (pScanChanList + chanIdx)->MaxScanTime = + wlan_cpu_to_le16(scanDur); } /* Check if we are only scanning the current channel */ - if ((chanIdx == 1) && (pUserScanIn->chanList[0].chanNumber - == priv->adapter->CurBssParams.channel)) { + if ((chanIdx == 1) + && (pUserScanIn->chanList[0].chanNumber + == priv->adapter->CurBssParams.BSSDescriptor.Channel)) { *pScanCurrentOnly = TRUE; PRINTM(INFO, "Scan: Scanning current channel only"); } @@ -621,7 +695,6 @@ } } - /** * @brief Construct and send multiple scan config commands to the firmware * @@ -644,7 +717,8 @@ * * @return WLAN_STATUS_SUCCESS or error return otherwise */ -static int wlan_scan_channel_list(wlan_private* priv, +static int +wlan_scan_channel_list(wlan_private * priv, int maxChanPerScan, BOOLEAN filteredScan, wlan_scan_cmd_config* pScanCfgOut, @@ -656,6 +730,7 @@ u8 scanBand; int doneEarly; int tlvIdx; + int totalscantime; int ret; ENTER(); @@ -680,6 +755,7 @@ while (pTmpChan->ChanNumber) { tlvIdx = 0; + totalscantime = 0; pChanTlvOut->Header.Len = 0; scanBand = pTmpChan->RadioType; pStartChan = pTmpChan; @@ -702,8 +778,7 @@ /* Copy the current channel TLV to the command being prepared */ memcpy(pChanTlvOut->ChanScanParam + tlvIdx, - pTmpChan, - sizeof(pChanTlvOut->ChanScanParam)); + pTmpChan, sizeof(pChanTlvOut->ChanScanParam)); /* Increment the TLV header length by the size appended */ pChanTlvOut->Header.Len += sizeof(pChanTlvOut->ChanScanParam); @@ -724,6 +799,9 @@ /* Increment the index to the channel tlv we are constructing */ tlvIdx++; + /* Count the total scan time per command */ + totalscantime += pTmpChan->MaxScanTime; + doneEarly = FALSE; /* Stop the loop if the *current* channel is in the 1,6,11 set @@ -749,6 +827,16 @@ } } + /* The total scan time should be less than scan command timeout value */ + if (totalscantime > MRVDRV_MAX_TOTAL_SCAN_TIME) { + PRINTM(MSG, + "Total scan time %d ms is over limit (%d ms), scan skipped\n", + totalscantime, MRVDRV_MAX_TOTAL_SCAN_TIME); + ret = WLAN_STATUS_FAILURE; + break; + } + + pChanTlvOut->Header.Len = wlan_cpu_to_le16(pChanTlvOut->Header.Len); /* Send the scan command to the firmware with the specified cfg */ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SCAN, 0, @@ -765,7 +853,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Internal function used to start a scan based on an input config * @@ -779,7 +866,8 @@ * * @return WLAN_STATUS_SUCCESS or < 0 if error */ -static int wlan_scan_networks(wlan_private* priv, +static int +wlan_scan_networks(wlan_private * priv, const wlan_ioctl_user_scan_cfg* pUserScanIn) { wlan_adapter* Adapter = priv->adapter; @@ -792,6 +880,7 @@ BOOLEAN scanCurrentChanOnly; int maxChanPerScan; int ret; + BOOLEAN bBgScan; ENTER(); @@ -806,8 +895,7 @@ &pChanTlvOut, scanChanList, &maxChanPerScan, - &filteredScan, - &scanCurrentChanOnly); + &filteredScan, &scanCurrentChanOnly); if (pUserScanIn) { keepPreviousScan = pUserScanIn->keepPreviousScan; @@ -817,21 +905,27 @@ memset(Adapter->ScanTable, 0x00, sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST); Adapter->NumInScanTable = 0; + Adapter->pBeaconBufEnd = Adapter->beaconBuffer; } /* Keep the data path active if we are only scanning our current channel */ if (!scanCurrentChanOnly) { - os_stop_queue(priv); - os_carrier_off(priv); + PRINTM(INFO, "Scan: WMM Queue stop\n"); + priv->wlan_dev.netdev->watchdog_timeo = MRVDRV_SCAN_WATCHDOG_TIMEOUT; + /* If WMM queues are in use, only stop the internal data queues */ + wmm_stop_queue(priv); } + bBgScan = priv->adapter->bgScanConfig->Enable; + if (priv->adapter->bgScanConfig->Enable == TRUE) { + wlan_bg_scan_enable(priv, FALSE); + } ret = wlan_scan_channel_list(priv, maxChanPerScan, filteredScan, &scanCfgOut.config, - pChanTlvOut, - scanChanList); + pChanTlvOut, scanChanList); /* Process the resulting scan table: * - Remove any bad ssids @@ -839,7 +933,17 @@ */ wlan_scan_process_results(priv); + if (bBgScan == TRUE) { + wlan_bg_scan_enable(priv, TRUE); + } + PRINTM(INFO, "Scan: WMM Queue start\n"); + + priv->wlan_dev.netdev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; + + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + wmm_start_queue(priv); + } os_carrier_on(priv); os_start_queue(priv); @@ -847,63 +951,96 @@ return ret; } - /** * @brief Create a brief scan resp to relay basic BSS info to the app layer * - * When the beacon/probe response has not been buffered, use the fixed field + * When the beacon/probe response has not been buffered, use the saved BSS * information available to provide a minimum response for the application - * ioctl retrieval routines. + * ioctl retrieval routines. Include: + * - Timestamp + * - Beacon Period + * - Capabilities (including WMM Element if available) + * - SSID * * @param ppBuffer Output parameter: Buffer used to create basic scan rsp - * @param pBssDesc Pointer to a BSS entry in the scan table to create + * @param pBSSDesc Pointer to a BSS entry in the scan table to create * scan response from for delivery to the application layer * * @return void */ -static void wlan_scan_create_brief_scan_table(u8** ppBuffer, - BSSDescriptor_t* pBssDesc) +static void +wlan_scan_create_brief_table_entry(u8 ** ppBuffer, BSSDescriptor_t * pBSSDesc) { u8* pTmpBuf = *ppBuffer; u8 tmpSSIDHdr[2]; + u8 ieLen; - if (copy_to_user(pTmpBuf, pBssDesc->TimeStamp, sizeof(pBssDesc->TimeStamp))) { + if (copy_to_user(pTmpBuf, pBSSDesc->TimeStamp, + sizeof(pBSSDesc->TimeStamp))) { PRINTM(INFO, "Copy to user failed\n"); return; } - pTmpBuf += sizeof(pBssDesc->TimeStamp); + pTmpBuf += sizeof(pBSSDesc->TimeStamp); - if (copy_to_user(pTmpBuf, &pBssDesc->BeaconPeriod, - sizeof(pBssDesc->BeaconPeriod))) { + if (copy_to_user(pTmpBuf, &pBSSDesc->BeaconPeriod, + sizeof(pBSSDesc->BeaconPeriod))) { PRINTM(INFO, "Copy to user failed\n"); return; } - pTmpBuf += sizeof(pBssDesc->BeaconPeriod); + pTmpBuf += sizeof(pBSSDesc->BeaconPeriod); - if (copy_to_user(pTmpBuf, &pBssDesc->Cap, sizeof(pBssDesc->Cap))) { + if (copy_to_user(pTmpBuf, &pBSSDesc->Cap, sizeof(pBSSDesc->Cap))) { PRINTM(INFO, "Copy to user failed\n"); return; } - pTmpBuf += sizeof(pBssDesc->Cap); + pTmpBuf += sizeof(pBSSDesc->Cap); tmpSSIDHdr[0] = 0; /* Element ID for SSID is zero */ - tmpSSIDHdr[1] = pBssDesc->Ssid.SsidLength; + tmpSSIDHdr[1] = pBSSDesc->Ssid.SsidLength; if (copy_to_user(pTmpBuf, tmpSSIDHdr, sizeof(tmpSSIDHdr))) { PRINTM(INFO, "Copy to user failed\n"); return; } pTmpBuf += sizeof(tmpSSIDHdr); - if (copy_to_user(pTmpBuf, pBssDesc->Ssid.Ssid, - pBssDesc->Ssid.SsidLength)) { + if (copy_to_user(pTmpBuf, pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength)) { PRINTM(INFO, "Copy to user failed\n"); return; } - pTmpBuf += pBssDesc->Ssid.SsidLength; + pTmpBuf += pBSSDesc->Ssid.SsidLength; - *ppBuffer = pTmpBuf; + if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) { + ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->wmmIE.VendHdr.Len; + if (copy_to_user(pTmpBuf, &pBSSDesc->wmmIE, ieLen)) { + PRINTM(INFO, "Copy to user failed\n"); + return; + } + + pTmpBuf += ieLen; + } + + if (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE) { + ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->wpaIE.VendHdr.Len; + if (copy_to_user(pTmpBuf, &pBSSDesc->wpaIE, ieLen)) { + PRINTM(INFO, "Copy to user failed\n"); + return; + } + + pTmpBuf += ieLen; + } + + if (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE) { + ieLen = sizeof(IEEEtypes_Header_t) + pBSSDesc->rsnIE.IeeeHdr.Len; + if (copy_to_user(pTmpBuf, &pBSSDesc->rsnIE, ieLen)) { + PRINTM(INFO, "Copy to user failed\n"); + return; + } + + pTmpBuf += ieLen; } + *ppBuffer = pTmpBuf; +} /** * @brief Inspect the scan response buffer for pointers to expected TLVs @@ -914,14 +1051,14 @@ * * @param pTlv Pointer to the start of the TLV buffer to parse * @param tlvBufSize Size of the TLV buffer - * @param pTsfTlv Output parameter: Pointer to the TSF TLV if found + * @param ppTsfTlv Output parameter: Pointer to the TSF TLV if found * * @return void */ -static -void wlan_ret_802_11_scan_get_tlv_ptrs(MrvlIEtypes_Data_t* pTlv, +static void +wlan_ret_802_11_scan_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize, - MrvlIEtypes_TsfTimestamp_t** pTsfTlv) + MrvlIEtypes_TsfTimestamp_t ** ppTsfTlv) { MrvlIEtypes_Data_t* pCurrentTlv; int tlvBufLeft; @@ -930,7 +1067,7 @@ pCurrentTlv = pTlv; tlvBufLeft = tlvBufSize; - *pTsfTlv = NULL; + *ppTsfTlv = NULL; PRINTM(INFO, "SCAN_RESP: tlvBufSize = %d\n", tlvBufSize); HEXDUMP("SCAN_RESP: TLV Buf", (u8 *)pTlv, tlvBufSize); @@ -941,7 +1078,8 @@ switch (tlvType) { case TLV_TYPE_TSFTIMESTAMP: - *pTsfTlv = (MrvlIEtypes_TsfTimestamp_t*)pCurrentTlv; + PRINTM(INFO, "SCAN_RESP: TSF Timestamp TLV, len = %d\n", tlvLen); + *ppTsfTlv = (MrvlIEtypes_TsfTimestamp_t *) pCurrentTlv; break; default: @@ -955,7 +1093,6 @@ } /* while */ } - /** * @brief Interpret a BSS scan response returned from the firmware * @@ -967,9 +1104,9 @@ * * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int InterpretBSSDescriptionWithIE(BSSDescriptor_t* pBSSEntry, - u8** pBeaconInfo, - int* bytesLeft) +static int +InterpretBSSDescriptionWithIE(BSSDescriptor_t * pBSSEntry, + u8 ** pBeaconInfo, int *bytesLeft) { IEEEtypes_ElementId_e elemID; IEEEtypes_FhParamSet_t* pFH; @@ -981,16 +1118,18 @@ u8* pCurrentPtr; u8* pRate; u8 elemLen; + u16 totalIeLen; u8 bytesToCopy; u8 rateSize; u16 beaconSize; BOOLEAN foundDataRateIE; int bytesLeftForCurrentBeacon; + IEEEtypes_ERPInfo_t *pERPInfo; - PWPA_SUPPLICANT pwpa_supplicant; - PWPA_SUPPLICANT pwpa2_supplicant; - IE_WPA* pIe; - const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 }; + IEEEtypes_VendorSpecific_t *pVendorIe; + const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; + const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; + const u8 wps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 }; IEEEtypes_CountryInfoSet_t* pcountryinfo; @@ -1025,11 +1164,8 @@ bytesLeftForCurrentBeacon = beaconSize; - pwpa_supplicant = &pBSSEntry->wpa_supplicant; - pwpa2_supplicant = &pBSSEntry->wpa2_supplicant; - memcpy(pBSSEntry->MacAddress, pCurrentPtr, MRVDRV_ETH_ADDR_LEN); - PRINTM(INFO, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n", + PRINTM(INFO, "InterpretIE: AP MAC Addr-%02x:%02x:%02x:%02x:%02x:%02x\n", pBSSEntry->MacAddress[0], pBSSEntry->MacAddress[1], pBSSEntry->MacAddress[2], pBSSEntry->MacAddress[3], pBSSEntry->MacAddress[4], pBSSEntry->MacAddress[5]); @@ -1053,6 +1189,13 @@ pCurrentPtr += 1; bytesLeftForCurrentBeacon -= 1; + /* + * The RSSI is not part of the beacon/probe response. After we have + * advanced pCurrentPtr past the RSSI field, save the remaining + * data for use at the application layer + */ + pBSSEntry->pBeaconBuf = pCurrentPtr; + pBSSEntry->beaconBufSize = bytesLeftForCurrentBeacon; /* time stamp is 8 bytes long */ memcpy(fixedIE.Timestamp, pCurrentPtr, 8); @@ -1083,7 +1226,6 @@ HEXDUMP("InterpretIE: IE info", (u8 *)pCurrentPtr, bytesLeftForCurrentBeacon); - if (pCap->Privacy) { PRINTM(INFO, "InterpretIE: AP WEP enabled\n"); pBSSEntry->Privacy = Wlan802_11PrivFilter8021xWEP; @@ -1097,12 +1239,11 @@ pBSSEntry->InfrastructureMode = Wlan802_11Infrastructure; } - - /* process variable IE */ while (bytesLeftForCurrentBeacon >= 2) { elemID = (IEEEtypes_ElementId_e)(*((u8 *)pCurrentPtr)); elemLen = *((u8 *) pCurrentPtr + 1); + totalIeLen = elemLen + sizeof(IEEEtypes_Header_t); if (bytesLeftForCurrentBeacon < elemLen) { PRINTM(INFO, "InterpretIE: Error in processing IE, " @@ -1116,12 +1257,14 @@ case SSID: pBSSEntry->Ssid.SsidLength = elemLen; memcpy(pBSSEntry->Ssid.Ssid, (pCurrentPtr + 2), elemLen); - PRINTM(INFO, "Ssid: %32s", pBSSEntry->Ssid.Ssid); + PRINTM(INFO, "InterpretIE: Ssid: %-32s\n", pBSSEntry->Ssid.Ssid); break; case SUPPORTED_RATES: - memcpy(pBSSEntry->DataRates, (pCurrentPtr + 2), elemLen); - memmove(pBSSEntry->SupportedRates, (pCurrentPtr + 2), elemLen); + memcpy(pBSSEntry->DataRates, pCurrentPtr + 2, elemLen); + memcpy(pBSSEntry->SupportedRates, pCurrentPtr + 2, elemLen); + HEXDUMP("InterpretIE: SupportedRates:", + pBSSEntry->SupportedRates, elemLen); rateSize = elemLen; foundDataRateIE = TRUE; break; @@ -1134,11 +1277,11 @@ case FH_PARAM_SET: pFH = (IEEEtypes_FhParamSet_t *)pCurrentPtr; pBSSEntry->NetworkTypeInUse = Wlan802_11FH; - memmove(&pBSSEntry->PhyParamSet.FhParamSet, pFH, + memcpy(&pBSSEntry->PhyParamSet.FhParamSet, pFH, sizeof(IEEEtypes_FhParamSet_t)); pBSSEntry->PhyParamSet.FhParamSet.DwellTime - = wlan_le16_to_cpu(pBSSEntry->PhyParamSet - .FhParamSet.DwellTime); + = + wlan_le16_to_cpu(pBSSEntry->PhyParamSet.FhParamSet.DwellTime); break; case DS_PARAM_SET: @@ -1153,7 +1296,6 @@ case CF_PARAM_SET: pCF = (IEEEtypes_CfParamSet_t *)pCurrentPtr; - memcpy(&pBSSEntry->SsParamSet.CfParamSet, pCF, sizeof(IEEEtypes_CfParamSet_t)); break; @@ -1161,13 +1303,8 @@ case IBSS_PARAM_SET: pIbss = (IEEEtypes_IbssParamSet_t *)pCurrentPtr; pBSSEntry->ATIMWindow = wlan_le32_to_cpu(pIbss->AtimWindow); - - memmove(&pBSSEntry->SsParamSet.IbssParamSet, pIbss, + memcpy(&pBSSEntry->SsParamSet.IbssParamSet, pIbss, sizeof(IEEEtypes_IbssParamSet_t)); - - pBSSEntry->SsParamSet.IbssParamSet.AtimWindow - = wlan_le16_to_cpu(pBSSEntry->SsParamSet - .IbssParamSet.AtimWindow); break; /* Handle Country Info IE */ @@ -1178,20 +1315,20 @@ || pcountryinfo->Len > 254 ) { PRINTM(INFO, "InterpretIE: 11D- Err " "CountryInfo len =%d min=%d max=254\n", - pcountryinfo->Len, - sizeof(pcountryinfo->CountryCode) ); + pcountryinfo->Len, sizeof(pcountryinfo->CountryCode)); LEAVE(); return WLAN_STATUS_FAILURE; } memcpy(&pBSSEntry->CountryInfo, - pcountryinfo, - pcountryinfo->Len + 2); + pcountryinfo, pcountryinfo->Len + 2); HEXDUMP("InterpretIE: 11D- CountryInfo:", - (u8 *)pcountryinfo, - (u32)(pcountryinfo->Len + 2)); + (u8 *) pcountryinfo, (u32) (pcountryinfo->Len + 2)); + break; + case ERP_INFO: + pERPInfo = (IEEEtypes_ERPInfo_t *) pCurrentPtr; + pBSSEntry->ERPFlags = pERPInfo->ERPFlags; break; - case EXTENDED_SUPPORTED_RATES: /* * only process extended supported rate @@ -1208,44 +1345,76 @@ pRate = (u8 *)pBSSEntry->DataRates; pRate += rateSize; - memmove(pRate,(pCurrentPtr +2), bytesToCopy); + memcpy(pRate, pCurrentPtr + 2, bytesToCopy); pRate = (u8 *)pBSSEntry->SupportedRates; - pRate += rateSize; - memmove(pRate,(pCurrentPtr +2), bytesToCopy); + memcpy(pRate, pCurrentPtr + 2, bytesToCopy); } + HEXDUMP("InterpretIE: ExtSupportedRates:", + pBSSEntry->SupportedRates, elemLen + rateSize); break; case VENDOR_SPECIFIC_221: -#define IE_ID_LEN_FIELDS_BYTES 2 - pIe = (IE_WPA *) pCurrentPtr; + pVendorIe = (IEEEtypes_VendorSpecific_t *) pCurrentPtr; + + if ((!memcmp + (pVendorIe->VendHdr.Oui, wpa_oui, + sizeof(pVendorIe->VendHdr.Oui))) + && (pVendorIe->VendHdr.OuiType == wpa_oui[3])) { + pBSSEntry->wpaIE.VendHdr.Len + = (MIN(totalIeLen, sizeof(pBSSEntry->wpaIE)) + - sizeof(IEEEtypes_Header_t)); + + memcpy(&pBSSEntry->wpaIE, + pCurrentPtr, + (pBSSEntry->wpaIE.VendHdr.Len + + sizeof(IEEEtypes_Header_t))); - if (!memcmp(pIe->oui, oui01, sizeof(oui01))) { - pwpa_supplicant->Wpa_ie_len - = MIN(elemLen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pwpa_supplicant->Wpa_ie)); - memcpy(pwpa_supplicant->Wpa_ie, - pCurrentPtr, pwpa_supplicant->Wpa_ie_len); HEXDUMP("InterpretIE: Resp WPA_IE", - pwpa_supplicant->Wpa_ie, elemLen); + (u8 *) & pBSSEntry->wpaIE, + (pBSSEntry->wpaIE.VendHdr.Len + + sizeof(IEEEtypes_Header_t))); + } else + if ((!memcmp + (pVendorIe->VendHdr.Oui, wmm_oui, + sizeof(pVendorIe->VendHdr.Oui))) + && (pVendorIe->VendHdr.OuiType == wmm_oui[3])) { + if (totalIeLen == sizeof(IEEEtypes_WmmParameter_t) + || totalIeLen == sizeof(IEEEtypes_WmmInfo_t)) { + + /* Only accept and copy the WMM IE if it matches + * the size expected for the WMM Info IE or the + * WMM Parameter IE. + */ + memcpy((u8 *) & pBSSEntry->wmmIE, pCurrentPtr, + totalIeLen); + HEXDUMP("InterpretIE: Resp WMM_IE", + (u8 *) & pBSSEntry->wmmIE, totalIeLen); + } + } else + if ((!memcmp + (pVendorIe->VendHdr.Oui, wps_oui, + sizeof(pVendorIe->VendHdr.Oui))) + && (pVendorIe->VendHdr.OuiType == wps_oui[3])) { + memcpy((u8 *) & pBSSEntry->wpsIE, pCurrentPtr, totalIeLen); + HEXDUMP("InterpretIE: Resp WPS_IE", + (u8 *) & pBSSEntry->wpsIE, totalIeLen); } break; - case WPA2_IE: - pIe = (IE_WPA *)pCurrentPtr; - pwpa2_supplicant->Wpa_ie_len - = MIN(elemLen + IE_ID_LEN_FIELDS_BYTES, - sizeof(pwpa2_supplicant->Wpa_ie)); - memcpy(pwpa2_supplicant->Wpa_ie, - pCurrentPtr, pwpa2_supplicant->Wpa_ie_len); + case RSN_IE: + pBSSEntry->rsnIE.IeeeHdr.Len + = (MIN(totalIeLen, sizeof(pBSSEntry->rsnIE)) + - sizeof(IEEEtypes_Header_t)); - HEXDUMP("InterpretIE: Resp WPA2_IE", - pwpa2_supplicant->Wpa_ie, elemLen); - break; - case TIM: - break; + memcpy(&pBSSEntry->rsnIE, + pCurrentPtr, + pBSSEntry->rsnIE.IeeeHdr.Len + sizeof(IEEEtypes_Header_t)); - case CHALLENGE_TEXT: + HEXDUMP("InterpretIE: Resp RSN_IE", + (u8 *) & pBSSEntry->rsnIE, + pBSSEntry->rsnIE.IeeeHdr.Len + + sizeof(IEEEtypes_Header_t)); break; } @@ -1259,7 +1428,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Compare two SSIDs * @@ -1268,7 +1436,8 @@ * * @return 0--ssid is same, otherwise is different */ -int SSIDcmp(WLAN_802_11_SSID* ssid1, WLAN_802_11_SSID* ssid2) +int +SSIDcmp(WLAN_802_11_SSID * ssid1, WLAN_802_11_SSID * ssid2) { if (!ssid1 || !ssid2) return -1; @@ -1279,7 +1448,6 @@ return memcmp(ssid1->Ssid, ssid2->Ssid, ssid1->SsidLength); } - /** * @brief This function finds a specific compatible BSSID in the scan list * @@ -1289,7 +1457,8 @@ * * @return index in BSSID list, or error return code (< 0) */ -int FindBSSIDInList(wlan_adapter* Adapter, u8* bssid, int mode) +int +FindBSSIDInList(wlan_adapter * Adapter, u8 * bssid, int mode) { int ret = -ENETUNREACH; int i; @@ -1319,6 +1488,12 @@ } } + if (ret >= 0) { + if (find_cfp_by_band_and_channel + (Adapter, 0, Adapter->ScanTable[ret].Channel) == NULL) { + ret = -ENETUNREACH; + } + } return ret; } @@ -1332,35 +1507,40 @@ * * @return index in BSSID list */ -int FindSSIDInList(wlan_adapter* Adapter, - WLAN_802_11_SSID* ssid, u8* bssid, int mode) +int +FindSSIDInList(wlan_adapter * Adapter, WLAN_802_11_SSID * ssid, + u8 * bssid, int mode) { int net = -ENETUNREACH; u8 bestrssi = 0; - int i; - int j; + int i, j; PRINTM(INFO, "Num of Entries in Table = %d\n", Adapter->NumInScanTable); - for (i = 0; i < Adapter->NumInScanTable; i++) { - if (!SSIDcmp(&Adapter->ScanTable[i].Ssid, ssid) && - (!bssid || - !memcmp(Adapter->ScanTable[i]. - MacAddress, bssid, ETH_ALEN))) { + /* Loop through the table until the maximum is reached or until a match + * is found based on the bssid field comparison + */ + for (i = 0; + i < Adapter->NumInScanTable && (bssid == NULL || (bssid && net < 0)); + i++) { + + if (!SSIDcmp(&Adapter->ScanTable[i].Ssid, ssid) && ((bssid == NULL) + || + !memcmp(Adapter-> + ScanTable + [i]. + MacAddress, + bssid, + ETH_ALEN))) + { switch (mode) { case Wlan802_11Infrastructure : case Wlan802_11IBSS : j = IsNetworkCompatible(Adapter, i, mode); if (j >= 0) { - if (bssid) { - return i; - } - - if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) - > bestrssi) { - bestrssi = - SCAN_RSSI(Adapter->ScanTable[i].Rssi); + if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) { + bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi); net = i; } } else { @@ -1371,17 +1551,24 @@ break; case Wlan802_11AutoUnknown : default : - if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) - > bestrssi) { - bestrssi = - SCAN_RSSI(Adapter->ScanTable[i].Rssi); + /* Do not check compatibility if the mode requested is + * AutoUnknown. Allows generic find to work without + * verifying against the Adapter security settings + */ + if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) { + bestrssi = SCAN_RSSI(Adapter->ScanTable[i].Rssi); net = i; } break; } } } - + if (net >= 0) { + if (find_cfp_by_band_and_channel + (Adapter, 0, Adapter->ScanTable[net].Channel) == NULL) { + net = -ENETUNREACH; + } + } return net; } @@ -1395,7 +1582,8 @@ * * @return index in BSSID list */ -int FindBestSSIDInList(wlan_adapter* Adapter) +int +FindBestSSIDInList(wlan_adapter * Adapter) { int mode = Adapter->InfrastructureMode; int bestnet = -ENETUNREACH; @@ -1431,7 +1619,6 @@ return bestnet; } - /** * @brief Find the AP with specific ssid in the scan list * @@ -1440,7 +1627,8 @@ * * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -int FindBestNetworkSsid(wlan_private* priv, WLAN_802_11_SSID* pSSID) +int +FindBestNetworkSsid(wlan_private * priv, WLAN_802_11_SSID * pSSID) { wlan_adapter* Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; @@ -1468,8 +1656,7 @@ HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP, - OID_802_11_INFRASTRUCTURE_MODE, - NULL); + OID_802_11_INFRASTRUCTURE_MODE, NULL); if (ret) { LEAVE(); @@ -1487,28 +1674,134 @@ } /** - * @brief Convert radio type scan paramter to a band config used in join cmd + * @brief Delete a specific indexed entry from the scan table. * - * @param scanBand Scan parameter indicating the band used for a channel - * in a scan command. + * Delete the scan table entry indexed by tableIdx. Compact the remaining + * entries and adjust any buffering of beacon/probe response data + * if needed. * - * @return Band type conversion of scanBand used in join/assoc cmds + * @param priv A pointer to wlan_private structure + * @param tableIdx Scan table entry index to delete from the table * + * @return void + * + * @pre tableIdx must be an index to a valid entry */ -u8 wlan_scan_radio_to_band(u8 scanBand) +static void +wlan_scan_delete_table_entry(wlan_private * priv, int tableIdx) { - u8 retBand = BAND_G; + wlan_adapter *Adapter = priv->adapter; + int delIdx; + uint beaconBufAdj; + u8 *pBeaconBuf; - switch (scanBand) { - case HostCmd_SCAN_RADIO_TYPE_BG: - default: - retBand = BAND_G; - break; + /* Shift the saved beacon buffer data for the scan table back over the + * entry being removed. Update the end of buffer pointer. Save the + * deleted buffer allocation size for pointer adjustments for entries + * compacted after the deleted index. + */ + beaconBufAdj = Adapter->ScanTable[tableIdx].beaconBufSizeMax; + + PRINTM(INFO, "Scan: Delete Entry %d, beacon buffer removal = %d bytes\n", + tableIdx, beaconBufAdj); + + /* Check if the table entry had storage allocated for its beacon */ + if (beaconBufAdj) { + pBeaconBuf = Adapter->ScanTable[tableIdx].pBeaconBuf; + + /* Remove the entry's buffer space, decrement the table end pointer + * by the amount we are removing + */ + Adapter->pBeaconBufEnd -= beaconBufAdj; + + PRINTM(INFO, + "Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n", + tableIdx, + pBeaconBuf, + pBeaconBuf + beaconBufAdj, + Adapter->pBeaconBufEnd - pBeaconBuf); + + /* Compact data storage. Copy all data after the deleted entry's + * end address (pBeaconBuf + beaconBufAdj) back to the original + * start address (pBeaconBuf). + * + * Scan table entries affected by the move will have their entry + * pointer adjusted below. + * + * Use memmove since the dest/src memory regions overlap. + */ + memmove(pBeaconBuf, + pBeaconBuf + beaconBufAdj, + Adapter->pBeaconBufEnd - pBeaconBuf); } - return retBand; + PRINTM(INFO, "Scan: Delete Entry %d, NumInScanTable = %d\n", + tableIdx, Adapter->NumInScanTable); + + /* Shift all of the entries after the tableIdx back by one, compacting + * the table and removing the requested entry + */ + for (delIdx = tableIdx; (delIdx + 1) < Adapter->NumInScanTable; delIdx++) { + /* Copy the next entry over this one */ + memcpy(Adapter->ScanTable + delIdx, + Adapter->ScanTable + delIdx + 1, sizeof(BSSDescriptor_t)); + + /* Adjust this entry's pointer to its beacon buffer based on the + * removed/compacted entry from the deleted index. Don't decrement + * if the buffer pointer is NULL (no data stored for this entry). + */ + if (Adapter->ScanTable[delIdx].pBeaconBuf) { + Adapter->ScanTable[delIdx].pBeaconBuf -= beaconBufAdj; + } } + /* The last entry is invalid now that it has been deleted or moved back */ + memset(Adapter->ScanTable + Adapter->NumInScanTable - 1, + 0x00, sizeof(BSSDescriptor_t)); + + Adapter->NumInScanTable--; +} + +/** + * @brief Delete all occurrences of a given SSID from the scan table + * + * Iterate through the scan table and delete all entries that match a given + * SSID. Compact the remaining scan table entries. + * + * @param priv A pointer to wlan_private structure + * @param pDelSSID Pointer to an SSID struct to use in deleting all + * matching SSIDs from the scan table + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + * + */ +static int +wlan_scan_delete_ssid_table_entry(wlan_private * priv, + WLAN_802_11_SSID * pDelSSID) +{ + int tableIdx; + int retval = WLAN_STATUS_FAILURE; + + ENTER(); + + PRINTM(INFO, "Scan: Delete Ssid Entry: %-32s\n", pDelSSID->Ssid); + + /* If the requested SSID is found in the table, delete it. Then keep + * searching the table for multiple entires for the SSID until no + * more are found + */ + while ((tableIdx = FindSSIDInList(priv->adapter, + pDelSSID, + NULL, Wlan802_11AutoUnknown)) >= 0) { + PRINTM(INFO, "Scan: Delete Ssid Entry: Found Idx = %d\n", tableIdx); + retval = WLAN_STATUS_SUCCESS; + wlan_scan_delete_table_entry(priv, tableIdx); + } + + LEAVE(); + + return retval; +} /** * @brief Scan Network @@ -1520,27 +1813,55 @@ * * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_scan(struct net_device* dev, struct iw_request_info* info, +int +wlan_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_param* vwrq, char* extra) { wlan_private* priv = dev->priv; wlan_adapter* Adapter = priv->adapter; union iwreq_data wrqu; - +#if WIRELESS_EXT >= 18 + struct iw_scan_req *req; + struct iw_point *dwrq = (struct iw_point *) vwrq; + wlan_ioctl_user_scan_cfg scanCfg; +#endif ENTER(); - + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } #ifdef REASSOCIATION if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->ReassocSem)) { - PRINTM(FATAL, "Acquire semaphore error, wlan_set_scan\n"); + PRINTM(ERROR, "Acquire semaphore error, wlan_set_scan\n"); return -EBUSY; } #endif +#if WIRELESS_EXT >= 18 + if ((dwrq->flags & IW_SCAN_THIS_ESSID) && + (dwrq->length == sizeof(struct iw_scan_req))) { + req = (struct iw_scan_req *) extra; + if (req->essid_len <= WLAN_MAX_SSID_LENGTH) { + memset(&scanCfg, 0x00, sizeof(scanCfg)); + memcpy(scanCfg.ssidList[0].ssid, (u8 *) req->essid, + req->essid_len); + if (!wlan_scan_networks(priv, &scanCfg)) { + memset(&wrqu, 0, sizeof(union iwreq_data)); + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, + NULL); + } + } + } else { +#endif if (!wlan_scan_networks(priv, NULL)) { memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL); + wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, + NULL); + } +#if WIRELESS_EXT >= 18 } +#endif #ifdef REASSOCIATION OS_REL_SEMAPHORE(&Adapter->ReassocSem); @@ -1553,19 +1874,16 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Send a scan command for all available channels filtered on a spec * * @param priv A pointer to wlan_private structure * @param pRequestedSSID A pointer to AP's ssid - * @param keepPreviousScan Flag used to save/clear scan table before scan * * @return WLAN_STATUS_SUCCESS-success, otherwise fail */ -int SendSpecificSSIDScan(wlan_private* priv, - WLAN_802_11_SSID* pRequestedSSID, - BOOLEAN keepPreviousScan) +int +SendSpecificSSIDScan(wlan_private * priv, WLAN_802_11_SSID * pRequestedSSID) { wlan_adapter* Adapter = priv->adapter; wlan_ioctl_user_scan_cfg scanCfg; @@ -1576,11 +1894,13 @@ return WLAN_STATUS_FAILURE; } + wlan_scan_delete_ssid_table_entry(priv, pRequestedSSID); + memset(&scanCfg, 0x00, sizeof(scanCfg)); - memcpy(scanCfg.specificSSID, pRequestedSSID->Ssid, - pRequestedSSID->SsidLength); - scanCfg.keepPreviousScan = keepPreviousScan; + memcpy(scanCfg.ssidList[0].ssid, + pRequestedSSID->Ssid, pRequestedSSID->SsidLength); + scanCfg.keepPreviousScan = TRUE; wlan_scan_networks(priv, &scanCfg); @@ -1591,19 +1911,16 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief scan an AP with specific BSSID * * @param priv A pointer to wlan_private structure * @param bssid A pointer to AP's bssid - * @param keepPreviousScan Flag used to save/clear scan table before scan * * @return WLAN_STATUS_SUCCESS-success, otherwise fail */ -int SendSpecificBSSIDScan(wlan_private* priv, - u8* bssid, - BOOLEAN keepPreviousScan) +int +SendSpecificBSSIDScan(wlan_private * priv, u8 * bssid) { wlan_ioctl_user_scan_cfg scanCfg; @@ -1615,7 +1932,7 @@ memset(&scanCfg, 0x00, sizeof(scanCfg)); memcpy(scanCfg.specificBSSID, bssid, sizeof(scanCfg.specificBSSID)); - scanCfg.keepPreviousScan = keepPreviousScan; + scanCfg.keepPreviousScan = TRUE; wlan_scan_networks(priv, &scanCfg); @@ -1623,7 +1940,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Retrieve the scan table entries via wireless tools IOCTL call * @@ -1634,7 +1950,8 @@ * * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_get_scan(struct net_device* dev, struct iw_request_info* info, +int +wlan_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point* dwrq, char* extra) { wlan_private* priv = dev->priv; @@ -1652,12 +1969,19 @@ u8 buf[16+256*2]; u8* ptr; + u8 *pRawData; ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } - if (Adapter->MediaConnectStatus == WlanMediaStateConnected) - PRINTM(INFO, "Current Ssid: %32s\n", Adapter->CurBssParams.ssid.Ssid); + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + PRINTM(INFO, "Current Ssid: %-32s\n", + Adapter->CurBssParams.BSSDescriptor.Ssid.Ssid); + } PRINTM(INFO, "Scan: Get: NumInScanTable = %d\n", Adapter->NumInScanTable); @@ -1677,9 +2001,11 @@ pScanTable = &Adapter->ScanTable[i]; - PRINTM(INFO, "i=%d Ssid: %32s\n", i, pScanTable->Ssid.Ssid); + PRINTM(INFO, "i=%d Ssid: %-32s\n", i, pScanTable->Ssid.Ssid); - cfp = find_cfp_by_band_and_channel(Adapter, 0, pScanTable->Channel); + cfp = + find_cfp_by_band_and_channel(Adapter, 0, + (u16) pScanTable->Channel); if (!cfp) { PRINTM(INFO, "Invalid channel number %d\n", pScanTable->Channel); continue; @@ -1693,8 +2019,7 @@ iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, - &Adapter->ScanTable[i].MacAddress, - ETH_ALEN); + &Adapter->ScanTable[i].MacAddress, ETH_ALEN); iwe.len = IW_EV_ADDR_LEN; current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len); @@ -1707,10 +2032,11 @@ } iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; + iwe.u.essid.flags = (i + 1) & IW_ENCODE_INDEX; iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - Adapter->ScanTable[i].Ssid.Ssid); + (s8 *) Adapter->ScanTable[i].Ssid. + Ssid); //Add mode iwe.cmd = SIOCGIWMODE; @@ -1735,11 +2061,13 @@ iwe.u.qual.noise = CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]); } if ((Adapter->InfrastructureMode == Wlan802_11IBSS) && - !SSIDcmp(&Adapter->CurBssParams.ssid, &Adapter->ScanTable[i].Ssid) + !SSIDcmp(&Adapter->CurBssParams.BSSDescriptor.Ssid, + &Adapter->ScanTable[i].Ssid) && Adapter->AdhocCreate) { ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RSSI, - 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, + NULL); if (ret) { LEAVE(); @@ -1762,8 +2090,7 @@ } iwe.u.data.length = 0; iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; - current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, - Adapter->ScanTable->Ssid.Ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); current_val = current_ev + IW_EV_LCP_LEN; @@ -1786,12 +2113,14 @@ iwe.u.bitrate.value = (Adapter->ScanTable[i].SupportedRates[j] & 0x7f) * 500000; iwe.len = IW_EV_PARAM_LEN; - current_ev = iwe_stream_add_value(current_ev, current_val, end_buf, - &iwe, iwe.len); + current_ev = + iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, + iwe.len); } if ((Adapter->ScanTable[i].InfrastructureMode == Wlan802_11IBSS) && - !SSIDcmp(&Adapter->CurBssParams.ssid, &Adapter->ScanTable[i].Ssid) + !SSIDcmp(&Adapter->CurBssParams.BSSDescriptor.Ssid, + &Adapter->ScanTable[i].Ssid) && Adapter->AdhocCreate) { iwe.u.bitrate.value = 22 * 500000; } @@ -1802,16 +2131,23 @@ /* Add new value to event */ current_val = current_ev + IW_EV_LCP_LEN; - if (Adapter->ScanTable[i].wpa2_supplicant.Wpa_ie[0] == WPA2_IE) { + if (Adapter->ScanTable[i].rsnIE.IeeeHdr.ElementId == RSN_IE) { + pRawData = (u8 *) & Adapter->ScanTable[i].rsnIE; memset(&iwe, 0, sizeof(iwe)); memset(buf, 0, sizeof(buf)); ptr = buf; +#if WIRELESS_EXT >= 18 + memcpy(buf, pRawData, + Adapter->ScanTable[i].rsnIE.IeeeHdr.Len + 2); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = Adapter->ScanTable[i].rsnIE.IeeeHdr.Len + 2; +#else ptr += sprintf(ptr, "rsn_ie="); for (j = 0; - j < Adapter->ScanTable[i].wpa2_supplicant.Wpa_ie_len; j++) { - ptr += sprintf(ptr, "%02x", (Adapter->ScanTable[i] - .wpa2_supplicant.Wpa_ie[j])); + j < (Adapter->ScanTable[i].rsnIE.IeeeHdr.Len + + sizeof(IEEEtypes_Header_t)); j++) { + ptr += sprintf(ptr, "%02x", *(pRawData + j)); } iwe.u.data.length = strlen(buf); @@ -1819,19 +2155,27 @@ PRINTM(INFO, "WPA2 BUF: %s \n",buf); iwe.cmd = IWEVCUSTOM; +#endif iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); } - if (Adapter->ScanTable[i].wpa_supplicant.Wpa_ie[0] == WPA_IE) { + if (Adapter->ScanTable[i].wpaIE.VendHdr.ElementId == WPA_IE) { + pRawData = (u8 *) & Adapter->ScanTable[i].wpaIE; memset(&iwe, 0, sizeof(iwe)); memset(buf, 0, sizeof(buf)); ptr = buf; +#if WIRELESS_EXT >= 18 + memcpy(buf, pRawData, + Adapter->ScanTable[i].wpaIE.VendHdr.Len + 2); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = Adapter->ScanTable[i].wpaIE.VendHdr.Len + 2; +#else ptr += sprintf(ptr, "wpa_ie="); for (j = 0; - j < Adapter->ScanTable[i].wpa_supplicant.Wpa_ie_len; j++) { - ptr += sprintf(ptr, "%02x", - Adapter->ScanTable[i].wpa_supplicant.Wpa_ie[j]); + j < (Adapter->ScanTable[i].wpaIE.VendHdr.Len + + sizeof(IEEEtypes_Header_t)); j++) { + ptr += sprintf(ptr, "%02x", *(pRawData + j)); } iwe.u.data.length = strlen(buf); @@ -1839,10 +2183,31 @@ PRINTM(INFO, "WPA BUF: %s \n",buf); iwe.cmd = IWEVCUSTOM; +#endif iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); } + if (Adapter->ScanTable[i].wpsIE.VendHdr.ElementId == WPS_IE) { + pRawData = (u8 *) & Adapter->ScanTable[i].wpsIE; + memset(&iwe, 0, sizeof(iwe)); + memset(buf, 0, sizeof(buf)); + ptr = buf; + ptr += sprintf(ptr, "wps_ie="); + for (j = 0; + j < (Adapter->ScanTable[i].wpsIE.VendHdr.Len + + sizeof(IEEEtypes_Header_t)); j++) { + ptr += sprintf(ptr, "%02x", *(pRawData + j)); + } + iwe.u.data.length = strlen(buf); + + PRINTM(INFO, "iwe.u.data.length %d\n", iwe.u.data.length); + PRINTM(INFO, "WPS BUF: %s \n", buf); + + iwe.cmd = IWEVCUSTOM; + iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); + } #if WIRELESS_EXT > 14 @@ -1880,106 +2245,91 @@ } /** - * @brief Retrieve the scan response/beacon table + * @brief Create a wlan_ioctl_get_scan_table_entry for a given BSS + * Descriptor for inclusion in the ioctl response to the user space + * application. + * * * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure + * @param pBSSDesc Pointer to a BSS entry in the scan table to form + * scan response from for delivery to the application layer + * @param ppBuffer Output parameter: Buffer used to output scan return struct + * @param pSpaceLeft Output parameter: Number of bytes available in the + * response buffer. * - * @return WLAN_STATUS_SUCCESS --success, otherwise fail + * @return WLAN_STATUS_SUCCESS, or < 0 with IOCTL error code */ -int wlan_get_scan_table_ioctl(wlan_private* priv, struct iwreq* wrq) +static int +wlan_get_scan_table_ret_entry(wlan_private * priv, + BSSDescriptor_t * pBSSDesc, + u8 ** ppBuffer, int *pSpaceLeft) { wlan_adapter* Adapter; - BSSDescriptor_t* pBssInfo; - wlan_ioctl_get_scan_table_info* pRspInfo; wlan_ioctl_get_scan_table_entry* pRspEntry; wlan_ioctl_get_scan_table_entry tmpRspEntry; - int retcode; - int retlen; int spaceNeeded; - int spaceLeft; u8* pCurrent; - u8* pBufferEnd; - u32 scanStart; - u32 numScansDone; int variableSize; const int fixedSize = (sizeof(tmpRspEntry.fixedFieldLength) + sizeof(tmpRspEntry.fixedFields) + sizeof(tmpRspEntry.bssInfoLength)); - retlen = 0; - - if (copy_from_user(&scanStart, - wrq->u.data.pointer, sizeof(scanStart)) != 0) { - /* copy_from_user failed */ - PRINTM(INFO, "GetScanTable: copy from user failed\n"); - retcode = -EFAULT; - - } else { - - PRINTM(INFO, "GetScanTable: scanStart req = %d\n", scanStart); - PRINTM(INFO, "GetScanTable: length avail = %d\n", wrq->u.data.length); + ENTER(); Adapter = priv->adapter; + pCurrent = *ppBuffer; - numScansDone = 0; - - pRspInfo = (wlan_ioctl_get_scan_table_info*)wrq->u.data.pointer; - pCurrent = pRspInfo->scan_table_entry_buffer; - pBufferEnd = wrq->u.data.pointer + wrq->u.data.length - 1; - spaceLeft = pBufferEnd - pCurrent; - - while (spaceLeft && - scanStart + numScansDone < Adapter->NumInScanTable) { - - pBssInfo = &Adapter->ScanTable[scanStart + numScansDone]; - - /* No beacon stored, variable size set to 0 */ - variableSize = 0; + /* The variable size returned is the stored beacon size */ + variableSize = pBSSDesc->beaconBufSize; /* If we stored a beacon and its size was zero, set the variable * size return value to the size of the brief scan response - * wlan_scan_create_brief_scan_table creates. Also used if + * wlan_scan_create_brief_table_entry creates. Also used if * we are not configured to store beacons in the first place */ - if (variableSize == 0) - { - variableSize = pBssInfo->Ssid.SsidLength + 2; - variableSize += (sizeof(pBssInfo->BeaconPeriod) - + sizeof(pBssInfo->TimeStamp) - + sizeof(pBssInfo->Cap)); + if (variableSize == 0) { + variableSize = pBSSDesc->Ssid.SsidLength + 2; + variableSize += (sizeof(pBSSDesc->BeaconPeriod) + + sizeof(pBSSDesc->TimeStamp) + + sizeof(pBSSDesc->Cap)); + if (pBSSDesc->wmmIE.VendHdr.ElementId == WMM_IE) { + variableSize += (sizeof(IEEEtypes_Header_t) + + pBSSDesc->wmmIE.VendHdr.Len); + } + + if (pBSSDesc->wpaIE.VendHdr.ElementId == WPA_IE) { + variableSize += (sizeof(IEEEtypes_Header_t) + + pBSSDesc->wpaIE.VendHdr.Len); + } + + if (pBSSDesc->rsnIE.IeeeHdr.ElementId == RSN_IE) { + variableSize += (sizeof(IEEEtypes_Header_t) + + pBSSDesc->rsnIE.IeeeHdr.Len); + } } spaceNeeded = fixedSize + variableSize; - spaceLeft = pBufferEnd - pCurrent; - PRINTM(INFO, "GetScanTable: bss[%d], need(%d), left(%d)\n", - scanStart + numScansDone, - spaceNeeded, - spaceLeft); + PRINTM(INFO, "GetScanTable: need(%d), left(%d)\n", + spaceNeeded, *pSpaceLeft); - if (spaceNeeded >= spaceLeft) { - spaceLeft = 0; - } else { + if (spaceNeeded >= *pSpaceLeft) { + *pSpaceLeft = 0; + LEAVE(); + return -E2BIG; + } - PRINTM(INFO, "GetScanTable: bss[%d] = " - "%02x:%02x:%02x:%02x:%02x:%02x\n", - scanStart + numScansDone, - pBssInfo->MacAddress[0], pBssInfo->MacAddress[1], - pBssInfo->MacAddress[2], pBssInfo->MacAddress[3], - pBssInfo->MacAddress[4], pBssInfo->MacAddress[5]); + *pSpaceLeft -= spaceNeeded; - tmpRspEntry.fixedFieldLength - = sizeof(pRspEntry->fixedFields); + tmpRspEntry.fixedFieldLength = sizeof(pRspEntry->fixedFields); memcpy(tmpRspEntry.fixedFields.bssid, - pBssInfo->MacAddress, - sizeof(pRspEntry->fixedFields.bssid)); + pBSSDesc->MacAddress, sizeof(pRspEntry->fixedFields.bssid)); - tmpRspEntry.fixedFields.rssi = pBssInfo->Rssi; - tmpRspEntry.fixedFields.channel = pBssInfo->Channel; - tmpRspEntry.fixedFields.networkTSF = pBssInfo->networkTSF; + tmpRspEntry.fixedFields.rssi = pBSSDesc->Rssi; + tmpRspEntry.fixedFields.channel = pBSSDesc->Channel; + tmpRspEntry.fixedFields.networkTSF = pBSSDesc->networkTSF; tmpRspEntry.bssInfoLength = variableSize; /* @@ -1987,30 +2337,151 @@ */ if (copy_to_user(pCurrent, &tmpRspEntry, fixedSize)) { PRINTM(INFO, "Copy to user failed\n"); + LEAVE(); return -EFAULT; } pCurrent += fixedSize; - wlan_scan_create_brief_scan_table(&pCurrent, pBssInfo); + if (pBSSDesc->pBeaconBuf) { + /* + * Copy variable length elements to user space + */ + if (copy_to_user(pCurrent, pBSSDesc->pBeaconBuf, + pBSSDesc->beaconBufSize)) { + PRINTM(INFO, "Copy to user failed\n"); + LEAVE(); + return -EFAULT; + } - numScansDone++; + pCurrent += pBSSDesc->beaconBufSize; + } else { + wlan_scan_create_brief_table_entry(&pCurrent, pBSSDesc); + } - } /* else */ + *ppBuffer = pCurrent; - } /* while (spaceLeft && ... ) */ + LEAVE(); - pRspInfo->scanNumber = numScansDone; - retlen = pCurrent - (u8*)wrq->u.data.pointer; + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Retrieve the scan response/beacon table + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_get_scan_table_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter; + BSSDescriptor_t *pBSSDesc; + wlan_ioctl_get_scan_table_info *pRspInfo; + int retcode; + int retlen; + int spaceLeft; + u8 *pCurrent; + u8 *pBufferEnd; + u32 scanStart; + u32 numScansDone; + numScansDone = 0; retcode = WLAN_STATUS_SUCCESS; + Adapter = priv->adapter; + + if (copy_from_user(&scanStart, + wrq->u.data.pointer, sizeof(scanStart)) != 0) { + /* copy_from_user failed */ + PRINTM(INFO, "GetScanTable: copy from user failed\n"); + return -EFAULT; + } + + pRspInfo = (wlan_ioctl_get_scan_table_info *) wrq->u.data.pointer; + pCurrent = pRspInfo->scan_table_entry_buffer; + pBufferEnd = wrq->u.data.pointer + wrq->u.data.length - 1; + spaceLeft = pBufferEnd - pCurrent; + + PRINTM(INFO, "GetScanTable: scanStart req = %d\n", scanStart); + PRINTM(INFO, "GetScanTable: length avail = %d\n", wrq->u.data.length); + + if (scanStart == 0) { + PRINTM(INFO, "GetScanTable: get current BSS Descriptor\n"); + + /* Use to get current association saved descriptor */ + pBSSDesc = &Adapter->CurBssParams.BSSDescriptor; + + retcode = wlan_get_scan_table_ret_entry(priv, + pBSSDesc, + &pCurrent, &spaceLeft); + + if (retcode == WLAN_STATUS_SUCCESS) { + numScansDone = 1; } + } else { + scanStart--; + + while (spaceLeft + && (scanStart + numScansDone < Adapter->NumInScanTable) + && (retcode == WLAN_STATUS_SUCCESS)) { + + pBSSDesc = &Adapter->ScanTable[scanStart + numScansDone]; + + PRINTM(INFO, "GetScanTable: get current BSS Descriptor [%d]\n", + scanStart + numScansDone); + + retcode = wlan_get_scan_table_ret_entry(priv, + pBSSDesc, + &pCurrent, &spaceLeft); + + if (retcode == WLAN_STATUS_SUCCESS) { + numScansDone++; + } + } + } + + pRspInfo->scanNumber = numScansDone; + retlen = pCurrent - (u8 *) wrq->u.data.pointer; + wrq->u.data.length = retlen; - return retcode; + /* Return retcode (EFAULT or E2BIG) in the case where no scan results were + * successfully encoded. + */ + return (numScansDone ? WLAN_STATUS_SUCCESS : retcode); } +/** + * @brief Update the scan entry TSF timestamps to reflect a new association + * + * @param priv A pointer to wlan_private structure + * @param pNewBssDesc A pointer to the newly associated AP's scan table entry + * + * @return void + */ +void +wlan_scan_update_tsf_timestamps(wlan_private * priv, + BSSDescriptor_t * pNewBssDesc) +{ + wlan_adapter *Adapter = priv->adapter; + int tableIdx; + u64 newTsfBase; + s64 tsfDelta; + + memcpy(&newTsfBase, pNewBssDesc->TimeStamp, sizeof(newTsfBase)); + + tsfDelta = newTsfBase - pNewBssDesc->networkTSF; + + PRINTM(INFO, "TSF: Update TSF timestamps, 0x%016llx -> 0x%016llx\n", + pNewBssDesc->networkTSF, newTsfBase); + + for (tableIdx = 0; tableIdx < Adapter->NumInScanTable; tableIdx++) { + Adapter->ScanTable[tableIdx].networkTSF += tsfDelta; + } +} /** * @brief Private IOCTL entry to perform an app configured immediate scan @@ -2021,12 +2492,22 @@ * * @return 0 if successful; IOCTL error code otherwise */ -int wlan_set_user_scan_ioctl(wlan_private* priv, struct iwreq* wrq) +int +wlan_set_user_scan_ioctl(wlan_private * priv, struct iwreq *wrq) { wlan_ioctl_user_scan_cfg scanReq; int retcode; union iwreq_data wrqu; +#ifdef REASSOCIATION + if (OS_ACQ_SEMAPHORE_BLOCK(&priv->adapter->ReassocSem)) { + PRINTM(ERROR, "Acquire semaphore error, wlan_extscan_ioctl\n"); + return -EBUSY; + } +#endif + + memset(&scanReq, 0x00, sizeof(scanReq)); + if (copy_from_user(&scanReq, wrq->u.data.pointer, MIN(wrq->u.data.length, sizeof(scanReq))) != 0) { @@ -2041,10 +2522,13 @@ wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL); } +#ifdef REASSOCIATION + OS_REL_SEMAPHORE(&priv->adapter->ReassocSem); +#endif + return retcode; } - /** * @brief Prepare a scan command to be sent to the firmware * @@ -2065,9 +2549,9 @@ * * @sa wlan_scan_create_channel_list */ -int wlan_cmd_802_11_scan(wlan_private* priv, - HostCmd_DS_COMMAND* cmd, - void* pdata_buf) +int +wlan_cmd_802_11_scan(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *pdata_buf) { HostCmd_DS_802_11_SCAN* pScan = &cmd->params.scan; wlan_scan_cmd_config* pScanCfg; @@ -2086,15 +2570,236 @@ /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ cmd->Size = wlan_cpu_to_le16(sizeof(pScan->BSSType) + sizeof(pScan->BSSID) - + pScanCfg->tlvBufferLen - + S_DS_GEN); + + pScanCfg->tlvBufferLen + S_DS_GEN); - PRINTM(INFO, "SCAN_CMD: Command=%x, Size=%x, SeqNum=%x\n", - cmd->Command, cmd->Size, cmd->SeqNum); LEAVE(); return WLAN_STATUS_SUCCESS; } +/** + * @brief Store a beacon or probe response for a BSS returned in the scan + * + * Store a new scan response or an update for a previous scan response. New + * entries need to verify that they do not exceed the total amount of + * memory allocated for the table. + + * Replacement entries need to take into consideration the amount of space + * currently allocated for the beacon/probe response and adjust the entry + * as needed. + * + * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved + * for an entry in case it is a beacon since a probe response for the + * network will by larger per the standard. This helps to reduce the + * amount of memory copying to fit a new probe response into an entry + * already occupied by a network's previously stored beacon. + * + * @param priv A pointer to wlan_private structure + * @param beaconIdx Index in the scan table to store this entry; may be + * replacing an older duplicate entry for this BSS + * @param numInTable Number of entries currently in the table + * @param pNewBeacon Pointer to the new beacon/probe response to save + * + * @return void + */ +void +wlan_ret_802_11_scan_store_beacon(wlan_private * priv, + int beaconIdx, + int numInTable, + BSSDescriptor_t * pNewBeacon) +{ + wlan_adapter *Adapter = priv->adapter; + u8 *pBcnStore; + int newBcnSize; + int oldBcnSize; + int bcnSpace; + int adjIdx; + + if (Adapter->ScanTable[beaconIdx].pBeaconBuf != NULL) { + + newBcnSize = pNewBeacon->beaconBufSize; + oldBcnSize = Adapter->ScanTable[beaconIdx].beaconBufSize; + bcnSpace = Adapter->ScanTable[beaconIdx].beaconBufSizeMax; + pBcnStore = Adapter->ScanTable[beaconIdx].pBeaconBuf; + + /* Set the max to be the same as current entry unless changed below */ + pNewBeacon->beaconBufSizeMax = bcnSpace; + + if (newBcnSize == oldBcnSize) { + /* + * Beacon is the same size as the previous entry. + * Replace the previous contents with the scan result + */ + memcpy(pBcnStore, + pNewBeacon->pBeaconBuf, pNewBeacon->beaconBufSize); + + } else if (newBcnSize <= bcnSpace) { + /* + * New beacon size will fit in the amount of space + * we have previously allocated for it + */ + + /* Copy the new beacon buffer entry over the old one */ + memcpy(pBcnStore, pNewBeacon->pBeaconBuf, newBcnSize); + + /* If the old beacon size was less than the maximum + * we had alloted for the entry, and the new entry + * is even smaller, reset the max size to the old beacon + * entry and compress the storage space (leaving a new + * pad space of (oldBcnSize - newBcnSize). + */ + if (oldBcnSize < bcnSpace && newBcnSize != bcnSpace) { + /* + * Old Beacon size is smaller than the alloted storage size. + * Shrink the alloted storage space. + */ + PRINTM(INFO, "AppControl: Smaller Duplicate Beacon (%d), " + "old = %d, new = %d, space = %d, left = %d\n", + beaconIdx, oldBcnSize, newBcnSize, bcnSpace, + (sizeof(Adapter->beaconBuffer) - + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer))); + + /* memmove (since the memory overlaps) the data + * after the beacon we just stored to the end of + * the current beacon. This cleans up any unused + * space the old larger beacon was using in the buffer + */ + memmove(pBcnStore + oldBcnSize, + pBcnStore + bcnSpace, + Adapter->pBeaconBufEnd - (pBcnStore + bcnSpace)); + + /* Decrement the end pointer by the difference between + * the old larger size and the new smaller size since + * we are using less space due to the new beacon being + * smaller + */ + Adapter->pBeaconBufEnd -= (bcnSpace - oldBcnSize); + + /* Set the maximum storage size to the old beacon size */ + pNewBeacon->beaconBufSizeMax = oldBcnSize; + + /* Adjust beacon buffer pointers that are past the current */ + for (adjIdx = 0; adjIdx < numInTable; adjIdx++) { + if (Adapter->ScanTable[adjIdx].pBeaconBuf > pBcnStore) { + Adapter->ScanTable[adjIdx].pBeaconBuf + -= (bcnSpace - oldBcnSize); + } + } + } + } else if (Adapter->pBeaconBufEnd + (newBcnSize - bcnSpace) + < (Adapter->beaconBuffer + sizeof(Adapter->beaconBuffer))) { + /* + * Beacon is larger than space previously allocated (bcnSpace) + * and there is enough space left in the beaconBuffer to store + * the additional data + */ + PRINTM(INFO, "AppControl: Larger Duplicate Beacon (%d), " + "old = %d, new = %d, space = %d, left = %d\n", + beaconIdx, oldBcnSize, newBcnSize, bcnSpace, + (sizeof(Adapter->beaconBuffer) - + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer))); + + /* memmove (since the memory overlaps) the data + * after the beacon we just stored to the end of + * the current beacon. This moves the data for + * the beacons after this further in memory to + * make space for the new larger beacon we are + * about to copy in. + */ + memmove(pBcnStore + newBcnSize, + pBcnStore + bcnSpace, + Adapter->pBeaconBufEnd - (pBcnStore + bcnSpace)); + + /* Copy the new beacon buffer entry over the old one */ + memcpy(pBcnStore, pNewBeacon->pBeaconBuf, newBcnSize); + + /* Move the beacon end pointer by the amount of new + * beacon data we are adding + */ + Adapter->pBeaconBufEnd += (newBcnSize - bcnSpace); + + /* This entry is bigger than the alloted max space + * previously reserved. Increase the max space to + * be equal to the new beacon size + */ + pNewBeacon->beaconBufSizeMax = newBcnSize; + + /* Adjust beacon buffer pointers that are past the current */ + for (adjIdx = 0; adjIdx < numInTable; adjIdx++) { + if (Adapter->ScanTable[adjIdx].pBeaconBuf > pBcnStore) { + Adapter->ScanTable[adjIdx].pBeaconBuf + += (newBcnSize - bcnSpace); + } + } + } else { + /* + * Beacon is larger than the previously allocated space, but + * there is not enough free space to store the additional data + */ + PRINTM(INFO, + "AppControl: Failed: Larger Duplicate Beacon (%d)," + " old = %d, new = %d, space = %d, left = %d\n", + beaconIdx, oldBcnSize, newBcnSize, bcnSpace, + (sizeof(Adapter->beaconBuffer) - + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer))); + + /* Storage failure, keep old beacon intact */ + pNewBeacon->beaconBufSize = oldBcnSize; + } + + /* Point the new entry to its permanent storage space */ + pNewBeacon->pBeaconBuf = pBcnStore; + + } else { + /* No existing beacon data exists for this entry, check to see + * if we can fit it in the remaining space + */ + if (Adapter->pBeaconBufEnd + pNewBeacon->beaconBufSize + + SCAN_BEACON_ENTRY_PAD < (Adapter->beaconBuffer + + sizeof(Adapter->beaconBuffer))) { + + /* Copy the beacon buffer data from the local entry to the + * adapter dev struct buffer space used to store the raw + * beacon data for each entry in the scan table + */ + memcpy(Adapter->pBeaconBufEnd, pNewBeacon->pBeaconBuf, + pNewBeacon->beaconBufSize); + + /* Update the beacon ptr to point to the table save area */ + pNewBeacon->pBeaconBuf = Adapter->pBeaconBufEnd; + pNewBeacon->beaconBufSizeMax = (pNewBeacon->beaconBufSize + + SCAN_BEACON_ENTRY_PAD); + + /* Increment the end pointer by the size reserved */ + Adapter->pBeaconBufEnd += pNewBeacon->beaconBufSizeMax; + + PRINTM(INFO, "AppControl: Beacon[%02d] sz=%03d," + " used = %04d, left = %04d\n", + beaconIdx, + pNewBeacon->beaconBufSize, + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer), + (sizeof(Adapter->beaconBuffer) - + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer))); + } else { + /* + * No space for new beacon + */ + PRINTM(INFO, "AppControl: No space beacon (%d): " + "%02x:%02x:%02x:%02x:%02x:%02x; sz=%03d, left=%03d\n", + beaconIdx, + pNewBeacon->MacAddress[0], pNewBeacon->MacAddress[1], + pNewBeacon->MacAddress[2], pNewBeacon->MacAddress[3], + pNewBeacon->MacAddress[4], pNewBeacon->MacAddress[5], + pNewBeacon->beaconBufSize, + (sizeof(Adapter->beaconBuffer) - + (Adapter->pBeaconBufEnd - Adapter->beaconBuffer))); + + /* Storage failure; clear storage records for this bcn */ + pNewBeacon->pBeaconBuf = NULL; + pNewBeacon->beaconBufSize = 0; + pNewBeacon->beaconBufSizeMax = 0; + } + } +} /** * @brief This function handles the command response of scan @@ -2120,7 +2825,8 @@ * * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_ret_802_11_scan(wlan_private* priv, HostCmd_DS_COMMAND* resp) +int +wlan_ret_802_11_scan(wlan_private * priv, HostCmd_DS_COMMAND * resp) { wlan_adapter* Adapter = priv->adapter; HostCmd_DS_802_11_SCAN_RSP* pScan; @@ -2135,10 +2841,16 @@ int idx; int tlvBufSize; u64 tsfVal; + BOOLEAN bgScanResp; ENTER(); + bgScanResp = (resp->Command == HostCmd_RET_802_11_BG_SCAN_QUERY); + if (bgScanResp) { + pScan = &resp->params.bgscanqueryresp.scanresp; + } else { pScan = &resp->params.scanresp; + } if (pScan->NumberOfSets > MRVDRV_MAX_BSSID_LIST) { PRINTM(INFO, "SCAN_RESP: Invalid number of AP returned (%d)!!\n", @@ -2150,8 +2862,9 @@ bytesLeft = wlan_le16_to_cpu(pScan->BSSDescriptSize); PRINTM(INFO, "SCAN_RESP: BSSDescriptSize %d\n", bytesLeft); - scanRespSize = wlan_le16_to_cpu(resp->Size); - PRINTM(INFO, "SCAN_RESP: returned %d AP before parsing\n", + scanRespSize = resp->Size; + + PRINTM(CMND, "SCAN_RESP: returned %d APs before parsing\n", pScan->NumberOfSets); numInTable = Adapter->NumInScanTable; @@ -2162,8 +2875,7 @@ * BSS Descriptions (BSSDescriptSize as bytesLef) and the command * response header (S_DS_GEN) */ - tlvBufSize = scanRespSize - (bytesLeft - + sizeof(pScan->BSSDescriptSize) + tlvBufSize = scanRespSize - (bytesLeft + sizeof(pScan->BSSDescriptSize) + sizeof(pScan->NumberOfSets) + S_DS_GEN); @@ -2231,8 +2943,16 @@ } /* - * If the TSF TLV was appended to the scan results, save the - * this entries TSF value in the networkTSF field. The + * Save the beacon/probe response returned for later application + * retrieval. Duplicate beacon/probe responses are updated if + * possible + */ + wlan_ret_802_11_scan_store_beacon(priv, + bssIdx, + numInTable, &newBssEntry); + /* + * If the TSF TLV was appended to the scan results, save + * this entry's TSF value in the networkTSF field. The * networkTSF is the firmware's TSF value at the time the * beacon or probe response was received. */ @@ -2241,15 +2961,12 @@ tsfVal = wlan_le64_to_cpu(tsfVal); memcpy(&newBssEntry.networkTSF, - &tsfVal, - sizeof(newBssEntry.networkTSF)); + &tsfVal, sizeof(newBssEntry.networkTSF)); } - /* Copy the locally created newBssEntry to the scan table */ memcpy(&Adapter->ScanTable[bssIdx], - &newBssEntry, - sizeof(Adapter->ScanTable[bssIdx])); + &newBssEntry, sizeof(Adapter->ScanTable[bssIdx])); } else { @@ -2259,7 +2976,7 @@ } } - PRINTM(INFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", + PRINTM(CMND, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", pScan->NumberOfSets, numInTable - Adapter->NumInScanTable, numInTable); @@ -2278,26 +2995,223 @@ * * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_extscan_ioctl(wlan_private* priv, struct ifreq* req) +int +wlan_extscan_ioctl(wlan_private * priv, struct ifreq *req) { + wlan_adapter *Adapter = priv->adapter; WLAN_802_11_SSID Ext_Scan_SSID; + wlan_ioctl_user_scan_cfg scanCfg; union iwreq_data wrqu; ENTER(); - if (copy_from_user(&Ext_Scan_SSID, req->ifr_data, - sizeof(Ext_Scan_SSID))) { + if (copy_from_user(&Ext_Scan_SSID, req->ifr_data, sizeof(Ext_Scan_SSID))) { PRINTM(INFO, "copy of SSID for ext scan from user failed \n"); LEAVE(); return -EFAULT; } - SendSpecificSSIDScan(priv, &Ext_Scan_SSID, TRUE); +#ifdef REASSOCIATION + if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->ReassocSem)) { + PRINTM(ERROR, "Acquire semaphore error, wlan_extscan_ioctl\n"); + return -EBUSY; + } +#endif + + memset(&scanCfg, 0x00, sizeof(scanCfg)); + + memcpy(scanCfg.ssidList[0].ssid, Ext_Scan_SSID.Ssid, + Ext_Scan_SSID.SsidLength); + + wlan_scan_networks(priv, &scanCfg); memset(&wrqu, 0, sizeof(union iwreq_data)); wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu , NULL); +#ifdef REASSOCIATION + OS_REL_SEMAPHORE(&Adapter->ReassocSem); +#endif + + if (Adapter->SurpriseRemoved) + return WLAN_STATUS_FAILURE; + LEAVE(); return WLAN_STATUS_SUCCESS; } +/** + * @brief This function sends BG_SCAN query command to firmware. + * + * @param priv A pointer to wlan_private structure + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +sendBgScanQueryCmd(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + /* Clear the previous scan result */ + memset(Adapter->ScanTable, 0x00, + sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST); + Adapter->NumInScanTable = 0; + Adapter->pBeaconBufEnd = Adapter->beaconBuffer; + + return PrepareAndSendCommand(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY, + 0, 0, 0, NULL); +} + +/** + * @brief Enable/Disable BG Scan + * + * @param priv A pointer to wlan_private structure + * @param enable TRUE-enable, FALSE-disable + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_bg_scan_enable(wlan_private * priv, BOOLEAN enable) +{ + int ret; + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_BG_SCAN_CONFIG, + 0, HostCmd_OPTION_WAITFORRSP, 0, &enable); + return ret; +} + +/** + * @brief config BGSCAN parameter + + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_do_bg_scan_config_ioctl(wlan_private * priv, struct ifreq *req) +{ + wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; + u8 action; + u8 *buf = NULL; + HostCmd_DS_802_11_BG_SCAN_CONFIG *tmp; + + ENTER(); + action = *((u8 *) req->ifr_data + SKIP_CMDNUM + SKIP_SIZE); + PRINTM(INFO, "Action = %d\n", action); + + switch (action) { + case HostCmd_ACT_GEN_GET: + buf = kmalloc(Adapter->bgScanConfigSize + SKIP_TYPE_SIZE, GFP_KERNEL); + if (!buf) { + PRINTM(MSG, "kmalloc no memory !!\n"); + return -ENOMEM; + } + memcpy(buf, &Adapter->bgScanConfigSize, SKIP_SIZE); + memcpy(buf + SKIP_TYPE_SIZE, Adapter->bgScanConfig, + Adapter->bgScanConfigSize); + + if (copy_to_user(req->ifr_data, buf, + Adapter->bgScanConfigSize + SKIP_TYPE_SIZE)) { + PRINTM(INFO, "Copy to user failed\n"); + kfree(buf); + return -EFAULT; + } + + kfree(buf); + + break; + + case HostCmd_ACT_GEN_SET: + Adapter->bgScanConfigSize = *(u16 *) (req->ifr_data + SKIP_CMDNUM); + PRINTM(INFO, "bgscanConfigSize = %d\n", Adapter->bgScanConfigSize); + + if (!(tmp = kmalloc(Adapter->bgScanConfigSize, GFP_KERNEL))) { + PRINTM(MSG, "kmalloc no memory !!\n"); + Adapter->bgScanConfigSize = 0; + return -ENOMEM; + } + + HEXDUMP("treq", req->ifr_data + SKIP_CMDNUM + SKIP_SIZE, + Adapter->bgScanConfigSize); + + if (copy_from_user(tmp, req->ifr_data + SKIP_CMDNUM + SKIP_SIZE, + Adapter->bgScanConfigSize)) { + PRINTM(INFO, "Copy from user failed\n"); + kfree(tmp); + return -EFAULT; + } + + if (Adapter->bgScanConfig) { + tmp->Enable = Adapter->bgScanConfig->Enable; + buf = (u8 *) Adapter->bgScanConfig; + } + Adapter->bgScanConfig = tmp; + if (buf) + kfree(buf); + + break; + } + + LEAVE(); + + return ret; +} + +/** + * @brief This function prepares command of bg_scan_config. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action the action: GET or SET + * @param pdata_buf A pointer to data buffer + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +wlan_cmd_802_11_bg_scan_config(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, + int cmd_action, void *pdata_buf) +{ + wlan_adapter *Adapter = priv->adapter; + HostCmd_DS_802_11_BG_SCAN_CONFIG *bgcfg = &cmd->params.bgscancfg; + BOOLEAN enable = *((BOOLEAN *) pdata_buf); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG); + cmd->Size = + wlan_cpu_to_le16((priv->adapter->bgScanConfigSize) + S_DS_GEN); + + Adapter->bgScanConfig->Enable = enable; + + memcpy(bgcfg, Adapter->bgScanConfig, Adapter->bgScanConfigSize); + + bgcfg->Action = wlan_cpu_to_le16(bgcfg->Action); + bgcfg->ScanInterval = wlan_cpu_to_le32(bgcfg->ScanInterval); + bgcfg->StoreCondition = wlan_cpu_to_le32(bgcfg->StoreCondition); + bgcfg->ReportConditions = wlan_cpu_to_le32(bgcfg->ReportConditions); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief This function prepares command of bg_scan_query. + * + * @param priv A pointer to wlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * + * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE + */ +int +wlan_cmd_802_11_bg_scan_query(wlan_private * priv, HostCmd_DS_COMMAND * cmd) +{ + HostCmd_DS_802_11_BG_SCAN_QUERY *bgquery = &cmd->params.bgscanquery; + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) + S_DS_GEN); + + bgquery->Flush = 1; + + return WLAN_STATUS_SUCCESS; +} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_scan.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_scan.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_scan.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_scan.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,6 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ -/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */ - /** @file wlan_scan.h * * @brief Interface for the wlan network scan routines @@ -8,16 +5,13 @@ * Driver interface functions and type declarations for the scan module * implemented in wlan_scan.c. * - * @sa wlan_scan.c - * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -36,13 +30,6 @@ #ifndef _WLAN_SCAN_H #define _WLAN_SCAN_H -/** - * @brief Maximum number of channels that can be sent in a setuserscan ioctl - * - * @sa wlan_ioctl_user_scan_cfg - */ -#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50 - //! Infrastructure BSS scan type in wlan_scan_cmd_config #define WLAN_SCAN_BSS_TYPE_BSS 1 @@ -52,6 +39,42 @@ //! Adhoc or Infrastructure BSS scan type in wlan_scan_cmd_config, no filter #define WLAN_SCAN_BSS_TYPE_ANY 3 +/** @brief Maximum buffer space for beacons retrieved from scan responses + * 4000 has successfully stored up to 40 beacons + * 6000 has successfully stored the max scan results (max 64) + */ +#define MAX_SCAN_BEACON_BUFFER 6000 + +/** + * @brief Buffer pad space for newly allocated beacons/probe responses + * + * Beacons are typically 6 bytes longer than an equivalent probe response. + * For each scan response stored, allocate an extra byte pad at the end to + * allow easy expansion to store a beacon in the same memory a probe reponse + * previously contained + */ +#define SCAN_BEACON_ENTRY_PAD 6 + +//! Scan time specified in the channel TLV for each channel for passive scans +#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100 + +//! Scan time specified in the channel TLV for each channel for active scans +#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 + +//! Scan time specified in the channel TLV for each channel for specific scans +#define MRVDRV_SPECIFIC_SCAN_CHAN_TIME 100 + +//! Max passive scan time for each channel in milliseconds +#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000 + +//! Max active scan time for each channel in milliseconds +#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500 + +/** + * Max total scan time in milliseconds + * The total scan time should be less than scan command timeout value (10s) + */ +#define MRVDRV_MAX_TOTAL_SCAN_TIME (MRVDRV_TIMER_10S - MRVDRV_TIMER_1S) /** * @brief Structure used internally in the wlan driver to configure a scan. @@ -62,7 +85,8 @@ * @sa wlan_scan_networks * */ -typedef struct { +typedef struct +{ /** * @brief BSS Type to be sent in the firmware command * @@ -95,78 +119,13 @@ } wlan_scan_cmd_config; /** - * @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg - * - * Multiple instances of this structure are included in the IOCTL command - * to configure a instance of a scan on the specific channel. - */ -typedef struct { - u8 chanNumber; //!< Channel Number to scan - u8 radioType; //!< Radio type: 'B/G' Band = 0, 'A' Band = 1 - u8 scanType; //!< Scan type: Active = 0, Passive = 1 - u16 scanTime; //!< Scan duration in milliseconds; if 0 default used -} wlan_ioctl_user_scan_chan; - -/** - * @brief IOCTL input structure to configure an immediate scan cmd to firmware - * - * Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl. Specifies - * a number of parameters to be used in general for the scan as well - * as a channel list (wlan_ioctl_user_scan_chan) for each scan period - * desired. - * - * @sa wlan_set_user_scan_ioctl - */ -typedef struct { - - /** - * @brief Flag set to keep the previous scan table intact - * - * If set, the scan results will accumulate, replacing any previous - * matched entries for a BSS with the new scan data - */ - u8 keepPreviousScan; //!< Do not erase the existing scan results - - /** - * @brief BSS Type to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. Valid settings are: - * - * - WLAN_SCAN_BSS_TYPE_BSS (infrastructure) - * - WLAN_SCAN_BSS_TYPE_IBSS (adhoc) - * - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure) - */ - u8 bssType; - - /** - * @brief Configure the number of probe requests for active chan scans - */ - u8 numProbes; - - /** - * @brief BSSID filter sent in the firmware command to limit the results - */ - u8 specificBSSID[MRVDRV_ETH_ADDR_LEN]; - - /** - * @brief SSID filter sent in the firmware command to limit the results - */ - char specificSSID[MRVDRV_MAX_SSID_LENGTH + 1]; - - /** - * @brief Variable number (fixed maximum) of channels to scan up - */ - wlan_ioctl_user_scan_chan chanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX]; -} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg; - -/** * @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS * * Fixed field information returned for the scan response in the IOCTL * response. */ -typedef struct { +typedef struct +{ u8 bssid[6]; //!< BSSID of this network u8 channel; //!< Channel this beacon/probe response was detected u8 rssi; //!< RSSI for the received packet @@ -179,7 +138,8 @@ * * @sa wlan_get_scan_table_ioctl */ -typedef struct { +typedef struct +{ /** * @brief Fixed field length included in the response. @@ -219,7 +179,8 @@ * * @sa wlan_get_scan_table_ioctl */ -typedef struct { +typedef struct +{ /** * - Zero based scan entry to start retrieval in command request @@ -238,7 +199,8 @@ /** * @brief Structure used to store information for each beacon/probe response */ -typedef struct { +typedef struct +{ WLAN_802_11_MAC_ADDRESS MacAddress; WLAN_802_11_SSID Ssid; @@ -254,10 +216,12 @@ u16 BeaconPeriod; u32 ATIMWindow; + u8 ERPFlags; WLAN_802_11_NETWORK_TYPE NetworkTypeInUse; WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; WLAN_802_11_RATES SupportedRates; + IEEEtypes_WmmParameter_t wmmIE; int extra_ie; @@ -269,31 +235,30 @@ u64 networkTSF; //!< TSF timestamp from the current firmware TSF - IEEEtypes_CountryInfoFullSet_t CountryInfo; - WPA_SUPPLICANT wpa_supplicant; - WPA_SUPPLICANT wpa2_supplicant; + IEEEtypes_VendorSpecific_t wpaIE; + IEEEtypes_Generic_t rsnIE; + IEEEtypes_VendorSpecific_t wpsIE; + + u8 *pBeaconBuf; //!< Pointer to the returned scan response + uint beaconBufSize; //!< Length of the stored scan response + uint beaconBufSizeMax; //!< Max allocated size for updated scan response } BSSDescriptor_t; extern int SSIDcmp(WLAN_802_11_SSID* ssid1, WLAN_802_11_SSID* ssid2); -extern int FindSSIDInList(wlan_adapter* Adapter, - WLAN_802_11_SSID* ssid, u8* bssid, int mode ); +extern int FindSSIDInList(wlan_adapter * Adapter, WLAN_802_11_SSID * ssid, + u8 * bssid, int mode); extern int FindBestSSIDInList(wlan_adapter* Adapter); extern int FindBSSIDInList(wlan_adapter* Adapter, u8* bssid, int mode); extern int FindBestNetworkSsid(wlan_private* priv, WLAN_802_11_SSID* pSSID); extern int SendSpecificSSIDScan(wlan_private* priv, - WLAN_802_11_SSID* pRequestedSSID, - BOOLEAN keepPreviousScan); -extern int SendSpecificBSSIDScan(wlan_private* priv, - u8* bssid, - BOOLEAN keepPreviousScan); - -extern u8 wlan_scan_radio_to_band(u8 scanBand); + WLAN_802_11_SSID * pRequestedSSID); +extern int SendSpecificBSSIDScan(wlan_private * priv, u8 * bssid); extern int wlan_get_scan_table_ioctl(wlan_private* priv, struct iwreq* wrq); extern int wlan_set_user_scan_ioctl(wlan_private* priv, struct iwreq* wrq); @@ -301,13 +266,25 @@ extern int wlan_associate(wlan_private* priv, BSSDescriptor_t* pBSSDesc); extern int wlan_cmd_802_11_scan(wlan_private* priv, - HostCmd_DS_COMMAND* cmd, - void* pdata_buf); + HostCmd_DS_COMMAND * cmd, void *pdata_buf); -extern int wlan_ret_802_11_scan(wlan_private* priv, HostCmd_DS_COMMAND* resp); +extern void wlan_scan_update_tsf_timestamps(wlan_private * priv, + BSSDescriptor_t * pNewBssDesc); + +extern int wlan_ret_802_11_scan(wlan_private * priv, + HostCmd_DS_COMMAND * resp); extern int wlan_extscan_ioctl(wlan_private* priv, struct ifreq* req); +extern int sendBgScanQueryCmd(wlan_private * priv); +extern int wlan_bg_scan_enable(wlan_private * priv, BOOLEAN enable); +extern int wlan_do_bg_scan_config_ioctl(wlan_private * priv, + struct ifreq *req); +extern int wlan_cmd_802_11_bg_scan_config(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, + int cmd_action, void *pdata_buf); +extern int wlan_cmd_802_11_bg_scan_query(wlan_private * priv, + HostCmd_DS_COMMAND * cmd); #ifdef __KERNEL__ extern int wlan_get_scan(struct net_device* dev, struct iw_request_info* info, diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_tx.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_tx.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_tx.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_tx.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,14 @@ /** @file wlan_tx.c - * @brief This file contains the handling of TX in wlan driver. + * @brief This file contains the handling of TX in wlan + * driver. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -41,32 +41,6 @@ ********************************************************/ /** - * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE - * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) - * - * @param rate Input rate - * @return Output Rate (0 if invalid) - */ -u32 convert_radiotap_rate_to_mv(u8 rate) -{ - switch (rate) { - case 2: /* 1 Mbps */ return 0 | (1<<4); - case 4: /* 2 Mbps */ return 1 | (1<<4); - case 11: /* 5.5 Mbps */ return 2 | (1<<4); - case 22: /* 11 Mbps */ return 3 | (1<<4); - case 12: /* 6 Mbps */ return 4 | (1<<4); - case 18: /* 9 Mbps */ return 5 | (1<<4); - case 24: /* 12 Mbps */ return 6 | (1<<4); - case 36: /* 18 Mbps */ return 7 | (1<<4); - case 48: /* 24 Mbps */ return 8 | (1<<4); - case 72: /* 36 Mbps */ return 9 | (1<<4); - case 96: /* 48 Mbps */ return 10 | (1<<4); - case 108: /* 54 Mbps */ return 11 | (1<<4); - } - return 0; -} - -/** * @brief This function processes a single packet and sends * to IF layer * @@ -74,25 +48,19 @@ * @param skb A pointer to skb which includes TX packet * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -static int SendSinglePacket(wlan_private *priv, struct sk_buff *skb) +static int +SendSinglePacket(wlan_private * priv, struct sk_buff *skb) { wlan_adapter *Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; TxPD LocalTxPD; TxPD *pLocalTxPD = &LocalTxPD; - u8 *p802x_hdr; - TxRadiotapHdr_t *pradiotap_hdr; - u32 new_rate; - u8 *ptr = priv->adapter->TmpTxBuf; + u8 *ptr = Adapter->TmpTxBuf; ENTER(); - if ( (priv->adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0 ) - HEXDUMP("TX packet: ", skb->data, MIN(skb->len, 100)); - - if (!skb->len || (skb->len > - MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { - PRINTM(INFO, "Tx Error: Bad skb length %d : %d\n", + if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { + PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); ret = WLAN_STATUS_FAILURE; goto done; @@ -102,13 +70,32 @@ pLocalTxPD->TxPacketLength = skb->len; + if (Adapter->wmm.enabled) { + /* + * original skb->priority has been overwritten + * by wmm_map_and_add_skb() + */ + pLocalTxPD->Priority = (u8) skb->priority; + + pLocalTxPD->PktDelay_2ms = wmm_compute_driver_packet_delay(skb); + } + + if (pLocalTxPD->Priority < NELEMENTS(Adapter->wmm.userPriPktTxCtrl)) { + /* + * Set the priority specific TxControl field, setting of 0 will + * cause the default value to be used later in this function + */ + pLocalTxPD->TxControl + = Adapter->wmm.userPriPktTxCtrl[pLocalTxPD->Priority]; + } + if(Adapter->PSState != PS_STATE_FULL_POWER){ if(TRUE == CheckLastPacketIndication(priv)){ - Adapter->TxLockFlag = 1; - pLocalTxPD->PowerMgmt = - MRVDRV_TxPD_POWER_MGMT_LAST_PACKET; + Adapter->TxLockFlag = TRUE; + pLocalTxPD->Flags = MRVDRV_TxPD_POWER_MGMT_LAST_PACKET; } } + /* offset of actual data */ pLocalTxPD->TxPacketLocation = sizeof(TxPD); @@ -112,84 +99,49 @@ /* offset of actual data */ pLocalTxPD->TxPacketLocation = sizeof(TxPD); + if (pLocalTxPD->TxControl == 0) { /* TxCtrl set by user or default */ pLocalTxPD->TxControl = Adapter->PktTxCtrl; - - p802x_hdr = skb->data; - if ( priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP ) { - - /* locate radiotap header */ - pradiotap_hdr = (TxRadiotapHdr_t*)skb->data; - - /* set TxPD fields from the radiotap header */ - new_rate = convert_radiotap_rate_to_mv( - pradiotap_hdr->rate); - if ( new_rate != 0 ) { - /* erase TxControl[4:0] */ - pLocalTxPD->TxControl &= ~0x1f; - /* write new TxControl[4:0] */ - pLocalTxPD->TxControl |= new_rate; - } - - /* skip the radiotap header */ - p802x_hdr += sizeof(TxRadiotapHdr_t); - pLocalTxPD->TxPacketLength -= sizeof(TxRadiotapHdr_t); - } - /* copy destination address from 802.3 or 802.11 header */ - if ( priv->adapter->linkmode == WLAN_LINKMODE_802_11 ) - memcpy(pLocalTxPD->TxDestAddrHigh, p802x_hdr + 4, - MRVDRV_ETH_ADDR_LEN); - else - memcpy(pLocalTxPD->TxDestAddrHigh, p802x_hdr, - MRVDRV_ETH_ADDR_LEN); - + endian_convert_TxPD(pLocalTxPD); - HEXDUMP("TxPD", (u8 *) pLocalTxPD, sizeof(TxPD)); + memcpy((u8 *) pLocalTxPD->TxDestAddr, skb->data, MRVDRV_ETH_ADDR_LEN); + ptr += SDIO_HEADER_LEN; memcpy(ptr, pLocalTxPD, sizeof(TxPD)); ptr += sizeof(TxPD); - HEXDUMP("Tx Data", (u8 *) p802x_hdr, - pLocalTxPD->TxPacketLength); - memcpy(ptr, p802x_hdr, pLocalTxPD->TxPacketLength); - ret = sbi_host_to_card(priv, MVMS_DAT, - priv->adapter->TmpTxBuf, - pLocalTxPD->TxPacketLength + sizeof(TxPD)); - + memcpy(ptr, skb->data, skb->len); + ret = sbi_host_to_card(priv, MVMS_DAT, Adapter->TmpTxBuf, + skb->len + sizeof(TxPD)); if (ret) { - PRINTM(INFO, "Tx Error: sbi_host_to_card failed: 0x%X\n",ret); + PRINTM(ERROR, + "SendSinglePacket Error: sbi_host_to_card failed: 0x%X\n", + ret); + Adapter->dbg.num_tx_host_to_card_failure++; goto done; } - PRINTM(INFO, "SendSinglePacket succeeds\n"); + PRINTM(DATA, "Data => FW\n"); + DBG_HEXDUMP(DAT_D, "Tx", ptr - sizeof(TxPD), + MIN(skb->len + sizeof(TxPD), MAX_DATA_DUMP_LEN)); + + wmm_process_fw_iface_tx_xfer_start(priv); done: if (!ret) { priv->stats.tx_packets++; priv->stats.tx_bytes += skb->len; - } - else { + } else { priv->stats.tx_dropped++; priv->stats.tx_errors++; } - if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) { - /* Keep the skb to echo it back once Tx feedback is - received from FW */ - skb_orphan(priv->adapter->CurrentTxSkb); - /* stop processing outgoing pkts */ - os_stop_queue(priv); - /* freeze any packets already in our queues */ - priv->adapter->TxLockFlag = 1; - } else - { + /* need to be freed in all cases */ os_free_tx_packet(priv); - os_start_queue(priv); - } LEAVE(); return ret; @@ -206,23 +158,22 @@ * @param priv A pointer to wlan_private structure * @return n/a */ -void wlan_process_tx(wlan_private *priv) +void +wlan_process_tx(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; - OS_INTERRUPT_SAVE_AREA; - ENTER(); + OS_INTERRUPT_SAVE_AREA; + if(priv->wlan_dev.dnld_sent) { PRINTM(MSG, "TX Error: dnld_sent = %d, not sending\n", priv->wlan_dev.dnld_sent); goto done; } - SendSinglePacket(priv, Adapter->CurrentTxSkb); - OS_INT_DISABLE; priv->adapter->HisRegCpy &= ~HIS_TxDnLdRdy; OS_INT_RESTORE; @@ -239,7 +190,8 @@ * @param skb A pointer to skb which includes TX packet * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ -int wlan_tx_packet(wlan_private *priv, struct sk_buff *skb) +int +wlan_tx_packet(wlan_private * priv, struct sk_buff *skb) { ulong flags; wlan_adapter *Adapter = priv->adapter; @@ -251,11 +203,8 @@ spin_lock_irqsave(&Adapter->CurrentTxLock, flags); - { - Adapter->TxSkbNum ++; - list_add_tail((struct list_head *) skb,(struct list_head *) &priv->adapter->TxSkbQ); + wmm_map_and_add_skb(priv, skb); wake_up_interruptible(&priv->MainThread.waitQ); - } spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); LEAVE(); @@ -263,29 +212,29 @@ return ret; } - /** * @brief This function tells firmware to send a NULL data packet. * * @param priv A pointer to wlan_private structure - * @param pwr_mgmt indicate if power management bit should be 0 or 1 + * @param flags Trasnit Pkt Flags * @return n/a */ -int SendNullPacket(wlan_private *priv, u8 pwr_mgmt) +int +SendNullPacket(wlan_private * priv, u8 flags) { wlan_adapter *Adapter = priv->adapter; - TxPD txpd; + TxPD txpd = { 0 }; int ret = WLAN_STATUS_SUCCESS; - u8 *ptr = priv->adapter->TmpTxBuf; + u8 *ptr = Adapter->TmpTxBuf; ENTER(); - if (priv->adapter->SurpriseRemoved == TRUE) { + if (Adapter->SurpriseRemoved == TRUE) { ret = WLAN_STATUS_FAILURE; goto done; } - if (priv->adapter->MediaConnectStatus == WlanMediaStateDisconnected) { + if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) { ret = WLAN_STATUS_FAILURE; goto done; } @@ -293,20 +242,24 @@ memset(&txpd, 0, sizeof(TxPD)); txpd.TxControl = Adapter->PktTxCtrl; - txpd.PowerMgmt = pwr_mgmt; + txpd.Flags = flags; + txpd.Priority = WMM_HIGHEST_PRIORITY; txpd.TxPacketLocation = sizeof(TxPD); + endian_convert_TxPD(&txpd); + ptr += SDIO_HEADER_LEN; memcpy(ptr, &txpd, sizeof(TxPD)); - ret = sbi_host_to_card(priv, MVMS_DAT, - priv->adapter->TmpTxBuf, sizeof(TxPD)); + ret = sbi_host_to_card(priv, MVMS_DAT, Adapter->TmpTxBuf, sizeof(TxPD)); - if (ret != 0) - { - PRINTM(INFO, "TX Error: SendNullPacket failed!\n"); + if (ret != 0) { + PRINTM(ERROR, "TX Error: SendNullPacket failed!\n"); + Adapter->dbg.num_tx_host_to_card_failure++; goto done; } + PRINTM(DATA, "Null data => FW\n"); + DBG_HEXDUMP(DAT_D, "Tx", ptr, sizeof(TxPD)); done: LEAVE(); @@ -320,58 +273,28 @@ * * @return TRUE or FALSE */ -BOOLEAN CheckLastPacketIndication(wlan_private *priv) +BOOLEAN +CheckLastPacketIndication(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; BOOLEAN ret = FALSE; - if(Adapter->sleep_period.period == 0) - goto done; -done: - return ret; -} - -/** - * @brief This function sends to the host the last transmitted packet, - * filling the radiotap headers with transmission information. - * - * @param priv A pointer to wlan_private structure - * @param status A 32 bit value containing transmission status. - * - * @returns void - */ -void SendTxFeedback(wlan_private *priv) -{ - wlan_adapter *Adapter = priv->adapter; - TxRadiotapHdr_t *radiotap_hdr; - u32 status = Adapter->EventCause; - int txfail; - int try_count; - - - if (Adapter->radiomode != WLAN_RADIOMODE_RADIOTAP || - Adapter->CurrentTxSkb == NULL) - return; + BOOLEAN prop_ps = TRUE; - radiotap_hdr = (TxRadiotapHdr_t*) Adapter->CurrentTxSkb->data; + ENTER(); - if ((Adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0 ) - HEXDUMP("TX feedback: ", (u8 *) radiotap_hdr, - MIN(Adapter->CurrentTxSkb->len, 100)); + if (Adapter->sleep_period.period == 0 || Adapter->gen_null_pkg == FALSE /* for UPSD certification tests */ + ) { + LEAVE(); + return ret; + } - txfail = (status >> 24); + if (wmm_lists_empty(priv)) { + if (((Adapter->CurBssParams.wmm_uapsd_enabled == TRUE) + && (Adapter->wmm.qosinfo != 0)) || prop_ps) { + ret = TRUE; + } + } -#if 0 - /* The version of roofnet that we've tested does not use this yet - * But it may be used in the future. - */ - if (txfail) - radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; -#endif - try_count = (status >> 16) & 0xff; - radiotap_hdr->data_retries = (try_count) ? - (1 + Adapter->TxRetryCount - try_count) : 0; - os_upload_rx_packet(priv, Adapter->CurrentTxSkb); - Adapter->CurrentTxSkb = NULL; - priv->adapter->TxLockFlag = 0; - os_start_queue(priv); + LEAVE(); + return ret; } diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_types.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_types.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_types.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_types.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,13 @@ /** @file wlan_types.h * @brief This header file contains definition for global types * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -26,40 +25,123 @@ 04/10/06: Add power_adapt_cfg_ext command 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 05/03/06: Add auto_tx hostcmd + 08/28/06: Add LED_CTRL hostcmd ************************************************************/ #ifndef _WLAN_TYPES_ #define _WLAN_TYPES_ +#ifndef __KERNEL__ +typedef char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed long s32; +typedef unsigned long u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +typedef u32 dma_addr_t; +typedef u32 dma64_addr_t; +/* Dma addresses are 32-bits wide. */ +#ifndef __ATTRIB_ALIGN__ +#define __ATTRIB_ALIGN__ __attribute__((aligned(4))) +#endif + +#ifndef __ATTRIB_PACK__ +#define __ATTRIB_PACK__ __attribute__ ((packed)) +#endif +#endif + +typedef long LONG; +typedef unsigned long long ULONGLONG; +typedef u32 WLAN_OID; + +#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 +#define MRVDRV_MAX_CHANNEL_SIZE 14 +#define MRVDRV_ETH_ADDR_LEN 6 +#define MRVDRV_MAX_SSID_LENGTH 32 +#define MRVDRV_MAX_BSS_DESCRIPTS 16 +/** WEP list macros & data structures */ +#define MRVL_KEY_BUFFER_SIZE_IN_BYTE 16 +#define MRVL_MAX_KEY_WPA_KEY_LENGTH 32 + +#define HOSTCMD_SUPPORTED_RATES G_SUPPORTED_RATES + +#define BAND_B (0x01) +#define BAND_G (0x02) +#define ALL_802_11_BANDS (BAND_B | BAND_G) + +#define B_SUPPORTED_RATES 8 +#define G_SUPPORTED_RATES 14 + +#define WLAN_SUPPORTED_RATES 14 +#define WLAN_MAX_SSID_LENGTH 32 + +#define MAX_POWER_ADAPT_GROUP 5 + +#define MRVDRV_MAX_SSID_LIST_LENGTH 10 + +typedef u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES]; +typedef u8 WLAN_802_11_MAC_ADDRESS[ETH_ALEN]; + +/** WLAN_802_11_NETWORK_TYPE */ +typedef enum _WLAN_802_11_NETWORK_TYPE +{ + Wlan802_11FH, + Wlan802_11DS, + /*defined as upper bound */ + Wlan802_11NetworkTypeMax +} WLAN_802_11_NETWORK_TYPE, *PWLAN_802_11_NETWORK_TYPE; + +/** WLAN_802_11_NETWORK_INFRASTRUCTURE */ +typedef enum _WLAN_802_11_NETWORK_INFRASTRUCTURE +{ + Wlan802_11IBSS, + Wlan802_11Infrastructure, + Wlan802_11AutoUnknown, + /*defined as upper bound */ + Wlan802_11InfrastructureMax +} WLAN_802_11_NETWORK_INFRASTRUCTURE, *PWLAN_802_11_NETWORK_INFRASTRUCTURE; + +#define IEEE_MAX_IE_SIZE 256 + /** IEEE Type definitions */ -typedef enum _IEEEtypes_ElementId_e { +typedef enum _IEEEtypes_ElementId_e +{ SSID = 0, - SUPPORTED_RATES, - FH_PARAM_SET, - DS_PARAM_SET, - CF_PARAM_SET, - TIM, - IBSS_PARAM_SET, - COUNTRY_INFO = 7, + SUPPORTED_RATES = 1, + FH_PARAM_SET = 2, + DS_PARAM_SET = 3, + CF_PARAM_SET = 4, - CHALLENGE_TEXT = 16, + IBSS_PARAM_SET = 6, + COUNTRY_INFO = 7, + ERP_INFO = 42, EXTENDED_SUPPORTED_RATES = 50, VENDOR_SPECIFIC_221 = 221, + WMM_IE = VENDOR_SPECIFIC_221, - WPA_IE = 221, - WPA2_IE = 48, + WPS_IE = VENDOR_SPECIFIC_221, + + WPA_IE = VENDOR_SPECIFIC_221, + RSN_IE = 48, EXTRA_IE = 133, } __ATTRIB_PACK__ IEEEtypes_ElementId_e; - #define CAPINFO_MASK (~( W_BIT_15 | W_BIT_14 | \ W_BIT_12 | W_BIT_11 | W_BIT_9) ) -typedef struct _IEEEtypes_CapInfo_t { +typedef struct _IEEEtypes_CapInfo_t +{ u8 Ess:1; u8 Ibss:1; u8 CfPollable:1; @@ -77,9 +159,15 @@ u8 Rsrvd1:2; } __ATTRIB_PACK__ IEEEtypes_CapInfo_t; +typedef struct +{ + u8 ElementId; + u8 Len; +} __ATTRIB_PACK__ IEEEtypes_Header_t; /** IEEEtypes_CfParamSet_t */ -typedef struct _IEEEtypes_CfParamSet_t { +typedef struct _IEEEtypes_CfParamSet_t +{ u8 ElementId; u8 Len; u8 CfpCnt; @@ -88,20 +176,23 @@ u16 CfpDurationRemaining; } __ATTRIB_PACK__ IEEEtypes_CfParamSet_t; -typedef struct IEEEtypes_IbssParamSet_t { +typedef struct IEEEtypes_IbssParamSet_t +{ u8 ElementId; u8 Len; u16 AtimWindow; } __ATTRIB_PACK__ IEEEtypes_IbssParamSet_t; /** IEEEtypes_SsParamSet_t */ -typedef union _IEEEtypes_SsParamSet_t { +typedef union _IEEEtypes_SsParamSet_t +{ IEEEtypes_CfParamSet_t CfParamSet; IEEEtypes_IbssParamSet_t IbssParamSet; } __ATTRIB_PACK__ IEEEtypes_SsParamSet_t; /** IEEEtypes_FhParamSet_t */ -typedef struct _IEEEtypes_FhParamSet_t { +typedef struct _IEEEtypes_FhParamSet_t +{ u8 ElementId; u8 Len; u16 DwellTime; @@ -110,28 +201,68 @@ u8 HopIndex; } __ATTRIB_PACK__ IEEEtypes_FhParamSet_t; -typedef struct _IEEEtypes_DsParamSet_t { +typedef struct _IEEEtypes_DsParamSet_t +{ u8 ElementId; u8 Len; u8 CurrentChan; } __ATTRIB_PACK__ IEEEtypes_DsParamSet_t; /** IEEEtypes_DsParamSet_t */ -typedef union IEEEtypes_PhyParamSet_t { +typedef union IEEEtypes_PhyParamSet_t +{ IEEEtypes_FhParamSet_t FhParamSet; IEEEtypes_DsParamSet_t DsParamSet; } __ATTRIB_PACK__ IEEEtypes_PhyParamSet_t; +typedef struct _IEEEtypes_ERPInfo_t +{ + u8 ElementId; + u8 Len; + u8 ERPFlags; +} __ATTRIB_PACK__ IEEEtypes_ERPInfo_t; + typedef u16 IEEEtypes_AId_t; typedef u16 IEEEtypes_StatusCode_t; -typedef struct { +typedef struct +{ IEEEtypes_CapInfo_t Capability; IEEEtypes_StatusCode_t StatusCode; IEEEtypes_AId_t AId; u8 IEBuffer[1]; } __ATTRIB_PACK__ IEEEtypes_AssocRsp_t; +typedef struct +{ + u8 ElementId; + u8 Len; + u8 Oui[3]; + u8 OuiType; + u8 OuiSubtype; + u8 Version; +} __ATTRIB_PACK__ IEEEtypes_VendorHeader_t; + +typedef struct +{ + IEEEtypes_VendorHeader_t VendHdr; + + /* IE Max - size of previous fields */ + u8 Data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)]; + +} +__ATTRIB_PACK__ IEEEtypes_VendorSpecific_t; + +typedef struct +{ + IEEEtypes_Header_t IeeeHdr; + + /* IE Max - size of previous fields */ + u8 Data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)]; + +} +__ATTRIB_PACK__ IEEEtypes_Generic_t; + /** TLV type ID definition */ #define PROPRIETARY_TLV_BASE_ID 0x0100 @@ -159,59 +290,67 @@ #define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8) #define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9) #define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11) #define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12) #define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13) -#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14) -#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15) #define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) -#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17) #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) +#define TLV_TYPE_POWERADAPTCFGEXT (PROPRIETARY_TLV_BASE_ID + 20) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) +#define TLV_TYPE_AUTO_TX (PROPRIETARY_TLV_BASE_ID + 24) +#define TLV_TYPE_WPS_ENROLLEE_PROBE_REQ_TLV (PROPRIETARY_TLV_BASE_ID + 27) +#define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 30) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) /** TLV related data structures*/ /** MrvlIEtypesHeader_t */ -typedef struct _MrvlIEtypesHeader { +typedef struct _MrvlIEtypesHeader +{ u16 Type; u16 Len; } __ATTRIB_PACK__ MrvlIEtypesHeader_t; /** MrvlIEtypes_Data_t */ -typedef struct _MrvlIEtypes_Data_t { +typedef struct _MrvlIEtypes_Data_t +{ MrvlIEtypesHeader_t Header; u8 Data[1]; } __ATTRIB_PACK__ MrvlIEtypes_Data_t; /** MrvlIEtypes_RatesParamSet_t */ -typedef struct _MrvlIEtypes_RatesParamSet_t { +typedef struct _MrvlIEtypes_RatesParamSet_t +{ MrvlIEtypesHeader_t Header; u8 Rates[1]; } __ATTRIB_PACK__ MrvlIEtypes_RatesParamSet_t; /** MrvlIEtypes_SsIdParamSet_t */ -typedef struct _MrvlIEtypes_SsIdParamSet_t { +typedef struct _MrvlIEtypes_SsIdParamSet_t +{ MrvlIEtypesHeader_t Header; u8 SsId[1]; } __ATTRIB_PACK__ MrvlIEtypes_SsIdParamSet_t; /** MrvlIEtypes_WildCardSsIdParamSet_t */ -typedef struct _MrvlIEtypes_WildCardSsIdParamSet_t { +typedef struct _MrvlIEtypes_WildCardSsIdParamSet_t +{ MrvlIEtypesHeader_t Header; u8 MaxSsidLength; u8 SsId[1]; } __ATTRIB_PACK__ MrvlIEtypes_WildCardSsIdParamSet_t; /** ChanScanMode_t */ -typedef struct { +typedef struct +{ u8 PassiveScan : 1; u8 DisableChanFilt : 1; u8 Reserved_2_7 : 6; } __ATTRIB_PACK__ ChanScanMode_t; /** ChanScanParamSet_t */ -typedef struct _ChanScanParamSet_t{ +typedef struct _ChanScanParamSet_t +{ u8 RadioType; u8 ChanNumber; ChanScanMode_t ChanScanMode; @@ -220,13 +359,15 @@ } __ATTRIB_PACK__ ChanScanParamSet_t; /** MrvlIEtypes_ChanListParamSet_t */ -typedef struct _MrvlIEtypes_ChanListParamSet_t { +typedef struct _MrvlIEtypes_ChanListParamSet_t +{ MrvlIEtypesHeader_t Header; ChanScanParamSet_t ChanScanParam[1]; } __ATTRIB_PACK__ MrvlIEtypes_ChanListParamSet_t; /** CfParamSet_t */ -typedef struct _CfParamSet_t { +typedef struct _CfParamSet_t +{ u8 CfpCnt; u8 CfpPeriod; u16 CfpMaxDuration; @@ -234,21 +375,25 @@ } __ATTRIB_PACK__ CfParamSet_t; /** IbssParamSet_t */ -typedef struct _IbssParamSet_t { +typedef struct _IbssParamSet_t +{ u16 AtimWindow; } __ATTRIB_PACK__ IbssParamSet_t; /** MrvlIEtypes_SsParamSet_t */ -typedef struct _MrvlIEtypes_SsParamSet_t { +typedef struct _MrvlIEtypes_SsParamSet_t +{ MrvlIEtypesHeader_t Header; - union { + union + { CfParamSet_t CfParamSet[1]; IbssParamSet_t IbssParamSet[1]; } cf_ibss; } __ATTRIB_PACK__ MrvlIEtypes_SsParamSet_t; /** FhParamSet_t */ -typedef struct _FhParamSet_t { +typedef struct _FhParamSet_t +{ u16 DwellTime; u8 HopSet; u8 HopPattern; @@ -256,103 +401,655 @@ } __ATTRIB_PACK__ FhParamSet_t; /** DsParamSet_t */ -typedef struct _DsParamSet_t { +typedef struct _DsParamSet_t +{ u8 CurrentChan; } __ATTRIB_PACK__ DsParamSet_t; /** MrvlIEtypes_PhyParamSet_t */ -typedef struct _MrvlIEtypes_PhyParamSet_t { +typedef struct _MrvlIEtypes_PhyParamSet_t +{ MrvlIEtypesHeader_t Header; - union { + union + { FhParamSet_t FhParamSet[1]; DsParamSet_t DsParamSet[1]; } fh_ds; } __ATTRIB_PACK__ MrvlIEtypes_PhyParamSet_t; - /** MrvlIEtypes_RsnParamSet_t */ -typedef struct _MrvlIEtypes_RsnParamSet_t { +typedef struct _MrvlIEtypes_RsnParamSet_t +{ MrvlIEtypesHeader_t Header; u8 RsnIE[1]; } __ATTRIB_PACK__ MrvlIEtypes_RsnParamSet_t; +/** MrvlIEtypes_WmmParamSet_t */ +typedef struct _MrvlIEtypes_WmmParamSet_t +{ + MrvlIEtypesHeader_t Header; + u8 WmmIE[1]; +} __ATTRIB_PACK__ MrvlIEtypes_WmmParamSet_t; -typedef struct { +typedef struct +{ + MrvlIEtypesHeader_t Header; + u8 QueueIndex; + u8 Disabled; + u8 Reserved1; + u8 Reserved2; + u8 FlowRequired; + u8 FlowCreated; + u32 Reserved3; +} __ATTRIB_PACK__ MrvlIEtypes_WmmQueueStatus_t; + +/** Table of TSF values returned in the scan result */ +typedef struct +{ MrvlIEtypesHeader_t Header; u64 tsfTable[1]; } __ATTRIB_PACK__ MrvlIEtypes_TsfTimestamp_t; /** Local Power Capability */ -typedef struct _MrvlIEtypes_PowerCapability_t { +typedef struct _MrvlIEtypes_PowerCapability_t +{ MrvlIEtypesHeader_t Header; s8 MinPower; s8 MaxPower; } __ATTRIB_PACK__ MrvlIEtypes_PowerCapability_t; /** MrvlIEtypes_RssiParamSet_t */ -typedef struct _MrvlIEtypes_RssiThreshold_t { +typedef struct _MrvlIEtypes_RssiThreshold_t +{ MrvlIEtypesHeader_t Header; u8 RSSIValue; u8 RSSIFreq; -} __ATTRIB_PACK__ MrvlIEtypes_RssiParamSet_t; +} __ATTRIB_PACK__ MrvlIEtypes_RssiThreshold_t; /** MrvlIEtypes_SnrThreshold_t */ -typedef struct _MrvlIEtypes_SnrThreshold_t { +typedef struct _MrvlIEtypes_SnrThreshold_t +{ MrvlIEtypesHeader_t Header; u8 SNRValue; u8 SNRFreq; } __ATTRIB_PACK__ MrvlIEtypes_SnrThreshold_t; /** MrvlIEtypes_FailureCount_t */ -typedef struct _MrvlIEtypes_FailureCount_t { +typedef struct _MrvlIEtypes_FailureCount_t +{ MrvlIEtypesHeader_t Header; u8 FailValue; u8 FailFreq; } __ATTRIB_PACK__ MrvlIEtypes_FailureCount_t; /** MrvlIEtypes_BeaconsMissed_t */ -typedef struct _MrvlIEtypes_BeaconsMissed_t { +typedef struct _MrvlIEtypes_BeaconsMissed_t +{ MrvlIEtypesHeader_t Header; u8 BeaconMissed; u8 Reserved; } __ATTRIB_PACK__ MrvlIEtypes_BeaconsMissed_t; /** MrvlIEtypes_NumProbes_t */ -typedef struct _MrvlIEtypes_NumProbes_t { +typedef struct _MrvlIEtypes_NumProbes_t +{ MrvlIEtypesHeader_t Header; u16 NumProbes; } __ATTRIB_PACK__ MrvlIEtypes_NumProbes_t; -/** MrvlIEtypes_BcastProbe_t */ -typedef struct _MrvlIEtypes_BcastProbe_t { - MrvlIEtypesHeader_t Header; - u16 BcastProbe; -} __ATTRIB_PACK__ MrvlIEtypes_BcastProbe_t; - -/** MrvlIEtypes_NumSSIDProbe_t */ -typedef struct _MrvlIEtypes_NumSSIDProbe_t { +/** MrvlIEtypes_StartBGScanLater_t */ +typedef struct _MrvlIEtypes_StartBGScanLater_t +{ MrvlIEtypesHeader_t Header; - u16 NumSSIDProbe; -} __ATTRIB_PACK__ MrvlIEtypes_NumSSIDProbe_t; + u16 StartLater; +} __ATTRIB_PACK__ MrvlIEtypes_StartBGScanLater_t; -typedef struct { - u8 Led; - u8 Pin; -} __ATTRIB_PACK__ Led_Pin; +typedef struct _LedGpio_t +{ + u8 LedNum; /* LED # mapped to GPIO pin # below */ + u8 GpioNum; /* GPIO pin # used to control LED # above */ +} __ATTRIB_PACK__ LedGpio_t; /** MrvlIEtypes_LedGpio_t */ -typedef struct _MrvlIEtypes_LedGpio_t { +typedef struct _MrvlIEtypes_LedGpio_t +{ MrvlIEtypesHeader_t Header; - Led_Pin LedPin[1]; + LedGpio_t LedGpio[1]; } __ATTRIB_PACK__ MrvlIEtypes_LedGpio_t; +/** MrvlIEtypes_LedBehavior_t */ +typedef struct _MrvlIEtypes_LedBehavior_t +{ + MrvlIEtypesHeader_t Header; + u8 FirmwareState; /* Firmware State */ + u8 LedNum; /* LED # */ + u8 LedState; /* LED State corresponding to Firmware State */ + u8 LedArgs; /* Arguments for LED State */ +} __ATTRIB_PACK__ MrvlIEtypes_LedBehavior_t; + +typedef struct _PA_Group_t +{ + u16 PowerAdaptLevel; + u16 RateBitmap; + u32 Reserved; +} __ATTRIB_PACK__ PA_Group_t; + +/** MrvlIEtypes_PA_Group_t */ +typedef struct _MrvlIEtypes_PowerAdapt_Group_t +{ + MrvlIEtypesHeader_t Header; + PA_Group_t PA_Group[MAX_POWER_ADAPT_GROUP]; +} __ATTRIB_PACK__ MrvlIEtypes_PowerAdapt_Group_t; + +typedef struct _AutoTx_MacFrame_t +{ + u16 Interval; /* in seconds */ + u8 Priority; /* User Priority: 0~7, ignored if non-WMM */ + u8 Reserved; /* set to 0 */ + u16 FrameLen; /* Length of MAC frame payload */ + u8 DestMacAddr[ETH_ALEN]; + u8 SrcMacAddr[ETH_ALEN]; + u8 Payload[]; +} __ATTRIB_PACK__ AutoTx_MacFrame_t; + +/** MrvlIEtypes_AutoTx_t */ +typedef struct _MrvlIEtypes_AutoTx_t +{ + MrvlIEtypesHeader_t Header; + AutoTx_MacFrame_t AutoTx_MacFrame; +} __ATTRIB_PACK__ MrvlIEtypes_AutoTx_t; typedef struct { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 ethertype; -} __ATTRIB_PACK__ EthII_Hdr_t; + u8 value; + u8 Freq; +} Threshold; -#endif /* _WLAN_TYPES_ */ +typedef struct +{ + u16 EventsBitmap; /* bit 0: RSSI low, bit 1: SNR low, + * bit 2: RSSI high, bit 3: SNR high + */ + Threshold Rssi_low; + Threshold Snr_low; + Threshold Rssi_high; + Threshold Snr_high; + u8 Rssi_low_count; + u8 Snr_low_count; + u8 Rssi_high_count; + u8 Snr_high_count; +} wlan_subscribe_event; + +/** Auth type to be used in the Authentication portion of an Assoc seq */ +typedef struct +{ + MrvlIEtypesHeader_t Header; + u16 AuthType; +} __ATTRIB_PACK__ MrvlIEtypes_AuthType_t; + +#define MRVDRV_MAX_SUBBAND_802_11D 83 +#define COUNTRY_CODE_LEN 3 + +/** Data structure for Country IE*/ +typedef struct _IEEEtypes_SubbandSet +{ + u8 FirstChan; + u8 NoOfChan; + u8 MaxTxPwr; +} __ATTRIB_PACK__ IEEEtypes_SubbandSet_t; + +typedef struct _IEEEtypes_CountryInfoSet +{ + u8 ElementId; + u8 Len; + u8 CountryCode[COUNTRY_CODE_LEN]; + IEEEtypes_SubbandSet_t Subband[1]; +} __ATTRIB_PACK__ IEEEtypes_CountryInfoSet_t; + +typedef struct _IEEEtypes_CountryInfoFullSet +{ + u8 ElementId; + u8 Len; + u8 CountryCode[COUNTRY_CODE_LEN]; + IEEEtypes_SubbandSet_t Subband[MRVDRV_MAX_SUBBAND_802_11D]; +} __ATTRIB_PACK__ IEEEtypes_CountryInfoFullSet_t; + +typedef struct _MrvlIEtypes_DomainParamSet +{ + MrvlIEtypesHeader_t Header; + u8 CountryCode[COUNTRY_CODE_LEN]; + IEEEtypes_SubbandSet_t Subband[1]; +} __ATTRIB_PACK__ MrvlIEtypes_DomainParamSet_t; +/** Size of a TSPEC. Used to allocate necessary buffer space in commands */ +#define WMM_TSPEC_SIZE 63 + +/** Extra IE bytes allocated in messages for appended IEs after a TSPEC */ +#define WMM_ADDTS_EXTRA_IE_BYTES 256 + +/** Extra TLV bytes allocated in messages for configuring WMM Queues */ +#define WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES 64 +/** Maximum number of AC QOS queues available in the driver/firmware */ +#define MAX_AC_QUEUES 4 + +/** enum of WMM AC_QUEUES */ +typedef enum +{ + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VO, +} __ATTRIB_PACK__ wlan_wmm_ac_e; + +/** data structure of WMM QoS information */ +typedef struct +{ + u8 ParaSetCount:4; + u8 Reserved:3; + u8 QosUAPSD:1; +} __ATTRIB_PACK__ IEEEtypes_WmmQosInfo_t; + +typedef struct +{ + u8 Aifsn:4; + u8 Acm:1; + u8 Aci:2; + u8 Reserved:1; +} __ATTRIB_PACK__ IEEEtypes_WmmAciAifsn_t; + +/** data structure of WMM ECW */ +typedef struct +{ + u8 EcwMin:4; + u8 EcwMax:4; +} __ATTRIB_PACK__ IEEEtypes_WmmEcw_t; + +/** data structure of WMM AC parameters */ +typedef struct +{ + IEEEtypes_WmmAciAifsn_t AciAifsn; + IEEEtypes_WmmEcw_t Ecw; + u16 TxopLimit; +} __ATTRIB_PACK__ IEEEtypes_WmmAcParameters_t; + +/** data structure of WMM Info IE */ +typedef struct +{ + + /** + * WMM Info IE - Vendor Specific Header: + * ElementId [221/0xdd] + * Len [7] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [0] + * Version [1] + */ + IEEEtypes_VendorHeader_t VendHdr; + + IEEEtypes_WmmQosInfo_t QoSInfo; + +} __ATTRIB_PACK__ IEEEtypes_WmmInfo_t; + +/** data structure of WMM parameter IE */ +typedef struct +{ + /** + * WMM Parameter IE - Vendor Specific Header: + * ElementId [221/0xdd] + * Len [24] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [1] + * Version [1] + */ + IEEEtypes_VendorHeader_t VendHdr; + + IEEEtypes_WmmQosInfo_t QoSInfo; + u8 Reserved; + + /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */ + IEEEtypes_WmmAcParameters_t AcParams[MAX_AC_QUEUES]; + +} __ATTRIB_PACK__ IEEEtypes_WmmParameter_t; + +/** + * @brief Firmware command structure to retrieve the firmware WMM status. + * + * Used to retrieve the status of each WMM AC Queue in TLV + * format (MrvlIEtypes_WmmQueueStatus_t) as well as the current WMM + * parameter IE advertised by the AP. + * + * Used in response to a MACREG_INT_CODE_WMM_STATUS_CHANGE event signalling + * a QOS change on one of the ACs or a change in the WMM Parameter in + * the Beacon. + * + * TLV based command, byte arrays used for max sizing purpose. There are no + * arguments sent in the command, the TLVs are returned by the firmware. + */ +typedef struct +{ + u8 queueStatusTlv[sizeof(MrvlIEtypes_WmmQueueStatus_t) * MAX_AC_QUEUES]; + u8 wmmParamTlv[sizeof(IEEEtypes_WmmParameter_t) + 2]; + +} +__ATTRIB_PACK__ HostCmd_DS_WMM_GET_STATUS; + +/** + * @brief Enumeration for the command result from an ADDTS or DELTS command + */ +typedef enum +{ + TSPEC_RESULT_SUCCESS = 0, + TSPEC_RESULT_EXEC_FAILURE = 1, + TSPEC_RESULT_TIMEOUT = 2, + TSPEC_RESULT_DATA_INVALID = 3, + +} __ATTRIB_PACK__ wlan_wmm_tspec_result_e; + +/** + * @brief IOCTL structure to send an ADDTS request and retrieve the response. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an ADDTS management frame with an appropriate TSPEC IE as well + * as any additional IEs appended in the ADDTS Action frame. + * + * @sa wlan_wmm_addts_req_ioctl + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; + u32 timeout_ms; + + u8 ieeeStatusCode; + + u8 tspecData[WMM_TSPEC_SIZE]; + + u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES]; + +} __ATTRIB_PACK__ wlan_ioctl_wmm_addts_req_t; + +/** + * @brief IOCTL structure to send a DELTS request. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an DELTS management frame with an appropriate TSPEC IE. + * + * @sa wlan_wmm_delts_req_ioctl + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; //!< Firmware execution result + + u8 ieeeReasonCode; //!< IEEE reason code sent, unused for WMM + + u8 tspecData[WMM_TSPEC_SIZE]; //!< TSPEC to send in the DELTS + +} __ATTRIB_PACK__ wlan_ioctl_wmm_delts_req_t; + +/** + * @brief Internal command structure used in executing an ADDTS command. + * + * Relay information between the IOCTL layer and the firmware command and + * command response procedures. + * + * @sa wlan_wmm_addts_req_ioctl + * @sa wlan_cmd_wmm_addts_req + * @sa wlan_cmdresp_wmm_addts_req + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; + u32 timeout_ms; + + u8 dialogToken; + u8 ieeeStatusCode; + + int tspecDataLen; + u8 tspecData[WMM_TSPEC_SIZE]; + u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES]; + +} wlan_cmd_wmm_addts_req_t; + +/** + * @brief Internal command structure used in executing an DELTS command. + * + * Relay information between the IOCTL layer and the firmware command and + * command response procedures. + * + * @sa wlan_wmm_delts_req_ioctl + * @sa wlan_cmd_wmm_delts_req + * @sa wlan_cmdresp_wmm_delts_req + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; + + u8 dialogToken; + + u8 ieeeReasonCode; + + int tspecDataLen; + u8 tspecData[WMM_TSPEC_SIZE]; + +} wlan_cmd_wmm_delts_req_t; + +/** + * @brief Command structure for the HostCmd_CMD_WMM_ADDTS_REQ firmware command + * + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; + u32 timeout_ms; + + u8 dialogToken; + u8 ieeeStatusCode; + u8 tspecData[WMM_TSPEC_SIZE]; + u8 addtsExtraIEBuf[WMM_ADDTS_EXTRA_IE_BYTES]; + +} __ATTRIB_PACK__ HostCmd_DS_WMM_ADDTS_REQ; + +/** + * @brief Command structure for the HostCmd_CMD_WMM_DELTS_REQ firmware command + */ +typedef struct +{ + wlan_wmm_tspec_result_e commandResult; + u8 dialogToken; + u8 ieeeReasonCode; + u8 tspecData[WMM_TSPEC_SIZE]; + +} __ATTRIB_PACK__ HostCmd_DS_WMM_DELTS_REQ; + +/** + * @brief Enumeration for the action field in the Queue configure command + */ +typedef enum +{ + WMM_QUEUE_CONFIG_ACTION_GET = 0, + WMM_QUEUE_CONFIG_ACTION_SET = 1, + WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2, + + WMM_QUEUE_CONFIG_ACTION_MAX +} __ATTRIB_PACK__ wlan_wmm_queue_config_action_e; + +/** + * @brief Command structure for the HostCmd_CMD_WMM_QUEUE_CONFIG firmware cmd + * + * Set/Get/Default the Queue parameters for a specific AC in the firmware. + * + */ +typedef struct +{ + wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default + wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3) + + /** @brief MSDU lifetime expiry per 802.11e + * + * - Ignored if 0 on a set command + * - Set to the 802.11e specified 500 TUs when defaulted + */ + u16 msduLifetimeExpiry; + + u8 tlvBuffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; //!< Not supported yet + +} __ATTRIB_PACK__ HostCmd_DS_WMM_QUEUE_CONFIG; + +/** + * @brief Internal command structure used in executing a queue config command. + * + * Relay information between the IOCTL layer and the firmware command and + * command response procedures. + * + * @sa wlan_wmm_queue_config_ioctl + * @sa wlan_cmd_wmm_queue_config + * @sa wlan_cmdresp_wmm_queue_config + */ +typedef struct +{ + wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default + wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3) + u16 msduLifetimeExpiry; //!< lifetime expiry in TUs + + int tlvBufLen; //!< Not supported yet + u8 tlvBuffer[WMM_QUEUE_CONFIG_EXTRA_TLV_BYTES]; //!< Not supported yet + +} wlan_cmd_wmm_queue_config_t; + +/** + * @brief IOCTL structure to configure a specific AC Queue's parameters + * + * IOCTL structure from the application layer relayed to firmware to + * get, set, or default the WMM AC queue parameters. + * + * - msduLifetimeExpiry is ignored if set to 0 on a set command + * + * @sa wlan_wmm_queue_config_ioctl + */ +typedef struct +{ + wlan_wmm_queue_config_action_e action; //!< Set, Get, or Default + wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3) + u16 msduLifetimeExpiry; //!< lifetime expiry in TUs + + u8 supportedRates[10]; //!< Not supported yet + +} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_config_t; + +/** + * @brief Enumeration for the action field in the queue stats command + */ +typedef enum +{ + WMM_STATS_ACTION_START = 0, + WMM_STATS_ACTION_STOP = 1, + WMM_STATS_ACTION_GET_CLR = 2, + WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */ + WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */ + + WMM_STATS_ACTION_MAX +} __ATTRIB_PACK__ wlan_wmm_stats_action_e; + +/** Number of bins in the histogram for the HostCmd_DS_WMM_QUEUE_STATS */ +#define WMM_STATS_PKTS_HIST_BINS 7 + +/** + * @brief Command structure for the HostCmd_CMD_WMM_QUEUE_STATS firmware cmd + * + * Turn statistical collection on/off for a given AC or retrieve the + * accumulated stats for an AC and clear them in the firmware. + */ +typedef struct +{ + wlan_wmm_stats_action_e action; //!< Start, Stop, or Get + wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3) + + u16 pktCount; //!< Number of successful packets transmitted + u16 pktLoss; //!< Packets lost; not included in pktCount + u32 avgQueueDelay; //!< Average Queue delay in microseconds + u32 avgTxDelay; //!< Average Transmission delay in microseconds + u32 usedTime; //!< Calculated medium time - Not currently used + + /** @brief Queue Delay Histogram; number of packets per queue delay range + * + * [0] - 0ms <= delay < 5ms + * [1] - 5ms <= delay < 10ms + * [2] - 10ms <= delay < 20ms + * [3] - 20ms <= delay < 30ms + * [4] - 30ms <= delay < 40ms + * [5] - 40ms <= delay < 50ms + * [6] - 50ms <= delay < msduLifetime (TUs) + */ + u16 delayHistogram[WMM_STATS_PKTS_HIST_BINS]; + + u16 reserved_u16_1; + +} __ATTRIB_PACK__ HostCmd_DS_WMM_QUEUE_STATS; + +/** + * @brief IOCTL structure to start, stop, and get statistics for a WMM AC + * + * IOCTL structure from the application layer relayed to firmware to + * start or stop statistical collection for a given AC. Also used to + * retrieve and clear the collected stats on a given AC. + * + * @sa wlan_wmm_queue_stats_ioctl + */ +typedef struct +{ + wlan_wmm_stats_action_e action; //!< Start, Stop, or Get + wlan_wmm_ac_e accessCategory; //!< WMM_AC_BK(0) to WMM_AC_VO(3) + u16 pktCount; //!< Number of successful packets transmitted + u16 pktLoss; //!< Packets lost; not included in pktCount + u32 avgQueueDelay; //!< Average Queue delay in microseconds + u32 avgTxDelay; //!< Average Transmission delay in microseconds + u32 usedTime; //!< Calculated medium time + + /** @brief Queue Delay Histogram; number of packets per queue delay range + * + * [0] - 0ms <= delay < 5ms + * [1] - 5ms <= delay < 10ms + * [2] - 10ms <= delay < 20ms + * [3] - 20ms <= delay < 30ms + * [4] - 30ms <= delay < 40ms + * [5] - 40ms <= delay < 50ms + * [6] - 50ms <= delay < msduLifetime (TUs) + */ + u16 delayHistogram[WMM_STATS_PKTS_HIST_BINS]; +} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_stats_t; + +/** + * @brief IOCTL sub structure for a specific WMM AC Status + */ +typedef struct +{ + u8 wmmAcm; + u8 flowRequired; + u8 flowCreated; + u8 disabled; +} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_status_ac_t; + +/** + * @brief IOCTL structure to retrieve the WMM AC Queue status + * + * IOCTL structure from the application layer to retrieve: + * - ACM bit setting for the AC + * - Firmware status (flow required, flow created, flow disabled) + * + * @sa wlan_wmm_queue_status_ioctl + */ +typedef struct +{ + wlan_ioctl_wmm_queue_status_ac_t acStatus[MAX_AC_QUEUES]; +} __ATTRIB_PACK__ wlan_ioctl_wmm_queue_status_t; + +/** Firmware status for a specific AC */ +typedef struct +{ + u8 Disabled; + u8 FlowRequired; + u8 FlowCreated; +} WmmAcStatus_t; + +#endif /* _WLAN_TYPES_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_version.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_version.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_version.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_version.h 2007-11-06 12:26:40.000000000 -0500 @@ -2,13 +2,12 @@ * @brief This file contains wlan driver version number. * * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -25,9 +24,8 @@ ********************************************************/ #include "../release_version.h" - const char driver_version[] = - "COMM-USB8388-%s-" DRIVER_RELEASE_VERSION + "sd8686-%s-" DRIVER_RELEASE_VERSION "-(" "FP" FPNUM ")" #ifdef DEBUG_LEVEL2 "-dbg" #endif diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wext.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wext.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wext.c 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wext.c 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,13 @@ /** @file wlan_wext.c * @brief This file contains ioctl functions * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -25,21 +24,23 @@ duplicate BSSIDs when earlier matches are not compatible 12/26/05: Remove errant memcpy in wlanidle_off; overwriting stack space 01/05/06: Add kernel 2.6.x support - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support Monahans/Zylonite 01/11/06: Conditionalize new scan/join functions. Update statics/externs. Move forward decl. from wlan_decl.h 04/06/06: Add TSPEC, queue metrics, and MSDU expiry support 04/10/06: Add hostcmd generic API 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 05/04/06: Add IBSS coalescing related new iwpriv command + 08/29/06: Add ledgpio private command + 10/23/06: Validate setbcnavg/setdataavg command parameters and + return error if out of range ********************************************************/ - #include "include.h" #include "wlan_version.h" -#define GETLOG_BUFSIZE 300 +#define GETLOG_BUFSIZE 512 #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \ MRVDRV_MAX_SSID_LENGTH + \ @@ -47,7 +48,36 @@ IW_EV_QUAL_LEN + MRVDRV_MAX_SSID_LENGTH + \ IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */ -#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ) +typedef struct _ioctl_cmd +{ + int cmd; + int subcmd; + BOOLEAN fixsize; +} ioctl_cmd; + +static ioctl_cmd Commands_Allowed_In_DeepSleep[] = { + {.cmd = WLANDEEPSLEEP,.subcmd = 0,.fixsize = FALSE}, + {.cmd = WLAN_SETONEINT_GETWORDCHAR,.subcmd = WLANVERSION,.fixsize = + FALSE}, + {.cmd = WLAN_SETINT_GETINT,.subcmd = WLANSDIOCLOCK,.fixsize = TRUE}, + {.cmd = WLAN_SET_GET_2K,.subcmd = WLAN_GET_CFP_TABLE,.fixsize = FALSE}, +#ifdef DEBUG_LEVEL1 + {.cmd = WLAN_SET_GET_SIXTEEN_INT,.subcmd = WLAN_DRV_DBG,.fixsize = FALSE}, +#endif +}; + +static ioctl_cmd Commands_Allowed_In_HostSleep[] = { + {.cmd = WLAN_SETONEINT_GETWORDCHAR,.subcmd = WLANVERSION,.fixsize = + FALSE}, + {.cmd = WLANDEEPSLEEP,.subcmd = 1,.fixsize = FALSE}, + {.cmd = WLANDEEPSLEEP,.subcmd = 0,.fixsize = FALSE}, + {.cmd = WLAN_SETINT_GETINT,.subcmd = WLANSDIOCLOCK,.fixsize = TRUE}, + {.cmd = WLAN_SET_GET_2K,.subcmd = WLAN_GET_CFP_TABLE,.fixsize = FALSE}, +#ifdef DEBUG_LEVEL1 + {.cmd = WLAN_SET_GET_SIXTEEN_INT,.subcmd = WLAN_DRV_DBG,.fixsize = FALSE}, +#endif +}; + /******************************************************** Local Variables ********************************************************/ @@ -55,7 +85,15 @@ /******************************************************** Global Variables ********************************************************/ - +#ifdef DEBUG_LEVEL1 +#ifdef DEBUG_LEVEL2 +#define DEFAULT_DEBUG_MASK (0xffffffff & ~DBG_EVENT) +#else +#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR) +#endif +u32 drvdbg = DEFAULT_DEBUG_MASK; +u32 ifdbg = 0; +#endif /******************************************************** Local Functions @@ -65,8 +103,9 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra); -static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra); +static int wlan_get_essid(struct net_device *dev, + struct iw_request_info *info, struct iw_point *dwrq, + char *extra); static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra); @@ -78,28 +117,80 @@ static int wlan_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra); -static int wlan_set_encode(struct net_device *dev,struct iw_request_info *info, +static int wlan_set_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *dwrq, char *extra); -static int wlan_get_encode(struct net_device *dev,struct iw_request_info *info, +static int wlan_get_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *dwrq, u8 * extra); -static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra); -static int wlan_get_txpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra); +static int wlan_set_txpow(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, + char *extra); +static int wlan_get_txpow(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, + char *extra); -/* DFT function declaration */ -static int wlan_dft_add_ioctl(wlan_private *priv, struct ifreq *req); -static int wlan_dft_del_ioctl(wlan_private *priv, struct ifreq *req); -static int wlan_dft_reset_ioctl(wlan_private *priv); -static int wlan_dft_list_ioctl(wlan_private *priv, struct ifreq *req); +static int wlan_set_coalescing_ioctl(wlan_private * priv, struct iwreq *wrq); -/* BT function declaration */ -static int wlan_bt_add_ioctl(wlan_private *priv, struct ifreq *req); -static int wlan_bt_del_ioctl(wlan_private *priv, struct ifreq *req); -static int wlan_bt_reset_ioctl(wlan_private *priv); -static int wlan_bt_list_ioctl(wlan_private *priv, struct ifreq *req); +extern CHANNEL_FREQ_POWER *wlan_get_region_cfp_table(u8 region, u8 band, + int *cfp_no); + +/** + * @brief This function checks if the commans is allowed + * in deepsleep/hostsleep mode or not. + * + * @param req A pointer to ifreq structure + * @param cmd the command ID + * @return TRUE or FALSE + */ +static BOOLEAN +Is_Command_Allowed_In_Sleep(struct ifreq *req, int cmd, + ioctl_cmd * allowed_cmds, int count) +{ + int subcmd = 0; + struct iwreq *wrq = (struct iwreq *) req; + int i; + for (i = 0; i < count; i++) { + if (cmd == allowed_cmds[i].cmd) { + if (allowed_cmds[i].subcmd == 0) + return TRUE; + if (allowed_cmds[i].fixsize == TRUE) + subcmd = (int) req->ifr_data; + else + subcmd = wrq->u.data.flags; + if (allowed_cmds[i].subcmd == subcmd) + return TRUE; + } + } + return FALSE; +} + +/** + * @brief This function checks if the command is allowed. + * + * @param priv A pointer to wlan_private structure + * @return TRUE or FALSE + */ +BOOLEAN +Is_Command_Allowed(wlan_private * priv) +{ + BOOLEAN ret = TRUE; + + if (priv->adapter->bHostSleepConfigured) { + PRINTM(INFO, "IOCTLS called when WLAN access is blocked\n"); + ret = FALSE; + } + if (!priv->adapter->IsAutoDeepSleepEnabled) { + if ((priv->adapter->IsDeepSleep == TRUE)) { + PRINTM(INFO, "IOCTLS called when station is in DeepSleep\n"); + ret = FALSE; + } + } + + return ret; +} /** * @brief Find a character in a string. @@ -109,7 +200,8 @@ * @param dlen the length of string * @return A pointer to the first occurrence of c in string, or NULL if c is not found. */ -static void *wlan_memchr(void *s, int c, int n) +static void * +wlan_memchr(void *s, int c, int n) { const u8 *p = s; @@ -121,7 +213,6 @@ return NULL; } - #if WIRELESS_EXT > 14 /** * @brief Convert mw value to dbm value @@ -129,7 +220,8 @@ * @param mw the value of mw * @return the value of dbm */ -static int mw_to_dbm(int mw) +static int +mw_to_dbm(int mw) { if (mw < 2) return 0; @@ -168,8 +260,40 @@ else return 21; } + +/** + * @brief This function sends customized event to application. + * + * @param priv A pointer to wlan_private structure + * @para str A pointer to event string + * @return n/a + */ +void +send_iwevcustom_event(wlan_private * priv, s8 * str) +{ + union iwreq_data iwrq; + u8 buf[50]; + + ENTER(); + + memset(&iwrq, 0, sizeof(union iwreq_data)); + memset(buf, 0, sizeof(buf)); + + snprintf(buf, sizeof(buf) - 1, "%s", str); + + iwrq.data.pointer = buf; + iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; + + /* Send Event to upper layer */ + wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf); + PRINTM(INFO, "Wireless event %s is sent to app\n", str); + + LEAVE(); + return; +} #endif +#define FIRST_VALID_CHANNEL 0xff /** * @brief Find the channel frequency power info with specific channel * @@ -178,8 +302,8 @@ * @param channel the channel for looking * @return A pointer to CHANNEL_FREQ_POWER structure or NULL if not find. */ -CHANNEL_FREQ_POWER *find_cfp_by_band_and_channel(wlan_adapter *adapter, - u8 band, u16 channel) +CHANNEL_FREQ_POWER * +find_cfp_by_band_and_channel(wlan_adapter * adapter, u8 band, u16 channel) { CHANNEL_FREQ_POWER *cfp = NULL; REGION_CHANNEL *rc; @@ -197,6 +321,9 @@ continue; if (rc->Band != band) continue; + if (channel == FIRST_VALID_CHANNEL) + cfp = &rc->CFP[0]; + else { for (i = 0; i < rc->NrCFP; i++) { if (rc->CFP[i].Channel == channel) { cfp = &rc->CFP[i]; @@ -204,6 +331,7 @@ } } } + } if (!cfp && channel) PRINTM(INFO, "find_cfp_by_band_and_channel(): cannot find " @@ -218,10 +346,10 @@ * @param adapter A pointer to wlan_adapter structure * @param band it can be BAND_A, BAND_G or BAND_B * @param freq the frequency for looking - * @return A pointer to CHANNEL_FREQ_POWER structure or NULL if not find. + * @return Pointer to CHANNEL_FREQ_POWER structure; NULL if not found */ -static CHANNEL_FREQ_POWER *find_cfp_by_band_and_freq(wlan_adapter *adapter, - u8 band, u32 freq) +static CHANNEL_FREQ_POWER * +find_cfp_by_band_and_freq(wlan_adapter * adapter, u8 band, u32 freq) { CHANNEL_FREQ_POWER *cfp = NULL; REGION_CHANNEL *rc; @@ -255,6 +383,119 @@ return cfp; } +#ifdef MFG_CMD_SUPPORT +/** + * @brief Manufacturing command ioctl function + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS--success, otherwise--fail + */ +static int +wlan_mfg_command(wlan_private * priv, struct iwreq *wrq) +{ + HostCmd_DS_GEN *pCmdPtr; + u8 *mfg_cmd; + u16 mfg_cmd_len; + int ret; + + ENTER(); + + /* allocate MFG command buffer */ + if (!(mfg_cmd = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) { + PRINTM(INFO, "allocate MFG command buffer failed!\n"); + return -ENOMEM; + } + + /* get MFG command header */ + if (copy_from_user(mfg_cmd, wrq->u.data.pointer, sizeof(HostCmd_DS_GEN))) { + PRINTM(INFO, "copy from user failed: MFG command header\n"); + ret = -EFAULT; + goto mfg_exit; + } + + /* get the command size */ + pCmdPtr = (HostCmd_DS_GEN *) mfg_cmd; + mfg_cmd_len = pCmdPtr->Size; + PRINTM(INFO, "MFG command len = %d\n", mfg_cmd_len); + + if (mfg_cmd_len > MRVDRV_SIZE_OF_CMD_BUFFER) { + ret = -EINVAL; + goto mfg_exit; + } + + /* get the whole command from user */ + if (copy_from_user(mfg_cmd, wrq->u.data.pointer, mfg_cmd_len)) { + PRINTM(INFO, "copy from user failed: MFG command\n"); + ret = -EFAULT; + goto mfg_exit; + } + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_MFG_COMMAND, + 0, HostCmd_OPTION_WAITFORRSP, 0, mfg_cmd); + + /* copy the response back to user */ + if (!ret && pCmdPtr->Size) { + mfg_cmd_len = MIN(pCmdPtr->Size, mfg_cmd_len); + if (copy_to_user(wrq->u.data.pointer, mfg_cmd, mfg_cmd_len)) { + PRINTM(INFO, "copy to user failed: MFG command\n"); + ret = -EFAULT; + } + wrq->u.data.length = mfg_cmd_len; + } + + mfg_exit: + kfree(mfg_cmd); + LEAVE(); + return ret; +} +#endif + +/** + * @brief Check if Rate Auto + * + * @param priv A pointer to wlan_private structure + * @return TRUE/FALSE + */ +BOOLEAN +Is_Rate_Auto(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int i; + int ratenum = 0; + int bitsize = 0; + bitsize = sizeof(Adapter->RateBitmap) * 8; + for (i = 0; i < bitsize; i++) { + if (Adapter->RateBitmap & (1 << i)) + ratenum++; + if (ratenum > 1) + break; + } + if (ratenum > 1) + return TRUE; + else + return FALSE; +} + +/** + * @brief Covert Rate Bitmap to Rate index + * + * @param priv A pointer to wlan_private structure + * @return TRUE/FALSE + */ +int +GetRateIndex(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int bitsize = sizeof(Adapter->RateBitmap) * 8; + int i; + for (i = 0; i < bitsize; i++) { + if (Adapter->RateBitmap & (1 << i)) + return i; + } + return 0; +} /** * @brief Update Current Channel @@ -262,7 +503,8 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -static int UpdateCurrentChannel(wlan_private *priv) +static int +UpdateCurrentChannel(wlan_private * priv) { int ret; @@ -271,10 +513,10 @@ */ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_CHANNEL, HostCmd_OPT_802_11_RF_CHANNEL_GET, - HostCmd_OPTION_WAITFORRSP, 0, - NULL); + HostCmd_OPTION_WAITFORRSP, 0, NULL); - PRINTM(INFO, "Current Channel = %d\n", priv->adapter->CurBssParams.channel); + PRINTM(INFO, "Current Channel = %d\n", + priv->adapter->CurBssParams.BSSDescriptor.Channel); return ret; } @@ -286,7 +528,8 @@ * @param channel The channel to be set. * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -static int SetCurrentChannel(wlan_private *priv, int channel) +static int +SetCurrentChannel(wlan_private * priv, int channel) { PRINTM(INFO, "Set Channel = %d\n", channel); @@ -295,8 +538,7 @@ */ return (PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_CHANNEL, HostCmd_OPT_802_11_RF_CHANNEL_SET, - HostCmd_OPTION_WAITFORRSP, 0, - &channel)); + HostCmd_OPTION_WAITFORRSP, 0, &channel)); } /** @@ -306,7 +548,8 @@ * @param channel The channel to be set. * @return WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail */ -static int ChangeAdhocChannel(wlan_private *priv, int channel) +static int +ChangeAdhocChannel(wlan_private * priv, int channel) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -315,22 +558,24 @@ UpdateCurrentChannel(priv); - if (Adapter->CurBssParams.channel == Adapter->AdhocChannel){ + if (Adapter->CurBssParams.BSSDescriptor.Channel == Adapter->AdhocChannel) { /* AdhocChannel is set to the current Channel already */ LEAVE(); return WLAN_STATUS_SUCCESS; } PRINTM(INFO, "Updating Channel from %d to %d\n", - Adapter->CurBssParams.channel, Adapter->AdhocChannel); + Adapter->CurBssParams.BSSDescriptor.Channel, + Adapter->AdhocChannel); SetCurrentChannel(priv, Adapter->AdhocChannel); UpdateCurrentChannel(priv); - if (Adapter->CurBssParams.channel != Adapter->AdhocChannel){ + if (Adapter->CurBssParams.BSSDescriptor.Channel != Adapter->AdhocChannel) { PRINTM(INFO, "Failed to updated Channel to %d, channel = %d\n", - Adapter->AdhocChannel, Adapter->CurBssParams.channel); + Adapter->AdhocChannel, + Adapter->CurBssParams.BSSDescriptor.Channel); LEAVE(); return WLAN_STATUS_FAILURE; } @@ -342,7 +587,8 @@ PRINTM(INFO, "Channel Changed while in an IBSS\n"); /* Copy the current ssid */ - memcpy(&curAdhocSsid, &Adapter->CurBssParams.ssid, + memcpy(&curAdhocSsid, + &Adapter->CurBssParams.BSSDescriptor.Ssid, sizeof(WLAN_802_11_SSID)); /* Exit Adhoc mode */ @@ -353,25 +599,20 @@ LEAVE(); return ret; } - /* Scan for the network, do not save previous results. Stale - * scan data will cause us to join a non-existant adhoc network - */ - SendSpecificSSIDScan(priv, &curAdhocSsid, FALSE); + /* Scan for the network */ + SendSpecificSSIDScan(priv, &curAdhocSsid); // find out the BSSID that matches the current SSID - i = FindSSIDInList(Adapter, &curAdhocSsid, NULL, - Wlan802_11IBSS); + i = FindSSIDInList(Adapter, &curAdhocSsid, NULL, Wlan802_11IBSS); if (i >= 0) { - PRINTM(INFO, "SSID found at %d in List," - "so join\n", i); + PRINTM(INFO, "SSID found at %d in List," "so join\n", i); JoinAdhocNetwork(priv, &Adapter->ScanTable[i]); } else { // else send START command PRINTM(INFO, "SSID not found in list, " - "so creating adhoc with ssid = %s\n", - curAdhocSsid.Ssid); + "so creating adhoc with ssid = %s\n", curAdhocSsid.Ssid); StartAdhocNetwork(priv, &curAdhocSsid); } // end of else (START command) } @@ -381,6 +622,75 @@ } /** + * @brief Set/Get WPA IE + * + * @param priv A pointer to wlan_private structure + * @param ie_data_ptr A pointer to IE + * @param ie_len Length of the IE + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_wpa_ie_helper(wlan_private * priv, u8 * ie_data_ptr, u16 ie_len) +{ + wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (ie_len) { + if (ie_len > sizeof(Adapter->Wpa_ie)) { + PRINTM(INFO, "failed to copy WPA IE, too big \n"); + return -EFAULT; + } + if (copy_from_user(Adapter->Wpa_ie, ie_data_ptr, ie_len)) { + PRINTM(INFO, "failed to copy WPA IE \n"); + return -EFAULT; + } + Adapter->Wpa_ie_len = ie_len; + PRINTM(INFO, "Set Wpa_ie_len=%d IE=%#x\n", + Adapter->Wpa_ie_len, Adapter->Wpa_ie[0]); + HEXDUMP("Wpa_ie", Adapter->Wpa_ie, Adapter->Wpa_ie_len); + + if (Adapter->Wpa_ie[0] == WPA_IE) { + Adapter->SecInfo.WPAEnabled = TRUE; + } else if (Adapter->Wpa_ie[0] == RSN_IE) { + Adapter->SecInfo.WPA2Enabled = TRUE; + } else { + Adapter->SecInfo.WPAEnabled = FALSE; + Adapter->SecInfo.WPA2Enabled = FALSE; + } + } else { + memset(Adapter->Wpa_ie, 0, sizeof(Adapter->Wpa_ie)); + Adapter->Wpa_ie_len = ie_len; + PRINTM(INFO, "Reset Wpa_ie_len=%d IE=%#x\n", + Adapter->Wpa_ie_len, Adapter->Wpa_ie[0]); + Adapter->SecInfo.WPAEnabled = FALSE; + Adapter->SecInfo.WPA2Enabled = FALSE; + } + + LEAVE(); + return ret; +} + +/** + * @brief Set/Get WPA IE + * + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_wpa_ie_ioctl(wlan_private * priv, struct ifreq *req) +{ + struct iwreq *wrq = (struct iwreq *) req; + + return wlan_set_wpa_ie_helper(priv, + wrq->u.data.pointer, wrq->u.data.length); +} + +/** * @brief Set WPA key * * @param dev A pointer to net_device structure @@ -389,24 +699,26 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_encode_wpa(struct net_device *dev, +static int +wlan_set_encode_wpa(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; wlan_private *priv = dev->priv; - PWLAN_802_11_KEY pKey; + WLAN_802_11_KEY *pKey; ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } - pKey = (PWLAN_802_11_KEY) extra; + pKey = (WLAN_802_11_KEY *) extra; HEXDUMP("Key buffer: ", extra, dwrq->length); - HEXDUMP("KeyMaterial: ", (u8 *) pKey->KeyMaterial, - pKey->KeyLength); - // current driver only supports key length of up to 32 bytes if (pKey->KeyLength > MRVL_MAX_WPA_KEY_LENGTH) { PRINTM(INFO, " Error in key length \n"); @@ -447,7 +760,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_encode_nonwpa(struct net_device *dev, +static int +wlan_set_encode_nonwpa(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { @@ -455,11 +769,17 @@ wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; MRVL_WEP_KEY *pWep; - WLAN_802_11_SSID ssid; int index, PrevAuthMode; ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + + if (Adapter->CurrentWepKeyIndex >= MRVL_NUM_WEP_KEY) + Adapter->CurrentWepKeyIndex = 0; pWep = &Adapter->WepKey[Adapter->CurrentWepKeyIndex]; PrevAuthMode = Adapter->SecInfo.AuthenticationMode; @@ -470,7 +790,6 @@ return -EINVAL; } - PRINTM(INFO, "Flags=0x%x, Length=%d Index=%d CurrentWepKeyIndex=%d\n", dwrq->flags, dwrq->length, index, Adapter->CurrentWepKeyIndex); @@ -483,7 +802,7 @@ * Check the size of the key */ - if (dwrq->length > MAX_KEY_SIZE) { + if (dwrq->length > MAX_WEP_KEY_SIZE) { return -EINVAL; } @@ -507,11 +826,11 @@ memcpy(pWep->KeyMaterial, extra, dwrq->length); /* Set the length */ - if (dwrq->length > MIN_KEY_SIZE) { - pWep->KeyLength = MAX_KEY_SIZE; + if (dwrq->length > MIN_WEP_KEY_SIZE) { + pWep->KeyLength = MAX_WEP_KEY_SIZE; } else { if (dwrq->length > 0) { - pWep->KeyLength = MIN_KEY_SIZE; + pWep->KeyLength = MIN_WEP_KEY_SIZE; } else { /* Disable the key */ pWep->KeyLength = 0; @@ -523,29 +842,25 @@ /* * The status is set as Key Absent * so as to make sure we display the - * keys when iwlist ethX key is - * used - MPS + * keys when iwlist ethX key is used */ - - Adapter->SecInfo.WEPStatus = - Wlan802_11WEPKeyAbsent; + Adapter->SecInfo.WEPStatus = Wlan802_11WEPKeyAbsent; } PRINTM(INFO, "KeyIndex=%u KeyLength=%u\n", - pWep->KeyIndex, - pWep->KeyLength); - HEXDUMP("WepKey", (u8 *) pWep->KeyMaterial, - pWep->KeyLength); + pWep->KeyIndex, pWep->KeyLength); + HEXDUMP("WepKey", (u8 *) pWep->KeyMaterial, pWep->KeyLength); } } else { /* * No key provided so it is either enable key, * on or off */ if (dwrq->flags & IW_ENCODE_DISABLED) { - PRINTM(INFO, "******** iwconfig ethX key off **********\n"); + PRINTM(INFO, "*** iwconfig ethX key off ***\n"); Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled; - if (Adapter->SecInfo.AuthenticationMode == Wlan802_11AuthModeShared) + if (Adapter->SecInfo.AuthenticationMode == + Wlan802_11AuthModeShared) Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen; } else { /* iwconfig ethX key [n] @@ -554,11 +869,10 @@ */ if (index < 0 || index > 3) { - PRINTM(INFO, "******** iwconfig ethX key on **********\n"); + PRINTM(INFO, "*** iwconfig ethX key on ***\n"); index = Adapter->CurrentWepKeyIndex; - } - else { - PRINTM(INFO, "******** iwconfig ethX key [x=%d] **********\n",index); + } else { + PRINTM(INFO, "*** iwconfig ethX key [x=%d] ***\n", index); Adapter->CurrentWepKeyIndex = index; } @@ -572,8 +886,7 @@ Adapter->SecInfo.WEPStatus = Wlan802_11WEPEnabled; - HEXDUMP("KeyMaterial", (u8 *) pWep->KeyMaterial, - pWep->KeyLength); + HEXDUMP("KeyMaterial", (u8 *) pWep->KeyMaterial, pWep->KeyLength); } } @@ -595,52 +908,25 @@ Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WEP_ENABLE; } - SetMacPacketFilter(priv); + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_MAC_CONTROL, + 0, HostCmd_OPTION_WAITFORRSP, + 0, &Adapter->CurrentPacketFilter); if (dwrq->flags & IW_ENCODE_RESTRICTED) { /* iwconfig ethX restricted key [1] */ Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeShared; - PRINTM(INFO, "Authentication mode restricted!\n"); + PRINTM(INFO, "Auth mode restricted!\n"); } else if (dwrq->flags & IW_ENCODE_OPEN) { /* iwconfig ethX key [2] open */ Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen; - PRINTM(INFO, "Authentication mode open!\n"); - } - - /* - * If authentication mode changed - de-authenticate, set authentication - * method and re-associate if we were previously associated. - */ - if (Adapter->SecInfo.AuthenticationMode != PrevAuthMode) { - if (Adapter->MediaConnectStatus == WlanMediaStateConnected && - Adapter->InfrastructureMode == - Wlan802_11Infrastructure) { - - /* keep a copy of the ssid associated with */ - memcpy(&ssid, &Adapter->CurBssParams.ssid, sizeof(ssid)); - - /* - * De-authenticate from AP - */ - - ret = SendDeauthentication(priv); - - if (ret) { - LEAVE(); - return ret; - } - - } else { - /* reset ssid */ - memset(&ssid, 0, sizeof(ssid)); - } + PRINTM(INFO, "Auth mode open!\n"); } LEAVE(); return WLAN_STATUS_SUCCESS; } - /** * @brief Set RX Antenna * @@ -648,7 +934,8 @@ * @param Mode RF antenna mode * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int SetRxAntenna(wlan_private *priv, int Mode) +static int +SetRxAntenna(wlan_private * priv, int Mode) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -675,7 +962,8 @@ * @param Mode RF antenna mode * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int SetTxAntenna(wlan_private *priv, int Mode) +static int +SetTxAntenna(wlan_private * priv, int Mode) { int ret = 0; wlan_adapter *Adapter = priv->adapter; @@ -703,7 +991,8 @@ * @param buf A pointer to recieve antenna mode * @return length of buf */ -static int GetRxAntenna(wlan_private *priv, char *buf) +static int +GetRxAntenna(wlan_private * priv, char *buf) { int ret = 0; wlan_adapter *Adapter = priv->adapter; @@ -737,7 +1026,8 @@ * @param buf A pointer to recieve antenna mode * @return length of buf */ -static int GetTxAntenna(wlan_private *priv, char *buf) +static int +GetTxAntenna(wlan_private * priv, char *buf) { int ret = 0; wlan_adapter *Adapter = priv->adapter; @@ -771,7 +1061,8 @@ * @option Radio Option * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_radio_ioctl(wlan_private *priv, u8 option) +static int +wlan_radio_ioctl(wlan_private * priv, u8 option) { int ret = 0; wlan_adapter *Adapter = priv->adapter; @@ -779,13 +1070,19 @@ ENTER(); if (Adapter->RadioOn != option) { + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + PRINTM(MSG, "Cannot turn radio off in connected state.\n"); + LEAVE(); + return -EINVAL; + } + PRINTM(INFO, "Switching %s the Radio\n", option ? "On" : "Off"); Adapter->RadioOn = option; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RADIO_CONTROL, - HostCmd_ACT_GEN_SET, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + HostCmd_ACT_GEN_SET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); } LEAVE(); @@ -799,13 +1096,13 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int reassociation_on(wlan_private *priv) +static int +reassociation_on(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; ENTER(); - Adapter->Reassoc_on = TRUE; LEAVE(); @@ -818,16 +1115,16 @@ * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int reassociation_off(wlan_private *priv) +static int +reassociation_off(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; ENTER(); - - if (Adapter->TimerIsSet == TRUE) { + if (Adapter->ReassocTimerIsSet == TRUE) { CancelTimer(&Adapter->MrvDrvTimer); - Adapter->TimerIsSet = FALSE; + Adapter->ReassocTimerIsSet = FALSE; } Adapter->Reassoc_on = FALSE; @@ -837,7 +1134,6 @@ } #endif /* REASSOCIATION */ - /** * @brief Set Region * @@ -845,7 +1141,8 @@ * @param region_code region code * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_region(wlan_private *priv, u16 region_code) +static int +wlan_set_region(wlan_private * priv, u16 region_code) { int i; @@ -854,7 +1151,6 @@ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { // use the region code to search for the index if (region_code == RegionCodeToIndex[i]) { - priv->adapter->RegionTableIndex = (u16) i; priv->adapter->RegionCode = region_code; break; } @@ -876,7 +1172,6 @@ return WLAN_STATUS_SUCCESS; } - /** * @brief Copy Rates * @@ -885,7 +1180,8 @@ * @param len The len of Src Buf * @return Number of Rates copyed */ -static inline int CopyRates(u8 *dest, int pos, u8 *src, int len) +static inline int +CopyRates(u8 * dest, int pos, u8 * src, int len) { int i; @@ -905,7 +1201,8 @@ * @param rate The buf to return the active rates * @return The number of Rates */ -static int get_active_data_rates(wlan_adapter *Adapter, WLAN_802_11_RATES rates) +static int +get_active_data_rates(wlan_adapter * Adapter, WLAN_802_11_RATES rates) { int k = 0; @@ -915,13 +1212,11 @@ if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { //Infra. mode PRINTM(INFO, "Infra\n"); - k = CopyRates(rates, k, SupportedRates, - sizeof(SupportedRates)); + k = CopyRates(rates, k, SupportedRates, sizeof(SupportedRates)); } else { //ad-hoc mode PRINTM(INFO, "Adhoc G\n"); - k = CopyRates(rates, k, AdhocRates_G, - sizeof(AdhocRates_G)); + k = CopyRates(rates, k, AdhocRates_G, sizeof(AdhocRates_G)); } } else { k = CopyRates(rates, 0, Adapter->CurBssParams.DataRates, @@ -934,20 +1229,180 @@ } /** - * @brief Get/Set Firmware wakeup method + * @brief Get/Set Per packet TX Control flags * * @param priv A pointer to wlan_private structure * @param wrq A pointer to user data * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -static int wlan_txcontrol(wlan_private *priv, struct iwreq *wrq) +static int +wlan_txcontrol(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + int data[3]; + int ret; + + ENTER(); + + ret = WLAN_STATUS_SUCCESS; + + switch (wrq->u.data.length) { + case 0: + /* + * Get the Global setting for TxCtrl + */ + if (copy_to_user(wrq->u.data.pointer, + &Adapter->PktTxCtrl, sizeof(u32))) { + PRINTM(INFO, "copy_to_user failed!\n"); + ret = -EFAULT; + } else { + wrq->u.data.length = 1; + } + break; + + case 1: + /* + * Set the Global setting for TxCtrl + */ + if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + } else { + Adapter->PktTxCtrl = data[0]; + PRINTM(INFO, "PktTxCtrl set: 0x%08x\n", Adapter->PktTxCtrl); + } + break; + + case 2: + /* + * Get the per User Priority setting for TxCtrl for the given UP + */ + if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * 2)) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + + } else if (data[1] >= NELEMENTS(Adapter->wmm.userPriPktTxCtrl)) { + /* Range check the UP input from user space */ + PRINTM(INFO, "User priority out of range\n"); + ret = -EINVAL; + + } else if (Adapter->wmm.userPriPktTxCtrl[data[1]]) { + data[2] = Adapter->wmm.userPriPktTxCtrl[data[1]]; + + /* User priority setting is valid, return it */ + if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 3)) { + PRINTM(INFO, "copy_to_user failed!\n"); + ret = -EFAULT; + } else { + wrq->u.data.length = 3; + } + + } else { + /* Return the global setting since the UP set is zero */ + data[2] = Adapter->PktTxCtrl; + + if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 3)) { + PRINTM(INFO, "copy_to_user failed!\n"); + ret = -EFAULT; + } else { + wrq->u.data.length = 3; + } + } + break; + + case 3: + /* + * Set the per User Priority setting for TxCtrl for the given UP + */ + + if (copy_from_user(data, wrq->u.data.pointer, sizeof(int) * 3)) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + } else if (data[1] >= NELEMENTS(Adapter->wmm.userPriPktTxCtrl)) { + PRINTM(INFO, "User priority out of range\n"); + ret = -EINVAL; + } else { + Adapter->wmm.userPriPktTxCtrl[data[1]] = data[2]; + + if (Adapter->wmm.userPriPktTxCtrl[data[1]] == 0) { + /* Return the global setting since the UP set is zero */ + data[2] = Adapter->PktTxCtrl; + } + + if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 3)) { + PRINTM(INFO, "copy_to_user failed!\n"); + ret = -EFAULT; + } else { + wrq->u.data.length = 3; + } + } + break; + + default: + ret = -EINVAL; + break; + } + + LEAVE(); + return ret; +} + +/** + * @brief Enable/Disable atim uapsd null package generation + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to user data + * @return WLAN_STATUS_SUCCESS--success, otherwise fail + */ +static int +wlan_null_pkg_gen(wlan_private * priv, struct iwreq *wrq) +{ + int data; + wlan_adapter *Adapter = priv->adapter; + int *val; + + ENTER(); + + data = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + PRINTM(INFO, "Enable UAPSD NULL PKG: %s\n", + (data == CMD_ENABLED) ? "Enable" : "Disable"); + switch (data) { + case CMD_ENABLED: + Adapter->gen_null_pkg = TRUE; + break; + case CMD_DISABLED: + Adapter->gen_null_pkg = FALSE; + break; + default: + break; + } + + data = (Adapter->gen_null_pkg == TRUE) ? CMD_ENABLED : CMD_DISABLED; + val = (int *) wrq->u.name; + *val = data; + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get/Set NULL Package generation interval + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to user data + * @return WLAN_STATUS_SUCCESS--success, otherwise fail + */ +static int +wlan_null_pkt_interval(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; int data; ENTER(); if((int) wrq->u.data.length == 0) { - if(copy_to_user(wrq->u.data.pointer, &Adapter->PktTxCtrl, sizeof(u32))) { + data = Adapter->NullPktInterval; + + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { PRINTM(MSG, "copy_to_user failed!\n"); return -EFAULT; } @@ -961,7 +1416,7 @@ return -EFAULT; } - Adapter->PktTxCtrl = (u32)data; + Adapter->NullPktInterval = data; } wrq->u.data.length = 1; @@ -970,24 +1425,68 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief Get/Set Adhoc awake period + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_adhoc_awake_period(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + int data; + ENTER(); + if ((int) wrq->u.data.length == 0) { + data = Adapter->AdhocAwakePeriod; + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { + PRINTM(MSG, "copy_to_user failed!\n"); + return -EFAULT; + } + } else { + if ((int) wrq->u.data.length > 1) { + PRINTM(MSG, "ioctl too many args!\n"); + return -EFAULT; + } + if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } +#define AWAKE_PERIOD_MIN 1 +#define AWAKE_PERIOD_MAX 31 +#define DISABLE_AWAKE_PERIOD 0xff + if ((((data & 0xff) >= AWAKE_PERIOD_MIN) && + ((data & 0xff) <= AWAKE_PERIOD_MAX)) || + ((data & 0xff) == DISABLE_AWAKE_PERIOD)) + Adapter->AdhocAwakePeriod = (u16) data; + else { + PRINTM(INFO, + "Invalid parameter, AdhocAwakePeriod not changed.\n"); + return -EINVAL; + + } + } + wrq->u.data.length = 1; + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** - * @brief Get/Set NULL Package generation interval - * + * @brief Get/Set bcn missing timeout * @param priv A pointer to wlan_private structure - * @param wrq A pointer to user data + * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -static int wlan_null_pkt_interval(wlan_private *priv, struct iwreq *wrq) +static int +wlan_bcn_miss_timeout(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; int data; ENTER(); if((int) wrq->u.data.length == 0) { - data = Adapter->NullPktInterval; - + data = Adapter->BCNMissTimeOut; if(copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { PRINTM(MSG, "copy_to_user failed!\n"); return -EFAULT; @@ -1001,8 +1500,14 @@ PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } + if (((data >= 0) && (data <= 50)) || (data == 0xffff)) + Adapter->BCNMissTimeOut = (u16) data; + else { + PRINTM(INFO, + "Invalid parameter, BCN Missing timeout not changed.\n"); + return -EINVAL; - Adapter->NullPktInterval = data; + } } wrq->u.data.length = 1; @@ -1012,6 +1517,191 @@ } /** + * @brief Get/Set adhoc g proctection + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_adhoc_g_protection(wlan_private * priv, struct iwreq *wrq) +{ + int data; + int *val; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); +#define ADHOC_G_PROTECTION_ON 1 +#define ADHOC_G_PROTECTION_OFF 0 + data = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + + switch (data) { + case CMD_DISABLED: + Adapter->CurrentPacketFilter &= + ~HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; + break; + case CMD_ENABLED: + Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; + break; + + case CMD_GET: + if (Adapter-> + CurrentPacketFilter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON) + data = ADHOC_G_PROTECTION_ON; + else + data = ADHOC_G_PROTECTION_OFF; + break; + + default: + return -EINVAL; + } + + val = (int *) wrq->u.name; + *val = data; + + LEAVE(); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get/Set LDO config + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to wrq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_ldo_config(wlan_private * priv, struct iwreq *wrq) +{ + HostCmd_DS_802_11_LDO_CONFIG ldocfg; + int data = 0; + u16 action; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (wrq->u.data.length == 0) { + action = HostCmd_ACT_GEN_GET; + } else if (wrq->u.data.length > 1) { + PRINTM(MSG, "ioctl too many args!\n"); + ret = -EFAULT; + goto ldoexit; + } else { + if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + goto ldoexit; + } + if (data != LDO_INTERNAL && data != LDO_EXTERNAL) { + PRINTM(MSG, "Invalid parameter, LDO config not changed.\n"); + ret = -EFAULT; + goto ldoexit; + } + action = HostCmd_ACT_GEN_SET; + } + ldocfg.Action = action; + ldocfg.PMSource = (u16) data; + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_LDO_CONFIG, + action, HostCmd_OPTION_WAITFORRSP, + 0, (void *) &ldocfg); + + if (!ret && action == HostCmd_ACT_GEN_GET) { + data = (int) ldocfg.PMSource; + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { + PRINTM(INFO, "Copy to user failed\n"); + ret = -EFAULT; + goto ldoexit; + } + wrq->u.data.length = 1; + } + + ldoexit: + LEAVE(); + return ret; +} + +#ifdef DEBUG_LEVEL1 +/** + * @brief Get/Set the bit mask of driver debug message control + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to wrq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_drv_dbg(wlan_private * priv, struct iwreq *wrq) +{ + int data[4]; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (wrq->u.data.length == 0) { + data[0] = drvdbg; + data[1] = ifdbg; + /* Return the current driver debug bit masks */ + if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) { + PRINTM(INFO, "Copy to user failed\n"); + ret = -EFAULT; + goto drvdbgexit; + } + wrq->u.data.length = 2; + } else if (wrq->u.data.length < 3) { + /* Get the driver debug bit masks */ + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + goto drvdbgexit; + } + drvdbg = data[0]; + if (wrq->u.data.length == 2) + ifdbg = data[1]; + } else { + PRINTM(INFO, "Invalid parameter number\n"); + goto drvdbgexit; + } + + printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg); +#ifdef DEBUG_LEVEL2 + printk(KERN_ALERT "INFO (%08x) %s\n", DBG_INFO, + (drvdbg & DBG_INFO) ? "X" : ""); + printk(KERN_ALERT "WARN (%08x) %s\n", DBG_WARN, + (drvdbg & DBG_WARN) ? "X" : ""); + printk(KERN_ALERT "ENTRY (%08x) %s\n", DBG_ENTRY, + (drvdbg & DBG_ENTRY) ? "X" : ""); +#endif + printk(KERN_ALERT "FW_D (%08x) %s\n", DBG_FW_D, + (drvdbg & DBG_FW_D) ? "X" : ""); + printk(KERN_ALERT "CMD_D (%08x) %s\n", DBG_CMD_D, + (drvdbg & DBG_CMD_D) ? "X" : ""); + printk(KERN_ALERT "DAT_D (%08x) %s\n", DBG_DAT_D, + (drvdbg & DBG_DAT_D) ? "X" : ""); + printk(KERN_ALERT "INTR (%08x) %s\n", DBG_INTR, + (drvdbg & DBG_INTR) ? "X" : ""); + printk(KERN_ALERT "EVENT (%08x) %s\n", DBG_EVENT, + (drvdbg & DBG_EVENT) ? "X" : ""); + printk(KERN_ALERT "CMND (%08x) %s\n", DBG_CMND, + (drvdbg & DBG_CMND) ? "X" : ""); + printk(KERN_ALERT "DATA (%08x) %s\n", DBG_DATA, + (drvdbg & DBG_DATA) ? "X" : ""); + printk(KERN_ALERT "ERROR (%08x) %s\n", DBG_ERROR, + (drvdbg & DBG_ERROR) ? "X" : ""); + printk(KERN_ALERT "FATAL (%08x) %s\n", DBG_FATAL, + (drvdbg & DBG_FATAL) ? "X" : ""); + printk(KERN_ALERT "MSG (%08x) %s\n", DBG_MSG, + (drvdbg & DBG_MSG) ? "X" : ""); + printk(KERN_ALERT "ifdbg = 0x%x\n", ifdbg); + printk(KERN_ALERT "IF_D (%08x) %s\n", DBG_IF_D, + (ifdbg & DBG_IF_D) ? "X" : ""); + + drvdbgexit: + LEAVE(); + return ret; +} +#endif + +/** * @brief Commit handler: called after a bunch of SET operations * * @param dev A pointer to net_device structure @@ -1020,9 +1710,9 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_config_commit(struct net_device *dev, - struct iw_request_info *info, - char *cwrq, char *extra) +static int +wlan_config_commit(struct net_device *dev, + struct iw_request_info *info, char *cwrq, char *extra) { ENTER(); @@ -1039,7 +1729,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_name(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, char *extra) { const char *cp; @@ -1079,7 +1770,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1088,14 +1780,20 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } cfp = find_cfp_by_band_and_channel(Adapter, 0, - Adapter->CurBssParams.channel); + (u16) Adapter->CurBssParams. + BSSDescriptor.Channel); if (!cfp) { - if (Adapter->CurBssParams.channel) + if (Adapter->CurBssParams.BSSDescriptor.Channel) { PRINTM(INFO, "Invalid channel=%d\n", - Adapter->CurBssParams.channel); + Adapter->CurBssParams.BSSDescriptor.Channel); + } return -EINVAL; } @@ -1117,7 +1815,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra) { wlan_private *priv = dev->priv; @@ -1126,7 +1825,8 @@ ENTER(); if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { - memcpy(awrq->sa_data, Adapter->CurBssParams.bssid, ETH_ALEN); + memcpy(awrq->sa_data, + Adapter->CurBssParams.BSSDescriptor.MacAddress, ETH_ALEN); } else { memset(awrq->sa_data, 0, ETH_ALEN); } @@ -1145,7 +1845,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info, +static int +wlan_set_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1177,7 +1878,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1215,7 +1917,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info, +static int +wlan_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -1225,6 +1928,10 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } if (vwrq->disabled) { Adapter->RTSThsd = rthr = MRVDRV_RTS_MAX_VALUE; @@ -1251,7 +1958,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -1260,6 +1968,10 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } Adapter->RTSThsd = 0; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, @@ -1270,7 +1982,6 @@ return ret; } - vwrq->value = Adapter->RTSThsd; vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE) || (vwrq->value > MRVDRV_RTS_MAX_VALUE)); @@ -1289,7 +2000,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info, +static int +wlan_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -1299,6 +2011,10 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } if (vwrq->disabled) { Adapter->FragThsd = fthr = MRVDRV_FRAG_MAX_VALUE; @@ -1310,8 +2026,7 @@ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP, - OID_802_11_FRAGMENTATION_THRESHOLD, - &fthr); + OID_802_11_FRAGMENTATION_THRESHOLD, &fthr); LEAVE(); return ret; } @@ -1325,7 +2040,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -1334,12 +2050,16 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + Adapter->FragThsd = 0; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP, - OID_802_11_FRAGMENTATION_THRESHOLD, - NULL); + OID_802_11_FRAGMENTATION_THRESHOLD, NULL); if (ret) { LEAVE(); return ret; @@ -1363,7 +2083,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_mode(struct net_device *dev, +static int +wlan_get_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1399,7 +2120,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_encode(struct net_device *dev, +static int +wlan_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, u8 * extra) { @@ -1411,9 +2133,14 @@ ENTER(); PRINTM(INFO, "flags=0x%x index=%d length=%d CurrentWepKeyIndex=%d\n", - dwrq->flags, index, dwrq->length, - adapter->CurrentWepKeyIndex); - + dwrq->flags, index, dwrq->length, adapter->CurrentWepKeyIndex); + if (index < 0 || index > 4) { + PRINTM(INFO, "Key index #%d out of range.\n", index); + LEAVE(); + return -EINVAL; + } + if (adapter->CurrentWepKeyIndex >= MRVL_NUM_WEP_KEY) + adapter->CurrentWepKeyIndex = 0; dwrq->flags = 0; /* @@ -1436,9 +2163,7 @@ if ((adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) || (adapter->SecInfo.WEPStatus == Wlan802_11WEPKeyAbsent) - || adapter->SecInfo.WPAEnabled - || adapter->SecInfo.WPA2Enabled - ) { + || adapter->SecInfo.WPAEnabled || adapter->SecInfo.WPA2Enabled) { dwrq->flags &= ~IW_ENCODE_DISABLED; } else { dwrq->flags |= IW_ENCODE_DISABLED; @@ -1493,11 +2218,6 @@ extra[0], extra[1], extra[2], extra[3], extra[4], extra[5], dwrq->length); - if (adapter->EncryptionStatus == Wlan802_11Encryption2Enabled - && !dwrq->length) { - dwrq->length = MAX_KEY_SIZE; - } - PRINTM(INFO, "Return flags=0x%x\n", dwrq->flags); LEAVE(); @@ -1513,7 +2233,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_txpow(struct net_device *dev, +static int +wlan_get_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { @@ -1523,12 +2244,15 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_TX_POWER, - HostCmd_ACT_TX_POWER_OPT_GET, - HostCmd_OPTION_WAITFORRSP, - 0, NULL); + HostCmd_ACT_GEN_GET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { LEAVE(); @@ -1558,7 +2282,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info, +static int +wlan_set_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -1567,6 +2292,10 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } if (vwrq->flags == IW_RETRY_LIMIT) { /* The MAC has a 4-bit Total_Tx_Count register @@ -1576,13 +2305,13 @@ if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) return -EINVAL; - /* Adding 1 to convert retry count to try count */ - adapter->TxRetryCount = vwrq->value + 1; + /* Set Tx retry count */ + adapter->TxRetryCount = vwrq->value; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP, - OID_802_11_TX_RETRYCOUNT, - NULL); + HostCmd_ACT_SET, + HostCmd_OPTION_WAITFORRSP, + OID_802_11_TX_RETRYCOUNT, NULL); if (ret) { LEAVE(); @@ -1605,7 +2334,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1613,12 +2343,17 @@ int ret = WLAN_STATUS_SUCCESS; ENTER(); + + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + Adapter->TxRetryCount = 0; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP, - OID_802_11_TX_RETRYCOUNT, - NULL); + OID_802_11_TX_RETRYCOUNT, NULL); if (ret) { LEAVE(); return ret; @@ -1641,7 +2376,8 @@ * @param num number of Channels * @return NA */ -static inline void sort_channels(struct iw_freq *freq, int num) +static inline void +sort_channels(struct iw_freq *freq, int num) { int i, j; struct iw_freq temp; @@ -1680,7 +2416,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_range(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int i, j; @@ -1690,8 +2427,6 @@ CHANNEL_FREQ_POWER *cfp; WLAN_802_11_RATES rates; - BOOLEAN flag = FALSE; - ENTER(); dwrq->length = sizeof(struct iw_range); @@ -1702,12 +2437,16 @@ memset(rates, 0, sizeof(rates)); range->num_bitrates = get_active_data_rates(Adapter, rates); + if (range->num_bitrates > sizeof(rates)) + range->num_bitrates = sizeof(rates); - for (i=0; i < MIN(range->num_bitrates,IW_MAX_BITRATES) && rates[i]; i++) { + for (i = 0; i < MIN(range->num_bitrates, IW_MAX_BITRATES) && rates[i]; + i++) { range->bitrate[i] = (rates[i] & 0x7f) * 500000; } range->num_bitrates = i; - PRINTM(INFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n",IW_MAX_BITRATES,range->num_bitrates); + PRINTM(INFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES, + range->num_bitrates); range->num_frequency = 0; if( wlan_get_state_11d( priv) == ENABLE_11D && @@ -1715,15 +2454,12 @@ u8 chan_no; u8 band; - parsed_region_chan_11d_t *parsed_region_chan = &Adapter->parsed_region_chan; + parsed_region_chan_11d_t *parsed_region_chan = + &Adapter->parsed_region_chan; - if( parsed_region_chan == NULL ) { - PRINTM(INFO, "11D:parsed_region_chan is NULL\n"); - LEAVE(); - return 0; - } band = parsed_region_chan->band; - PRINTM(INFO, "band=%d NoOfChan=%d\n", band, parsed_region_chan->NoOfChan); + PRINTM(INFO, "band=%d NoOfChan=%d\n", band, + parsed_region_chan->NoOfChan); for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && (i < parsed_region_chan->NoOfChan); i++) { @@ -1735,22 +2471,17 @@ range->freq[range->num_frequency].e = 1; range->num_frequency++; } - flag = TRUE; - } - if ( !flag ) - { + } else { for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && (j < sizeof(Adapter->region_channel) - / sizeof(Adapter->region_channel[0])); - j++) { + / sizeof(Adapter->region_channel[0])); j++) { cfp = Adapter->region_channel[j].CFP; for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) && Adapter->region_channel[j].Valid - && cfp - && (i < Adapter->region_channel[j].NrCFP); - i++) { + && cfp && (i < Adapter->region_channel[j].NrCFP); i++) { range->freq[range->num_frequency].i = (long) cfp->Channel; - range->freq[range->num_frequency].m = (long) cfp->Freq * 100000; + range->freq[range->num_frequency].m = + (long) cfp->Freq * 100000; range->freq[range->num_frequency].e = 1; cfp++; range->num_frequency++; @@ -1758,8 +2489,8 @@ } } - PRINTM(INFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",IW_MAX_FREQUENCIES, - range->num_frequency); + PRINTM(INFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n", + IW_MAX_FREQUENCIES, range->num_frequency); range->num_channels = range->num_frequency; @@ -1784,10 +2515,16 @@ range->num_encoding_sizes = 2; range->max_encoding_tokens = 4; - range->min_pmp = 1000000; - range->max_pmp = 120000000; - range->min_pmt = 1000; - range->max_pmt = 1000000; +#define IW_POWER_PERIOD_MIN 1000000 /* 1 sec */ +#define IW_POWER_PERIOD_MAX 120000000 /* 2 min */ +#define IW_POWER_TIMEOUT_MIN 1000 /* 1 ms */ +#define IW_POWER_TIMEOUT_MAX 1000000 /* 1 sec */ + + /* Power Management duration & timeout */ + range->min_pmp = IW_POWER_PERIOD_MIN; + range->max_pmp = IW_POWER_PERIOD_MAX; + range->min_pmt = IW_POWER_TIMEOUT_MIN; + range->max_pmt = IW_POWER_TIMEOUT_MAX; range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; @@ -1814,27 +2551,25 @@ /* * need to put the right values here */ - range->max_qual.qual = 10; +#define IW_MAX_QUAL_PERCENT 100 +#define IW_AVG_QUAL_PERCENT 70 + range->max_qual.qual = IW_MAX_QUAL_PERCENT; range->max_qual.level = 0; range->max_qual.noise = 0; - range->sensitivity = 0; + range->avg_qual.qual = IW_AVG_QUAL_PERCENT; + range->avg_qual.level = 0; + range->avg_qual.noise = 0; + + range->sensitivity = 0; /* * Setup the supported power level ranges */ memset(range->txpower, 0, sizeof(range->txpower)); - range->txpower[0] = 5; - range->txpower[1] = 7; - range->txpower[2] = 9; - range->txpower[3] = 11; - range->txpower[4] = 13; - range->txpower[5] = 15; - range->txpower[6] = 17; - range->txpower[7] = 19; - - range->num_txpower = 8; - range->txpower_capa = IW_TXPOW_DBM; - range->txpower_capa |= IW_TXPOW_RANGE; + range->txpower[0] = Adapter->MinTxPowerLevel; + range->txpower[1] = Adapter->MaxTxPowerLevel; + range->num_txpower = 2; + range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE; LEAVE(); return WLAN_STATUS_SUCCESS; @@ -1849,7 +2584,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_power(struct net_device *dev, struct iw_request_info *info, +int +wlan_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1857,6 +2593,10 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } /* PS is currently supported only in Infrastructure Mode * Remove this check if it is to be supported in IBSS mode also @@ -1902,7 +2642,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_power(struct net_device *dev, struct iw_request_info *info, +static int +wlan_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { wlan_private *priv = dev->priv; @@ -1914,8 +2655,7 @@ mode = Adapter->PSMode; if ((vwrq->disabled = (mode == Wlan802_11PowerModeCAM)) - || Adapter->MediaConnectStatus == - WlanMediaStateDisconnected) { + || Adapter->MediaConnectStatus == WlanMediaStateDisconnected) { LEAVE(); return WLAN_STATUS_SUCCESS; } @@ -1935,7 +2675,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_sens(struct net_device *dev, struct iw_request_info *info, +static int +wlan_set_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { ENTER(); @@ -1952,7 +2693,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_FAILURE */ -static int wlan_get_sens(struct net_device *dev, +static int +wlan_get_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { @@ -1961,7 +2703,502 @@ return WLAN_STATUS_FAILURE; } +/** + * @brief Append/Reset IE buffer. + * + * Pass an opaque block of data, expected to be IEEE IEs, to the driver + * for eventual passthrough to the firmware in an associate/join + * (and potentially start) command. This function is the main body + * for both wlan_set_gen_ie_ioctl and wlan_set_gen_ie + * + * Data is appended to an existing buffer and then wrapped in a passthrough + * TLV in the command API to the firmware. The firmware treats the data + * as a transparent passthrough to the transmitted management frame. + * + * @param Adapter A pointer to wlan_private structure + * @param ie_data_ptr A pointer to iwreq structure + * @param ie_len Length of the IE or IE block passed in ie_data_ptr + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_gen_ie_helper(wlan_private * priv, u8 * ie_data_ptr, u16 ie_len) +{ + int ret = WLAN_STATUS_SUCCESS; + wlan_adapter *Adapter = priv->adapter; + IEEEtypes_VendorHeader_t *pVendorIe; + const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; + const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 }; + /* If the passed length is zero, reset the buffer */ + if (ie_len == 0) { + Adapter->genIeBufferLen = 0; + + } else if (ie_data_ptr == NULL) { + /* NULL check */ + ret = -EINVAL; + } else { + pVendorIe = (IEEEtypes_VendorHeader_t *) ie_data_ptr; + + /* Test to see if it is a WPA IE, if not, then it is a gen IE */ + if ((pVendorIe->ElementId == RSN_IE) + || ((pVendorIe->ElementId == WPA_IE) + && (pVendorIe->OuiType == wpa_oui[3]) + && (memcmp(pVendorIe->Oui, wpa_oui, sizeof(pVendorIe->Oui)) == + 0))) { + + /* IE is a WPA/WPA2 IE so call set_wpa function */ + ret = wlan_set_wpa_ie_helper(priv, ie_data_ptr, ie_len); + } else if ((pVendorIe->ElementId == WPS_IE) + && (memcmp(pVendorIe->Oui, wps_oui, sizeof(pVendorIe->Oui)) + == 0) + && (pVendorIe->OuiType == wps_oui[3])) { + /* + * Discard first two byte (Element ID and Length) + * because they are not needed in the case of setting WPS_IE + */ + if (pVendorIe->Len > 4) { + memcpy((u8 *) & Adapter->wps.wpsIe, ie_data_ptr, ie_len); + HEXDUMP("wpsIe", + (u8 *) & Adapter->wps.wpsIe, + Adapter->wps.wpsIe.VendHdr.Len + 2); + + } else { + /* Only wps oui exist, reset driver wps buffer */ + memset((u8 *) & Adapter->wps.wpsIe, + 0x00, sizeof(Adapter->wps.wpsIe)); + PRINTM(INFO, "wpsIe cleared\n"); + } + } else { + /* + * Verify that the passed length is not larger than the available + * space remaining in the buffer + */ + if (ie_len < (sizeof(Adapter->genIeBuffer) + - Adapter->genIeBufferLen)) { + + /* Append the passed data to the end of the genIeBuffer */ + if (copy_from_user((Adapter->genIeBuffer + + Adapter->genIeBufferLen), + ie_data_ptr, ie_len)) { + PRINTM(INFO, "Copy from user failed\n"); + ret = -EFAULT; + + } else { + /* Increment the stored buffer length by the size passed */ + Adapter->genIeBufferLen += ie_len; + } + + } else { + /* Passed data does not fit in the remaining buffer space */ + ret = WLAN_STATUS_FAILURE; + } + } + } + + /* Return WLAN_STATUS_SUCCESS, or < 0 for error case */ + return ret; +} + +/** + * @brief Get IE buffer from driver + * + * Used to pass an opaque block of data, expected to be IEEE IEs, + * back to the application. Currently the data block passed + * back to the application is the saved association response retrieved + * from the firmware. + * + * @param priv A pointer to wlan_private structure + * @param ie_data_ptr A pointer to the IE or IE block + * @param ie_len_ptr In/Out parameter pointer for the buffer length passed + * in ie_data_ptr and the resulting data length copied + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_get_gen_ie_helper(wlan_private * priv, + u8 * ie_data_ptr, u16 * ie_len_ptr) +{ + wlan_adapter *Adapter = priv->adapter; + IEEEtypes_AssocRsp_t *pAssocRsp; + int copySize; + + pAssocRsp = (IEEEtypes_AssocRsp_t *) Adapter->assocRspBuffer; + + /* + * Set the amount to copy back to the application as the minimum of the + * available IE data or the buffer provided by the application + */ + copySize = (Adapter->assocRspSize - sizeof(pAssocRsp->Capability) - + -sizeof(pAssocRsp->StatusCode) - sizeof(pAssocRsp->AId)); + copySize = MIN(copySize, *ie_len_ptr); + + /* Copy the IEEE TLVs in the assoc response back to the application */ + if (copy_to_user(ie_data_ptr, (u8 *) pAssocRsp->IEBuffer, copySize)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + + /* Returned copy length */ + *ie_len_ptr = copySize; + + /* No error on return */ + return WLAN_STATUS_SUCCESS; +} + +#if (WIRELESS_EXT >= 18) +/** + * @brief Set IE + * + * Calls main function set_gen_ie_fuct that adds the inputted IE + * to the genie buffer + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_gen_ie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + return wlan_set_gen_ie_helper(dev->priv, dwrq->pointer, dwrq->length); +} + +/** + * @brief Get IE + * + * Calls main function get_gen_ie_fuct that retrieves expected IEEE IEs + * and places then in the iw_point structure + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_get_gen_ie(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + return wlan_get_gen_ie_helper(dev->priv, dwrq->pointer, &dwrq->length); +} + +/** + * @brief Set authentication mode + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_setauthalg(wlan_private * priv, int alg) +{ + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + PRINTM(INFO, "auth alg is %#x\n", alg); + + switch (alg) { + case IW_AUTH_ALG_SHARED_KEY: + Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeShared; + break; + case IW_AUTH_ALG_LEAP: + //clear WPA IE + wlan_set_wpa_ie_helper(priv, NULL, 0); + Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeNetworkEAP; + break; + case IW_AUTH_ALG_OPEN_SYSTEM: + default: + Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen; + break; + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief set authentication mode params + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param vwrq A pointer to iw_param structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_auth(struct net_device *dev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + wlan_private *priv = dev->priv; + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + switch (vwrq->flags & IW_AUTH_INDEX) { + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + if (vwrq->value & IW_AUTH_CIPHER_NONE) + priv->adapter->SecInfo.EncryptionMode = CIPHER_NONE; + else if (vwrq->value & IW_AUTH_CIPHER_WEP40) + priv->adapter->SecInfo.EncryptionMode = CIPHER_WEP40; + else if (vwrq->value & IW_AUTH_CIPHER_TKIP) + priv->adapter->SecInfo.EncryptionMode = CIPHER_TKIP; + else if (vwrq->value & IW_AUTH_CIPHER_CCMP) + priv->adapter->SecInfo.EncryptionMode = CIPHER_CCMP; + else if (vwrq->value & IW_AUTH_CIPHER_WEP104) + priv->adapter->SecInfo.EncryptionMode = CIPHER_WEP104; + break; + case IW_AUTH_80211_AUTH_ALG: + wlan_setauthalg(priv, vwrq->value); + break; + case IW_AUTH_WPA_ENABLED: + if (vwrq->value == FALSE) + wlan_set_wpa_ie_helper(priv, NULL, 0); + break; + case IW_AUTH_WPA_VERSION: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + break; + } + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief get authentication mode params + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param vwrq A pointer to iw_param structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_get_auth(struct net_device *dev, struct iw_request_info *info, + struct iw_param *vwrq, char *extra) +{ + wlan_private *priv = dev->priv; + wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; + ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + switch (vwrq->flags & IW_AUTH_INDEX) { + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + if (priv->adapter->SecInfo.EncryptionMode == CIPHER_NONE) + vwrq->value = IW_AUTH_CIPHER_NONE; + else if (priv->adapter->SecInfo.EncryptionMode == CIPHER_WEP40) + vwrq->value = IW_AUTH_CIPHER_WEP40; + else if (priv->adapter->SecInfo.EncryptionMode == CIPHER_TKIP) + vwrq->value = IW_AUTH_CIPHER_TKIP; + else if (priv->adapter->SecInfo.EncryptionMode == CIPHER_CCMP) + vwrq->value = IW_AUTH_CIPHER_CCMP; + else if (priv->adapter->SecInfo.EncryptionMode == CIPHER_WEP104) + vwrq->value = IW_AUTH_CIPHER_WEP104; + break; + case IW_AUTH_80211_AUTH_ALG: + if (Adapter->SecInfo.AuthenticationMode == Wlan802_11AuthModeShared) + vwrq->value = IW_AUTH_ALG_SHARED_KEY; + else if (Adapter->SecInfo.AuthenticationMode == + Wlan802_11AuthModeNetworkEAP) + vwrq->value = IW_AUTH_ALG_LEAP; + else + vwrq->value = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case IW_AUTH_WPA_ENABLED: + if (Adapter->Wpa_ie_len > 0) + vwrq->value = TRUE; + else + vwrq->value = FALSE; + break; + case IW_AUTH_WPA_VERSION: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + ret = -EOPNOTSUPP; + break; + } + LEAVE(); + return ret; +} + +/** + * @brief Request MLME operation + * + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_mlme(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + struct iw_mlme *mlme = (struct iw_mlme *) extra; + wlan_private *priv = dev->priv; + wlan_adapter *Adapter = priv->adapter; + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + if ((mlme->cmd == IW_MLME_DEAUTH) || (mlme->cmd == IW_MLME_DISASSOC)) { + if (Adapter->InfrastructureMode == Wlan802_11Infrastructure && + Adapter->MediaConnectStatus == WlanMediaStateConnected) { + SendDeauthentication(priv); + } else if (Adapter->InfrastructureMode == Wlan802_11IBSS && + Adapter->MediaConnectStatus == WlanMediaStateConnected) { + StopAdhocNetwork(priv); + } + } + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Extended version of encoding configuration + * + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_encode_ext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; + wlan_private *priv = dev->priv; + WLAN_802_11_KEY *pkey; + int keyindex; + u8 *pKeyMaterial = NULL; + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + keyindex = dwrq->flags & IW_ENCODE_INDEX; + if (keyindex > 4) + return -EINVAL; + if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) + return -EINVAL; + pKeyMaterial = (u8 *) (ext + 1); + //Disable Key + if ((dwrq->flags & IW_ENCODE_DISABLED) && (ext->key_len == 0)) { + dwrq->length = 0; + wlan_set_encode_nonwpa(dev, info, dwrq, extra); + return WLAN_STATUS_SUCCESS; + } + //Set WEP key + if (ext->key_len <= MAX_WEP_KEY_SIZE) { + dwrq->length = ext->key_len; + wlan_set_encode_nonwpa(dev, info, dwrq, pKeyMaterial); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + dwrq->length = 0; + wlan_set_encode_nonwpa(dev, info, dwrq, extra); + } + } else { + pkey = kmalloc(sizeof(WLAN_802_11_KEY) + ext->key_len, GFP_KERNEL); + if (!pkey) { + PRINTM(INFO, "allocate key buffer failed!\n"); + return -ENOMEM; + } + memset(pkey, 0, sizeof(WLAN_802_11_KEY) + ext->key_len); + memcpy((u8 *) pkey->BSSID, (u8 *) ext->addr.sa_data, ETH_ALEN); + pkey->KeyLength = ext->key_len; + memcpy(pkey->KeyMaterial, pKeyMaterial, ext->key_len); + pkey->KeyIndex = keyindex - 1; + if (pkey->KeyIndex == 0) + pkey->KeyIndex = 0x40000000; + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) + memcpy((u8 *) & pkey->KeyRSC, ext->rx_seq, + IW_ENCODE_SEQ_MAX_SIZE); + pkey->Length = sizeof(WLAN_802_11_KEY) + ext->key_len; + wlan_set_encode_wpa(dev, info, dwrq, (u8 *) pkey); + kfree(pkey); + } + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Extended version of encoding configuration + * + * + * @param dev A pointer to net_device structure + * @param info A pointer to iw_request_info structure + * @param dwrq A pointer to iw_point structure + * @param extra A pointer to extra data buf + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_get_encode_ext(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, char *extra) +{ + return -EOPNOTSUPP; +} +#endif /* #if (WIRELESS_EXT >= 18) */ + +/** + * @brief Append/Reset IE buffer. + * + * Pass an opaque block of data, expected to be IEEE IEs, to the driver + * for eventual passthrough to the firmware in an associate/join + * (and potentially start) command. + * + * Data is appended to an existing buffer and then wrapped in a passthrough + * TLV in the command API to the firmware. The firmware treats the data + * as a transparent passthrough to the transmitted management frame. + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_set_gen_ie_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + return wlan_set_gen_ie_helper(priv, + wrq->u.data.pointer, wrq->u.data.length); +} + +/** + * @brief Get IE buffer from driver + * + * Used to pass an opaque block of data, expected to be IEEE IEs, + * back to the application. Currently the data block passed + * back to the application is the saved association response retrieved + * from the firmware. + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_get_gen_ie_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + return wlan_get_gen_ie_helper(priv, + wrq->u.data.pointer, &wrq->u.data.length); +} /* * iwconfig settable callbacks @@ -2001,7 +3238,11 @@ #endif /* WIRELESS_EXT > 15 */ (iw_handler) wlan_set_wap, /* SIOCSIWAP */ (iw_handler) wlan_get_wap, /* SIOCGIWAP */ +#if WIRELESS_EXT >= 18 + (iw_handler) wlan_set_mlme, /* SIOCSIWMLME */ +#else (iw_handler) NULL, /* -- hole -- */ +#endif //(iw_handler) wlan_get_aplist, /* SIOCGIWAPLIST */ NULL, /* SIOCGIWAPLIST */ #if WIRELESS_EXT > 13 @@ -2034,8 +3275,12 @@ #if (WIRELESS_EXT >= 18) (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ + (iw_handler) wlan_set_gen_ie, /* SIOCSIWGENIE */ + (iw_handler) wlan_get_gen_ie, /* SIOCGIWGENIE */ + (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */ + (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */ + (iw_handler) wlan_set_encode_ext, /* SIOCSIWENCODEEXT */ + (iw_handler) wlan_get_encode_ext, /* SIOCGIWENCODEEXT */ #endif /* WIRELESSS_EXT >= 18 */ }; @@ -2055,110 +3300,168 @@ WLANEXTSCAN, IW_PRIV_TYPE_INT, IW_PRIV_TYPE_CHAR | 2, - "extscan" - }, - + "extscan"}, + { + WLANHOSTCMD, + IW_PRIV_TYPE_BYTE | 2047, + IW_PRIV_TYPE_BYTE | 2047, + "hostcmd"}, + { + WLANARPFILTER, + IW_PRIV_TYPE_BYTE | 2047, + IW_PRIV_TYPE_BYTE | 2047, + "arpfilter"}, + { + WLANREGRDWR, + IW_PRIV_TYPE_CHAR | 256, + IW_PRIV_TYPE_CHAR | 256, + "regrdwr"}, + { + WLANCMD52RDWR, + IW_PRIV_TYPE_BYTE | 7, + IW_PRIV_TYPE_BYTE | 7, + "sdcmd52rw"}, + { + WLANCMD53RDWR, + IW_PRIV_TYPE_CHAR | 32, + IW_PRIV_TYPE_CHAR | 32, + "sdcmd53rw"}, + { + WLAN_SETCONF_GETCONF, + IW_PRIV_TYPE_BYTE | MAX_SETGET_CONF_SIZE, + IW_PRIV_TYPE_BYTE | MAX_SETGET_CONF_SIZE, + "setgetconf"}, { WLANCISDUMP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_BYTE | 512, - "getcis" - }, - + "getcis"}, { WLANSCAN_TYPE, IW_PRIV_TYPE_CHAR | 8, IW_PRIV_TYPE_CHAR | 8, - "scantype" - }, - + "scantype"}, { WLAN_SETINT_GETINT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "" - }, + ""}, { WLANNF, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getNF" - }, + "getNF"}, { WLANRSSI, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getRSSI" - }, + "getRSSI"}, + { + WLANBGSCAN, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "bgscan"}, { WLANENABLE11D, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "enable11d" - }, + "enable11d"}, { WLANADHOCGRATE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "adhocgrate" - }, - + "adhocgrate"}, { - WLAN_SUBCMD_SET_PRESCAN, + WLANSDIOCLOCK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "prescan" - }, + "sdioclock"}, + { + WLANWMM_ENABLE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "wmm"}, + { + WLANNULLGEN, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "uapsdnullgen"}, + { + WLANADHOCCSET, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "setcoalescing"}, + { + WLAN_ADHOC_G_PROT, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "adhocgprot"}, { WLAN_SETONEINT_GETONEINT, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, - "" - }, + ""}, { - WLAN_BEACON_INTERVAL, + WLAN_WMM_QOSINFO, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, - "bcninterval" - }, + "wmm_qosinfo"}, { WLAN_LISTENINTRVL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, - "lolisteninter" - }, + "lolisteninter"}, { - WLAN_TXCONTROL, + WLAN_FW_WAKEUP_METHOD, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, - "txcontrol" - }, + "fwwakeupmethod"}, { WLAN_NULLPKTINTERVAL, IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_INT | 1, - "psnullinterval" - }, + "psnullinterval"}, + { + WLAN_BCN_MISS_TIMEOUT, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_INT | 1, + "bcnmisto"}, + { + WLAN_ADHOC_AWAKE_PERIOD, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_INT | 1, + "adhocawakepd"}, + { + WLAN_LDO, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_INT | 1, + "ldocfg"}, + { + WLAN_AUTODEEPSLEEP, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_INT | 1, + "autodeepsleep"}, + { + WLAN_WAKEUP_MT, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_INT | 1, + "wakeupmt"}, /* Using iwpriv sub-command feature */ { - WLAN_SETONEINT_GETNONE, /* IOCTL: 24 */ + WLAN_SETONEINT_GETNONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "" - }, - + ""}, { WLAN_SUBCMD_SETRXANTENNA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setrxant" - }, + "setrxant"}, { WLAN_SUBCMD_SETTXANTENNA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "settxant" - }, + "settxant"}, { WLANSETAUTHALG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -2166,12 +3469,6 @@ "authalgs", }, { - WLANSET8021XAUTHALG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "8021xauthalgs", - }, - { WLANSETENCRYPTIONMODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, @@ -2181,407 +3478,389 @@ WLANSETREGION, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setregioncode" - }, + "setregioncode"}, { WLAN_SET_LISTEN_INTERVAL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setlisteninter" - }, + "setlisteninter"}, { WLAN_SET_MULTIPLE_DTIM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setmultipledtim" - }, - { - WLAN_SET_ATIM_WINDOW, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "atimwindow" - }, + "setmultipledtim"}, { WLANSETBCNAVG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setbcnavg" - }, + "setbcnavg"}, { WLANSETDATAAVG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "setdataavg" - }, - { - WLAN_SET_LINKMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "linkmode" - }, - { - WLAN_SET_RADIOMODE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, - "radiomode" - }, + "setdataavg"}, { - WLAN_SET_DEBUGMODE, + WLANASSOCIATE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, - "debugmode" - }, + "associate"}, { WLAN_SETNONE_GETONEINT, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "" - }, + ""}, { WLANGETREGION, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getregioncode" - }, + "getregioncode"}, { WLAN_GET_LISTEN_INTERVAL, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getlisteninter" - }, + "getlisteninter"}, { WLAN_GET_MULTIPLE_DTIM, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getmultipledtim" - }, + "getmultipledtim"}, { WLAN_GET_TX_RATE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "gettxrate" - }, + "gettxrate"}, { WLANGETBCNAVG, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getbcnavg" - }, - { - WLAN_GET_LINKMODE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_linkmode" - }, - { - WLAN_GET_RADIOMODE, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_radiomode" - }, + "getbcnavg"}, { - WLAN_GET_DEBUGMODE, + WLANGETDATAAVG, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_debugmode" - }, + "getdataavg"}, { WLAN_SETNONE_GETTWELVE_CHAR, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12, - "" - }, + ""}, { WLAN_SUBCMD_GETRXANTENNA, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12, - "getrxant" - }, + "getrxant"}, { WLAN_SUBCMD_GETTXANTENNA, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12, - "gettxant" - }, + "gettxant"}, { WLAN_GET_TSF, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | 12, - "gettsf" - }, + "gettsf"}, + { + WLAN_WPS_SESSION, + IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_CHAR | 12, + "wpssession"}, + { + WLANDEEPSLEEP, + IW_PRIV_TYPE_CHAR | 1, + IW_PRIV_TYPE_CHAR | 6, + "deepsleep"}, + { + WLANHOSTSLEEPCFG, + IW_PRIV_TYPE_CHAR | 31, + IW_PRIV_TYPE_NONE, + "hostsleepcfg"}, { WLAN_SETNONE_GETNONE, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "" - }, + ""}, { WLANDEAUTH, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "deauth" - }, + "deauth"}, { WLANADHOCSTOP, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "adhocstop" - }, + "adhocstop"}, { WLANRADIOON, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "radioon" - }, + "radioon"}, { WLANRADIOOFF, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "radiooff" - }, + "radiooff"}, + { + WLANREMOVEADHOCAES, + IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_NONE, + "rmaeskey"}, #ifdef REASSOCIATION { WLANREASSOCIATIONAUTO, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "reasso-on" - }, + "reasso-on"}, { WLANREASSOCIATIONUSER, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "reasso-off" - }, + "reasso-off"}, #endif /* REASSOCIATION */ { WLANWLANIDLEON, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "wlanidle-on" - }, + "wlanidle-on"}, { WLANWLANIDLEOFF, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_NONE, - "wlanidle-off" - }, - { - WLAN_SUBCMD_DFT_RESET, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "dft_reset" - }, - { - WLAN_SUBCMD_BT_RESET, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_NONE, - "bt_reset" - }, + "wlanidle-off"}, { WLAN_SET64CHAR_GET64CHAR, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "" - }, + ""}, { WLANSLEEPPARAMS, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "sleepparams" - }, + "sleepparams"}, - /* DFT Management */ { - WLAN_SUBCMD_DFT_ADD, - IW_PRIV_TYPE_CHAR | 64, - IW_PRIV_TYPE_CHAR | 64, - "dft_add" - }, - { - WLAN_SUBCMD_DFT_DEL, - IW_PRIV_TYPE_CHAR | 64, - IW_PRIV_TYPE_CHAR | 64, - "dft_del" - }, - { - WLAN_SUBCMD_DFT_LIST, + WLAN_BCA_TIMESHARE, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "dft_list" - }, - /* BT Management */ + "bca-ts"}, { - WLAN_SUBCMD_BT_ADD, + WLANSCAN_MODE, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "bt_add" - }, + "scanmode"}, { - WLAN_SUBCMD_BT_DEL, + WLAN_GET_ADHOC_STATUS, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "bt_del" - }, + "getadhocstatus"}, { - WLAN_SUBCMD_BT_LIST, + WLAN_SET_GEN_IE, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "bt_list" - }, + "setgenie"}, { - WLANSCAN_MODE, + WLAN_GET_GEN_IE, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "scanmode" - }, + "getgenie"}, { - WLAN_GET_ADHOC_STATUS, + WLAN_WMM_QUEUE_STATUS, IW_PRIV_TYPE_CHAR | 64, IW_PRIV_TYPE_CHAR | 64, - "getadhocstatus" - }, + "qstatus"}, { WLAN_SETWORDCHAR_GETNONE, IW_PRIV_TYPE_CHAR | 32, IW_PRIV_TYPE_NONE, - "" - }, + ""}, { - WLAN_SETNONE_GETWORDCHAR, + WLANSETADHOCAES, + IW_PRIV_TYPE_CHAR | 32, IW_PRIV_TYPE_NONE, + "setaeskey"}, + { + WLAN_SETONEINT_GETWORDCHAR, + IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128, - "" - }, + ""}, + { + WLANGETADHOCAES, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_CHAR | 128, + "getaeskey"}, { WLANVERSION, - IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_INT | 1, IW_PRIV_TYPE_CHAR | 128, - "version" - }, + "version"}, + { + WLANVEREXT, + IW_PRIV_TYPE_INT | 1, + IW_PRIV_TYPE_CHAR | 128, + "verext"}, { WLANSETWPAIE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 24, IW_PRIV_TYPE_NONE, - "setwpaie" - }, - { - WLAN_SETTENCHAR_GETNONE, - IW_PRIV_TYPE_CHAR | 10, - IW_PRIV_TYPE_NONE, - "" - }, - { - WLAN_SETNONE_GETTENCHAR, - IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_CHAR | 10, - "" - }, + "setwpaie"}, { WLANGETLOG, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE, - "getlog" - }, + "getlog"}, { WLAN_SET_GET_SIXTEEN_INT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "" - }, + ""}, { WLAN_TPCCFG, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "tpccfg" - }, - { - WLAN_POWERCFG, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "powercfg" - }, - { - WLAN_AUTO_FREQ_SET, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "setafc" - }, - { - WLAN_AUTO_FREQ_GET, - IW_PRIV_TYPE_INT | 16, - IW_PRIV_TYPE_INT | 16, - "getafc" - }, + "tpccfg"}, { WLAN_SCANPROBES, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "scanprobes" - }, + "scanprobes"}, { WLAN_LED_GPIO_CTRL, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "ledgpio" - }, + "ledgpio"}, { WLAN_SLEEP_PERIOD, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "sleeppd" - }, + "sleeppd"}, { WLAN_ADAPT_RATESET, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "rateadapt" - }, + "rateadapt"}, { WLAN_INACTIVITY_TIMEOUT, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "inactivityto" - }, + "inactivityto"}, { WLANSNR, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "getSNR" - }, + "getSNR"}, { WLAN_GET_RATE, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "getrate" - }, + "getrate"}, { WLAN_GET_RXINFO, IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, - "getrxinfo" - }, + "getrxinfo"}, + { + WLAN_SET_ATIM_WINDOW, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "atimwindow"}, + { + WLAN_BEACON_INTERVAL, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "bcninterval"}, + { + WLAN_SDIO_PULL_CTRL, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "sdiopullctrl"}, + { + WLAN_SCAN_TIME, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "scantime"}, + { + WLAN_DATA_SUBSCRIBE_EVENT, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "dataevtcfg"}, + { + WLAN_TXCONTROL, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "txcontrol"}, + { + WLANHSCFG, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "hscfg"}, + { + WLANHSSETPARA, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "hssetpara"}, +#ifdef DEBUG_LEVEL1 + { + WLAN_DRV_DBG, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "drvdbg"}, +#endif { - WLAN_SET_GET_2K, /* IOCTL : 14 */ + WLAN_SET_GET_2K, IW_PRIV_TYPE_BYTE | 2000, IW_PRIV_TYPE_BYTE | 2000, - "" - }, - + ""}, { WLAN_SET_USER_SCAN, IW_PRIV_TYPE_BYTE | 2000, IW_PRIV_TYPE_BYTE | 2000, - "setuserscan" - }, + "setuserscan"}, { WLAN_GET_SCAN_TABLE, IW_PRIV_TYPE_BYTE | 2000, IW_PRIV_TYPE_BYTE | 2000, - "getscantable" - }, - + "getscantable"}, + { + WLAN_SET_MRVL_TLV, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "setmrvltlv"}, + { + WLAN_GET_ASSOC_RSP, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "getassocrsp"}, + { + WLAN_ADDTS_REQ, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "addts"}, + { + WLAN_DELTS_REQ, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "delts"}, + { + WLAN_QUEUE_CONFIG, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "qconfig"}, + { + WLAN_QUEUE_STATS, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "qstats"}, + { + WLAN_TX_PKT_STATS, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "txpktstats"}, + { + WLAN_GET_CFP_TABLE, + IW_PRIV_TYPE_BYTE | 2000, + IW_PRIV_TYPE_BYTE | 2000, + "getcfptable"}, }; struct iw_handler_def wlan_handler_def = { @@ -2602,17 +3881,26 @@ * @param cmd command * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_hostcmd_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +static int +wlan_hostcmd_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { u8 *tempResponseBuffer; CmdCtrlNode *pCmdNode; - HostCmd_DS_GEN *gencmd, *pCmdPtr; + HostCmd_DS_GEN *pCmdPtr; wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; u16 wait_option = 0; + struct iwreq *wrq = (struct iwreq *) req; ENTER(); + if ((wrq->u.data.pointer == NULL) || (wrq->u.data.length < S_DS_GEN)) { + PRINTM(INFO, + "wlan_hostcmd_ioctl() corrupt data: pointer=%p, length=%d\n", + wrq->u.data.pointer, wrq->u.data.length); + return -EFAULT; + } + /* * Get a free command control node */ @@ -2621,8 +3909,11 @@ return -ENOMEM; } - if (!(tempResponseBuffer = kmalloc(3000, GFP_KERNEL))) { + if (! + (tempResponseBuffer = + kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) { PRINTM(INFO, "ERROR: Failed to allocate response buffer!\n"); + CleanupAndInsertCmd(priv, pCmdNode); return -ENOMEM; } @@ -2632,30 +3923,39 @@ init_waitqueue_head(&pCmdNode->cmdwait_q); pCmdPtr = (HostCmd_DS_GEN *) pCmdNode->BufVirtualAddr; - gencmd = (HostCmd_DS_GEN *) req->ifr_data; /* * Copy the whole command into the command buffer */ - if (copy_from_user(pCmdPtr, req->ifr_data, gencmd->Size)) { + if (copy_from_user(pCmdPtr, wrq->u.data.pointer, wrq->u.data.length)) { PRINTM(INFO, "Copy from user failed\n"); kfree(tempResponseBuffer); + CleanupAndInsertCmd(priv, pCmdNode); + return -EFAULT; + } + + if (pCmdPtr->Size < S_DS_GEN) { + PRINTM(INFO, "wlan_hostcmd_ioctl() invalid cmd size: Size=%d\n", + pCmdPtr->Size); + kfree(tempResponseBuffer); + CleanupAndInsertCmd(priv, pCmdNode); return -EFAULT; } pCmdNode->pdata_buf = tempResponseBuffer; pCmdNode->CmdFlags |= CMD_F_HOSTCMD; - pCmdPtr->SeqNum = ++priv->adapter->SeqNum; pCmdPtr->Result = 0; - PRINTM(INFO, "HOSTCMD Command: 0x%04x Size: %d SeqNum: %d\n", - pCmdPtr->Command, pCmdPtr->Size, pCmdPtr->SeqNum); + PRINTM(INFO, "HOSTCMD Command: 0x%04x Size: %d\n", + pCmdPtr->Command, pCmdPtr->Size); HEXDUMP("Command Data", (u8 *) (pCmdPtr), MIN(32, pCmdPtr->Size)); PRINTM(INFO, "Copying data from : (user)0x%p -> 0x%p(driver)\n", req->ifr_data, pCmdPtr); pCmdNode->CmdWaitQWoken = FALSE; + pCmdPtr->Command = wlan_cpu_to_le16(pCmdPtr->Command); + pCmdPtr->Size = wlan_cpu_to_le16(pCmdPtr->Size); QueueCmd(Adapter, pCmdNode, TRUE); wake_up_interruptible(&priv->MainThread.waitQ); @@ -2668,9 +3968,9 @@ /* Copy the response back to user space */ pCmdPtr = (HostCmd_DS_GEN *) tempResponseBuffer; - if (copy_to_user(req->ifr_data, tempResponseBuffer, pCmdPtr->Size)) + if (copy_to_user(wrq->u.data.pointer, tempResponseBuffer, pCmdPtr->Size)) PRINTM(INFO, "ERROR: copy_to_user failed!\n"); - + wrq->u.data.length = pCmdPtr->Size; kfree(tempResponseBuffer); LEAVE(); @@ -2678,13 +3978,68 @@ } /** + * @brief wlan arpfilter ioctl handler + * + * @param dev A pointer to net_device structure + * @param req A pointer to ifreq structure + * @param cmd command + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_arpfilter_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +{ + wlan_private *priv = dev->priv; + struct iwreq *wrq = (struct iwreq *) req; + wlan_adapter *Adapter = priv->adapter; + MrvlIEtypesHeader_t hdr; + + ENTER(); + + if ((wrq->u.data.pointer == NULL) + || (wrq->u.data.length < sizeof(MrvlIEtypesHeader_t)) + || (wrq->u.data.length > sizeof(Adapter->ArpFilter))) { + PRINTM(INFO, + "wlan_arpfilter_ioctl() corrupt data: pointer=%p, length=%d\n", + wrq->u.data.pointer, wrq->u.data.length); + return -EFAULT; + } + + if (copy_from_user(&hdr, wrq->u.data.pointer, sizeof(hdr))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + if (hdr.Len == 0) { + Adapter->ArpFilterSize = 0; + memset(Adapter->ArpFilter, 0, sizeof(Adapter->ArpFilter)); + } else { + Adapter->ArpFilterSize = wrq->u.data.length; + + PRINTM(INFO, "Copying data from : (user)0x%p -> 0x%p(driver)\n", + wrq->u.data.pointer, Adapter->ArpFilter); + if (copy_from_user(Adapter->ArpFilter, wrq->u.data.pointer, + Adapter->ArpFilterSize)) { + Adapter->ArpFilterSize = 0; + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + HEXDUMP("ArpFilter", Adapter->ArpFilter, Adapter->ArpFilterSize); + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** * @brief Get Rx Info * * @param priv A pointer to wlan_private structure * @param wreq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success */ -static int wlan_get_rxinfo(wlan_private *priv, struct iwreq *wrq) +static int +wlan_get_rxinfo(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; int data[2]; @@ -2707,7 +4062,8 @@ * @param wreq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_snr(wlan_private *priv, struct iwreq *wrq) +static int +wlan_get_snr(wlan_private * priv, struct iwreq *wrq) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -2716,31 +4072,33 @@ ENTER(); memset(data,0,sizeof(data)); if(wrq->u.data.length) { - if (copy_from_user(data,wrq->u.data.pointer,MIN(wrq->u.data.length,4) * sizeof(int))) { + if (copy_from_user + (data, wrq->u.data.pointer, + MIN(wrq->u.data.length, 4) * sizeof(int))) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } } - if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) - { + if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) { if (Adapter->MediaConnectStatus == WlanMediaStateConnected){ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RSSI, 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); - if (ret) - { + if (ret) { LEAVE(); return ret; } } } - if (wrq->u.data.length == 0) - { + if (wrq->u.data.length == 0) { data[0] = Adapter->SNR[TYPE_BEACON][TYPE_NOAVG]; data[1] = Adapter->SNR[TYPE_BEACON][TYPE_AVG]; + if ((jiffies - Adapter->RxPDAge) > HZ) //data expired after 1 second + data[2] = 0; + else data[2] = Adapter->SNR[TYPE_RXPD][TYPE_NOAVG]; data[3] = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; if (copy_to_user(wrq->u.data.pointer,data,sizeof(int) * 4)) { @@ -2748,52 +4106,156 @@ return -EFAULT; } wrq->u.data.length = 4; - } - else if (data[0] == 0) - { + } else if (data[0] == 0) { data[0] = Adapter->SNR[TYPE_BEACON][TYPE_NOAVG]; if (copy_to_user(wrq->u.data.pointer,data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } wrq->u.data.length = 1; - } - else if (data[0] == 1) - { + } else if (data[0] == 1) { data[0] = Adapter->SNR[TYPE_BEACON][TYPE_AVG]; if (copy_to_user(wrq->u.data.pointer,data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } wrq->u.data.length = 1; - } - else if (data[0] == 2) - { + } else if (data[0] == 2) { + if ((jiffies - Adapter->RxPDAge) > HZ) //data expired after 1 second + data[0] = 0; + else data[0] = Adapter->SNR[TYPE_RXPD][TYPE_NOAVG]; if (copy_to_user(wrq->u.data.pointer,data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } wrq->u.data.length = 1; - } - else if (data[0] == 3) - { + } else if (data[0] == 3) { data[0] = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; if (copy_to_user(wrq->u.data.pointer,data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } wrq->u.data.length = 1; + } else { + return -ENOTSUPP; } - else + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get/Set SDIO PULL CTRL + * + * @param priv A pointer to wlan_private structure + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_sdio_pull_ctrl(wlan_private * priv, struct iwreq *wrq) { - return -ENOTSUPP; + int data[2]; + HostCmd_DS_SDIO_PULL_CTRL sdio_pull_ctrl; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + memset(&sdio_pull_ctrl, 0, sizeof(sdio_pull_ctrl)); + if (wrq->u.data.length > 0) { + if (copy_from_user(data, wrq->u.data.pointer, sizeof(data))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + PRINTM(INFO, "WLAN SET SDIO PULL CTRL: %d %d\n", data[0], data[1]); + sdio_pull_ctrl.Action = HostCmd_ACT_GEN_SET; + sdio_pull_ctrl.PullUp = data[0]; + sdio_pull_ctrl.PullDown = data[1]; + } else { + sdio_pull_ctrl.Action = HostCmd_ACT_GEN_GET; } + ret = PrepareAndSendCommand(priv, HostCmd_CMD_SDIO_PULL_CTRL, + 0, HostCmd_OPTION_WAITFORRSP, + 0, (void *) &sdio_pull_ctrl); + data[0] = sdio_pull_ctrl.PullUp; + data[1] = sdio_pull_ctrl.PullDown; + wrq->u.data.length = 2; + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } LEAVE(); return WLAN_STATUS_SUCCESS; } +/** + * @brief Get/Set scan time + * + * @param priv A pointer to wlan_private structure + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_scan_time(wlan_private * priv, struct iwreq *wrq) +{ + int data[3] = { 0, 0, 0 }; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + if (wrq->u.data.length > 0 && wrq->u.data.length <= 3) { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + PRINTM(INFO, + "WLAN SET Scan Time: Specific %d, Active %d, Passive %d\n", + data[0], data[1], data[2]); + if (data[0]) { + if (data[0] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME) { + PRINTM(MSG, + "Invalid parameter, max specific scan time is %d ms\n", + MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME); + return -EINVAL; + } + Adapter->SpecificScanTime = data[0]; + } + if (data[1]) { + if (data[1] > MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME) { + PRINTM(MSG, + "Invalid parameter, max active scan time is %d ms\n", + MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME); + return -EINVAL; + } + Adapter->ActiveScanTime = data[1]; + } + if (data[2]) { + if (data[2] > MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME) { + PRINTM(MSG, + "Invalid parameter, max passive scan time is %d ms\n", + MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME); + return -EINVAL; + } + Adapter->PassiveScanTime = data[2]; + } + } + + data[0] = Adapter->SpecificScanTime; + data[1] = Adapter->ActiveScanTime; + data[2] = Adapter->PassiveScanTime; + wrq->u.data.length = 3; + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief Get/Set Adhoc beacon Interval @@ -2802,32 +4264,131 @@ * @param wreq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_beacon_interval(wlan_private *priv, struct iwreq *wrq) +static int +wlan_beacon_interval(wlan_private * priv, struct iwreq *wrq) { - int data; + int data[2]; wlan_adapter *Adapter = priv->adapter; ENTER(); if ( wrq->u.data.length > 0 ) { - if (copy_from_user(&data,wrq->u.data.pointer,sizeof(int))) { + if (copy_from_user(data, wrq->u.data.pointer, sizeof(int))) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } - PRINTM(INFO, "WLAN SET BEACON INTERVAL: %d\n", data); - if((data > MRVDRV_MAX_BEACON_INTERVAL) || (data < MRVDRV_MIN_BEACON_INTERVAL)) + PRINTM(INFO, "WLAN SET BEACON INTERVAL: %d\n", data[0]); + if ((data[0] > MRVDRV_MAX_BEACON_INTERVAL) || + (data[0] < MRVDRV_MIN_BEACON_INTERVAL)) return -ENOTSUPP; - Adapter->BeaconPeriod = data; + Adapter->BeaconPeriod = data[0]; } - data = Adapter->BeaconPeriod; - if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { + data[0] = Adapter->BeaconPeriod; + wrq->u.data.length = 1; + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + data[1] = Adapter->CurBssParams.BSSDescriptor.BeaconPeriod; + wrq->u.data.length = 2; + } + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } + LEAVE(); + return WLAN_STATUS_SUCCESS; +} +/** + * @brief Get/Set Adhoc ATIM Window + * + * @param priv A pointer to wlan_private structure + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_ATIM_Window(wlan_private * priv, struct iwreq *wrq) +{ + int data[2]; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + if (wrq->u.data.length > 0) { + if (copy_from_user(data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + PRINTM(INFO, "WLAN SET ATIM WINDOW: %d\n", data[0]); + Adapter->AtimWindow = data[0]; + Adapter->AtimWindow = MIN(Adapter->AtimWindow, 50); + } + data[0] = Adapter->AtimWindow; wrq->u.data.length = 1; + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + data[1] = Adapter->CurBssParams.BSSDescriptor.ATIMWindow; + wrq->u.data.length = 2; + } + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get/Set data subscribe event + * + * @param priv A pointer to wlan_private structure + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_data_subscribe_event(wlan_private * priv, struct iwreq *wrq) +{ + int data[9]; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + memset(data, 0, sizeof(data)); + if (wrq->u.data.length > 9) + return -EFAULT; + if (wrq->u.data.length > 0) { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + memset(&Adapter->subevent, 0, sizeof(Adapter->subevent)); + Adapter->subevent.EventsBitmap = (u16) data[0]; + Adapter->subevent.Rssi_low.value = (u8) data[1]; + Adapter->subevent.Rssi_low.Freq = (u8) data[2]; + Adapter->subevent.Snr_low.value = (u8) data[3]; + Adapter->subevent.Snr_low.Freq = (u8) data[4]; + Adapter->subevent.Rssi_high.value = (u8) data[5]; + Adapter->subevent.Rssi_high.Freq = (u8) data[6]; + Adapter->subevent.Snr_high.value = (u8) data[7]; + Adapter->subevent.Snr_high.Freq = (u8) data[8]; + } else { + data[0] = (int) Adapter->subevent.EventsBitmap; + data[1] = (int) Adapter->subevent.Rssi_low.value; + data[2] = (int) Adapter->subevent.Rssi_low.Freq; + data[3] = (int) Adapter->subevent.Snr_low.value; + data[4] = (int) Adapter->subevent.Snr_low.Freq; + data[5] = (int) Adapter->subevent.Rssi_high.value; + data[6] = (int) Adapter->subevent.Rssi_high.Freq; + data[7] = (int) Adapter->subevent.Snr_high.value; + data[8] = (int) Adapter->subevent.Snr_high.Freq; + } + wrq->u.data.length = 9; + if (copy_to_user(wrq->u.data.pointer, data, sizeof(data))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } LEAVE(); return WLAN_STATUS_SUCCESS; } @@ -2839,7 +4400,8 @@ * @param wreq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_rssi(wlan_private *priv, struct iwreq *wrq) +static int +wlan_get_rssi(wlan_private * priv, struct iwreq *wrq) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -2852,8 +4414,7 @@ if ((data == 0) || (data == 1)) { ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RSSI, - 0,HostCmd_OPTION_WAITFORRSP, - 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { LEAVE(); return ret; @@ -2871,6 +4432,9 @@ Adapter->NF[TYPE_BEACON][TYPE_AVG]); break; case 2: + if ((jiffies - Adapter->RxPDAge) > HZ) //data expired after 1 second + temp = 0; + else temp = CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_NOAVG], Adapter->NF[TYPE_RXPD][TYPE_NOAVG]); break; @@ -2895,7 +4459,8 @@ * @param wreq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_nf(wlan_private *priv, struct iwreq *wrq) +static int +wlan_get_nf(wlan_private * priv, struct iwreq *wrq) { int ret = WLAN_STATUS_SUCCESS; wlan_adapter *Adapter = priv->adapter; @@ -2908,8 +4473,7 @@ if ((data == 0) || (data == 1) ) { ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RSSI, - 0,HostCmd_OPTION_WAITFORRSP, - 0, NULL); + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); if (ret) { LEAVE(); @@ -2925,6 +4489,9 @@ temp = Adapter->NF[TYPE_BEACON][TYPE_AVG]; break; case 2: + if ((jiffies - Adapter->RxPDAge) > HZ) //data expired after 1 second + temp = 0; + else temp = Adapter->NF[TYPE_RXPD][TYPE_NOAVG]; break; case 3: @@ -2943,7 +4510,42 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief Remove AES key + * + * @param priv A pointer to wlan_private structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_remove_aes(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + WLAN_802_11_KEY key; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + if (Adapter->InfrastructureMode != Wlan802_11IBSS || + Adapter->MediaConnectStatus == WlanMediaStateConnected) + return -EOPNOTSUPP; + + Adapter->AdhocAESEnabled = FALSE; + + memset(&key, 0, sizeof(WLAN_802_11_KEY)); + PRINTM(INFO, "WPA2: DISABLE AES_KEY\n"); + key.KeyLength = WPA_AES_KEY_LEN; + key.KeyIndex = 0x40000000; + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_SET, + HostCmd_OPTION_WAITFORRSP, + !(KEY_INFO_ENABLED), &key); + + LEAVE(); + + return ret; +} /** * @brief Get Support Rates @@ -2952,11 +4554,12 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_getrate_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_getrate_ioctl(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; WLAN_802_11_RATES rates; - int rate[16]; + int rate[sizeof(rates)]; int i; ENTER(); @@ -2964,16 +4567,16 @@ memset(rates, 0, sizeof(rates)); memset(rate,0,sizeof(rate)); wrq->u.data.length = get_active_data_rates(Adapter, rates); - if(wrq->u.data.length > 16) - wrq->u.data.length = 16; + if (wrq->u.data.length > sizeof(rates)) + wrq->u.data.length = sizeof(rates); - for (i = 0; i < wrq->u.data.length; i++) - { + for (i = 0; i < wrq->u.data.length; i++) { rates[i] &= ~0x80; rate[i] = rates[i]; } - if (copy_to_user(wrq->u.data.pointer, rate, wrq->u.data.length * sizeof(int))) { + if (copy_to_user + (wrq->u.data.pointer, rate, wrq->u.data.length * sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } @@ -2989,7 +4592,8 @@ * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_txrate_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_get_txrate_ioctl(wlan_private * priv, struct ifreq *req) { wlan_adapter *Adapter = priv->adapter; int * pdata; @@ -3018,7 +4622,8 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_adhoc_status_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_get_adhoc_status_ioctl(wlan_private * priv, struct iwreq *wrq) { char status[64]; wlan_adapter *Adapter = priv->adapter; @@ -3029,18 +4634,18 @@ case Wlan802_11IBSS: if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { if (Adapter->AdhocCreate == TRUE) - memcpy(&status, "AdhocStarted", sizeof(status)); + strcpy(status, "AdhocStarted"); else - memcpy(&status, "AdhocJoined", sizeof(status)); + strcpy(status, "AdhocJoined"); } else { - memcpy(&status, "AdhocIdle", sizeof(status)); + strcpy(status, "AdhocIdle"); } break; case Wlan802_11Infrastructure: - memcpy(&status, "InfraMode", sizeof(status)); + strcpy(status, "InfraMode"); break; default: - memcpy(&status, "AutoUnknownMode", sizeof(status)); + strcpy(status, "AutoUnknownMode"); break; } @@ -3048,8 +4653,7 @@ wrq->u.data.length = strlen(status) + 1; if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - &status, wrq->u.data.length)) + if (copy_to_user(wrq->u.data.pointer, &status, wrq->u.data.length)) return -EFAULT; } @@ -3064,7 +4668,8 @@ * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_version_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_version_ioctl(wlan_private * priv, struct ifreq *req) { int len; char buf[128]; @@ -3090,72 +4695,111 @@ } /** + * @brief Get Driver and FW version + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_verext_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + HostCmd_DS_VERSION_EXT versionExtCmd; + int len; + + ENTER(); + + memset(&versionExtCmd, 0x00, sizeof(versionExtCmd)); + + if (wrq->u.data.flags == 0) { + //from iwpriv subcmd + versionExtCmd.versionStrSel = + *((int *) (wrq->u.name + SUBCMD_OFFSET)); + } else { + if (copy_from_user(&versionExtCmd.versionStrSel, + wrq->u.data.pointer, + sizeof(versionExtCmd.versionStrSel))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + } + + PrepareAndSendCommand(priv, + HostCmd_CMD_VERSION_EXT, 0, + HostCmd_OPTION_WAITFORRSP, 0, &versionExtCmd); + + len = strlen(versionExtCmd.versionStr) + 1; + if (wrq->u.data.pointer) { + if (copy_to_user(wrq->u.data.pointer, versionExtCmd.versionStr, len)) { + PRINTM(INFO, "CopyToUser failed\n"); + return -EFAULT; + } + wrq->u.data.length = len; + } + + PRINTM(INFO, "Version: %s\n", versionExtCmd.versionStr); + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** * @brief Read/Write adapter registers * * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_regrdwr_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_regrdwr_ioctl(wlan_private * priv, struct ifreq *req) { wlan_ioctl_regrdwr regrdwr; wlan_offset_value offval; - wlan_adapter *Adapter = priv->adapter; + u8 *pRdeeprom; int ret = WLAN_STATUS_SUCCESS; ENTER(); if(copy_from_user(®rdwr, req->ifr_data, sizeof(regrdwr))){ - PRINTM(INFO, "copy of regrdwr for wlan_regrdwr_ioctl from user failed \n"); + PRINTM(INFO, + "copy of regrdwr for wlan_regrdwr_ioctl from user failed \n"); LEAVE(); return -EFAULT; } if(regrdwr.WhichReg == REG_EEPROM) { - PRINTM(MSG, "Inside RDEEPROM\n"); - Adapter->pRdeeprom = (char *) kmalloc((regrdwr.NOB + sizeof(regrdwr)), GFP_KERNEL); - if(!Adapter -> pRdeeprom) + PRINTM(INFO, "Inside RDEEPROM\n"); + pRdeeprom = + (char *) kmalloc((regrdwr.NOB + sizeof(regrdwr)), GFP_KERNEL); + if (!pRdeeprom) { + PRINTM(INFO, "allocate memory for EEPROM read failed\n"); return -ENOMEM; - memcpy(Adapter->pRdeeprom, ®rdwr,sizeof(regrdwr)); - /* +14 is for Action, Offset, and NOB in - * response */ - PRINTM(INFO, "Action:%d Offset: %x NOB: %02x\n", - regrdwr.Action, - regrdwr.Offset, regrdwr.NOB); + } + memcpy(pRdeeprom, ®rdwr, sizeof(regrdwr)); + PRINTM(INFO, "Action: %d, Offset: %x, NOB: %02x\n", + regrdwr.Action, regrdwr.Offset, regrdwr.NOB); ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, regrdwr.Action,HostCmd_OPTION_WAITFORRSP, - 0, ®rdwr); - - if (ret) { - if(Adapter -> pRdeeprom) - kfree(Adapter -> pRdeeprom); - LEAVE(); - return ret; - } - - mdelay(10); + 0, pRdeeprom); /* * Return the result back to the user */ - - if (regrdwr.Action == HostCmd_ACT_GEN_READ) { - if(copy_to_user(req->ifr_data, Adapter -> pRdeeprom, sizeof(regrdwr) + regrdwr.NOB)) - { - if(Adapter -> pRdeeprom) - kfree(Adapter -> pRdeeprom); - PRINTM(INFO, "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n"); - LEAVE(); - return -EFAULT; + if (!ret && regrdwr.Action == HostCmd_ACT_GEN_READ) { + if (copy_to_user + (req->ifr_data, pRdeeprom, sizeof(regrdwr) + regrdwr.NOB)) { + PRINTM(INFO, + "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n"); + ret = -EFAULT; } } - if(Adapter -> pRdeeprom) - kfree(Adapter -> pRdeeprom); + kfree(pRdeeprom); - return WLAN_STATUS_SUCCESS; + LEAVE(); + return ret; } offval.offset = regrdwr.Offset; @@ -3163,8 +4807,7 @@ PRINTM(INFO, "RegAccess: %02x Action:%d " "Offset: %04x Value: %04x\n", - regrdwr.WhichReg, regrdwr.Action, - offval.offset, offval.value); + regrdwr.WhichReg, regrdwr.Action, offval.offset, offval.value); /* * regrdwr.WhichReg should contain the command that @@ -3177,119 +4820,233 @@ regrdwr.Action,HostCmd_OPTION_WAITFORRSP, 0, &offval); - if (ret) { - LEAVE(); - return ret; - } - - mdelay(10); - /* * Return the result back to the user */ - regrdwr.Value = Adapter->OffsetValue.value; - if (regrdwr.Action == HostCmd_ACT_GEN_READ) { + if (!ret && regrdwr.Action == HostCmd_ACT_GEN_READ) { + regrdwr.Value = offval.value; if(copy_to_user(req->ifr_data, ®rdwr, sizeof(regrdwr))){ - PRINTM(INFO, "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n"); + PRINTM(INFO, + "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n"); + ret = -EFAULT; + } + } + LEAVE(); + return ret; +} + +/** + * @brief Cmd52 read/write register + * + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_cmd52rdwr_ioctl(wlan_private * priv, struct ifreq *req) +{ + u8 buf[7]; + u8 rw, func, dat = 0xff; + u32 reg; + + ENTER(); + + if (copy_from_user(buf, req->ifr_data, sizeof(buf))) { + PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } + + rw = buf[0]; + func = buf[1]; + reg = buf[5]; + reg = (reg << 8) + buf[4]; + reg = (reg << 8) + buf[3]; + reg = (reg << 8) + buf[2]; + + if (rw != 0) + dat = buf[6]; + + PRINTM(INFO, "rw=%d func=%d reg=0x%08X dat=0x%02X\n", rw, func, reg, dat); + + if (rw == 0) { + if (sbi_read_ioreg(priv, func, reg, &dat) < 0) { + PRINTM(INFO, "sdio_read_ioreg: reading register 0x%X failed\n", + reg); + dat = 0xff; + } + } else { + if (sbi_write_ioreg(priv, func, reg, dat) < 0) { + PRINTM(INFO, "sdio_read_ioreg: writing register 0x%X failed\n", + reg); + dat = 0xff; + } + } + if (copy_to_user(req->ifr_data, &dat, sizeof(dat))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; } LEAVE(); return WLAN_STATUS_SUCCESS; } +/** + * @brief Cmd53 read/write register + * + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_cmd53rdwr_ioctl(wlan_private * priv, struct ifreq *req) +{ + return -EINVAL; +} +/** + * @brief Convert ascii string to Hex integer + * + * @param d A pointer to integer buf + * @param s A pointer to ascii string + * @param dlen the length o fascii string + * @return number of integer + */ +static int +ascii2hex(u8 * d, char *s, u32 dlen) +{ + int i; + u8 n; + memset(d, 0x00, dlen); + + for (i = 0; i < dlen * 2; i++) { + if ((s[i] >= 48) && (s[i] <= 57)) + n = s[i] - 48; + else if ((s[i] >= 65) && (s[i] <= 70)) + n = s[i] - 55; + else if ((s[i] >= 97) && (s[i] <= 102)) + n = s[i] - 87; + else + break; + if ((i % 2) == 0) + n = n * 16; + d[i / 2] += n; + } + + return i; +} /** - * @brief Set/Get WPA IE + * @brief Set adhoc aes key + * * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_setwpaie_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_setadhocaes_ioctl(wlan_private * priv, struct ifreq *req) { + u8 key_ascii[32]; + u8 key_hex[16]; + int ret = 0; struct iwreq *wrq = (struct iwreq *) req; wlan_adapter *Adapter = priv->adapter; - int ret = WLAN_STATUS_SUCCESS; + + WLAN_802_11_KEY key; ENTER(); - if (wrq->u.data.length) { - if (wrq->u.data.length > sizeof(Adapter->Wpa_ie)){ - PRINTM(INFO, "failed to copy WPA IE, too big \n"); - return -EFAULT; - } - if (copy_from_user(Adapter->Wpa_ie, wrq->u.data.pointer, - wrq->u.data.length)) { - PRINTM(INFO, "failed to copy WPA IE \n"); + if (Adapter->InfrastructureMode != Wlan802_11IBSS) + return -EOPNOTSUPP; + + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) + return -EOPNOTSUPP; + + if (copy_from_user(key_ascii, wrq->u.data.pointer, sizeof(key_ascii))) { + PRINTM(INFO, "wlan_setadhocaes_ioctl copy from user failed \n"); + LEAVE(); return -EFAULT; } - Adapter->Wpa_ie_len = wrq->u.data.length; - PRINTM(INFO, "Set Wpa_ie_len=%d IE=%#x\n", Adapter->Wpa_ie_len, - Adapter->Wpa_ie[0]); - HEXDUMP("Wpa_ie", Adapter->Wpa_ie, Adapter->Wpa_ie_len); - if (Adapter->Wpa_ie[0] == WPA_IE) - Adapter->SecInfo.WPAEnabled = TRUE; - else if (Adapter->Wpa_ie[0] == WPA2_IE) - Adapter->SecInfo.WPA2Enabled = TRUE; - else { - Adapter->SecInfo.WPAEnabled = FALSE; - Adapter->SecInfo.WPA2Enabled = FALSE; - } - } else { - memset(Adapter->Wpa_ie, 0, sizeof(Adapter->Wpa_ie)); - Adapter->Wpa_ie_len = wrq->u.data.length; - PRINTM(INFO, "Reset Wpa_ie_len=%d IE=%#x\n", Adapter->Wpa_ie_len, - Adapter->Wpa_ie[0]); - Adapter->SecInfo.WPAEnabled = FALSE; - Adapter->SecInfo.WPA2Enabled = FALSE; - } - // enable/disable RSN in firmware if WPA is enabled/disabled - // depending on variable Adapter->SecInfo.WPAEnabled is set or not - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_ENABLE_RSN, - HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + Adapter->AdhocAESEnabled = TRUE; + ascii2hex(key_hex, key_ascii, sizeof(key_hex)); + + HEXDUMP("wlan_setadhocaes_ioctl", key_hex, sizeof(key_hex)); + + PRINTM(INFO, "WPA2: ENABLE AES_KEY\n"); + key.KeyLength = WPA_AES_KEY_LEN; + key.KeyIndex = 0x40000000; + memcpy(key.KeyMaterial, key_hex, key.KeyLength); + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_SET, + HostCmd_OPTION_WAITFORRSP, + KEY_INFO_ENABLED, &key); LEAVE(); return ret; } /** - * @brief Set Auto Prescan + * @brief Get adhoc aes key * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure + * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_subcmd_setprescan_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_getadhocaes_ioctl(wlan_private * priv, struct ifreq *req) { - int data; + u8 *tmp; + u8 key_ascii[33]; + u8 key_hex[16]; + int i, ret = 0; + struct iwreq *wrq = (struct iwreq *) req; wlan_adapter *Adapter = priv->adapter; - int *val; + WLAN_802_11_KEY key; ENTER(); - data = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - PRINTM(INFO, "WLAN_SUBCMD_SET_PRESCAN %d\n", data); - switch ( data ) { - case CMD_ENABLED: - Adapter->Prescan = TRUE; - break; - case CMD_DISABLED: - Adapter->Prescan = FALSE; - break; - default: - break; + memset(key_hex, 0x00, sizeof(key_hex)); + + PRINTM(INFO, "WPA2: ENABLE AES_KEY\n"); + key.KeyLength = WPA_AES_KEY_LEN; + key.KeyIndex = 0x40000000; + memcpy(key.KeyMaterial, key_hex, key.KeyLength); + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_KEY_MATERIAL, + HostCmd_ACT_GET, + HostCmd_OPTION_WAITFORRSP, + KEY_INFO_ENABLED, &key); + + if (ret) { + LEAVE(); + return ret; + } + + memcpy(key_hex, Adapter->aeskey.KeyParamSet.Key, sizeof(key_hex)); + + HEXDUMP("wlan_getadhocaes_ioctl", key_hex, sizeof(key_hex)); + + wrq->u.data.length = sizeof(key_ascii) + 1; + + memset(key_ascii, 0x00, sizeof(key_ascii)); + tmp = key_ascii; + + for (i = 0; i < sizeof(key_hex); i++) + tmp += sprintf(tmp, "%02x", key_hex[i]); + + if (wrq->u.data.pointer) { + if (copy_to_user(wrq->u.data.pointer, &key_ascii, sizeof(key_ascii))) { + PRINTM(INFO, "copy_to_user failed\n"); + return -EFAULT; + } } - data = Adapter->Prescan; - val = (int *)wrq->u.name; - *val = data; LEAVE(); - return WLAN_STATUS_SUCCESS; + return ret; } /** @@ -3298,7 +5055,8 @@ * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_multiple_dtim_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_set_multiple_dtim_ioctl(wlan_private * priv, struct ifreq *req) { struct iwreq *wrq = (struct iwreq *) req; u32 mdtim; @@ -3309,7 +5067,8 @@ idata = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); mdtim = (u32)idata; - if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM) && (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM)) + if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM) && + (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM)) || (mdtim == MRVDRV_IGNORE_MULTIPLE_DTIM)) { priv->adapter->MultipleDtim = mdtim; ret = WLAN_STATUS_SUCCESS; @@ -3327,7 +5086,8 @@ * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_setauthalg_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_setauthalg_ioctl(wlan_private * priv, struct ifreq *req) { int alg; struct iwreq *wrq = (struct iwreq *) req; @@ -3353,8 +5113,7 @@ Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeShared; break; case AUTH_ALG_NETWORK_EAP: - Adapter->SecInfo.AuthenticationMode = - Wlan802_11AuthModeNetworkEAP; + Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeNetworkEAP; break; case AUTH_ALG_OPEN_SYSTEM: default: @@ -3367,273 +5126,446 @@ } /** - * @brief Set 802.1x authentication mode + * @brief Set Encryption mode * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set8021xauthalg_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req) { - int alg; + int mode; struct iwreq *wrq = (struct iwreq *) req; ENTER(); if (wrq->u.data.flags == 0) { //from iwpriv subcmd - alg = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); + mode = *((int *) (wrq->u.name + SUBCMD_OFFSET)); } else { //from wpa_supplicant subcmd - if (copy_from_user(&alg,wrq->u.data.pointer,sizeof(int))) { + if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } } - PRINTM(INFO, "802.1x auth alg is %#x\n",alg); - priv->adapter->SecInfo.Auth1XAlg = alg; + PRINTM(INFO, "encryption mode is %#x\n", mode); + priv->adapter->SecInfo.EncryptionMode = mode; LEAVE(); return WLAN_STATUS_SUCCESS; } /** - * @brief Set Encryption mode + * @brief Get Rx antenna * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_setencryptionmode_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_subcmd_getrxantenna_ioctl(wlan_private * priv, struct ifreq *req) { - int mode; + int len; + char buf[8]; struct iwreq *wrq = (struct iwreq *) req; ENTER(); - if (wrq->u.data.flags == 0) { - //from iwpriv subcmd - mode = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - } - else { - //from wpa_supplicant subcmd - if (copy_from_user(&mode,wrq->u.data.pointer,sizeof(int))) { - PRINTM(INFO, "Copy from user failed\n"); + PRINTM(INFO, "WLAN_SUBCMD_GETRXANTENNA\n"); + len = GetRxAntenna(priv, buf); + + wrq->u.data.length = len; + if (wrq->u.data.pointer) { + if (copy_to_user(wrq->u.data.pointer, &buf, len)) { + PRINTM(INFO, "CopyToUser failed\n"); return -EFAULT; } } - PRINTM(INFO, "encryption mode is %#x\n",mode); - priv->adapter->SecInfo.EncryptionMode = mode; LEAVE(); return WLAN_STATUS_SUCCESS; } -static void adjust_mtu(wlan_private *priv) -{ - int mtu_increment = 0; - - if (priv->adapter->linkmode == WLAN_LINKMODE_802_11) - mtu_increment += sizeof(IEEE80211_Hdr_t); - - if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) - mtu_increment += max(sizeof(TxRadiotapHdr_t), - sizeof(RxRadiotapHdr_t)); - priv->wlan_dev.netdev->mtu = MRVDRV_MAXIMUM_ETH_PACKET_SIZE - - sizeof(EthII_Hdr_t) - + mtu_increment; -} - /** - * @brief Set Link-Layer Layer mode + * @brief Get Tx antenna * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_linkmode_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_subcmd_gettxantenna_ioctl(wlan_private * priv, struct ifreq *req) { - int mode; + int len; + char buf[8]; + struct iwreq *wrq = (struct iwreq *) req; ENTER(); - mode = (int) ((struct ifreq *)((u8 *)req + 4))->ifr_data; + PRINTM(INFO, "WLAN_SUBCMD_GETTXANTENNA\n"); + len = GetTxAntenna(priv, buf); - switch (mode) { - case WLAN_LINKMODE_802_3: - priv->adapter->linkmode = mode; - break; - case WLAN_LINKMODE_802_11: - priv->adapter->linkmode = mode; - break; - default: - PRINTM(FATAL, "usb8388-5: invalid link-layer mode (%#x)\n", mode); - return WLAN_STATUS_NOT_ACCEPTED; - break; + wrq->u.data.length = len; + if (wrq->u.data.pointer) { + if (copy_to_user(wrq->u.data.pointer, &buf, len)) { + PRINTM(INFO, "CopyToUser failed\n"); + return -EFAULT; + } } - PRINTM(INFO, "usb8388-5: link-layer mode is %#x\n", mode); - - adjust_mtu(priv); LEAVE(); return WLAN_STATUS_SUCCESS; } /** - * @brief Set Radio Header mode + * @brief Get the MAC TSF value from the firmware + * * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail + * @param wrq A pointer to iwreq structure containing buffer + * space to store a TSF value retrieved from the firmware + * + * @return 0 if successful; IOCTL error code otherwise */ -static int wlan_set_radiomode_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq) { - int mode; + u64 tsfVal = 0; + int ret; ENTER(); - mode = (int) ((struct ifreq *)((u8 *)req + 4))->ifr_data; + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_GET_TSF, + 0, HostCmd_OPTION_WAITFORRSP, 0, &tsfVal); - switch (mode) { - case WLAN_RADIOMODE_NONE: - priv->adapter->radiomode = mode; - break; - case WLAN_RADIOMODE_RADIOTAP: - priv->adapter->radiomode = mode; - break; - default: - PRINTM(INFO, "usb8388-5: invalid radio header mode (%#x)\n", mode); - return WLAN_STATUS_NOT_ACCEPTED; - break; - } - PRINTM(INFO, "usb8388-5: radio-header mode is %#x\n", mode); + PRINTM(INFO, "IOCTL: Get TSF = 0x%016llx\n", tsfVal); - adjust_mtu(priv); + if (ret != WLAN_STATUS_SUCCESS) { + PRINTM(INFO, "IOCTL: Get TSF; Command exec failed\n"); + ret = -EFAULT; + } else { + if (copy_to_user(wrq->u.data.pointer, + &tsfVal, + MIN(wrq->u.data.length, sizeof(tsfVal))) != 0) { + + PRINTM(INFO, "IOCTL: Get TSF; Copy to user failed\n"); + ret = -EFAULT; + } else { + ret = 0; + } + } LEAVE(); - return WLAN_STATUS_SUCCESS; + + return ret; } /** - * @brief Set Debug Header mode + * @brief Control WPS Session Enable/Disable * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_set_debugmode_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_do_wps_session_ioctl(wlan_private * priv, struct iwreq *req) { + wlan_adapter *Adapter = priv->adapter; + char buf[8]; + struct iwreq *wrq = (struct iwreq *) req; + ENTER(); - priv->adapter->debugmode = (int) ((struct ifreq*) - ((u8 *)req + 4))->ifr_data; + + PRINTM(INFO, "WLAN_WPS_SESSION\n"); + + memset(buf, 0, sizeof(buf)); + if (copy_from_user(buf, wrq->u.data.pointer, + MIN(sizeof(buf) - 1, wrq->u.data.length))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + if (buf[0] == 1) + Adapter->wps.SessionEnable = TRUE; + else + Adapter->wps.SessionEnable = FALSE; + + PRINTM(INFO, "Adapter->wps.SessionEnable = %d\n", + Adapter->wps.SessionEnable); + LEAVE(); return WLAN_STATUS_SUCCESS; } /** - * @brief Get Rx antenna + * @brief Get/Set DeepSleep mode * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_subcmd_getrxantenna_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_deepsleep_ioctl(wlan_private * priv, struct ifreq *req) { - int len; - char buf[8]; + int ret = WLAN_STATUS_SUCCESS; + char status[128]; struct iwreq *wrq = (struct iwreq *) req; + wlan_adapter *Adapter = priv->adapter; ENTER(); - PRINTM(INFO, "WLAN_SUBCMD_GETRXANTENNA\n"); - len = GetRxAntenna(priv, buf); + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + PRINTM(MSG, "Cannot enter Deep Sleep mode in connected state.\n"); + return -EINVAL; + } + + if (*(char *) req->ifr_data == '0') { + PRINTM(INFO, "Exit Deep Sleep Mode.\n"); + sprintf(status, "setting to off "); + SetDeepSleep(priv, FALSE); + } else if (*(char *) req->ifr_data == '1') { + PRINTM(INFO, "Enter Deep Sleep Mode.\n"); + sprintf(status, "setting to on "); + SetDeepSleep(priv, TRUE); + } else if (*(char *) req->ifr_data == '2') { + PRINTM(INFO, "Get Deep Sleep Mode.\n"); + if (Adapter->IsDeepSleep == TRUE) { + sprintf(status, "on "); + } else { + sprintf(status, "off "); + } + } else { + PRINTM(INFO, "unknown option = %d\n", *(u8 *) req->ifr_data); + return -EINVAL; + } - wrq->u.data.length = len; if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, &buf, len)) { - PRINTM(INFO, "CopyToUser failed\n"); + if (copy_to_user(wrq->u.data.pointer, &status, strlen(status))) return -EFAULT; - } + wrq->u.data.length = strlen(status); } LEAVE(); - return WLAN_STATUS_SUCCESS; + return ret; } /** - * @brief Get Tx antenna + * @brief Config hostsleep parameter * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure + * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_subcmd_gettxantenna_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_do_hostsleepcfg_ioctl(wlan_private * priv, struct iwreq *wrq) { - int len; - char buf[8]; - struct iwreq *wrq = (struct iwreq *) req; - - ENTER(); - - PRINTM(INFO, "WLAN_SUBCMD_GETTXANTENNA\n"); - len = GetTxAntenna(priv, buf); + wlan_adapter *Adapter = priv->adapter; + char buf[32]; + int ret = WLAN_STATUS_SUCCESS; + int gpio, gap; - wrq->u.data.length = len; - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, &buf, len)) { - PRINTM(INFO, "CopyToUser failed\n"); + memset(buf, 0, sizeof(buf)); + if (copy_from_user(buf, wrq->u.data.pointer, + MIN(sizeof(buf) - 1, wrq->u.data.length))) { + PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } + buf[sizeof(buf) - 1] = 0; + + if (sscanf(buf, "%x %x %x", &Adapter->HSCfg.conditions, &gpio, &gap) != 3) { + PRINTM(MSG, "Invalid parameters\n"); + return -EINVAL; } - LEAVE(); - return WLAN_STATUS_SUCCESS; + if (Adapter->HSCfg.conditions != HOST_SLEEP_CFG_CANCEL) { + Adapter->HSCfg.gpio = (u8) gpio; + Adapter->HSCfg.gap = (u8) gap; + } + + PRINTM(INFO, + "hostsleepcfg: cond=%#x gpio=%#x gap=%#x PSState=%d HS_Activated=%d\n", + Adapter->HSCfg.conditions, Adapter->HSCfg.gpio, Adapter->HSCfg.gap, + Adapter->PSState, Adapter->HS_Activated); + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_HOST_SLEEP_CFG, + 0, HostCmd_OPTION_WAITFORRSP, 0, + &Adapter->HSCfg); + + return ret; } /** - * @brief Get the MAC TSF value from the firmware + * @brief Config Host Sleep parameters * * @param priv A pointer to wlan_private structure - * @param wrq A pointer to iwreq structure containing buffer - * space to store a TSF value retrieved from the firmware - * - * @return 0 if successful; IOCTL error code otherwise + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_get_tsf_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_hscfg_ioctl(wlan_private * priv, struct iwreq *wrq) { - u64 tsfVal; - int ret; + wlan_adapter *Adapter = priv->adapter; + int data[3] = { -1, 0xff, 0xff }; + int ret = WLAN_STATUS_SUCCESS; ENTER(); + if (wrq->u.data.length >= 1 && wrq->u.data.length <= 3) { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + PRINTM(INFO, + "wlan_hscfg_ioctl: data[0]=%#08x, data[1]=%#02x, data[2]=%#02x\n", + data[0], data[1], data[2]); + } else { + PRINTM(MSG, "Invalid Argument\n"); + return -EINVAL; + } + + Adapter->HSCfg.conditions = data[0]; + if (Adapter->HSCfg.conditions != HOST_SLEEP_CFG_CANCEL) { + if (wrq->u.data.length == 2) { + Adapter->HSCfg.gpio = (u8) data[1]; + } else if (wrq->u.data.length == 3) { + Adapter->HSCfg.gpio = (u8) data[1]; + Adapter->HSCfg.gap = (u8) data[2]; + } + } + + PRINTM(INFO, + "hscfg: cond=%#x gpio=%#x gap=%#x PSState=%d HS_Activated=%d\n", + Adapter->HSCfg.conditions, Adapter->HSCfg.gpio, Adapter->HSCfg.gap, + Adapter->PSState, Adapter->HS_Activated); + ret = PrepareAndSendCommand(priv, - HostCmd_CMD_GET_TSF, + HostCmd_CMD_802_11_HOST_SLEEP_CFG, 0, HostCmd_OPTION_WAITFORRSP, 0, - &tsfVal); + &Adapter->HSCfg); - PRINTM(INFO, "IOCTL: Get TSF = 0x%016llx\n", tsfVal); + data[0] = Adapter->HSCfg.conditions; + data[1] = Adapter->HSCfg.gpio; + data[2] = Adapter->HSCfg.gap; + wrq->u.data.length = 3; + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } - if (ret != WLAN_STATUS_SUCCESS) - { - PRINTM(INFO, "IOCTL: Get TSF; Command exec failed\n"); - ret = -EFAULT; + LEAVE(); + return ret; } - else + +/** + * @brief Set Host Sleep parameters + * + * @param priv A pointer to wlan_private structure + * @param wreq A pointer to iwreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_hssetpara_ioctl(wlan_private * priv, struct iwreq *wrq) { - if (copy_to_user(wrq->u.data.pointer, - &tsfVal, - MIN(wrq->u.data.length, sizeof(tsfVal))) != 0) { + wlan_adapter *Adapter = priv->adapter; + int data[3] = { -1, 0xff, 0xff }; + int ret = WLAN_STATUS_SUCCESS; - PRINTM(INFO, "IOCTL: Get TSF; Copy to user failed\n"); - ret = -EFAULT; + ENTER(); + + if (wrq->u.data.length >= 1 && wrq->u.data.length <= 3) { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; } - else - { - ret = 0; + PRINTM(INFO, + "wlan_hssetpara_ioctl: data[0]=%#08x, data[1]=%#02x, data[2]=%#02x\n", + data[0], data[1], data[2]); + } + + Adapter->HSCfg.conditions = data[0]; + if (Adapter->HSCfg.conditions != HOST_SLEEP_CFG_CANCEL) { + if (wrq->u.data.length == 2) { + Adapter->HSCfg.gpio = (u8) data[1]; + } else if (wrq->u.data.length == 3) { + Adapter->HSCfg.gpio = (u8) data[1]; + Adapter->HSCfg.gap = (u8) data[2]; } } - LEAVE(); + PRINTM(INFO, + "hssetpara: cond=%#x gpio=%#x gap=%#x PSState=%d HS_Activated=%d\n", + Adapter->HSCfg.conditions, Adapter->HSCfg.gpio, Adapter->HSCfg.gap, + Adapter->PSState, Adapter->HS_Activated); + + data[0] = Adapter->HSCfg.conditions; + data[1] = Adapter->HSCfg.gpio; + data[2] = Adapter->HSCfg.gap; + wrq->u.data.length = 3; + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + LEAVE(); return ret; } +/** + * @brief Get/Set Cal data ext + * @param priv A pointer to wlan_private structure + * @param req A pointer to ifreq structure + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +static int +wlan_do_caldata_ext_ioctl(wlan_private * priv, struct ifreq *req) +{ + HostCmd_DS_802_11_CAL_DATA_EXT *pCalData = NULL; + int ret = WLAN_STATUS_SUCCESS; + u16 action; + + ENTER(); + if (!(pCalData = kmalloc(MAX_SETGET_CONF_CMD_LEN, GFP_KERNEL))) { + PRINTM(INFO, "Allocate memory failed\n"); + ret = -ENOMEM; + goto calexit; + } + memset(pCalData, 0, MAX_SETGET_CONF_CMD_LEN); + if (copy_from_user(pCalData, req->ifr_data + SKIP_CMDNUM, + MAX_SETGET_CONF_CMD_LEN)) { + PRINTM(INFO, "Copy from user failed\n"); + kfree(pCalData); + ret = -EFAULT; + goto calexit; + } + action = (pCalData->Action == HostCmd_ACT_GEN_SET) ? + HostCmd_ACT_GEN_SET : HostCmd_ACT_GEN_GET; + + HEXDUMP("Cal data ext", (u8 *) pCalData, MAX_SETGET_CONF_CMD_LEN); + + PRINTM(INFO, "CalData Action = 0x%0X\n", action); + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_CAL_DATA_EXT, + action, + HostCmd_OPTION_WAITFORRSP, 0, pCalData); + + if (!ret && action == HostCmd_ACT_GEN_GET) { + if (copy_to_user(req->ifr_data + SKIP_CMDNUM, pCalData, + MAX_SETGET_CONF_CMD_LEN)) { + PRINTM(INFO, "Copy to user failed\n"); + ret = -EFAULT; + } + } + + kfree(pCalData); + calexit: + LEAVE(); + return ret; +} /** * @brief Get/Set sleep period @@ -3641,7 +5573,8 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_sleep_period(wlan_private *priv, struct iwreq *wrq) +static int +wlan_sleep_period(wlan_private * priv, struct iwreq *wrq) { int ret; int data; @@ -3657,17 +5590,22 @@ memset(&Adapter->sleep_period, 0, sizeof(SleepPeriod)); if (wrq->u.data.length == 0) { - sleeppd.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); + sleeppd.Action = HostCmd_ACT_GEN_GET; } else { if (copy_from_user(&data,wrq->u.data.pointer,sizeof(int))) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } - /* sleep period is between 0 or 10 ... 60 */ - if ((data <= 60 && data >= 10) || (data == 0)){ - sleeppd.Action = - wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + /* sleep period is 0 or 10~60 in milliseconds */ +#define MIN_SLEEP_PERIOD 10 +#define MAX_SLEEP_PERIOD 60 +#define SLEEP_PERIOD_RESERVED_FF 0xFF + if ((data <= MAX_SLEEP_PERIOD && data >= MIN_SLEEP_PERIOD) || + (data == 0) + || (data == SLEEP_PERIOD_RESERVED_FF) /* for UPSD certification tests */ + ) { + sleeppd.Action = HostCmd_ACT_GEN_SET; sleeppd.Period = data; } else return -EINVAL; @@ -3694,11 +5632,13 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_adapt_rateset(wlan_private *priv, struct iwreq *wrq) +static int +wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq) { int ret; wlan_adapter *Adapter = priv->adapter; - int data[2]; + int data[4]; + int rateindex; ENTER(); memset(data,0,sizeof(data)); @@ -3706,32 +5646,49 @@ PRINTM(INFO, "Get ADAPT RATE SET\n"); ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RATE_ADAPT_RATESET, - HostCmd_ACT_GEN_GET, HostCmd_OPTION_WAITFORRSP, - 0, NULL); - data[0] = Adapter->EnableHwAuto; + HostCmd_ACT_GEN_GET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); + data[0] = Adapter->HWRateDropMode; + data[2] = Adapter->Threshold; + data[3] = Adapter->FinalRate; + wrq->u.data.length = 4; data[1] = Adapter->RateBitmap; - if (copy_to_user(wrq->u.data.pointer,data,sizeof(int) * 2)) { + if (copy_to_user + (wrq->u.data.pointer, data, sizeof(int) * wrq->u.data.length)) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } -#define GET_TWO_INT 2 - wrq->u.data.length = GET_TWO_INT; } else { PRINTM(INFO, "Set ADAPT RATE SET\n"); - if(wrq->u.data.length > 2) + if (wrq->u.data.length > 4) return -EINVAL; - if (copy_from_user(data,wrq->u.data.pointer,sizeof(int) * wrq->u.data.length)) { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * wrq->u.data.length)) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } - Adapter->EnableHwAuto = data[0]; + if (data[0] > HW_SINGLE_RATE_DROP) + return -EINVAL; + Adapter->HWRateDropMode = data[0]; + Adapter->Threshold = data[2]; + Adapter->FinalRate = data[3]; Adapter->RateBitmap = data[1]; - ret = PrepareAndSendCommand(priv, - HostCmd_CMD_802_11_RATE_ADAPT_RATESET, - HostCmd_ACT_GEN_SET,HostCmd_OPTION_WAITFORRSP, - 0, NULL); + Adapter->Is_DataRate_Auto = Is_Rate_Auto(priv); + if (Adapter->Is_DataRate_Auto) + Adapter->DataRate = 0; + else { + rateindex = GetRateIndex(priv); + Adapter->DataRate = index_to_data_rate(rateindex); + } + PRINTM(INFO, "RateBitmap=%x,IsRateAuto=%d,DataRate=%d\n", + Adapter->RateBitmap, Adapter->Is_DataRate_Auto, + Adapter->DataRate); + ret = + PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RATE_ADAPT_RATESET, + HostCmd_ACT_GEN_SET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); } LEAVE(); @@ -3744,7 +5701,8 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_inactivity_timeout(wlan_private *priv, struct iwreq *wrq) +static int +wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq) { int ret; int data = 0; @@ -3758,8 +5716,8 @@ /* Get*/ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_INACTIVITY_TIMEOUT, - HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP, - 0, &timeout); + HostCmd_ACT_GET, + HostCmd_OPTION_WAITFORRSP, 0, &timeout); data = timeout; if (copy_to_user(wrq->u.data.pointer,&data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); @@ -3775,8 +5733,8 @@ timeout =data; ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_INACTIVITY_TIMEOUT, - HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP, - 0, &timeout); + HostCmd_ACT_SET, + HostCmd_OPTION_WAITFORRSP, 0, &timeout); } wrq->u.data.length = 1; @@ -3791,31 +5749,39 @@ * @param wrq A pointer to iwreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_do_getlog_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq) { int ret; - char buf[GETLOG_BUFSIZE-1]; + char *buf = NULL; wlan_adapter *Adapter = priv->adapter; ENTER(); PRINTM(INFO, " GET STATS\n"); - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); - - if (ret) { - LEAVE(); - return ret; + if (!(buf = kmalloc(GETLOG_BUFSIZE, GFP_KERNEL))) { + PRINTM(INFO, "kmalloc failed!\n"); + return -ENOMEM; } - if (wrq->u.data.pointer) { - sprintf(buf, "\n mcasttxframe %u failed %u retry %u " - "multiretry %u framedup %u " - "rtssuccess %u rtsfailure %u ackfailure %u\n" - "rxfrag %u mcastrxframe %u fcserror %u " - "txframe %u wepundecryptable %u ", + ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG, + 0, HostCmd_OPTION_WAITFORRSP, 0, NULL); + + if (!ret && wrq->u.data.pointer) { + sprintf(buf, "\n" + "mcasttxframe %u\n" + "failed %u\n" + "retry %u\n" + "multiretry %u\n" + "framedup %u\n" + "rtssuccess %u\n" + "rtsfailure %u\n" + "ackfailure %u\n" + "rxfrag %u\n" + "mcastrxframe %u\n" + "fcserror %u\n" + "txframe %u\n", Adapter->LogMsg.mcasttxframe, Adapter->LogMsg.failed, Adapter->LogMsg.retry, @@ -3826,28 +5792,27 @@ Adapter->LogMsg.ackfailure, Adapter->LogMsg.rxfrag, Adapter->LogMsg.mcastrxframe, - Adapter->LogMsg.fcserror, - Adapter->LogMsg.txframe, - Adapter->LogMsg.wepundecryptable); + Adapter->LogMsg.fcserror, Adapter->LogMsg.txframe); wrq->u.data.length = strlen(buf) + 1; if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) { PRINTM(INFO, "Copy to user failed\n"); - return -EFAULT; + ret = -EFAULT; } } + kfree(buf); LEAVE(); - return WLAN_STATUS_SUCCESS; + return ret; } - /** * @brief config sleep parameters * @param priv A pointer to wlan_private structure * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_sleep_params_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_sleep_params_ioctl(wlan_private * priv, struct iwreq *wrq) { int ret; wlan_adapter *Adapter = priv->adapter; @@ -3857,6 +5822,8 @@ memset(&sp, 0, sizeof(sp)); + if (!wrq->u.data.pointer) + return -EFAULT; if (copy_from_user(&sp, wrq->u.data.pointer, MIN(sizeof(sp), wrq->u.data.length))) { PRINTM(INFO, "Copy from user failed\n"); @@ -3869,7 +5836,7 @@ sp.Action, HostCmd_OPTION_WAITFORRSP, 0, NULL); - if (!ret && !sp.Action && wrq->u.data.pointer) { + if (!ret && !sp.Action) { memcpy(&sp.Error, &Adapter->sp, sizeof(SleepParams)); if (copy_to_user(wrq->u.data.pointer, &sp, sizeof(sp))) { PRINTM(INFO, "Copy to user failed\n"); @@ -3888,7 +5855,8 @@ * @param req A pointer to ifreq structure * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -static int wlan_do_getcis_ioctl(wlan_private *priv, struct ifreq *req) +static int +wlan_do_getcis_ioctl(wlan_private * priv, struct ifreq *req) { int ret = WLAN_STATUS_SUCCESS; struct iwreq *wrq = (struct iwreq *) req; @@ -3909,6 +5877,52 @@ return ret; } +/** + * @brief Set BCA timeshare + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to user data + * @return WLAN_STATUS_SUCCESS--success, otherwise fail + */ +static int +wlan_bca_timeshare_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + int ret; + wlan_adapter *Adapter = priv->adapter; + wlan_ioctl_bca_timeshare_config bca_ts; + + ENTER(); + + memset(&bca_ts, 0, sizeof(HostCmd_DS_802_11_BCA_TIMESHARE)); + + if (!wrq->u.data.pointer) + return -EFAULT; + if (copy_from_user(&bca_ts, wrq->u.data.pointer, + MIN(sizeof(bca_ts), wrq->u.data.length))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + PRINTM(INFO, "TrafficType=%x TimeShareInterva=%x BTTime=%x\n", + bca_ts.TrafficType, bca_ts.TimeShareInterval, bca_ts.BTTime); + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_BCA_CONFIG_TIMESHARE, + bca_ts.Action, HostCmd_OPTION_WAITFORRSP, + 0, &bca_ts); + + if (!ret && !bca_ts.Action) { + if (copy_to_user(wrq->u.data.pointer, &Adapter->bca_ts, + sizeof(bca_ts))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + wrq->u.data.length = sizeof(HostCmd_DS_802_11_BCA_TIMESHARE); + } + + LEAVE(); + return ret; +} /** * @brief Set scan type @@ -3917,7 +5931,8 @@ * @param wrq A pointer to user data * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -static int wlan_scan_type_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq) { u8 buf[12]; u8 *option[] = { "active", "passive", "get", }; @@ -3957,12 +5972,10 @@ Adapter->ScanType = HostCmd_SCAN_TYPE_PASSIVE; break; case 2: - wrq->u.data.length = - strlen(option[Adapter->ScanType]) + 1; + wrq->u.data.length = strlen(option[Adapter->ScanType]) + 1; if (copy_to_user(wrq->u.data.pointer, - option[Adapter->ScanType], - wrq->u.data.length)) { + option[Adapter->ScanType], wrq->u.data.length)) { PRINTM(INFO, "Copy to user failed\n"); ret = -EFAULT; } @@ -3985,7 +5998,8 @@ * @param wrq A pointer to user data * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -static int wlan_scan_mode_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; u8 buf[12]; @@ -4025,8 +6039,7 @@ break; case 3: - wrq->u.data.length = - strlen(option[Adapter->ScanMode-1]) + 1; + wrq->u.data.length = strlen(option[Adapter->ScanMode - 1]) + 1; PRINTM(INFO, "Get Scan Mode Option = %s\n", option[Adapter->ScanMode-1]); @@ -4034,8 +6047,7 @@ PRINTM(INFO, "Scan Mode Length %d\n", wrq->u.data.length); if (copy_to_user(wrq->u.data.pointer, - option[Adapter->ScanMode-1], - wrq->u.data.length)) { + option[Adapter->ScanMode - 1], wrq->u.data.length)) { PRINTM(INFO, "Copy to user failed\n"); ret = -EFAULT; } @@ -4061,7 +6073,8 @@ * @param wrq A pointer to user data * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -static int wlan_do_set_grate_ioctl(wlan_private *priv, struct iwreq *wrq) +static int +wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq) { wlan_adapter *Adapter = priv->adapter; int data,data1; @@ -4089,6 +6102,230 @@ return WLAN_STATUS_SUCCESS; } +/** + * @brief Get/Set Firmware wakeup method + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to user data + * @return WLAN_STATUS_SUCCESS--success, otherwise fail + */ +static int +wlan_cmd_fw_wakeup_method(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + u16 action; + u16 method; + int ret; + int data; + + ENTER(); + + if (wrq->u.data.length == 0 || !wrq->u.data.pointer) { + action = HostCmd_ACT_GET; + method = Adapter->fwWakeupMethod; + } else { + action = HostCmd_ACT_SET; + if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + switch (data) { + case 0: + method = WAKEUP_FW_UNCHANGED; + break; + case 1: + method = WAKEUP_FW_THRU_INTERFACE; + break; + case 2: + method = WAKEUP_FW_THRU_GPIO; + break; + default: + return -EINVAL; + } + } + + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_FW_WAKE_METHOD, action, + HostCmd_OPTION_WAITFORRSP, 0, &method); + + if (action == HostCmd_ACT_GET) { + method = Adapter->fwWakeupMethod; + if (copy_to_user(wrq->u.data.pointer, &method, sizeof(method))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + wrq->u.data.length = 1; + } + + LEAVE(); + return ret; +} + +/** + * @brief Get/Set Auto Deep Sleep mode + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to user data + * @return WLAN_STATUS_SUCCESS--success, otherwise fail + */ +static int +wlan_auto_deep_sleep(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + int data; + + ENTER(); + + if (wrq->u.data.length > 0 && wrq->u.data.pointer) { + if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + switch (data) { + case 0: + if (Adapter->IsAutoDeepSleepEnabled) { + Adapter->IsAutoDeepSleepEnabled = FALSE; + /* Try to exit DS if auto DS disabled */ + SetDeepSleep(priv, FALSE); + } + break; + case 1: + if (!Adapter->IsAutoDeepSleepEnabled) { + Adapter->IsAutoDeepSleepEnabled = TRUE; + /* Wakeup main thread to enter DS if auto DS enabled */ + wake_up_interruptible(&priv->MainThread.waitQ); + } + break; + default: + return -EINVAL; + } + } + + data = Adapter->IsAutoDeepSleepEnabled; + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(data))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + wrq->u.data.length = 1; + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Get the CFP table based on the region code + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_get_cfp_table_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + pwlan_ioctl_cfp_table ioctl_cfp; + CHANNEL_FREQ_POWER *cfp; + int cfp_no; + int regioncode; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + if (wrq->u.data.length == 0 || !wrq->u.data.pointer) { + ret = -EINVAL; + goto cfpexit; + } + + ioctl_cfp = (pwlan_ioctl_cfp_table) wrq->u.data.pointer; + + if (copy_from_user(®ioncode, &ioctl_cfp->region, sizeof(int))) { + PRINTM(INFO, "Get CFP table: copy from user failed\n"); + ret = -EFAULT; + goto cfpexit; + } + + if (!regioncode) + regioncode = Adapter->RegionCode; + + cfp = + wlan_get_region_cfp_table((u8) regioncode, BAND_G | BAND_B, &cfp_no); + + if (cfp == NULL) { + PRINTM(MSG, "No related CFP table found, region code = 0x%x\n", + regioncode); + ret = -EFAULT; + goto cfpexit; + } + + if (copy_to_user(&ioctl_cfp->cfp_no, &cfp_no, sizeof(int))) { + PRINTM(INFO, "Get CFP table: copy to user failed\n"); + ret = -EFAULT; + goto cfpexit; + } + + if (copy_to_user + (ioctl_cfp->cfp, cfp, sizeof(CHANNEL_FREQ_POWER) * cfp_no)) { + PRINTM(INFO, "Get CFP table: copy to user failed\n"); + ret = -EFAULT; + goto cfpexit; + } + + wrq->u.data.length = + sizeof(int) * 2 + sizeof(CHANNEL_FREQ_POWER) * cfp_no; + + cfpexit: + LEAVE(); + return ret; +} + +/** + * @brief Retrieve transmit packet statistics from the firmware + * + * @param priv A pointer to wlan_private structure + * @param wrq A pointer to iwreq structure + * + * @return WLAN_STATUS_SUCCESS --success, otherwise fail + */ +int +wlan_tx_pkt_stats_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + HostCmd_DS_TX_PKT_STATS txPktStats; + int ret; + + ENTER(); + + if (wrq->u.data.length == 0 || !wrq->u.data.pointer) { + LEAVE(); + return -EINVAL; + } + + if (wrq->u.data.length < sizeof(txPktStats)) { + LEAVE(); + return -E2BIG; + } + + memset(&txPktStats, 0x00, sizeof(txPktStats)); + + if ((ret = PrepareAndSendCommand(priv, + HostCmd_CMD_TX_PKT_STATS, 0, + HostCmd_OPTION_WAITFORRSP, + 0, &txPktStats))) { + LEAVE(); + return ret; + } + + if (copy_to_user(wrq->u.data.pointer, + (u8 *) & txPktStats, sizeof(txPktStats))) { + PRINTM(INFO, "TxPktStats: copy to user failed\n"); + return -EFAULT; + } + + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /******************************************************** Global Functions @@ -4101,7 +6338,8 @@ * @param cmd command * @return WLAN_STATUS_SUCCESS--success, otherwise fail */ -int wlan_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) +int +wlan_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { int subcmd = 0; int idata = 0; @@ -4113,6 +6351,73 @@ ENTER(); + if (Adapter->bHostSleepConfigured) { + BOOLEAN cmd_allowed = FALSE; + int count = sizeof(Commands_Allowed_In_HostSleep) + / sizeof(Commands_Allowed_In_HostSleep[0]); + + if (cmd == WLANHOSTSLEEPCFG) { + char buf[32]; + u32 cond; + + memset(buf, 0, sizeof(buf)); + if (copy_from_user(buf, wrq->u.data.pointer, + MIN(sizeof(buf) - 1, wrq->u.data.length))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + buf[sizeof(buf) - 1] = 0; + sscanf(buf, "%x ", &cond); + if (cond == HOST_SLEEP_CFG_CANCEL) { + cmd_allowed = TRUE; + if (Adapter->IsDeepSleep) { + SetDeepSleep(priv, FALSE); + } + } + } else if (cmd == WLAN_SET_GET_SIXTEEN_INT && + ((int) wrq->u.data.flags == WLANHSCFG)) { + u32 cond; + if (copy_from_user(&cond, wrq->u.data.pointer, sizeof(cond))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + + if (cond == HOST_SLEEP_CFG_CANCEL) { + cmd_allowed = TRUE; + if (Adapter->IsDeepSleep) { + SetDeepSleep(priv, FALSE); + } + } + } else + if (Is_Command_Allowed_In_Sleep + (req, cmd, Commands_Allowed_In_HostSleep, count)) { + cmd_allowed = TRUE; + } + if (!cmd_allowed) { + PRINTM(MSG, "%s IOCTLS called when WLAN access is blocked\n", + __FUNCTION__); + return -EBUSY; + } + } + + if (!Adapter->IsAutoDeepSleepEnabled) { + if (Adapter->IsDeepSleep) { + int count = sizeof(Commands_Allowed_In_DeepSleep) + / sizeof(Commands_Allowed_In_DeepSleep[0]); + + if (!Is_Command_Allowed_In_Sleep + (req, cmd, Commands_Allowed_In_DeepSleep, count)) { + PRINTM(MSG, + "():%s IOCTLS called when station is" + " in DeepSleep\n", __FUNCTION__); + return -EBUSY; + } + } + } else if (cmd == WLANDEEPSLEEP) { + PRINTM(MSG, + "DeepSleep command is not allowed in AutoDeepSleep mode\n"); + return -EBUSY; + } PRINTM(INFO, "wlan_do_ioctl: ioctl cmd = 0x%x\n", cmd); switch (cmd) { @@ -4122,6 +6427,9 @@ case WLANHOSTCMD: ret = wlan_hostcmd_ioctl(dev, req, cmd); break; + case WLANARPFILTER: + ret = wlan_arpfilter_ioctl(dev, req, cmd); + break; case WLANCISDUMP: /* Read CIS Table */ ret = wlan_do_getcis_ioctl(priv, req); @@ -4132,21 +6440,43 @@ ret = wlan_scan_type_ioctl(priv, wrq); break; +#ifdef MFG_CMD_SUPPORT + case WLANMANFCMD: + PRINTM(INFO, "Entering the Manufacturing ioctl SIOCCFMFG\n"); + ret = wlan_mfg_command(priv, wrq); + + PRINTM(INFO, "Manufacturing Ioctl %s\n", + (ret) ? "failed" : "success"); + break; +#endif case WLANREGRDWR: /* Register read write command */ ret = wlan_regrdwr_ioctl(priv, req); break; + case WLANCMD52RDWR: /* CMD52 read/write command */ + ret = wlan_cmd52rdwr_ioctl(priv, req); + break; + + case WLANCMD53RDWR: /* CMD53 read/write command */ + ret = wlan_cmd53rdwr_ioctl(priv, req); + break; case SIOCSIWENCODE: /* set encoding token & mode for WPA */ - ret = wlan_set_encode(dev, NULL, &(wrq->u.data), - wrq->u.data.pointer); + ret = wlan_set_encode(dev, NULL, &(wrq->u.data), wrq->u.data.pointer); break; case WLAN_SETNONE_GETNONE : /* set WPA mode on/off ioctl #20 */ switch(wrq->u.data.flags) { case WLANDEAUTH : PRINTM(INFO, "Deauth\n"); - wlan_send_deauth(priv); + if (Adapter->InfrastructureMode == Wlan802_11Infrastructure && + Adapter->MediaConnectStatus == WlanMediaStateConnected) { + SendDeauthentication(priv); + } else if (Adapter->InfrastructureMode == Wlan802_11IBSS && + Adapter->MediaConnectStatus == + WlanMediaStateConnected) { + StopAdhocNetwork(priv); + } break; case WLANADHOCSTOP: @@ -4159,7 +6489,10 @@ break; case WLANRADIOOFF: - wlan_radio_ioctl(priv, RADIO_OFF); + ret = wlan_radio_ioctl(priv, RADIO_OFF); + break; + case WLANREMOVEADHOCAES: + ret = wlan_remove_aes(priv); break; #ifdef REASSOCIATION case WLANREASSOCIATIONAUTO: @@ -4175,29 +6508,33 @@ case WLANWLANIDLEOFF: wlanidle_off(priv); break; - case WLAN_SUBCMD_DFT_RESET: /* dft_reset */ - wlan_dft_reset_ioctl(priv); - break; - case WLAN_SUBCMD_BT_RESET: /* bt_reset */ - wlan_bt_reset_ioctl(priv); - break; } /* End of switch */ break; case WLAN_SETWORDCHAR_GETNONE : switch(wrq->u.data.flags) { + case WLANSETADHOCAES: + ret = wlan_setadhocaes_ioctl(priv, req); + break; } break; - case WLAN_SETNONE_GETWORDCHAR: + case WLAN_SETONEINT_GETWORDCHAR: switch(wrq->u.data.flags) { + case WLANGETADHOCAES: + ret = wlan_getadhocaes_ioctl(priv, req); + break; case WLANVERSION: /* Get driver version */ ret = wlan_version_ioctl(priv, req); break; + case WLANVEREXT: + ret = wlan_verext_ioctl(priv, wrq); + break; } break; + case WLANSETWPAIE: - ret = wlan_setwpaie_ioctl(priv, req); + ret = wlan_set_wpa_ie_ioctl(priv, req); break; case WLAN_SETINT_GETINT: /* The first 4 bytes of req->ifr_data is sub-ioctl number @@ -4211,15 +6548,81 @@ case WLANRSSI : ret = wlan_get_rssi(priv, wrq); break; + case WLANBGSCAN: + { + int data, data1; + int *val; + data1 = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + switch (data1) { + case CMD_DISABLED: + PRINTM(INFO, "Background scan is set to disable\n"); + ret = wlan_bg_scan_enable(priv, FALSE); + val = (int *) wrq->u.name; + *val = data1; + break; + case CMD_ENABLED: + PRINTM(INFO, "Background scan is set to enable\n"); + ret = wlan_bg_scan_enable(priv, TRUE); + val = (int *) wrq->u.name; + *val = data1; + break; + case CMD_GET: + data = (Adapter->bgScanConfig->Enable == TRUE) ? + CMD_ENABLED : CMD_DISABLED; + val = (int *) wrq->u.name; + *val = data; + break; + default: + ret = -EINVAL; + PRINTM(INFO, "Background scan: wrong parameter\n"); + break; + } + } + break; case WLANENABLE11D: ret = wlan_cmd_enable_11d( priv, wrq ); break; case WLANADHOCGRATE: ret = wlan_do_set_grate_ioctl(priv, wrq); break; - case WLAN_SUBCMD_SET_PRESCAN: - ret = wlan_subcmd_setprescan_ioctl(priv,wrq); + case WLANSDIOCLOCK: + { + int data; + int *val; + data = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + switch (data) { + case CMD_DISABLED: + PRINTM(INFO, "SDIO clock is turned off\n"); + ret = sbi_set_bus_clock(priv, FALSE); + break; + case CMD_ENABLED: + PRINTM(INFO, "SDIO clock is turned on\n"); + ret = sbi_set_bus_clock(priv, TRUE); + break; + case CMD_GET: /* need an API in sdio.c to get STRPCL */ + default: + ret = -EINVAL; + PRINTM(INFO, "sdioclock: wrong parameter\n"); + break; + } + val = (int *) wrq->u.name; + *val = data; + } + break; + case WLANWMM_ENABLE: + ret = wlan_wmm_enable_ioctl(priv, wrq); + break; + case WLANNULLGEN: + ret = wlan_null_pkg_gen(priv, wrq); + /* enable/disable null pkg generation */ + break; + case WLANADHOCCSET: + ret = wlan_set_coalescing_ioctl(priv, wrq); + break; + case WLAN_ADHOC_G_PROT: + ret = wlan_adhoc_g_protection(priv, wrq); break; + } break; @@ -4225,18 +6628,34 @@ case WLAN_SETONEINT_GETONEINT: switch(wrq->u.data.flags) { - case WLAN_BEACON_INTERVAL: - ret = wlan_beacon_interval(priv,wrq); - break; + case WLAN_WMM_QOSINFO: + { + int data; + if (wrq->u.data.length == 1) { + if (copy_from_user + (&data, wrq->u.data.pointer, sizeof(int))) { + PRINTM(INFO, "Copy from user failed\n"); + return -EFAULT; + } + Adapter->wmm.qosinfo = (u8) data; + } else { + data = (int) Adapter->wmm.qosinfo; + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + wrq->u.data.length = 1; + } + } + break; case WLAN_LISTENINTRVL: if(!wrq->u.data.length) { int data; PRINTM(INFO, "Get LocalListenInterval Value\n"); #define GET_ONE_INT 1 data = Adapter->LocalListenInterval; - if (copy_to_user(wrq->u.data.pointer, - &data,sizeof(int))) { + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); return -EFAULT; } @@ -4258,14 +6677,29 @@ Adapter->LocalListenInterval = data; } break; - case WLAN_TXCONTROL: - ret = wlan_txcontrol(priv, wrq ); //adds for txcontrol ioctl + case WLAN_FW_WAKEUP_METHOD: + ret = wlan_cmd_fw_wakeup_method(priv, wrq); break; - case WLAN_NULLPKTINTERVAL: ret = wlan_null_pkt_interval(priv, wrq); break; - + case WLAN_BCN_MISS_TIMEOUT: + ret = wlan_bcn_miss_timeout(priv, wrq); + break; + case WLAN_ADHOC_AWAKE_PERIOD: + ret = wlan_adhoc_awake_period(priv, wrq); + break; + case WLAN_LDO: + ret = wlan_ldo_config(priv, wrq); + break; + case WLAN_AUTODEEPSLEEP: + ret = wlan_auto_deep_sleep(priv, wrq); + break; + case WLAN_WAKEUP_MT: + if (wrq->u.data.length > 0) + Adapter->IntCounter++; + wake_up_interruptible(&priv->MainThread.waitQ); + break; default: ret = -EOPNOTSUPP; break; @@ -4281,40 +6715,50 @@ if(!subcmd) subcmd = (int)req->ifr_data; //from iwpriv subcmd + idata = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + switch (subcmd) { case WLAN_SUBCMD_SETRXANTENNA : /* SETRXANTENNA */ - idata = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); ret = SetRxAntenna(priv, idata); break; case WLAN_SUBCMD_SETTXANTENNA : /* SETTXANTENNA */ - idata = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); ret = SetTxAntenna(priv, idata); break; - case WLAN_SET_ATIM_WINDOW: - Adapter->AtimWindow = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - Adapter->AtimWindow = MIN(Adapter->AtimWindow, 50); - break; + case WLANSETBCNAVG: - Adapter->bcn_avg_factor = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - if(Adapter->bcn_avg_factor == 0) - Adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; - if(Adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR) + if (idata == 0) Adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; + else if (idata > MAX_BCN_AVG_FACTOR || idata < MIN_BCN_AVG_FACTOR) { + PRINTM(MSG, "The value '%u' is out of the range (0-%u).\n", + idata, MAX_BCN_AVG_FACTOR); + return -EINVAL; + } else + Adapter->bcn_avg_factor = idata; break; case WLANSETDATAAVG: - Adapter->data_avg_factor = *( (int *) (wrq->u.name + SUBCMD_OFFSET) ); - if(Adapter->data_avg_factor == 0) - Adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; - if(Adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR) + if (idata == 0) Adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; + else if (idata > MAX_DATA_AVG_FACTOR + || idata < MIN_DATA_AVG_FACTOR) { + PRINTM(MSG, "The value '%u' is out of the range (0-%u).\n", + idata, MAX_DATA_AVG_FACTOR); + return -EINVAL; + } else + Adapter->data_avg_factor = idata; + memset(Adapter->rawSNR, 0x00, sizeof(Adapter->rawSNR)); + memset(Adapter->rawNF, 0x00, sizeof(Adapter->rawNF)); + Adapter->nextSNRNF = 0; + Adapter->numSNRNF = 0; + break; + case WLANASSOCIATE: + ret = wlan_associate_to_table_idx(priv, idata); break; + case WLANSETREGION: - idata = *( (int *) (wrq->u.name + SUBCMD_OFFSET)); ret = wlan_set_region(priv, (u16)idata); break; case WLAN_SET_LISTEN_INTERVAL: - idata = *( (int *) (wrq->u.name + SUBCMD_OFFSET)); Adapter->ListenInterval = (u16)idata; break; @@ -4326,26 +6770,10 @@ ret = wlan_setauthalg_ioctl(priv, req); break; - case WLANSET8021XAUTHALG: - ret = wlan_set8021xauthalg_ioctl(priv, req); - break; - case WLANSETENCRYPTIONMODE: ret = wlan_setencryptionmode_ioctl(priv, req); break; - case WLAN_SET_LINKMODE: - ret = wlan_set_linkmode_ioctl(priv, req); - break; - - case WLAN_SET_RADIOMODE: - ret = wlan_set_radiomode_ioctl(priv, req); - break; - - case WLAN_SET_DEBUGMODE: - ret = wlan_set_debugmode_ioctl(priv, req); - break; - default: ret = -EOPNOTSUPP; break; @@ -4371,11 +6799,20 @@ case WLAN_GET_TSF: ret = wlan_get_tsf_ioctl(priv, wrq); break; + + case WLAN_WPS_SESSION: + ret = wlan_do_wps_session_ioctl(priv, wrq); + break; } break; + case WLANDEEPSLEEP: + ret = wlan_deepsleep_ioctl(priv, req); + break; - + case WLANHOSTSLEEPCFG: + ret = wlan_do_hostsleepcfg_ioctl(priv, wrq); + break; case WLAN_SET64CHAR_GET64CHAR: switch ((int)wrq->u.data.flags) { @@ -4384,6 +6821,9 @@ ret = wlan_sleep_params_ioctl(priv, wrq); break; + case WLAN_BCA_TIMESHARE: + ret = wlan_bca_timeshare_ioctl(priv, wrq); + break; case WLANSCAN_MODE : PRINTM(INFO, "Scan Mode Ioctl\n"); ret = wlan_scan_mode_ioctl(priv, wrq); @@ -4392,31 +6832,28 @@ case WLAN_GET_ADHOC_STATUS: ret = wlan_get_adhoc_status_ioctl(priv, wrq); break; - case WLAN_SUBCMD_DFT_ADD: - ret = wlan_dft_add_ioctl(priv, req); - break; - case WLAN_SUBCMD_DFT_DEL: - ret = wlan_dft_del_ioctl(priv, req); - break; - case WLAN_SUBCMD_DFT_LIST: - ret = wlan_dft_list_ioctl(priv, req); - break; - case WLAN_SUBCMD_BT_ADD: - ret = wlan_bt_add_ioctl(priv, req); + case WLAN_SET_GEN_IE: + ret = wlan_set_gen_ie_ioctl(priv, wrq); break; - case WLAN_SUBCMD_BT_DEL: - ret = wlan_bt_del_ioctl(priv, req); + case WLAN_GET_GEN_IE: + ret = wlan_get_gen_ie_ioctl(priv, wrq); break; - case WLAN_SUBCMD_BT_LIST: - ret = wlan_bt_list_ioctl(priv, req); + case WLAN_WMM_QUEUE_STATUS: + ret = wlan_wmm_queue_status_ioctl(priv, wrq); break; } break; case WLAN_SETCONF_GETCONF: - PRINTM(INFO, "The WLAN_SETCONF_GETCONF=0x%x is %d\n",WLAN_SETCONF_GETCONF, *(u8 *)req->ifr_data); + PRINTM(INFO, "The WLAN_SETCONF_GETCONF=0x%x is %d\n", + WLAN_SETCONF_GETCONF, *(u8 *) req->ifr_data); switch (*(u8 *)req->ifr_data) { - + case CAL_DATA_EXT_CONFIG: + ret = wlan_do_caldata_ext_ioctl(priv, req); + break; + case BG_SCAN_CONFIG: + ret = wlan_do_bg_scan_config_ioctl(priv, req); + break; } break; @@ -4427,6 +6864,11 @@ *pdata =(int) Adapter->bcn_avg_factor; break; + case WLANGETDATAAVG: + pdata = (int *) wrq->u.name; + *pdata = (int) Adapter->data_avg_factor; + break; + case WLANGETREGION: pdata = (int *)wrq->u.name; *pdata =(int) Adapter->RegionCode; @@ -4437,18 +6879,6 @@ *pdata =(int) Adapter->ListenInterval; break; - case WLAN_GET_LINKMODE: - req->ifr_data = (char *)((u32)Adapter->linkmode); - break; - - case WLAN_GET_RADIOMODE: - req->ifr_data = (char *)((u32)Adapter->radiomode); - break; - - case WLAN_GET_DEBUGMODE: - req->ifr_data = (char *)((u32)Adapter->debugmode); - break; - case WLAN_GET_MULTIPLE_DTIM: pdata = (int *)wrq->u.name; *pdata =(int) Adapter->MultipleDtim; @@ -4463,22 +6893,10 @@ break; - case WLAN_SETTENCHAR_GETNONE: - switch ((int)wrq->u.data.flags) { - - } - break; - - case WLAN_SETNONE_GETTENCHAR: - switch ((int)wrq->u.data.flags) { - } - break; - case WLANGETLOG: ret = wlan_do_getlog_ioctl(priv, wrq); break; - case WLAN_SET_GET_SIXTEEN_INT: switch ((int)wrq->u.data.flags) { case WLAN_TPCCFG: @@ -4490,25 +6908,33 @@ return WLAN_STATUS_FAILURE; if (wrq->u.data.length == 0){ - cfg.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); - } - else - { - if (copy_from_user(data,wrq->u.data.pointer, sizeof(int) * 5)) { + cfg.Action = HostCmd_ACT_GEN_GET; + } else { + if (copy_from_user(data, + wrq->u.data.pointer, + sizeof(int) * 5)) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } - cfg.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + cfg.Action = HostCmd_ACT_GEN_SET; cfg.Enable = data[0]; cfg.UseSNR = data[1]; +#define TPC_DATA_NO_CHANG 0x7f + if (wrq->u.data.length == 1) { + cfg.P0 = TPC_DATA_NO_CHANG; + cfg.P1 = TPC_DATA_NO_CHANG; + cfg.P2 = TPC_DATA_NO_CHANG; + } else { cfg.P0 = data[2]; cfg.P1 = data[3]; cfg.P2 = data[4]; } - - ret = PrepareAndSendCommand(priv,HostCmd_CMD_802_11_TPC_CFG,0, - HostCmd_OPTION_WAITFORRSP,0,(void *) &cfg); + } + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_TPC_CFG, 0, + HostCmd_OPTION_WAITFORRSP, 0, + (void *) &cfg); data[0] = cfg.Enable; data[1] = cfg.UseSNR; @@ -4524,98 +6950,18 @@ } break; - case WLAN_POWERCFG: - { - int data[4]; - HostCmd_DS_802_11_PWR_CFG cfg; - memset(&cfg, 0, sizeof(cfg)); - if ((wrq->u.data.length > 1) && (wrq->u.data.length != 4)) - return WLAN_STATUS_FAILURE; - if (wrq->u.data.length == 0){ - cfg.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); - } - else - { - if (copy_from_user(data,wrq->u.data.pointer, sizeof(int) * 4)) { - PRINTM(INFO, "Copy from user failed\n"); - return -EFAULT; - } - - cfg.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); - cfg.Enable = data[0]; - cfg.PA_P0 = data[1]; - cfg.PA_P1 = data[2]; - cfg.PA_P2 = data[3]; - } - ret = PrepareAndSendCommand(priv,HostCmd_CMD_802_11_PWR_CFG,0, - HostCmd_OPTION_WAITFORRSP,0,(void *) &cfg); - data[0] = cfg.Enable; - data[1] = cfg.PA_P0; - data[2] = cfg.PA_P1; - data[3] = cfg.PA_P2; - if (copy_to_user(wrq->u.data.pointer,data,sizeof(int) * 4)) { - PRINTM(INFO, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = 4; - } - break; - case WLAN_AUTO_FREQ_SET: - { - int data[3]; - HostCmd_DS_802_11_AFC afc; - memset(&afc, 0, sizeof(afc)); - if (wrq->u.data.length != 3) - return WLAN_STATUS_FAILURE; - if (copy_from_user(data,wrq->u.data.pointer,sizeof(int)*3)) { - PRINTM(INFO, "Copy from user failed\n"); - return -EFAULT; - } - afc.afc_auto = data[0]; - - if (afc.afc_auto != 0) { - afc.afc_thre = data[1]; - afc.afc_period = data[2]; - } else { - afc.afc_toff = data[1]; - afc.afc_foff = data[2]; - } - ret = PrepareAndSendCommand(priv,HostCmd_CMD_802_11_SET_AFC,0, - HostCmd_OPTION_WAITFORRSP,0,(void *) &afc); - } - break; - case WLAN_AUTO_FREQ_GET: - { - int data[3]; - HostCmd_DS_802_11_AFC afc; - memset(&afc, 0, sizeof(afc)); - ret = PrepareAndSendCommand(priv,HostCmd_CMD_802_11_GET_AFC,0, - HostCmd_OPTION_WAITFORRSP,0,(void *) &afc); - data[0] = afc.afc_auto; - data[1] = afc.afc_toff; - data[2] = afc.afc_foff; - if (copy_to_user(wrq->u.data.pointer,data,sizeof(int) * 3)) { - PRINTM(INFO, "Copy to user failed\n"); - return -EFAULT; - } - - wrq->u.data.length = 3; - } - break; case WLAN_SCANPROBES: { int data; if (wrq->u.data.length > 0){ - if (copy_from_user(&data,wrq->u.data.pointer,sizeof(int))) { + if (copy_from_user + (&data, wrq->u.data.pointer, sizeof(int))) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } Adapter->ScanProbes = data; - } - else - { + } else { data = Adapter->ScanProbes; if (copy_to_user(wrq->u.data.pointer,&data,sizeof(int))) { PRINTM(INFO, "Copy to user failed\n"); @@ -4628,38 +6974,45 @@ case WLAN_LED_GPIO_CTRL: { int i; - int data[16]; - + int data[MAX_LEDS * 2]; HostCmd_DS_802_11_LED_CTRL ctrl; - MrvlIEtypes_LedGpio_t *gpio = (MrvlIEtypes_LedGpio_t *) ctrl.data; + MrvlIEtypes_LedGpio_t *gpio; + + gpio = (MrvlIEtypes_LedGpio_t *) & ctrl.LedGpio; + + if ((wrq->u.data.length > MAX_LEDS * 2) || + (wrq->u.data.length % 2) != 0) { + PRINTM(MSG, "invalid ledgpio parameters\n"); + return -EINVAL; + } memset(&ctrl, 0, sizeof(ctrl)); - if (wrq->u.data.length > MAX_LEDS*2) - return -ENOTSUPP; - if ((wrq->u.data.length % 2) != 0) - return -ENOTSUPP; if (wrq->u.data.length == 0) { - ctrl.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET); + ctrl.Action = HostCmd_ACT_GEN_GET; } else { - if (copy_from_user(data,wrq->u.data.pointer,sizeof(int)*wrq->u.data.length)) { + if (copy_from_user(data, wrq->u.data.pointer, + sizeof(int) * wrq->u.data.length)) { PRINTM(INFO, "Copy from user failed\n"); return -EFAULT; } - ctrl.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); - ctrl.NumLed = wlan_cpu_to_le16(0); - gpio->Header.Type = wlan_cpu_to_le16(TLV_TYPE_LED_GPIO); + ctrl.Action = HostCmd_ACT_GEN_SET; + ctrl.LedNums = 0; + gpio->Header.Type = TLV_TYPE_LED_GPIO; gpio->Header.Len = wrq->u.data.length; for (i=0; i < wrq->u.data.length; i+=2) { - gpio->LedPin[i/2].Led = data[i]; - gpio->LedPin[i/2].Pin = data[i+1]; + gpio->LedGpio[i / 2].LedNum = data[i]; + gpio->LedGpio[i / 2].GpioNum = data[i + 1]; } } - ret = PrepareAndSendCommand( priv, HostCmd_CMD_802_11_LED_GPIO_CTRL,0, - HostCmd_OPTION_WAITFORRSP,0, (void *) &ctrl); + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_LED_CONTROL, 0, + HostCmd_OPTION_WAITFORRSP, + 0, (void *) &ctrl); + for (i=0; i < gpio->Header.Len; i+=2) { - data[i] = gpio->LedPin[i/2].Led; - data[i+1] = gpio->LedPin[i/2].Pin; + data[i] = gpio->LedGpio[i / 2].LedNum; + data[i + 1] = gpio->LedGpio[i / 2].GpioNum; } if (copy_to_user(wrq->u.data.pointer,data, sizeof(int)* gpio->Header.Len)) { @@ -4687,6 +7040,37 @@ break; case WLAN_GET_RXINFO: ret = wlan_get_rxinfo(priv,wrq); + break; + case WLAN_SET_ATIM_WINDOW: + ret = wlan_ATIM_Window(priv, wrq); + break; + case WLAN_BEACON_INTERVAL: + ret = wlan_beacon_interval(priv, wrq); + break; + case WLAN_SDIO_PULL_CTRL: + ret = wlan_sdio_pull_ctrl(priv, wrq); + break; + case WLAN_SCAN_TIME: + ret = wlan_scan_time(priv, wrq); + break; + case WLAN_DATA_SUBSCRIBE_EVENT: + ret = wlan_data_subscribe_event(priv, wrq); + break; + case WLAN_TXCONTROL: + ret = wlan_txcontrol(priv, wrq); + break; + case WLANHSCFG: + ret = wlan_hscfg_ioctl(priv, wrq); + break; + case WLANHSSETPARA: + ret = wlan_hssetpara_ioctl(priv, wrq); + break; +#ifdef DEBUG_LEVEL1 + case WLAN_DRV_DBG: + ret = wlan_drv_dbg(priv, wrq); + break; +#endif + } break; @@ -4698,7 +7082,30 @@ case WLAN_GET_SCAN_TABLE: ret = wlan_get_scan_table_ioctl(priv, wrq); break; - + case WLAN_SET_MRVL_TLV: + ret = wlan_set_mrvl_tlv_ioctl(priv, wrq); + break; + case WLAN_GET_ASSOC_RSP: + ret = wlan_get_assoc_rsp_ioctl(priv, wrq); + break; + case WLAN_ADDTS_REQ: + ret = wlan_wmm_addts_req_ioctl(priv, wrq); + break; + case WLAN_DELTS_REQ: + ret = wlan_wmm_delts_req_ioctl(priv, wrq); + break; + case WLAN_QUEUE_CONFIG: + ret = wlan_wmm_queue_config_ioctl(priv, wrq); + break; + case WLAN_QUEUE_STATS: + ret = wlan_wmm_queue_stats_ioctl(priv, wrq); + break; + case WLAN_TX_PKT_STATS: + ret = wlan_tx_pkt_stats_ioctl(priv, wrq); + break; + case WLAN_GET_CFP_TABLE: + ret = wlan_get_cfp_table_ioctl(priv, wrq); + break; default: ret = -EOPNOTSUPP; } @@ -4714,10 +7122,15 @@ /** * @brief Get wireless statistics * + * NOTE: If PrepareAndSendCommand() with wait option is issued + * in this function, a kernel dump (scheduling while atomic) + * issue may happen on some versions of kernels. + * * @param dev A pointer to net_device structure * @return A pointer to iw_statistics buf */ -struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev) +struct iw_statistics * +wlan_get_wireless_stats(struct net_device *dev) { wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; @@ -4725,14 +7138,18 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return NULL; + } + priv->wstats.status = Adapter->InfrastructureMode; priv->wstats.discard.retries = priv->stats.tx_errors; /* send RSSI command to get beacon RSSI/NF, valid only if associated */ ret = PrepareAndSendCommand(priv, - HostCmd_CMD_802_11_RSSI, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + HostCmd_CMD_802_11_RSSI, 0, + HostCmd_OPTION_WAITFORRSP, 0, NULL); priv->wstats.qual.level = CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG], @@ -4749,12 +7166,11 @@ PRINTM(INFO, "Signal Level = %#x\n", priv->wstats.qual.level); PRINTM(INFO, "Noise = %#x\n", priv->wstats.qual.noise); - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG, - 0, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_GET_LOG, 0, + HostCmd_OPTION_WAITFORRSP, 0, NULL); if (!ret) { - priv->wstats.discard.code = Adapter->LogMsg.wepundecryptable; + priv->wstats.discard.code = 0; priv->wstats.discard.fragment = Adapter->LogMsg.fcserror; priv->wstats.discard.retries = Adapter->LogMsg.retry; priv->wstats.discard.misc = Adapter->LogMsg.ackfailure; @@ -4763,6 +7179,53 @@ return &priv->wstats; } +static int +wlan_set_coalescing_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + int data; + int *val; + int ret = WLAN_STATUS_SUCCESS; + + ENTER(); + + data = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + + switch (data) { + case CMD_DISABLED: + case CMD_ENABLED: + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_SET, + HostCmd_OPTION_WAITFORRSP, 0, &data); + if (ret) { + LEAVE(); + return ret; + } + break; + + case CMD_GET: + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, + HostCmd_ACT_GET, + HostCmd_OPTION_WAITFORRSP, 0, &data); + if (ret) { + LEAVE(); + return ret; + } + break; + + default: + return -EINVAL; + } + + val = (int *) wrq->u.name; + *val = data; + + LEAVE(); + + return WLAN_STATUS_SUCCESS; +} + /** * @brief Set frequency * @@ -4772,7 +7235,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS--success, otherwise--fail */ -int wlan_set_freq(struct net_device *dev, struct iw_request_info *info, +int +wlan_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -4783,7 +7247,12 @@ ENTER(); - + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + if (Adapter->InfrastructureMode != Wlan802_11IBSS) + return -EOPNOTSUPP; /* * If setting by frequency, convert to a channel @@ -4816,44 +7285,103 @@ } else { int channel = fwrq->m; - cfp = find_cfp_by_band_and_channel(Adapter, 0, channel); + cfp = find_cfp_by_band_and_channel(Adapter, 0, (u16) channel); if (!cfp) { rc = -EINVAL; } else { - if (Adapter->InfrastructureMode == Wlan802_11IBSS) { rc = ChangeAdhocChannel(priv, channel); /* If station is WEP enabled, send the * command to set WEP in firmware */ - if (Adapter->SecInfo.WEPStatus == - Wlan802_11WEPEnabled) { + if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) { PRINTM(INFO, "set_freq: WEP Enabled\n"); ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SET_WEP, - 0,HostCmd_OPTION_WAITFORRSP - , OID_802_11_ADD_WEP, - NULL); + 0, HostCmd_OPTION_WAITFORRSP, + OID_802_11_ADD_WEP, NULL); if (ret) { LEAVE(); return ret; } + Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_WEP_ENABLE; - Adapter->CurrentPacketFilter |= - HostCmd_ACT_MAC_WEP_ENABLE; + PrepareAndSendCommand(priv, + HostCmd_CMD_MAC_CONTROL, + 0, HostCmd_OPTION_WAITFORRSP, + 0, &Adapter->CurrentPacketFilter); + } + } + } - SetMacPacketFilter(priv); + LEAVE(); + return rc; +} + +/** + * @brief Set Deep Sleep + * + * @param adapter A pointer to wlan_private structure + * @param bDeepSleep TRUE--enalbe deepsleep, FALSE--disable deepsleep + * @return WLAN_STATUS_SUCCESS-success, otherwise fail + */ + +int +SetDeepSleep(wlan_private * priv, BOOLEAN bDeepSleep) +{ + int ret = WLAN_STATUS_SUCCESS; + wlan_adapter *Adapter = priv->adapter; + + ENTER(); + + if (bDeepSleep == TRUE) { + if (Adapter->IsDeepSleep != TRUE) { + PRINTM(INFO, "Deep Sleep: sleep\n"); + + // note: the command could be queued and executed later + // if there is command in prigressing. + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_DEEP_SLEEP, 0, + HostCmd_OPTION_WAITFORRSP, 0, NULL); + + if (ret) { + LEAVE(); + return ret; + } + wmm_stop_queue(priv); + os_stop_queue(priv); + os_carrier_off(priv); } } else { - rc = -EOPNOTSUPP; + if (Adapter->IsDeepSleep == TRUE) { + PRINTM(CMND, "Deep Sleep: wakeup\n"); + + if (Adapter->IntCounterSaved) { + Adapter->IntCounter = Adapter->IntCounterSaved; + Adapter->IntCounterSaved = 0; } + + if (sbi_exit_deep_sleep(priv)) + PRINTM(ERROR, "Deep Sleep : wakeup failed\n"); + + if (Adapter->IsDeepSleep == TRUE) { + + if (os_wait_interruptible_timeout(Adapter->ds_awake_q, + !Adapter->IsDeepSleep, + MRVDRV_DEEP_SLEEP_EXIT_TIMEOUT) + == 0) { + PRINTM(MSG, "ds_awake_q: timer expired\n"); } } - LEAVE(); - return rc; + if (Adapter->IntCounter) + wake_up_interruptible(&priv->MainThread.waitQ); + } } + LEAVE(); + return WLAN_STATUS_SUCCESS; +} /** * @brief use index to get the data rate @@ -4861,7 +7389,8 @@ * @param index The index of data rate * @return data rate or 0 */ -u32 index_to_data_rate(u8 index) +u32 +index_to_data_rate(u8 index) { if (index >= sizeof(WlanDataRates)) index = 0; @@ -4875,7 +7404,8 @@ * @param rate data rate * @return index or 0 */ -u8 data_rate_to_index(u32 rate) +u8 +data_rate_to_index(u32 rate) { u8 *ptr; @@ -4896,28 +7426,40 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_rate(struct net_device *dev, struct iw_request_info *info, + +int +wlan_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; u32 data_rate; - u16 action; int ret = WLAN_STATUS_SUCCESS; WLAN_802_11_RATES rates; u8 *rate; ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } PRINTM(INFO, "Vwrq->value = %d\n", vwrq->value); if (vwrq->value == -1) { - action = HostCmd_ACT_SET_TX_AUTO; // Auto - Adapter->Is_DataRate_Auto = TRUE; Adapter->DataRate = 0; + Adapter->RateBitmap = 0; + memset(rates, 0, sizeof(rates)); + get_active_data_rates(Adapter, rates); + rate = rates; + while (*rate) { + Adapter->RateBitmap |= 1 << (data_rate_to_index(*rate & 0x7f)); + rate++; + } + Adapter->Is_DataRate_Auto = TRUE; } else { - if (vwrq->value % 100000) { + if ((vwrq->value % 500000)) { return -EINVAL; } @@ -4939,13 +7481,14 @@ } Adapter->DataRate = data_rate; - action = HostCmd_ACT_SET_TX_FIX_RATE; + Adapter->RateBitmap = 1 << (data_rate_to_index(Adapter->DataRate)); Adapter->Is_DataRate_Auto = FALSE; } - ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_DATA_RATE, - action, HostCmd_OPTION_WAITFORRSP, - 0, NULL); + ret = PrepareAndSendCommand(priv, + HostCmd_CMD_802_11_RATE_ADAPT_RATESET, + HostCmd_ACT_GEN_SET, + HostCmd_OPTION_WAITFORRSP, 0, NULL); LEAVE(); return ret; @@ -4960,21 +7503,36 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_get_rate(struct net_device *dev, struct iw_request_info *info, +int +wlan_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; + int ret = WLAN_STATUS_SUCCESS; ENTER(); - if (Adapter->Is_DataRate_Auto) { + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } + + if (Adapter->Is_DataRate_Auto) vwrq->fixed = 0; - } else { + else vwrq->fixed = 1; - } - vwrq->value = Adapter->DataRate * 500000; + Adapter->TxRate = 0; + + ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, + HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP, + 0, NULL); + if (ret) { + LEAVE(); + return ret; + } + vwrq->value = index_to_data_rate(Adapter->TxRate) * 500000; LEAVE(); return WLAN_STATUS_SUCCESS; @@ -4989,7 +7547,8 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_mode(struct net_device *dev, +int +wlan_set_mode(struct net_device *dev, struct iw_request_info *info, u32 * uwrq, char *extra) { int ret = WLAN_STATUS_SUCCESS; @@ -5000,12 +7559,25 @@ ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } switch (*uwrq) { case IW_MODE_ADHOC: - PRINTM(INFO, "Wanted Mode is ad-hoc: current DataRate=%#x\n",Adapter->DataRate); + PRINTM(INFO, "Wanted Mode is ad-hoc: current DataRate=%#x\n", + Adapter->DataRate); WantedMode = Wlan802_11IBSS; Adapter->AdhocChannel = DEFAULT_AD_HOC_CHANNEL; + if (!find_cfp_by_band_and_channel + (Adapter, 0, (u16) Adapter->AdhocChannel)) { + CHANNEL_FREQ_POWER *cfp; + cfp = + find_cfp_by_band_and_channel(Adapter, 0, FIRST_VALID_CHANNEL); + if (cfp) + Adapter->AdhocChannel = cfp->Channel; + } break; case IW_MODE_INFRA: @@ -5043,7 +7615,6 @@ if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) { ret = SendDeauthentication(priv); - if (ret) { LEAVE(); return ret; @@ -5059,28 +7630,6 @@ } } - if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) { - /* If there is a key with the specified SSID, - * send REMOVE WEP command, to make sure we clean up - * the WEP keys in firmware - */ - ret = PrepareAndSendCommand(priv, - HostCmd_CMD_802_11_SET_WEP, - 0, HostCmd_OPTION_WAITFORRSP - , OID_802_11_REMOVE_WEP, - NULL); - - if (ret) { - LEAVE(); - return ret; - } - - Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - - SetMacPacketFilter(priv); - } - - Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled; Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen; Adapter->InfrastructureMode = WantedMode; @@ -5088,8 +7637,7 @@ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_SNMP_MIB, 0, HostCmd_OPTION_WAITFORRSP, - OID_802_11_INFRASTRUCTURE_MODE, - NULL); + OID_802_11_INFRASTRUCTURE_MODE, NULL); if (ret) { LEAVE(); @@ -5109,37 +7657,36 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_encode(struct net_device *dev, +static int +wlan_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { - PWLAN_802_11_KEY pKey = NULL; + WLAN_802_11_KEY *pKey = NULL; + int retval = -EINVAL; ENTER(); - if (dwrq->length > MAX_KEY_SIZE) { - pKey = (PWLAN_802_11_KEY) extra; - - if(pKey->KeyLength <= MAX_KEY_SIZE) { + if (dwrq->length > MAX_WEP_KEY_SIZE) { + pKey = (WLAN_802_11_KEY *) extra; + if (pKey->KeyLength <= MAX_WEP_KEY_SIZE) { //dynamic WEP dwrq->length = pKey->KeyLength; dwrq->flags = pKey->KeyIndex + 1; - return wlan_set_encode_nonwpa(dev, info, dwrq, + retval = wlan_set_encode_nonwpa(dev, info, dwrq, pKey->KeyMaterial); - } - else { + } else { //WPA - return wlan_set_encode_wpa(dev, info, dwrq, extra); - } + retval = wlan_set_encode_wpa(dev, info, dwrq, extra); } - else { + } else { //static WEP PRINTM(INFO, "Setting WEP\n"); - return wlan_set_encode_nonwpa(dev, info, dwrq, extra); + retval = wlan_set_encode_nonwpa(dev, info, dwrq, extra); } - return -EINVAL; + return retval; } /** @@ -5151,37 +7698,44 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, +int +wlan_set_txpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { - int ret = WLAN_STATUS_SUCCESS; wlan_private *priv= dev->priv; wlan_adapter *Adapter= priv->adapter; - - int wlan_radio_ioctl(wlan_private *priv, u8 option); + int ret = WLAN_STATUS_SUCCESS; u16 dbm; ENTER(); + if (!Is_Command_Allowed(priv)) { + PRINTM(MSG, "%s: not allowed\n", __FUNCTION__); + return -EBUSY; + } if(vwrq->disabled) { wlan_radio_ioctl(priv, RADIO_OFF); return WLAN_STATUS_SUCCESS; } - Adapter->Preamble = HostCmd_TYPE_AUTO_PREAMBLE; - wlan_radio_ioctl(priv, RADIO_ON); #if WIRELESS_EXT > 14 if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) { dbm = (u16) mw_to_dbm(vwrq->value); - } - else + } else #endif dbm = (u16) vwrq->value; + if ((dbm < Adapter->MinTxPowerLevel) || (dbm > Adapter->MaxTxPowerLevel)) { + PRINTM(MSG, + "The set txpower value %d dBm is out of range (%d dBm-%d dBm)!\n", + dbm, Adapter->MinTxPowerLevel, Adapter->MaxTxPowerLevel); + LEAVE(); + return -EINVAL; + } /* auto tx power control */ @@ -5192,9 +7746,8 @@ ret = PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RF_TX_POWER, - HostCmd_ACT_TX_POWER_OPT_SET_LOW, - HostCmd_OPTION_WAITFORRSP, - 0, (void *) &dbm); + HostCmd_ACT_GEN_SET, + HostCmd_OPTION_WAITFORRSP, 0, (void *) &dbm); LEAVE(); return ret; @@ -5209,41 +7762,50 @@ * @param extra A pointer to extra data buf * @return WLAN_STATUS_SUCCESS --success, otherwise fail */ -int wlan_get_essid(struct net_device *dev, struct iw_request_info *info, +int +wlan_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { wlan_private *priv = dev->priv; wlan_adapter *Adapter = priv->adapter; + int tblIdx = -1; + BSSDescriptor_t *pBSSDesc; ENTER(); - /* - * Note : if dwrq->flags != 0, we should get the relevant SSID from - * the SSID list... - */ + + pBSSDesc = &Adapter->CurBssParams.BSSDescriptor; /* * Get the current SSID */ if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { - memcpy(extra, Adapter->CurBssParams.ssid.Ssid, - Adapter->CurBssParams.ssid.SsidLength); - extra[Adapter->CurBssParams.ssid.SsidLength] = '\0'; + + tblIdx = FindSSIDInList(Adapter, + &pBSSDesc->Ssid, + pBSSDesc->MacAddress, + Adapter->InfrastructureMode); + + memcpy(extra, &pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength); + extra[pBSSDesc->Ssid.SsidLength] = '\0'; + } else { memset(extra, 0, 32); - extra[Adapter->CurBssParams.ssid.SsidLength] = '\0'; + extra[pBSSDesc->Ssid.SsidLength] = '\0'; } - /* - * If none, we may want to get the one that was set - */ /* To make the driver backward compatible with WPA supplicant v0.2.4 */ - if (dwrq->length == 32) /* check with WPA supplicant buffer size */ - dwrq->length = MIN(Adapter->CurBssParams.ssid.SsidLength, - IW_ESSID_MAX_SIZE); - else - dwrq->length = Adapter->CurBssParams.ssid.SsidLength + 1; + if (dwrq->length == 32) { + dwrq->length = MIN(pBSSDesc->Ssid.SsidLength, IW_ESSID_MAX_SIZE); + } else { + dwrq->length = pBSSDesc->Ssid.SsidLength + 1; + } - dwrq->flags = 1; /* active */ + /* If the current network is in the table, return the table index */ + if (tblIdx >= 0) { + dwrq->flags = (tblIdx + 1) & IW_ENCODE_INDEX; + } else { + dwrq->flags = 1; + } LEAVE(); return WLAN_STATUS_SUCCESS; @@ -5257,9 +7819,11 @@ * @param maxlen max length of version buffer * @return NA */ -void get_version(wlan_adapter *adapter, char *version, int maxlen) +void +get_version(wlan_adapter * adapter, char *version, int maxlen) +{ + union { - union { u32 l; u8 c[4]; } ver; @@ -5267,375 +7831,10 @@ ver.l = adapter->FWReleaseNumber; if(ver.c[3] == 0) - sprintf(fwver, "%u.%u.%u", - ver.c[2], ver.c[1], ver.c[0]); + sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]); else sprintf(fwver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0],ver.c[3]); snprintf(version, maxlen, driver_version, fwver); } - -static inline int hex2int(char c) -{ - if (c >= '0' && c <= '9') - return (c - '0'); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - return -1; -} - -/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx") - into binary format (6 bytes). - - This function expects that each byte is represented with 2 characters - (e.g., 11:2:11:11:11:11 is invalid) - - */ -static char *eth_str2addr(char *ethstr, u8 *addr) -{ - int i, val, val2; - char *pos = ethstr; - - /* get rid of initial blanks */ - while (*pos == ' ' || *pos == '\t') ++pos; - - for (i = 0; i < 6; i++) { - val = hex2int(*pos++); - if (val < 0) - return NULL; - val2 = hex2int(*pos++); - if (val2 < 0) - return NULL; - addr[i] = (val * 16 + val2) & 0xff; - - if (i < 5 && *pos++ != ':') - return NULL; - } - return pos; -} - -/* this writes xx:xx:xx:xx:xx:xx into ethstr - (ethstr must have space for 18 chars) */ -static int eth_addr2str(u8 *addr, char *ethstr) -{ - int i; - char *pos = ethstr; - - for (i = 0; i < 6; i++) { - sprintf (pos, "%02x", addr[i] & 0xff); - pos += 2; - if (i < 5 ) - *pos++ = ':'; - } - return 17; -} - -/** - * @brief Add an entry to the DFT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_dft_add_ioctl(wlan_private *priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *) req; - char ethaddrs_str[36]; - char *pos; - u8 ethaddrs[2*ETH_ALEN]; -#define ethaddr1 (ethaddrs+0) -#define ethaddr2 (ethaddrs+6) - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr1)) == NULL) { - PRINTM(FATAL, "DFT_ADD: Invalid MAC address 1\n"); - return -EINVAL; - } - - if (eth_str2addr(pos, ethaddr2) == NULL) { - PRINTM(FATAL, "DFT_ADD: Invalid MAC address 2\n"); - return -EINVAL; - } - -#ifdef DEBUG_LEVEL4 - { - char ethaddr1_str[18], ethaddr2_str[18]; - PRINTM(INFO, "DFT: adding %s\n", ethaddrs_str); - eth_addr2str(ethaddr1, ethaddr1_str); - eth_addr2str(ethaddr2, ethaddr2_str); - PRINTM(INFO, "DFT: adding (%s,%s)\n", ethaddr1_str, ethaddr2_str); - } -#endif - - LEAVE(); - return (PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_DFT_ACCESS_ADD, - HostCmd_OPTION_WAITFORRSP, 0, - ethaddrs)); -} - -/** - * @brief Delete an entry from the DFT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_dft_del_ioctl(wlan_private *priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *) req; - char ethaddrs_str[18]; - u8 ethaddr[ETH_ALEN]; - char *pos; - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - PRINTM(FATAL, "Invalid MAC address\n"); - return -EINVAL; - } - - PRINTM(INFO, "DFT: deleting %s\n", ethaddrs_str); - - LEAVE(); - return (PrepareAndSendCommand(priv, - HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_DFT_ACCESS_DEL, - HostCmd_OPTION_WAITFORRSP, 0, - ethaddr)); -} - -/** - * @brief Reset all entries from the DFT table - * @param priv A pointer to wlan_private structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_dft_reset_ioctl(wlan_private *priv) -{ - ENTER(); - - PRINTM(MSG, "DFT: resetting\n"); - - LEAVE(); - return (PrepareAndSendCommand(priv, - HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_DFT_ACCESS_RESET, - HostCmd_OPTION_WAITFORRSP, 0, - NULL)); -} - -/** - * @brief List an entry from the DFT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_dft_list_ioctl(wlan_private *priv, struct ifreq *req) -{ - int pos; - char *addr1, *addr2; - struct iwreq *wrq = (struct iwreq *) req; - /* used to pass id and store the dft entry returned by the FW */ - union { - int id; - char addr1addr2[2 * ETH_ALEN]; - } param; - static char outstr[64]; - char *pbuf = outstr; - int ret; - - ENTER(); - - if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) { - PRINTM(INFO, "Copy from user failed\n"); - return WLAN_STATUS_FAILURE; - } - param.id = simple_strtoul(outstr, NULL, 10); - pos = sprintf(pbuf, "%d: ", param.id); - pbuf += pos; - - ret = PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_DFT_ACCESS_LIST, - HostCmd_OPTION_WAITFORRSP, 0, - (char *) ¶m); - - if (ret == WLAN_STATUS_SUCCESS) { - addr1 = param.addr1addr2; - addr2 = param.addr1addr2+ ETH_ALEN; - - pos = sprintf(pbuf, "da "); - pbuf += pos; - pos = eth_addr2str(addr1, pbuf); - pbuf += pos; - pos = sprintf(pbuf, " next hop "); - pbuf += pos; - pos = eth_addr2str(addr2, pbuf); - pbuf += pos; - } else { - sprintf(pbuf, "(null)"); - pbuf += pos; - } - wrq->u.data.length = strlen(outstr); - if (copy_to_user(wrq->u.data.pointer, (char *) outstr, - wrq->u.data.length)) { - PRINTM(INFO, "DFT_LIST: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief Add an entry to the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_bt_add_ioctl(wlan_private *priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *) req; - char ethaddrs_str[18]; - char *pos; - u8 ethaddr[ETH_ALEN]; - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - PRINTM(FATAL, "BT_ADD: Invalid MAC address\n"); - return -EINVAL; - } - - PRINTM(INFO, "BT: adding %s\n", ethaddrs_str); - LEAVE(); - return (PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_BT_ACCESS_ADD, - HostCmd_OPTION_WAITFORRSP, 0, - ethaddr)); -} - -/** - * @brief Delete an entry from the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_bt_del_ioctl(wlan_private *priv, struct ifreq *req) -{ - struct iwreq *wrq = (struct iwreq *) req; - char ethaddrs_str[18]; - u8 ethaddr[ETH_ALEN]; - char *pos; - - ENTER(); - if (copy_from_user(ethaddrs_str, wrq->u.data.pointer, - sizeof(ethaddrs_str))) - return -EFAULT; - - if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) { - PRINTM(FATAL, "Invalid MAC address\n"); - return -EINVAL; - } - - PRINTM(INFO, "BT: deleting %s\n", ethaddrs_str); - - - return (PrepareAndSendCommand(priv, - HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_BT_ACCESS_DEL, - HostCmd_OPTION_WAITFORRSP, 0, - ethaddr)); - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief Reset all entries from the BT table - * @param priv A pointer to wlan_private structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_bt_reset_ioctl(wlan_private *priv) -{ - ENTER(); - - PRINTM(MSG, "BT: resetting\n"); - - return (PrepareAndSendCommand(priv, - HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_BT_ACCESS_RESET, - HostCmd_OPTION_WAITFORRSP, 0, - NULL)); - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - -/** - * @brief List an entry from the BT table - * @param priv A pointer to wlan_private structure - * @param req A pointer to ifreq structure - * @return WLAN_STATUS_SUCCESS --success, otherwise fail - */ -static int wlan_bt_list_ioctl(wlan_private *priv, struct ifreq *req) -{ - int pos; - char *addr1; - struct iwreq *wrq = (struct iwreq *) req; - /* used to pass id and store the bt entry returned by the FW */ - union { - int id; - char addr1addr2[2 * ETH_ALEN]; - } param; - static char outstr[64]; - char *pbuf = outstr; - int ret; - - ENTER(); - - if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) { - PRINTM(INFO, "Copy from user failed\n"); - return WLAN_STATUS_FAILURE; - } - param.id = simple_strtoul(outstr, NULL, 10); - pos = sprintf(pbuf, "%d: ", param.id); - pbuf += pos; - - ret = PrepareAndSendCommand(priv, HostCmd_CMD_DFT_ACCESS, - HostCmd_ACT_BT_ACCESS_LIST, - HostCmd_OPTION_WAITFORRSP, 0, - (char *) ¶m); - - if (ret == WLAN_STATUS_SUCCESS) { - addr1 = param.addr1addr2; - - pos = sprintf(pbuf, "ignoring traffic from "); - pbuf += pos; - pos = eth_addr2str(addr1, pbuf); - pbuf += pos; - } else { - sprintf(pbuf, "(null)"); - pbuf += pos; - } - - wrq->u.data.length = strlen(outstr); - if (copy_to_user(wrq->u.data.pointer, (char *) outstr, - wrq->u.data.length)) { - PRINTM(INFO, "BT_LIST: Copy to user failed!\n"); - return -EFAULT; - } - - LEAVE(); - return WLAN_STATUS_SUCCESS; -} - diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wext.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wext.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wext.h 2006-05-24 16:38:40.000000000 -0400 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wext.h 2007-11-06 12:26:40.000000000 -0500 @@ -1,14 +1,13 @@ /** @file wlan_wext.h * @brief This file contains definition for IOCTL call. * - * (c) Copyright © 2003-2006, Marvell International Ltd. - * All Rights Reserved + * (c) Copyright © 2003-2007, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in * accordance with the terms and conditions of the License, a copy of which - * is available along with the File in the license.txt file or by writing to + * is available along with the File in the gpl.txt file or by writing to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. * @@ -22,33 +21,46 @@ Change log: 10/11/05: Add Doxygen format comments 12/19/05: Correct a typo in structure _wlan_ioctl_wmm_tspec - 01/11/06: Change compile flag BULVERDE_SDIO to SD to support Monahans/Zylonite 01/11/06: Conditionalize new scan/join ioctls 04/10/06: Add hostcmd generic API 04/18/06: Remove old Subscrive Event and add new Subscribe Event implementation through generic hostcmd API + 06/08/06: Add definitions of custom events + 08/29/06: Add ledgpio private command ********************************************************/ #ifndef _WLAN_WEXT_H_ #define _WLAN_WEXT_H_ +#include "wlan_types.h" + #define SUBCMD_OFFSET 4 /** PRIVATE CMD ID */ -#define WLANIOCTL SIOCIWFIRSTPRIV +#define WLANIOCTL 0x8BE0 #define WLANSETWPAIE (WLANIOCTL + 0) #define WLANCISDUMP (WLANIOCTL + 1) +#ifdef MFG_CMD_SUPPORT +#define WLANMANFCMD (WLANIOCTL + 2) +#endif #define WLANREGRDWR (WLANIOCTL + 3) #define MAX_EEPROM_DATA 256 #define WLANHOSTCMD (WLANIOCTL + 4) +#define WLANHOSTSLEEPCFG (WLANIOCTL + 5) +#define WLANARPFILTER (WLANIOCTL + 6) #define WLAN_SETINT_GETINT (WLANIOCTL + 7) #define WLANNF 1 #define WLANRSSI 2 +#define WLANBGSCAN 4 #define WLANENABLE11D 5 #define WLANADHOCGRATE 6 -#define WLAN_SUBCMD_SET_PRESCAN 11 +#define WLANSDIOCLOCK 7 +#define WLANWMM_ENABLE 8 +#define WLANNULLGEN 10 +#define WLANADHOCCSET 11 +#define WLAN_ADHOC_G_PROT 12 #define WLAN_SETNONE_GETNONE (WLANIOCTL + 8) #define WLANDEAUTH 1 @@ -56,28 +68,32 @@ #define WLANRADIOOFF 3 #define WLANREMOVEADHOCAES 4 #define WLANADHOCSTOP 5 -#define WLANCIPHERTEST 6 -#define WLANCRYPTOTEST 7 #ifdef REASSOCIATION #define WLANREASSOCIATIONAUTO 8 #define WLANREASSOCIATIONUSER 9 #endif /* REASSOCIATION */ - #define WLANWLANIDLEON 10 #define WLANWLANIDLEOFF 11 -#define WLAN_SUBCMD_DFT_RESET 12 -#define WLAN_SUBCMD_BT_RESET 13 #define WLANGETLOG (WLANIOCTL + 9) #define WLAN_SETCONF_GETCONF (WLANIOCTL + 10) +#define BG_SCAN_CONFIG 1 +#define CAL_DATA_EXT_CONFIG 2 #define WLANSCAN_TYPE (WLANIOCTL + 11) #define WLAN_SET_GET_2K (WLANIOCTL + 13) #define WLAN_SET_USER_SCAN 1 #define WLAN_GET_SCAN_TABLE 2 - +#define WLAN_SET_MRVL_TLV 3 +#define WLAN_GET_ASSOC_RSP 4 +#define WLAN_ADDTS_REQ 5 +#define WLAN_DELTS_REQ 6 +#define WLAN_QUEUE_CONFIG 7 +#define WLAN_QUEUE_STATS 8 +#define WLAN_GET_CFP_TABLE 9 +#define WLAN_TX_PKT_STATS 12 #define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15) #define WLANGETREGION 1 @@ -85,74 +101,70 @@ #define WLAN_GET_MULTIPLE_DTIM 3 #define WLAN_GET_TX_RATE 4 #define WLANGETBCNAVG 5 - -#define WLAN_GET_LINKMODE 6 -#define WLAN_GET_RADIOMODE 7 -#define WLAN_GET_DEBUGMODE 8 - -#define WLAN_SETTENCHAR_GETNONE (WLANIOCTL + 16) - -#define WLAN_SETNONE_GETTENCHAR (WLANIOCTL + 17) - -#define WLANREGCFRDWR (WLANIOCTL + 18) +#define WLANGETDATAAVG 6 #define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19) #define WLAN_SUBCMD_GETRXANTENNA 1 #define WLAN_SUBCMD_GETTXANTENNA 2 #define WLAN_GET_TSF 3 +#define WLAN_WPS_SESSION 4 #define WLAN_SETWORDCHAR_GETNONE (WLANIOCTL + 20) #define WLANSETADHOCAES 1 -#define WLAN_SETNONE_GETWORDCHAR (WLANIOCTL + 21) +#define WLAN_SETONEINT_GETWORDCHAR (WLANIOCTL + 21) #define WLANGETADHOCAES 1 #define WLANVERSION 2 +#define WLANVEREXT 3 #define WLAN_SETONEINT_GETONEINT (WLANIOCTL + 23) -#define WLAN_BEACON_INTERVAL 1 -#define WLAN_LISTENINTRVL 4 +#define WLAN_WMM_QOSINFO 2 +#define WLAN_LISTENINTRVL 3 +#define WLAN_FW_WAKEUP_METHOD 4 +#define WAKEUP_FW_UNCHANGED 0 +#define WAKEUP_FW_THRU_INTERFACE 1 +#define WAKEUP_FW_THRU_GPIO 2 -#define WLAN_TXCONTROL 6 -#define WLAN_NULLPKTINTERVAL 7 +#define WLAN_NULLPKTINTERVAL 5 +#define WLAN_BCN_MISS_TIMEOUT 6 +#define WLAN_ADHOC_AWAKE_PERIOD 7 +#define WLAN_LDO 8 +#define WLAN_AUTODEEPSLEEP 12 +#define WLAN_WAKEUP_MT 13 #define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24) #define WLAN_SUBCMD_SETRXANTENNA 1 #define WLAN_SUBCMD_SETTXANTENNA 2 -#define WLANSETAUTHALG 5 -#define WLANSET8021XAUTHALG 6 -#define WLANSETENCRYPTIONMODE 7 -#define WLANSETREGION 8 -#define WLAN_SET_LISTEN_INTERVAL 9 +#define WLANSETAUTHALG 4 +#define WLANSETENCRYPTIONMODE 5 +#define WLANSETREGION 6 +#define WLAN_SET_LISTEN_INTERVAL 7 -#define WLAN_SET_MULTIPLE_DTIM 10 -#define WLAN_SET_ATIM_WINDOW 11 -#define WLANSETBCNAVG 13 -#define WLANSETDATAAVG 14 -#define WLAN_SET_LINKMODE 15 -#define WLAN_SET_RADIOMODE 16 -#define WLAN_SET_DEBUGMODE 17 +#define WLAN_SET_MULTIPLE_DTIM 8 + +#define WLANSETBCNAVG 9 +#define WLANSETDATAAVG 10 +#define WLANASSOCIATE 11 #define WLAN_SET64CHAR_GET64CHAR (WLANIOCTL + 25) #define WLANSLEEPPARAMS 2 +#define WLAN_BCA_TIMESHARE 3 #define WLANSCAN_MODE 6 #define WLAN_GET_ADHOC_STATUS 9 -#define WLAN_SUBCMD_DFT_ADD 15 -#define WLAN_SUBCMD_DFT_DEL 16 -#define WLAN_SUBCMD_DFT_LIST 17 -#define WLAN_SUBCMD_BT_ADD 18 -#define WLAN_SUBCMD_BT_DEL 19 -#define WLAN_SUBCMD_BT_LIST 20 +#define WLAN_SET_GEN_IE 10 +#define WLAN_GET_GEN_IE 11 + +#define WLAN_WMM_QUEUE_STATUS 13 #define WLANEXTSCAN (WLANIOCTL + 26) +#define WLANDEEPSLEEP (WLANIOCTL + 27) +#define DEEP_SLEEP_ENABLE 1 +#define DEEP_SLEEP_DISABLE 0 #define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29) #define WLAN_TPCCFG 1 -#define WLAN_POWERCFG 2 - -#define WLAN_AUTO_FREQ_SET 3 -#define WLAN_AUTO_FREQ_GET 4 #define WLAN_LED_GPIO_CTRL 5 #define WLAN_SCANPROBES 6 #define WLAN_SLEEP_PERIOD 7 @@ -161,6 +173,17 @@ #define WLANSNR 10 #define WLAN_GET_RATE 11 #define WLAN_GET_RXINFO 12 +#define WLAN_SET_ATIM_WINDOW 13 +#define WLAN_BEACON_INTERVAL 14 +#define WLAN_SDIO_PULL_CTRL 15 +#define WLAN_SCAN_TIME 16 +#define WLAN_DATA_SUBSCRIBE_EVENT 18 +#define WLAN_TXCONTROL 19 +#define WLANHSCFG 21 +#define WLANHSSETPARA 22 +#ifdef DEBUG_LEVEL1 +#define WLAN_DRV_DBG 25 +#endif #define WLANCMD52RDWR (WLANIOCTL + 30) #define WLANCMD53RDWR (WLANIOCTL + 31) @@ -170,10 +193,6 @@ #define REG_BBP 0x1a #define REG_RF 0x1b #define REG_EEPROM 0x59 -#define WLAN_LINKMODE_802_3 0 -#define WLAN_LINKMODE_802_11 2 -#define WLAN_RADIOMODE_NONE 0 -#define WLAN_RADIOMODE_RADIOTAP 2 #define CMD_DISABLED 0 #define CMD_ENABLED 1 @@ -185,8 +204,41 @@ #define SKIP_TYPE_SIZE (SKIP_TYPE + SKIP_SIZE) #define SKIP_TYPE_ACTION (SKIP_TYPE + SKIP_ACTION) +#define MAX_SETGET_CONF_SIZE 2000 /* less than MRVDRV_SIZE_OF_CMD_BUFFER */ +#define MAX_SETGET_CONF_CMD_LEN (MAX_SETGET_CONF_SIZE - SKIP_CMDNUM) + +/* define custom events */ +#define CUS_EVT_HS_ACTIVATED "HS_ACTIVATED " +#define CUS_EVT_HS_DEACTIVATED "HS_DEACTIVATED " +#define CUS_EVT_HS_GPIO_INT "HS_GPIO_INT " +#define CUS_EVT_BEACON_RSSI_LOW "EVENT=BEACON_RSSI_LOW" +#define CUS_EVT_BEACON_SNR_LOW "EVENT=BEACON_SNR_LOW" +#define CUS_EVT_BEACON_RSSI_HIGH "EVENT=BEACON_RSSI_HIGH" +#define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH" +#define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL" +#define CUS_EVT_MLME_MIC_ERR_UNI "MLME-MICHAELMICFAILURE.indication unicast " +#define CUS_EVT_MLME_MIC_ERR_MUL "MLME-MICHAELMICFAILURE.indication multicast " + +#define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW" +#define CUS_EVT_DATA_SNR_LOW "EVENT=DATA_SNR_LOW" +#define CUS_EVT_DATA_RSSI_HIGH "EVENT=DATA_RSSI_HIGH" +#define CUS_EVT_DATA_SNR_HIGH "EVENT=DATA_SNR_HIGH" + +#define CUS_EVT_DEEP_SLEEP_AWAKE "EVENT=DS_AWAKE" + +#define CUS_EVT_ADHOC_LINK_SENSED "EVENT=ADHOC_LINK_SENSED" +#define CUS_EVT_ADHOC_BCN_LOST "EVENT=ADHOC_BCN_LOST" + +/** + * @brief Maximum number of channels that can be sent in a setuserscan ioctl + * + * @sa wlan_ioctl_user_scan_cfg + */ +#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50 + /** wlan_ioctl */ -typedef struct _wlan_ioctl { +typedef struct _wlan_ioctl +{ /** Command ID */ u16 command; /** data length */ @@ -196,13 +248,15 @@ } wlan_ioctl; /** wlan_ioctl_rfantenna */ -typedef struct _wlan_ioctl_rfantenna { +typedef struct _wlan_ioctl_rfantenna +{ u16 Action; u16 AntennaMode; } wlan_ioctl_rfantenna; /** wlan_ioctl_regrdwr */ -typedef struct _wlan_ioctl_regrdwr { +typedef struct _wlan_ioctl_regrdwr +{ /** Which register to access */ u16 WhichReg; /** Read or Write */ @@ -213,7 +267,8 @@ } wlan_ioctl_regrdwr; /** wlan_ioctl_cfregrdwr */ -typedef struct _wlan_ioctl_cfregrdwr { +typedef struct _wlan_ioctl_cfregrdwr +{ /** Read or Write */ u8 Action; /** register address */ @@ -222,31 +277,18 @@ u16 Value; } wlan_ioctl_cfregrdwr; -/** wlan_ioctl_rdeeprom */ -typedef struct _wlan_ioctl_rdeeprom { - u16 WhichReg; - u16 Action; - u16 Offset; - u16 NOB; - u8 Value; -} wlan_ioctl_rdeeprom; - /** wlan_ioctl_adhoc_key_info */ -typedef struct _wlan_ioctl_adhoc_key_info { +typedef struct _wlan_ioctl_adhoc_key_info +{ u16 action; u8 key[16]; u8 tkiptxmickey[16]; u8 tkiprxmickey[16]; }wlan_ioctl_adhoc_key_info; -#ifdef __KERNEL__ -extern struct iw_handler_def wlan_handler_def; -struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev); -int wlan_do_ioctl(struct net_device *dev, struct ifreq *req, int i); -#endif - /** sleep_params */ -typedef struct _wlan_ioctl_sleep_params_config { +typedef struct _wlan_ioctl_sleep_params_config +{ u16 Action; u16 Error; u16 Offset; @@ -258,7 +300,8 @@ *pwlan_ioctl_sleep_params_config; /** BCA TIME SHARE */ -typedef struct _wlan_ioctl_bca_timeshare_config { +typedef struct _wlan_ioctl_bca_timeshare_config +{ /** ACT_GET/ACT_SET */ u16 Action; /** Type: WLAN, BT */ @@ -270,10 +313,103 @@ } __ATTRIB_PACK__ wlan_ioctl_bca_timeshare_config, *pwlan_ioctl_bca_timeshare_config; -typedef struct _wlan_ioctl_reassociation_info { - u8 CurrentBSSID[6]; - u8 DesiredBSSID[6]; - char DesiredSSID[IW_ESSID_MAX_SIZE + 1]; -} __ATTRIB_PACK__ wlan_ioctl_reassociation_info; +#define MAX_CFP_LIST_NUM 64 + +/** wlan_ioctl_cfp_table */ +typedef struct _wlan_ioctl_cfp_table +{ + u32 region; + u32 cfp_no; + struct + { + u16 Channel; + u32 Freq; + u16 MaxTxPower; + BOOLEAN Unsupported; + } cfp[MAX_CFP_LIST_NUM]; +} __ATTRIB_PACK__ wlan_ioctl_cfp_table, *pwlan_ioctl_cfp_table; + +/** + * @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg + * + * Multiple instances of this structure are included in the IOCTL command + * to configure a instance of a scan on the specific channel. + */ +typedef struct +{ + u8 chanNumber; //!< Channel Number to scan + u8 radioType; //!< Radio type: 'B/G' Band = 0, 'A' Band = 1 + u8 scanType; //!< Scan type: Active = 0, Passive = 1 + u8 reserved; + u16 scanTime; //!< Scan duration in milliseconds; if 0 default used +} __ATTRIB_PACK__ wlan_ioctl_user_scan_chan; +/** + * @brief IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg + * + * Used to specify SSID specific filters as well as SSID pattern matching + * filters for scan result processing in firmware. + */ +typedef struct +{ + char ssid[MRVDRV_MAX_SSID_LENGTH + 1]; + u8 maxLen; +} __ATTRIB_PACK__ wlan_ioctl_user_scan_ssid; + +/** + * @brief IOCTL input structure to configure an immediate scan cmd to firmware + * + * Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl. Specifies + * a number of parameters to be used in general for the scan as well + * as a channel list (wlan_ioctl_user_scan_chan) for each scan period + * desired. + * + * @sa wlan_set_user_scan_ioctl + */ +typedef struct +{ + + /** + * @brief Flag set to keep the previous scan table intact + * + * If set, the scan results will accumulate, replacing any previous + * matched entries for a BSS with the new scan data + */ + u8 keepPreviousScan; //!< Do not erase the existing scan results + + /** + * @brief BSS Type to be sent in the firmware command + * + * Field can be used to restrict the types of networks returned in the + * scan. Valid settings are: + * + * - WLAN_SCAN_BSS_TYPE_BSS (infrastructure) + * - WLAN_SCAN_BSS_TYPE_IBSS (adhoc) + * - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure) + */ + u8 bssType; + + /** + * @brief Configure the number of probe requests for active chan scans + */ + u8 numProbes; + + u8 reserved; + + /** + * @brief BSSID filter sent in the firmware command to limit the results + */ + u8 specificBSSID[MRVDRV_ETH_ADDR_LEN]; + + /** + * @brief SSID filter list used in the to limit the scan results + */ + wlan_ioctl_user_scan_ssid ssidList[MRVDRV_MAX_SSID_LIST_LENGTH]; + + /** + * @brief Variable number (fixed maximum) of channels to scan up + */ + wlan_ioctl_user_scan_chan chanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX]; + +} __ATTRIB_PACK__ wlan_ioctl_user_scan_cfg; #endif /* _WLAN_WEXT_H_ */ diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wmm.c 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wmm.c --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wmm.c 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wmm.c 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,1678 @@ +/** @file wlan_wmm.c + * @brief This file contains functions for WMM. + * + * (c) Copyright © 2003-2006, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/******************************************************** +Change log: + 10/04/05: Add Doxygen format comments + 11/11/05: Add support for WMM Status change event + 01/05/06: Add kernel 2.6.x support + 01/11/06: Conditionalize new scan/join code modifications. + 04/06/06: Add TSPEC, queue metrics, and MSDU expiry support +********************************************************/ +#include "include.h" + +/******************************************************** + Local Variables +********************************************************/ + +/** Maximum value FW can accept for driver delay in packet transmission */ +#define DRV_PKT_DELAY_TO_FW_MAX 512 + +/** Set limit of driver packet delay for use in MSDU lifetime expiry and + * traffic stream metrics. + * + * - Set to 0 to disable driver delay in firmware + * - Set to DRV_PKT_DELAY_TO_FW_MAX to enable all possible values + */ +#define DRV_PKT_DELAY_TO_FW_LIMIT 0 + +/** Upper and Lower threshold for packet queuing in the driver + * + * - When the number of packets queued reaches the upper limit, + * the driver will stop the net queue in the app/kernel space. + * + * - When the number of packets drops beneath the lower limit after + * having reached the upper limit, the driver will restart the net + * queue. + */ +#define WMM_QUEUED_PACKET_LOWER_LIMIT 40 +#define WMM_QUEUED_PACKET_UPPER_LIMIT 50 + +#define IPTOS_OFFSET 5 + +static const u8 wmm_info_ie[] = { WMM_IE, 0x07, + 0x00, 0x50, 0xf2, 0x02, + 0x00, 0x01, 0x00 +}; + +/******************************************************** + Local Functions +********************************************************/ +#ifdef DEBUG_LEVEL2 +/** + * @brief Debug print function to display the priority parameters for a WMM AC + * + * @param acStr String pointer giving the AC enumeration (BK, BE, VI, VO) + * @param pACParam Pointer to the AC paramters to display + * + * @return void + */ +static void +wmm_debugPrintAC(wlan_wmm_ac_e acVal, + const IEEEtypes_WmmAcParameters_t * pACParam) +{ + const char *acStr[] = { "BK", "BE", "VI", "VO" }; + + PRINTM(INFO, "WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " + "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", + acStr[acVal], pACParam->AciAifsn.Aci, pACParam->AciAifsn.Acm, + pACParam->AciAifsn.Aifsn, pACParam->Ecw.EcwMin, + pACParam->Ecw.EcwMax, wlan_le16_to_cpu(pACParam->TxopLimit)); +} + +#define PRINTM_AC(acStr, pACParam) wmm_debugPrintAC(acStr, pACParam) +#else +#define PRINTM_AC(acStr, pACParam) +#endif + +/** + * @brief Compute the difference between two timestamps. + * + * @param pTv1 Pointer to timestamp1 + * @param pTv2 Pointer to timestamp2 + * + * @return Time difference in ms between pTv1 and pTv2 (pTv1 - pTv2) + */ +static int +timeval_diff_in_ms(const struct timeval *pTv1, const struct timeval *pTv2) +{ + int diff_ms; + + diff_ms = (pTv1->tv_sec - pTv2->tv_sec) * 1000; + diff_ms += (pTv1->tv_usec - pTv2->tv_usec) / 1000; + + return diff_ms; +} + +/** + * @brief Set the WMM queue priorities to their default values + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +static void +wmm_default_queue_priorities(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + /* default queue priorities: VO->VI->BE->BK */ + Adapter->wmm.queuePriority[0] = WMM_AC_VO; + Adapter->wmm.queuePriority[1] = WMM_AC_VI; + Adapter->wmm.queuePriority[2] = WMM_AC_BE; + Adapter->wmm.queuePriority[3] = WMM_AC_BK; +} + +/** + * @brief Initialize WMM priority queues + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +static void +wmm_setup_queue_priorities(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + IEEEtypes_WmmParameter_t *pWmmIe; + wlan_wmm_ac_e acOrder[4] = { WMM_AC_BE, WMM_AC_BK, + WMM_AC_VI, WMM_AC_VO + }; + + u16 cwmax, cwmin, avg_back_off, tmp[4]; + int i, j, numAc; + + if (Adapter->wmm.enabled == FALSE) { + /* WMM is not enabled, just set the defaults and return */ + wmm_default_queue_priorities(priv); + return; + } + + pWmmIe = &Adapter->CurBssParams.BSSDescriptor.wmmIE; + + HEXDUMP("WMM: setup_queue_priorities: param IE", + (u8 *) pWmmIe, sizeof(IEEEtypes_WmmParameter_t)); + + PRINTM(INFO, "WMM Parameter IE: version=%d, " + "QoSInfo Parameter Set Count=%d, Reserved=%#x\n", + pWmmIe->VendHdr.Version, pWmmIe->QoSInfo.ParaSetCount, + pWmmIe->Reserved); + + for (numAc = 0; numAc < NELEMENTS(acOrder); numAc++) { + cwmax = (1 << pWmmIe->AcParams[numAc].Ecw.EcwMax) - 1; + cwmin = (1 << pWmmIe->AcParams[numAc].Ecw.EcwMin) - 1; + avg_back_off = (cwmin >> 1) + pWmmIe->AcParams[numAc].AciAifsn.Aifsn; + Adapter->wmm.queuePriority[numAc] = acOrder[numAc]; + tmp[numAc] = avg_back_off; + + PRINTM(INFO, "WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", + cwmax, cwmin, avg_back_off); + PRINTM_AC(acOrder[numAc], &pWmmIe->AcParams[numAc]); + } + + HEXDUMP("WMM: avg_back_off", (u8 *) tmp, sizeof(tmp)); + HEXDUMP("WMM: queuePriority", Adapter->wmm.queuePriority, + sizeof(Adapter->wmm.queuePriority)); + + /* bubble sort */ + for (i = 0; i < numAc; i++) { + for (j = 1; j < numAc - i; j++) { + if (tmp[j - 1] > tmp[j]) { + SWAP_U16(tmp[j - 1], tmp[j]); + SWAP_U8(Adapter->wmm.queuePriority[j - 1], + Adapter->wmm.queuePriority[j]); + } else if (tmp[j - 1] == tmp[j]) { + if (Adapter->wmm.queuePriority[j - 1] + < Adapter->wmm.queuePriority[j]) { + SWAP_U8(Adapter->wmm.queuePriority[j - 1], + Adapter->wmm.queuePriority[j]); + } + } + } + } + + HEXDUMP("WMM: avg_back_off, sort", (u8 *) tmp, sizeof(tmp)); + HEXDUMP("WMM: queuePriority, sort", Adapter->wmm.queuePriority, + sizeof(Adapter->wmm.queuePriority)); +} + +/** + * @brief pop up the highest skb from wmm queue + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +static void +wmm_pop_highest_prio_skb(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int i; + u8 ac; + + ENTER(); + + for (i = 0; i < MAX_AC_QUEUES; i++) { + ac = Adapter->wmm.queuePriority[i]; + if (!list_empty((struct list_head *) &Adapter->wmm.txSkbQ[ac])) { + PRINTM(DATA, "WMM: Highest prio pkt in AC Queue %d\n", i); + Adapter->CurrentTxSkb = Adapter->wmm.txSkbQ[ac].next; + Adapter->wmm.packetsOut[ac]++; + list_del((struct list_head *) Adapter->wmm.txSkbQ[ac].next); + break; + } + } + + LEAVE(); +} + +/** + * @brief Evaluate whether or not an AC is to be downgraded + * + * @param priv Pointer to the wlan_private driver data struct + * @param evalAC AC to evaluate for downgrading + * + * @return WMM AC the evalAC traffic is to be sent on. + */ +static wlan_wmm_ac_e +wmm_eval_downgrade_ac(wlan_private * priv, wlan_wmm_ac_e evalAC) +{ + wlan_wmm_ac_e downAC; + wlan_wmm_ac_e retAC; + WmmAcStatus_t *pACStatus; + + pACStatus = &priv->adapter->wmm.acStatus[evalAC]; + + if (pACStatus->Disabled == FALSE) { + /* Okay to use this AC, its enabled */ + return evalAC; + } + + /* Setup a default return value of the lowest priority */ + retAC = WMM_AC_BK; + + /* + * Find the highest AC that is enabled and does not require admission + * control. The spec disallows downgarding to an AC which is enabled + * due to a completed admission control. Unadmitted traffic is not + * to be sent on an AC with admitted traffic. + */ + for (downAC = WMM_AC_BK; downAC < evalAC; downAC++) { + pACStatus = &priv->adapter->wmm.acStatus[downAC]; + + if ((pACStatus->Disabled == FALSE) + && (pACStatus->FlowRequired == FALSE)) { + /* AC is enabled and does not require admission control */ + retAC = downAC; + } + } + + return retAC; +} + +/** + * @brief Downgrade WMM priority queue + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +static void +wmm_setup_ac_downgrade(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + wlan_wmm_ac_e acVal; + + PRINTM(INFO, "WMM: AC Priorities: BK(0), BE(1), VI(2), VO(3)\n"); + + if (Adapter->wmm.enabled == FALSE) { + /* WMM is not enabled, default priorities */ + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + Adapter->wmm.acDowngradedVals[acVal] = acVal; + } + } + } else { + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + Adapter->wmm.acDowngradedVals[acVal] + = wmm_eval_downgrade_ac(priv, acVal); + PRINTM(INFO, "WMM: AC PRIO %d maps to %d\n", + acVal, Adapter->wmm.acDowngradedVals[acVal]); + } + } +} + +/** + * @brief Convert the IP TOS field to an WMM AC Queue assignment + * + * @param tos IP TOS field + * + * @return WMM AC Queue mapping of the IP TOS field + */ +wlan_wmm_ac_e +wmm_convert_tos_to_ac(int tos) +{ + u8 tosIdx; + + /* Map of TOS UP values to WMM AC */ + const wlan_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO + }; + + tosIdx = tos >> IPTOS_OFFSET; + + if (tosIdx >= NELEMENTS(tos_to_ac)) { + return WMM_AC_BE; + } + + return tos_to_ac[tosIdx]; +} + +/** + * @brief Evaluate a given AC and downgrade it to a lower AC if the + * WMM Parameter IE received from the AP indicates that the AP + * is disabled (due to call admission control (ACM bit) + * + * @param priv Pointer to the wlan_private driver data struct + * @param acVal AC to evaulate for downgrading + * + * @return Same AC as input if downgrading not required or + * the AC the traffic for the given AC should be downgraded to + */ +wlan_wmm_ac_e +wmm_downgrade_ac(wlan_private * priv, wlan_wmm_ac_e acVal) +{ + wlan_adapter *Adapter = priv->adapter; + + return (Adapter->wmm.acDowngradedVals[acVal]); +} + +/** + * @brief Map the IP TOS field to a user priority value + * + * @param tos IP TOS field + * + * @return User priority tos input parameter maps to + */ +static u8 +wmm_tos_to_priority(u8 tos) +{ + u8 tosIdx; + const u8 tos_to_priority[] = { + /* Priority DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ + 0x00, /* 0 0 0 AC_BE */ + 0x01, /* 0 0 1 AC_BK */ + 0x02, /* 0 1 0 AC_BK */ + 0x03, /* 0 1 1 AC_BE */ + 0x04, /* 1 0 0 AC_VI */ + 0x05, /* 1 0 1 AC_VI */ + 0x06, /* 1 1 0 AC_VO */ + 0x07 /* 1 1 1 AC_VO */ + }; + + tosIdx = tos >> IPTOS_OFFSET; + + if (tosIdx >= NELEMENTS(tos_to_priority)) { + return WMM_AC_BE; + } + + return tos_to_priority[tosIdx]; +} + +/** + * @brief Process a transfer of a data packet to the firmware from the + * driver queue in order to manipulate flow control in the driver. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_process_fw_iface_tx_xfer_start(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + if (--Adapter->wmm.packetsQueued < WMM_QUEUED_PACKET_LOWER_LIMIT) { + PRINTM(DATA, "WMM: FW OS+: %d\n", Adapter->wmm.packetsQueued); + os_start_queue(priv); + } +} + +/** + * @brief Process the completion of a data packet transfer to the firmware + * from the driver queue in order to manipulate flow control in the + * driver. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + * + */ +void +wmm_process_fw_iface_tx_xfer_end(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + if (Adapter->wmm.packetsQueued) { + PRINTM(DATA, "WMM: FW OS-: %d\n", Adapter->wmm.packetsQueued); + os_stop_queue(priv); + } +} + +/** + * @brief Process a transfer of a data packet from the OS to the driver + * queue in order to manipulate flow control in the driver. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_process_app_iface_tx(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + Adapter->wmm.packetsQueued++; + + if ((!priv->wlan_dev.dnld_sent && (Adapter->PSState != PS_STATE_SLEEP)) + || (Adapter->wmm.packetsQueued >= WMM_QUEUED_PACKET_UPPER_LIMIT)) { + PRINTM(DATA, "WMM: APP OS-: %d\n", Adapter->wmm.packetsQueued); + os_stop_queue(priv); + } +} + +/** + * @brief Stop the WMM data queues. Traffic is still accepted from the + * OS until the buffer limits are reached. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_stop_queue(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + PRINTM(DATA, "WMM: Q-: %d\n", Adapter->wmm.packetsQueued); + Adapter->wmm.queueStopped = TRUE; +} + +/** + * @brief Start/re-start the WMM data queues and indicate to the OS layer + * that data is being accepted again. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_start_queue(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + + PRINTM(DATA, "WMM: Q+: %d\n", Adapter->wmm.packetsQueued); + Adapter->wmm.queueStopped = FALSE; + if (Adapter->wmm.packetsQueued) { + wake_up_interruptible(&priv->MainThread.waitQ); + } + os_carrier_on(priv); + os_start_queue(priv); +} + +/** + * @brief Query the status of the WMM queues. Determine if the driver data + * path is active or not. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return TRUE if WMM queues have been stopped, FALSE if still active + */ +int +wmm_is_queue_stopped(wlan_private * priv) +{ + return (priv->adapter->wmm.queueStopped == TRUE); +} + +/** + * @brief Initialize the WMM state information and the WMM data path queues. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_init(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + int i; + memset(&Adapter->wmm, 0x00, sizeof(Adapter->wmm)); + + for (i = 0; i < MAX_AC_QUEUES; i++) { + INIT_LIST_HEAD((struct list_head *) &Adapter->wmm.txSkbQ[i]); + } + + Adapter->wmm.required = FALSE; + + Adapter->gen_null_pkg = TRUE; /*Enable NULL Pkg generation */ +} + +/** + * @brief Setup the queue priorities and downgrade any queues as required + * by the WMM info. Setups default values if WMM is not active + * for this association. + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_setup_queues(wlan_private * priv) +{ + wmm_setup_queue_priorities(priv); + wmm_setup_ac_downgrade(priv); +} + +/** + * @brief implement WMM enable command + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq Pointer to user data + * + * @return WLAN_STATUS_SUCCESS if success; otherwise <0 + */ +int +wlan_wmm_enable_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + ulong flags; + int data, data1; + int *val; + + ENTER(); + + data = *((int *) (wrq->u.name + SUBCMD_OFFSET)); + switch (data) { + case CMD_DISABLED: /* disable */ + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + return -EPERM; + } + + spin_lock_irqsave(&Adapter->CurrentTxLock, flags); + Adapter->wmm.required = FALSE; + if (!Adapter->wmm.enabled) { + spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); + data1 = Adapter->wmm.required; + val = (int *) wrq->u.name; + *val = data; + return WLAN_STATUS_SUCCESS; + } else { + Adapter->wmm.enabled = 0; + } + + if (Adapter->CurrentTxSkb) { + kfree_skb(Adapter->CurrentTxSkb); + OS_INT_DISABLE; + Adapter->CurrentTxSkb = NULL; + OS_INT_RESTORE; + priv->stats.tx_dropped++; + } + + spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); + break; + + case CMD_ENABLED: /* enable */ + if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { + return -EPERM; + } + spin_lock_irqsave(&Adapter->CurrentTxLock, flags); + Adapter->wmm.required = TRUE; + spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); + break; + + case CMD_GET: + break; + default: + PRINTM(INFO, "Invalid option\n"); + return -EINVAL; + } + + data = Adapter->wmm.required; + val = (int *) wrq->u.name; + *val = data; + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Implement cmd HostCmd_CMD_WMM_GET_STATUS + * + * @param priv Pointer to the wlan_private driver data struct + * @param cmd Pointer to CMD buffer + * @param InfoBuf Pointer to cmd data + * + * @return WLAN_STATUS_SUCCESS + */ +int +wlan_cmd_wmm_get_status(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) +{ + PRINTM(INFO, "WMM: WMM_GET_STATUS cmd sent\n"); + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); + cmd->Size = + wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_GET_STATUS) + S_DS_GEN); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Send a command to firmware to retrieve the current WMM status + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE + */ +int +sendWMMStatusChangeCmd(wlan_private * priv) +{ + return PrepareAndSendCommand(priv, HostCmd_CMD_WMM_GET_STATUS, + 0, 0, 0, NULL); +} + +/** + * @brief Check if wmm TX queue is empty + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return FALSE if not empty; TRUE if empty + */ +int +wmm_lists_empty(wlan_private * priv) +{ + int i; + + for (i = 0; i < MAX_AC_QUEUES; i++) { + if (!list_empty((struct list_head *) &priv->adapter->wmm.txSkbQ[i])) { + return FALSE; + } + } + return TRUE; +} + +/** + * @brief Cleanup wmm TX queue + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_cleanup_queues(wlan_private * priv) +{ + int i; + struct sk_buff *delNode, *Q; + + ENTER(); + + for (i = 0; i < MAX_AC_QUEUES; i++) { + Q = &priv->adapter->wmm.txSkbQ[i]; + + while (!list_empty((struct list_head *) Q)) { + delNode = Q->next; + list_del((struct list_head *) delNode); + kfree_skb(delNode); + } + } + + priv->adapter->wmm.packetsQueued = 0; + + LEAVE(); +} + +/** + * @brief Add skb to WMM queue + * + * @param priv Pointer to the wlan_private driver data struct + * @param skb Pointer to sk_buff + * + * @return void + */ +void +wmm_map_and_add_skb(wlan_private * priv, struct sk_buff *skb) +{ + wlan_adapter *Adapter = priv->adapter; + struct ethhdr *eth; + struct timeval tstamp; + u8 tos; + wlan_wmm_ac_e ac; + wlan_wmm_ac_e ac_down; + + eth = (struct ethhdr *) skb->data; + + switch (eth->h_proto) { + case __constant_htons(ETH_P_IP): + PRINTM(DATA, "packet type ETH_P_IP: %04x, tos=%#x prio=%#x\n", + eth->h_proto, skb->nh.iph->tos, skb->priority); + tos = IPTOS_PREC(skb->nh.iph->tos); + break; + case __constant_htons(ETH_P_ARP): + PRINTM(DATA, "ARP packet %04x\n", eth->h_proto); + default: + tos = 0; + break; + } + + ac = wmm_convert_tos_to_ac(tos); + ac_down = wmm_downgrade_ac(priv, ac); + + skb->priority = wmm_tos_to_priority(tos); + PRINTM(DATA, "wmm_map: tos=%#x, ac=%#x ac_down=%#x, priority=%#x\n", + tos, ac, ac_down, skb->priority); + + list_add_tail((struct list_head *) skb, + (struct list_head *) &Adapter->wmm.txSkbQ[ac_down]); + + wmm_process_app_iface_tx(priv); + + /* Record the current time the packet was queued; used to determine + * the amount of time the packet was queued in the driver before it + * was sent to the firmware. The delay is then sent along with the + * packet to the firmware for aggregate delay calculation for stats + * and MSDU lifetime expiry. + */ + do_gettimeofday(&tstamp); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + skb_set_timestamp(skb, &tstamp); +#else + memcpy(&skb->stamp, &tstamp, sizeof(skb->stamp)); +#endif +} + +/** + * @brief Process the GET_WMM_STATUS command response from firmware + * + * The GET_WMM_STATUS command returns multiple TLVs for: + * - Each AC Queue status + * - Current WMM Parameter IE + * + * This function parses the TLVs and then calls further functions + * to process any changes in the queue prioritization or state. + * + * @param priv Pointer to the wlan_private driver data struct + * @param resp Pointer to the command response buffer including TLVs + * TLVs for each queue and the WMM Parameter IE. + * + * @return WLAN_STATUS_SUCCESS + */ +int +wlan_cmdresp_wmm_get_status(wlan_private * priv, + const HostCmd_DS_COMMAND * resp) +{ + wlan_adapter *Adapter = priv->adapter; + u8 *pCurrent = (u8 *) & resp->params.getWmmStatus; + u32 respLen = resp->Size; + int valid = TRUE; + int enableData = TRUE; + + MrvlIEtypes_Data_t *pTlvHdr; + MrvlIEtypes_WmmQueueStatus_t *pTlvWmmQStatus; + IEEEtypes_WmmParameter_t *pWmmParamIe; + WmmAcStatus_t *pACStatus; + + PRINTM(INFO, "WMM: WMM_GET_STATUS cmdresp received: %d\n", respLen); + HEXDUMP("CMD_RESP: WMM_GET_STATUS", pCurrent, respLen); + + while ((respLen >= sizeof(pTlvHdr->Header)) && valid) { + pTlvHdr = (MrvlIEtypes_Data_t *) pCurrent; + pTlvHdr->Header.Len = wlan_le16_to_cpu(pTlvHdr->Header.Len); + + switch (wlan_le16_to_cpu(pTlvHdr->Header.Type)) { + case TLV_TYPE_WMMQSTATUS: + pTlvWmmQStatus = (MrvlIEtypes_WmmQueueStatus_t *) pTlvHdr; + PRINTM(INFO, + "CMD_RESP: WMM_GET_STATUS: QSTATUS TLV: %d, %d, %d\n", + pTlvWmmQStatus->QueueIndex, pTlvWmmQStatus->FlowRequired, + pTlvWmmQStatus->Disabled); + + pACStatus = &Adapter->wmm.acStatus[pTlvWmmQStatus->QueueIndex]; + pACStatus->Disabled = pTlvWmmQStatus->Disabled; + pACStatus->FlowRequired = pTlvWmmQStatus->FlowRequired; + pACStatus->FlowCreated = pTlvWmmQStatus->FlowCreated; + break; + + case WMM_IE: + /* + * Point the regular IEEE IE 2 bytes into the Marvell IE + * and setup the IEEE IE type and length byte fields + */ + + HEXDUMP("WMM: WMM TLV:", (u8 *) pTlvHdr, pTlvHdr->Header.Len + 4); + + pWmmParamIe = (IEEEtypes_WmmParameter_t *) (pCurrent + 2); + pWmmParamIe->VendHdr.Len = pTlvHdr->Header.Len; + pWmmParamIe->VendHdr.ElementId = WMM_IE; + + PRINTM(INFO, "CMD_RESP: WMM_GET_STATUS: WMM Parameter Set: %d\n", + pWmmParamIe->QoSInfo.ParaSetCount); + + memcpy((u8 *) & Adapter->CurBssParams.BSSDescriptor.wmmIE, + pWmmParamIe, pWmmParamIe->VendHdr.Len + 2); + + break; + + default: + valid = FALSE; + break; + } + + pCurrent += (pTlvHdr->Header.Len + sizeof(pTlvHdr->Header)); + respLen -= (pTlvHdr->Header.Len + sizeof(pTlvHdr->Header)); + } + + wmm_setup_queue_priorities(priv); + wmm_setup_ac_downgrade(priv); + + if (enableData) { + wmm_start_queue(priv); + os_carrier_on(priv); + os_start_queue(priv); + } + + send_iwevcustom_event(priv, WMM_CONFIG_CHANGE_INDICATION); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Call back from the command module to allow insertion of a WMM TLV + * + * If the BSS we are associating to supports WMM, add the required WMM + * Information IE to the association request command buffer in the form + * of a Marvell extended IEEE IE. + * + * @param priv Pointer to the wlan_private driver data struct + * @param ppAssocBuf Output parameter: Pointer to the TLV output buffer, + * modified on return to point after the appended WMM TLV + * @param pWmmIE Pointer to the WMM IE for the BSS we are joining + * + * @return Length of data appended to the association tlv buffer + */ +u32 +wlan_wmm_process_association_req(wlan_private * priv, + u8 ** ppAssocBuf, + IEEEtypes_WmmParameter_t * pWmmIE) +{ + wlan_adapter *Adapter = priv->adapter; + MrvlIEtypes_WmmParamSet_t *pWmmTlv; + u32 retLen = 0; + + /* Null checks */ + if (ppAssocBuf == 0) + return 0; + if (*ppAssocBuf == 0) + return 0; + if (pWmmIE == 0) + return 0; + + PRINTM(INFO, "WMM: process assoc req: bss->wmmIe=%x\n", + pWmmIE->VendHdr.ElementId); + + if (Adapter->wmm.required && pWmmIE->VendHdr.ElementId == WMM_IE) { + pWmmTlv = (MrvlIEtypes_WmmParamSet_t *) * ppAssocBuf; + pWmmTlv->Header.Type = (u16) wmm_info_ie[0]; + pWmmTlv->Header.Type = wlan_cpu_to_le16(pWmmTlv->Header.Type); + pWmmTlv->Header.Len = (u16) wmm_info_ie[1]; + pWmmTlv->Header.Len = wlan_cpu_to_le16(pWmmTlv->Header.Len); + + memcpy(pWmmTlv->WmmIE, &wmm_info_ie[2], pWmmTlv->Header.Len); +#define QOS_INFO_PARA_MASK 0x0f + if (pWmmIE->QoSInfo.QosUAPSD + && ((Adapter->wmm.qosinfo & QOS_INFO_PARA_MASK) != 0)) { + memcpy((u8 *) (pWmmTlv->WmmIE + pWmmTlv->Header.Len + - sizeof(Adapter->wmm.qosinfo)), + &Adapter->wmm.qosinfo, sizeof(Adapter->wmm.qosinfo)); + } + retLen = sizeof(pWmmTlv->Header) + pWmmTlv->Header.Len; + + HEXDUMP("ASSOC_CMD: WMM IE", (u8 *) pWmmTlv, retLen); + *ppAssocBuf += retLen; + } + + return retLen; +} + +/** + * @brief Compute the time delay in the driver queues for a given skb. + * + * When the skb is received at the OS/Driver interface, the current + * time is set in the skb structure. The difference between the present + * time and that received time is computed in this function and limited + * based on pre-compiled limits in the driver. + * + * @param skb Pointer to a sk_buff which has been previously timestamped + * + * @return Time delay of the packet in 2ms units after having limit applied + */ +u8 +wmm_compute_driver_packet_delay(const struct sk_buff * skb) +{ + u8 retVal; + struct timeval in_tv; + struct timeval out_tv; + int queue_delay; + + retVal = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + skb_get_timestamp(skb, &in_tv); +#else + memcpy(&in_tv, &skb->stamp, sizeof(in_tv)); +#endif + do_gettimeofday(&out_tv); + + queue_delay = timeval_diff_in_ms(&out_tv, &in_tv); + + /* Queue delay is passed as a uint8 in units of 2ms (ms shifted + * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. + * + * Pass max value if queue_delay is beyond the uint8 range + */ + retVal = MIN(queue_delay, DRV_PKT_DELAY_TO_FW_LIMIT) >> 1; + + PRINTM(DATA, "WMM: Pkt Delay: %d ms, %d ms sent to FW\n", + queue_delay, retVal); + + return retVal; +} + +/** + * @brief Transmit the highest priority packet awaiting in the WMM Queues + * + * @param priv Pointer to the wlan_private driver data struct + * + * @return void + */ +void +wmm_process_tx(wlan_private * priv) +{ + wlan_adapter *Adapter = priv->adapter; + ulong flags; + + OS_INTERRUPT_SAVE_AREA; + + ENTER(); + + if ((Adapter->PSState == PS_STATE_SLEEP) + || (Adapter->PSState == PS_STATE_PRE_SLEEP)) { + PRINTM(INFO, "In PS State %d" + " - Not sending the packet\n", Adapter->PSState); + LEAVE(); + + return; + } + + spin_lock_irqsave(&Adapter->CurrentTxLock, flags); + + if (priv->wlan_dev.dnld_sent) { + spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); + + LEAVE(); + + return; + } + + UpdateTransStart(priv->wlan_dev.netdev); + wmm_pop_highest_prio_skb(priv); + + spin_unlock_irqrestore(&Adapter->CurrentTxLock, flags); + + if (Adapter->CurrentTxSkb) { + wlan_process_tx(priv); + } + + LEAVE(); +} + +/** + * @brief Private IOCTL entry to get the status of the WMM queues + * + * Return the following information for each WMM AC: + * - WMM IE Acm Required + * - Firmware Flow Required + * - Firmware Flow Established + * - Firmware Queue Enabled + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq A pointer to iwreq structure containing the + * wlan_ioctl_wmm_queue_status_t struct for request + * + * @return 0 if successful; IOCTL error code otherwise + */ +int +wlan_wmm_queue_status_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_adapter *Adapter = priv->adapter; + wlan_ioctl_wmm_queue_status_t qstatus; + wlan_wmm_ac_e acVal; + WmmAcStatus_t *pACStatus; + IEEEtypes_WmmAcParameters_t *pWmmIeAC; + + for (acVal = WMM_AC_BK; acVal <= WMM_AC_VO; acVal++) { + pACStatus = &Adapter->wmm.acStatus[acVal]; + pWmmIeAC = &Adapter->CurBssParams.BSSDescriptor.wmmIE.AcParams[acVal]; + + /* Acm bit */ + qstatus.acStatus[acVal].wmmAcm = pWmmIeAC->AciAifsn.Acm; + + /* Firmware status */ + qstatus.acStatus[acVal].flowRequired = pACStatus->FlowRequired; + qstatus.acStatus[acVal].flowCreated = pACStatus->FlowCreated; + qstatus.acStatus[acVal].disabled = pACStatus->Disabled; + } + + if (copy_to_user(wrq->u.data.pointer, &qstatus, sizeof(qstatus))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Private IOCTL entry to send an ADDTS TSPEC + * + * Receive a ADDTS command from the application. The command structure + * contains a TSPEC and timeout in milliseconds. The timeout is performed + * in the firmware after the ADDTS command frame is sent. + * + * The TSPEC is received in the API as an opaque block whose length is + * calculated from the IOCTL data length. The firmware will send the + * entire data block, including the bytes after the TSPEC. This is done + * to allow extra IEs to be packaged with the TSPEC in the ADDTS action + * frame. + * + * The IOCTL structure contains two return fields: + * - The firmware command result which indicates failure and timeouts + * - The IEEE Status code which contains the corresponding value from + * any ADDTS response frame received. + * + * In addition, the opaque TSPEC data block passed in is replaced with the + * TSPEC recieved in the ADDTS response frame. In case of failure, the + * AP may modify the TSPEC on return and in the case of success, the + * medium time is returned as calculated by the AP. Along with the TSPEC, + * any IEs that are sent in the ADDTS response are also returned and can be + * parsed using the IOCTL length as an indicator of extra elements. + * + * The return value to the application layer indicates a driver execution + * success or failure. A successful return could still indicate a firmware + * failure or AP negotiation failure via the commandResult field copied + * back to the application. + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq A pointer to iwreq structure containing the + * wlan_ioctl_wmm_addts_req_t struct for this ADDTS request + * + * @return 0 if successful; IOCTL error code otherwise + */ +int +wlan_wmm_addts_req_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + static int dialogTok = 0; + wlan_ioctl_wmm_addts_req_t addtsIoctl; + wlan_cmd_wmm_addts_req_t addtsCmd; + int retcode; + + if (copy_from_user(&addtsIoctl, + wrq->u.data.pointer, + MIN(wrq->u.data.length, sizeof(addtsIoctl))) != 0) { + /* copy_from_user failed */ + PRINTM(INFO, "TSPEC: ADDTS copy from user failed\n"); + retcode = -EFAULT; + + } else { + memset(&addtsCmd, 0x00, sizeof(addtsCmd)); + addtsCmd.dialogToken = ++dialogTok; + addtsCmd.timeout_ms = addtsIoctl.timeout_ms; + addtsCmd.tspecDataLen = (wrq->u.data.length + - sizeof(addtsCmd.timeout_ms) + - sizeof(addtsCmd.commandResult) + - sizeof(addtsCmd.ieeeStatusCode)); + memcpy(addtsCmd.tspecData, + addtsIoctl.tspecData, addtsCmd.tspecDataLen); + + retcode = PrepareAndSendCommand(priv, + HostCmd_CMD_WMM_ADDTS_REQ, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &addtsCmd); + + wrq->u.data.length = (sizeof(addtsIoctl.timeout_ms) + + sizeof(addtsIoctl.commandResult) + + sizeof(addtsIoctl.ieeeStatusCode) + + addtsCmd.tspecDataLen); + + addtsIoctl.commandResult = addtsCmd.commandResult; + addtsIoctl.ieeeStatusCode = addtsCmd.ieeeStatusCode; + memcpy(addtsIoctl.tspecData, + addtsCmd.tspecData, addtsCmd.tspecDataLen); + + if (copy_to_user(wrq->u.data.pointer, + &addtsIoctl, sizeof(addtsIoctl))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + + if (retcode) { + return -EFAULT; + } + } + + return retcode; +} + +/** + * @brief Private IOCTL entry to send a DELTS TSPEC + * + * Receive a DELTS command from the application. The command structure + * contains a TSPEC and reason code along with space for a command result + * to be returned. The information is packaged is sent to the wlan_cmd.c + * firmware command prep and send routines for execution in the firmware. + * + * The reason code is not used for WMM implementations but is indicated in + * the 802.11e specification. + * + * The return value to the application layer indicates a driver execution + * success or failure. A successful return could still indicate a firmware + * failure via the commandResult field copied back to the application. + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq A pointer to iwreq structure containing the + * wlan_ioctl_wmm_delts_req_t struct for this DELTS request + * + * @return 0 if successful; IOCTL error code otherwise + */ +int +wlan_wmm_delts_req_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_ioctl_wmm_delts_req_t deltsIoctl; + wlan_cmd_wmm_delts_req_t deltsCmd; + int retcode; + + if (copy_from_user(&deltsIoctl, + wrq->u.data.pointer, + MIN(wrq->u.data.length, sizeof(deltsIoctl))) != 0) { + /* copy_from_user failed */ + PRINTM(INFO, "TSPEC: DELTS copy from user failed\n"); + retcode = -EFAULT; + + } else { + memset(&deltsCmd, 0x00, sizeof(deltsCmd)); + + /* Dialog token unused for WMM implementations */ + deltsCmd.dialogToken = 0; + + deltsCmd.ieeeReasonCode = deltsIoctl.ieeeReasonCode; + + /* Calculate the length of the TSPEC and any other IEs */ + deltsCmd.tspecDataLen = (wrq->u.data.length + - sizeof(deltsCmd.commandResult) + - sizeof(deltsCmd.ieeeReasonCode)); + memcpy(deltsCmd.tspecData, + deltsIoctl.tspecData, deltsCmd.tspecDataLen); + + /* Send the DELTS request to firmware, wait for a response */ + retcode = PrepareAndSendCommand(priv, + HostCmd_CMD_WMM_DELTS_REQ, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &deltsCmd); + + /* Return the firmware command result back to the application layer */ + deltsIoctl.commandResult = deltsCmd.commandResult; + + if (copy_to_user(wrq->u.data.pointer, + &deltsCmd, + MIN(wrq->u.data.length, sizeof(deltsIoctl)))) { + PRINTM(INFO, "Copy to user failed\n"); + return -EFAULT; + } + + if (retcode) { + retcode = -EFAULT; + } + } + + return retcode; +} + +/** + * @brief Process the ADDTS_REQ command response from firmware + * + * Return the ADDTS firmware response to the calling thread that sent + * the command. The result is then relayed back the app layer. + * + * @param priv Pointer to the wlan_private driver data struct + * @param resp Pointer to the command response buffer including the + * command result and any returned ADDTS response TSPEC + * elements + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_addts_req_ioctl + */ +int +wlan_cmdresp_wmm_addts_req(wlan_private * priv, + const HostCmd_DS_COMMAND * resp) +{ + wlan_cmd_wmm_addts_req_t *pAddTsCmd; + const HostCmd_DS_WMM_ADDTS_REQ *pCmdResp; + u32 u32tSpecDataLen = 0; + + /* Cast the NULL pointer of the buffer the IOCTL sent in the command req */ + pAddTsCmd = (wlan_cmd_wmm_addts_req_t *) priv->adapter->CurCmd->pdata_buf; + + /* Convenience variable for the ADDTS response from the firmware */ + pCmdResp = &resp->params.addTsReq; + + /* Assign return data */ + + pAddTsCmd->commandResult = pCmdResp->commandResult; + + if (pCmdResp->commandResult == TSPEC_RESULT_SUCCESS) { + /* The tspecData field is potentially variable in size due to extra IEs + * that may have been in the ADDTS response action frame. Calculate + * the data length from the firmware command response. + */ + pAddTsCmd->tspecDataLen = (resp->Size + - sizeof(pCmdResp->commandResult) + - sizeof(pCmdResp->timeout_ms) + - sizeof(pCmdResp->dialogToken) + - sizeof(pCmdResp->ieeeStatusCode) + - S_DS_GEN); + + u32tSpecDataLen = MAX(pAddTsCmd->tspecDataLen, + sizeof(pAddTsCmd->tspecData) + + sizeof(pAddTsCmd->addtsExtraIEBuf)); + + if (u32tSpecDataLen <= WMM_TSPEC_SIZE) { + + /* Copy back the TSPEC data including any extra IEs after the TSPEC */ + memcpy(pAddTsCmd->tspecData, + pCmdResp->tspecData, u32tSpecDataLen); + pAddTsCmd->dialogToken = pCmdResp->dialogToken; + pAddTsCmd->ieeeStatusCode = pCmdResp->ieeeStatusCode; + } else { + PRINTM(INFO, "Invalid tspect data length =%d\n", u32tSpecDataLen); + return WLAN_STATUS_FAILURE; + } + } else { + pAddTsCmd->tspecDataLen = 0; + pAddTsCmd->dialogToken = 0; + pAddTsCmd->ieeeStatusCode = 0; + } + + PRINTM(INFO, "TSPEC: ADDTS ret = %d,%d sz=%d\n", + pAddTsCmd->commandResult, pAddTsCmd->ieeeStatusCode, + pAddTsCmd->tspecDataLen); + + HEXDUMP("TSPEC: ADDTS data", + pAddTsCmd->tspecData, pAddTsCmd->tspecDataLen); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Process the DELTS_REQ command response from firmware + * + * Return the DELTS firmware response to the calling thread that sent + * the command. The result is then relayed back the app layer. + * + * @param priv Pointer to the wlan_private driver data struct + * @param resp Pointer to the command response buffer with the command + * result. No other response information is passed back + * to the driver. + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_delts_req_ioctl + */ +int +wlan_cmdresp_wmm_delts_req(wlan_private * priv, + const HostCmd_DS_COMMAND * resp) +{ + wlan_cmd_wmm_delts_req_t *pDelTsCmd; + + /* Cast the NULL pointer of the buffer the IOCTL sent in the command req */ + pDelTsCmd = (wlan_cmd_wmm_delts_req_t *) priv->adapter->CurCmd->pdata_buf; + + pDelTsCmd->commandResult = + wlan_le16_to_cpu(resp->params.delTsReq.commandResult); + + PRINTM(INFO, "TSPEC: DELTS result = %d\n", pDelTsCmd->commandResult); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Implement cmd HostCmd_DS_WMM_ADDTS_REQ + * + * @param priv Pointer to the wlan_private driver data struct + * @param cmd Pointer to CMD buffer + * @param InfoBuf Pointer to cmd data + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_addts_req_ioctl + */ +int +wlan_cmd_wmm_addts_req(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) +{ + wlan_cmd_wmm_addts_req_t *pAddTsCmd; + int tspecCopySize; + + pAddTsCmd = (wlan_cmd_wmm_addts_req_t *) InfoBuf; + + cmd->params.addTsReq.timeout_ms = pAddTsCmd->timeout_ms; + cmd->params.addTsReq.dialogToken = pAddTsCmd->dialogToken; + + tspecCopySize = MIN(pAddTsCmd->tspecDataLen, + sizeof(cmd->params.addTsReq.tspecData)); + memcpy(&cmd->params.addTsReq.tspecData, + pAddTsCmd->tspecData, tspecCopySize); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_ADDTS_REQ); + cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.addTsReq.dialogToken) + + sizeof(cmd->params.addTsReq.timeout_ms) + + sizeof(cmd->params.addTsReq.commandResult) + + sizeof(cmd->params.addTsReq.ieeeStatusCode) + + tspecCopySize + S_DS_GEN); + + cmd->params.addTsReq.timeout_ms + = wlan_cpu_to_le32(cmd->params.addTsReq.timeout_ms); + + PRINTM(INFO, "WMM: ADDTS Cmd: Data Len = %d\n", pAddTsCmd->tspecDataLen); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Implement cmd HostCmd_DS_WMM_DELTS_REQ + * + * @param priv Pointer to the wlan_private driver data struct + * @param cmd Pointer to CMD buffer + * @param InfoBuf Void pointer cast of a wlan_cmd_wmm_delts_req_t struct + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_delts_req_ioctl + */ +int +wlan_cmd_wmm_delts_req(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) +{ + wlan_cmd_wmm_delts_req_t *pDelTsCmd; + int tspecCopySize; + + pDelTsCmd = (wlan_cmd_wmm_delts_req_t *) InfoBuf; + + cmd->params.delTsReq.dialogToken = pDelTsCmd->dialogToken; + cmd->params.delTsReq.ieeeReasonCode = pDelTsCmd->ieeeReasonCode; + + tspecCopySize = MIN(pDelTsCmd->tspecDataLen, + sizeof(cmd->params.delTsReq.tspecData)); + memcpy(&cmd->params.delTsReq.tspecData, + pDelTsCmd->tspecData, tspecCopySize); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_DELTS_REQ); + cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.delTsReq.dialogToken) + + sizeof(cmd->params.delTsReq.commandResult) + + sizeof(cmd->params.delTsReq.ieeeReasonCode) + + tspecCopySize + S_DS_GEN); + + PRINTM(INFO, "WMM: DELTS Cmd prepared\n"); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Prepare the firmware command buffer for the WMM_QUEUE_CONFIG command + * + * @param priv Pointer to the wlan_private driver data struct + * @param cmd Pointer to CMD buffer + * @param InfoBuf Void pointer cast of a wlan_cmd_wmm_queue_config_t struct + * + * @return WLAN_STATUS_SUCCESS + */ +int +wlan_cmd_wmm_queue_config(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) +{ + wlan_cmd_wmm_queue_config_t *pQConfigCmd; + int tlvCopySize; + + pQConfigCmd = (wlan_cmd_wmm_queue_config_t *) InfoBuf; + + cmd->params.queueConfig.action = pQConfigCmd->action; + cmd->params.queueConfig.accessCategory = pQConfigCmd->accessCategory; + cmd->params.queueConfig.msduLifetimeExpiry + = wlan_cpu_to_le16(pQConfigCmd->msduLifetimeExpiry); + + tlvCopySize = MIN(pQConfigCmd->tlvBufLen, + sizeof(cmd->params.queueConfig.tlvBuffer)); + memcpy(&cmd->params.queueConfig.tlvBuffer, + pQConfigCmd->tlvBuffer, tlvCopySize); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_CONFIG); + cmd->Size = wlan_cpu_to_le16(sizeof(cmd->params.queueConfig.action) + + + sizeof(cmd->params.queueConfig. + accessCategory) + + + sizeof(cmd->params.queueConfig. + msduLifetimeExpiry) + + tlvCopySize + S_DS_GEN); + + PRINTM(INFO, "WMM: QUEUE CONFIG Cmd prepared\n"); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Process the WMM_QUEUE_CONFIG command response from firmware + * + * Return the firmware command response to the blocked IOCTL caller function. + * + * @param priv Pointer to the wlan_private driver data struct + * @param resp Pointer to the command response buffer with: + * - action code + * - access category + * - collected statistics if requested + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_queue_config_ioctl + */ +int +wlan_cmdresp_wmm_queue_config(wlan_private * priv, + const HostCmd_DS_COMMAND * resp) +{ + wlan_cmd_wmm_queue_config_t *pQConfigCmd; + const HostCmd_DS_WMM_QUEUE_CONFIG *pCmdResp; + + pQConfigCmd = + (wlan_cmd_wmm_queue_config_t *) (priv->adapter->CurCmd->pdata_buf); + pCmdResp = &resp->params.queueConfig; + + pQConfigCmd->action = pCmdResp->action; + pQConfigCmd->accessCategory = pCmdResp->accessCategory; + pQConfigCmd->msduLifetimeExpiry + = wlan_le16_to_cpu(pCmdResp->msduLifetimeExpiry); + + pQConfigCmd->tlvBufLen = (resp->Size - sizeof(pCmdResp->action) + - sizeof(pCmdResp->accessCategory) + - sizeof(pCmdResp->msduLifetimeExpiry) + - S_DS_GEN); + + memcpy(pQConfigCmd->tlvBuffer, + pCmdResp->tlvBuffer, pQConfigCmd->tlvBufLen); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Private IOCTL entry to get/set a specified AC Queue's parameters + * + * Receive a AC Queue configuration command which is used to get, set, or + * default the parameters associated with a specific WMM AC Queue. + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq A pointer to iwreq structure containing the + * wlan_ioctl_wmm_queue_config_t struct + * + * @return 0 if successful; IOCTL error code otherwise + */ +int +wlan_wmm_queue_config_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_ioctl_wmm_queue_config_t queueConfigIoctl; + wlan_cmd_wmm_queue_config_t queueConfigCmd; + int retcode; + + PRINTM(INFO, "WMM: Queue Config IOCTL Enter\n"); + + if (copy_from_user(&queueConfigIoctl, + wrq->u.data.pointer, + MIN(wrq->u.data.length, + sizeof(queueConfigIoctl))) != 0) { + /* copy_from_user failed */ + PRINTM(INFO, "WMM: Queue Config: copy from user failed\n"); + retcode = -EFAULT; + + } else { + memset(&queueConfigCmd, 0x00, sizeof(queueConfigCmd)); + + queueConfigCmd.action = queueConfigIoctl.action; + queueConfigCmd.accessCategory = queueConfigIoctl.accessCategory; + queueConfigCmd.msduLifetimeExpiry + = queueConfigIoctl.msduLifetimeExpiry; + + /* Create a rates TLV from the supportedRates[] ioctl field */ + queueConfigCmd.tlvBufLen = 0; + + retcode = PrepareAndSendCommand(priv, + HostCmd_CMD_WMM_QUEUE_CONFIG, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &queueConfigCmd); + if (retcode) { + retcode = -EFAULT; + } else { + memset(&queueConfigIoctl, 0x00, sizeof(queueConfigIoctl)); + + queueConfigIoctl.action = queueConfigCmd.action; + queueConfigIoctl.accessCategory = queueConfigCmd.accessCategory; + queueConfigIoctl.msduLifetimeExpiry + = queueConfigCmd.msduLifetimeExpiry; + + wrq->u.data.length = sizeof(queueConfigIoctl); + + if (copy_to_user(wrq->u.data.pointer, + &queueConfigIoctl, sizeof(queueConfigIoctl))) { + PRINTM(INFO, "Copy to user failed\n"); + retcode = -EFAULT; + } + } + } + + return retcode; +} + +/** + * @brief Prepare the firmware command buffer for the WMM_QUEUE_STATS command + * + * @param priv Pointer to the wlan_private driver data struct + * @param cmd pointer to CMD buffer + * @param InfoBuf void pointer cast of a HostCmd_CMD_WMM_QUEUE_STATS struct + * + * @return WLAN_STATUS_SUCCESS + */ +int +wlan_cmd_wmm_queue_stats(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf) +{ + memcpy(&cmd->params.queueStats, InfoBuf, sizeof(cmd->params.queueStats)); + + cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_WMM_QUEUE_STATS); + cmd->Size = wlan_cpu_to_le16(sizeof(HostCmd_DS_WMM_QUEUE_STATS) + + S_DS_GEN); + + PRINTM(INFO, "WMM: QUEUE STATS Cmd prepared\n"); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Process the WMM_QUEUE_STATS command response from firmware + * + * Return the firmware command response to the blocked IOCTL caller function. + * + * @param priv Pointer to the wlan_private driver data struct + * @param resp Pointer to the command response buffer with: + * - action code + * - access category + * - collected statistics if requested + * + * @return WLAN_STATUS_SUCCESS + * + * @sa wlan_wmm_queue_stats_ioctl + */ +int +wlan_cmdresp_wmm_queue_stats(wlan_private * priv, + const HostCmd_DS_COMMAND * resp) +{ + HostCmd_DS_WMM_QUEUE_STATS *pQueueStats = + (HostCmd_DS_WMM_QUEUE_STATS *) priv->adapter->CurCmd->pdata_buf; + + memcpy(pQueueStats, &resp->params.queueStats, (resp->Size - S_DS_GEN)); + + pQueueStats->pktCount = wlan_le16_to_cpu(pQueueStats->pktCount); + pQueueStats->pktLoss = wlan_le16_to_cpu(pQueueStats->pktLoss); + pQueueStats->avgQueueDelay = wlan_le32_to_cpu(pQueueStats->avgQueueDelay); + pQueueStats->avgTxDelay = wlan_le32_to_cpu(pQueueStats->avgTxDelay); + pQueueStats->usedTime = wlan_le32_to_cpu(pQueueStats->usedTime); + + PRINTM(INFO, "WMM: Queue Stats response: %d\n", resp->Size - S_DS_GEN); + + return WLAN_STATUS_SUCCESS; +} + +/** + * @brief Private IOCTL entry to get and start/stop queue stats on a WMM AC + * + * Receive a AC Queue statistics command from the application for a specific + * WMM AC. The command can: + * - Turn stats on + * - Turn stats off + * - Collect and clear the stats + * + * @param priv Pointer to the wlan_private driver data struct + * @param wrq A pointer to iwreq structure containing the + * wlan_ioctl_wmm_queue_stats_t struct + * + * @return 0 if successful; IOCTL error code otherwise + */ +int +wlan_wmm_queue_stats_ioctl(wlan_private * priv, struct iwreq *wrq) +{ + wlan_ioctl_wmm_queue_stats_t queueStatsIoctl; + HostCmd_DS_WMM_QUEUE_STATS queueStatsCmd; + int retcode; + + if (copy_from_user(&queueStatsIoctl, + wrq->u.data.pointer, + MIN(wrq->u.data.length, + sizeof(queueStatsIoctl))) != 0) { + /* copy_from_user failed */ + PRINTM(INFO, "WMM: Queue Stats: copy from user failed\n"); + retcode = -EFAULT; + + } else { + memcpy(&queueStatsCmd, &queueStatsIoctl, sizeof(queueStatsCmd)); + + PRINTM(INFO, "WMM: QUEUE STATS Ioctl: %d, %d\n", + queueStatsCmd.action, queueStatsCmd.accessCategory); + + retcode = PrepareAndSendCommand(priv, + HostCmd_CMD_WMM_QUEUE_STATS, 0, + HostCmd_OPTION_WAITFORRSP, 0, + &queueStatsCmd); + if (retcode) { + retcode = -EFAULT; + } else { + if (copy_to_user(wrq->u.data.pointer, + &queueStatsCmd, + MIN(wrq->u.data.length, + sizeof(queueStatsCmd)))) { + PRINTM(INFO, "Copy to user failed\n"); + retcode = -EFAULT; + } + } + } + + if (retcode != WLAN_STATUS_SUCCESS) { + PRINTM(INFO, "WMM: QUEUE STATS Ioctl FAILED: %d, %d\n", + queueStatsIoctl.action, queueStatsIoctl.accessCategory); + } + + return retcode; +} diff -NurbBwd USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wmm.h 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wmm.h --- USB-8388-FEDORA26-X86-5.110.7.p0-26318.P7/src_usb8388/wlan/wlan_wmm.h 1969-12-31 19:00:00.000000000 -0500 +++ 8686/SD-8686-FEDORA26FC6-SYSKT-GPL-9.70.3.p18-26409.P39_GPL/src_sd8686/wlan/wlan_wmm.h 2007-11-06 12:26:40.000000000 -0500 @@ -0,0 +1,125 @@ +/** @file wlan_wmm.h + * @brief This file contains related macros, enum, and struct + * of wmm functionalities + * + * (c) Copyright © 2003-2006, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +/**************************************************** +Change log: + 09/26/05: add Doxygen format comments + 04/06/06: Add TSPEC, queue metrics, and MSDU expiry support +****************************************************/ + +#ifndef __WLAN_WMM_H +#define __WLAN_WMM_H + +/** Custom indiciation message sent to the application layer for WMM changes */ +#define WMM_CONFIG_CHANGE_INDICATION "WMM_CONFIG_CHANGE.indication" + +/** Highest priority setting for a packet (uses voice AC) */ +#define WMM_HIGHEST_PRIORITY 7 + +#ifdef __KERNEL__ + +/** struct of WMM DESC */ +typedef struct +{ + u8 required; + u8 enabled; + u8 packetsQueued; + u8 queueStopped; + u32 packetsOut[MAX_AC_QUEUES]; + u32 userPriPktTxCtrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ + + struct sk_buff txSkbQ[MAX_AC_QUEUES]; + WmmAcStatus_t acStatus[MAX_AC_QUEUES]; + wlan_wmm_ac_e acDowngradedVals[MAX_AC_QUEUES]; + + /** wmm queue priority table*/ + u8 queuePriority[MAX_AC_QUEUES]; + + u8 qosinfo; +} __ATTRIB_PACK__ WMM_DESC; + +extern void wmm_map_and_add_skb(wlan_private * priv, struct sk_buff *); +extern u8 wmm_compute_driver_packet_delay(const struct sk_buff *skb); +#endif + +extern int sendWMMStatusChangeCmd(wlan_private * priv); +extern int wmm_lists_empty(wlan_private * priv); +extern void wmm_cleanup_queues(wlan_private * priv); +extern void wmm_process_tx(wlan_private * priv); + +extern void wmm_init(wlan_private * priv); +extern void wmm_setup_queues(wlan_private * priv); +extern void wmm_start_queue(wlan_private * priv); +extern void wmm_stop_queue(wlan_private * priv); +extern int wmm_is_queue_stopped(wlan_private * priv); + +extern void wmm_process_fw_iface_tx_xfer_start(wlan_private * priv); +extern void wmm_process_fw_iface_tx_xfer_end(wlan_private * priv); +extern void wmm_process_app_iface_tx(wlan_private * priv); +extern wlan_wmm_ac_e wmm_convert_tos_to_ac(int tos); +extern wlan_wmm_ac_e wmm_downgrade_ac(wlan_private * priv, + wlan_wmm_ac_e acVal); + +extern u32 wlan_wmm_process_association_req(wlan_private * priv, + u8 ** ppAssocBuf, + IEEEtypes_WmmParameter_t * + pWmmIE); + +/* + * Functions used in the cmd handling routine + */ +extern int wlan_cmd_wmm_get_status(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf); +extern int wlan_cmd_wmm_addts_req(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf); +extern int wlan_cmd_wmm_delts_req(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf); +extern int wlan_cmd_wmm_queue_config(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf); +extern int wlan_cmd_wmm_queue_stats(wlan_private * priv, + HostCmd_DS_COMMAND * cmd, void *InfoBuf); + +/* + * Functions used in the cmdresp handling routine + */ +extern int wlan_cmdresp_wmm_get_status(wlan_private * priv, + const HostCmd_DS_COMMAND * resp); +extern int wlan_cmdresp_wmm_addts_req(wlan_private * priv, + const HostCmd_DS_COMMAND * resp); +extern int wlan_cmdresp_wmm_delts_req(wlan_private * priv, + const HostCmd_DS_COMMAND * resp); +extern int wlan_cmdresp_wmm_queue_config(wlan_private * priv, + const HostCmd_DS_COMMAND * resp); +extern int wlan_cmdresp_wmm_queue_stats(wlan_private * priv, + const HostCmd_DS_COMMAND * resp); + +/* + * IOCTLs + */ +extern int wlan_wmm_enable_ioctl(wlan_private * priv, struct iwreq *wrq); +extern int wlan_wmm_queue_status_ioctl(wlan_private * priv, + struct iwreq *wrq); + +extern int wlan_wmm_addts_req_ioctl(wlan_private * priv, struct iwreq *wrq); +extern int wlan_wmm_delts_req_ioctl(wlan_private * priv, struct iwreq *wrq); +extern int wlan_wmm_queue_config_ioctl(wlan_private * priv, + struct iwreq *wrq); +extern int wlan_wmm_queue_stats_ioctl(wlan_private * priv, struct iwreq *wrq); +#endif /* __WLAN_WMM_H */